aboutsummaryrefslogtreecommitdiff
path: root/src/graphql
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphql')
-rw-r--r--src/graphql/anime/index.ts4
-rw-r--r--src/graphql/anime/resolvers.ts45
-rw-r--r--src/graphql/anime/schema.graphql30
-rw-r--r--src/graphql/client.ts4
-rw-r--r--src/graphql/server.ts6
-rw-r--r--src/graphql/user/index.ts4
-rw-r--r--src/graphql/user/resolvers.ts438
-rw-r--r--src/graphql/user/schema.graphql98
8 files changed, 333 insertions, 296 deletions
diff --git a/src/graphql/anime/index.ts b/src/graphql/anime/index.ts
index 925a7ece..d5eef7f2 100644
--- a/src/graphql/anime/index.ts
+++ b/src/graphql/anime/index.ts
@@ -1,4 +1,4 @@
-import typeDefs from './schema.graphql?raw';
-import { resolvers } from './resolvers';
+import typeDefs from "./schema.graphql?raw";
+import { resolvers } from "./resolvers";
export default { typeDefs, resolvers };
diff --git a/src/graphql/anime/resolvers.ts b/src/graphql/anime/resolvers.ts
index f2fc4b61..2b897eda 100644
--- a/src/graphql/anime/resolvers.ts
+++ b/src/graphql/anime/resolvers.ts
@@ -1,27 +1,32 @@
-import type { WithIndex } from '../$types';
-import type { Resolvers as RootResolvers } from '../$types';
+import type { WithIndex } from "../$types";
+import type { Resolvers as RootResolvers } from "../$types";
type AnimeResolvers = Pick<
- RootResolvers,
- 'Query' | 'Anime' | 'Subtitles' | 'SubtitleSchedule' | 'Subtitle'
+ RootResolvers,
+ "Query" | "Anime" | "Subtitles" | "SubtitleSchedule" | "Subtitle"
>;
export const resolvers: WithIndex<AnimeResolvers> = {
- Query: {
- Anime: async (_, args) => {
- const timezone = args.timezone || 'Asia/Tokyo';
+ Query: {
+ Anime: async (_, args) => {
+ const timezone = args.timezone || "Asia/Tokyo";
- return {
- subtitles: {
- timezone,
- schedule: Object.fromEntries(
- Object.entries(
- (await (await fetch(`https://subsplease.org/api/?f=schedule&tz=${timezone}`)).json())
- .schedule
- ).map(([key, value]) => [key.toLowerCase(), value])
- )
- }
- };
- }
- }
+ return {
+ subtitles: {
+ timezone,
+ schedule: Object.fromEntries(
+ Object.entries(
+ (
+ await (
+ await fetch(
+ `https://subsplease.org/api/?f=schedule&tz=${timezone}`,
+ )
+ ).json()
+ ).schedule,
+ ).map(([key, value]) => [key.toLowerCase(), value]),
+ ),
+ },
+ };
+ },
+ },
};
diff --git a/src/graphql/anime/schema.graphql b/src/graphql/anime/schema.graphql
index a0415944..d5774966 100644
--- a/src/graphql/anime/schema.graphql
+++ b/src/graphql/anime/schema.graphql
@@ -1,29 +1,29 @@
type Query {
- Anime(timezone: String): Anime!
+ Anime(timezone: String): Anime!
}
type Anime {
- subtitles: Subtitles
+ subtitles: Subtitles
}
type Subtitles {
- timezone: String
- schedule: SubtitleSchedule
+ timezone: String
+ schedule: SubtitleSchedule
}
type SubtitleSchedule {
- monday: [Subtitle]
- tuesday: [Subtitle]
- wednesday: [Subtitle]
- thursday: [Subtitle]
- friday: [Subtitle]
- saturday: [Subtitle]
- sunday: [Subtitle]
+ monday: [Subtitle]
+ tuesday: [Subtitle]
+ wednesday: [Subtitle]
+ thursday: [Subtitle]
+ friday: [Subtitle]
+ saturday: [Subtitle]
+ sunday: [Subtitle]
}
type Subtitle {
- title: String
- page: String
- image_url: String
- time: String
+ title: String
+ page: String
+ image_url: String
+ time: String
}
diff --git a/src/graphql/client.ts b/src/graphql/client.ts
index 367b8381..071c3097 100644
--- a/src/graphql/client.ts
+++ b/src/graphql/client.ts
@@ -1,3 +1,3 @@
-import { HoudiniClient } from '$houdini';
+import { HoudiniClient } from "$houdini";
-export default new HoudiniClient({ url: '/graphql' });
+export default new HoudiniClient({ url: "/graphql" });
diff --git a/src/graphql/server.ts b/src/graphql/server.ts
index 2dc183dc..f5731080 100644
--- a/src/graphql/server.ts
+++ b/src/graphql/server.ts
@@ -1,6 +1,6 @@
-import { createSchema, createServer } from 'sveltekit-graphql';
-import userModule from './user';
-import animeModule from './anime';
+import { createSchema, createServer } from "sveltekit-graphql";
+import userModule from "./user";
+import animeModule from "./anime";
const schema = createSchema([userModule, animeModule]);
const server = createServer(schema);
diff --git a/src/graphql/user/index.ts b/src/graphql/user/index.ts
index 925a7ece..d5eef7f2 100644
--- a/src/graphql/user/index.ts
+++ b/src/graphql/user/index.ts
@@ -1,4 +1,4 @@
-import typeDefs from './schema.graphql?raw';
-import { resolvers } from './resolvers';
+import typeDefs from "./schema.graphql?raw";
+import { resolvers } from "./resolvers";
export default { typeDefs, resolvers };
diff --git a/src/graphql/user/resolvers.ts b/src/graphql/user/resolvers.ts
index 879d066d..986b9684 100644
--- a/src/graphql/user/resolvers.ts
+++ b/src/graphql/user/resolvers.ts
@@ -1,244 +1,276 @@
-import { userIdentity, type UserIdentity } from '$lib/Data/AniList/identity';
+import { userIdentity, type UserIdentity } from "$lib/Data/AniList/identity";
import {
- addUserBadge,
- getUserBadges,
- removeAllUserBadges,
- removeUserBadge,
- setShadowHidden,
- setShadowHiddenBadge,
- updateUserBadge,
- type Badge as DatabaseBadge
-} from '$lib/Database/SB/User/badges';
-import type { WithIndex } from '../$types';
-import type { Resolvers as RootResolvers, Badge } from '../$types';
-import type { RequestEvent } from '@sveltejs/kit';
+ addUserBadge,
+ getUserBadges,
+ removeAllUserBadges,
+ removeUserBadge,
+ setShadowHidden,
+ setShadowHiddenBadge,
+ updateUserBadge,
+ type Badge as DatabaseBadge,
+} from "$lib/Database/SB/User/badges";
+import type { WithIndex } from "../$types";
+import type { Resolvers as RootResolvers, Badge } from "../$types";
+import type { RequestEvent } from "@sveltejs/kit";
import {
- getUserPreferences,
- setBiography,
- setCSS,
- setPinnedBadgeWallCategories,
- toggleHideAWCBadges,
- toggleHideMissingBadges,
- toggleHololiveStreamPinning,
- togglePinnedBadgeWallCategory,
- type UserPreferences
-} from '$lib/Database/SB/User/preferences';
-import privilegedUser from '$lib/Utility/privilegedUser';
+ getUserPreferences,
+ setBiography,
+ setCSS,
+ setPinnedBadgeWallCategories,
+ toggleHideAWCBadges,
+ toggleHideMissingBadges,
+ toggleHololiveStreamPinning,
+ togglePinnedBadgeWallCategory,
+ type UserPreferences,
+} from "$lib/Database/SB/User/preferences";
+import privilegedUser from "$lib/Utility/privilegedUser";
type Context = RequestEvent<Partial<Record<string, string>>, string | null>;
-type UserResolvers = Pick<RootResolvers, 'Query' | 'Mutation' | 'User' | 'Badge' | 'Preferences'>;
+type UserResolvers = Pick<
+ RootResolvers,
+ "Query" | "Mutation" | "User" | "Badge" | "Preferences"
+>;
const toGraphQLBadges = (databaseBadges: DatabaseBadge[]): Badge[] =>
- databaseBadges.map((databaseBadge) => ({
- id: databaseBadge.id ?? 0,
- post: databaseBadge.post ?? '',
- image: databaseBadge.image ?? '',
- time: databaseBadge.time ?? new Date().toISOString(),
- hidden: databaseBadge.hidden ?? false,
- shadow_hidden: databaseBadge.shadow_hidden ?? false,
- click_count: databaseBadge.click_count ?? 0,
- category: databaseBadge.category ?? null,
- description: databaseBadge.description ?? null,
- source: databaseBadge.source ?? null,
- designer: databaseBadge.designer ?? null
- }));
+ databaseBadges.map((databaseBadge) => ({
+ id: databaseBadge.id ?? 0,
+ post: databaseBadge.post ?? "",
+ image: databaseBadge.image ?? "",
+ time: databaseBadge.time ?? new Date().toISOString(),
+ hidden: databaseBadge.hidden ?? false,
+ shadow_hidden: databaseBadge.shadow_hidden ?? false,
+ click_count: databaseBadge.click_count ?? 0,
+ category: databaseBadge.category ?? null,
+ description: databaseBadge.description ?? null,
+ source: databaseBadge.source ?? null,
+ designer: databaseBadge.designer ?? null,
+ }));
const auth = async (context: Context) => {
- const userCookie = context.cookies.get('user');
+ const userCookie = context.cookies.get("user");
- if (!userCookie) return Error('Unauthorised');
+ if (!userCookie) return Error("Unauthorised");
- const user = JSON.parse(userCookie);
+ const user = JSON.parse(userCookie);
- return await userIdentity({
- tokenType: user['token_type'],
- expiresIn: user['expires_in'],
- accessToken: user['access_token'],
- refreshToken: user['refresh_token']
- });
+ return await userIdentity({
+ tokenType: user["token_type"],
+ expiresIn: user["expires_in"],
+ accessToken: user["access_token"],
+ refreshToken: user["refresh_token"],
+ });
};
const authenticatedBadgesOperation = async (
- context: Context,
- operation: (identity: UserIdentity, authorised: boolean) => Promise<unknown>
+ context: Context,
+ operation: (identity: UserIdentity, authorised: boolean) => Promise<unknown>,
) => {
- const identity = await auth(context);
+ const identity = await auth(context);
- if (identity instanceof Error) throw new Error('Unauthorized');
+ if (identity instanceof Error) throw new Error("Unauthorized");
- const authorised = privilegedUser(identity.id);
+ const authorised = privilegedUser(identity.id);
- await operation(identity, authorised);
+ await operation(identity, authorised);
- const databaseBadges = await getUserBadges(identity.id);
- const badges = toGraphQLBadges(databaseBadges);
+ const databaseBadges = await getUserBadges(identity.id);
+ const badges = toGraphQLBadges(databaseBadges);
- return {
- id: identity.id,
- badges,
- preferences: null,
- badgesCount: badges.length
- };
+ return {
+ id: identity.id,
+ badges,
+ preferences: null,
+ badgesCount: badges.length,
+ };
};
const authenticatedPreferencesOperation = async (
- context: Context,
- operation: (identity: UserIdentity, authorised: boolean) => Promise<UserPreferences | null>
+ context: Context,
+ operation: (
+ identity: UserIdentity,
+ authorised: boolean,
+ ) => Promise<UserPreferences | null>,
) => {
- const identity = await auth(context);
+ const identity = await auth(context);
- if (identity instanceof Error) throw new Error('Unauthorized');
+ if (identity instanceof Error) throw new Error("Unauthorized");
- const authorised = privilegedUser(identity.id);
+ const authorised = privilegedUser(identity.id);
- return {
- id: identity.id,
- badges: [] as Badge[],
- preferences: await operation(identity, authorised),
- badgesCount: 0
- };
+ return {
+ id: identity.id,
+ badges: [] as Badge[],
+ preferences: await operation(identity, authorised),
+ badgesCount: 0,
+ };
};
const ensureOwnerOrPrivileged = (
- identity: UserIdentity,
- authorised: boolean,
- targetUserId: number
+ identity: UserIdentity,
+ authorised: boolean,
+ targetUserId: number,
) => {
- if (!authorised && identity.id !== targetUserId) throw new Error('Unauthorized');
+ if (!authorised && identity.id !== targetUserId)
+ throw new Error("Unauthorized");
};
const ensureBadgeOwnerOrPrivileged = async (
- identity: UserIdentity,
- authorised: boolean,
- badgeId: number
+ identity: UserIdentity,
+ authorised: boolean,
+ badgeId: number,
) => {
- if (authorised) return;
+ if (authorised) return;
- const ownsBadge = (await getUserBadges(identity.id)).some((badge) => badge.id === badgeId);
+ const ownsBadge = (await getUserBadges(identity.id)).some(
+ (badge) => badge.id === badgeId,
+ );
- if (!ownsBadge) throw new Error('Unauthorized');
+ if (!ownsBadge) throw new Error("Unauthorized");
};
export const resolvers: WithIndex<UserResolvers> = {
- Query: {
- User: async (_, args) => {
- if (!args.id) return null;
-
- const databaseBadges = await getUserBadges(args.id);
- const badges = toGraphQLBadges(databaseBadges);
-
- return {
- id: args.id,
- badges,
- preferences: await getUserPreferences(args.id),
- badgesCount: badges.length
- };
- },
- badges: async (_, args) => {
- if (!args.id) return [];
-
- const databaseBadges = await getUserBadges(args.id, args.page || 0, args.size || 0);
-
- return toGraphQLBadges(databaseBadges);
- }
- },
- Mutation: {
- shadowHideBadges: async (_, args, context) =>
- await authenticatedBadgesOperation(context, async (identity, authorised) => {
- ensureOwnerOrPrivileged(identity, authorised, args.userId);
-
- await setShadowHidden(args.userId, authorised);
- }),
- shadowHideBadge: async (_, args, context) =>
- await authenticatedBadgesOperation(context, async (identity, authorised) => {
- await ensureBadgeOwnerOrPrivileged(identity, authorised, args.id);
- await setShadowHiddenBadge(args.id, args.state == null ? true : args.state);
- }),
- hideBadge: async (_, args, context) =>
- await authenticatedBadgesOperation(context, async (identity) => {
- const allBadges = await getUserBadges(identity.id);
- const category = args.category || '';
-
- await Promise.all(
- allBadges
- .filter((badge) => badge.category === category)
- .map(async (badge) => {
- await updateUserBadge(identity.id, badge.id as number, {
- ...badge,
- hidden:
- allBadges
- .filter((badge) => badge.category === category)
- .filter((badge) => badge.hidden).length >
- allBadges.filter((badge) => badge.category === category).length / 2
- ? false
- : true
- });
- })
- );
- }),
- updateBadge: async (_, args, context) =>
- await authenticatedBadgesOperation(context, async (identity) => {
- const badge = {
- post: args.post || undefined,
- image: args.image || undefined,
- description: args.description || null,
- time: args.time || undefined,
- category: args.category || null,
- hidden: args.hidden || false,
- source: args.source || null,
- designer: args.designer || null
- };
-
- if ((await getUserBadges(identity.id)).find((badge) => badge.id === args.id)) {
- await updateUserBadge(identity.id, args.id as number, badge);
- } else {
- await addUserBadge(identity.id, badge);
- }
- }),
- deleteBadge: async (_, args, context) =>
- await authenticatedBadgesOperation(
- context,
- async (identity) => await removeUserBadge(identity.id, args.id)
- ),
- pruneUserBadges: async (_, __, context) =>
- await authenticatedBadgesOperation(
- context as Context,
- async (identity) => await removeAllUserBadges(identity.id)
- ),
- toggleHideMissingBadges: async (_, _args, context) =>
- await authenticatedPreferencesOperation(
- context as Context,
- async (identity) => await toggleHideMissingBadges(identity.id)
- ),
- toggleHideAWCBadges: async (_, _args, context) =>
- await authenticatedPreferencesOperation(
- context as Context,
- async (identity) => await toggleHideAWCBadges(identity.id)
- ),
- setBadgeWallCSS: async (_, args, context) =>
- await authenticatedPreferencesOperation(
- context as Context,
- async (identity) => await setCSS(identity.id, args.css)
- ),
- togglePinnedBadgeWallCategory: async (_, args, context) =>
- await authenticatedPreferencesOperation(
- context as Context,
- async (identity) => await togglePinnedBadgeWallCategory(identity.id, args.category)
- ),
- setPinnedBadgeWallCategories: async (_, args, context) =>
- await authenticatedPreferencesOperation(
- context as Context,
- async (identity) => await setPinnedBadgeWallCategories(identity.id, args.categories)
- ),
- setBiography: async (_, args, context) =>
- await authenticatedPreferencesOperation(
- context as Context,
- async (identity) => await setBiography(identity.id, args.biography.slice(0, 3000))
- ),
- togglePinnedHololiveStream: async (_, args, context) =>
- await authenticatedPreferencesOperation(
- context as Context,
- async (identity) => await toggleHololiveStreamPinning(identity.id, args.stream)
- )
- }
+ Query: {
+ User: async (_, args) => {
+ if (!args.id) return null;
+
+ const databaseBadges = await getUserBadges(args.id);
+ const badges = toGraphQLBadges(databaseBadges);
+
+ return {
+ id: args.id,
+ badges,
+ preferences: await getUserPreferences(args.id),
+ badgesCount: badges.length,
+ };
+ },
+ badges: async (_, args) => {
+ if (!args.id) return [];
+
+ const databaseBadges = await getUserBadges(
+ args.id,
+ args.page || 0,
+ args.size || 0,
+ );
+
+ return toGraphQLBadges(databaseBadges);
+ },
+ },
+ Mutation: {
+ shadowHideBadges: async (_, args, context) =>
+ await authenticatedBadgesOperation(
+ context,
+ async (identity, authorised) => {
+ ensureOwnerOrPrivileged(identity, authorised, args.userId);
+
+ await setShadowHidden(args.userId, authorised);
+ },
+ ),
+ shadowHideBadge: async (_, args, context) =>
+ await authenticatedBadgesOperation(
+ context,
+ async (identity, authorised) => {
+ await ensureBadgeOwnerOrPrivileged(identity, authorised, args.id);
+ await setShadowHiddenBadge(
+ args.id,
+ args.state == null ? true : args.state,
+ );
+ },
+ ),
+ hideBadge: async (_, args, context) =>
+ await authenticatedBadgesOperation(context, async (identity) => {
+ const allBadges = await getUserBadges(identity.id);
+ const category = args.category || "";
+
+ await Promise.all(
+ allBadges
+ .filter((badge) => badge.category === category)
+ .map(async (badge) => {
+ await updateUserBadge(identity.id, badge.id as number, {
+ ...badge,
+ hidden:
+ allBadges
+ .filter((badge) => badge.category === category)
+ .filter((badge) => badge.hidden).length >
+ allBadges.filter((badge) => badge.category === category)
+ .length /
+ 2
+ ? false
+ : true,
+ });
+ }),
+ );
+ }),
+ updateBadge: async (_, args, context) =>
+ await authenticatedBadgesOperation(context, async (identity) => {
+ const badge = {
+ post: args.post || undefined,
+ image: args.image || undefined,
+ description: args.description || null,
+ time: args.time || undefined,
+ category: args.category || null,
+ hidden: args.hidden || false,
+ source: args.source || null,
+ designer: args.designer || null,
+ };
+
+ if (
+ (await getUserBadges(identity.id)).find(
+ (badge) => badge.id === args.id,
+ )
+ ) {
+ await updateUserBadge(identity.id, args.id as number, badge);
+ } else {
+ await addUserBadge(identity.id, badge);
+ }
+ }),
+ deleteBadge: async (_, args, context) =>
+ await authenticatedBadgesOperation(
+ context,
+ async (identity) => await removeUserBadge(identity.id, args.id),
+ ),
+ pruneUserBadges: async (_, __, context) =>
+ await authenticatedBadgesOperation(
+ context as Context,
+ async (identity) => await removeAllUserBadges(identity.id),
+ ),
+ toggleHideMissingBadges: async (_, _args, context) =>
+ await authenticatedPreferencesOperation(
+ context as Context,
+ async (identity) => await toggleHideMissingBadges(identity.id),
+ ),
+ toggleHideAWCBadges: async (_, _args, context) =>
+ await authenticatedPreferencesOperation(
+ context as Context,
+ async (identity) => await toggleHideAWCBadges(identity.id),
+ ),
+ setBadgeWallCSS: async (_, args, context) =>
+ await authenticatedPreferencesOperation(
+ context as Context,
+ async (identity) => await setCSS(identity.id, args.css),
+ ),
+ togglePinnedBadgeWallCategory: async (_, args, context) =>
+ await authenticatedPreferencesOperation(
+ context as Context,
+ async (identity) =>
+ await togglePinnedBadgeWallCategory(identity.id, args.category),
+ ),
+ setPinnedBadgeWallCategories: async (_, args, context) =>
+ await authenticatedPreferencesOperation(
+ context as Context,
+ async (identity) =>
+ await setPinnedBadgeWallCategories(identity.id, args.categories),
+ ),
+ setBiography: async (_, args, context) =>
+ await authenticatedPreferencesOperation(
+ context as Context,
+ async (identity) =>
+ await setBiography(identity.id, args.biography.slice(0, 3000)),
+ ),
+ togglePinnedHololiveStream: async (_, args, context) =>
+ await authenticatedPreferencesOperation(
+ context as Context,
+ async (identity) =>
+ await toggleHololiveStreamPinning(identity.id, args.stream),
+ ),
+ },
};
diff --git a/src/graphql/user/schema.graphql b/src/graphql/user/schema.graphql
index 70ea066a..f21edd9b 100644
--- a/src/graphql/user/schema.graphql
+++ b/src/graphql/user/schema.graphql
@@ -1,63 +1,63 @@
type Query {
- User(id: Int): User
- badges(id: Int!, page: Int, size: Int): [Badge!]!
+ User(id: Int): User
+ badges(id: Int!, page: Int, size: Int): [Badge!]!
}
type Mutation {
- shadowHideBadges(userId: Int!): User!
- shadowHideBadge(id: Int!, state: Boolean): User!
- hideBadge(category: String): User!
- updateBadge(
- id: Int
- post: String
- image: String
- description: String
- time: String
- category: String
- hidden: Boolean
- source: String
- designer: String
- ): User!
- deleteBadge(id: Int!): User!
- pruneUserBadges: User!
- toggleHideMissingBadges: User!
- toggleHideAWCBadges: User!
- setBadgeWallCSS(css: String!): User!
- togglePinnedBadgeWallCategory(category: String!): User!
- setPinnedBadgeWallCategories(categories: [String!]!): User!
- setBiography(biography: String!): User!
- togglePinnedHololiveStream(stream: String!): User!
+ shadowHideBadges(userId: Int!): User!
+ shadowHideBadge(id: Int!, state: Boolean): User!
+ hideBadge(category: String): User!
+ updateBadge(
+ id: Int
+ post: String
+ image: String
+ description: String
+ time: String
+ category: String
+ hidden: Boolean
+ source: String
+ designer: String
+ ): User!
+ deleteBadge(id: Int!): User!
+ pruneUserBadges: User!
+ toggleHideMissingBadges: User!
+ toggleHideAWCBadges: User!
+ setBadgeWallCSS(css: String!): User!
+ togglePinnedBadgeWallCategory(category: String!): User!
+ setPinnedBadgeWallCategories(categories: [String!]!): User!
+ setBiography(biography: String!): User!
+ togglePinnedHololiveStream(stream: String!): User!
}
type User {
- id: Int!
- badges: [Badge!]!
- preferences: Preferences
- badgesCount: Int!
+ id: Int!
+ badges: [Badge!]!
+ preferences: Preferences
+ badgesCount: Int!
}
type Badge {
- post: String!
- image: String!
- description: String
- id: Int!
- time: String!
- category: String
- hidden: Boolean!
- source: String
- designer: String
- shadow_hidden: Boolean!
- click_count: Int!
+ post: String!
+ image: String!
+ description: String
+ id: Int!
+ time: String!
+ category: String
+ hidden: Boolean!
+ source: String
+ designer: String
+ shadow_hidden: Boolean!
+ click_count: Int!
}
type Preferences {
- created_at: String!
- updated_at: String!
- user_id: Int!
- pinned_hololive_streams: [String!]!
- hide_missing_badges: Boolean!
- biography: String
- badge_wall_css: String!
- hide_awc_badges: Boolean!
- pinned_badge_wall_categories: [String!]!
+ created_at: String!
+ updated_at: String!
+ user_id: Int!
+ pinned_hololive_streams: [String!]!
+ hide_missing_badges: Boolean!
+ biography: String
+ badge_wall_css: String!
+ hide_awc_badges: Boolean!
+ pinned_badge_wall_categories: [String!]!
}