233 lines
5.8 KiB
Svelte
233 lines
5.8 KiB
Svelte
<script>
|
|
import { fetchMetadata, verifyPassword, BOT_USERNAME } from '../lib/api.js'
|
|
|
|
let cxidInput = $state('')
|
|
let passwordInput = $state('')
|
|
let needsPassword = $state(false)
|
|
let loading = $state(false)
|
|
let error = $state('')
|
|
let reportCxid = $state('')
|
|
|
|
async function submit() {
|
|
error = ''
|
|
if (!cxidInput.trim()) return
|
|
loading = true
|
|
try {
|
|
const meta = await fetchMetadata(cxidInput.trim())
|
|
if (meta.has_password && !passwordInput) {
|
|
needsPassword = true
|
|
loading = false
|
|
return
|
|
}
|
|
if (meta.has_password) {
|
|
const ok = await verifyPassword(cxidInput.trim(), passwordInput)
|
|
if (!ok) {
|
|
error = 'Incorrect password.'
|
|
loading = false
|
|
return
|
|
}
|
|
}
|
|
const url = new URL(window.location.href)
|
|
url.searchParams.set('cxid', cxidInput.trim())
|
|
if (passwordInput) url.searchParams.set('sc', passwordInput)
|
|
history.pushState({}, '', url.toString())
|
|
window.dispatchEvent(new PopStateEvent('popstate'))
|
|
} catch (e) {
|
|
error = e.message || 'Content not found.'
|
|
loading = false
|
|
}
|
|
}
|
|
|
|
function onKeydown(e) {
|
|
if (e.key === 'Enter') submit()
|
|
}
|
|
</script>
|
|
|
|
<main class="home">
|
|
<div class="hero">
|
|
<h1 class="retro-heading"><a href="https://cg.cx/">CG.CX</a></h1>
|
|
</div>
|
|
|
|
<div class="panel">
|
|
<p class="cg-subtitle">-- cannibal girls --</p>
|
|
<p class="bot-link">
|
|
<a href="https://t.me/{BOT_USERNAME}?start=submit" target="_blank" rel="noopener">
|
|
t.me/{BOT_USERNAME}
|
|
</a>
|
|
</p>
|
|
<p class="share-text">Share & submit your own media</p>
|
|
<label for="cxid">Content ID</label>
|
|
<input id="cxid" type="text" bind:value={cxidInput} placeholder="Enter content ID..." onkeydown={onKeydown} />
|
|
|
|
{#if needsPassword}
|
|
<label for="pw">Password</label>
|
|
<input id="pw" type="password" bind:value={passwordInput} placeholder="Enter password..." onkeydown={onKeydown} />
|
|
{/if}
|
|
|
|
{#if error}
|
|
<p class="error">{error}</p>
|
|
{/if}
|
|
|
|
<button onclick={submit} disabled={loading}>
|
|
{loading ? 'Loading...' : '[ Unlock ]'}
|
|
</button>
|
|
|
|
<details class="misc-section">
|
|
<summary>[ Misc ]</summary>
|
|
<div class="misc-content">
|
|
<a href="https://t.me/harmfulmeowbot?start=submit" target="_blank" rel="noopener">Report Content via Telegram</a>
|
|
<div class="report-direct">
|
|
<span>Report Content directly</span>
|
|
<div class="report-direct-row">
|
|
<input type="text" bind:value={reportCxid} placeholder="Content ID or link..." />
|
|
<a href={`https://t.me/harmfulmeowbot?start=report_${reportCxid}`} target="_blank" rel="noopener">
|
|
<button disabled={!reportCxid.trim()}>[ Submit ]</button>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</details>
|
|
</div>
|
|
|
|
<footer>
|
|
<p>Developed by <a href="https://t.me/forgecadrape" target="_blank" rel="noopener">@forgecadrape</a></p>
|
|
<p>portfolio <a href="https://kittens.rip/" target="_blank" rel="noopener">kittens.rip</a></p>
|
|
<p class="footer-small">Created with <3 in Europe<br/>@2026 <a href="https://cg.cx/">cg.cx</a></p>
|
|
</footer>
|
|
</main>
|
|
|
|
<style>
|
|
.home {
|
|
min-height: 100vh;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 24px;
|
|
gap: 32px;
|
|
}
|
|
.hero {
|
|
text-align: center;
|
|
}
|
|
.hero a {
|
|
text-decoration: none;
|
|
color: inherit;
|
|
}
|
|
.cg-subtitle {
|
|
font-family: 'Press Start 2P', cursive;
|
|
font-size: 0.9rem;
|
|
text-align: center;
|
|
letter-spacing: 2px;
|
|
margin-top: 0;
|
|
margin-bottom: 8px;
|
|
background: linear-gradient(90deg, var(--retro-green), var(--retro-green-light));
|
|
-webkit-background-clip: text;
|
|
-webkit-text-fill-color: transparent;
|
|
background-clip: text;
|
|
}
|
|
.panel {
|
|
width: min(400px, 100%);
|
|
background: var(--retro-panel);
|
|
border: 3px solid var(--retro-border);
|
|
padding: 24px;
|
|
box-shadow: 6px 6px 0px var(--retro-shadow);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
}
|
|
.panel label {
|
|
font-family: 'Press Start 2P', cursive;
|
|
font-size: 0.55rem;
|
|
color: var(--retro-green);
|
|
text-transform: uppercase;
|
|
}
|
|
.error {
|
|
color: var(--retro-danger);
|
|
font-size: 1rem;
|
|
}
|
|
footer {
|
|
text-align: center;
|
|
font-size: 0.95rem;
|
|
color: #555;
|
|
}
|
|
footer p {
|
|
margin: 4px 0;
|
|
}
|
|
.footer-small {
|
|
font-size: 0.85rem;
|
|
margin-top: 12px;
|
|
color: #777;
|
|
}
|
|
.misc-section {
|
|
margin-top: 8px;
|
|
border: 2px solid var(--retro-border);
|
|
padding: 8px 12px;
|
|
background: #f5f5f5;
|
|
}
|
|
.misc-section summary {
|
|
font-family: 'Press Start 2P', cursive;
|
|
font-size: 0.55rem;
|
|
color: var(--retro-green);
|
|
cursor: pointer;
|
|
user-select: none;
|
|
}
|
|
.misc-content {
|
|
margin-top: 8px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
}
|
|
.misc-content a {
|
|
font-size: 0.9rem;
|
|
color: var(--retro-green);
|
|
text-decoration: none;
|
|
}
|
|
.misc-content a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
.report-direct {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
margin-top: 4px;
|
|
}
|
|
.report-direct span {
|
|
font-size: 0.9rem;
|
|
color: var(--retro-green);
|
|
}
|
|
.report-direct-row {
|
|
display: flex;
|
|
gap: 6px;
|
|
align-items: center;
|
|
}
|
|
.report-direct-row input {
|
|
flex: 1;
|
|
padding: 4px 8px;
|
|
font-size: 0.85rem;
|
|
border: 2px solid var(--retro-border);
|
|
background: #fff;
|
|
color: #333;
|
|
}
|
|
.report-direct-row button {
|
|
padding: 4px 8px;
|
|
font-size: 0.75rem;
|
|
cursor: pointer;
|
|
}
|
|
.bot-link {
|
|
font-style: italic;
|
|
text-align: center;
|
|
margin: 0;
|
|
}
|
|
.bot-link a {
|
|
color: var(--retro-green);
|
|
text-decoration: underline;
|
|
font-size: 0.95rem;
|
|
}
|
|
.share-text {
|
|
font-size: 0.85rem;
|
|
color: #555;
|
|
text-align: center;
|
|
margin: 2px 0 8px;
|
|
}
|
|
</style>
|