From d4999b9c485d7b0e4c3d7e5b2d43a9d57b2c6056 Mon Sep 17 00:00:00 2001 From: bipinkrish Date: Sun, 26 Feb 2023 19:30:51 +0530 Subject: [PATCH] Abilty to get book from just IA url --- DeGourou.py | 110 ++++++++++++++++++++++++++-------- requirements.txt | 1 + setup/ia.py | 135 ++++++++++++++++++++++++++++++++++++++++++ setup/loginAccount.py | 36 ++++------- 4 files changed, 231 insertions(+), 51 deletions(-) create mode 100644 setup/ia.py diff --git a/DeGourou.py b/DeGourou.py index ced4b09..242d7db 100644 --- a/DeGourou.py +++ b/DeGourou.py @@ -7,34 +7,43 @@ from decrypt.decodeEPUB import decryptEPUB import argparse from os import mkdir, remove, rename from os.path import exists -from sys import exit from setup.params import FILE_DEVICEKEY, FILE_DEVICEXML, FILE_ACTIVATIONXML from decrypt.params import KEYPATH from setup.data import createDefaultFiles +from setup.ia import SESSION_FILE, manage_login, get_book, return_book -def main(acsmFile, login, outputFilename): - - # user login - if login: - if not exists("account"): - mkdir("account") - loginAndGetKey() - exit(0) + +def loginADE(email, password): + if email is None or password is None: + print("Email or Password cannot be empty") + print() + return + if not exists('account'): mkdir('account') + loginAndGetKey(email, password) + print() + +def loginIA(email,password): + if email is None or password is None: + print("Email or Password cannot be empty") + print() + return + manage_login(email,password) + print() + +def main(acsmFile, outputFilename): + if not exists('account'): mkdir('account') # setting up the account and keys if not (exists(FILE_ACTIVATIONXML) and exists(FILE_DEVICEXML) and exists(FILE_DEVICEKEY) and exists(KEYPATH)): - if not exists("account"): - mkdir("account") createDefaultFiles() - print() # cheek for file existance if not exists(acsmFile): print(f"{acsmFile} file does not exist") print() - exit(1) + return # download encryptedFile = downloadFile(acsmFile) @@ -49,7 +58,7 @@ def main(acsmFile, login, outputFilename): else: print("File format not supported") print() - exit(1) + return remove(encryptedFile) if outputFilename is None: @@ -60,20 +69,69 @@ def main(acsmFile, login, outputFilename): print(tempName) print() +def handle_IA(url,format): + if not exists(SESSION_FILE): + print("Login to InternetArchive first or give ACSm file as input") + return + acsmFile = get_book(url,format) + if acsmFile is None: + print("Could not get Book, try using ACSm file as input") + return + main(acsmFile,None) + remove(acsmFile) + if(return_book(url) is None): + print("Please return it yourself") + if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Download and Decrypt an encrypted PDF or EPUB file. It uses Dummy account for ADE, you can overide using --login") - parser.add_argument("file", type=str, nargs='?', default=None, help="Path to the ACSM file") - parser.add_argument("-l", "--login", action="store_true", help="Login to your ADE account. (optional)") - parser.add_argument("-o", "--output", type=str, default=None, help="Output file name. (optional)") + parser = argparse.ArgumentParser(description="Download and Decrypt an encrypted PDF or EPUB file.") + parser.add_argument("-f", type=str, nargs='?', default=None, help="path to the ACSM file") + parser.add_argument("-u", type=str, nargs='?', default=None, help="book url from InternetArchive") + parser.add_argument("-t", type=str, nargs='?', default='pdf', help="book file type/format/extension for book url (defaults to PDF)") + parser.add_argument("-o", type=str, nargs='?', default=None, help="output file name") + parser.add_argument("-la", action="store_true", help="login to your ADE account.") + parser.add_argument("-li", action="store_true", help="login to your InternetArchive.") + parser.add_argument("-e", type=str, nargs='?', default=None, help="email/username") + parser.add_argument("-p", type=str, nargs='?', default=None, help="password") + parser.add_argument("-lo", action="store_true", help="logout from all") args = parser.parse_args() - # check for default value - if args.file == None: - if exists("URLLink.acsm"): - args.file = "URLLink.acsm" - else: - parser.print_help() - exit(0) + # Logout + if args.lo: + from shutil import rmtree + rmtree("account") + mkdir('account') + print() + print("Logout Sucessfull") + print() - main(args.file, args.login, args.output) + # ADE login + elif args.la: + print() + print("chose login for ADE") + loginADE(args.e, args.p) + + # IA login + elif args.li: + print() + print("chose login for InternetArchive") + loginIA(args.e, args.p) + + # Book url + elif args.u: + print() + if not args.t in ['pdf','epub']: + print("only PDF and EPUB are supported") + else: + handle_IA(args.u, args.t) + print() + + # check for default value + elif args.f == None: + if exists("URLLink.acsm"): + args.f = "URLLink.acsm" + main(args.f, args.output) + else: parser.print_help() + + else: + main(args.f, args.output) diff --git a/requirements.txt b/requirements.txt index 32a10f2..58cb74e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ pycryptodomex==3.17 oscrypto==1.3.0 lxml==4.9.2 +requests \ No newline at end of file diff --git a/setup/ia.py b/setup/ia.py new file mode 100644 index 0000000..e6dc729 --- /dev/null +++ b/setup/ia.py @@ -0,0 +1,135 @@ +from os import path, mkdir +import requests +import random +import string +import pickle + + +SESSION_FILE = 'account/session.pkl' +session = None +if path.exists(SESSION_FILE): + with open(SESSION_FILE, 'rb') as f: session = pickle.load(f) + + +# print error +def display_error(response, message): + print(message) + print(response) + print(response.text) + + +# login and format +def format_data(content_type, fields): + data = "" + for name, value in fields.items(): + data += f"--{content_type}\x0d\x0aContent-Disposition: form-data; name=\"{name}\"\x0d\x0a\x0d\x0a{value}\x0d\x0a" + data += content_type+"--" + return data + +def login(email, password): + session = requests.Session() + session.get("https://archive.org/account/login") + content_type = "----WebKitFormBoundary"+"".join(random.sample(string.ascii_letters + string.digits, 16)) + + headers = {'Content-Type': 'multipart/form-data; boundary='+content_type} + data = format_data(content_type, {"username":email, "password":password, "submit_by_js":"true"}) + + response = session.post("https://archive.org/account/login", data=data, headers=headers) + if "bad_login" in response.text: + print("[-] Invalid credentials!") + return None + elif "Successful login" in response.text: + print("[+] Successful login") + return session + else: + display_error(response, "[-] Error while login:") + return None + + +# get book +def loan(book_id): + global session + if not session: + with open(SESSION_FILE, 'rb') as f: session = pickle.load(f) + data = { + "action": "grant_access", + "identifier": book_id + } + response = session.post("https://archive.org/services/loans/loan/searchInside.php", data=data) + data['action'] = "browse_book" + response = session.post("https://archive.org/services/loans/loan/", data=data) + + if response.status_code == 400 : + if response.json()["error"] == "This book is not available to borrow at this time. Please try again later.": + print("This book doesn't need to be borrowed") + return session + else : + display_error(response, "Something went wrong when trying to borrow the book.") + return None + + data['action'] = "create_token" + response = session.post("https://archive.org/services/loans/loan/", data=data) + + if "token" in response.text: + print("[+] Successful loan") + return session + else: + display_error(response, "Something went wrong when trying to borrow the book, maybe you can't borrow this book.") + return None + +# acsm file +def get_acsmfile(bookid,format="pdf"): + global session + if not session: + with open(SESSION_FILE, 'rb') as f: session = pickle.load(f) + + response = session.get(f"https://archive.org/services/loans/loan/?action=media_url&format={format}&redirect=1&identifier={bookid}") + + if response.status_code == 200: + with open(f"{bookid}.acsm","w") as af: af.write(response.text) + return f"{bookid}.acsm" + else: + display_error(response, "Something went wrong when trying to get ACSM") + return None + + +# return the book +def return_loan(book_id): + global session + if not session: + with open(SESSION_FILE, 'rb') as f: session = pickle.load(f) + data = { + "action": "return_loan", + "identifier": book_id + } + response = session.post("https://archive.org/services/loans/loan/", data=data) + if response.status_code == 200 and response.json()["success"]: + print("[+] Book returned") + return True + else: + display_error(response, "Something went wrong when trying to return the book") + return None + + +# manage +def manage_login(email,password): + global session + if not path.exists('account'): mkdir('account') + sess = login(email,password) + if sess is not None: + with open(SESSION_FILE, 'wb') as f: pickle.dump(sess, f) + session = sess + +def get_book(url,format): + global session + bookid = url.split("/")[4] + sess = loan(bookid) + if sess is not None: + with open(SESSION_FILE, 'wb') as f: pickle.dump(sess, f) + session = sess + return get_acsmfile(bookid,format) + return None + +def return_book(url): + bookid = url.split("/")[4] + return return_loan(bookid) diff --git a/setup/loginAccount.py b/setup/loginAccount.py index b07dcb5..d1715c5 100644 --- a/setup/loginAccount.py +++ b/setup/loginAccount.py @@ -16,21 +16,7 @@ from decrypt.params import KEYPATH ################################################################# -def takeInput(): - - global VAR_MAIL - global VAR_PASS - - VAR_MAIL = input("Enter Mail: ") - VAR_PASS = input("Enter Password: ") - - if VAR_MAIL == "" or VAR_MAIL == "": - print("It cannot be empty") - print() - exit(1) - - -def loginAndGetKey(): +def loginAndGetKey(email, password): global VAR_MAIL global VAR_PASS @@ -40,31 +26,32 @@ def loginAndGetKey(): # acc files if True: - takeInput() + VAR_MAIL = email + VAR_PASS = password + print("Logging in") - createDeviceKeyFile() success = createDeviceFile(True, VAR_VER) if (success is False): print("Error, couldn't create device file.") - exit(1) + return success, resp = createUser(VAR_VER, None) if (success is False): print("Error, couldn't create user: %s" % resp) - exit(1) + return success, resp = signIn("AdobeID", VAR_MAIL, VAR_PASS) if (success is False): print("Login unsuccessful: " + resp) - exit(1) + return success, resp = activateDevice(VAR_VER, None) if (success is False): print("Couldn't activate device: " + resp) - exit(1) + return print("Authorized to account " + VAR_MAIL) @@ -79,16 +66,15 @@ def loginAndGetKey(): success = exportAccountEncryptionKeyDER(filename) if (success is False): print("Couldn't export key.") - exit(1) + return print("Successfully exported key for account " + VAR_MAIL + " to file " + filename) else: print("failed") - exit(1) - + except Exception as e: print(e) - exit(1) + print('All Set') print() \ No newline at end of file