import asyncio import json import logging import netrc import re import threading import time from json.decoder import JSONDecodeError from queue import Queue from typing import Callable from urllib.request import urlopen from uuid import UUID import requests import search_bot from flask import Flask, jsonify, request from habanero import Crossref from waitress import serve NETRC_FILE = r"C:\Users\Activcom.pl\.netrc" HOST_ADDRESS = "192.168.1.192" PORT_ADDRESS = 5001 MAIN_BOT_ADDRESS = "http://192.168.1.191:5000" SEND_RESULTS = "/conjurer" BDSM_UUID_TEST = "96b7f85a-1142-4908-8986-62a2ea25a147" ENCODING = "utf-8" app = Flask(__name__) librarian_queue = Queue() librarian_list = [] class Librarian(object): def __init__(self, app, query, uuid) -> None: netrc_mod = netrc.netrc(NETRC_FILE) authTokens = netrc_mod.authenticators("crossref") self.cr = Crossref(mailto=authTokens[0]) self.query = query self.uuid = str(uuid) self.limit = 3000 self.fetched = 0 self.hit = 0 self.total = 0 self.app = app self.logger = app.logger self.live_results = [] self.search_result_from_cr = {} self.done = False async def search_crossref(self, query): self.app.logger.info("STARTED SEARCH") result = self.cr.works(query=query, limit=1000) self.search_result_from_cr.update(result) self.total = result["message"]["total-results"] self.fetched += len(result["message"]["items"]) self.logger.info(self.total) self.logger.info(self.fetched) while self.total > self.fetched and self.limit > self.fetched: result = self.cr.works(query=query, limit=1000) self.search_result_from_cr.update(result) self.total = result["message"]["total-results"] self.fetched += len(result["message"]["items"]) self.logger.info(self.total) self.logger.info(self.fetched) time.sleep(1) self.app.logger.info("CROSSREF DONE") # TODO: add to sql with UUID # sql row - title, doi, author, uuid, last retrieved, is_available with open("rr_results.json", "r+", encoding="utf-8") as data_file: # First we load existing data into a dict. try: file_data = json.load(data_file) except JSONDecodeError: file_data = {} summarized_results = [] self.app.logger.info("REFINE: Removing all derived works from the list") for item in self.search_result_from_cr["message"]["items"]: container = "NO" if "container-title" in item: container = "YES" else: summarized_results.append( { "DOI": item["DOI"], "title": item["title"] if "title" in item else None, "type": item["type"] if "type" in item else None, "container": container, } ) result = { self.uuid: { "total_results": self.search_result_from_cr["message"][ "total-results" ], "on_page": 1, "summary": summarized_results, "results": self.search_result_from_cr["message"]["items"], } } if file_data: file_data.update(result) else: file_data = result self.app.logger.info("REFINE: Dumping to file") data_file.truncate(0) data_file.seek(0) json.dump(file_data, data_file, indent=4) return result async def check_dois_in_local_db(self, doi): self.app.logger.info("REFINE: Running search in the backend app") coro = asyncio.to_thread( search_bot.search_for_doi, doi, self.live_results, self.app.logger ) result = await coro return result async def check_if_exists_brute_force(self, page_url): self.app.logger.error("REFINE: Brute force search!") if not page_url.startswith(("http:", "https:")): raise ValueError("URL must start with 'http:' or 'https:'") # trunk-ignore(bandit/B310) with urlopen(page_url) as response: data = response.read() text = data.decode("utf-8") for line in text.splitlines(): if re.match( r".*Unfortunately, Sci-Hub doesn't have the requested document.*", line, ): return False if m := re.match( r".*