UNPKG

@zennomi/mangadex-full-api

Version:

A MangaDex api based around the official API.

254 lines (236 loc) 7.8 kB
import IDObject from '../internal/IDObject'; import { fetchMD, fetchMDByArrayParam, fetchMDData, fetchMDDataWithBody, fetchMDSearch } from '../util/Network'; import Relationship from '../internal/Relationship'; import LocalizedString from '../internal/LocalizedString'; import type { CreateScanlationGroupSchema, GetSearchGroupParamsSchema, ResponseSchema, ScanlationGroupAttributesSchema, ScanlationGroupListSchema, ScanlationGroupResponseSchema, ScanlationGroupSchema, Statistics, User as UserNamespace, } from '../types/schema'; import type { DeepRequire, Merge } from '../types/helpers'; import type User from './User'; type GroupSearchParams = Partial<Merge<GetSearchGroupParamsSchema, { ids: Group[] }>>; type GroupStatsResponse = DeepRequire<Statistics.GetStatisticsGroups.ResponseBody>; type GroupStats = GroupStatsResponse['statistics'][string]; type FollowedGroupsParams = UserNamespace.GetUserFollowsGroup.RequestQuery; export default class Group extends IDObject implements ScanlationGroupAttributesSchema { /** * The MangaDex UUID of this group */ id: string; /** * The name of this group */ name: string; /** * Alternate names for this group, including localized names */ altNames: LocalizedString[]; /** * Url to this group's website */ website: string | null; /** * IRC server of this group */ ircServer: string | null; /** * IRC channel of this group */ ircChannel: string | null; /** * Discord server of this group */ discord: string | null; /** * Email of this group */ contactEmail: string | null; /** * Description of this group (not localized) */ description: string | null; /** * Twitter profile of this group */ twitter: string | null; /** * MangaUpdates profile of this group */ mangaUpdates: string | null; /** * Languages this group focusses on translating */ focusedLanguage: string[] | null; /** * Is this group locked from uploading? */ locked: boolean; /** * Is this an official scanlation group? */ official: boolean; /** * Is this group inactive? */ inactive: boolean; /** * The delay between when this group uploads a chapter and when that chapter becomes readable */ publishDelay: string; /** * The version of this group (incremented by updating the group data) */ version: number; /** * When this group was created */ createdAt: Date; /** * When this group was last updated */ updatedAt: Date; /** * Relationship to the user profile of the user */ leader: Relationship<User> | null; /** * Array of relationships to the member users of this group */ members: Relationship<User>[]; /** * Is this group ex-licensed? */ exLicensed: boolean; /** * Is this group verified? */ verified: boolean; constructor(schem: ScanlationGroupSchema) { super(); this.id = schem.id; this.name = schem.attributes.name; this.altNames = schem.attributes.altNames.map((name) => new LocalizedString(name)); this.website = schem.attributes.website; this.ircServer = schem.attributes.ircServer; this.ircChannel = schem.attributes.ircChannel; this.discord = schem.attributes.discord; this.contactEmail = schem.attributes.contactEmail; this.description = schem.attributes.description; this.twitter = schem.attributes.twitter; this.mangaUpdates = schem.attributes.mangaUpdates; this.focusedLanguage = schem.attributes.focusedLanguage; this.locked = schem.attributes.locked; this.official = schem.attributes.official; this.inactive = schem.attributes.inactive; this.publishDelay = schem.attributes.publishDelay; this.version = schem.attributes.version; this.createdAt = new Date(schem.attributes.createdAt); this.updatedAt = new Date(schem.attributes.updatedAt); this.leader = Relationship.convertType<User>('leader', schem.relationships).pop() ?? null; this.members = Relationship.convertType<User>('member', schem.relationships); this.exLicensed = schem.attributes.exLicensed; this.verified = schem.attributes.verified; } /** * Retrieves a group by their id */ static async get(id: string): Promise<Group> { return new Group(await fetchMDData<ScanlationGroupResponseSchema>(`/group/${id}`)); } /** * Retrieves a list of groups according to the specified search parameters */ static async search(query?: GroupSearchParams): Promise<Group[]> { const res = await fetchMDSearch<ScanlationGroupListSchema>(`/group`, query); return res.map((u) => new Group(u)); } /** * Retrieves an array of groups by an array of ids */ static async getMultiple(ids: string[]): Promise<Group[]> { const res = await fetchMDByArrayParam<ScanlationGroupListSchema>('/group', ids); return res.map((u) => new Group(u)); } /** * Performs a search for a group and returns the first one found. If no results are * found, null is returned */ static async getByQuery(query?: GroupSearchParams): Promise<Group | null> { const res = await this.search(query); return res[0] ?? null; } /** * Create a new group */ static async create(data: CreateScanlationGroupSchema) { return new Group(await fetchMDDataWithBody<ScanlationGroupResponseSchema>('/group', data)); } /** * Deletes a group by their id */ static async delete(id: string) { await fetchMD<ResponseSchema>(`/group/${id}`, undefined, { method: 'DELETE' }); } /** * Deletes this group */ async delete() { await Group.delete(this.id); } /** * Updates a group's information. */ async update(data: Omit<CreateScanlationGroupSchema, 'version'>) { return new Group( await fetchMDDataWithBody<ScanlationGroupResponseSchema>( `/group/${this.id}`, { ...data, version: this.version + 1, }, undefined, 'PUT', ), ); } /** * Makes the logged in user follow or unfollow a group */ static async changeFollowship(id: string, follow = true): Promise<void> { await fetchMD(`/group/${id}/follow`, undefined, { method: follow ? 'POST' : 'DELETE' }); } /** * Makes the user follow or unfollow this group */ async changeFollowship(follow = true): Promise<void> { await Group.changeFollowship(this.id, follow); } /** * Gets the statistics about a list of groups */ static async getStatistics(ids: string[] | Group[]): Promise<Record<string, GroupStats>> { const res = await fetchMD<GroupStatsResponse>(`/statistics/group`, { group: ids }); return res.statistics; } /** * Gets the statistics about this group */ async getStatistics(): Promise<GroupStats> { const res = await Group.getStatistics([this.id]); return res[this.id]; } /** * Gets an array of groups that the current user follows */ static async getFollowedGroups(query: FollowedGroupsParams = { limit: Infinity, offset: 0 }): Promise<Group[]> { const res = await fetchMDSearch<ScanlationGroupListSchema>('/user/follows/group', query); return res.map((u) => new Group(u)); } }