~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
91 lines · 3.0 KB Raw History
<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>