39 lines
7.8 KiB
Python
Executable File
39 lines
7.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""Build static, tracker-free support and policy pages ready for HTTPS hosting."""
|
||
from pathlib import Path
|
||
import html,re
|
||
ROOT=Path(__file__).resolve().parents[1]
|
||
SITE=ROOT/'website'
|
||
def markdown(text):
|
||
blocks=[];inlist=False
|
||
for line in text.splitlines():
|
||
if not line.strip():
|
||
if inlist:blocks.append('</ul>');inlist=False
|
||
continue
|
||
line=html.escape(line)
|
||
line=re.sub(r'(https://[^\s<]+)',r'<a href="\1">\1</a>',line)
|
||
if line.startswith('# '):blocks.append('<h1>'+line[2:]+'</h1>')
|
||
elif line.startswith('## '):blocks.append('<h2>'+line[3:]+'</h2>')
|
||
elif line.startswith('- '):
|
||
if not inlist:blocks.append('<ul>');inlist=True
|
||
blocks.append('<li>'+line[2:]+'</li>')
|
||
else:blocks.append('<p>'+line+'</p>')
|
||
if inlist:blocks.append('</ul>')
|
||
return '\n'.join(blocks)
|
||
|
||
def page(title,content):
|
||
return '''<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Tarnax — native remote control for your qBittorrent server. Support and privacy information."><title>'''+html.escape(title)+''' · Tarnax</title><link rel="icon" href="assets/favicon.png"><link rel="apple-touch-icon" href="assets/apple-touch-icon.png"><link rel="stylesheet" href="style.css"></head><body><header><a class="brand" href="index.html"><img src="assets/icon.png" alt="" width="44" height="44">Tarnax</a><nav aria-label="Main navigation"><a href="support.html">Support</a><a href="privacy.html">Privacy</a><a href="terms.html">Usage</a></nav></header><main>'''+content+'''</main><footer>© 2026 Mark Gregory · <a href="mailto:mark.gregory@abbeysoftware.com">mark.gregory@abbeysoftware.com</a><p>Independent software. Not affiliated with or endorsed by the qBittorrent project.</p></footer></body></html>'''
|
||
|
||
SITE.mkdir(exist_ok=True)
|
||
SITE.joinpath('style.css').write_text('''*{box-sizing:border-box}html{color-scheme:dark}body{margin:0;background:#070b1b;color:#edf1fc;font:18px/1.7 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}header,main,footer{max-width:1060px;margin:auto;padding:30px clamp(20px,5vw,64px)}header{display:flex;justify-content:space-between;align-items:center;gap:20px;border-bottom:1px solid #242e4a}.brand{display:flex;align-items:center;gap:14px;color:white;font-size:25px;font-weight:700;text-decoration:none}.brand img{border-radius:10px}nav{display:flex;gap:24px}a{color:#a9bdff;text-underline-offset:4px}a:hover{color:#fff}a:focus-visible{outline:3px solid #25c7ce;outline-offset:6px}h1{font-size:clamp(36px,6vw,64px);line-height:1.12;letter-spacing:-1.8px;margin:30px 0}h2{font-size:26px;line-height:1.3;margin-top:45px}p,li{max-width:76ch;color:#c8d2e8}.eyebrow{color:#67e3dd;font-size:14px;font-weight:700;letter-spacing:2px;text-transform:uppercase}.hero{padding:30px 0 50px}.hero img{width:140px;border-radius:32px}.hero strong{color:#c0c9ff}.button{display:inline-block;background:#7763ff;color:white;text-decoration:none;padding:12px 23px;border-radius:12px;font-weight:650}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:20px}.card{background:#111a31;border:1px solid #253253;border-radius:20px;padding:25px}.card h2{margin-top:0}.note{padding:20px 25px;border-left:3px solid #20bdc4;background:#101b2d}footer{font-size:14px;border-top:1px solid #242e4a;margin-top:40px}footer p{font-size:13px}details{border-bottom:1px solid #253253;padding:20px 0}summary{cursor:pointer;font-weight:650;color:white}@media(max-width:600px){header{align-items:flex-start;flex-direction:column}nav{font-size:16px}body{font-size:17px}}''')
|
||
home='''<section class="hero"><img src="assets/icon.png" alt="Tarnax app icon"><p class="eyebrow">Remote for qBittorrent</p><h1>Your server.<br><strong>Your control.</strong></h1><p>A native iPhone and iPad remote for your own qBittorrent server. Follow live transfers, organise your library and manage the details from wherever you are.</p><a class="button" href="support.html">Get support</a></section><section class="cards"><article class="card"><h2>See the flow</h2><p>Colourful upload and download graphs, live speeds and the server space you need to know about.</p></article><article class="card"><h2>Manage the details</h2><p>Search and filter your transfers, control file priorities and edit your server’s preferences.</p></article><article class="card"><h2>Your connection</h2><p>Trusted HTTPS, device Keychain credentials and optional Face ID or device authentication.</p></article></section><p class="note">Requires your own qBittorrent server with its Web UI API enabled and a trusted HTTPS connection. Torrent contents stay on your server. Use only content you are authorised to access and share.</p>'''
|
||
SITE.joinpath('index.html').write_text(page('Your server. Your control.',home))
|
||
support='''<h1>How can we help?</h1><p>For Tarnax support, email <a href="mailto:mark.gregory@abbeysoftware.com">mark.gregory@abbeysoftware.com</a>. Please include the Tarnax version/build, iPhone or iPad model, iOS version, qBittorrent version, and what happened.</p><p class="note">Never send passwords, private magnet links or sensitive server contents. Redact identifying information from screenshots.</p><h2>Quick answers</h2>'''
|
||
faqs=[('What do I need?','An existing qBittorrent server, Web UI API access, valid credentials and a trusted HTTPS endpoint. Tarnax does not provide the server, content catalogue or a VPN.'),('Why does my connection fail?','Check the HTTPS hostname, certificate chain and reverse-proxy subpath. HTTP 401 usually means proxy authentication; HTTP 403 may indicate session expiry, access rules or server protection. Use Disconnect/change server to reconnect after correcting the configuration.'),('Does Tarnax download to my phone?','No. It sends commands and selected .torrent files to your server. Torrent contents remain on that server.'),('Why does the graph start empty?','History records transfer samples while Tarnax is active and unlocked. It is session history, not a download-history database. Wait for a few updates; background pauses appear as gaps.'),('How do I retry Face ID?','Normal unlocking happens automatically. If authentication is cancelled or interrupted, tap Unlock to retry using Face ID or the device passcode fallback. Check that the app is allowed to use Face ID in iOS Settings.'),('How do I remove saved credentials?','Open Tarnax Settings and choose Forget saved credentials. iOS may retain Keychain data after deleting an app, so use this action before uninstalling if you want to remove the saved connection.'),('Can I edit every server option?','Tarnax exposes preferences returned by your server. Available settings and commands depend on qBittorrent’s version and configuration. Network, authentication and storage changes may interrupt access or move data.'),('Why don’t transfers update in the background?','This version refreshes while the app is active and unlocked. iOS background execution is not requested.'),('Where is the privacy policy?','Open Privacy in the navigation above, or Settings → Privacy policy inside Tarnax.')]
|
||
for q,a in faqs:support+='<details><summary>'+html.escape(q)+'</summary><p>'+html.escape(a)+'</p></details>'
|
||
SITE.joinpath('support.html').write_text(page('Support',support))
|
||
privacy=markdown((ROOT/'legal/privacy-policy.md').read_text())+'<h2>This website</h2><p>These supplied pages contain no analytics scripts, advertising or cookies. The hosting provider you use may process technical request logs for operating and securing the site. Confirm the final hosting arrangement before publishing this policy.</p>'
|
||
SITE.joinpath('privacy.html').write_text(page('Privacy',privacy))
|
||
SITE.joinpath('terms.html').write_text(page('Usage',markdown((ROOT/'legal/terms-of-use.md').read_text())))
|
||
print('Built four static support/marketing/policy pages; no publication performed.')
|