#!/usr/bin/env python3.9 from dataclasses import dataclass import json from pathlib import Path import subprocess import typing from playwright.sync_api import Playwright, sync_playwright, Browser from typer import Option, Typer class Storage(typing.Protocol): def get(self, key: str) -> typing.Optional[typing.Any]: ... def set(self, key: str, value) -> None: ... @dataclass class FileStorage: path: Path def get(self, key: str): try: return json.loads(self.path.read_text()).get(key) except FileNotFoundError: return None def set(self, key: str, value) -> None: try: data = json.loads(self.path.read_text()) except FileNotFoundError: data = {} data[key] = value self.path.write_text(json.dumps(data)) class Emp: def __init__(self, browser: Browser, storage: Storage) -> None: self.browser = browser self.storage = storage def ensure_session(self, username: str, password: str) -> None: if self.storage.get("cookies") is None: self.login(username, password) def login(self, username: str, password: str) -> typing.Dict[str, str]: """ logins and returns session cookies """ context = self.browser.new_context() # Open new page page = context.new_page() # Go to https://www.empornium.is/ page.goto("https://www.empornium.is/login") page.locator('[placeholder="Username"]').fill(username) page.locator('[placeholder="Password"]').fill(password) # Click text=Stay logged in page.locator("text=Stay logged in").click() # Click input:has-text("login") page.locator('input:has-text("login")').click() cookies = {c["name"]: c["value"] for c in context.cookies()} self.storage.set("cookies", {"sid": cookies["sid"]}) return { "sid": cookies["sid"], } def prepare_post( self, torrent_path: Path, title: str, tags: str, description: str, cover_image_url: str, category: typing.Optional[str] = None, ) -> None: cookies = self.storage.get("cookies") assert cookies, "You must login first" context = self.browser.new_context() context.add_cookies( [{"name": k, "value": v, "domain": "www.empornium.is", "path": "/"} for k, v in cookies.items()] ) page = context.new_page() page.goto("https://www.empornium.is/upload.php") if torrent_path.is_file(): page.locator('input[name="file_input"]').set_input_files(torrent_path.expanduser().resolve()) page.locator('text="check for dupes"').click() # Select category if category: page.locator('select[name="category"]').select_option(label=category) page.locator('input[name="title"]').fill(title) page.locator('textarea[name="taglist"]').fill(tags) page.locator('input[name="image"]').fill(cover_image_url) page.locator('textarea[name="desc"]').fill(description) # Click text=Preview page.locator("text=Preview").click() def submit_post(): storage = FileStorage(Path("emp.json")) with sync_playwright() as playwright: browser = playwright.chromium.launch(headless=False) emp = Emp(browser=browser, storage=storage) emp.ensure_session(username="zzzp", password="9arjs9za2o") emp.prepare_post( torrent_path=Path("~/Downloads/v.torrent"), title="A Title", tags="tag.1 tag.2", description="Some description", cover_image_url="https://images.com/image.jpg", category="Anal", ) input("Press Enter to continue...") browser.close() cli = Typer(name="emp") torrent_cli = Typer(name="torrent") cli.add_typer(torrent_cli) @torrent_cli.callback("torrent") def make_torrent(paths: typing.List[Path], announce_url: str = Option(..., envvar="ANNOUNCE_URL")): if len(paths) == 1 and paths[0].is_dir(): dir_path = paths[0] dir_path = dir_path.expanduser().resolve() proc = subprocess.run( [ "torrentify", f"-announce={announce_url}", f"-comment=created by zzzp", f"-created-by=zzzp", f"-name={dir_path.name}", str(dir_path), ], check=True, capture_output=True, ) torrent_path = dir_path / f"{dir_path.name}.torrent" torrent_path.write_bytes(proc.stdout) @torrent_cli.command() def clone(): pass if __name__ == "__main__": cli()