362 lines
11 KiB
HTML
362 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Linkster</title>
|
|
<link rel="icon" type="image/png" href="/favicon.png">
|
|
<style>
|
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
background: #0f1117;
|
|
color: #e2e8f0;
|
|
line-height: 1.6;
|
|
padding: 2rem 1rem;
|
|
}
|
|
|
|
.container { max-width: 780px; margin: 0 auto; }
|
|
|
|
header { margin-bottom: 2.5rem; }
|
|
header h1 { font-size: 2rem; font-weight: 700; color: #f8fafc; }
|
|
header p { color: #94a3b8; margin-top: .4rem; }
|
|
|
|
h2 {
|
|
font-size: 1.1rem;
|
|
font-weight: 600;
|
|
color: #f8fafc;
|
|
margin: 2rem 0 .75rem;
|
|
padding-bottom: .4rem;
|
|
border-bottom: 1px solid #1e293b;
|
|
}
|
|
|
|
.endpoint {
|
|
background: #1e293b;
|
|
border: 1px solid #334155;
|
|
border-radius: .5rem;
|
|
padding: 1rem 1.25rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
.endpoint .method {
|
|
display: inline-block;
|
|
background: #2563eb;
|
|
color: #fff;
|
|
font-size: .75rem;
|
|
font-weight: 700;
|
|
padding: .15rem .5rem;
|
|
border-radius: .25rem;
|
|
margin-right: .6rem;
|
|
vertical-align: middle;
|
|
}
|
|
.endpoint .path {
|
|
font-family: "SFMono-Regular", Consolas, monospace;
|
|
font-size: .95rem;
|
|
color: #7dd3fc;
|
|
}
|
|
.endpoint .desc { color: #94a3b8; margin-top: .4rem; font-size: .9rem; }
|
|
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
font-size: .9rem;
|
|
}
|
|
th {
|
|
text-align: left;
|
|
padding: .5rem .75rem;
|
|
background: #1e293b;
|
|
color: #94a3b8;
|
|
font-weight: 600;
|
|
font-size: .8rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: .05em;
|
|
}
|
|
td {
|
|
padding: .5rem .75rem;
|
|
border-top: 1px solid #1e293b;
|
|
}
|
|
td code {
|
|
font-family: "SFMono-Regular", Consolas, monospace;
|
|
background: #1e293b;
|
|
padding: .1rem .35rem;
|
|
border-radius: .25rem;
|
|
font-size: .85rem;
|
|
color: #7dd3fc;
|
|
}
|
|
tr:hover td { background: #0f1e30; }
|
|
|
|
pre {
|
|
background: #1e293b;
|
|
border: 1px solid #334155;
|
|
border-radius: .5rem;
|
|
padding: 1rem 1.25rem;
|
|
overflow-x: auto;
|
|
font-family: "SFMono-Regular", Consolas, monospace;
|
|
font-size: .85rem;
|
|
line-height: 1.7;
|
|
}
|
|
.key { color: #7dd3fc; }
|
|
.str { color: #86efac; }
|
|
.bool { color: #f472b6; }
|
|
|
|
.badge {
|
|
display: inline-block;
|
|
font-size: .7rem;
|
|
padding: .1rem .4rem;
|
|
border-radius: .2rem;
|
|
font-weight: 600;
|
|
margin-left: .3rem;
|
|
}
|
|
.badge-full { background: #14532d; color: #86efac; }
|
|
.badge-no { background: #450a0a; color: #fca5a5; }
|
|
|
|
.playlist-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
|
|
gap: .5rem;
|
|
}
|
|
.playlist-item {
|
|
background: #1e293b;
|
|
border: 1px solid #334155;
|
|
border-radius: .375rem;
|
|
padding: .5rem .75rem;
|
|
font-size: .85rem;
|
|
color: #cbd5e1;
|
|
}
|
|
|
|
footer {
|
|
margin-top: 3rem;
|
|
padding-top: 1rem;
|
|
border-top: 1px solid #1e293b;
|
|
color: #475569;
|
|
font-size: .8rem;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
flex-wrap: wrap;
|
|
gap: .5rem;
|
|
}
|
|
footer a { color: #64748b; text-decoration: none; }
|
|
footer a:hover { color: #94a3b8; }
|
|
|
|
.download-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: .5rem;
|
|
margin-top: .75rem;
|
|
padding: .5rem 1rem;
|
|
background: #16a34a;
|
|
color: #fff;
|
|
font-size: .85rem;
|
|
font-weight: 600;
|
|
border-radius: .375rem;
|
|
text-decoration: none;
|
|
}
|
|
.download-btn:hover { background: #15803d; }
|
|
|
|
.legal {
|
|
margin-top: 4rem;
|
|
padding-top: 2rem;
|
|
border-top: 2px solid #1e293b;
|
|
}
|
|
.legal h2 {
|
|
font-size: 1.3rem;
|
|
margin-top: 2.5rem;
|
|
}
|
|
.legal h3 {
|
|
font-size: .95rem;
|
|
font-weight: 600;
|
|
color: #cbd5e1;
|
|
margin: 1.25rem 0 .4rem;
|
|
}
|
|
.legal p {
|
|
color: #94a3b8;
|
|
font-size: .9rem;
|
|
margin-bottom: .6rem;
|
|
}
|
|
.legal address {
|
|
font-style: normal;
|
|
color: #94a3b8;
|
|
font-size: .9rem;
|
|
line-height: 1.8;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
|
|
<header>
|
|
<img src="/favicon.png" alt="Linkster Logo" style="width:80px;height:80px;border-radius:.75rem;margin-bottom:.75rem;display:block;">
|
|
<h1>Linkster App</h1>
|
|
<p style="margin-top:.75rem">Löst die QR-Code aus einem bekannten Spiel auf und ermöglicht den Aufruf anderer Streaming Dienste als Spotify.</p>
|
|
<a class="download-btn" href="/linkster.apk" download="linkster-1.0.apk">
|
|
↓ Android App herunterladen (v1.0)
|
|
</a>
|
|
<p>
|
|
<h2>Installation</h2>
|
|
<h3>1. Die APK-Datei finden</h3>
|
|
<p>Zuerst musst du die Datei auf deinem Gerät finden. Meistens landet sie im Ordner Downloads.</p>
|
|
<p>Öffne eine Dateimanager-App (oft heißt sie "Eigene Dateien", "Files" oder "Dateien").</p>
|
|
<p>Navigiere zum Ordner Downloads und tippe die APK-Datei an.</p>
|
|
<h3>2. Installation aus unbekannten Quellen erlauben</h3>
|
|
<p>Wenn du die Datei das erste Mal antippst, erscheint normalerweise eine Sicherheitswarnung.</p>
|
|
<p>Tippe in dem Pop-up-Fenster auf Einstellungen.</p>
|
|
<p>Du wirst nun zu einem Menü weitergeleitet ("Unbekannte Apps installieren"). Dort musst du den Schalter bei der App aktivieren, mit der du die APK öffnen willst (z. B. Chrome oder dein Dateimanager).</p>
|
|
<p>Gehe danach zurück zur Datei.</p>
|
|
<h3>3. Installation durchführen</h3>
|
|
<p>Tippe die Datei erneut an.</p>
|
|
<p>Es erscheint die Frage: "Möchtest du diese App installieren?". Bestätige dies mit Installieren.</p>
|
|
<p>Nach kurzem Warten ist die App bereit und du kannst auf Öffnen tippen.</p>
|
|
</header>
|
|
|
|
|
|
|
|
<h1>Linkster API</h1>
|
|
<h2>Endpunkte</h2>
|
|
|
|
<div class="endpoint">
|
|
<span class="method">GET</span>
|
|
<span class="path">/api/resolve?url={url}</span>
|
|
<div class="desc">Löst einen Streaming-Link auf und gibt Titel, Künstler und verfügbare Provider-Links zurück.</div>
|
|
</div>
|
|
|
|
<div class="endpoint">
|
|
<span class="method">GET</span>
|
|
<span class="path">/api/health</span>
|
|
<div class="desc">Gibt <code>"ok"</code> zurück, wenn der Server läuft.</div>
|
|
</div>
|
|
|
|
<h2>Parameter</h2>
|
|
<table>
|
|
<thead>
|
|
<tr><th>Parameter</th><th>Typ</th><th>Beschreibung</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><code>url</code></td>
|
|
<td>string</td>
|
|
<td>Die vollständige URL vom Hitster-QR-Code (z.B. Apple Music Link)</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<h2>Antwort (gefunden)</h2>
|
|
<pre><span class="key">"found"</span>: <span class="bool">true</span>,
|
|
<span class="key">"title"</span>: <span class="str">"Song-Titel"</span>,
|
|
<span class="key">"artist"</span>: <span class="str">"Künstlername"</span>,
|
|
<span class="key">"playlist"</span>: <span class="str">"Hitster Deutsch"</span>,
|
|
<span class="key">"providers"</span>: {
|
|
<span class="key">"spotify"</span>: <span class="str">"https://open.spotify.com/track/..."</span>,
|
|
<span class="key">"deezer"</span>: <span class="str">"https://www.deezer.com/track/..."</span>,
|
|
<span class="key">"youtube"</span>: <span class="str">"https://www.youtube.com/watch?v=..."</span>,
|
|
<span class="key">"youtubeMusic"</span>: <span class="str">"https://music.youtube.com/watch?v=..."</span>,
|
|
<span class="key">"appleMusic"</span>: <span class="str">"https://music.apple.com/..."</span>,
|
|
<span class="key">"amazonMusic"</span>: <span class="str">"https://music.amazon.com/..."</span>,
|
|
<span class="key">"tidal"</span>: <span class="str">"https://tidal.com/track/..."</span>
|
|
}</pre>
|
|
|
|
<h2>Antwort (nicht gefunden)</h2>
|
|
<pre><span class="key">"found"</span>: <span class="bool">false</span></pre>
|
|
|
|
<h2>Unterstützte Playlists</h2>
|
|
<div class="playlist-grid">
|
|
<div class="playlist-item">Hitster Deutsch</div>
|
|
<div class="playlist-item">Hitster Bingo Deutschland</div>
|
|
<div class="playlist-item">Hitster Bayern 1 Expansion (DE)</div>
|
|
<div class="playlist-item">Hitster Celebration (DE)</div>
|
|
<div class="playlist-item">Hitster Guilty Pleasures (DE)</div>
|
|
<div class="playlist-item">Hitster Rock (DE)</div>
|
|
<div class="playlist-item">Hitster Schlager Party (DE)</div>
|
|
<div class="playlist-item">Hitster Soundtracks Expansion (DE)</div>
|
|
<div class="playlist-item">Hitster Summer Party (DE)</div>
|
|
<div class="playlist-item">Hitster Canada</div>
|
|
<div class="playlist-item">Hitster Canada (Franco)</div>
|
|
<div class="playlist-item">Hitster Guilty Pleasures (CA)</div>
|
|
<div class="playlist-item">Hitster Guilty Pleasures (NOR)</div>
|
|
<div class="playlist-item">Hitster Italia</div>
|
|
</div>
|
|
|
|
<footer>
|
|
<span>Linkster — linkster.langhei.de</span>
|
|
<span>
|
|
<a href="#impressum">Impressum</a>
|
|
 · 
|
|
<a href="#datenschutz">Datenschutz</a>
|
|
</span>
|
|
</footer>
|
|
|
|
<div class="legal">
|
|
|
|
<h2 id="impressum">Impressum</h2>
|
|
|
|
<h3>Angaben gemäß § 5 TMG</h3>
|
|
<address>
|
|
Mario Störmer<br>
|
|
Langheide 14<br>
|
|
24354 Rieseby<br>
|
|
Deutschland
|
|
</address>
|
|
|
|
<h3>Hinweis</h3>
|
|
<p>
|
|
Dieses Angebot ist ein privates, nicht-kommerzielles Hobbyprojekt.
|
|
Es werden keine wirtschaftlichen Interessen verfolgt und kein Entgelt erhoben.
|
|
</p>
|
|
|
|
<h2 id="datenschutz">Datenschutzerklärung</h2>
|
|
|
|
<h3>Verantwortlicher</h3>
|
|
<address>
|
|
Mario Störmer<br>
|
|
Langheide 14<br>
|
|
24354 Rieseby<br>
|
|
Deutschland
|
|
</address>
|
|
|
|
<h3>Welche Daten werden verarbeitet?</h3>
|
|
<p>
|
|
Beim Aufruf dieser Seite und der API werden technisch bedingt folgende Daten
|
|
kurzfristig im Server-Log gespeichert:
|
|
</p>
|
|
<p>
|
|
IP-Adresse des anfragenden Geräts, aufgerufene URL, Zeitpunkt der Anfrage sowie
|
|
HTTP-Statuscode. Diese Daten sind für den stabilen Betrieb des Dienstes notwendig
|
|
und werden nicht an Dritte weitergegeben.
|
|
</p>
|
|
|
|
<h3>Zweck der Verarbeitung</h3>
|
|
<p>
|
|
Die Daten werden ausschließlich zur Fehleranalyse und Sicherstellung des Betriebs
|
|
verwendet. Eine Auswertung zu Analyse-, Tracking- oder Werbezwecken findet nicht statt.
|
|
</p>
|
|
|
|
<h3>Speicherdauer</h3>
|
|
<p>
|
|
Server-Logs werden automatisch nach 30 Tagen gelöscht. Es erfolgt keine
|
|
dauerhafte Speicherung personenbezogener Daten.
|
|
</p>
|
|
|
|
<h3>Cookies & Tracking</h3>
|
|
<p>
|
|
Diese Website verwendet keine Cookies, keine Analyse-Tools und kein Tracking
|
|
jeglicher Art.
|
|
</p>
|
|
|
|
<h3>Weitergabe an Dritte</h3>
|
|
<p>
|
|
Es findet keine Weitergabe von Daten an Dritte statt. Der Dienst ist
|
|
ausschließlich für den privaten Gebrauch bestimmt.
|
|
</p>
|
|
|
|
<h3>Rechte betroffener Personen</h3>
|
|
<p>
|
|
Gemäß DSGVO stehen Ihnen das Recht auf Auskunft, Berichtigung, Löschung und
|
|
Einschränkung der Verarbeitung zu. Anfragen können per Post an die oben genannte
|
|
Adresse gerichtet werden.
|
|
</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</body>
|
|
</html>
|