johnandersen777.bsky.social/knotless
git that lives in your Atmosphere account
Forked from chadtmiller.com/knotless
0
0
<script lang="ts">
/**
* Whether an account or record is taken down on this appview, and taking
* it down or putting it back, as an operator: `subject` is a DID or an
* at:// URI, as `knotless admin takedown` takes one.
*/
let { subject = $bindable('') }: { subject?: string } = $props();
let down: boolean | null = $state(null);
let problem = $state('');
// Which is under way: 'look', 'down' or 'up'.
let busy = $state('');
const named = $derived(subject.trim());
const ref = $derived(
named.startsWith('did:')
? { $type: 'com.atproto.admin.defs#repoRef', did: named }
: { $type: 'com.atproto.repo.strongRef', uri: named }
);
/** What the server says, or why not, in its words. */
async function ask(res: Response | null): Promise<{ takedown?: { applied?: boolean } } | null> {
if (res?.ok) return res.json();
const failure = await res?.json().catch(() => null);
problem = failure?.message ?? 'That did not work. Try again.';
return null;
}
async function look(e?: SubmitEvent) {
e?.preventDefault();
busy = 'look';
problem = '';
const by = named.startsWith('did:') ? 'did' : 'uri';
const q = new URLSearchParams({ [by]: named });
const said = await ask(
await fetch(`/xrpc/com.atproto.admin.getSubjectStatus?${q}`, { cache: 'no-cache' }).catch(
() => null
)
);
down = said ? said.takedown?.applied === true : null;
busy = '';
}
async function set(applied: boolean) {
busy = applied ? 'down' : 'up';
problem = '';
const body = JSON.stringify({ subject: ref, takedown: { applied } });
const res = await fetch('/xrpc/com.atproto.admin.updateSubjectStatus', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body
}).catch(() => null);
if (await ask(res)) down = applied;
busy = '';
}
</script>
<div class="box admin-box">
<div class="boxhead"><h2>Take down</h2></div>
<form class="admin-form" onsubmit={look}>
<label for="takedown-subject"
>An account's DID, or a repository's, pull's, issue's or comment's at:// URI</label
>
<input
id="takedown-subject"
name="subject"
placeholder="did:plc:… or at://…"
autocapitalize="none"
spellcheck="false"
required
bind:value={subject}
oninput={() => (down = null)}
/>
<div class="admin-actions">
<button class="btn" type="submit" disabled={!!busy || !named} aria-busy={busy === 'look'}
>{busy === 'look' ? 'Looking…' : 'Look up'}</button
>
<button
class="btn primary"
type="button"
disabled={!!busy || !named || down === true}
aria-busy={busy === 'down'}
onclick={() => set(true)}>{busy === 'down' ? 'Taking down…' : 'Take down'}</button
>
<button
class="btn"
type="button"
disabled={!!busy || !named || down === false}
aria-busy={busy === 'up'}
onclick={() => set(false)}>{busy === 'up' ? 'Putting back…' : 'Put back'}</button
>
{#if down !== null}<span class="mute" role="status">{down ? 'Taken down' : 'Up'}</span>{/if}
</div>
{#if problem}<p class="problem" role="alert">{problem}</p>{/if}
</form>
</div>