# -*- coding: utf-8 -*- # VERSION: 2.1 # AUTHORS: nishizhen (Original author: Yun ) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import re import ssl try: import urllib.request HAS_URLLIB = True except ImportError: HAS_URLLIB = False try: from HTMLParser import HTMLParser except ModuleNotFoundError: from html.parser import HTMLParser # import qBT modules try: from novaprinter import prettyPrinter from helpers import retrieve_url as _retrieve_url except ModuleNotFoundError: pass USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' def acgrip_retrieve_url(url): """Retrieve URL content with proper headers and SSL settings.""" if HAS_URLLIB: # Try multiple SSL approaches for maximum compatibility ssl_attempts = [] # Approach 1: Standard with cert verification disabled try: ctx1 = ssl.create_default_context() ctx1.check_hostname = False ctx1.verify_mode = ssl.CERT_NONE ssl_attempts.append(ctx1) except Exception: pass # Approach 2: TLSv1.2 only (most compatible) try: ctx2 = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) ctx2.check_hostname = False ctx2.verify_mode = ssl.CERT_NONE ctx2.minimum_version = ssl.TLSVersion.TLSv1_2 ctx2.maximum_version = ssl.TLSVersion.TLSv1_3 ssl_attempts.append(ctx2) except Exception: pass for ctx in ssl_attempts: try: req = urllib.request.Request( url, headers={ 'User-Agent': USER_AGENT, 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', 'Connection': 'keep-alive', } ) with urllib.request.urlopen(req, context=ctx, timeout=30) as response: return response.read().decode('utf-8') except Exception: continue # Fallback to qBittorrent's retrieve_url if available try: return _retrieve_url(url) except Exception: pass raise ConnectionError(f"Failed to retrieve URL: {url}") class acgrip(object): """Class used by qBittorrent to search for torrents.""" url = 'https://acg.rip' name = 'acg.rip' ########################################################################### # defines which search categories are supported by this search engine # and their corresponding id. Possible categories are: # 'all', 'movies', 'tv', 'music', 'games', 'anime', 'software', 'pictures', # 'books' supported_categories = {'all': '0_0'} class acgripParser(HTMLParser): """Parses acg.rip search page for results.""" def __init__(self, res, url): """Construct a acgrip html parser. Parameters: :param list res: a list to store the results in :param str url: the base url of the search engine """ try: super().__init__() except TypeError: HTMLParser.__init__(self) self.engine_url = url self.results = res # State tracking self.in_table = False self.in_row = False self.current_row = None # Dict to hold current row data self.cell_index = -1 # Current cell index (0=pub, 1=title, 2=dl, 3=size) self.row_pub_date = None # Unix timestamp from