32 Commits

Author SHA1 Message Date
AB
45177e13e4 major UI improvement. 2019-12-26 20:19:10 +00:00
AB
d348989afb major UI improvement. 2019-12-26 20:18:40 +00:00
c631da43a1 Start keyboard version 2019-12-26 16:56:16 +03:00
6ab5e06c5e Remove trash 2019-12-26 16:41:57 +03:00
AB
ab7aef8da7 Adjust bot to new portal. 2019-12-06 12:23:21 +03:00
AB
16d8af1bac Fix 30th pages (4 options pages) 2019-03-28 19:48:12 +03:00
AB
377213edfd Update some scam_data. Split list command for subjects and tests. 2019-03-28 18:28:23 +03:00
77c59a91bd Dummy commit 2018-09-26 18:48:22 +03:00
287b5b346b Fix CI procedure 2018-09-26 18:34:46 +03:00
0dcb2d6f9b Add Ci procedure 2018-09-26 18:24:55 +03:00
4d463182aa Merge branch 'master' of https://github.com/hillsofeternity1/fesmoo_perdoliq 2018-06-04 08:16:11 +00:00
52e78ef94d Update cookies. 2018-06-04 08:15:44 +00:00
da9c098623 Try to catch telegram api network issues and prevent bot crash. 2018-05-24 16:17:20 +03:00
b0ff3b9034 Merge branch 'master' of github.com:hillsofeternity1/fesmoo_perdoliq 2018-05-17 20:08:23 +03:00
506978ea76 Database features. Development has started. 2018-05-17 20:07:50 +03:00
21527657b2 Update README.md 2018-05-17 19:40:02 +03:00
7341eaaa4e Multithreading message handling. 2018-05-17 16:33:53 +00:00
6b948d4b2b Fix include issue 2018-05-17 15:58:53 +00:00
67244888af Fix 2018-05-17 18:43:54 +03:00
358c6b348b Added dryrun mode. Also tg bot key has been moved to tg_settings file 2018-05-17 18:42:45 +03:00
AB
03748de34e Update command style 2018-05-12 15:05:59 +03:00
mk
2f3e43f937 added beautiful picture 2018-05-12 00:36:56 +02:00
mk
6b711e7151 added beautiful picture 2018-05-12 00:36:34 +02:00
fcb5b74e41 Fix message parse error. 2018-05-11 22:11:07 +00:00
484636369d Make telegram interface more user friendly. 2018-05-11 21:30:42 +00:00
408c1e890b Make telegram interface more user friendly. 2018-05-11 21:29:39 +00:00
AB
69ff9de93d PIZDA 2018-05-11 23:09:11 +03:00
AB
da97ee7c99 PIZDA 2018-05-11 23:08:29 +03:00
mk
6c882a8e02 fixes 2018-05-11 22:03:35 +02:00
mk
9a2d216691 fixes 2018-05-11 21:50:45 +02:00
mk
f135c613a9 removet useless action 2018-05-11 21:27:43 +02:00
mk
2de7d4bd56 added baraban 2018-05-11 20:46:37 +02:00
15 changed files with 739 additions and 243 deletions

5
.gitignore vendored
View File

@ -1,5 +1,10 @@
# configs
creds.ini
baraban.build/
tg_settings.py
*.swp
*.swo
.vscode/
# Byte-compiled / optimized / DLL files
__pycache__/

117
.vscode/launch.json vendored
View File

@ -1,117 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}"
},
{
"name": "Python: Attach",
"type": "python",
"request": "attach",
"localRoot": "${workspaceFolder}",
"remoteRoot": "${workspaceFolder}",
"port": 3000,
"secret": "my_secret",
"host": "localhost"
},
{
"name": "Python: Terminal (integrated)",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
},
{
"name": "Python: Terminal (external)",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "externalTerminal"
},
{
"name": "Python: Django",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/manage.py",
"args": [
"runserver",
"--noreload",
"--nothreading"
],
"debugOptions": [
"RedirectOutput",
"Django"
]
},
{
"name": "Python: Flask (0.11.x or later)",
"type": "python",
"request": "launch",
"module": "flask",
"env": {
"FLASK_APP": "${workspaceFolder}/app.py"
},
"args": [
"run",
"--no-debugger",
"--no-reload"
]
},
{
"name": "Python: Module",
"type": "python",
"request": "launch",
"module": "module.name"
},
{
"name": "Python: Pyramid",
"type": "python",
"request": "launch",
"args": [
"${workspaceFolder}/development.ini"
],
"debugOptions": [
"RedirectOutput",
"Pyramid"
]
},
{
"name": "Python: Watson",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/console.py",
"args": [
"dev",
"runserver",
"--noreload=True"
]
},
{
"name": "Python: All debug Options",
"type": "python",
"request": "launch",
"pythonPath": "${config:python.pythonPath}",
"program": "${file}",
"module": "module.name",
"env": {
"VAR1": "1",
"VAR2": "2"
},
"envFile": "${workspaceFolder}/.env",
"args": [
"arg1",
"arg2"
],
"debugOptions": [
"RedirectOutput"
]
}
]
}

View File

@ -1,5 +0,0 @@
{
"python.pythonPath": "/bin/python",
"python.formatting.provider": "yapf",
"python.linting.pylintEnabled": false
}

11
Dockerfile Normal file
View 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 bot_keys.py

View File

@ -1,2 +1,14 @@
# fesmoo_perdoliq
dirty hack for kids
It is a Telegram bot which is using OpenPerdoliqlib for resolving tests on fesmu university website.
here is docker image https://hub.docker.com/r/ultradesu/fesmoo_perdoliq/
# python3 only
reqs:
pip install requests
pip install beautifulsoup4
pip install python-telegram-bot

42
baraban.py Executable file
View File

@ -0,0 +1,42 @@
#!/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
from time import sleep
from main import Perdoliq
def main():
list_test('4016014', '40403')
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)
if __name__ == '__main__':
try:
main()
except:
pass

168
bot.py Executable file
View File

@ -0,0 +1,168 @@
#!/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 subjects...")
sleep(1)
tests = list_test(s[1], s[2])
msg = "Here is an available subjects:\n```"
i = 0
for subj in tests:
tests_count = len(tests[subj])
msg = msg + (" [%s] %s (%s tests)\n" % (i, subj, tests_count))
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 or test numbers*")
elif len(s) == 4:
update.message.reply_text("Fetching tests...")
sleep(1)
tests = list_test(s[1], s[2])
i = int(s[3])
msg = "Here is an available tests:\n"
j = 0
for subj in tests:
if j == i:
msg = msg + ("``` *** %s ***\n----------\n" % subj)
k = 0
for test in tests[subj]:
msg = msg + ("[%s] %s\n" % (k, test))
k += 1
j += 1
update.message.reply_markdown(msg + "```\n Pay attention to "\
"numbers in brackets \[..] *Here is subj or test numbers*")
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
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

243
bot_keys.py Normal file
View File

@ -0,0 +1,243 @@
#!/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
from telegram import *
from telegram.ext import Updater, CommandHandler, CallbackQueryHandler
from telegram.error import NetworkError, Unauthorized
from time import sleep
from functools import wraps
from pprint import pprint
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
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)
LOG = logging.getLogger(__name__)
auth = dict()
cached_tests = dict()
def main():
"""Run bot."""
updater = Updater(TOKEN, use_context=True)
dp = updater.dispatcher
dp.add_handler(CallbackQueryHandler(button_handler))
dp.add_handler(CommandHandler("login", login,
pass_args=True,
pass_job_queue=True,
pass_chat_data=True))
dp.add_handler(CommandHandler("list", list_,
pass_args=True,
pass_job_queue=True,
pass_chat_data=True))
# log all errors
dp.add_error_handler(error)
updater.start_polling()
updater.idle()
def error(update, context):
"""Log Errors caused by Updates."""
LOG.warning('Update "%s" caused error "%s"', update, context.error)
def is_authorized(id_):
def decorator(f):
@wraps(f)
def wrapped(*args, **kwargs):
if args[0].effective_user.id not in auth:
LOG.info(
"User %s (%s) is new user. Redirecting to login.",
args[0].effective_user.first_name,
args[0].effective_user.id)
return login_first(*args, **kwargs)
ret = f(*args, **kwargs)
return ret
return wrapped
return decorator
def login_first(update, context):
msg = "Необходимо авторизоваться. "\
"Авторизация будет сохранена "\
"до момента перезагрузки бота. Пример: /login <user> <pass>"
try:
update.message.reply_text(msg)
except:
query = update.callback_query
query.edit_message_text(msg)
LOG.info("Going to login")
def login(update, context):
user_id = update.effective_user.id
message = update.message.text.split()
if len(message) == 3:
login = message[1]
passwd = message[2]
auth[user_id] = dict()
auth[user_id]["login"] = login
auth[user_id]["passwd"] = passwd
update.message.reply_text("Учетные данные сохранены.")
elif len(message) == 2 and message[1] == 'status':
if user_id in auth:
update.message.reply_text(
"Вы авторизованы с данными: {} : {}***\n"\
"Для обновления данных авторизуйтесь повторно.".format(
auth[user_id]["login"],
auth[user_id]["passwd"][0:2]))
else:
update.message.reply_text("Вы еще не авторизованы.")
else:
update.message.reply_text("Запрет! Попытка взлома! Делай так: "\
"/login <user> <pass> или /login status")
def perdoliq(username, password, subj, test, acc, submit=True, is_delayed=False):
try:
app = Perdoliq(username, password)
app.auth()
app.resolve(subj, test, acc, submit, is_delayed)
except Exception as e:
return "Exception: " + str(e)
def list_test(username, password):
if username in cached_tests:
return cached_tests[username]
try:
app = Perdoliq(username, password)
app.auth()
tests = app.get_tests()
cached_tests[username] = tests
return tests
except Exception as e:
return "Exception: " + str(e)
@is_authorized('list_')
def list_(update, context):
query = update.callback_query
user_id = update.effective_user.id
tests = list_test(auth[user_id]["login"], auth[user_id]["passwd"])
print(tests)
keyboard = list()
i = 1
for subj in tests:
tests_count = len(tests[subj])
#msg = msg + (" [%s] %s (%s tests)\n" % (i, subj, tests_count))
keyboard.append([InlineKeyboardButton(f"{i}. {subj}", callback_data=f"s_{i}")])
i += 1
keyboard.append([InlineKeyboardButton("Close", callback_data="subj")])
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text('Чо будем хакать?', reply_markup=reply_markup)
@is_authorized('button_handler')
def button_handler(update, context):
query = update.callback_query
user_id = update.effective_user.id
tests = list_test(auth[user_id]["login"], auth[user_id]["passwd"])
if query.data.split('_')[0] == 'close':
query.edit_message_text('Пака братишка')
if query.data.split('_')[0] == 's': # subj
data = query.data
subj_num = query.data.split('_')[1]
keyboard = list()
subj_name = None
j = 1 # subj number
i = 1 # test number
for subj in tests:
LOG.debug("Checking: %s. %s is %s", subj, j, subj_num)
if j != int(subj_num):
j += 1
continue
else:
LOG.info("Found needed subj: %s", subj)
subj_name = subj
for test in tests[subj]:
LOG.info("Found test: %s", test)
keyboard.append([
InlineKeyboardButton(f"{i}. {test}",
callback_data=f"t_{i}_{data}")])
i += 1
break
keyboard.append([InlineKeyboardButton("Закрыть", callback_data=f"close")])
reply_markup = InlineKeyboardMarkup(keyboard)
query.edit_message_text(
f"Ok, решаем {subj_name}, а какой тест?",
reply_markup=reply_markup)
if query.data.split('_')[0] == 't': # test
data = query.data
keyboard = [[], []]
for p in range(0, 51, 5):
keyboard[0].append(InlineKeyboardButton(f"{p}", callback_data=f"p_{p}_{data}"))
for p in range(50, 101, 5):
keyboard[1].append(InlineKeyboardButton(f"{p}", callback_data=f"p_{p}_{data}"))
keyboard.append([InlineKeyboardButton("Закрыть", callback_data=f"close")])
reply_markup = InlineKeyboardMarkup(keyboard)
query.edit_message_text("Ok, а какая точность?", reply_markup=reply_markup)
if query.data.split('_')[0] == 'm': # autosubmit
data = query.data
keyboard = [[
InlineKeyboardButton(f"Быстро", callback_data=f"d_0_{data}"),
InlineKeyboardButton(f"С задержками", callback_data=f"d_1_{data}"),]]
keyboard.append([InlineKeyboardButton("Закрыть", callback_data=f"close")])
reply_markup = InlineKeyboardMarkup(keyboard)
query.edit_message_text(
"Решить тест быстро или с задержками, типа я думал над ответом.",
reply_markup=reply_markup)
if query.data.split('_')[0] == 'p': # precision
data = query.data
keyboard = [[
InlineKeyboardButton(f"Завершить", callback_data=f"m_1_{data}"),
InlineKeyboardButton(f"Не завершать", callback_data=f"m_0_{data}"),]]
keyboard.append([InlineKeyboardButton("Close", callback_data=f"close")])
reply_markup = InlineKeyboardMarkup(keyboard)
query.edit_message_text(
"Завершить тест автоматически после решения или оставить для проверки?",
reply_markup=reply_markup)
if query.data.split('_')[0] == 'd': # is_delayed
data = query.data
LOG.info(data)
# d_0_m_1_p_100_t_1_s_10
subj = query.data.split('_')[9]
test = query.data.split('_')[7]
precision = query.data.split('_')[5]
submit = bool(int(query.data.split('_')[3]))
delay = bool(int(query.data.split('_')[1]))
query.edit_message_text(
"Опять работа... "\
"Пока я решаю тест ЗАПРЕЩЕНО "\
"пользоваться сайтом с тестами. "\
"Резултат будет испорчен.")
perdoliq(
auth[user_id]["login"],
auth[user_id]["passwd"],
int(subj)-1,
int(test)-1,
precision,
submit,
delay)
if __name__ == '__main__':
try:
main()
except Exception as e:
LOG.error("%s", e)
pass

41
database.py Normal file
View 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
View 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()

21
main.py
View File

@ -30,15 +30,15 @@ class Perdoliq:
settings.fesmu_root_url,
data=settings.merge(
settings.scam_data_1, {
'ctl00$MainContent$TextBox1': self.username,
'ctl00$MainContent$TextBox2': self.password,
'ctl00$MainContent$UserText': self.username,
'ctl00$MainContent$PassText': self.password,
}),
cookies={'ASP.NET_SessionId': self.SessionId})
r = requests.get(
settings.fesmu_root_url + 'startstu.aspx',
cookies={'ASP.NET_SessionId': self.SessionId})
soup = BeautifulSoup(r.text, "html.parser")
#print("****** ", soup)
_p = re.compile(',.*$')
self.name = _p.sub(
'', soup.find(id="ctl00_MainContent_Label1").get_text())[14:]
@ -61,6 +61,7 @@ class Perdoliq:
# parse tests per subject
i = 0
for subject in self.subjects:
logging.info('Found subject %s' % subject)
r = requests.post(
settings.fesmu_root_url + 'studtst1.aspx',
data=settings.merge(settings.scam_data_2,
@ -69,6 +70,7 @@ class Perdoliq:
soup = BeautifulSoup(r.text, "html.parser")
for test in soup.find_all(class_="dxeListBoxItem_Aqua dxeLTM"):
if test.get_text() != '\xa0':
logging.info('\tFound test %s for subject %s' % (test.get_text(), subject))
self.subjects[subject].append(test.get_text())
logging.debug('%s - Found test %s' % (subject,
test.get_text()))
@ -132,7 +134,7 @@ class Perdoliq:
settings.fesmu_root_url + 'studtst3.aspx',
data=settings.scam_data_5,
cookies={'ASP.NET_SessionId': self.SessionId})
# get answer page
# get page with answers
r = requests.get(
settings.fesmu_root_url + 'studtst5.aspx',
cookies={'ASP.NET_SessionId': self.SessionId},
@ -143,7 +145,7 @@ class Perdoliq:
"There isn't any correct answers for %s. Looks like"\
" 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(
settings.fesmu_root_url + 'studtst2.aspx',
data=settings.merge(
@ -155,6 +157,7 @@ class Perdoliq:
settings.fesmu_root_url + 'studtst30.aspx',
data=settings.scam_data_7,
cookies={'ASP.NET_SessionId': self.SessionId})
# get page with answers
r = requests.get(
settings.fesmu_root_url + 'studtst5.aspx',
cookies={'ASP.NET_SessionId': self.SessionId},
@ -221,8 +224,10 @@ class Perdoliq:
data=settings.scam_data_10,
cookies={'ASP.NET_SessionId': self.SessionId})
def resolve(self, subj, test, accuracy, is_delayed=False):
def resolve(self, subj, test, accuracy=100, submit=False, is_delayed=False):
# renew auth
logging.info(
f"Resolving subj {subj}, test {test}, acc {accuracy}, submit {submit}, delay {is_delayed}")
self.auth()
# get count of questions
q_count = self.start_test(subj, test)
@ -232,12 +237,12 @@ class Perdoliq:
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 = []
@ -253,5 +258,5 @@ class Perdoliq:
self.answer(i, prediction)
# make autocommit
if is_delayed == True:
if submit == True:
self.finish_test()

View File

@ -1,5 +1,4 @@
python3
requests
beautifulsoup4
python-telegram-bot
py -m pip install requests
py -m pip install beautifulsoup4

12
scheme.sql Normal file
View 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;

File diff suppressed because one or more lines are too long

1
tg_settings.py.example Normal file
View File

@ -0,0 +1 @@
TG_TOKEN = '4712707:329GqTj222i8unS23367sXqeMsyE'