Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 45 additions & 11 deletions monitorrent/plugins/trackers/nnmclub.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
standard_library.install_aliases()
from builtins import object
import sys
from requests import Session
import asyncio
import requests
import urllib.request, urllib.parse, urllib.error
from sqlalchemy import Column, Integer, String, ForeignKey
Expand Down Expand Up @@ -85,18 +85,52 @@ def parse_url(self, url):
return self._get_title(title)

def login(self, username, password):
s = Session()
data = {"username": username, "password": password, "autologin": "on", "login": "%C2%F5%EE%E4"}
login_result = s.post(self._login_url, data, **self.tracker_settings.get_requests_kwargs())
if login_result.url.startswith(self._login_url):
# TODO get error info (although it shouldn't contain anything useful
cookies = asyncio.run(self._login_with_browser(username, password))
if u'phpbb2mysql_4_sid' not in cookies:
raise NnmClubLoginFailedException(1, "Invalid login or password")
else:
sid = s.cookies[u'phpbb2mysql_4_sid']
data = s.cookies[u'phpbb2mysql_4_data']
parsed_data = loads(unquote(data).encode('utf-8'))
self.sid = cookies[u'phpbb2mysql_4_sid']
data_cookie = cookies.get(u'phpbb2mysql_4_data', '')
if data_cookie:
parsed_data = loads(unquote(data_cookie).encode('utf-8'))
self.user_id = parsed_data[u'userid'.encode('utf-8')].decode('utf-8')
self.sid = sid

async def _login_with_browser(self, username, password):
from playwright.async_api import async_playwright, TimeoutError as PlaywrightTimeoutError

async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
context = await browser.new_context()
page = await context.new_page()

await page.goto(self._login_url)
await page.fill('input[name="username"]', username)
await page.fill('input[name="password"]', password)

# Wait for Cloudflare Turnstile to auto-complete and inject its token
try:
await page.wait_for_function(
"() => { const el = document.querySelector('[name=\"cf-turnstile-response\"]'); "
"return el && el.value && el.value.length > 0; }",
timeout=30000
)
except PlaywrightTimeoutError:
pass # Proceed anyway; Turnstile may have completed silently

await page.click('input[name="login"]')

try:
await page.wait_for_url(
lambda url: not url.startswith(self._login_url),
timeout=15000
)
except PlaywrightTimeoutError:
await browser.close()
raise NnmClubLoginFailedException(2, "Login failed: CAPTCHA not solved or invalid credentials")

all_cookies = await context.cookies()
await browser.close()

return {c['name']: c['value'] for c in all_cookies}

def verify(self):
cookies = self.get_cookies()
Expand Down