# VERSION: 1.0
# AUTHOR: github.com/444995

import os
import json
import gzip
import urllib.parse
import urllib.request
import tempfile
import http.cookiejar as cookielib
from urllib.error import HTTPError
from novaprinter import prettyPrinter
from math import ceil

# User settings
USERNAME = "REPLACE_ME"
PASSWORD = "REPLACE_ME"
CACHE_LOGIN_COOKIES = True
COOKIES_FILE_NAME = "torrentleech.cookies"

class torrentleech(object):
    url = 'https://www.torrentleech.org'
    name = 'TorrentLeech'
    supported_categories = {
        'all': '0', 
        'anime': '34',
        'movies': '8,9,11,37,43,14,12,13,47,15,29', 
        'tv': '26,32,27', 
        'music': '31,16',
        'games': '17,42,18,19,40,20,21,39,49,22,28,30,48', 
        'software': '23,24,25,33', 
        'books': '45,46',
    }
    cookies_file_path = os.path.join(
        os.path.dirname(os.path.realpath(__file__)), 
        COOKIES_FILE_NAME
    )

    def __init__(self):
        self.login_url = f"{self.url}/user/account/login/"
        self.torrents_per_page = 50
        self.cookiejar = cookielib.LWPCookieJar()
        self.opener = self._create_opener()
        self._login()

    def _create_opener(self):
        opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.cookiejar))
        opener.addheaders = [
            ('User-Agent', 'Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0'),
            ('Accept-Encoding', 'gzip, deflate'),
        ]
        return opener

    def _make_request(self, url, data=None):
        try:
            encoded_data = urllib.parse.urlencode(data).encode() if data else None
            with self.opener.open(url, encoded_data) as response:
                if response.info().get('Content-Encoding') == 'gzip':
                    return gzip.decompress(response.read())
                return response.read()
        except HTTPError as e:
            raise Exception(f"Request failed: {e}")

    def _login(self):
        if CACHE_LOGIN_COOKIES and os.path.exists(self.cookies_file_path):
            self.cookiejar.load(self.cookies_file_path, ignore_discard=True, ignore_expires=True)
            if self._is_logged_in():
                return

        data = {"username": USERNAME, 
                "password": PASSWORD}
        self._make_request(self.login_url, data)

        if not self._is_logged_in():
            raise ValueError("Failed to login: Invalid credentials")

        if CACHE_LOGIN_COOKIES:
            self.cookiejar.save(self.cookies_file_path, ignore_discard=True, ignore_expires=True)

    def _is_logged_in(self):
        return any(cookie.name == 'tlpass' for cookie in self.cookiejar)

    def download_torrent(self, info):
        torrent_file = self._make_request(info)
        with tempfile.NamedTemporaryFile(suffix='.torrent', delete=False) as file:
            file.write(torrent_file)
        print(f"{file.name} {info}")


    def search(self, what, cat='all'):
        category_str = self.supported_categories[cat]
        search_url = self._establish_search_url(what, category_str)
        
        total_pages = self._get_total_pages(search_url)
        for page in range(1, total_pages + 1):
            self._search_page(f"{search_url}/page/{page}")

    def _establish_search_url(self, what, category_str):
        base_url = f"{self.url}/torrents/browse/list"
        return f"{base_url}/categories/{category_str}/query/{what}" if category_str != '0' else f"{base_url}/query/{what}"

    def _get_total_pages(self, search_url):
        response = self._make_request(f"{search_url}/page/1")
        num_torrents = json.loads(response).get("numFound", 0)
        return ceil(num_torrents / self.torrents_per_page)

    def _search_page(self, url):
        response = self._make_request(url)
        torrents = json.loads(response).get("torrentList", [])
        for torrent in torrents:
            self._print_torrent(torrent)

    def _print_torrent(self, torrent):
        prettyPrinter({
            'link': f"{self.url}/download/{torrent['fid']}/{torrent['filename']}",
            'name': torrent['name'],
            'size': f"{torrent['size']} B",
            'seeds': torrent['seeders'],
            'leech': torrent['leechers'],
            'engine_url': self.url,
            'desc_link': f"{self.url}/torrent/{torrent['fid']}"
        })

if __name__ == "__main__":
    engine = torrentleech()
    engine.search("ubuntu")