Skip to content

Commit b5f0d88

Browse files
committed
feat: hianime + some fixes
1 parent 0381276 commit b5f0d88

File tree

12 files changed

+389
-343
lines changed

12 files changed

+389
-343
lines changed

src/modules/animeCustomTitles.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@ export const animeCustomTitles: AnimeCustomTitles = {
2323
'168623': { title: 'Dahlia in Bloom', index: 0 }, // anilist has wrong name (Madougushi Dahlia wa Utsumukanai -> Madougushi Dahliya wa Utsumukanai)
2424
},
2525
ANIX: {},
26+
HIANIME: {},
2627
ANIMEUNITY: {},
2728
};

src/modules/providers/animeunity.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { IVideo } from '@consumet/extensions';
1+
import { ISource, IVideo } from '@consumet/extensions';
22
import { SOFAMAXXING_URL } from '../../constants/utils';
33
import { getCacheId } from '../utils';
44
import { apiRequest } from './api';
@@ -33,7 +33,9 @@ class AnimeUnityApi {
3333
return cache.animeIds[animeSearch];
3434

3535
// search anime (per dub too)
36-
const searchResults = await apiRequest(`${api}/${animeSearch}`);
36+
const searchResults = await apiRequest(
37+
`${api}/${dubbed ? `${animeSearch} (ITA)` : animeSearch}`,
38+
);
3739
const filteredResults = searchResults.results.filter((result: any) =>
3840
dubbed
3941
? (result.title as string).includes('(ITA)')
@@ -46,7 +48,8 @@ class AnimeUnityApi {
4648
const animeResult = (cache.animeIds[animeSearch] =
4749
filteredResults.filter(
4850
(result: any) =>
49-
result.title == animeSearch ||
51+
result.title.toLowerCase().trim() ==
52+
animeSearch.toLowerCase().trim() ||
5053
result.releaseDate == releaseDate.toString(),
5154
)[index] ?? null);
5255

@@ -73,7 +76,7 @@ class AnimeUnityApi {
7376

7477
if (episodeId) {
7578
const video = await apiRequest(`${api}/episode/${episodeId}`);
76-
return video.sources as IVideo[];
79+
return video as ISource;
7780
}
7881

7982
// episode not found

src/modules/providers/anix.ts

Lines changed: 69 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,79 @@
1-
import { IVideo } from '@consumet/extensions';
2-
import Anix from '@consumet/extensions/dist/providers/anime/anix';
3-
import ProviderCache from './cache';
1+
import { ISource, IVideo } from '@consumet/extensions';
2+
import { SOFAMAXXING_URL } from '../../constants/utils';
43
import { getCacheId } from '../utils';
4+
import { apiRequest } from './api';
5+
import ProviderCache from './cache';
56

7+
const api = `${SOFAMAXXING_URL}/anix`;
68
const cache = new ProviderCache();
7-
const consumet = new Anix();
89

9-
export const getEpisodeUrl = async (
10-
animeTitles: string[],
11-
index: number,
12-
episode: number,
13-
dubbed: boolean,
14-
releaseDate: number,
15-
): Promise<IVideo[] | null> => {
16-
console.log(
17-
`%c Episode ${episode}, looking for ${consumet.name} source...`,
18-
`color: #0fe2fd`,
19-
);
20-
21-
for (const animeSearch of animeTitles) {
22-
const result = await searchEpisodeUrl(
23-
animeSearch,
24-
index,
25-
episode,
26-
dubbed,
27-
releaseDate,
10+
class AnixApi {
11+
/**
12+
*
13+
* @returns animeId from provider
14+
*/
15+
searchInProvider = async (
16+
animeTitles: string[],
17+
index: number,
18+
episode: number,
19+
dubbed: boolean,
20+
releaseDate: number,
21+
) => {
22+
console.log(
23+
`%c Episode ${episode}, looking for Anix match...`,
24+
`color: #0fe2fd`,
2825
);
29-
if (result) {
30-
return result;
31-
}
32-
}
33-
34-
return null;
35-
};
36-
37-
/**
38-
* Gets the episode url and isM3U8 flag
39-
*
40-
* @param {*} animeSearch
41-
* @param {*} episode anime episode to look for
42-
* @param {*} dubbed dubbed version or not
43-
* @returns IVideo sources if found, null otherwise
44-
*/
45-
async function searchEpisodeUrl(
46-
animeSearch: string,
47-
index: number,
48-
episode: number,
49-
dubbed: boolean,
50-
releaseDate: number,
51-
): Promise<IVideo[] | null> {
52-
const cacheId = getCacheId(animeSearch, episode, dubbed);
53-
54-
if (cache.search[cacheId] !== undefined) return cache.search[cacheId];
55-
56-
const animeId = await getAnimeId(index, animeSearch, releaseDate);
5726

58-
if (animeId) {
59-
const animeEpisodeId = await getAnimeEpisodeId(animeId, episode);
60-
if (animeEpisodeId) {
61-
const data = await consumet.fetchEpisodeSources(
62-
animeId,
63-
animeEpisodeId,
64-
undefined,
65-
dubbed ? 'dub' : 'sub',
66-
);
67-
console.log(`%c ${animeSearch}`, `color: #45AD67`);
68-
const result = (cache.search[cacheId] = data.sources);
69-
return result;
27+
// start searching
28+
for (const animeSearch of animeTitles) {
29+
// first, check cache
30+
const cacheId = getCacheId(animeSearch, episode, dubbed);
31+
if (cache.search[cacheId] !== undefined) return cache.search[cacheId];
32+
if (cache.animeIds[animeSearch] !== undefined)
33+
return cache.animeIds[animeSearch];
34+
35+
// search anime (per dub too)
36+
const searchResults = await apiRequest(`${api}/${animeSearch}`);
37+
// how to check dub???
38+
39+
// find the best result: first check for same name,
40+
// then check for same release date.
41+
// finally, update cache
42+
const animeResult = (cache.animeIds[animeSearch] =
43+
searchResults.results.filter(
44+
(result: any) =>
45+
result.title.toLowerCase().trim() ==
46+
animeSearch.toLowerCase().trim() ||
47+
result.releaseDate == releaseDate.toString(),
48+
)[index] ?? null);
49+
50+
return animeResult;
51+
}
52+
};
53+
54+
getEpisodeSource = async (animeId: string, episode: number) => {
55+
// first, check cache
56+
// if(cache.episodes[animeId] !== undefined) {
57+
// const found = cache.episodes[animeId]?.find((ep) => ep.number == episode)
58+
// if(found)
59+
// return found.id;
60+
// }
61+
62+
const animeInfo = await apiRequest(`${api}/info/${animeId}`);
63+
64+
const episodeId =
65+
(cache.episodes[animeId] = animeInfo?.episodes)?.find(
66+
(ep: any) => ep.number == episode,
67+
)?.id ?? null;
68+
69+
if (episodeId) {
70+
const video = await apiRequest(`${api}/episode/${animeId}/${episodeId}`);
71+
return video as ISource;
7072
}
71-
}
7273

73-
cache.search[cacheId] = null;
74-
console.log(`%c ${animeSearch}`, `color: #E5A639`);
75-
return null;
74+
// episode not found
75+
return null;
76+
};
7677
}
7778

78-
/**
79-
* Gets the anime id
80-
*
81-
* @param {*} animeSearch
82-
* @returns anime id if found, otherwise null
83-
*/
84-
export const getAnimeId = async (
85-
index: number,
86-
animeSearch: string,
87-
releaseDate: number,
88-
): Promise<string | null> => {
89-
if (cache.animeIds[animeSearch] !== undefined)
90-
return cache.animeIds[animeSearch];
91-
92-
const data = await consumet.search(animeSearch);
93-
94-
const result = (cache.animeIds[animeSearch] =
95-
data.results.filter(
96-
(result) =>
97-
result.releaseDate == releaseDate.toString() ||
98-
result.title == animeSearch,
99-
)[index]?.id ?? null);
100-
101-
return result;
102-
};
103-
104-
/**
105-
* Gets the anime episode id
106-
*
107-
* @param {*} animeId
108-
* @param {*} episode
109-
* @returns anime episode id if found, otherwise null
110-
*/
111-
export const getAnimeEpisodeId = async (
112-
animeId: string,
113-
episode: number,
114-
): Promise<string | null> => {
115-
if (cache.episodes[animeId] !== undefined) {
116-
const found = cache.episodes[animeId]?.find((ep) => ep.number == episode);
117-
118-
if (found) return found.id;
119-
}
120-
121-
const data = await consumet.fetchAnimeInfo(animeId);
122-
return (
123-
(cache.episodes[animeId] = data?.episodes)?.find(
124-
(ep) => ep.number == episode,
125-
)?.id ?? null
126-
);
127-
};
79+
export default AnixApi;

src/modules/providers/api.ts

Lines changed: 57 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1+
import 'dotenv/config';
2+
13
import { IVideo } from '@consumet/extensions';
4+
import axios from 'axios';
25
import Store from 'electron-store';
3-
import 'dotenv/config';
6+
47
import { ListAnimeData } from '../../types/anilistAPITypes';
58
import { animeCustomTitles } from '../animeCustomTitles';
69
import { getParsedAnimeTitles } from '../utils';
710
import AnimeUnityApi from './animeunity';
8-
import { getEpisodeUrl as gogoanime } from './gogoanime';
9-
import axios from 'axios';
11+
import AnixApi from './anix';
12+
import GogoanimeApi from './gogoanime';
13+
import HiAnimeAPI from './hianime';
1014

1115
const STORE = new Store();
1216

@@ -28,16 +32,36 @@ export const searchAnimeInProvider = async (
2832
console.log(lang + ' ' + dubbed + ' ' + customTitle?.title);
2933

3034
switch (lang) {
31-
// case 'GOGOANIME': {
32-
// const data = await gogoanime(
33-
// animeTitles,
34-
// customTitle ? customTitle.index : 0,
35-
// episode,
36-
// dubbed,
37-
// listAnimeData.media.startDate?.year ?? 0,
38-
// );
39-
// return data ? getDefaultQualityVideo(data) : null;
40-
// }
35+
case 'HIANIME': {
36+
const api = new HiAnimeAPI();
37+
return await api.searchInProvider(
38+
animeTitles,
39+
customTitle ? customTitle.index : 0,
40+
episode,
41+
dubbed,
42+
listAnimeData.media.startDate?.year ?? 0,
43+
);
44+
}
45+
case 'ANIX': {
46+
const api = new AnixApi();
47+
return await api.searchInProvider(
48+
animeTitles,
49+
customTitle ? customTitle.index : 0,
50+
episode,
51+
dubbed,
52+
listAnimeData.media.startDate?.year ?? 0,
53+
);
54+
}
55+
case 'GOGOANIME': {
56+
const api = new GogoanimeApi();
57+
return await api.searchInProvider(
58+
animeTitles,
59+
customTitle ? customTitle.index : 0,
60+
episode,
61+
dubbed,
62+
listAnimeData.media.startDate?.year ?? 0,
63+
);
64+
}
4165
case 'ANIMEUNITY': {
4266
const api = new AnimeUnityApi();
4367
return await api.searchInProvider(
@@ -60,11 +84,29 @@ export const getSourceFromProvider = async (
6084
const lang = (await STORE.get('source_flag')) as string;
6185

6286
switch (lang) {
87+
case 'HIANIME': {
88+
const api = new HiAnimeAPI();
89+
const source = await api.getEpisodeSource(providerAnimeId, episode);
90+
91+
return source;
92+
}
93+
case 'ANIX': {
94+
const api = new AnixApi();
95+
const source = await api.getEpisodeSource(providerAnimeId, episode);
96+
97+
return source;
98+
}
99+
case 'GOGOANIME': {
100+
const api = new GogoanimeApi();
101+
const source = await api.getEpisodeSource(providerAnimeId, episode);
102+
103+
return source;
104+
}
63105
case 'ANIMEUNITY': {
64106
const api = new AnimeUnityApi();
65-
const video = await api.getEpisodeSource(providerAnimeId, episode);
107+
const source = await api.getEpisodeSource(providerAnimeId, episode);
66108

67-
return video !== null ? getBestQualityVideo(video) : null;
109+
return source;
68110
}
69111
}
70112

@@ -133,22 +175,3 @@ export const getUniversalEpisodeUrl = async (
133175

134176
return null;
135177
};
136-
137-
const getDefaultQualityVideo = (videos: IVideo[]): IVideo =>
138-
videos.find((video) => video.quality === 'default') ??
139-
getBestQualityVideo(videos);
140-
141-
const getBestQualityVideo = (videos: IVideo[]): IVideo => {
142-
const qualityOrder = ['1080p', '720p', '480p', '360p', 'default', 'backup'];
143-
144-
videos.sort((a, b) => {
145-
const indexA = qualityOrder.indexOf(a.quality || 'default');
146-
const indexB = qualityOrder.indexOf(b.quality || 'default');
147-
148-
if (indexA < indexB) return -1;
149-
if (indexA > indexB) return 1;
150-
return 0;
151-
});
152-
153-
return videos[0];
154-
};

0 commit comments

Comments
 (0)