ani-client 2.0.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -446,6 +446,7 @@ var RELATIONS_FIELDS = `
446
446
  coverImage { extraLarge large medium color }
447
447
  genres
448
448
  averageScore
449
+ meanScore
449
450
  studios { nodes { id name isAnimationStudio siteUrl } }
450
451
  siteUrl
451
452
  nextAiringEpisode {
@@ -459,6 +460,30 @@ var RELATIONS_FIELDS = `
459
460
  }
460
461
  }
461
462
  `;
463
+ var MEDIA_RECOMMENDATION_FIELDS = `
464
+ id
465
+ rating
466
+ mediaRecommendation {
467
+ id
468
+ title { romaji english native userPreferred }
469
+ type
470
+ format
471
+ coverImage { large medium }
472
+ averageScore
473
+ meanScore
474
+ episodes
475
+ chapters
476
+ volumes
477
+ nextAiringEpisode
478
+ season
479
+ seasonYear
480
+ startDate
481
+ endDate
482
+ studios
483
+ genres
484
+ siteUrl
485
+ }
486
+ `;
462
487
  var MEDIA_FIELDS = `
463
488
  ${MEDIA_FIELDS_BASE}
464
489
  ${RELATIONS_FIELDS}
@@ -744,6 +769,7 @@ query (
744
769
  $genre_not_in: [String],
745
770
  $tag_not_in: [String],
746
771
  $isAdult: Boolean,
772
+ $idNotIn: [Int],
747
773
  $sort: [MediaSort],
748
774
  $page: Int,
749
775
  $perPage: Int
@@ -766,6 +792,7 @@ query (
766
792
  genre_not_in: $genre_not_in,
767
793
  tag_not_in: $tag_not_in,
768
794
  isAdult: $isAdult,
795
+ id_not_in: $idNotIn,
769
796
  sort: $sort
770
797
  ) {
771
798
  ${MEDIA_FIELDS_BASE}
@@ -773,19 +800,42 @@ query (
773
800
  }
774
801
  }`;
775
802
  var QUERY_TRENDING = `
776
- query ($type: MediaType, $isAdult: Boolean, $page: Int, $perPage: Int) {
803
+ query (
804
+ $type: MediaType,
805
+ $isAdult: Boolean,
806
+ $idNotIn: [Int],
807
+ $page: Int,
808
+ $perPage: Int
809
+ ) {
777
810
  Page(page: $page, perPage: $perPage) {
778
811
  pageInfo { total perPage currentPage lastPage hasNextPage }
779
- media(type: $type, isAdult: $isAdult, sort: TRENDING_DESC) {
812
+ media(
813
+ type: $type,
814
+ isAdult: $isAdult,
815
+ id_not_in: $idNotIn,
816
+ sort: TRENDING_DESC
817
+ ) {
780
818
  ${MEDIA_FIELDS_BASE}
781
819
  }
782
820
  }
783
821
  }`;
784
822
  var QUERY_AIRING_SCHEDULE = `
785
- query ($airingAt_greater: Int, $airingAt_lesser: Int, $isAdult: Boolean, $sort: [AiringSort], $page: Int, $perPage: Int) {
823
+ query (
824
+ $airingAt_greater: Int,
825
+ $airingAt_lesser: Int,
826
+ $sort: [AiringSort],
827
+ $idNotIn: [Int],
828
+ $page: Int,
829
+ $perPage: Int
830
+ ) {
786
831
  Page(page: $page, perPage: $perPage) {
787
832
  pageInfo { total perPage currentPage lastPage hasNextPage }
788
- airingSchedules(airingAt_greater: $airingAt_greater, airingAt_lesser: $airingAt_lesser, sort: $sort) {
833
+ airingSchedules(
834
+ airingAt_greater: $airingAt_greater,
835
+ airingAt_lesser: $airingAt_lesser,
836
+ id_not_in: $idNotIn,
837
+ sort: $sort
838
+ ) {
789
839
  id
790
840
  airingAt
791
841
  timeUntilAiring
@@ -798,19 +848,43 @@ query ($airingAt_greater: Int, $airingAt_lesser: Int, $isAdult: Boolean, $sort:
798
848
  }
799
849
  }`;
800
850
  var QUERY_RECENT_CHAPTERS = `
801
- query ($isAdult: Boolean $page: Int, $perPage: Int) {
851
+ query (
852
+ $isAdult: Boolean,
853
+ $idNotIn: [Int],
854
+ $page: Int,
855
+ $perPage: Int
856
+ ) {
802
857
  Page(page: $page, perPage: $perPage) {
803
858
  pageInfo { total perPage currentPage lastPage hasNextPage }
804
- media(type: MANGA, isAdult: $isAdult status: RELEASING, sort: UPDATED_AT_DESC) {
859
+ media(
860
+ type: MANGA,
861
+ isAdult: $isAdult,
862
+ id_not_in: $idNotIn,
863
+ status: RELEASING,
864
+ sort: UPDATED_AT_DESC
865
+ ) {
805
866
  ${MEDIA_FIELDS_BASE}
806
867
  }
807
868
  }
808
869
  }`;
809
870
  var QUERY_PLANNING = `
810
- query ($type: MediaType, $isAdult: Boolean, $sort: [MediaSort], $page: Int, $perPage: Int) {
871
+ query (
872
+ $type: MediaType,
873
+ $isAdult: Boolean,
874
+ $idNotIn: [Int],
875
+ $sort: [MediaSort],
876
+ $page: Int,
877
+ $perPage: Int
878
+ ) {
811
879
  Page(page: $page, perPage: $perPage) {
812
880
  pageInfo { total perPage currentPage lastPage hasNextPage }
813
- media(type: $type, isAdult: $isAdult, status: NOT_YET_RELEASED, sort: $sort) {
881
+ media(
882
+ type: $type,
883
+ isAdult: $isAdult,
884
+ id_not_in: $idNotIn,
885
+ status: NOT_YET_RELEASED,
886
+ sort: $sort
887
+ ) {
814
888
  ${MEDIA_FIELDS_BASE}
815
889
  }
816
890
  }
@@ -821,6 +895,7 @@ query (
821
895
  $seasonYear: Int!,
822
896
  $type: MediaType,
823
897
  $isAdult: Boolean,
898
+ $idNotIn: [Int],
824
899
  $sort: [MediaSort],
825
900
  $page: Int,
826
901
  $perPage: Int
@@ -832,6 +907,7 @@ query (
832
907
  seasonYear: $seasonYear,
833
908
  type: $type,
834
909
  isAdult: $isAdult,
910
+ id_not_in: $idNotIn,
835
911
  sort: $sort
836
912
  ) {
837
913
  ${MEDIA_FIELDS_BASE}
@@ -850,25 +926,7 @@ query ($mediaId: Int!, $page: Int, $perPage: Int, $sort: [RecommendationSort]) {
850
926
  recommendations(page: $page, perPage: $perPage, sort: $sort) {
851
927
  pageInfo { total perPage currentPage lastPage hasNextPage }
852
928
  nodes {
853
- id
854
- rating
855
- userRating
856
- mediaRecommendation {
857
- id
858
- idMal
859
- title { romaji english native userPreferred }
860
- type
861
- format
862
- status
863
- coverImage { extraLarge large medium color }
864
- bannerImage
865
- genres
866
- averageScore
867
- meanScore
868
- popularity
869
- favourites
870
- siteUrl
871
- }
929
+ ${MEDIA_RECOMMENDATION_FIELDS}
872
930
  user {
873
931
  id
874
932
  name
@@ -925,17 +983,7 @@ function buildMediaByIdQuery(include) {
925
983
  extra.push(`
926
984
  recommendations(perPage: ${perPage}, sort: [RATING_DESC]) {
927
985
  nodes {
928
- id
929
- rating
930
- mediaRecommendation {
931
- id
932
- title { romaji english native userPreferred }
933
- type
934
- format
935
- coverImage { large medium }
936
- averageScore
937
- siteUrl
938
- }
986
+ ${MEDIA_RECOMMENDATION_FIELDS}
939
987
  }
940
988
  }`);
941
989
  }
@@ -974,6 +1022,44 @@ query ($id: Int!) {
974
1022
  }
975
1023
  }`;
976
1024
  }
1025
+ function buildMediaCharactersQuery(options = {}) {
1026
+ const sortClause = options.sort === false ? "" : ", sort: [ROLE, RELEVANCE, ID]";
1027
+ const voiceActorBlock = options.voiceActors ? `
1028
+ voiceActors {
1029
+ ${VOICE_ACTOR_FIELDS_COMPACT}
1030
+ }` : "";
1031
+ return `
1032
+ query ($mediaId: Int!, $page: Int, $perPage: Int) {
1033
+ Media(id: $mediaId) {
1034
+ characters(page: $page, perPage: $perPage${sortClause}) {
1035
+ pageInfo { total perPage currentPage lastPage hasNextPage }
1036
+ edges {
1037
+ role
1038
+ node {
1039
+ ${CHARACTER_FIELDS_COMPACT}
1040
+ }${voiceActorBlock}
1041
+ }
1042
+ }
1043
+ }
1044
+ }`;
1045
+ }
1046
+ function buildMediaStaffQuery(options = {}) {
1047
+ const sortClause = options.sort === false ? "" : ", sort: [RELEVANCE, ID]";
1048
+ return `
1049
+ query ($mediaId: Int!, $page: Int, $perPage: Int) {
1050
+ Media(id: $mediaId) {
1051
+ staff(page: $page, perPage: $perPage${sortClause}) {
1052
+ pageInfo { total perPage currentPage lastPage hasNextPage }
1053
+ edges {
1054
+ role
1055
+ node {
1056
+ ${STAFF_FIELDS}
1057
+ }
1058
+ }
1059
+ }
1060
+ }
1061
+ }`;
1062
+ }
977
1063
  function buildBatchQuery(ids, typeName, fields, prefix) {
978
1064
  const aliases = ids.map((id, i) => `${prefix}${i}: ${typeName}(id: ${id}) { ${fields} }`).join("\n ");
979
1065
  return `query {
@@ -1032,6 +1118,75 @@ query {
1032
1118
  }
1033
1119
  }`;
1034
1120
 
1121
+ // src/queries/review.ts
1122
+ var QUERY_REVIEWS = `
1123
+ query ($page: Int, $perPage: Int, $sort: [ReviewSort], $mediaId: Int, $userId: Int) {
1124
+ Page(page: $page, perPage: $perPage) {
1125
+ pageInfo {
1126
+ total
1127
+ currentPage
1128
+ lastPage
1129
+ hasNextPage
1130
+ perPage
1131
+ }
1132
+ reviews(sort: $sort, mediaId: $mediaId, userId: $userId) {
1133
+ id
1134
+ userId
1135
+ mediaId
1136
+ mediaType
1137
+ summary
1138
+ body
1139
+ rating
1140
+ ratingAmount
1141
+ userRating
1142
+ score
1143
+ private
1144
+ siteUrl
1145
+ createdAt
1146
+ updatedAt
1147
+ user {
1148
+ id
1149
+ name
1150
+ avatar { large medium }
1151
+ siteUrl
1152
+ }
1153
+ media {
1154
+ ${MEDIA_FIELDS_LIGHT}
1155
+ }
1156
+ }
1157
+ }
1158
+ }
1159
+ `;
1160
+ var QUERY_REVIEW_BY_ID = `
1161
+ query ($id: Int) {
1162
+ Review(id: $id) {
1163
+ id
1164
+ userId
1165
+ mediaId
1166
+ mediaType
1167
+ summary
1168
+ body
1169
+ rating
1170
+ ratingAmount
1171
+ userRating
1172
+ score
1173
+ private
1174
+ siteUrl
1175
+ createdAt
1176
+ updatedAt
1177
+ user {
1178
+ id
1179
+ name
1180
+ avatar { large medium }
1181
+ siteUrl
1182
+ }
1183
+ media {
1184
+ ${MEDIA_FIELDS_BASE}
1185
+ }
1186
+ }
1187
+ }
1188
+ `;
1189
+
1035
1190
  // src/queries/staff.ts
1036
1191
  var QUERY_STAFF_BY_ID = `
1037
1192
  query ($id: Int!) {
@@ -1557,6 +1712,21 @@ var RecommendationSort = /* @__PURE__ */ ((RecommendationSort2) => {
1557
1712
  return RecommendationSort2;
1558
1713
  })(RecommendationSort || {});
1559
1714
 
1715
+ // src/types/review.ts
1716
+ var ReviewSort = /* @__PURE__ */ ((ReviewSort2) => {
1717
+ ReviewSort2["ID"] = "ID";
1718
+ ReviewSort2["ID_DESC"] = "ID_DESC";
1719
+ ReviewSort2["SCORE"] = "SCORE";
1720
+ ReviewSort2["SCORE_DESC"] = "SCORE_DESC";
1721
+ ReviewSort2["RATING"] = "RATING";
1722
+ ReviewSort2["RATING_DESC"] = "RATING_DESC";
1723
+ ReviewSort2["CREATED_AT"] = "CREATED_AT";
1724
+ ReviewSort2["CREATED_AT_DESC"] = "CREATED_AT_DESC";
1725
+ ReviewSort2["UPDATED_AT"] = "UPDATED_AT";
1726
+ ReviewSort2["UPDATED_AT_DESC"] = "UPDATED_AT_DESC";
1727
+ return ReviewSort2;
1728
+ })(ReviewSort || {});
1729
+
1560
1730
  // src/types/staff.ts
1561
1731
  var StaffSort = /* @__PURE__ */ ((StaffSort2) => {
1562
1732
  StaffSort2["ID"] = "ID";
@@ -1626,6 +1796,25 @@ async function getMedia(client, id, include) {
1626
1796
  const data = await client.request(query, { id });
1627
1797
  return data.Media;
1628
1798
  }
1799
+ async function getMediaCharacters(client, mediaId, options = {}) {
1800
+ validateId(mediaId, "mediaId");
1801
+ const query = buildMediaCharactersQuery(options);
1802
+ const data = await client.request(
1803
+ query,
1804
+ { mediaId, page: options.page ?? 1, perPage: clampPerPage(options.perPage ?? 25) }
1805
+ );
1806
+ return { pageInfo: data.Media.characters.pageInfo, results: data.Media.characters.edges };
1807
+ }
1808
+ async function getMediaStaff(client, mediaId, options = {}) {
1809
+ validateId(mediaId, "mediaId");
1810
+ const query = buildMediaStaffQuery(options);
1811
+ const data = await client.request(query, {
1812
+ mediaId,
1813
+ page: options.page ?? 1,
1814
+ perPage: clampPerPage(options.perPage ?? 25)
1815
+ });
1816
+ return { pageInfo: data.Media.staff.pageInfo, results: data.Media.staff.edges };
1817
+ }
1629
1818
  async function getMediaByMalId(client, malId, type) {
1630
1819
  validateId(malId, "malId");
1631
1820
  const data = await client.request(QUERY_MEDIA_BY_MAL_ID, {
@@ -1664,16 +1853,20 @@ async function searchMedia(client, options = {}) {
1664
1853
  );
1665
1854
  }
1666
1855
  async function getTrending(client, options) {
1667
- const { type = "ANIME" /* ANIME */, isAdult = false, page = 1, perPage = 20 } = options;
1668
- return client.pagedRequest(QUERY_TRENDING, { type, isAdult, page, perPage: clampPerPage(perPage) }, "media");
1856
+ const { type = "ANIME" /* ANIME */, isAdult = false, idNotIn = [], page = 1, perPage = 20 } = options;
1857
+ return client.pagedRequest(
1858
+ QUERY_TRENDING,
1859
+ { type, isAdult, idNotIn, page, perPage: clampPerPage(perPage) },
1860
+ "media"
1861
+ );
1669
1862
  }
1670
1863
  async function getPopular(client, options) {
1671
- const { type = "ANIME" /* ANIME */, isAdult = false, page = 1, perPage = 20 } = options;
1672
- return searchMedia(client, { type, isAdult, sort: ["POPULARITY_DESC" /* POPULARITY_DESC */], page, perPage });
1864
+ const { type = "ANIME" /* ANIME */, isAdult = false, idNotIn = [], page = 1, perPage = 20 } = options;
1865
+ return searchMedia(client, { type, isAdult, idNotIn, sort: ["POPULARITY_DESC" /* POPULARITY_DESC */], page, perPage });
1673
1866
  }
1674
1867
  async function getTopRated(client, options) {
1675
- const { type = "ANIME" /* ANIME */, isAdult = false, page = 1, perPage = 20 } = options;
1676
- return searchMedia(client, { type, isAdult, sort: ["SCORE_DESC" /* SCORE_DESC */], page, perPage });
1868
+ const { type = "ANIME" /* ANIME */, isAdult = false, idNotIn = [], page = 1, perPage = 20 } = options;
1869
+ return searchMedia(client, { type, isAdult, idNotIn, sort: ["SCORE_DESC" /* SCORE_DESC */], page, perPage });
1677
1870
  }
1678
1871
  async function getAiredEpisodes(client, options = {}) {
1679
1872
  const now = Math.floor(Date.now() / 1e3);
@@ -1682,7 +1875,7 @@ async function getAiredEpisodes(client, options = {}) {
1682
1875
  {
1683
1876
  airingAt_greater: options.airingAtGreater ?? now - 24 * 3600,
1684
1877
  airingAt_lesser: options.airingAtLesser ?? now,
1685
- isAdult: options.isAdult ?? false,
1878
+ idNotIn: options.idNotIn ?? [],
1686
1879
  sort: options.sort,
1687
1880
  page: options.page ?? 1,
1688
1881
  perPage: clampPerPage(options.perPage ?? 20)
@@ -1695,6 +1888,7 @@ async function getRecentlyUpdatedManga(client, options = {}) {
1695
1888
  QUERY_RECENT_CHAPTERS,
1696
1889
  {
1697
1890
  isAdult: options.isAdult ?? false,
1891
+ idNotIn: options.idNotIn ?? [],
1698
1892
  page: options.page ?? 1,
1699
1893
  perPage: clampPerPage(options.perPage ?? 20)
1700
1894
  },
@@ -1707,6 +1901,7 @@ async function getPlanning(client, options = {}) {
1707
1901
  {
1708
1902
  type: options.type,
1709
1903
  isAdult: options.isAdult ?? false,
1904
+ idNotIn: options.idNotIn ?? [],
1710
1905
  sort: options.sort ?? ["POPULARITY_DESC" /* POPULARITY_DESC */],
1711
1906
  page: options.page ?? 1,
1712
1907
  perPage: clampPerPage(options.perPage ?? 20)
@@ -1735,6 +1930,7 @@ async function getMediaBySeason(client, options) {
1735
1930
  seasonYear: options.seasonYear,
1736
1931
  type: options.type,
1737
1932
  isAdult: options.isAdult ?? false,
1933
+ idNotIn: options.idNotIn ?? [],
1738
1934
  sort: options.sort,
1739
1935
  page: options.page ?? 1,
1740
1936
  perPage: clampPerPage(options.perPage ?? 20)
@@ -1742,7 +1938,7 @@ async function getMediaBySeason(client, options) {
1742
1938
  "media"
1743
1939
  );
1744
1940
  }
1745
- async function getWeeklySchedule(client, date = /* @__PURE__ */ new Date(), isAdult = false) {
1941
+ async function getWeeklySchedule(client, date = /* @__PURE__ */ new Date(), idNotIn) {
1746
1942
  const schedule = {
1747
1943
  Monday: [],
1748
1944
  Tuesday: [],
@@ -1764,7 +1960,7 @@ async function getWeeklySchedule(client, date = /* @__PURE__ */ new Date(), isAd
1764
1960
  (page) => getAiredEpisodes(client, {
1765
1961
  airingAtGreater: startTimestamp,
1766
1962
  airingAtLesser: endTimestamp,
1767
- isAdult,
1963
+ idNotIn,
1768
1964
  page,
1769
1965
  perPage: 50
1770
1966
  }),
@@ -1779,6 +1975,17 @@ async function getWeeklySchedule(client, date = /* @__PURE__ */ new Date(), isAd
1779
1975
  return schedule;
1780
1976
  }
1781
1977
 
1978
+ // src/client/review.ts
1979
+ async function getReview(client, id) {
1980
+ validateId(id, "reviewId");
1981
+ const data = await client.request(QUERY_REVIEW_BY_ID, { id });
1982
+ return data.Review;
1983
+ }
1984
+ async function searchReviews(client, options = {}) {
1985
+ const { mediaId, userId, sort, page = 1, perPage = 20 } = options;
1986
+ return client.pagedRequest(QUERY_REVIEWS, { mediaId, userId, sort, page, perPage }, "reviews");
1987
+ }
1988
+
1782
1989
  // src/client/staff.ts
1783
1990
  async function getStaff(client, id, include) {
1784
1991
  validateId(id, "staffId");
@@ -1910,7 +2117,7 @@ function mapFavorites(fav) {
1910
2117
 
1911
2118
  // src/client/index.ts
1912
2119
  var DEFAULT_API_URL = "https://graphql.anilist.co";
1913
- var LIB_VERSION = "2.0.2" ;
2120
+ var LIB_VERSION = "2.1.0" ;
1914
2121
  var AniListClient = class {
1915
2122
  apiUrl;
1916
2123
  headers;
@@ -2053,6 +2260,12 @@ var AniListClient = class {
2053
2260
  async getMedia(id, include) {
2054
2261
  return getMedia(this, id, include);
2055
2262
  }
2263
+ async getMediaCharacters(mediaId, options = {}) {
2264
+ return getMediaCharacters(this, mediaId, options);
2265
+ }
2266
+ async getMediaStaff(mediaId, options = {}) {
2267
+ return getMediaStaff(this, mediaId, options);
2268
+ }
2056
2269
  /**
2057
2270
  * Search for anime or manga.
2058
2271
  *
@@ -2087,7 +2300,7 @@ var AniListClient = class {
2087
2300
  return getRecentlyUpdatedManga(this, options);
2088
2301
  }
2089
2302
  /**
2090
- * @deprecated Use `getRecentlyUpdatedManga` instead. This alias will be removed in v2.
2303
+ * @deprecated Use `getRecentlyUpdatedManga()` instead. This alias will be removed in v3.
2091
2304
  */
2092
2305
  async getAiredChapters(options = {}) {
2093
2306
  return this.getRecentlyUpdatedManga(options);
@@ -2168,6 +2381,23 @@ var AniListClient = class {
2168
2381
  async getUserFavorites(idOrName, options) {
2169
2382
  return getUserFavorites(this, idOrName, options);
2170
2383
  }
2384
+ /**
2385
+ * Fetch a review by its AniList ID.
2386
+ *
2387
+ * @param id - The AniList review ID
2388
+ */
2389
+ async getReview(id) {
2390
+ return getReview(this, id);
2391
+ }
2392
+ /**
2393
+ * Search for reviews with optional filters.
2394
+ *
2395
+ * @param options - Search and filter options
2396
+ * @returns Paginated results with matching reviews
2397
+ */
2398
+ async searchReviews(options = {}) {
2399
+ return searchReviews(this, options);
2400
+ }
2171
2401
  /**
2172
2402
  * Fetch a studio by its AniList ID.
2173
2403
  * Pass `include` to customise the number of media returned.
@@ -2328,6 +2558,7 @@ exports.MemoryCache = MemoryCache;
2328
2558
  exports.RateLimiter = RateLimiter;
2329
2559
  exports.RecommendationSort = RecommendationSort;
2330
2560
  exports.RedisCache = RedisCache;
2561
+ exports.ReviewSort = ReviewSort;
2331
2562
  exports.StaffSort = StaffSort;
2332
2563
  exports.StudioSort = StudioSort;
2333
2564
  exports.ThreadSort = ThreadSort;