mirror of
https://github.com/zedeus/nitter
synced 2026-09-05 14:49:32 +00:00
Add session validation tool
This commit is contained in:
parent
607765c463
commit
206622ea38
2 changed files with 137 additions and 1 deletions
|
|
@ -34,7 +34,7 @@ proc setApiProxy*(url: string) =
|
||||||
if "http" notin apiProxy:
|
if "http" notin apiProxy:
|
||||||
apiProxy = "http://" & apiProxy
|
apiProxy = "http://" & apiProxy
|
||||||
|
|
||||||
proc toUrl(req: ApiReq; sessionKind: SessionKind): Uri =
|
proc toUrl*(req: ApiReq; sessionKind: SessionKind): Uri =
|
||||||
let url = case sessionKind
|
let url = case sessionKind
|
||||||
of oauth: req.oauth
|
of oauth: req.oauth
|
||||||
of cookie: req.cookie
|
of cookie: req.cookie
|
||||||
|
|
|
||||||
136
tools/test_sessions.nim
Normal file
136
tools/test_sessions.nim
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
# Test each cookie session in a JSONL file by hitting the UserMedia endpoint.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# nim r --path:src tools/test_sessions.nim [sessions_file] [--delay N]
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# nim r --path:src tools/test_sessions.nim
|
||||||
|
# nim r --path:src tools/test_sessions.nim sessions_cookie.jsonl --delay 1
|
||||||
|
|
||||||
|
import asyncdispatch, httpclient, strutils, uri, os, zippy
|
||||||
|
import apiutils, auth, consts, types
|
||||||
|
import experimental/parser/session
|
||||||
|
|
||||||
|
const
|
||||||
|
# jack (id=12) — public account with media, same target as ratelimit_probe.py
|
||||||
|
testVars = userMediaVars % ["12", "", "20"]
|
||||||
|
|
||||||
|
# Build the ApiReq once — same for every session
|
||||||
|
let
|
||||||
|
testUrl = ApiUrl(endpoint: graphUserMedia,
|
||||||
|
params: @[("variables", testVars), ("features", gqlFeatures)])
|
||||||
|
testReq = ApiReq(cookie: testUrl, oauth: testUrl)
|
||||||
|
url = testReq.toUrl(SessionKind.cookie)
|
||||||
|
|
||||||
|
proc parseCookieSessions(path: string): seq[Session] =
|
||||||
|
var skipped = 0
|
||||||
|
for line in path.lines:
|
||||||
|
let s = line.strip()
|
||||||
|
if s.len == 0: continue
|
||||||
|
try:
|
||||||
|
let sess = parseSession(s)
|
||||||
|
if sess.kind == SessionKind.cookie:
|
||||||
|
result.add sess
|
||||||
|
else:
|
||||||
|
inc skipped
|
||||||
|
except Exception as e:
|
||||||
|
echo " [!] Parse error: ", e.msg
|
||||||
|
if skipped > 0:
|
||||||
|
echo " (skipped ", skipped, " non-cookie sessions)"
|
||||||
|
|
||||||
|
proc testSession(session: Session): Future[tuple[ok: bool, code: int,
|
||||||
|
remaining, limit: int, detail: string]] {.async.} =
|
||||||
|
let headers = await genHeaders(session, url, skipTid = false)
|
||||||
|
let client = newAsyncHttpClient(headers = headers)
|
||||||
|
defer: client.close()
|
||||||
|
|
||||||
|
try:
|
||||||
|
let resp = await client.get($url)
|
||||||
|
var body = await resp.body
|
||||||
|
if resp.headers.getOrDefault("content-encoding") == "gzip":
|
||||||
|
body = uncompress(body, dfGzip)
|
||||||
|
|
||||||
|
var remaining, limit: int
|
||||||
|
if resp.headers.hasKey("x-rate-limit-remaining"):
|
||||||
|
remaining = parseInt(resp.headers["x-rate-limit-remaining"])
|
||||||
|
if resp.headers.hasKey("x-rate-limit-limit"):
|
||||||
|
limit = parseInt(resp.headers["x-rate-limit-limit"])
|
||||||
|
|
||||||
|
if resp.code == Http200:
|
||||||
|
return (true, resp.code.int, remaining, limit, "")
|
||||||
|
else:
|
||||||
|
let detail = if body.len in 1..120: body else: ""
|
||||||
|
return (false, resp.code.int, remaining, limit, detail)
|
||||||
|
except Exception as e:
|
||||||
|
return (false, 0, 0, 0, e.msg[0 ..< min(e.msg.len, 120)])
|
||||||
|
|
||||||
|
proc main() {.async.} =
|
||||||
|
var
|
||||||
|
sessionsPath = "sessions.jsonl"
|
||||||
|
delay = 500 # ms
|
||||||
|
i = 1
|
||||||
|
|
||||||
|
while i <= paramCount():
|
||||||
|
let arg = paramStr(i)
|
||||||
|
case arg
|
||||||
|
of "--delay":
|
||||||
|
inc i
|
||||||
|
if i > paramCount():
|
||||||
|
echo "Error: --delay requires a value (seconds)"; quit(1)
|
||||||
|
delay = int(parseFloat(paramStr(i)) * 1000)
|
||||||
|
of "--help", "-h":
|
||||||
|
echo "Usage: nim r --path:src tools/test_sessions.nim [sessions_file] [--delay N]"
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
sessionsPath = arg
|
||||||
|
inc i
|
||||||
|
|
||||||
|
if not fileExists(sessionsPath):
|
||||||
|
echo "File not found: ", sessionsPath; quit(1)
|
||||||
|
|
||||||
|
setApiProxy("")
|
||||||
|
setDisableTid(false)
|
||||||
|
|
||||||
|
let sessions = parseCookieSessions(sessionsPath)
|
||||||
|
if sessions.len == 0:
|
||||||
|
echo "No cookie sessions found in ", sessionsPath; quit(0)
|
||||||
|
|
||||||
|
echo "Testing ", sessions.len, " sessions from ", sessionsPath
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
var
|
||||||
|
nValid, nFail: int
|
||||||
|
failures: seq[string]
|
||||||
|
|
||||||
|
for idx, session in sessions:
|
||||||
|
let
|
||||||
|
num = idx + 1
|
||||||
|
prefix = "[" & $num & "/" & $sessions.len & "] " & session.pretty
|
||||||
|
res = await testSession(session)
|
||||||
|
|
||||||
|
if res.ok:
|
||||||
|
inc nValid
|
||||||
|
var extra = ""
|
||||||
|
if res.limit > 0:
|
||||||
|
extra = " remaining=" & $res.remaining & "/" & $res.limit
|
||||||
|
echo prefix, " ✓ ", res.code, extra
|
||||||
|
else:
|
||||||
|
inc nFail
|
||||||
|
let detail = if res.code > 0: $res.code else: "error: " & res.detail
|
||||||
|
failures.add session.pretty & " " & detail
|
||||||
|
echo prefix, " ✗ ", detail
|
||||||
|
|
||||||
|
if num < sessions.len and delay > 0:
|
||||||
|
await sleepAsync(delay)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Done: ", nValid, " valid, ", nFail, " invalid [", sessions.len, " total]"
|
||||||
|
|
||||||
|
if failures.len > 0:
|
||||||
|
echo ""
|
||||||
|
echo "Failures:"
|
||||||
|
for f in failures:
|
||||||
|
echo " ", f
|
||||||
|
|
||||||
|
waitFor main()
|
||||||
Loading…
Reference in a new issue