feat: return user data when marking episode as watched
This commit is contained in:
@@ -2,6 +2,7 @@ import { graphql } from "gql.tada";
|
|||||||
import { GraphQLClient } from "graphql-request";
|
import { GraphQLClient } from "graphql-request";
|
||||||
|
|
||||||
import { sleep } from "~/libs/sleep";
|
import { sleep } from "~/libs/sleep";
|
||||||
|
import type { User } from "~/types/user";
|
||||||
|
|
||||||
const GetUserQuery = graphql(`
|
const GetUserQuery = graphql(`
|
||||||
query GetUser {
|
query GetUser {
|
||||||
@@ -23,23 +24,6 @@ const GetUserQuery = graphql(`
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
type User = {
|
|
||||||
statistics: {
|
|
||||||
minutesWatched?: number | undefined;
|
|
||||||
episodesWatched?: number | undefined;
|
|
||||||
count?: number | undefined;
|
|
||||||
meanScore?: number | undefined;
|
|
||||||
};
|
|
||||||
name?: string | undefined;
|
|
||||||
avatar?:
|
|
||||||
| {
|
|
||||||
medium: string | null;
|
|
||||||
large: string | null;
|
|
||||||
}
|
|
||||||
| null
|
|
||||||
| undefined;
|
|
||||||
} | null;
|
|
||||||
|
|
||||||
export async function getUser(aniListToken: string): Promise<User> {
|
export async function getUser(aniListToken: string): Promise<User> {
|
||||||
const client = new GraphQLClient("https://graphql.anilist.co/");
|
const client = new GraphQLClient("https://graphql.anilist.co/");
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,21 @@ const MarkEpisodeAsWatchedMutation = graphql(`
|
|||||||
status: CURRENT
|
status: CURRENT
|
||||||
progress: $episodeNumber
|
progress: $episodeNumber
|
||||||
) {
|
) {
|
||||||
id
|
user {
|
||||||
|
name
|
||||||
|
avatar {
|
||||||
|
medium
|
||||||
|
large
|
||||||
|
}
|
||||||
|
statistics {
|
||||||
|
anime {
|
||||||
|
minutesWatched
|
||||||
|
episodesWatched
|
||||||
|
count
|
||||||
|
meanScore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
@@ -16,7 +30,21 @@ const MarkEpisodeAsWatchedMutation = graphql(`
|
|||||||
const MarkTitleAsWatchedMutation = graphql(`
|
const MarkTitleAsWatchedMutation = graphql(`
|
||||||
mutation MarkTitleAsWatched($titleId: Int!) {
|
mutation MarkTitleAsWatched($titleId: Int!) {
|
||||||
SaveMediaListEntry(mediaId: $titleId, status: COMPLETED) {
|
SaveMediaListEntry(mediaId: $titleId, status: COMPLETED) {
|
||||||
id
|
user {
|
||||||
|
name
|
||||||
|
avatar {
|
||||||
|
medium
|
||||||
|
large
|
||||||
|
}
|
||||||
|
statistics {
|
||||||
|
anime {
|
||||||
|
minutesWatched
|
||||||
|
episodesWatched
|
||||||
|
count
|
||||||
|
meanScore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
@@ -42,7 +70,10 @@ export async function markEpisodeAsWatched(
|
|||||||
);
|
);
|
||||||
|
|
||||||
return mutation
|
return mutation
|
||||||
.then((data) => !!data?.SaveMediaListEntry?.id)
|
.then((data) => ({
|
||||||
|
...data?.SaveMediaListEntry?.user,
|
||||||
|
statistics: data?.SaveMediaListEntry?.user?.statistics?.anime,
|
||||||
|
}))
|
||||||
.catch(async (err) => {
|
.catch(async (err) => {
|
||||||
console.error(await err.response);
|
console.error(await err.response);
|
||||||
throw err;
|
throw err;
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import {
|
|||||||
EpisodeNumberSchema,
|
EpisodeNumberSchema,
|
||||||
ErrorResponse,
|
ErrorResponse,
|
||||||
ErrorResponseSchema,
|
ErrorResponseSchema,
|
||||||
SuccessResponse,
|
|
||||||
SuccessResponseSchema,
|
SuccessResponseSchema,
|
||||||
} from "~/types/schema";
|
} from "~/types/schema";
|
||||||
|
import { User } from "~/types/user";
|
||||||
|
|
||||||
import { markEpisodeAsWatched } from "./anilist";
|
import { markEpisodeAsWatched } from "./anilist";
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ const route = createRoute({
|
|||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
schema: SuccessResponseSchema(),
|
schema: SuccessResponseSchema(User),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
description: "Returns whether the episode was marked as watched",
|
description: "Returns whether the episode was marked as watched",
|
||||||
@@ -78,7 +78,7 @@ app.openapi(route, async (c) => {
|
|||||||
await c.req.json<typeof MarkEpisodeAsWatchedRequest._type>();
|
await c.req.json<typeof MarkEpisodeAsWatchedRequest._type>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await markEpisodeAsWatched(
|
const user = await markEpisodeAsWatched(
|
||||||
aniListToken,
|
aniListToken,
|
||||||
aniListId,
|
aniListId,
|
||||||
episodeNumber,
|
episodeNumber,
|
||||||
@@ -93,13 +93,18 @@ app.openapi(route, async (c) => {
|
|||||||
"COMPLETED",
|
"COMPLETED",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
console.error("Failed to mark episode as watched - user not found?");
|
||||||
|
return c.json(ErrorResponse, { status: 500 });
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.json({ success: true, result: user }, 200);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to mark episode as watched");
|
console.error("Failed to mark episode as watched");
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return c.json(ErrorResponse, { status: 500 });
|
return c.json(ErrorResponse, { status: 500 });
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.json(SuccessResponse, 200);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
21
src/types/user.ts
Normal file
21
src/types/user.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export type User = z.infer<typeof User>;
|
||||||
|
export const User = z
|
||||||
|
.object({
|
||||||
|
statistics: z.object({
|
||||||
|
minutesWatched: z.number().openapi({ type: "integer", format: "int64" }),
|
||||||
|
episodesWatched: z.number().openapi({ type: "integer", format: "int64" }),
|
||||||
|
count: z
|
||||||
|
.number()
|
||||||
|
.int() /* .openapi({ type: "integer", format: "int64" }) */,
|
||||||
|
meanScore: z.number().openapi({ type: "number", format: "float" }),
|
||||||
|
}),
|
||||||
|
name: z.string(),
|
||||||
|
avatar: z.object({
|
||||||
|
medium: z.string(),
|
||||||
|
large: z.string(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.optional()
|
||||||
|
.nullable();
|
||||||
Reference in New Issue
Block a user