mirror of
https://github.com/house-of-vanity/fesmoo_perdoliq.git
synced 2025-07-08 06:14:06 +00:00
Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
287b5b346b | |||
0dcb2d6f9b | |||
4d463182aa | |||
52e78ef94d | |||
da9c098623 | |||
b0ff3b9034 | |||
506978ea76 | |||
21527657b2 | |||
7341eaaa4e | |||
6b948d4b2b | |||
67244888af | |||
358c6b348b | |||
03748de34e | |||
2f3e43f937 | |||
6b711e7151 | |||
fcb5b74e41 | |||
484636369d | |||
408c1e890b | |||
69ff9de93d | |||
da97ee7c99 | |||
6c882a8e02 | |||
9a2d216691 | |||
f135c613a9 | |||
2de7d4bd56 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,5 +1,8 @@
|
|||||||
# configs
|
# configs
|
||||||
creds.ini
|
creds.ini
|
||||||
|
tg_settings.py
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
11
Dockerfile
Normal file
11
Dockerfile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
FROM ubuntu:18.04
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y python3 python3-pip && \
|
||||||
|
pip3 install python-telegram-bot && \
|
||||||
|
pip3 install requests && \
|
||||||
|
pip3 install beautifulsoup4
|
||||||
|
|
||||||
|
WORKDIR /usr/share/fesmoo_perdoliq
|
||||||
|
COPY ./*py /usr/share/fesmoo_perdoliq/
|
||||||
|
CMD python3 baraban.py
|
||||||
|
|
11
README.md
11
README.md
@ -1,2 +1,13 @@
|
|||||||
# fesmoo_perdoliq
|
# fesmoo_perdoliq
|
||||||
dirty hack for kids
|
dirty hack for kids
|
||||||
|
|
||||||
|
It is a Telegram bot which is using OpenPerdoliqlib for resolving tests on fesmu university website.
|
||||||
|
|
||||||
|
|
||||||
|
# python3 only
|
||||||
|
reqs:
|
||||||
|
pip install requests
|
||||||
|
|
||||||
|
pip install beautifulsoup4
|
||||||
|
|
||||||
|
pip install python-telegram-bot
|
||||||
|
152
baraban.py
Executable file
152
baraban.py
Executable file
@ -0,0 +1,152 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Simple Bot to reply to Telegram messages.
|
||||||
|
This is built on the API wrapper, see echobot2.py to see the same example built
|
||||||
|
on the telegram.ext bot framework.
|
||||||
|
This program is dedicated to the public domain under the CC0 license.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
import threading
|
||||||
|
import telegram
|
||||||
|
from telegram.error import NetworkError, Unauthorized
|
||||||
|
from time import sleep
|
||||||
|
try:
|
||||||
|
TOKEN = os.environ["TG_TOKEN"]
|
||||||
|
except:
|
||||||
|
print("You have to set env var TG_TOKEN with bot token.")
|
||||||
|
sys.exit(1)
|
||||||
|
try:
|
||||||
|
if os.environ["DRYRUN"]:
|
||||||
|
from dryrun import Perdoliq
|
||||||
|
except:
|
||||||
|
from main import Perdoliq
|
||||||
|
|
||||||
|
update_id = None
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run the bot."""
|
||||||
|
global update_id
|
||||||
|
# Telegram Bot Authorization Token
|
||||||
|
bot = telegram.Bot(TOKEN)
|
||||||
|
|
||||||
|
# get the first pending update_id,
|
||||||
|
# this is so we can skip over it in case
|
||||||
|
# we get an "Unauthorized" exception.
|
||||||
|
try:
|
||||||
|
update_id = bot.get_updates()[0].update_id
|
||||||
|
except IndexError:
|
||||||
|
update_id = None
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
handle_update(bot)
|
||||||
|
except NetworkError:
|
||||||
|
sleep(1)
|
||||||
|
except Unauthorized:
|
||||||
|
# The user has removed or blocked the bot.
|
||||||
|
update_id += 1
|
||||||
|
|
||||||
|
|
||||||
|
def perdoliq(username, password, subj, test, acc, is_delayed):
|
||||||
|
try:
|
||||||
|
app = Perdoliq(username, password)
|
||||||
|
app.auth()
|
||||||
|
app.resolve(subj, test, acc, is_delayed=int(is_delayed))
|
||||||
|
except Exception as e:
|
||||||
|
return "Exception: " + str(e)
|
||||||
|
|
||||||
|
|
||||||
|
def list_test(username, password):
|
||||||
|
try:
|
||||||
|
app = Perdoliq(username, password)
|
||||||
|
app.auth()
|
||||||
|
return (app.get_tests())
|
||||||
|
except Exception as e:
|
||||||
|
return "Exception: " + str(e)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_update(bot):
|
||||||
|
"""Echo the message the user sent."""
|
||||||
|
global update_id
|
||||||
|
# Request updates after the last update_id
|
||||||
|
for update in bot.get_updates(offset=update_id, timeout=10):
|
||||||
|
update_id = update.update_id + 1
|
||||||
|
|
||||||
|
if update.message:
|
||||||
|
# if there is and update, process it in threads
|
||||||
|
t = threading.Thread(target=do_action, args=(update,))
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
def do_action(update):
|
||||||
|
try:
|
||||||
|
s = update.message.text.split()
|
||||||
|
except:
|
||||||
|
return 1
|
||||||
|
if s[0] == '/resolve':
|
||||||
|
if len(s) != 7:
|
||||||
|
update.message.reply_markdown("Missing operand... Try again")
|
||||||
|
update.message.reply_markdown("Usage: */resolve <user[text]> "\
|
||||||
|
"<pass[text]> <subj[int]> <test[int]> "\
|
||||||
|
"<accuracy[0-100]> <commit[1/0]>*")
|
||||||
|
return False
|
||||||
|
|
||||||
|
msg = "Please wait. If you have chosen commit=1, so test "\
|
||||||
|
"going to be resolved in about 20 minutes and will "\
|
||||||
|
"be commited automatically, otherwise it will take "\
|
||||||
|
"about a 2 minutes and you have to "\
|
||||||
|
"commit it by yourself. Just wait. PS you have "\
|
||||||
|
"chosen subj %s "\
|
||||||
|
"test %s and accuracy %s" % (s[3], s[4], s[5])
|
||||||
|
update.message.reply_text(msg)
|
||||||
|
update.message.reply_text("You cannot resolve more than "\
|
||||||
|
"one test in the same time."\
|
||||||
|
"Одновременно решать более одного теста невозможно,"\
|
||||||
|
" вы испортите результаты обоих тестов.")
|
||||||
|
perdoliq(s[1], s[2], s[3], s[4], s[5], s[6])
|
||||||
|
update.message.reply_text("It's done. Check your test because "\
|
||||||
|
"i disclaim any responsibility.")
|
||||||
|
elif s[0] == '/list':
|
||||||
|
try:
|
||||||
|
if len(s) == 3:
|
||||||
|
update.message.reply_text("Fetching tests...")
|
||||||
|
sleep(5)
|
||||||
|
tests = list_test(s[1], s[2])
|
||||||
|
#print("******",tests)
|
||||||
|
else:
|
||||||
|
update.message.reply_markdown("Usage: */list <user[text]>"\
|
||||||
|
" <pass[text]>*")
|
||||||
|
return False
|
||||||
|
except:
|
||||||
|
update.message.reply_markdown("Usage: */list <user[text]>"\
|
||||||
|
" <pass[text]>*")
|
||||||
|
return False
|
||||||
|
msg = "Here is an available tests:\n``` "
|
||||||
|
i = 0
|
||||||
|
#print("******",tests)
|
||||||
|
for subj in tests:
|
||||||
|
msg = msg + (" [%s] %s\n" % (i, subj))
|
||||||
|
i += 1
|
||||||
|
j = 0
|
||||||
|
for test in tests[subj]:
|
||||||
|
msg = msg + (" [%s] %s\n" % (j, test))
|
||||||
|
j += 1
|
||||||
|
update.message.reply_markdown(msg + "```\n Pay attention to "\
|
||||||
|
"numbers in brackets \[..] *Here is subj and test numbers*")
|
||||||
|
else:
|
||||||
|
update.message.reply_markdown("Possible commands: */resolve, /list*")
|
||||||
|
update.message.reply_markdown("Usage: */resolve <user[text]> "\
|
||||||
|
"<pass[text]> <subj[int]> <test[int]> "\
|
||||||
|
"<accuracy[0-100]> <commit[1/0]>*")
|
||||||
|
update.message.reply_markdown("Usage: */list <user[text]> "\
|
||||||
|
"<pass[text]>*")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
main()
|
||||||
|
except:
|
||||||
|
pass
|
94
bot.py
Executable file
94
bot.py
Executable file
@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Simple Bot to reply to Telegram messages.
|
||||||
|
This is built on the API wrapper, see echobot2.py to see the same example built
|
||||||
|
on the telegram.ext bot framework.
|
||||||
|
This program is dedicated to the public domain under the CC0 license.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
import threading
|
||||||
|
import telegram
|
||||||
|
from telegram.error import NetworkError, Unauthorized
|
||||||
|
from time import sleep
|
||||||
|
try:
|
||||||
|
import tg_settings
|
||||||
|
except:
|
||||||
|
print("You have to create tg_settings.py. See tg_settings.py.example.")
|
||||||
|
os.exit(1)
|
||||||
|
try:
|
||||||
|
if os.environ["DRYRUN"]:
|
||||||
|
from dryrun import Perdoliq
|
||||||
|
except:
|
||||||
|
from main import Perdoliq
|
||||||
|
|
||||||
|
update_id = None
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run the bot."""
|
||||||
|
global update_id
|
||||||
|
# Telegram Bot Authorization Token
|
||||||
|
TOKEN = tg_settings.TG_TOKEN
|
||||||
|
bot = telegram.Bot(TOKEN)
|
||||||
|
|
||||||
|
# get the first pending update_id,
|
||||||
|
# this is so we can skip over it in case
|
||||||
|
# we get an "Unauthorized" exception.
|
||||||
|
try:
|
||||||
|
update_id = bot.get_updates()[0].update_id
|
||||||
|
except IndexError:
|
||||||
|
update_id = None
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
handle_update(bot)
|
||||||
|
except NetworkError:
|
||||||
|
sleep(1)
|
||||||
|
except Unauthorized:
|
||||||
|
# The user has removed or blocked the bot.
|
||||||
|
update_id += 1
|
||||||
|
|
||||||
|
|
||||||
|
def perdoliq(username, password, subj, test, acc, is_delayed):
|
||||||
|
try:
|
||||||
|
app = Perdoliq(username, password)
|
||||||
|
app.auth()
|
||||||
|
app.resolve(subj, test, acc, is_delayed=int(is_delayed))
|
||||||
|
except Exception as e:
|
||||||
|
return "Exception: " + str(e)
|
||||||
|
|
||||||
|
|
||||||
|
def list_test(username, password):
|
||||||
|
try:
|
||||||
|
app = Perdoliq(username, password)
|
||||||
|
app.auth()
|
||||||
|
return (app.get_tests())
|
||||||
|
except Exception as e:
|
||||||
|
return "Exception: " + str(e)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_update(bot):
|
||||||
|
"""Echo the message the user sent."""
|
||||||
|
global update_id
|
||||||
|
# Request updates after the last update_id
|
||||||
|
for update in bot.get_updates(offset=update_id, timeout=10):
|
||||||
|
update_id = update.update_id + 1
|
||||||
|
|
||||||
|
if update.message:
|
||||||
|
# if there is and update, process it in threads
|
||||||
|
t = threading.Thread(target=do_action, args=(update,))
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
def do_action(update):
|
||||||
|
try:
|
||||||
|
s = update.message.text.split()
|
||||||
|
except:
|
||||||
|
return 1
|
||||||
|
# if s[0] == '/resolve':
|
||||||
|
# return 0
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
41
database.py
Normal file
41
database.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import datetime as dt
|
||||||
|
|
||||||
|
class DataBase:
|
||||||
|
def __init__(self, basefile, scheme):
|
||||||
|
import sqlite3
|
||||||
|
self.scheme = ''
|
||||||
|
try:
|
||||||
|
self.conn = sqlite3.connect(basefile, check_same_thread=False)
|
||||||
|
except:
|
||||||
|
print('Could not connect to DataBase.')
|
||||||
|
return None
|
||||||
|
with open(scheme, 'r') as scheme_sql:
|
||||||
|
sql = scheme_sql.read()
|
||||||
|
self.scheme = sql
|
||||||
|
if self.conn is not None:
|
||||||
|
try:
|
||||||
|
cursor = self.conn.cursor()
|
||||||
|
cursor.executescript(sql)
|
||||||
|
except:
|
||||||
|
print('Could not create scheme.')
|
||||||
|
else:
|
||||||
|
print("Error! cannot create the database connection.")
|
||||||
|
print('DB created.')
|
||||||
|
|
||||||
|
def execute(self, sql):
|
||||||
|
cursor = self.conn.cursor()
|
||||||
|
cursor.execute(sql)
|
||||||
|
self.conn.commit()
|
||||||
|
return cursor.fetchall()
|
||||||
|
|
||||||
|
def update_user(self, user_name, user_id):
|
||||||
|
date = int(dt.datetime.now().strftime("%s"))
|
||||||
|
sql = """INSERT OR IGNORE INTO
|
||||||
|
users('user_id', 'user_name', 'date')
|
||||||
|
VALUES ('%s','%s','%s')""" % (
|
||||||
|
user_id,
|
||||||
|
user_name,
|
||||||
|
date
|
||||||
|
)
|
||||||
|
self.execute(sql)
|
||||||
|
|
132
dryrun.py
Normal file
132
dryrun.py
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
import requests
|
||||||
|
import settings
|
||||||
|
import logging
|
||||||
|
import re
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from random import randint
|
||||||
|
import time
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
|
class Perdoliq:
|
||||||
|
def __init__(self, username, password):
|
||||||
|
self.password = password
|
||||||
|
self.username = username
|
||||||
|
self.SessionId = ''
|
||||||
|
self.name = ''
|
||||||
|
self.subjects = {}
|
||||||
|
|
||||||
|
# make auth
|
||||||
|
def auth(self):
|
||||||
|
self.SessionId = '** DRY_RUN_ASP.NET_SessionId **'
|
||||||
|
return self.SessionId
|
||||||
|
|
||||||
|
# update and return list of subjs and tests
|
||||||
|
def get_tests(self):
|
||||||
|
self.subjects = {
|
||||||
|
'Аналитическая химия': [
|
||||||
|
'броматометрическое титрование',
|
||||||
|
'Качественный анализ. Теоретические основы. Итоговый',
|
||||||
|
'Химический количественный анализ. Итоговый', 'Йодометрия',
|
||||||
|
'редоксиметрия. нитритометрия',
|
||||||
|
'Количественный анализ. Протолитометрия.'
|
||||||
|
],
|
||||||
|
'Безопасность жизнедеятельности, медицина катастроф': [
|
||||||
|
'Мобилизационная подготовка здравоохранения',
|
||||||
|
'Медицина катастроф', 'Гражданская оборона'
|
||||||
|
],
|
||||||
|
'Биологическая химия': [
|
||||||
|
'Химия белков', 'Ферменты', 'Витамины',
|
||||||
|
'Нуклеиновые кислоты и матричные биосинтезы',
|
||||||
|
'Обмен углеводов', 'Энергетический обмен'
|
||||||
|
],
|
||||||
|
'Дисциплины по выбору Ф-04-1':
|
||||||
|
['физико-химические методы анализа'],
|
||||||
|
'Иностранный язык': [
|
||||||
|
'лексико-грамматический 9', 'Лексико-грамматический 8',
|
||||||
|
'лексико-грамматический 10', 'лексико-грамматический 3а'
|
||||||
|
],
|
||||||
|
'Органическая химия': [
|
||||||
|
'Аминокислоты', 'Углеводы',
|
||||||
|
'Карбоновые кислоты, гетерофункуциональные соединения',
|
||||||
|
'Омыляемые липиды', 'Неомыляемые липиды',
|
||||||
|
'Гетероциклические соединения'
|
||||||
|
],
|
||||||
|
'Патология': [
|
||||||
|
'Аллергия', 'Патология системы иммунобиологического надзора',
|
||||||
|
'Нозология', 'Патология белкового обмена',
|
||||||
|
'Патология обмена жиров', 'Патология углеводного обмена',
|
||||||
|
'Патология водного и ионного обменов. Нарушение КОС.',
|
||||||
|
'ЛИХОРАДКА', 'Кислородное голодание',
|
||||||
|
'Патофизиология периферического кровобращения. Воспаление.'
|
||||||
|
],
|
||||||
|
'Первая доврачебная помощь': ['Первая доврачебная помощь'],
|
||||||
|
'Физическая культура': [
|
||||||
|
'Методы контроля за функциональным и физическим состоянием организма человека'
|
||||||
|
],
|
||||||
|
'Философия': [
|
||||||
|
'Онтология. Гносеология', 'Западная философия 19-20вв-2',
|
||||||
|
'Западная философия 19-20вв - 3', 'Онтология',
|
||||||
|
'Научное познание - 2', 'Западная философия 19-20вв',
|
||||||
|
'Философия истории', 'Философия человека - 1',
|
||||||
|
'Философия человека - 2', 'Бытие и сознание',
|
||||||
|
'Социальная философия - 1', 'Научное познание',
|
||||||
|
'Философия человека', 'Онтология - 2',
|
||||||
|
'Философия общества и глобальные проблемы человечества',
|
||||||
|
'Русская философия'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return self.subjects
|
||||||
|
|
||||||
|
def start_test(self, pred, test):
|
||||||
|
|
||||||
|
return 30
|
||||||
|
|
||||||
|
# predict answers for any question
|
||||||
|
def predict(self, q_number):
|
||||||
|
|
||||||
|
return ['2']
|
||||||
|
|
||||||
|
# mark answers into requested question
|
||||||
|
def answer(self, q_number, answers):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
# commit test
|
||||||
|
def finish_test(self):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def resolve(self, subj, test, accuracy, is_delayed=False):
|
||||||
|
# renew auth
|
||||||
|
self.auth()
|
||||||
|
# get count of questions
|
||||||
|
q_count = self.start_test(subj, test)
|
||||||
|
|
||||||
|
def sleep_rand():
|
||||||
|
delay = randint(20, 40)
|
||||||
|
logging.info("Going to wait %s sec for this question." % delay)
|
||||||
|
time.sleep(delay)
|
||||||
|
|
||||||
|
accuracy = int(accuracy)
|
||||||
|
# applying accuracy here. trying to make resulting
|
||||||
|
# accuracy NO LESSthan requested.
|
||||||
|
spoil_count = int(q_count - q_count * (accuracy / 100))
|
||||||
|
if int(spoil_count / q_count * (-100) + 100) < accuracy:
|
||||||
|
spoil_count -= 1
|
||||||
|
# skip random `spoil_count` questions.
|
||||||
|
# Choose questions which going to be skipped
|
||||||
|
skip_this = []
|
||||||
|
for i in range(0, spoil_count):
|
||||||
|
skip_this.append(randint(1, q_count + 1))
|
||||||
|
|
||||||
|
# start resolve test
|
||||||
|
for i in range(1, q_count + 1):
|
||||||
|
if is_delayed == True:
|
||||||
|
sleep_rand()
|
||||||
|
if i not in skip_this:
|
||||||
|
prediction = self.predict(i)
|
||||||
|
self.answer(i, prediction)
|
||||||
|
|
||||||
|
# make autocommit
|
||||||
|
if is_delayed == True:
|
||||||
|
self.finish_test()
|
5
main.py
5
main.py
@ -39,6 +39,7 @@ class Perdoliq:
|
|||||||
settings.fesmu_root_url + 'startstu.aspx',
|
settings.fesmu_root_url + 'startstu.aspx',
|
||||||
cookies={'ASP.NET_SessionId': self.SessionId})
|
cookies={'ASP.NET_SessionId': self.SessionId})
|
||||||
soup = BeautifulSoup(r.text, "html.parser")
|
soup = BeautifulSoup(r.text, "html.parser")
|
||||||
|
#print("****** ", soup)
|
||||||
_p = re.compile(',.*$')
|
_p = re.compile(',.*$')
|
||||||
self.name = _p.sub(
|
self.name = _p.sub(
|
||||||
'', soup.find(id="ctl00_MainContent_Label1").get_text())[14:]
|
'', soup.find(id="ctl00_MainContent_Label1").get_text())[14:]
|
||||||
@ -143,7 +144,7 @@ class Perdoliq:
|
|||||||
"There isn't any correct answers for %s. Looks like"\
|
"There isn't any correct answers for %s. Looks like"\
|
||||||
" something went wrong. Trying other way...", q_number
|
" something went wrong. Trying other way...", q_number
|
||||||
)
|
)
|
||||||
# send all checkboxes as answer to 30th page
|
# send all checkboxes as answer to 30th page (4 answers questions)
|
||||||
requests.post(
|
requests.post(
|
||||||
settings.fesmu_root_url + 'studtst2.aspx',
|
settings.fesmu_root_url + 'studtst2.aspx',
|
||||||
data=settings.merge(
|
data=settings.merge(
|
||||||
@ -232,12 +233,12 @@ class Perdoliq:
|
|||||||
logging.info("Going to wait %s sec for this question." % delay)
|
logging.info("Going to wait %s sec for this question." % delay)
|
||||||
time.sleep(delay)
|
time.sleep(delay)
|
||||||
|
|
||||||
|
accuracy = int(accuracy)
|
||||||
# applying accuracy here. trying to make resulting
|
# applying accuracy here. trying to make resulting
|
||||||
# accuracy NO LESSthan requested.
|
# accuracy NO LESSthan requested.
|
||||||
spoil_count = int(q_count - q_count * (accuracy / 100))
|
spoil_count = int(q_count - q_count * (accuracy / 100))
|
||||||
if int(spoil_count / q_count * (-100) + 100) < accuracy:
|
if int(spoil_count / q_count * (-100) + 100) < accuracy:
|
||||||
spoil_count -= 1
|
spoil_count -= 1
|
||||||
|
|
||||||
# skip random `spoil_count` questions.
|
# skip random `spoil_count` questions.
|
||||||
# Choose questions which going to be skipped
|
# Choose questions which going to be skipped
|
||||||
skip_this = []
|
skip_this = []
|
||||||
|
8
reqs.txt
8
reqs.txt
@ -1,5 +1,7 @@
|
|||||||
python3
|
# python3 only
|
||||||
|
pip install requests
|
||||||
|
|
||||||
py -m pip install requests
|
pip install beautifulsoup4
|
||||||
|
|
||||||
|
pip install python-telegram-bot
|
||||||
|
|
||||||
py -m pip install beautifulsoup4
|
|
12
scheme.sql
Normal file
12
scheme.sql
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
BEGIN TRANSACTION;
|
||||||
|
-- DROP TABLE IF EXISTS `user`;
|
||||||
|
CREATE TABLE IF NOT EXISTS `user` (
|
||||||
|
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
`user_id` TEXT NOT NULL,
|
||||||
|
`user_name` TEXT NOT NULL,
|
||||||
|
`site_name` TEXT,
|
||||||
|
`site_user` TEXT,
|
||||||
|
`site_pass` TEXT,
|
||||||
|
`date` INTEGER NOT NULL
|
||||||
|
);
|
||||||
|
COMMIT;
|
84
settings.py
84
settings.py
File diff suppressed because one or more lines are too long
1
tg_settings.py.example
Normal file
1
tg_settings.py.example
Normal file
@ -0,0 +1 @@
|
|||||||
|
TG_TOKEN = '4712707:329GqTj222i8unS23367sXqeMsyE'
|
Reference in New Issue
Block a user