Create a declaration file manga-provider.d.ts
// manga-provider.d.ts
declare type SearchResult = {
id: string // Passed to findChapters
title: string
synonyms?: string[]
year?: number
image?: string
}
declare type ChapterDetails = {
id: string // Passed to findChapterPages
url: string
// e.g. "Chapter 4", "Chapter 4.5"
title: string
// Chapter number
// e.g. "13", "13.5"
chapter: string
// Starts at 0
index: number
scanlator?: string
language?: string
rating?: number
updatedAt?: string
}
declare type ChapterPage = {
url: string
// Starts at 0
index: number
// Request headers for the page if proxying is required.
headers: { [key: string]: string }
}
declare type QueryOptions = {
query: string
year?: number
}
declare type Settings = {
supportsMultiLanguage?: boolean
supportsMultiScanlator?: boolean
}
Create a typescript (or javascript) file with the following template.
<aside> 🚨 Do not change the name of the class. It must be Provider.
</aside>
/// <reference path="./manga-provider.d.ts" />
class Provider {
private api = "<https://example.com>"
getSettings(): Settings {
return {
supportsMultiLanguage: false,
supportsMultiScanlator: false,
}
}
// Returns the search results based on the query.
async search(opts: QueryOptions): Promise<SearchResult[]> {
// TODO
return [{
id: "999",
title: "Manga Title",
synonyms: ["Synonym 1", "Synonym 2"],
year: 2021,
image: "<https://example.com/image.jpg>",
}]
}
// Returns the chapters based on the manga ID.
// The chapters should be sorted in ascending order (0, 1, ...).
async findChapters(mangaId: string): Promise<ChapterDetails[]> {
// TODO
return [{
id: `999-chapter-1`,
url: "<https://example.com/manga/999-chapter-1>",
title: "Chapter 1",
chapter: "1",
index: 0,
}]
}
// Returns the chapter pages based on the chapter ID.
// The pages should be sorted in ascending order (0, 1, ...).
async findChapterPages(chapterId: string): Promise<ChapterPage[]> {
// TODO
return [{
url: "<https://example.com/manga/999-chapter-1/page-1.jpg>",
index: 0,
headers: {
"Referer": "<https://example.com/manga/999/chapter-1>",
},
}]
}
}
search
is called twice when the user opens the manga page. Each time with a different manga title as query (English, Romaji).findChapters
will be called with the manga ID from the search result to get the list of chapters.findChapterPages
is called when the user requests to read or download the chapter.Depending on the source website you’re getting the data from, the URLs might get a little complex.
For example, if a manga’s chapter page is: https://example.com/manga/999/chapter-1
consisting of 2 URL sections (in this case, the manga ID and the chapter ID), you can construct the Seanime chapter ID by combining the two parts and splitting them in findChapterPages
,