diff options
| author | Fuwn <[email protected]> | 2023-10-24 19:11:21 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2023-10-24 19:11:21 -0700 |
| commit | 7051fd67e98be0166d4f093f111dfa5dfa28bc0a (patch) | |
| tree | 61395da21f35395a88950428990f21ca9c12d261 /src | |
| parent | feat: badge wall (diff) | |
| parent | chore(git): ignore data folder (diff) | |
| download | due.moe-7051fd67e98be0166d4f093f111dfa5dfa28bc0a.tar.xz due.moe-7051fd67e98be0166d4f093f111dfa5dfa28bc0a.zip | |
merge: main into badges
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/AniList/forum.ts | 58 | ||||
| -rw-r--r-- | src/lib/AniList/user.ts | 5 | ||||
| -rw-r--r-- | src/lib/List/Anime/CleanAnimeList.svelte | 10 | ||||
| -rw-r--r-- | src/lib/List/CleanMangaList.svelte | 2 | ||||
| -rw-r--r-- | src/lib/List/Template/MangaListTemplate.svelte | 4 | ||||
| -rw-r--r-- | src/lib/Media/manga.ts | 13 | ||||
| -rw-r--r-- | src/lib/Settings/SettingCheckboxToggle.svelte | 54 | ||||
| -rw-r--r-- | src/lib/Tools/EpisodeDiscussionCollector.svelte | 44 | ||||
| -rw-r--r-- | src/lib/userBadgesDatabase.ts | 8 | ||||
| -rw-r--r-- | src/routes/+layout.svelte | 10 | ||||
| -rw-r--r-- | src/routes/@[user]/+page.server.ts | 5 | ||||
| -rw-r--r-- | src/routes/@[user]/+page.svelte | 45 | ||||
| -rw-r--r-- | src/routes/feeds/activity-notifications/+server.ts | 6 | ||||
| -rw-r--r-- | src/routes/settings/+page.svelte | 99 | ||||
| -rw-r--r-- | src/routes/tools/+page.svelte | 23 | ||||
| -rw-r--r-- | src/routes/user/[user]/+page.svelte | 44 | ||||
| -rw-r--r-- | src/routes/user/[user]/badges/+page.svelte | 207 | ||||
| -rw-r--r-- | src/stores/settings.ts | 8 |
18 files changed, 305 insertions, 340 deletions
diff --git a/src/lib/AniList/forum.ts b/src/lib/AniList/forum.ts new file mode 100644 index 00000000..6b95fa07 --- /dev/null +++ b/src/lib/AniList/forum.ts @@ -0,0 +1,58 @@ +import { user } from './user'; + +export interface Thread { + id: number; + title: string; + createdAt: number; +} + +export interface ThreadPage { + data: { + Page: { + threads: Thread[]; + pageInfo: { + hasNextPage: boolean; + currentPage: number; + }; + }; + }; +} + +const threadPage = async (page: number, userId: number): Promise<ThreadPage> => + await ( + await fetch('https://graphql.anilist.co', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json' + }, + body: JSON.stringify({ + query: `{ Page(perPage: 50, page: ${page}) { + threads(userId: ${userId}) { id title createdAt } + pageInfo { hasNextPage } +} }` + }) + }) + ).json(); + +export const threads = async (username: string): Promise<Thread[]> => { + const allThreads = []; + const userId = (await user(username)).id; + let page = 1; + let currentPage = await threadPage(page, userId); + + for (const thread of currentPage.data.Page.threads) { + allThreads.push(thread); + } + + while (currentPage.data.Page.pageInfo.hasNextPage) { + page += 1; + currentPage = await threadPage(page, userId); + + for (const thread of currentPage.data.Page.threads) { + allThreads.push(thread); + } + } + + return allThreads; +}; diff --git a/src/lib/AniList/user.ts b/src/lib/AniList/user.ts index dd9995fd..fdc98a58 100644 --- a/src/lib/AniList/user.ts +++ b/src/lib/AniList/user.ts @@ -15,6 +15,9 @@ export interface User { volumesRead: number; }; }; + avatar: { + large: string; + }; } export const user = async (username: string): Promise<User> => { @@ -28,7 +31,7 @@ export const user = async (username: string): Promise<User> => { }, body: JSON.stringify({ query: `{ User(name: "${username}") { - name id statistics { + name id avatar { large } statistics { anime { count meanScore minutesWatched episodesWatched } diff --git a/src/lib/List/Anime/CleanAnimeList.svelte b/src/lib/List/Anime/CleanAnimeList.svelte index ffd34788..30443e83 100644 --- a/src/lib/List/Anime/CleanAnimeList.svelte +++ b/src/lib/List/Anime/CleanAnimeList.svelte @@ -37,14 +37,14 @@ {@const progress = (anime.mediaListEntry || { progress: 0 }).progress} <li> <a - href={$settings.linkToAniList - ? `https://anilist.co/anime/${anime.id}` - : `https://www.livechart.me/search?q=${ + href={$settings.linkToLiveChart + ? `https://www.livechart.me/search?q=${ anime.title.native || anime.title.english || anime.title.romaji - }`} + }` + : `https://anilist.co/anime/${anime.id}`} target="_blank" > - {#if lastUpdatedMedia === anime.id} + {#if lastUpdatedMedia === anime.id && anime.episodes !== progress} <span style="color: lightcoral"> {anime.title.english || anime.title.romaji || anime.title.native} </span> diff --git a/src/lib/List/CleanMangaList.svelte b/src/lib/List/CleanMangaList.svelte index a56a1c81..180c12f2 100644 --- a/src/lib/List/CleanMangaList.svelte +++ b/src/lib/List/CleanMangaList.svelte @@ -33,7 +33,7 @@ <li> <a href={`https://anilist.co/manga/${manga.id}`} target="_blank"> - {#if lastUpdatedMedia === manga.id} + {#if lastUpdatedMedia === manga.id && manga.chapters !== progress} <span style="color: lightcoral"> {manga.title.english || manga.title.romaji || manga.title.native} </span> diff --git a/src/lib/List/Template/MangaListTemplate.svelte b/src/lib/List/Template/MangaListTemplate.svelte index 9823f97f..a0b48bdf 100644 --- a/src/lib/List/Template/MangaListTemplate.svelte +++ b/src/lib/List/Template/MangaListTemplate.svelte @@ -69,7 +69,9 @@ ($settings.displayNotStarted === true ? 0 : 1) ); let finalMedia = releasingMedia; - const chapterPromises = finalMedia.map((m: Media) => chapterCount(identity, m)); + const chapterPromises = finalMedia.map((m: Media) => + chapterCount(identity, m, $settings.disableGuessing) + ); const chapterCounts = await Promise.all(chapterPromises); finalMedia.forEach((m: Media, i) => { diff --git a/src/lib/Media/manga.ts b/src/lib/Media/manga.ts index 9d0e08a6..3c0cf837 100644 --- a/src/lib/Media/manga.ts +++ b/src/lib/Media/manga.ts @@ -14,7 +14,8 @@ export const pruneAllManga = async () => { export const chapterCount = async ( identity: UserIdentity, manga: Media, - preferActivity = false + disableGuessing: boolean + // preferActivity = false ): Promise<number | null> => { const chapters = await chapterDatabase.chapters.get(manga.id); @@ -22,11 +23,15 @@ export const chapterCount = async ( return chapters.chapters === -1 ? null : chapters.chapters; } - if (preferActivity) { - return await recentMediaActivities(identity, manga); - } + // if (preferActivity) { + // return await recentMediaActivities(identity, manga); + // } const tryRecentMediaActivities = async () => { + if (disableGuessing) { + return null; + } + const anilistData = await recentMediaActivities(identity, manga); await chapterDatabase.chapters.put({ diff --git a/src/lib/Settings/SettingCheckboxToggle.svelte b/src/lib/Settings/SettingCheckboxToggle.svelte new file mode 100644 index 00000000..ab603278 --- /dev/null +++ b/src/lib/Settings/SettingCheckboxToggle.svelte @@ -0,0 +1,54 @@ +<script lang="ts"> + import settings, { type Settings } from '../../stores/settings'; + + type BooleanSettingsKeys<T> = { + [K in keyof T]: T[K] extends boolean ? K : never; + }; + type SettingsBooleanKeys = BooleanSettingsKeys<Settings>; + + export let sectionBreak = false; + export let disabled = false; + export let text: string; + export let setting: SettingsBooleanKeys[keyof SettingsBooleanKeys]; + + // const toggler = (key: keyof Settings) => [ + // () => + // settings.update((s) => { + // (s[key] as boolean) = true; + + // $settings = s; + + // return s; + // }), + // () => + // settings.update((s) => { + // (s[key] as boolean) = false; + + // $settings = s; + + // return s; + // }) + // ]; + + const check = (e: Event & { currentTarget: EventTarget & HTMLInputElement }): void => { + settings.setKey(setting, (e.target as HTMLInputElement).checked); + }; +</script> + +<input type="checkbox" on:change={check} bind:checked={$settings[setting]} /> + +{#if disabled} + <strike> + {text} + </strike> + <slot /> +{:else} + {text} + <slot /> +{/if} + +<br /> + +{#if sectionBreak} + <p /> +{/if} diff --git a/src/lib/Tools/EpisodeDiscussionCollector.svelte b/src/lib/Tools/EpisodeDiscussionCollector.svelte new file mode 100644 index 00000000..a9acd8ae --- /dev/null +++ b/src/lib/Tools/EpisodeDiscussionCollector.svelte @@ -0,0 +1,44 @@ +<script lang="ts"> + import { threads } from '$lib/AniList/forum'; + + let searchInput = ''; + let searchInputFinal = ''; +</script> + +<p> + <input type="text" placeholder="Username" bind:value={searchInput} /> + <a href={`#`} on:click={() => (searchInputFinal = searchInput)}>Search</a> +</p> + +{#if searchInputFinal !== ''} + {#await threads(searchInputFinal)} + Loading ... + {:then threads} + <ul> + {#each threads + .filter((thread) => thread.title.includes('[Spoilers]') && thread.title.includes('Episode')) + .sort((a, b) => b.createdAt - a.createdAt) as thread} + <li> + <a href={`https://anilist.co/forum/thread/${thread.id}`} target="_blank"> + {thread.title.replace('[Spoilers]', '')} + </a> + </li> + {/each} + </ul> + {:catch} + <p> + Threads could not be loaded. You might have been <a + href="https://en.wikipedia.org/wiki/Rate_limiting" + target="_blank">rate limited</a + >. + </p> + <p> + Try again in a few minutes. If the problem persists, please contact <a + href="https://anilist.co/user/fuwn" + target="_blank">@fuwn</a + > on AniList. + </p> + {/await} +{:else} + <p>Enter a username to search for to continue.</p> +{/if} diff --git a/src/lib/userBadgesDatabase.ts b/src/lib/userBadgesDatabase.ts index c129770e..78655cd3 100644 --- a/src/lib/userBadgesDatabase.ts +++ b/src/lib/userBadgesDatabase.ts @@ -8,16 +8,16 @@ export interface Badge { id?: number; } -const database = new Database('./due_moe.sqlite3', { +const database = new Database('./data/due_moe.sqlite3', { verbose: dev ? console.log : undefined }); database.exec(`create table if not exists user_badges ( id integer primary key, user_id integer not null, - post text not null, - image text not null, - description text default null, + post text(1000) not null, + image text(1000) not null, + description text(1000) default null, time timestamp default current_timestamp )`); diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 19df3f1c..20ae9ef4 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -52,11 +52,17 @@ <p id="desktop-navigation-bar"> 「 <a href="/">Home</a> • <a href="/completed">Completed</a> • <a href="/updates">Manga & LN Updates</a> • - <a href="/tools">Tools</a> • <a href="/settings">Settings</a> 」 + <a href="/tools">Tools</a> • {#if data.user} + <a href={`/user/${currentUserIdentity.name}`}>Profile</a> • + {/if} <a href="/settings">Settings</a> 」 </p> <div id="mobile-navigation-bar"> - <a href="/">Home</a> • <a href="/completed">Completed</a> • <a href="/tools">Tools</a><br /> + <a href="/">Home</a> • <a href="/completed">Completed</a> • <a href="/tools">Tools</a> + {#if data.user} + • <a href={`/user/${currentUserIdentity.name}`}>Profile</a> + {/if} + <br /> <a href="/settings">Settings</a> <a href="/updates">Manga & LN Updates</a> diff --git a/src/routes/@[user]/+page.server.ts b/src/routes/@[user]/+page.server.ts deleted file mode 100644 index 76d2d889..00000000 --- a/src/routes/@[user]/+page.server.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const load = ({ params }) => { - return { - username: params.user - }; -}; diff --git a/src/routes/@[user]/+page.svelte b/src/routes/@[user]/+page.svelte deleted file mode 100644 index 1763193a..00000000 --- a/src/routes/@[user]/+page.svelte +++ /dev/null @@ -1,45 +0,0 @@ -<script lang="ts"> - import { user, type User } from '$lib/AniList/user'; - import { onMount } from 'svelte'; - - export let data; - - let userData: User | undefined = undefined; - - onMount(() => { - user(data.username).then((profile) => { - userData = profile; - }); - }); - - // 8.5827814569536423841e0 -</script> - -{#if userData === null} - Could not load user profile for <a - href={`https://anilist.co/user/${data.username}`} - target="_blank">@{data.username}</a - >. - - <p /> - - Does this user exist? -{:else if userData === undefined} - Loading ... -{:else} - <a href={`https://anilist.co/user/${userData.name}`} target="_blank" title={String(userData.id)} - >@{userData.name}</a - > - - <p /> - - This user has watched {(userData.statistics.anime.minutesWatched / 60 / 24).toFixed(1)} days of anime - and read - {((userData.statistics.manga.chaptersRead * 8.58) / 60 / 24).toFixed(1)} days of manga. -{/if} - -<p /> - -<hr /> - -This page is under construction! diff --git a/src/routes/feeds/activity-notifications/+server.ts b/src/routes/feeds/activity-notifications/+server.ts index 06c55ace..dd4ee0b4 100644 --- a/src/routes/feeds/activity-notifications/+server.ts +++ b/src/routes/feeds/activity-notifications/+server.ts @@ -1,5 +1,9 @@ import { notifications, type Notification } from '$lib/AniList/notifications'; +const htmlEncode = (input: string) => { + return input.replace(/[\u00A0-\u9999<>&]/g, (i) => '&#' + i.charCodeAt(0) + ';'); +}; + const render = (posts: Notification[] = []) => `<?xml version="1.0" encoding="UTF-8" ?> <rss version="2.0" @@ -41,7 +45,7 @@ const render = (posts: Notification[] = []) => `<?xml version="1.0" encoding="UT return `<item> <guid isPermaLink="false">${notification.id}</guid> -<title>${title}</title> +<title>${htmlEncode(title)}</title> <link>${link}</link> <author>${notification.user.name}</author> <media:thumbnail url="${notification.user.avatar.large}" /> diff --git a/src/routes/settings/+page.svelte b/src/routes/settings/+page.svelte index b0885436..b8d368cc 100644 --- a/src/routes/settings/+page.svelte +++ b/src/routes/settings/+page.svelte @@ -5,7 +5,7 @@ import manga from '../../stores/manga'; import anime from '../../stores/anime'; import settings from '../../stores/settings'; - import SettingToggle from '$lib/Settings/SettingToggle.svelte'; + import SettingCheckboxToggle from '$lib/Settings/SettingCheckboxToggle.svelte'; import SettingHint from '$lib/Settings/SettingHint.svelte'; import { pruneAllManga } from '$lib/Media/manga'; @@ -44,55 +44,32 @@ <details open> <summary>Display</summary> - <SettingToggle setting={'forceLightTheme'} on={'Use preferred'} off={'Force light'}> - theme - </SettingToggle> - <SettingToggle - setting={'linkToAniList'} - on={'Link anime to LiveChart.me'} - off={'Link anime to AniList'} - /> - <SettingToggle setting={'displayPausedMedia'} on={'Hide'} off={'Show'}> - paused media - </SettingToggle> - <SettingToggle - setting={'limitListHeight'} - on={'Display full list area'} - off={'Limit list area to screen'} - /> - <SettingToggle setting={'displaySocialButton'} on={'Hide'} off={'Show'} sectionBreak> - social button - </SettingToggle> - - <p /> - - <SettingToggle setting={'displayUnresolved'} on={'Hide'} off={'Show'}>unresolved</SettingToggle> - <SettingHint>Displays unresolved chapter counts as "?"</SettingHint> - - <p /> - - <SettingToggle setting={'displayNotStarted'} on={'Hide'} off={'Show'}> - media with zero progress - </SettingToggle> - <SettingHint> - May cause <a href="https://en.wikipedia.org/wiki/Rate_limiting" target="_blank"> - rate-limiting - </a> depending on how much releasing manga are on your lists - </SettingHint> - - <p /> - - <SettingToggle setting={'closeAnimeByDefault'} on={'Expand'} off={'Close'}> - anime panel by default - </SettingToggle> - <SettingToggle setting={'closeMangaByDefault'} on={'Expand'} off={'Close'}> - manga panel by default - </SettingToggle> - <SettingToggle setting={'sortByDifference'}> - Sort anime by {@html !$settings.sortByDifference - ? 'difference between last watched and next episode' - : 'days left until next episode'} - </SettingToggle> + <SettingCheckboxToggle setting="forceLightTheme" text="Force light theme" /> + <SettingCheckboxToggle setting="linkToLiveChart" text="Link anime to LiveChart.me" /> + <SettingCheckboxToggle setting="displayPausedMedia" text="Show paused media" /> + <SettingCheckboxToggle setting="limitListHeight" text="Limit list area to screen" /> + <SettingCheckboxToggle setting="displaySocialButton" text="Show social button" /> + <SettingCheckboxToggle setting="displayUnresolved" text="Display unresolved media" /> + <SettingCheckboxToggle setting="displayNotStarted" text="Show media with zero progress"> + <SettingHint lineBreak> + May cause <a href="https://en.wikipedia.org/wiki/Rate_limiting" target="_blank"> + rate-limiting + </a> depending on how much releasing manga are on your lists + </SettingHint> + </SettingCheckboxToggle> + + <br /> + + <SettingCheckboxToggle setting="closeAnimeByDefault" text="Close anime panel by default" /> + <SettingCheckboxToggle setting="closeMangaByDefault" text="Close manga panel by default" /> + <SettingCheckboxToggle + setting="sortByDifference" + text="Sort anime by difference between last watched and next episode" + > + <SettingHint lineBreak> + By default, anime will be sorted by the number of days left until the next episode airs. + </SettingHint> + </SettingCheckboxToggle> </details> <p /> @@ -100,12 +77,20 @@ <details open> <summary>Calculation</summary> - <SettingToggle setting={'roundDownChapters'} on={'Maintain'} off={'Round down'}> - chapters - </SettingToggle> - <SettingHint> - 50/50.6 would {@html $settings.roundDownChapters ? '' : '<b>not</b>'} be due - </SettingHint> + <SettingCheckboxToggle setting="roundDownChapters" text="Round down chapters"> + <SettingHint lineBreak> + Round down to the nearest whole number. (e.g., 50/50.6 would <b>not</b> be due) + </SettingHint> + </SettingCheckboxToggle> + + <br /> + + <SettingCheckboxToggle setting="disableGuessing" text="Disable informed chapter estimation"> + <SettingHint lineBreak> + Enabling this setting will disable light novel chapter counts and may cause inaccuracy in + unresolved manga chapter counts + </SettingHint> + </SettingCheckboxToggle> </details> <p /> @@ -115,7 +100,7 @@ <a href={'#'} on:click={pruneUnresolved}>Re-cache <b>ALL</b> unresolved manga</a> - <p /> + <br /> <a href={'#'} on:click={pruneAllManga}>Re-cache <b>ALL</b> manga</a> <SettingHint lineBreak>Force a re-cache of all cached manga chapter counts</SettingHint> diff --git a/src/routes/tools/+page.svelte b/src/routes/tools/+page.svelte index 3976aeba..5a12fb0f 100644 --- a/src/routes/tools/+page.svelte +++ b/src/routes/tools/+page.svelte @@ -3,28 +3,33 @@ import { todaysCharacterBirthdays } from '$lib/AniList/character'; import Wrapped from '$lib/Tools/Wrapped.svelte'; import { browser } from '$app/environment'; + import EpisodeDiscussionCollector from '$lib/Tools/EpisodeDiscussionCollector.svelte'; export let data; - let tool = browser ? Number(new URLSearchParams(window.location.search).get('tool')) || 0 : 0; + const urlParameters = browser ? new URLSearchParams(window.location.search) : null; + let tool = browser && urlParameters?.size !== 0 ? urlParameters?.get('tool') : 'default'; </script> <p> <select bind:value={tool}> - <option value={0}>Tools</option> - <option value={1}>Today's Character Birthdays</option> - <option value={2}>Activity History Hole Risks</option> - <option value={3}>Wrapped (Beta)</option> + <option value="default" selected disabled hidden>Tool</option> + <option value="todays_character_birthdays">Today's Character Birthdays</option> + <option value="activity_history_hole_risks">Activity History Hole Risks</option> + <option value="wrapped">Wrapped (Beta)</option> + <option value="episode_discussion_collector">Episode Discussion Collector (Beta)</option> </select> </p> -{#if tool === 0} +{#if tool === 'default'} Select a tool to continue. -{:else if tool === 2} +{:else if tool === 'activity_history_hole_risks'} <ActivityHistory user={data.user} /> -{:else if tool === 3} +{:else if tool === 'wrapped'} <div id="wrapped"><Wrapped user={data.user} /></div> -{:else if tool === 1} +{:else if tool === 'episode_discussion_collector'} + <EpisodeDiscussionCollector /> +{:else if tool === 'todays_character_birthdays'} <ul> {#await todaysCharacterBirthdays()} <li>Loading ...</li> diff --git a/src/routes/user/[user]/+page.svelte b/src/routes/user/[user]/+page.svelte index 227ba252..858e6aec 100644 --- a/src/routes/user/[user]/+page.svelte +++ b/src/routes/user/[user]/+page.svelte @@ -27,14 +27,38 @@ {:else if userData === undefined} Loading ... {:else} - <p> - <a href={`https://anilist.co/user/${userData.name}`} target="_blank" title={String(userData.id)} - >@{userData.name}</a - > - • <a href={`/user/${userData.name}/badges`}>Badge Wall</a> - </p> - - This user has watched {(userData.statistics.anime.minutesWatched / 60 / 24).toFixed(1)} days of anime - and read - {((userData.statistics.manga.chaptersRead * 8.58) / 60 / 24).toFixed(1)} days of manga. + <div class="user-grid"> + <p> + <a + href={`https://anilist.co/user/${userData.name}`} + target="_blank" + title={String(userData.id)} + > + <img src={userData.avatar.large} alt="" width="100vw" /> + </a> + </p> + + <div> + <p> + <a + href={`https://anilist.co/user/${userData.name}`} + target="_blank" + title={String(userData.id)}>@{userData.name}</a + > + • <a href={`/user/${userData.name}/badges`}>Badge Wall</a> + </p> + + This user has watched {(userData.statistics.anime.minutesWatched / 60 / 24).toFixed(1)} days of + anime and read + {((userData.statistics.manga.chaptersRead * 8.58) / 60 / 24).toFixed(1)} days of manga. + </div> + </div> {/if} + +<style> + .user-grid { + display: flex; + flex-wrap: wrap; + column-gap: 1.5em; + } +</style> diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte index 276bf1ca..293a7ba5 100644 --- a/src/routes/user/[user]/badges/+page.svelte +++ b/src/routes/user/[user]/badges/+page.svelte @@ -8,195 +8,6 @@ let editMode = false; let currentUserIdentity: ReturnType<typeof userIdentity>; - // const badges: Badge[] = [ - // { - // post: 'https://anilist.co/activity/611973592', - // image: 'https://files.catbox.moe/6tvw17.png' - // }, - // { post: 'https://anilist.co/activity/611972285', image: 'https://files.catbox.moe/rn5qr5.png' }, - // { post: 'https://anilist.co/activity/611977824', image: 'https://i.imgur.com/DFkT4zB.png' }, - // { - // post: 'https://anilist.co/activity/612036793', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1144851101414326333/Badge2_26-08-23.png' - // }, - // { - // post: 'https://anilist.co/activity/612273794', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1144773312468234351/DOGDAY_5_v2.png' - // }, - // { post: 'https://anilist.co/activity/613961295', image: 'https://files.catbox.moe/6rebg8.png' }, - // { post: 'https://anilist.co/activity/614793182', image: 'https://imgur.com/QhJbw4l.png' }, - // { post: 'https://anilist.co/activity/615002857', image: 'https://files.catbox.moe/oc8g02.png' }, - // { post: 'https://anilist.co/activity/615426233', image: 'https://files.catbox.moe/4z226e.png' }, - // { post: 'https://anilist.co/activity/615427328', image: 'https://files.catbox.moe/tqcltp.png' }, - // { post: 'https://anilist.co/activity/615920191', image: 'https://files.catbox.moe/frw5p5.png' }, - // { post: 'https://anilist.co/activity/616629257', image: 'https://files.catbox.moe/15st7d.png' }, - // { post: 'https://anilist.co/activity/617442391', image: 'https://i.imgur.com/aHkSRCz.gif' }, - // { - // post: 'https://anilist.co/activity/617445099', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1148663790452346961/chondyunbday.gif' - // }, - // { - // post: 'https://anilist.co/activity/617616590', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1148678438551568444/Badge_3.png' - // }, - // { post: 'https://anilist.co/activity/617842237', image: 'https://i.imgur.com/Zx4uiAz.gif' }, - // { post: 'https://anilist.co/activity/618296369', image: 'https://i.imgur.com/V6UsqYI.gif' }, - // { post: 'https://anilist.co/activity/618664650', image: 'https://imgur.com/x98vT7p.png' }, - // { post: 'https://anilist.co/activity/619306471', image: 'https://i.imgur.com/GppbpqE.png' }, - // { post: 'https://anilist.co/activity/619657632', image: 'https://files.catbox.moe/barla6.png' }, - // { post: 'https://anilist.co/activity/619659847', image: 'https://i.imgur.com/e81dgSB.gif' }, - // { post: 'https://anilist.co/activity/619661657', image: 'https://i.imgur.com/S0fSeD4.gif' }, - // { post: 'https://anilist.co/activity/619664832', image: 'https://i.imgur.com/EXNQE3n.gif' }, - // { - // post: 'https://anilist.co/activity/619764622', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1151314632942817290/persona_5_3.png' - // }, - // { post: 'https://anilist.co/activity/620025361', image: 'https://i.imgur.com/DmEl13g.gif' }, - // { post: 'https://anilist.co/activity/620125206', image: 'https://i.imgur.com/SmzhGyu.gif' }, - // { post: 'https://anilist.co/activity/620125762', image: 'https://i.imgur.com/38I5gUM.gif' }, - // { post: 'https://anilist.co/activity/620126356', image: 'https://i.imgur.com/9I7Xggm.gif' }, - // { post: 'https://anilist.co/activity/620600819', image: 'https://i.imgur.com/nHREaUc.png' }, - // { post: 'https://anilist.co/activity/620989269', image: 'https://imgur.com/XjhyOHU.png' }, - // { - // post: 'https://anilist.co/activity/621253410', - // image: - // 'https://cdn.discordapp.com/attachments/1139717993845239849/1147701375707381760/0028HLA.png' - // }, - // { post: 'https://anilist.co/activity/621787546', image: 'https://i.imgur.com/tn5yVsk.gif' }, - // { - // post: 'https://anilist.co/activity/621789551', - // image: 'https://i.postimg.cc/Z5325GDx/ota-day-otaku-academia-ittle-witch-academia.png' - // }, - // { post: 'https://anilist.co/activity/622236894', image: 'https://i.imgur.com/vicrIfS.png' }, - // { post: 'https://anilist.co/activity/622237728', image: 'https://i.imgur.com/TLSC65A.jpg' }, - // { post: 'https://anilist.co/activity/623156563', image: 'https://files.catbox.moe/ujf0ym.png' }, - // { post: 'https://anilist.co/activity/623990926', image: 'https://files.catbox.moe/gkalwm.png' }, - // { - // post: 'https://anilist.co/activity/623995806', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1154888665638649916/monikabday.png' - // }, - // { post: 'https://anilist.co/activity/624542383', image: 'https://files.catbox.moe/9tzs66.png' }, - // { - // post: 'https://anilist.co/activity/624542383', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1154540564671377459/EMILIA_BADGE_2.png' - // }, - // { post: 'https://anilist.co/activity/624543474', image: 'https://imgur.com/WQuXh6g.png' }, - // { - // post: 'https://anilist.co/activity/624544489', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1154736156093726870/fsdfwefewfwf.png' - // }, - // { - // post: 'https://anilist.co/activity/624545233', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1153606849464111134/katoubadge1.png' - // }, - // { post: 'https://anilist.co/activity/624548754', image: 'https://imgur.com/j5aqX5w.png' }, - // { - // post: 'https://anilist.co/activity/624549956', - // image: - // 'https://cdn.discordapp.com/attachments/1152962059126972417/1154745849465811015/Day_of_Mid_2.png' - // }, - // { post: 'https://anilist.co/activity/626483669', image: 'https://files.catbox.moe/lz0r48.png' }, - // { - // post: 'https://anilist.co/activity/626483669', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1156396779332456538/jojobdayb.png' - // }, - // { - // post: 'https://anilist.co/activity/626770819', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1156582649779994664/kikurihiroi.png' - // }, - // { post: 'https://anilist.co/activity/626772329', image: 'https://i.imgur.com/P09v438.gif' }, - // { - // post: 'https://anilist.co/activity/627283326', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1157124224197083226/coffeeday2.png' - // }, - // { - // post: 'https://anilist.co/activity/628202238', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1156472801457340506/rinshima1.png' - // }, - // { - // post: 'https://anilist.co/activity/628202913', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1157574135069806592/Badge-1_-_01_10_23.png' - // }, - // { - // post: 'https://anilist.co/activity/628305048', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1157650582094479370/SakeDay2.png' - // }, - // { post: 'https://anilist.co/activity/629168789', image: 'https://files.catbox.moe/0mwudd.png' }, - // { post: 'https://anilist.co/activity/629592629', image: 'https://files.catbox.moe/pyjy0z.png' }, - // { post: 'https://anilist.co/activity/629593251', image: 'https://files.catbox.moe/e9xx50.png' }, - // { post: 'https://anilist.co/activity/630084060', image: 'https://i.imgur.com/zVU0gie.gif' }, - // { post: 'https://anilist.co/activity/630462423', image: 'https://files.catbox.moe/b63wxi.png' }, - // { - // post: 'https://anilist.co/activity/630464366', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1158527481486266490/codegeass1.png' - // }, - // { post: 'https://anilist.co/activity/630996180', image: 'https://files.catbox.moe/ap15dx.png' }, - // { post: 'https://anilist.co/activity/631494022', image: 'https://files.catbox.moe/fw4rqx.png' }, - // { - // post: 'https://anilist.co/activity/631503062', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1158787682231660684/rize1.png' - // }, - // { - // post: 'https://anilist.co/activity/632259051', - // image: - // 'https://cdn.discordapp.com/attachments/1154438205731524638/1158943217459412992/Luna_Bday2023_Axel5.png' - // }, - // { post: 'https://anilist.co/activity/632260829', image: 'https://files.catbox.moe/ighico.png' }, - // { post: 'https://anilist.co/activity/632311940', image: 'https://files.catbox.moe/ukv6tv.png' }, - // { - // post: 'https://anilist.co/activity/632311940', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1160915207711895593/Gintoki_2.png' - // }, - // { - // post: 'https://anilist.co/activity/632407688', - // image: - // 'https://cdn.discordapp.com/attachments/1136989514653519924/1159856849735127110/Nishinoya_1.png' - // }, - // { post: 'https://anilist.co/activity/632832412', image: 'https://files.catbox.moe/9lk6s1.png' }, - // { post: 'https://anilist.co/activity/633710355', image: 'https://i.imgur.com/JmpriDr.gif' }, - // { post: 'https://anilist.co/activity/633710743', image: 'https://files.catbox.moe/it9d7q.png' }, - // { - // post: 'https://anilist.co/activity/633711260', - // image: - // 'https://cdn.discordapp.com/attachments/1118627570074800264/1160674827670134804/Sonia1.png' - // }, - // { post: 'https://anilist.co/activity/634118108', image: 'https://files.catbox.moe/tzudpj.png' }, - // { - // post: 'https://anilist.co/activity/634119722', - // image: - // 'https://cdn.discordapp.com/attachments/1085425937933418578/1162583650840354846/Mystery_Day_badge_4.png' - // } - // ]; - - // onMount(async () => { - // const id = (await user(data.username)).id; - - // for (const badge of badges) { - // await fetch(`/api/badges-add?id=${id}`, { - // method: 'POST', - // body: JSON.stringify(badge) - // }); - // } - // }); - onMount(async () => { if (data.user) { currentUserIdentity = userIdentity(data.user); @@ -258,9 +69,21 @@ </p> <p> - <input type="text" placeholder="Image URL" name="image_url" /> - <input type="text" placeholder="Activity URL" name="activity_url" /> - <input type="text" placeholder="Description (Optional)" name="description" /> + <input type="text" placeholder="Image URL" name="image_url" minlength="1" maxlength="1000" /> + <input + type="text" + placeholder="Activity URL" + name="activity_url" + minlength="1" + maxlength="1000" + /> + <input + type="text" + placeholder="Description (Optional)" + name="description" + minlength="1" + maxlength="1000" + /> <a href={`#`} on:click={submitBadge}>Add Badge</a> </p> {/if} diff --git a/src/stores/settings.ts b/src/stores/settings.ts index 0c9742ee..5ffae4f5 100644 --- a/src/stores/settings.ts +++ b/src/stores/settings.ts @@ -11,10 +11,11 @@ export interface Settings { roundDownChapters: boolean; sortByDifference: boolean; forceLightTheme: boolean; - linkToAniList: boolean; + linkToLiveChart: boolean; displayPausedMedia: boolean; limitListHeight: boolean; displaySocialButton: boolean; + disableGuessing: boolean; } const defaultSettings: Settings = { @@ -27,10 +28,11 @@ const defaultSettings: Settings = { roundDownChapters: true, sortByDifference: false, forceLightTheme: false, - linkToAniList: true, + linkToLiveChart: true, displayPausedMedia: true, limitListHeight: false, - displaySocialButton: false + displaySocialButton: false, + disableGuessing: false }; const createStore = () => { |