diff --git a/endpoints.py b/endpoints.py new file mode 100755 index 0000000..922fa6f --- /dev/null +++ b/endpoints.py @@ -0,0 +1,4 @@ +BEGIN_TEST = lambda id: "https://videouroki.net/tests/api/beginTest/" + str(id) +DO_TEST = lambda uuid: "https://videouroki.net/tests/do/" + str(uuid) +COMPLETE_TEST = lambda uuid: "https://videouroki.net/tests/complete/" + str(uuid) +SAVE_ANSWER = lambda id: "https://videouroki.net/tests/api/save/" + str(id) \ No newline at end of file diff --git a/get_test.py b/get_test.py new file mode 100755 index 0000000..5c25c28 --- /dev/null +++ b/get_test.py @@ -0,0 +1,41 @@ +from concurrent.futures import ThreadPoolExecutor +from bs4 import BeautifulSoup +from yaspin import yaspin +import itertools +import endpoints +import requests +import json + +FIRSTNAME = "Иванов" +LASTNAME = "Василий" +CLASSTXT = "9А" +TEST_ID = int(input("Enter test ID: ")) + + +def begin_test(id: int, fisrstname: str, lastname: str, classtxt: str) -> dict: + data = { + "member": { + "id": False, + "lastname": lastname, + "firstname": fisrstname, + "classTxt": classtxt + }, + "related": 0 + } + return json.loads(requests.post(endpoints.BEGIN_TEST(id), json=data).content) + + +def get_test(uuid: str) -> dict: + content = requests.get(endpoints.DO_TEST(uuid)).content + soup = BeautifulSoup(content, "html.parser") + return json.loads(soup.select("body > script")[2].text.replace("window.backend = ", "").strip()) + +def complete_test(uuid: str) -> int: + content = requests.get(endpoints.COMPLETE_TEST(uuid)).content + soup = BeautifulSoup(content, "html.parser") + return int(soup.select("div.test_main__results_statitem")[2].text.strip().replace("Выполнено верно\n","")) + +test = begin_test(TEST_ID, FIRSTNAME, LASTNAME, CLASSTXT)['uuid'] + +print(get_test(test)) +complete_test(test) diff --git a/parse.py b/parse.py new file mode 100755 index 0000000..5ae02ff --- /dev/null +++ b/parse.py @@ -0,0 +1,188 @@ +import endpoints +from concurrent.futures import ThreadPoolExecutor +from bs4 import BeautifulSoup +from yaspin import yaspin +import itertools +import requests +import json + +FIRSTNAME = "Иванов" +LASTNAME = "Василий" +CLASSTXT = "9А" +TEST_ID = input("Enter test ID: ") + + +def begin_test(id: int, fisrstname: str, lastname: str, classtxt: str) -> dict: + data = { + "member": { + "id": False, + "lastname": lastname, + "firstname": fisrstname, + "classTxt": classtxt + }, + "related": 0 + } + return json.loads(requests.post(endpoints.BEGIN_TEST(id), json=data).content) + + +def get_test(uuid: str) -> dict: + content = requests.get(endpoints.DO_TEST(uuid)).content + soup = BeautifulSoup(content, "html.parser") + return json.loads(soup.select("body > script")[2].text.replace("window.backend = ", "").strip()) + +def complete_test(uuid: str) -> int: + content = requests.get(endpoints.COMPLETE_TEST(uuid)).content + soup = BeautifulSoup(content, "html.parser") + return int(soup.select("div.test_main__results_statitem")[2].text.strip().replace("Выполнено верно\n","")) + +def answer_question(question_id, variants, uuid, testTitle, fakeid): + data = { + "answer": { + "id": question_id, + "variants": variants + }, + "member": { + "testTitle": testTitle, + "user": " ".join([FIRSTNAME, LASTNAME]), + "class": CLASSTXT, + "fakeId": fakeid, + "uuid": uuid + } + } + requests.post(endpoints.SAVE_ANSWER(fakeid), json=data) + + +def toThread(vars, names): + test_person = begin_test( + TEST_ID, FIRSTNAME, LASTNAME, CLASSTXT) + test = get_test(test_person["uuid"]) + answer_question(question["id"], vars, test_person["uuid"], + test["member"]["testTitle"], test["member"]["fakeId"]) + return [complete_test(test_person['uuid']), names] + + + +test_person = begin_test(TEST_ID, FIRSTNAME, LASTNAME, CLASSTXT) +print("Test processing started.") + +test = get_test(test_person["uuid"]) +questions = json.loads(test["questions"]) + +complete_test(test_person['uuid']) + +for question in questions: + print("Q:", BeautifulSoup( + question["description"], "html.parser").text.replace("\n", ""), f"Type: {question['type']}") + if question['type'] == 1: + with yaspin(text="Initializing", color="cyan") as sp: + for i in range(len(question["answers"])): + test_person = begin_test( + TEST_ID, FIRSTNAME, LASTNAME, CLASSTXT) + test = get_test(test_person["uuid"]) + + answer_question(question["id"], question["answers"][i]["id"], + test_person["uuid"], test["member"]["testTitle"], test["member"]["fakeId"]) + + sp.text = f"Tried {i} of {len(question['answers'])}" + + if complete_test(test_person['uuid']) == 1: + sp.text = f"Answer: ✅ {question['answers'][i]['text']}" + sp.ok("Found!") + break + + elif question["type"] == 2: + with yaspin(text="Initializing", color="cyan") as sp: + combs = list(itertools.product( + (True, False), repeat=len(question["answers"]))) + for i in range(len(combs)): + test_person = begin_test( + TEST_ID, FIRSTNAME, LASTNAME, CLASSTXT) + test = get_test(test_person["uuid"]) + vars = [] + names = [] + for j in range(len(combs[i])): + if combs[i][j]: + vars.append(question["answers"][j]["id"]) + names.append(question["answers"][j]["text"]) + + answer_question(question["id"], vars, test_person["uuid"], + test["member"]["testTitle"], test["member"]["fakeId"]) + + sp.text = f"Tried {i} of {len(combs)} {int((i/len(combs))*100)}%" + + if complete_test(test_person['uuid']) == 1: + msg = '\n'.join(map(lambda x: ' ✅ '+x, names)) + sp.text = f"Answers: \n{msg}" + sp.ok("Found!") + break + + elif (question["type"] == 4 or question["type"] == 5) and False: + with yaspin(text="Initializing", color="cyan") as sp: + try: + combs = list(itertools.product(range(1, len(json.loads(question["annotation"]))+1), repeat=len(question["answers"]))) + except TypeError: + combs = list(itertools.product(range(1, len(question["answers"])+1), repeat=len(question["answers"]))) + pool = [] + with ThreadPoolExecutor() as executor: + for i in range(len(combs)): + vars = [] + names = [] + for j in range(len(combs[i])): + vars.append({ + "answer_id": question["answers"][j]["id"], + "answer": combs[i][j] + }) + names.append({ + "name": question["answers"][j]["text"], + "answer": combs[i][j] + }) + pool.append(executor.submit(toThread, vars, names)) + + sp.text = f"Completed 0 of {len(combs)} 0%" + for i in range(len(pool)): + result, names = pool[i].result() + sp.text = f"Completed {i+1} of {len(combs)} {int(((i+1)/len(combs))*100)}%" + if result == 1: + msg = '\n'.join([f" {answer['answer']}) {answer['name']}" for answer in names]) + sp.text = f"Answer: \n{msg}" + sp.ok("Found!") + executor.shutdown(wait=False, cancel_futures=True) + break + + + elif question["type"] == 6: + with yaspin(text="Initializing", color="cyan") as sp: + combs = list(itertools.product( + (0, 1), repeat=len(question["answers"]))) + for i in range(len(combs)): + test_person = begin_test( + TEST_ID, FIRSTNAME, LASTNAME, CLASSTXT) + test = get_test(test_person["uuid"]) + vars = [] + names = [] + for j in range(len(combs[i])): + vars.append({ + "answer_id": question["answers"][j]["id"], + "answer": combs[i][j] + }) + names.append({ + "name": question["answers"][j]["text"], + "answer": combs[i][j] + }) + + answer_question(question["id"], vars, test_person["uuid"], + test["member"]["testTitle"], test["member"]["fakeId"]) + + sp.text = f"Tried {i} of {len(combs)} {int((i/len(combs))*100)}%" + + if complete_test(test_person['uuid']) == 1: + msg = '\n'.join([f" {'✅ ' if answer['answer'] == 1 else '❌'} {answer['name']}" for answer in names]) + sp.text = f"Answer: \n{msg}" + sp.ok("Found!") + break + + elif question["type"] in [3] : + print("A: MANUAL") + print() + +print("Test processing finished.")