lib.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. interface CommonData {
  2. id: number
  3. name: string
  4. rus_name: string
  5. eng_name: string
  6. alt_name: string
  7. slug: string
  8. slug_url: string
  9. cover: Cover
  10. stats: Stat[]
  11. }
  12. export interface AnimeData extends Omit<CommonData, 'stats'> {
  13. ageRestriction: AgeRestriction
  14. cover: Cover
  15. /**
  16. * Example: 18 января 1991 г.
  17. */
  18. releaseDateString: string
  19. shiki_rate: number
  20. shikimori_href: string
  21. status: AnimeStatus
  22. type: AnimeType
  23. /**
  24. * Check if it exists. If it is, the anime is licensed and no anime data will be present
  25. */
  26. toast?: {
  27. message: string
  28. type: string
  29. }
  30. }
  31. export interface UserData {
  32. id: number
  33. username: string
  34. avatar: UserAvatar
  35. last_online_at: Date
  36. }
  37. export type CharacterData = CommonData
  38. export type PersonData = CommonData
  39. export type PublisherData = CommonData
  40. export type TeamData = Omit<CommonData, 'stats' | 'rus_name'>
  41. export interface CollectionData {
  42. id: number
  43. name: string
  44. user: Author
  45. type: 'titles' | 'character' | 'people'
  46. adult: boolean
  47. }
  48. export interface ReviewData {
  49. id: number
  50. title: string
  51. user: Author
  52. related: ReviewRelation
  53. }
  54. interface ReviewRelation {
  55. rus_name: string
  56. eng_name: string
  57. cover: Cover
  58. ageRestriction: AgeRestriction
  59. }
  60. interface Author {
  61. id: string
  62. username: string
  63. avatar: UserAvatar
  64. }
  65. interface Stat {
  66. value: number
  67. formated: string
  68. short: string
  69. tag: 'titles' | 'subscribers'
  70. label: string
  71. }
  72. interface UserAvatar {
  73. filename: string
  74. url: string
  75. }
  76. interface Cover {
  77. filename: string
  78. default: string
  79. thumbnail: string
  80. }
  81. export type AgeRestriction =
  82. | { id: 0, label: 'Нет' }
  83. | { id: 1, label: '6+' }
  84. | { id: 2, label: '12+' }
  85. | { id: 3, label: '16+' }
  86. | { id: 4, label: '18+' }
  87. | { id: 5, label: '18+ (RX)' }
  88. interface AnimeStatus {
  89. id: number // yet to be typed properly
  90. label: string
  91. }
  92. interface AnimeType {
  93. id: number // yet to be typed properly
  94. label: string
  95. }
  96. interface CachedResponse {
  97. id: string
  98. data: AnimeData | UserData | CharacterData | CollectionData | ReviewData
  99. }
  100. type APIEndpoint =
  101. | 'anime'
  102. | 'user'
  103. | 'character'
  104. | 'people'
  105. | 'collections'
  106. | 'reviews'
  107. | 'teams'
  108. | 'publisher'
  109. let cachedResponse: CachedResponse
  110. export class AnimeLib {
  111. private static api = 'https://api2.mangalib.me/api'
  112. private static split = (path: string) => path.split('/')[3]
  113. private static async request(
  114. id: string,
  115. endpoint: APIEndpoint,
  116. endpointPart?: string,
  117. ) {
  118. return await fetch(`${this.api}/${endpoint}/${endpointPart ?? id}`).then(
  119. async (response): Promise<CachedResponse> => {
  120. return {
  121. id,
  122. data: (await response.json()).data,
  123. }
  124. },
  125. )
  126. }
  127. public static async getAnime(
  128. path: string,
  129. id: string,
  130. ): Promise<CachedResponse> {
  131. if (!cachedResponse || cachedResponse.id !== id) {
  132. if (path.endsWith('/watch'))
  133. path = path.slice(0, -6)
  134. cachedResponse = await this.request(id, 'anime', this.split(path))
  135. }
  136. return cachedResponse
  137. }
  138. public static async getUser(id: string): Promise<CachedResponse> {
  139. if (!cachedResponse || cachedResponse.id !== id)
  140. cachedResponse = await this.request(id, 'user')
  141. return cachedResponse
  142. }
  143. public static async getCharacter(
  144. path: string,
  145. id: string,
  146. ): Promise<CachedResponse> {
  147. if (!cachedResponse || cachedResponse.id !== id)
  148. cachedResponse = await this.request(id, 'character', this.split(path))
  149. return cachedResponse
  150. }
  151. public static async getPerson(
  152. path: string,
  153. id: string,
  154. ): Promise<CachedResponse> {
  155. if (!cachedResponse || cachedResponse.id !== id)
  156. cachedResponse = await this.request(id, 'people', this.split(path))
  157. return cachedResponse
  158. }
  159. public static async getCollection(id: string): Promise<CachedResponse> {
  160. if (!cachedResponse || cachedResponse.id !== id)
  161. cachedResponse = await this.request(id, 'collections')
  162. return cachedResponse
  163. }
  164. public static async getReview(id: string): Promise<CachedResponse> {
  165. if (!cachedResponse || cachedResponse.id !== id)
  166. cachedResponse = await this.request(id, 'reviews')
  167. return cachedResponse
  168. }
  169. public static async getTeam(
  170. path: string,
  171. id: string,
  172. ): Promise<CachedResponse> {
  173. if (!cachedResponse || cachedResponse.id !== id)
  174. cachedResponse = await this.request(id, 'teams', this.split(path))
  175. return cachedResponse
  176. }
  177. public static async getPublisher(
  178. path: string,
  179. id: string,
  180. ): Promise<CachedResponse> {
  181. if (!cachedResponse || cachedResponse.id !== id)
  182. cachedResponse = await this.request(id, 'publisher', this.split(path))
  183. return cachedResponse
  184. }
  185. }