Skip to content

Commit

Permalink
ui polish
Browse files Browse the repository at this point in the history
  • Loading branch information
untitaker committed Oct 28, 2023
1 parent 70990d1 commit 8415937
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 53 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ posted in a week is not possible right now.

## Using the bot as a service

This bot is available as a webservice and currently in private beta. If you are
interested in trying, [DM me on Mastodon](https://woodland.cafe/@untitaker).
This bot is available as a webservice at
[list-bot.woodland.cafe](https://list-bot.woodland.cafe/). Sign in with
Mastodon, create one of the lists above and click "Sync now" to get started.

## Using the bot from your own machine

Expand Down
10 changes: 5 additions & 5 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ const launchLogin = async (baseUrl: string) => {
};

type AccountInfo = {
host: string,
username: string,
host: string;
username: string;
};

const getAccountInfo = async () => {
Expand Down Expand Up @@ -77,9 +77,9 @@ const getAccountInfo = async () => {
return false;
}

const response2 = await fetch('/register', {
const response2 = await fetch("/register", {
method: "POST",
body: new URLSearchParams({host: baseUrl, token: accessToken}),
body: new URLSearchParams({ host: baseUrl, token: accessToken }),
});

const json2 = await response2.json();
Expand All @@ -88,7 +88,7 @@ const getAccountInfo = async () => {
};

const syncImmediate = async (accountInfo: AccountInfo) => {
let response = await fetch('/sync-immediate', {
let response = await fetch("/sync-immediate", {
method: "POST",
body: new URLSearchParams(accountInfo),
});
Expand Down
7 changes: 6 additions & 1 deletion src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@
<header class="content">
<h1>Mastodon List Bot</h1>
<p>
Create programmatic lists in <a href="https://joinmastodon.org">Mastodon</a>. Take a look at the <a href="https://github.com/untitaker/mastodon-list-bot">GitHub project</a> for more information.
Create programmatic lists in
<a href="https://joinmastodon.org">Mastodon</a>. Take a look at the
<a href="https://github.com/untitaker/mastodon-list-bot"
>GitHub project</a
>
for more information.
</p>
<p></p>
</header>
Expand Down
17 changes: 1 addition & 16 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use axum::{
Form, Json, Router,
};
use clap::Parser;
use serde::Serialize;

mod api_cache;
mod api_client;
Expand Down Expand Up @@ -115,24 +114,10 @@ async fn register(
Ok(Json(account).into_response())
}

#[derive(Serialize)]
#[serde(rename = "snake_case")]
enum SyncImmediateResult {
Ok,
Error(String),
Pending,
}

async fn sync_immediate(
State(state): State<AppState>,
Form(account_pk): Form<AccountPk>,
) -> Result<Response, ResponseError> {
let result = state.store.sync_immediate(account_pk).await?;
let body = match result {
Some(Ok(_)) => SyncImmediateResult::Ok,
Some(Err(e)) => SyncImmediateResult::Error(e.to_string()),
None => SyncImmediateResult::Pending,
};

let body = state.store.sync_immediate(account_pk).await?;
Ok(Json(body).into_response())
}
36 changes: 27 additions & 9 deletions src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ impl Store {
pub async fn sync_immediate(
&self,
account_pk: AccountPk,
) -> Result<Option<Result<(), Error>>, ResponseError> {
) -> Result<SyncImmediateResult, ResponseError> {
let account = sqlx::query_as!(
Account,
"select * from accounts where host = ?1 and username = ?2",
Expand All @@ -131,14 +131,16 @@ impl Store {
.fetch_one(&self.pool)
.await?;

if account.last_success_at.map_or(false, |last_success_at| {
last_success_at > Utc::now().naive_utc() - Duration::minutes(30)
}) {
return Ok(Some(Err(anyhow::anyhow!("too many syncs"))));
}

let mut immediate_syncs = self.immediate_syncs.lock().await;

if !immediate_syncs.contains_key(&account_pk) {
if let Some(last_success_at) = account.last_success_at {
if last_success_at > Utc::now().naive_utc() - Duration::minutes(30) {
return Ok(SyncImmediateResult::TooMany);
}
}
}

let handle = &mut immediate_syncs
.entry(account_pk.clone())
.or_insert_with(move || {
Expand All @@ -151,12 +153,18 @@ impl Store {
.1;

if !handle.is_finished() {
return Ok(None);
return Ok(SyncImmediateResult::Pending);
}

let result = handle.await?;
immediate_syncs.remove(&account_pk);
Ok(Some(result))

Ok(match result {
Ok(()) => SyncImmediateResult::Ok,
Err(e) => SyncImmediateResult::Error {
value: e.to_string(),
},
})
}

async fn run_once_and_log(&self, account: Account) -> Result<Result<(), Error>, ResponseError> {
Expand Down Expand Up @@ -232,3 +240,13 @@ impl Store {
Ok((success_count, failure_count))
}
}

#[derive(Serialize)]
#[serde(tag = "type")]
#[serde(rename_all = "snake_case")]
pub enum SyncImmediateResult {
Ok,
Error { value: String },
Pending,
TooMany,
}
116 changes: 96 additions & 20 deletions src/svelte/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
required
name="host"
placeholder="e.g. mastodon.social"
pattern="[a-zA-Z0-9.:\-]+"
pattern="[a-zA-Z0-9.:\\-]+"
title="Something that looks like a hostname"
/>
</fieldset>
Expand All @@ -42,31 +42,107 @@
</form>
{:else}
<div>
<p class="green">Hello {accountInfo.username}@{accountInfo.host}!</p>
<p class="green">Hello {accountInfo.username}@{accountInfo.host}!</p>

{#if accountInfo.failure_count > 0}
<p class="red">We have encountered {accountInfo.failure_count} fatal errors when trying to sync. After 10 attempted sync attempts, we will stop synchronizing.</p>
{/if}
{#if accountInfo.last_success_at}
<p>
Your lists will be updated once per day automatically. Take a look at
the <a href="https://github.com/untitaker/mastodon-list-bot">README</a
> to see which list names are supported.
</p>

{#if accountInfo.last_error}
<p class="red">The last error we encountered was: <code>{accountInfo.last_error}</code></p>
{/if}
<p>
Your last successful sync was at <code
>{accountInfo.last_success_at}</code
>
</p>

<p>Your lists will be updated once per day automatically. Take a look at the <a href="https://github.com/untitaker/mastodon-list-bot">README</a> to see which list names are supported.</p>
<p>
<button
class="pure-button"
on:click={() => uiSyncImmediate(accountInfo)}
>
{#if syncImmediatePromise != null}
Refresh
{:else}
Sync immediately
{/if}
</button>
</p>
{:else}
<p>To get started:</p>

{#if accountInfo.last_success_at}
<p>Your last successful sync was at <code>{accountInfo.last_success_at}</code></p>
{/if}
<ol>
<li>
<p>
<a target="_blank" href={`https://${accountInfo.host}/lists`}
>create a list in Mastodon</a
>, for example <code>#last_status_at&lt;3d</code>
</p>

<p>You can also <button on:click={() => uiSyncImmediate(accountInfo)}>trigger a list sync manually</button>
<p>
Take a look at the <a
href="https://github.com/untitaker/mastodon-list-bot">README</a
> to see which list names are supported.
</p>
</li>

{#if syncImmediatePromise != null}
{#await syncImmediatePromise}
<p><code>loading...</code></p>
{:then syncImmediateResult}
<p><code>{JSON.stringify(syncImmediateResult)}</p>
{/await}
{/if}
<li>
<p>
<button
class="pure-button"
on:click={() => uiSyncImmediate(accountInfo)}
>
{#if syncImmediatePromise != null}
Refresh
{:else}
Trigger your first sync
{/if}
</button>
</p>
</li>
</ol>
{/if}

{#if syncImmediatePromise != null}
{#await syncImmediatePromise}
<code>loading...</code>
{:then syncImmediateResult}
{#if syncImmediateResult.type == "ok"}
{#if accountInfo.last_status_at}
<p>
Done syncing! Future updates to your lists will happen
automatically.
</p>
{:else}
<p>Done!</p>
{/if}
{:else if syncImmediateResult.type == "error"}
<p class="red">
Error: {JSON.stringify(syncImmediateResult.value)}
</p>
{:else if syncImmediateResult.type == "pending"}
<p>Sync ongoing.</p>
{:else if syncImmediateResult.type == "too_many"}
<p>Sync has been done recently, not starting another one.</p>
{/if}
{/await}
{/if}

{#if accountInfo.failure_count > 0}
<p class="red">
We have encountered {accountInfo.failure_count} fatal errors when trying
to sync. After 10 attempted sync attempts, we will stop synchronizing.
</p>
{/if}

{#if accountInfo.last_error}
<p class="red">
The last error we encountered was: <code
>{accountInfo.last_error}</code
>
</p>
{/if}
</div>
{/if}
{/await}

0 comments on commit 8415937

Please sign in to comment.