Reduce goodreads data source to single file

This commit is contained in:
Evan Fiordeliso 2025-06-26 13:16:54 -04:00
parent d86e4affa2
commit f2ac5736b2
5 changed files with 143 additions and 146 deletions

View File

@ -1,16 +1,142 @@
import { requestUrl } from "obsidian";
import {
Contributor,
NextData,
Ref,
Book as ApiBook,
SearchResult,
} from "./types";
import { Author, Book, Series } from "../../types";
import { Author, Book as OutputBook, Series as OutputSeries } from "../types";
export function createBookFromNextData(nextData: NextData, ref: Ref): Book {
interface Ref {
__ref: string;
}
interface BookContributorEdge {
__typename: "BookContributorEdge";
node: Ref;
role: string;
}
interface BookSeries {
__typename: "BookSeries";
userPosition: string;
series: Ref;
}
interface Genre {
__typename: "Genre";
name: string;
webUrl: string;
}
interface BookGenre {
__typename: "BookGenre";
genre: Genre;
}
interface Language {
__typename: "Language";
name: string;
}
interface BookDetails {
__typename: "BookDetails";
asin: string;
format: string;
numPages: number;
publicationTime: number;
publisher: string;
isbn: string;
isbn13: string;
language: Language;
}
interface Book {
__typename: "Book";
id: string;
legacyId: number;
webUrl: string;
title: string;
titleComplete: string;
description: string;
primaryContributorEdge: BookContributorEdge;
secondaryContributorEdges: BookContributorEdge[];
imageUrl: string;
bookSeries: BookSeries[];
bookGenres: BookGenre[];
details: BookDetails;
work: Ref;
}
interface ContributorWorksConnection {
__typename: "ContributorWorksConnection";
totalCount: number;
}
interface ContributorFollowersConnection {
__typename: "ContributorFollowersConnection";
totalCount: number;
}
interface Contributor {
__typename: "Contributor";
id: string;
legacyId: number;
name: string;
description: string;
isGrAuthor: boolean;
works: ContributorWorksConnection;
profileImageUrl: string;
webUrl: string;
followers: ContributorFollowersConnection;
}
interface Series {
__typename: "Series";
id: string;
title: string;
webUrl: string;
}
interface Work {
__typename: "Work";
id: string;
legacyId: number;
bestBook: Ref;
// ...Book
}
interface Query {
__typename: "Query";
[key: string]: any;
}
interface NextData {
props: {
pageProps: {
apolloState: {
ROOT_QUERY: Query;
[key: string]: any;
};
params: Record<string, string>;
query: Record<string, string>;
jwtToken: string;
dataSource: string;
};
};
}
export interface SearchResult {
legacyId: number;
title: string;
authors: string[];
avgRating: number;
ratingCount: number;
publicationYear: number;
editionCount: number;
coverImageUrl: string;
}
export function createBookFromNextData(
nextData: NextData,
ref: Ref
): OutputBook {
const apolloState = nextData.props.pageProps.apolloState;
const bookData = apolloState[ref.__ref] as ApiBook;
const bookData = apolloState[ref.__ref] as Book;
const contributorEdges = [
bookData.primaryContributorEdge,
@ -26,10 +152,10 @@ export function createBookFromNextData(nextData: NextData, ref: Ref): Book {
description: contributor.description,
}));
let series: Series | null = null;
let series: OutputSeries | null = null;
if (bookData.bookSeries.length > 0) {
const bookSeries = bookData.bookSeries[0];
const seriesData = apolloState[bookSeries.series.__ref];
const seriesData = apolloState[bookSeries.series.__ref] as Series;
series = {
title: seriesData.title,
position: parseInt(bookSeries.userPosition, 10),
@ -64,7 +190,7 @@ async function getNextData(legacyId: number): Promise<NextData> {
return nextData;
}
export async function getBookByLegacyId(legacyId: number): Promise<Book> {
export async function getBookByLegacyId(legacyId: number): Promise<OutputBook> {
const nextData = await getNextData(legacyId);
const bookRef = nextData.props.pageProps.apolloState.ROOT_QUERY[
`getBookByLegacyId({"legacyId":"${legacyId}"})`

View File

@ -1,129 +0,0 @@
export interface Ref {
__ref: string;
}
export interface BookContributorEdge {
__typename: "BookContributorEdge";
node: Ref;
role: string;
}
export interface BookSeries {
__typename: "BookSeries";
userPosition: string;
series: Ref;
}
export interface Genre {
__typename: "Genre";
name: string;
webUrl: string;
}
export interface BookGenre {
__typename: "BookGenre";
genre: Genre;
}
export interface Language {
__typename: "Language";
name: string;
}
export interface BookDetails {
__typename: "BookDetails";
asin: string;
format: string;
numPages: number;
publicationTime: number;
publisher: string;
isbn: string;
isbn13: string;
language: Language;
}
export interface Book {
__typename: "Book";
id: string;
legacyId: number;
webUrl: string;
title: string;
titleComplete: string;
description: string;
primaryContributorEdge: BookContributorEdge;
secondaryContributorEdges: BookContributorEdge[];
imageUrl: string;
bookSeries: BookSeries[];
bookGenres: BookGenre[];
details: BookDetails;
work: Ref;
}
export interface ContributorWorksConnection {
__typename: "ContributorWorksConnection";
totalCount: number;
}
export interface ContributorFollowersConnection {
__typename: "ContributorFollowersConnection";
totalCount: number;
}
export interface Contributor {
__typename: "Contributor";
id: string;
legacyId: number;
name: string;
description: string;
isGrAuthor: boolean;
works: ContributorWorksConnection;
profileImageUrl: string;
webUrl: string;
followers: ContributorFollowersConnection;
}
export interface Series {
__typename: "Series";
id: string;
title: string;
webUrl: string;
}
export interface Work {
__typename: "Work";
id: string;
legacyId: number;
bestBook: Ref;
// ...
}
export interface Query {
__typename: "Query";
[key: string]: any;
}
export interface NextData {
props: {
pageProps: {
apolloState: {
ROOT_QUERY: Query;
[key: string]: any;
};
params: Record<string, string>;
query: Record<string, string>;
jwtToken: string;
dataSource: string;
};
};
}
export interface SearchResult {
legacyId: number;
title: string;
authors: string[];
avgRating: number;
ratingCount: number;
publicationYear: number;
editionCount: number;
coverImageUrl: string;
}

View File

@ -4,7 +4,7 @@ import {
BookTrackerSettingTab,
DEFAULT_SETTINGS,
} from "./settings/settings";
import { getBookByLegacyId } from "@data-sources/goodreads/scraper";
import { getBookByLegacyId } from "@data-sources/goodreads";
import { Templater } from "./utils/templater";
import { GoodreadsSearchModal } from "@views/goodreads-search-modal";
import { GoodreadsSearchSuggestModal } from "@views/goodreads-search-suggest-modal";

View File

@ -1,5 +1,5 @@
import { searchBooks } from "@data-sources/goodreads/scraper";
import { SearchResult } from "@data-sources/goodreads/types";
import { searchBooks } from "@data-sources/goodreads";
import { SearchResult } from "@data-sources/goodreads";
import { App, Modal, Notice, TextComponent } from "obsidian";
export class GoodreadsSearchModal extends Modal {

View File

@ -1,4 +1,4 @@
import { SearchResult } from "@data-sources/goodreads/types";
import { SearchResult } from "@data-sources/goodreads";
import { App, Notice, SuggestModal } from "obsidian";
export class GoodreadsSearchSuggestModal extends SuggestModal<SearchResult> {