aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFuwn <[email protected]>2024-01-08 15:27:28 -0800
committerFuwn <[email protected]>2024-01-08 15:27:28 -0800
commit6620bc00fdf5173ffb20a9057a4580b59410dbd7 (patch)
tree57f149d20ce28960909bda1bba1d6fcbbd0ef515 /src
parentfix(badges): loading order (diff)
downloaddue.moe-6620bc00fdf5173ffb20a9057a4580b59410dbd7.tar.xz
due.moe-6620bc00fdf5173ffb20a9057a4580b59410dbd7.zip
feat(tools): new tools url method
Diffstat (limited to 'src')
-rw-r--r--src/lib/Birthday/ACDB.ts4
-rw-r--r--src/lib/Birthday/aniSearch.ts4
-rw-r--r--src/lib/Error/path.ts18
-rw-r--r--src/lib/Tools/Picker.svelte24
-rw-r--r--src/lib/Tools/tools.ts43
-rw-r--r--src/lib/Utility/proxy.ts4
-rw-r--r--src/lib/Utility/root.ts8
-rw-r--r--src/routes/birthdays/+server.ts12
-rw-r--r--src/routes/tools/+page.svelte150
-rw-r--r--src/routes/tools/[tool]/+page.server.ts5
-rw-r--r--src/routes/tools/[tool]/+page.svelte63
-rw-r--r--src/routes/wrapped/+server.ts10
12 files changed, 197 insertions, 148 deletions
diff --git a/src/lib/Birthday/ACDB.ts b/src/lib/Birthday/ACDB.ts
index 700b13e1..cb71880d 100644
--- a/src/lib/Birthday/ACDB.ts
+++ b/src/lib/Birthday/ACDB.ts
@@ -1,3 +1,5 @@
+import root from '$lib/Utility/root';
+
export interface ACDBBirthday {
character_image: string;
name: string;
@@ -7,7 +9,7 @@ export interface ACDBBirthday {
export const ACDBBirthdays = async (month: number, day: number): Promise<ACDBBirthday[]> =>
(
await (
- await fetch(`/api/birthdays/acdb?month=${month}&day=${day}`, {
+ await fetch(root(`/api/birthdays/acdb?month=${month}&day=${day}`), {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
diff --git a/src/lib/Birthday/aniSearch.ts b/src/lib/Birthday/aniSearch.ts
index a938f7ba..3fa77f61 100644
--- a/src/lib/Birthday/aniSearch.ts
+++ b/src/lib/Birthday/aniSearch.ts
@@ -1,3 +1,5 @@
+import root from '$lib/Utility/root';
+
export interface aniSearchBirthday {
name: string;
image: string;
@@ -7,4 +9,4 @@ export const aniSearchBirthdays = async (
month: number,
day: number
): Promise<aniSearchBirthday[]> =>
- await (await fetch(`/api/birthdays/anisearch?month=${month}&day=${day}`, {})).json();
+ await (await fetch(root(`/api/birthdays/anisearch?month=${month}&day=${day}`), {})).json();
diff --git a/src/lib/Error/path.ts b/src/lib/Error/path.ts
index f493726b..40f50b7c 100644
--- a/src/lib/Error/path.ts
+++ b/src/lib/Error/path.ts
@@ -1,17 +1,11 @@
-import levenshtein from 'fast-levenshtein';
-
export const closest = (path: string, suggestions: string[]) => {
- let closest = '';
- let lowestDistance = Infinity;
+ const partialMatch = suggestions.find((suggestion) => suggestion.includes(path));
- [...suggestions, '...'].forEach((suggestion) => {
- const distance = levenshtein.get(path, suggestion);
+ if (partialMatch) return partialMatch;
- if (distance < lowestDistance) {
- lowestDistance = distance;
- closest = suggestion;
- }
- });
+ const closestMatch = suggestions.reduce((prev, curr) => {
+ return prev.length > curr.length ? prev : curr;
+ }, '');
- return closest;
+ return closestMatch;
};
diff --git a/src/lib/Tools/Picker.svelte b/src/lib/Tools/Picker.svelte
new file mode 100644
index 00000000..6ead9624
--- /dev/null
+++ b/src/lib/Tools/Picker.svelte
@@ -0,0 +1,24 @@
+<script lang="ts">
+ import { browser } from '$app/environment';
+ import { goto } from '$app/navigation';
+
+ export let tool: string;
+</script>
+
+<blockquote>
+ <select
+ bind:value={tool}
+ on:change={() => {
+ if (browser) goto(`/tools/${tool}`);
+ }}
+ >
+ <option value="default" selected disabled hidden>Select a tool to continue</option>
+ <option value="wrapped">AniList Wrapped</option>
+ <option value="birthdays">Today's Character Birthdays</option>
+ <option value="sequel_spy">Sequel Spy</option>
+ <option value="discussions">Episode Discussion Collector</option>
+ <option value="random_follower">Random Follower Finder</option>
+ <option value="dump_profile">Dump Profile</option>
+ <option value="activity_history">Activity History Analyser</option>
+ </select>
+</blockquote>
diff --git a/src/lib/Tools/tools.ts b/src/lib/Tools/tools.ts
new file mode 100644
index 00000000..c0e499b2
--- /dev/null
+++ b/src/lib/Tools/tools.ts
@@ -0,0 +1,43 @@
+export const tools: { [key: string]: { name: string; description?: string; id: string } } = {
+ default: {
+ name: 'Tools',
+ description: 'A collection of tools to help you get the most out of AniList.',
+ id: 'default'
+ },
+ wrapped: {
+ name: 'AniList Wrapped & Statistics Panel',
+ description:
+ 'Instantly generate an AniList themed Wrapped for your profile, doubling as a statistics panel for your bio',
+ id: 'wrapped'
+ },
+ birthdays: {
+ name: "Today's Character Birthdays",
+ description:
+ 'Find and display the birthdays of all characters for today, or any other day of the year',
+ id: 'birthdays'
+ },
+ sequel_spy: {
+ name: 'Sequel Spy (Missing Prequel Finder)',
+ description: "Find media with prequels you haven't seen yet for any given simulcast season",
+ id: 'sequel_spy'
+ },
+ discussions: {
+ name: 'Episode Discussion Collector',
+ description: 'Find and display all episode discussions for a given user',
+ id: 'discussions'
+ },
+ random_follower: {
+ name: 'Random Follower Finder',
+ description: 'Find a random follower of any given user',
+ id: 'random_follower'
+ },
+ dump_profile: {
+ name: 'Dump Profile',
+ description: "Dump a user's profile to JSON",
+ id: 'dump_profile'
+ },
+ activity_history: {
+ name: 'Activity History Analyser',
+ id: 'activity_history'
+ }
+};
diff --git a/src/lib/Utility/proxy.ts b/src/lib/Utility/proxy.ts
index ec9c289b..3337fe29 100644
--- a/src/lib/Utility/proxy.ts
+++ b/src/lib/Utility/proxy.ts
@@ -1,7 +1,7 @@
import { env } from '$env/dynamic/public';
-export const proxy = (url: string, disable = true) =>
- env.PUBLIC_ANILIST_REDIRECT_URI?.includes('192.168') && !disable
+export const proxy = (url: string, enable = false) =>
+ env.PUBLIC_ANILIST_REDIRECT_URI?.includes('localhost') || enable
? url
: `https://proxy.due.moe/?q=${url}`;
diff --git a/src/lib/Utility/root.ts b/src/lib/Utility/root.ts
new file mode 100644
index 00000000..3f9ea07d
--- /dev/null
+++ b/src/lib/Utility/root.ts
@@ -0,0 +1,8 @@
+import { env } from '$env/dynamic/public';
+
+export const root = (path: string, enable = false) =>
+ env.PUBLIC_ANILIST_REDIRECT_URI?.includes('localhost') || enable
+ ? `http://localhost:5173${path}`
+ : `https://due.moe${path}`;
+
+export default root;
diff --git a/src/routes/birthdays/+server.ts b/src/routes/birthdays/+server.ts
index 2b9219b5..7f0fd833 100644
--- a/src/routes/birthdays/+server.ts
+++ b/src/routes/birthdays/+server.ts
@@ -1,7 +1,11 @@
+import root from '$lib/Utility/root.js';
+
export const GET = ({ url }) =>
Response.redirect(
- `https://due.moe/tools?tool=birthdays${
- url.searchParams.values.length > 0 ? `&${url.searchParams.toString()}` : ''
- }`,
- 301
+ root(
+ `/tools/birthdays${
+ url.searchParams.values.length > 0 ? `&${url.searchParams.toString()}` : ''
+ }`
+ ),
+ 307
);
diff --git a/src/routes/tools/+page.svelte b/src/routes/tools/+page.svelte
index e5bda954..6293d0b1 100644
--- a/src/routes/tools/+page.svelte
+++ b/src/routes/tools/+page.svelte
@@ -1,133 +1,35 @@
<script lang="ts">
- import ActivityHistory from '$lib/Tools/ActivityHistory/Tool.svelte';
- import Wrapped from '$lib/Tools/Wrapped.svelte';
- import { browser } from '$app/environment';
- import EpisodeDiscussionCollector from '$lib/Tools/EpisodeDiscussionCollector.svelte';
- import CharacterBirthdays from '$lib/Tools/Birthdays.svelte';
- import { page } from '$app/stores';
- import SequelSpy from '$lib/Tools/SequelSpy.svelte';
- import { closest } from '$lib/Error/path';
import HeadTitle from '$lib/HeadTitle.svelte';
- import RandomFollower from '$lib/Tools/RandomFollower.svelte';
- import DumpProfile from '$lib/Tools/DumpProfile.svelte';
+ import Picker from '$lib/Tools/Picker.svelte';
+ import { tools } from '$lib/Tools/tools.js';
- export let data;
-
- let tool =
- browser && $page.url.searchParams.size !== 0
- ? $page.url.searchParams.get('tool') || 'default'
- : 'default';
- const tools: { [key: string]: { name: string; description?: string } } = {
- default: {
- name: 'Tools',
- description: 'A collection of tools to help you get the most out of AniList.'
- },
- wrapped: {
- name: 'AniList Wrapped & Statistics Panel',
- description:
- 'Instantly generate an AniList themed Wrapped for your profile, doubling as a statistics panel for your bio'
- },
- birthdays: {
- name: "Today's Character Birthdays",
- description:
- 'Find and display the birthdays of all characters for today, or any other day of the year'
- },
- sequel_spy: {
- name: 'Sequel Spy (Missing Prequel Finder)',
- description: "Find media with prequels you haven't seen yet for any given simulcast season"
- },
- discussions: {
- name: 'Episode Discussion Collector',
- description: 'Find and display all episode discussions for a given user'
- },
- random_follower: {
- name: 'Random Follower Finder',
- description: 'Find a random follower of any given user'
- },
- dump_profile: {
- name: 'Dump Profile',
- description: "Dump a user's profile to JSON"
- },
- activity_history: {
- name: 'Activity History Analyser'
- }
- };
-
- $: {
- if (browser) {
- $page.url.searchParams.set('tool', tool);
- history.replaceState(null, '', `?${$page.url.searchParams.toString()}`);
- }
- }
- $: suggestion = closest(browser ? tool : '...', Object.keys(tools));
+ let tool = 'default';
</script>
-<blockquote>
- <select bind:value={tool}>
- <option value="default" selected disabled hidden>Tool</option>
- <option value="wrapped">AniList Wrapped</option>
- <option value="birthdays">Today's Character Birthdays</option>
- <option value="sequel_spy">Sequel Spy</option>
- <option value="discussions">Episode Discussion Collector</option>
- <option value="random_follower">Random Follower Finder</option>
- <option value="dump_profile">Dump Profile</option>
- <option value="activity_history">Activity History Analyser</option>
- </select>
-</blockquote>
-
-{#if !Object.keys(tools).includes(tool)}
- <HeadTitle route="Tools" path="/tools" />
- <div class="card">
- <p>Tool not found.</p>
+<Picker {tool} />
- <blockquote>
- Did you mean "<a
- href={`#`}
- style={suggestion === '...' ? 'pointer-events: none; color: inherit;' : ''}
- on:click={() => (tool = suggestion)}
- >
- {suggestion === '...' ? '...' : tools[suggestion]}</a
- >"?
- </blockquote>
- </div>
-{:else}
- <HeadTitle route={tools[tool].name} path={`/tools?tool=${tool}`} />
+<HeadTitle route={tools[tool].name} path={`/tools?tool=${tool}`} />
- {#if tool === 'default'}
- <div class="card">
- <p>Select a tool to continue.</p>
+<div class="card">
+ <p>Select a tool to continue.</p>
- <ul>
- {#each Object.keys(tools) as t}
- {#if t !== 'default'}
- <li>
- <a href={`#`} on:click={() => (tool = t)}>{tools[t].name}</a>
- {#if tools[t].description}
- <blockquote>{tools[t].description}</blockquote>
- {/if}
- </li>
+ <ul>
+ {#each Object.keys(tools) as t}
+ {#if t !== 'default'}
+ <li>
+ <a href={`/tools/${tools[t].id}`} on:click={() => (tool = t)}>{tools[t].name}</a>
+ {#if tools[t].description}
+ <blockquote>{tools[t].description}</blockquote>
{/if}
- {/each}
- </ul>
-
- <p />
-
- Have any requests for cool tools that you think others might find useful? Send a message to
- <a href="https://anilist.co/user/fuwn" target="_blank" rel="noopener">@fuwn</a> on AniList!
- </div>
- {:else if tool === 'activity_history'}
- <ActivityHistory user={data.user} />
- {:else if tool === 'wrapped'}
- <Wrapped user={data.user} />
- {:else if tool === 'discussions'}
- <EpisodeDiscussionCollector />
- {:else if tool === 'birthdays'}
- <CharacterBirthdays />
- {:else if tool === 'sequel_spy'}
- <SequelSpy user={data.user} />
- {:else if tool === 'random_follower'}
- <RandomFollower />
- {:else if tool === 'dump_profile'}
- <DumpProfile />
- {/if}
-{/if}
+ </li>
+ {/if}
+ {/each}
+ </ul>
+
+ <p />
+
+ <blockquote style="margin: 0 0 0 1.5rem;">
+ Have any requests for cool tools that you think others might find useful? Send a message to
+ <a href="https://anilist.co/user/fuwn" target="_blank" rel="noopener">@fuwn</a> on AniList!
+ </blockquote>
+</div>
diff --git a/src/routes/tools/[tool]/+page.server.ts b/src/routes/tools/[tool]/+page.server.ts
new file mode 100644
index 00000000..c7e72d18
--- /dev/null
+++ b/src/routes/tools/[tool]/+page.server.ts
@@ -0,0 +1,5 @@
+export const load = ({ params }) => {
+ return {
+ tool: params.tool
+ };
+};
diff --git a/src/routes/tools/[tool]/+page.svelte b/src/routes/tools/[tool]/+page.svelte
new file mode 100644
index 00000000..bd236d11
--- /dev/null
+++ b/src/routes/tools/[tool]/+page.svelte
@@ -0,0 +1,63 @@
+<script lang="ts">
+ import ActivityHistory from '$lib/Tools/ActivityHistory/Tool.svelte';
+ import Wrapped from '$lib/Tools/Wrapped.svelte';
+ import EpisodeDiscussionCollector from '$lib/Tools/EpisodeDiscussionCollector.svelte';
+ import CharacterBirthdays from '$lib/Tools/Birthdays.svelte';
+ import SequelSpy from '$lib/Tools/SequelSpy.svelte';
+ import { closest } from '$lib/Error/path';
+ import HeadTitle from '$lib/HeadTitle.svelte';
+ import RandomFollower from '$lib/Tools/RandomFollower.svelte';
+ import DumpProfile from '$lib/Tools/DumpProfile.svelte';
+ import { tools } from '$lib/Tools/tools.js';
+ import { onMount } from 'svelte';
+ import { goto } from '$app/navigation';
+ import Picker from '$lib/Tools/Picker.svelte';
+
+ export let data;
+
+ let tool = data.tool ?? 'default';
+
+ onMount(() => {
+ if (tool === 'default') goto('/tools');
+ });
+
+ $: suggestion = closest(tool, Object.keys(tools));
+</script>
+
+<Picker bind:tool />
+
+{#if !Object.keys(tools).includes(tool)}
+ <HeadTitle route="Tools" path="/tools" />
+
+ <div class="card">
+ <p>Tool not found.</p>
+
+ <blockquote style="margin: 0 0 0 1.5rem;">
+ Did you mean "<a
+ href={`/tools/${tools[suggestion].id}`}
+ on:click={() => (tool = suggestion)}
+ style={suggestion === '...' ? 'pointer-events: none; color: inherit;' : ''}
+ >
+ {suggestion === '...' ? '...' : tools[suggestion].name}</a
+ >"?
+ </blockquote>
+ </div>
+{:else}
+ <HeadTitle route={tools[tool].name} path={`/tools?tool=${tool}`} />
+
+ {#if tool === 'activity_history'}
+ <ActivityHistory user={data.user} />
+ {:else if tool === 'wrapped'}
+ <Wrapped user={data.user} />
+ {:else if tool === 'discussions'}
+ <EpisodeDiscussionCollector />
+ {:else if tool === 'birthdays'}
+ <CharacterBirthdays />
+ {:else if tool === 'sequel_spy'}
+ <SequelSpy user={data.user} />
+ {:else if tool === 'random_follower'}
+ <RandomFollower />
+ {:else if tool === 'dump_profile'}
+ <DumpProfile />
+ {/if}
+{/if}
diff --git a/src/routes/wrapped/+server.ts b/src/routes/wrapped/+server.ts
index 2eee34f0..cc070af0 100644
--- a/src/routes/wrapped/+server.ts
+++ b/src/routes/wrapped/+server.ts
@@ -1,7 +1,9 @@
+import root from '$lib/Utility/root.js';
+
export const GET = ({ url }) =>
Response.redirect(
- `https://due.moe/tools?tool=wrapped${
- url.searchParams.values.length > 0 ? `&${url.searchParams.toString()}` : ''
- }`,
- 301
+ root(
+ `/tools/wrapped${url.searchParams.values.length > 0 ? `&${url.searchParams.toString()}` : ''}`
+ ),
+ 307
);