
    FDj<                     @   S r SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSK	J
r
Jr  Sr\" \R                  5      S:  a  \" \R                  S   5      OSr\R"                  R%                  S\R"                  R'                  S5      5        SqS	qS
rS
rSqSqS
qSS jrSS jrS rS rS rSr  " S S\5      r!\"S:X  aD  \
" \\4\!5      r#\$" S5        \$" S\ 35        \$" S\ S35        \$" S5         \#RK                  5         gg! \& a    \#RO                  5          gf = f)zQuick web search UI for Ultimate Non-Debrid scrapers.
Usage: python3 search_web.py [port]
Then open http://localhost:8800 in a browser.    N)
HTTPServerBaseHTTPRequestHandlerz0.0.0.0   i`"  z4~/addon-audit/build/ultimate-nondebrid/resources/libz	127.0.0.1i   zhttp://192.168.1.509117c                    [         (       d  g [        R                  R                  U 5      nUS:X  a.  U(       a'  U(       a   [         S[
         S[          SU SU SU 3nO[         S[
         S[          SU 3n [        R                  R                  USS	9nUR                  5       R                  5       n[        U5      $ !    g = f)
Nepisode:z2/api/v2.0/indexers/all/results/torznab/api?apikey=z&t=tvsearch&q=&season=z&ep=z&t=movie&q=   timeout)JACKETT_APIurllibparsequoteJACKETT_HOSTJACKETT_PORTrequesturlopenreaddecodeparse_torznab)query
media_typeseasonr	   qurlrespxmls           '/home/rurouni/addon-audit/search_web.pysearch_jackettr"      s    ;t5!AY6ga~-_`k_llz{|z}  ~F  GM  FN  NR  SZ  R[  \a~-_`k_llwxywz{~~%%c2%6iik  "S!!4s   :AC Cc                 P   Sn[         R                  R                  U 5      n US:X  a  U(       a  U(       a  U SU SU SU 3nOU SU 3n  [         R                  R	                  USS9n[        UR                  5       R                  5       5      $ !   U SU 3n NQ= f!    g = f)	Nz$https://zilean.elfhosted.com/torznabr	   z/tv?q=r   z	&episode=z	/movie?q=
   r   )r   r   r   r   r   r   r   r   )r   r   r   r	   hostr   r   r   s           r!   search_dmm_torznabr&   &   s    1D5!A$"v'F&8F89WIFCF)A3'C~~%%c2%6TYY[//122	$is# 4s   !B B AB! 	B!B%c           	         / nSS K Js  Jn  SS0n UR                  U 5      nUR	                  S5       GH:  nSnUR	                  SU5       H,  nUR                  S5      S:X  d  M  UR                  S	S5      nM.     U(       dO  UR                  S
S5      n[        R                  " SU5      n	U	(       a  U	R                  S5      R                  5       nU(       d  M  UR                  SS5      n
UR                  SU5      nUb$  [        [        UR                  S	S5      5      5      OSnUR                  SU5      nUb  [        UR                  S	S5      5      OSnUR                  XXS.5        GM=     U$ !    U$ = f)Nr   tz$http://torznab.com/schemas/2015/feedz.//itemr   z	.//t:attrnameinfohashvalueguidzbtih:([a-fA-F0-9]{40})r   titleUnknownz.//t:attr[@name="size"]z.//t:attr[@name="seeders"])r-   hashsizeseeders)xml.etree.ElementTreeetreeElementTree
fromstringfindallgetfindtextresearchgrouplowerfindintfloatappend)xml_textresultsETNSrootitemihattrr,   mr-   size_elr0   seeds_elseedss                  r!   r   r   5   sR   G&&
5	6B}}X&LL+DB["588F#z1'2.B 6 }}VR0II7>1771:++-bxMM'95Eii 92>G:A:M3uW[[!456STDyy!=rBH5=5ICWa01qENNUWX ," N DNs   AE4 %DE4 4E9c                    ^ U R                  5       m[        U4S jS 5       5      (       a  gST;   a  gST;   a  g[        U4S jS	 5       5      (       a  g
g
)Nc              3   ,   >#    U  H	  oT;   v   M     g 7fN .0xns     r!   	<genexpr>!detect_quality.<locals>.<genexpr>P   s     
10a60   )21604kuhdu   🎬4K1080u	   📺1080p720u   📺720pc              3   ,   >#    U  H	  oT;   v   M     g 7frO   rP   rQ   s     r!   rU   rV   S   s     
98a68rW   )camzts.ztc.teleu   📀SD)r<   any)r)   rT   s    @r!   detect_qualityra   N   sK    

A

10
111({;z*

98
999(    c                 J    U (       d  gU S-  nUS:  a  US S3$ U S-  nUS S3$ )	N?i   @r   z.2fz GBi   z.0fz MBrP   )bytesgbmbs      r!   fmt_sizerh   V   s<    		B	Qw"S~%	BXS>rb   aI  <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Ultimate Search</title>
<style>
*{{box-sizing:border-box;margin:0;padding:0}}
body{{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:#0d1117;color:#e6edf3;max-width:960px;margin:0 auto;padding:20px}}
h1{{font-size:1.5rem;margin-bottom:20px;color:#58a6ff}}
.search-box{{display:flex;gap:8px;margin-bottom:20px}}
.search-box input[type=text]{{flex:1;padding:12px 16px;border:1px solid #30363d;border-radius:6px;background:#161b22;color:#e6edf3;font-size:1rem}}
.search-box input[type=text]:focus{{outline:none;border-color:#58a6ff}}
.search-box button{{padding:12px 24px;background:#238636;border:none;border-radius:6px;color:#fff;font-size:1rem;cursor:pointer}}
.search-box button:hover{{background:#2ea043}}
.filters{{display:flex;gap:16px;margin-bottom:20px;font-size:0.9rem;color:#8b949e}}
.filters label{{display:flex;align-items:center;gap:4px;cursor:pointer}}
table{{width:100%;border-collapse:collapse}}
th{{text-align:left;padding:8px 12px;border-bottom:2px solid #30363d;color:#8b949e;font-size:0.8rem;text-transform:uppercase;letter-spacing:0.05em}}
td{{padding:8px 12px;border-bottom:1px solid #21262d;font-size:0.9rem}}
tr:hover td{{background:#161b22}}
.hash{{font-family:'SF Mono','Fira Code',monospace;font-size:0.75rem;color:#8b949e}}
.size{{text-align:right;white-space:nowrap;color:#8b949e}}
.seeds{{text-align:right;white-space:nowrap;color:#8b949e}}
.quality{{white-space:nowrap}}
.action a{{color:#58a6ff;text-decoration:none;font-size:0.85rem}}
.action a:hover{{text-decoration:underline;color:#79c0ff}}
.title-cell{{max-width:400px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}}
.status{{padding:20px;text-align:center;color:#8b949e}}
.error{{color:#f85149}}
a{{color:#58a6ff}}
.footer{{margin-top:30px;padding-top:20px;border-top:1px solid #21262d;font-size:0.8rem;color:#8b949e}}
</style>
</head>
<body>
<h1>&#128270; Ultimate Search</h1>
<form class="search-box" method="get" action="/">
  <input type="text" name="q" placeholder="Movie or TV show title..." value="%s" autofocus>
  <button type="submit">Search</button>
</form>
<div class="filters">
  <label><input type="radio" name="type" value="movie" %s> Movie</label>
  <label><input type="radio" name="type" value="tv" %s> TV</label>
  <label><input type="checkbox" name="jackett" value="1" %s> Use Jackett</label>
  <span style="margin-left:auto">
    <button type="submit" style="background:none;border:none;color:#58a6ff;cursor:pointer;text-decoration:underline">Search</button>
  </span>
</div>
%s
<div class="footer">
TorrServer: %s
<a href="https://github.com/yourok/torrserver" target="_blank">TorrServer</a> &middot;
<a href="https://github.com/Jackett/Jackett" target="_blank">Jackett</a>
</div>
</body>
</html>c                   >    \ rS rSrS rS rS rS rS rS r	S r
S	rg
)Handler   c                 .   [         R                  R                  U R                  5      n[         R                  R	                  UR
                  5      nUR                  nUS:X  a  U R                  5       $ US:X  a  U R                  U5      $ UR                  SS/5      S   nUR                  SS/5      S   nUR                  SS/5      S   S	:H  nS
nU(       a  U R                  XEU5      nU R                  5       nU(       a  SOSn	US:X  a  SOSn
US:X  a  SOSnU(       a  SOSnU R                  XEXgU5      nU R                  S5        U R                  SS5        U R                  5         U R                  R!                  UR"                  " 5       5        g )Nz	/settingsz/save_settingsr   r   r   typemoviejackett1z4<div class="status">Enter a search query above</div>0   <span style="color:#3fb950">●</span> Connected2   <span style="color:#f85149">●</span> Not runningcheckedtv   Content-Typetext/html; charset=utf-8)r   r   urlparsepathparse_qsr   serve_settingssave_settingsr7   	do_searchcheck_torrserverrender_pagesend_responsesend_headerend_headerswfilewriteencode)selfparsedparamsry   r   r   use_jackettresults_htmlts_alive	ts_statusmcheckedtcheckedjcheckedhtmls                 r!   do_GETHandler.do_GET   sk   &&tyy1&&v||4{{;&&((##%%f-- 

3%a(ZZ	215
jjRD1!4;M>>%[IL ((*JRF  YM	 *g 592 *d 29 +9;hW3)CD

'rb   c                     [         R                  " U5      nUS:X  a  SOSnUS:X  a  SOSnU(       a  SOSn	U(       a  SOSn
SU SU S	U S
U	 SU SU
 S3$ )Nrn   rs   r   rt   rq   rr   aP  <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Ultimate Search</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:#0d1117;color:#e6edf3;max-width:960px;margin:0 auto;padding:20px}
h1{font-size:1.5rem;margin-bottom:20px;color:#58a6ff}
.search-box{display:flex;gap:8px;margin-bottom:20px}
.search-box input[type=text]{flex:1;padding:12px 16px;border:1px solid #30363d;border-radius:6px;background:#161b22;color:#e6edf3;font-size:1rem}
.search-box input[type=text]:focus{outline:none;border-color:#58a6ff}
.search-box button{padding:12px 24px;background:#238636;border:none;border-radius:6px;color:#fff;font-size:1rem;cursor:pointer}
.search-box button:hover{background:#2ea043}
.filters{display:flex;gap:16px;margin-bottom:20px;font-size:0.9rem;color:#8b949e}
.filters label{display:flex;align-items:center;gap:4px;cursor:pointer}
table{width:100%;border-collapse:collapse}
th{text-align:left;padding:8px 12px;border-bottom:2px solid #30363d;color:#8b949e;font-size:0.8rem;text-transform:uppercase;letter-spacing:0.05em}
td{padding:8px 12px;border-bottom:1px solid #21262d;font-size:0.9rem}
tr:hover td{background:#161b22}
.hash{font-family:'SF Mono','Fira Code',monospace;font-size:0.75rem;color:#8b949e}
.size{text-align:right;white-space:nowrap;color:#8b949e}
.seeds{text-align:right;white-space:nowrap;color:#8b949e}
.quality{white-space:nowrap}
.action a{color:#58a6ff;text-decoration:none;font-size:0.85rem}
.action a:hover{text-decoration:underline;color:#79c0ff}
.title-cell{max-width:400px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.status{padding:20px;text-align:center;color:#8b949e}
.error{color:#f85149}
a{color:#58a6ff}
.footer{margin-top:30px;padding-top:20px;border-top:1px solid #21262d;font-size:0.8rem;color:#8b949e}
</style>
</head>
<body>
<h1>&#128270; Ultimate Search</h1>
<form class="search-box" method="get" action="/">
  <input type="text" name="q" placeholder="Movie or TV show title..." value="z" autofocus>
  <button type="submit">Search</button>
</form>
<div class="filters">
  <label><input type="radio" name="type" value="movie" zD> Movie</label>
  <label><input type="radio" name="type" value="tv" zF> TV</label>
  <label><input type="checkbox" name="jackett" value="1" z> Use Jackett</label>
  <span style="margin-left:auto">
    <a href="/settings">Settings</a>
    &middot;
    <a href="/" onclick="document.querySelector('.search-box input').value='';return true">Clear</a>
  </span>
</div>
z"
<div class="footer">
TorrServer: z
<a href="https://github.com/yourok/torrserver" target="_blank">TorrServer</a> &middot;
<a href="https://github.com/Jackett/Jackett" target="_blank">Jackett</a>
</div>
</body>
</html>)r   escape)r   r   r   r   r   r   r   m_ckt_ckj_ckts_ss              r!   r   Handler.render_page   s    KK&'1yr&$.yB'yREMA  TH%NJ OPS Q8 9=v >559F ;::> @  F i9 9	rb   c                 $   / nU(       a#  [        X5      nU(       a  UR                  U5        U(       d#  [        X5      nU(       a  UR                  U5        U(       d  g/ nUS S  GH  n[        R                  " UR                  SS5      5      nUR                  SS5      n[        U5      n	[        UR                  SS5      5      n
UR                  S	S5      nS
U S[        R                  R                  U5       3nU R                  5       (       a  S[         S[         SU S3OSnSU S3nU(       a	  USU S3-  nUR                  SU SU SU	 SU
 SU SUS S  SU S35        GM     SSR                  U5       S[!        U5       S3nU$ ) NzT<div class="status">No results found. Try a different query or enable Jackett.</div>d   r-   r.   r/   r   r0   r   r1   zmagnet:?xt=urn:btih:z&dn=http://r
   z/play?hash=z
&file_id=0z	<a href="z">Magnet</a>z &middot; <a href="z" target="_blank">Stream</a>z#<tr>
<td class="title-cell" title="z">z</td>
<td class="quality">z</td>
<td class="size">z</td>
<td class="seeds">z</td>
<td class="hash">   z...</td>
<td class="action">z</td>
</tr>z<table>
<thead><tr>
<th>Title</th>
<th>Quality</th>
<th style="text-align:right">Size</th>
<th style="text-align:right">Seeds</th>
<th>Hash</th>
<th>Action</th>
</tr></thead>
<tbody>
zP
</tbody>
</table>
<div class="status" style="text-align:left;padding:8px 12px">z results</div>)r"   extendr&   r   r   r7   ra   rh   r   r   r   r~   TS_HOSTTS_PORTr@   joinlen)r   r   r   r   rB   rrowsr-   rG   qualr0   rL   magnetts_urlactionstables                   r!   r}   Handler.do_search   s    u1A'..# "55A'..#i#AKKgy 9:Evr"B!%(DAEE&!,-DEE)Q'E+B4tFLL4F4Fu4M3NOFOSOdOdOfOfwwiq	RD
KlnF!&6G08TUUKK $gRw /F  ' Sb' 9 	 
 .
  > ?B'l^>] rb   c                      [         R                  R                  S[         S[         S3SS9nUR                  5       S:H  $ !    g= f)Nr   r
   z/echo   r   s   uptimeF)r   r   r   r   r   r   )r   r   s     r!   r~   Handler.check_torrserver5  sH    	>>))GG9AgYe*LVW)XD99;)++us   ?A Ac                    S[          S[         S[         S[         S[         S3nU R                  S5        U R                  SS	5        U R                  5         U R                  R                  UR                  5       5        g )
Nu  <!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>Settings</title>
<style>body{font-family:sans-serif;background:#0d1117;color:#e6edf3;max-width:600px;margin:20px auto;padding:20px}
h1{color:#58a6ff} label{display:block;margin:12px 0;font-size:0.9rem}
input[type=text]{width:100%;padding:8px;margin-top:4px;border:1px solid #30363d;border-radius:4px;background:#161b22;color:#e6edf3}
button{padding:10px 20px;background:#238636;border:none;border-radius:6px;color:#fff;cursor:pointer}
a{color:#58a6ff}</style>
</head><body>
<h1>⚙️ Settings</h1>
<form method="get" action="/save_settings">
<label>TorrServer Host <input type="text" name="ts_host" value="zK"></label>
<label>TorrServer Port <input type="text" name="ts_port" value="zM"></label>
<label>Jackett Host <input type="text" name="jackett_host" value="zM"></label>
<label>Jackett Port <input type="text" name="jackett_port" value="zO"></label>
<label>Jackett API Key <input type="text" name="jackett_api" value="uo   "></label>
<button type="submit">Save</button>
</form>
<p><a href="/">← Back to search</a></p>
</body></html>ru   rv   rw   )r   r   r   r   r   r   r   r   r   r   r   )r   pages     r!   r{   Handler.serve_settings;  s    
A BI	 JAAH	 JCCO. QCCO. QEEPM R& 	3)CD

'rb   c                    UR                  S[        /5      S   qUR                  S[        [        5      /5      S   qUR                  S[        /5      S   qUR                  S[
        /5      S   qUR                  S[        /5      S   qU R                  S5        U R                  SS	5        U R                  5         g )
Nts_hostr   ts_portjackett_hostjackett_portjackett_apii.  Location/)
r7   r   strr   r   r   r   r   r   r   )r   r   s     r!   r|   Handler.save_settingsT  s    **Y	215**YW7:zz.<.A!Dzz.<.A!Djj>qA3S)rb   c                 D    [        SU R                  S    SX-   35        g )N[r   z] )printclient_address)r   formatargss      r!   log_messageHandler.log_message_  s%    $%%a()FM?;<rb   rP   N)__name__
__module____qualname____firstlineno__r   r   r}   r~   r{   r|   r   __static_attributes__rP   rb   r!   rj   rj      s)    "(H@D6p(2	=rb   rj   __main__u   
  🌐 Ultimate Search Web UIz  http://localhost:z  http://192.168.1.50:z  (from network)z
  Press Ctrl+C to stop
)rn   r   r   )(__doc__ossysjsonr   r9   urllib.requestr   urllib.parsehttp.serverr   r   HOSTr   argvr>   PORTry   insert
expanduserr   r   TS_USERTS_PASSr   r   r   r"   r&   r   ra   rh   PAGErj   r   serverr   serve_foreverKeyboardInterruptshutdownrP   rb   r!   <module>r      s?  1 = < < < :sxx=1,s388A;$ 277%%&\] ^ 


 %27rJ=$ J=X ztg.F	+-	v
&'	"4&(8
9:	&(   s   2D DD