.
675 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | AniKimi API v0.1.4
2 | A Simple, LightWeight, Statically-Typed Python3 API wrapper for GogoAnime
3 | The v2 of gogoanimeapi (depreciated)
4 | Made with JavaScript and Python3
5 |
6 | ###
7 |
8 |
9 |

10 |

11 |

12 |

13 |

14 |

15 |

16 |
17 |
18 | ###
19 |
20 | ### Features of AniKimi
21 | * Custom url changing option.
22 | * Statically-Typed, No more annoying JSON responses.
23 | * Autocomplete supported by most IDE's.
24 | * Complete solution.
25 | * Faster response.
26 | * Less CPU consumption.
27 |
28 | ### Installing
29 | Using Pypi
30 |
31 | ```$ pip3 install anikimiapi```
32 |
33 | ### Getting Started
34 | #### Pre-Requisites
35 | * #### Getting Required Tokens
36 | * Visit the GogoAnime Website.
37 | * Login or SignUp using ur email or google.
38 | * Add an extension to your browser named [Get cookies.txt](https://chrome.google.com/webstore/detail/get-cookiestxt/bgaddhkoddajcdgocldbbfleckgcbcid?hl=en).
39 | * Now in the GogoAnime Website, right click and select "Get cookies.txt". [Refer Image](https://github.com/BaraniARR/anikimiapi/blob/main/assets/1.jpg).
40 | * A `.txt` file will be downloaded.
41 | * In the `.txt` file, find the name "gogoanime" and "auth". [Refer Image](https://github.com/BaraniARR/anikimiapi/blob/main/assets/2.jpg).
42 | * Copy the respective tokens on the right side of the above names.
43 | * Keep it safely, since its your private credentials.
44 |
45 | ### Diving into the API
46 | ###
47 | #### Authorize the API
48 | To Authorize the API, use AniKimi class. You can also import it from other files. It also supports cross imports. But all API request should be made using this class only.
49 | ```python3
50 | from anikimiapi import AniKimi
51 |
52 | # Initialize AniKimi class
53 | anime = AniKimi(
54 | gogoanime_token="the saved gogoanime token",
55 | auth_token="the saved auth token",
56 | host="https://gogoanime.pe/"
57 | )
58 | ```
59 | ###
60 | >**Note:** If GogoAnime changes their domain, use the 'host' parameter. Otherwise, leave it blank. This parameter was optional and defaults to https://gogoanime.pe/
61 | ###
62 | #### Getting Anime search results
63 | You can search anime by using `search_anime` method, It returns the search results as `ResultObject` which contains two arguments, the `title` and `animeid`.
64 | ```python3
65 | from anikimiapi import AniKimi
66 |
67 | anime = AniKimi(
68 | gogoanime_token="the saved gogoanime token",
69 | auth_token="the saved auth token"
70 | )
71 |
72 | # Search Anime
73 | results = anime.search_anime(query="tokikaku kawaii")
74 |
75 | for i in results:
76 | print(i.title) # (or)
77 | print(i.animeid)
78 | ```
79 |
80 | ###
81 | >**Note:** If no search results found, the API will raise `NoSearchResultsError` error. Make sure to handle it.
82 | ###
83 | #### Getting details of a specific Anime
84 | You can the basic information about a specific anime with `animeid` using `get_details` method. It will return anime details as `MediaInfoObject`.
85 |
86 | The `MediaInfoObject` contains the following arguments,
87 | * title
88 | * other_names
89 | * season
90 | * year
91 | * status
92 | * genres
93 | * episodes
94 | * image_url
95 | * summary
96 | ```python
97 | from anikimiapi import AniKimi
98 |
99 | anime = AniKimi(
100 | gogoanime_token="the saved gogoanime token",
101 | auth_token="the saved auth token"
102 | )
103 |
104 | # Get anime Details
105 | details = anime.get_details(animeid="clannad-dub")
106 | print(details.title)
107 | print(details.genres) # And many more...
108 | ```
109 |
110 | ###
111 | >**Note:** If an Invalid `animeid` is given, the API will raise `InvalidAnimeIdError`. Make sure to handle it.
112 | ###
113 | #### Getting the Anime Links
114 | You can simply get the streamable and downloadable links of a specific episode of an Anime by its `animeid` and `episode_num` using `get_episode_link` method. It will return anime links in `MediaLinksObject`.
115 |
116 | The `MediaLinksObject` returns the links, if available. Otherwise, it will return `None`. The `MediaLinksObject` has the following arguments,
117 | * link_hdp
118 | * link_sdp
119 | * link_360p
120 | * link_480p
121 | * link_720p
122 | * link_1080p
123 | * link_streamsb
124 | * link_xstreamcdn
125 | * link_streamtape
126 | * link_mixdrop
127 | * link_mp4upload
128 | * link_doodstream
129 | ```python3
130 | from anikimiapi import AniKimi
131 |
132 | anime = AniKimi(
133 | gogoanime_token="the saved gogoanime token",
134 | auth_token="the saved auth token"
135 | )
136 |
137 | # Getting Anime Links basic method
138 | anime_link = anime.get_episode_link_basic(animeid="clannad-dub", episode_num=3)
139 |
140 | print(anime_link.link_hdp)
141 | print(anime_link.link_720p)
142 | print(anime_link.link_streamsb) # And many more...
143 |
144 | # Getting Anime Links advanced method
145 | anime_link = anime.get_episode_link_advanced(animeid="clannad-dub", episode_num=3)
146 |
147 | print(anime_link.link_hdp)
148 | print(anime_link.link_720p)
149 | print(anime_link.link_streamsb) # And many more...
150 | ```
151 | ###
152 | >**Note:** If invalid `animeid` or `episode_num` is passed, the API will return `InvalidAnimeIdError`. Make sure to handle it.
153 | >
154 | > If the given `gogoanime_token` and `auth_token` are invalid, the API will raise `InvalidTokenError`. So, be careful of that.
155 | ###
156 | #### Getting a List of anime by Genre
157 | You can also get the List of anime by their genres using `get_by_genres` method. This method will return results as a List of `ResultObject`.
158 |
159 | Currently, the following genres are supported,
160 | * action
161 | * adventure
162 | * cars
163 | * comedy
164 | * dementia
165 | * demons
166 | * drama
167 | * dub
168 | * ecchi
169 | * fantasy
170 | * game
171 | * harem
172 | * hentai - Temporarily Unavailable
173 | * historical
174 | * horror
175 | * josei
176 | * kids
177 | * magic
178 | * martial-arts
179 | * mecha
180 | * military
181 | * music
182 | * mystery
183 | * parody
184 | * police
185 | * psychological
186 | * romance
187 | * samurai
188 | * school
189 | * sci-fi
190 | * seinen
191 | * shoujo
192 | * shoujo-ai
193 | * shounen-ai
194 | * shounen
195 | * slice-of-life
196 | * space
197 | * sports
198 | * super-power
199 | * supernatural
200 | * thriller
201 | * vampire
202 | * yaoi
203 | * yuri
204 | ```python
205 | from anikimiapi import AniKimi
206 |
207 | anime = AniKimi(
208 | gogoanime_token="the saved gogoanime token",
209 | auth_token="the saved auth token"
210 | )
211 |
212 | # Getting anime list by genres
213 | gen = anime.get_by_genres(genre_name="romance", page=1)
214 |
215 | for result in gen:
216 | print(result.title)
217 | print(result.animeid)
218 | ```
219 | ###
220 | >**Note:** If invalid `genre_name` or `page` is passed, the API will raise `InvalidGenreNameError`. Make sure to handle it.
221 | ###
222 | #### Getting List of Airing Anime (v2 API New Feature)
223 | You can get a List of currently Airing Anime using `get_airing_anime` method. This method will return results as a List of `ResultObject`.
224 | ```python
225 | from anikimiapi import AniKimi
226 |
227 | anime = AniKimi(
228 | gogoanime_token="the saved gogoanime token",
229 | auth_token="the saved auth token"
230 | )
231 |
232 | # Getting Airing Anime List
233 | airing = anime.get_airing_anime(count=15)
234 | for i in airing:
235 | print(i.title)
236 | print(i.animeid)
237 | ```
238 | ###
239 | >**Note:** If the value of count exceeds 20, The API will raise `AiringIndexError`. So, pass a value less than or equal to 20.
240 |
241 | # Copyrights ©2021 BaraniARR;
242 | ### Licensed under GNU GPLv3 Licnense;
243 |
--------------------------------------------------------------------------------
/README_PYPI.md:
--------------------------------------------------------------------------------
1 | AniKimi API
2 | A Simple, LightWeight, Statically-Typed Python3 API wrapper for GogoAnime
3 | The v2 of gogoanimeapi (depreciated)
4 | Made with JavaScript and Python3
5 |
6 |
7 | ###
8 |
9 |
10 |

11 |

12 |

13 |

14 |

15 |
16 |
17 | ###
18 | ```
19 | from anikimiapi import AniKimi
20 |
21 | anime = AniKimi(
22 | gogoanime_token="dbakbihihrkqnk3",
23 | auth_token="EKWBIH4NJTO309U4HKTHI39U9TJ5OJ0UU5J9"
24 | )
25 |
26 | # Getting Anime Links
27 | anime_link = anime.get_episode_link(animeid="clannad-dub", episode_num=3)
28 |
29 | print(anime_link.link_hdp)
30 | print(anime_link.link_720p)
31 | print(anime_link.link_streamsb) # And many more...
32 | ```
33 |
34 | ### Features of AniKimi
35 | * Custom url changing option.
36 | * Statically-Typed, No more annoying JSON responses.
37 | * Autocomplete supported by most IDE's.
38 | * Complete solution.
39 | * Faster response.
40 | * Less CPU consumption.
41 |
42 | ###
43 | #### For full usage instructions, Head over to the [GitHub Page](https://github.com/BaraniARR/anikimiapi).
--------------------------------------------------------------------------------
/anikimiapi/__init__.py:
--------------------------------------------------------------------------------
1 | from anikimiapi.anikimi import AniKimi
--------------------------------------------------------------------------------
/anikimiapi/anikimi.py:
--------------------------------------------------------------------------------
1 | from requests_html import HTMLSession
2 | from bs4 import BeautifulSoup
3 | import requests
4 | from anikimiapi.data_classes import *
5 | from anikimiapi.error_handlers import *
6 | import re
7 |
8 |
9 | class AniKimi:
10 | """The `AniKimi` class which authorizes the gogoanime client.
11 |
12 | Parameters:
13 | gogoanime_token (``str``):
14 | To get this token, please refer to readme.md in the repository.
15 | auth_token (``str``):
16 | To get this token, please refer to readme.md in the repository.
17 | host (``str``):
18 | Change the base url, If gogoanime changes the domain, replace the url
19 | with the new domain. Defaults to https://gogoanime.pe/ .
20 |
21 | Example:
22 | .. code-block:: python
23 | :emphasize-lines: 1,4-7
24 |
25 | from anikimiapi import AniKimi
26 |
27 | # Authorize the api to GogoAnime
28 | anime = AniKimi(
29 | gogoanime_token="baikdk32hk1nrek3hw9",
30 | auth_token="NCONW9H48HNFONW9Y94NJT49YTHO45TU4Y8YT93HOGFNRKBI"
31 | )
32 |
33 |
34 |
35 | """
36 | def __init__(
37 | self,
38 | gogoanime_token: str,
39 | auth_token: str,
40 | host: str = "https://gogoanime.pe/"
41 | ):
42 | self.gogoanime_token = gogoanime_token
43 | self.auth_token = auth_token
44 | self.host = host
45 |
46 | def __str__(self) -> str:
47 | return "Anikimi API - Copyrights (c) 2020-2021 BaraniARR."
48 |
49 |
50 | def search_anime(self, query: str) -> list:
51 | """The method used to search anime when a query string is passed
52 |
53 | Parameters:
54 | query(``str``):
55 | The query String which was to be searched in the API.
56 |
57 | Returns:
58 | List of :obj:`-anikimiapi.data_classes.ResultObject`: On Success, the list of search results is returned.
59 |
60 | Example:
61 | .. code-block:: python
62 | :emphasize-lines: 1,4-7,10-13
63 |
64 | from anikimiapi import AniKimi
65 |
66 | # Authorize the api to GogoAnime
67 | anime = AniKimi(
68 | gogoanime_token="baikdk32hk1nrek3hw9",
69 | auth_token="NCONW9H48HNFONW9Y94NJT49YTHO45TU4Y8YT93HOGFNRKBI"
70 | )
71 |
72 | # Get search Results
73 | search_results = anime.search_anime(query="clannad")
74 | for results in search_results:
75 | print(results.title)
76 | print(results.animeid)
77 |
78 | """
79 | try:
80 | url1 = f"{self.host}/search.html?keyword={query}"
81 | session = HTMLSession()
82 | response = session.get(url1)
83 | response_html = response.text
84 | soup = BeautifulSoup(response_html, 'html.parser')
85 | animes = soup.find("ul", {"class": "items"}).find_all("li")
86 | res_list_search = []
87 | for anime in animes: # For every anime found
88 | tit = anime.a["title"]
89 | urll = anime.a["href"]
90 | r = urll.split('/')
91 | res_list_search.append(ResultObject(title=f"{tit}", animeid=f"{r[2]}"))
92 | if not res_list_search:
93 | raise NoSearchResultsError("No Search Results found for the query")
94 | else:
95 | return res_list_search
96 | except requests.exceptions.ConnectionError:
97 | raise NetworkError("Unable to connect to the Server, Check your connection")
98 |
99 | def get_details(self, animeid: str) -> MediaInfoObject:
100 | """Get the basic details of anime using an animeid parameter.
101 |
102 | Parameters:
103 | animeid(``str``):
104 | The animeid of the anime which you want to get the details.
105 |
106 | Returns:
107 | :obj:`-anikimiapi.data_classes.MediaInfoObject`: On success, the details of anime is returned as ``MediaInfoObject`` object.
108 |
109 | Example:
110 | .. code-block:: python
111 | :emphasize-lines: 1,4-7,10-12
112 |
113 | from anikimiapi import AniKimi
114 |
115 | # Authorize the api to GogoAnime
116 | anime = AniKimi(
117 | gogoanime_token="baikdk32hk1nrek3hw9",
118 | auth_token="NCONW9H48HNFONW9Y94NJT49YTHO45TU4Y8YT93HOGFNRKBI"
119 | )
120 |
121 | # Get anime Details
122 | details = anime.get_details(animeid="clannad-dub")
123 | print(details.image_url) # gives the url of the cover image
124 | print(details.status) # gives the status whether airing or completed
125 |
126 | # And many more...
127 | """
128 | try:
129 | animelink = f'{self.host}category/{animeid}'
130 | response = requests.get(animelink)
131 | plainText = response.text
132 | soup = BeautifulSoup(plainText, "lxml")
133 | source_url = soup.find("div", {"class": "anime_info_body_bg"}).img
134 | imgg = source_url.get('src')
135 | tit_url = soup.find("div", {"class": "anime_info_body_bg"}).h1.string
136 | lis = soup.find_all('p', {"class": "type"})
137 | plot_sum = lis[1]
138 | pl = plot_sum.get_text().split(':')
139 | pl.remove(pl[0])
140 | sum = ""
141 | plot_summary = sum.join(pl)
142 | type_of_show = lis[0].a['title']
143 | ai = lis[2].find_all('a') # .find_all('title')
144 | genres = []
145 | for link in ai:
146 | genres.append(link.get('title'))
147 | year1 = lis[3].get_text()
148 | year2 = year1.split(" ")
149 | year = year2[1]
150 | status = lis[4].a.get_text()
151 | oth_names = lis[5].get_text()
152 | lnk = soup.find(id="episode_page")
153 | ep_str = str(lnk.contents[-2])
154 | a_tag = ep_str.split("\n")[-2]
155 | a_tag_sliced = a_tag[:-4].split(">")
156 | last_ep_range = a_tag_sliced[-1]
157 | y = last_ep_range.split("-")
158 | ep_num = y[-1]
159 | res_detail_search = MediaInfoObject(
160 | title=f"{tit_url}",
161 | year=int(year),
162 | other_names=f"{oth_names}",
163 | season=f"{type_of_show}",
164 | status=f"{status}",
165 | genres=genres,
166 | episodes=int(ep_num),
167 | image_url=f"{imgg}",
168 | summary=f"{plot_summary}"
169 | )
170 | return res_detail_search
171 | except AttributeError:
172 | raise InvalidAnimeIdError("Invalid animeid given")
173 | except requests.exceptions.ConnectionError:
174 | raise NetworkError("Unable to connect to the Server, Check your connection")
175 |
176 | def get_episode_link_advanced(self, animeid: str, episode_num: int) -> MediaLinksObject:
177 | """Get streamable and downloadable links for a given animeid and episode number.
178 | If the link is not found, then this method will return ``None`` .
179 |
180 | Parameters:
181 | animeid(``str``):
182 | The animeid of the anime you want to download.
183 |
184 | episode_num(``int``):
185 | The episode number of the anime you want to download.
186 |
187 | Returns:
188 | :obj:`-anikimiapi.data_classes.MediaLinksObject`: On success, the links of the anime is returned.
189 |
190 | Example:
191 | .. code-block:: python
192 | :emphasize-lines: 1,4-7,10-13
193 |
194 | from anikimiapi import AniKimi
195 |
196 | # Authorize the api to GogoAnime
197 | anime = AniKimi(
198 | gogoanime_token="baikdk32hk1nrek3hw9",
199 | auth_token="NCONW9H48HNFONW9Y94NJT49YTHO45TU4Y8YT93HOGFNRKBI"
200 | )
201 |
202 | # Get anime Link
203 | link = anime.get_episode_link(animeid="clannad-dub", episode_num=3)
204 | print(link.link_hdp)
205 | print(link.link_360p)
206 | print(link.link_streamtape)
207 |
208 | # and many more...
209 | """
210 | try:
211 | ep_num_link_get = episode_num
212 | str_qry_final = animeid
213 | animelink = f'{self.host}category/{str_qry_final}'
214 | response = requests.get(animelink)
215 | plainText = response.text
216 | soup = BeautifulSoup(plainText, "lxml")
217 | lnk = soup.find(id="episode_page")
218 | source_url = lnk.find("li").a
219 | anime_title = soup.find("div", {"class": "anime_info_body_bg"}).h1.string
220 | ep_num_tot = source_url.get("ep_end")
221 | last_ep = int(ep_num_tot)
222 | episode_url = '{}{}-episode-{}'
223 | url = episode_url.format(self.host, str_qry_final, ep_num_link_get)
224 | master_keyboard_list = []
225 | cookies = {
226 | 'gogoanime': self.gogoanime_token,
227 | 'auth': self.auth_token
228 | }
229 | response = requests.get(url=url, cookies=cookies)
230 | plaintext = response.text
231 | soup = BeautifulSoup(plaintext, "lxml")
232 | download_div = soup.find("div", {'class': 'cf-download'}).findAll('a')
233 | links_final = MediaLinksObject()
234 | for links in download_div:
235 | download_links = links['href']
236 | q_name_raw = links.text.strip()
237 | q_name_raw_list = q_name_raw.split('x')
238 | quality_name = q_name_raw_list[1] # 360, 720, 1080p links .just append to keyb lists with name and href
239 | if quality_name == "360":
240 | links_final.link_360p = download_links
241 | elif quality_name == "480":
242 | links_final.link_480p = download_links
243 | elif quality_name == "720":
244 | links_final.link_720p = download_links
245 | elif quality_name == "1080":
246 | links_final.link_1080p = download_links
247 | anime_multi_link_initial = soup.find('div', {'class': 'anime_muti_link'}).findAll('li')
248 | anime_multi_link_initial.remove(anime_multi_link_initial[0])
249 | chumma_list = []
250 | for l in anime_multi_link_initial:
251 | get_a = l.find('a')
252 | video_links = get_a['data-video']
253 | valid = video_links[0:4]
254 | if valid == "http":
255 | pass
256 | else:
257 | video_links = f"https:{video_links}"
258 | chumma_list.append(video_links)
259 | anime_multi_link_initial.remove(anime_multi_link_initial[0])
260 | for other_links in anime_multi_link_initial:
261 | get_a_other = other_links.find('a')
262 | downlink = get_a_other['data-video'] # video links other websites
263 | quality_name = other_links.text.strip().split('C')[0] # other links name quality
264 | if quality_name == "Streamsb":
265 | links_final.link_streamsb = downlink
266 | elif quality_name == "Xstreamcdn":
267 | links_final.link_xstreamcdn = downlink
268 | elif quality_name == "Streamtape":
269 | links_final.link_streamtape = downlink
270 | elif quality_name == "Mixdrop":
271 | links_final.link_mixdrop = downlink
272 | elif quality_name == "Mp4Upload":
273 | links_final.link_mp4upload = downlink
274 | elif quality_name == "Doodstream":
275 | links_final.link_doodstream = downlink
276 | res = requests.get(chumma_list[0])
277 | plain = res.text
278 | s = BeautifulSoup(plain, "lxml")
279 | t = s.findAll('script')
280 | hdp_js = t[2].string
281 | hdp_link_initial = re.search("(?Phttps?://[^\s]+)", hdp_js).group("url")
282 | hdp_link_initial_list = hdp_link_initial.split("'")
283 | hdp_link_final = hdp_link_initial_list[0] # final hdp links
284 | links_final.link_hdp = hdp_link_final
285 | return links_final
286 | except AttributeError:
287 | raise InvalidAnimeIdError("Invalid animeid or episode_num given")
288 | except requests.exceptions.ConnectionError:
289 | raise NetworkError("Unable to connect to the Server, Check your connection")
290 | except TypeError:
291 | raise InvalidTokenError("Invalid tokens passed, Check your tokens")
292 |
293 | def get_episode_link_basic(self, animeid: str, episode_num: int) -> MediaLinksObject():
294 | """Get streamable and downloadable links for a given animeid and episode number.
295 | If the link is not found, then this method will return ``None`` .
296 |
297 | Parameters:
298 | animeid(``str``):
299 | The animeid of the anime you want to download.
300 |
301 | episode_num(``int``):
302 | The episode number of the anime you want to download.
303 |
304 | Returns:
305 | :obj:`-anikimiapi.data_classes.MediaLinksObject`: On success, the links of the anime is returned.
306 |
307 | Example:
308 | .. code-block:: python
309 | :emphasize-lines: 1,4-7,10-13
310 |
311 | from anikimiapi import AniKimi
312 |
313 | # Authorize the api to GogoAnime
314 | anime = AniKimi(
315 | gogoanime_token="baikdk32hk1nrek3hw9",
316 | auth_token="NCONW9H48HNFONW9Y94NJT49YTHO45TU4Y8YT93HOGFNRKBI"
317 | )
318 |
319 | # Get anime Link
320 | link = anime.get_episode_link(animeid="clannad-dub", episode_num=3)
321 | print(link.link_hdp)
322 | print(link.link_360p)
323 | print(link.link_streamtape)
324 |
325 | # and many more...
326 | """
327 | try:
328 | animelink = f'{self.host}category/{animeid}'
329 | response = requests.get(animelink)
330 | plainText = response.text
331 | soup = BeautifulSoup(plainText, "lxml")
332 | lnk = soup.find(id="episode_page")
333 | source_url = lnk.find("li").a
334 | tit_url = soup.find("div", {"class": "anime_info_body_bg"}).h1.string
335 | URL_PATTERN = '{}{}-episode-{}'
336 | url = URL_PATTERN.format(self.host, animeid, episode_num)
337 | srcCode = requests.get(url)
338 | plainText = srcCode.text
339 | soup = BeautifulSoup(plainText, "lxml")
340 | source_url = soup.find("li", {"class": "dowloads"}).a
341 | vidstream_link = source_url.get('href')
342 | # print(vidstream_link)
343 | URL = vidstream_link
344 | dowCode = requests.get(URL)
345 | data = dowCode.text
346 | soup = BeautifulSoup(data, "lxml")
347 | dow_url= soup.findAll('div',{'class':'dowload'})
348 | episode_res_link = {'title':f"{tit_url}"}
349 | links_final = MediaLinksObject()
350 | for i in range(len(dow_url)):
351 | Url = dow_url[i].find('a')
352 | downlink = Url.get('href')
353 | str_= Url.string
354 | str_spl = str_.split()
355 | str_spl.remove(str_spl[0])
356 | str_original = ""
357 | quality_name = str_original.join(str_spl)
358 | episode_res_link.update({f"{quality_name}":f"{downlink}"})
359 | if "(HDP-mp4)" in quality_name:
360 | links_final.link_hdp = downlink
361 | elif "(SDP-mp4)" in quality_name:
362 | links_final.link_sdp = downlink
363 | elif "(360P-mp4)" in quality_name:
364 | links_final.link_360p = downlink
365 | elif "(720P-mp4)" in quality_name:
366 | links_final.link_720p = downlink
367 | elif "(1080P-mp4)" in quality_name:
368 | links_final.link_1080p = downlink
369 | elif "Streamsb" in quality_name:
370 | links_final.link_streamsb = downlink
371 | elif "Xstreamcdn" in quality_name:
372 | links_final.link_xstreamcdn = downlink
373 | elif "Streamtape" in quality_name:
374 | links_final.link_streamtape = downlink
375 | elif "Mixdrop" in quality_name:
376 | links_final.link_mixdrop = downlink
377 | elif "Mp4Upload" in quality_name:
378 | links_final.link_mp4upload = downlink
379 | elif "Doodstream" in quality_name:
380 | links_final.link_doodstream = downlink
381 | return links_final
382 | except AttributeError:
383 | raise InvalidAnimeIdError("Invalid animeid or episode_num given")
384 | except requests.exceptions.ConnectionError:
385 | raise NetworkError("Unable to connect to the Server, Check your connection")
386 | except TypeError:
387 | raise InvalidTokenError("Invalid tokens passed, Check your tokens")
388 |
389 | def get_by_genres(self,genre_name, limit=60 ) -> list :
390 |
391 | """Get anime by genres, The genre object has the following genres working,
392 |
393 | action, adventure, cars, comedy, dementia, demons, drama, dub, ecchi, fantasy,
394 | game, harem, hentai - Temporarily Unavailable, historical, horror, josei, kids,
395 | magic, martial-arts, mecha, military, music, mystery, parody, police, psychological,
396 | romance, samurai, school, sci-fi, seinen, shoujo, shoujo-ai, shounen-ai, shounen,
397 | slice-of-life, space, sports, super-power, supernatural, thriller, vampire,
398 | yaoi, yuri.
399 |
400 | Parameters:
401 | genre_name(``str``):
402 | The name of the genre. You should use any from the above mentioned genres.
403 |
404 | limit(``int``):
405 | The limit for the number of anime you want from the results. defaults to 60 (i.e, 3 pages)
406 |
407 | Returns:
408 | List of :obj:`-anikimiapi.data_classes.ResultObject`: On Success, the list of genre results is returned.
409 |
410 | Example:
411 | .. code-block:: python
412 | :emphasize-lines: 1,4-7,10-13
413 |
414 | from anikimiapi import AniKimi
415 |
416 | # Authorize the api to GogoAnime
417 | anime = AniKimi(
418 | gogoanime_token="baikdk32hk1nrek3hw9",
419 | auth_token="NCONW9H48HNFONW9Y94NJT49YTHO45TU4Y8YT93HOGFNRKBI"
420 | )
421 |
422 | # Get anime by genre
423 | get_genre = anime.get_by_genres(genre_name="romance", page=1)
424 | for result in get_genre:
425 | print(result.title)
426 | print(result.animeid)
427 | """
428 | gen_ani = []
429 |
430 | def page_anime_scraper(soup_object) -> list:
431 | """a helper function to scrape anime results from page source"""
432 | ani_results = []
433 | animes = soup_object.find("ul", {"class": "items"}).find_all("li")
434 | for anime in animes:
435 | tits = anime.a["title"]
436 | urll = anime.a["href"]
437 | r = urll.split('/')
438 | ani_results.append(ResultObject(title=f"{tits}", animeid=f"{r[2]}"))
439 | return ani_results
440 |
441 | def pagination_helper(current_page_source : str,url,limit:int) -> None:
442 | """a recursive helper function which helps to successively scrape anime from following pages
443 | (if there are any) till limit is reached. """
444 | soup = BeautifulSoup(current_page_source,"lxml")
445 | next_page = soup.find("li",{"class": "selected"}).findNext('li')
446 |
447 |
448 | if (type(next_page) is not None):
449 |
450 | try :
451 |
452 | [next_page_value] = [i.get('data-page') for i in next_page]
453 | next_page_url = f'{url}{next_page_value}'
454 | next_page_src = (requests.get(next_page_url)).text
455 |
456 | soup = BeautifulSoup(next_page_src,"lxml")
457 |
458 | #next/subsequent page results
459 | next_page_results = page_anime_scraper(soup)
460 | for anime in next_page_results:
461 | if (len(gen_ani) < limit):
462 | gen_ani.append(anime)
463 | else:
464 | pass
465 | if (len(gen_ani) == limit):
466 | pass
467 | else:
468 | pagination_helper(next_page_src,url,limit)
469 |
470 | except AttributeError:
471 | pass
472 |
473 | else:
474 | pass
475 |
476 | try:
477 | url = f"{self.host}genre/{genre_name}?page="
478 | response = requests.get(url)
479 | plainText = response.text
480 | soup = BeautifulSoup(plainText,"lxml")
481 |
482 | # starting page
483 | starting_page_results = page_anime_scraper(soup)
484 | for anime in starting_page_results :
485 | if (len(gen_ani) < limit):
486 | gen_ani.append(anime)
487 | else:
488 | pass
489 |
490 | pagination_helper(current_page_source=plainText,url=url,limit=limit)
491 |
492 | return gen_ani
493 |
494 | except AttributeError or KeyError:
495 | raise InvalidGenreNameError("Invalid genre_name or page_num")
496 | except requests.exceptions.ConnectionError:
497 | raise NetworkError("Unable to connect to server")
498 |
499 | def get_airing_anime(self, count=10) -> list:
500 | """Get the currently airing anime and their animeid.
501 |
502 | Parameters:
503 | count(``int`` | ``str``, *optional*):
504 | The number of search results to be returned, Defaults to 10.
505 |
506 | Returns:
507 | List of :obj:`-anikimiapi.data_classes.ResultObject`: On Success, the list of currently airing anime results is returned.
508 |
509 | Example:
510 | .. code-block:: python
511 | :emphasize-lines: 1,4-7,10-13
512 |
513 | from anikimiapi import AniKimi
514 |
515 | # Authorize the api to GogoAnime
516 | anime = AniKimi(
517 | gogoanime_token="baikdk32hk1nrek3hw9",
518 | auth_token="NCONW9H48HNFONW9Y94NJT49YTHO45TU4Y8YT93HOGFNRKBI"
519 | )
520 |
521 | airing = anime.get_airing_anime()
522 | for result in airing:
523 | print(result.title)
524 | print(result.animeid)
525 | """
526 | try:
527 | if int(count) >= 20:
528 | raise CountError("count parameter cannot exceed 20")
529 | else:
530 | url = f"{self.host}"
531 | session = HTMLSession()
532 | response = session.get(url)
533 | response_html = response.text
534 | soup = BeautifulSoup(response_html, 'html.parser')
535 | anime = soup.find("nav", {"class": "menu_series cron"}).find("ul")
536 | air = []
537 | for link in anime.find_all('a'):
538 | airing_link = link.get('href')
539 | name = link.get('title') # name of the anime
540 | link = airing_link.split('/')
541 | lnk_final = link[2] # animeid of anime
542 | air.append(ResultObject(title=f"{name}", animeid=f"{lnk_final}"))
543 | return air[0:int(count)]
544 | except IndexError or AttributeError or TypeError:
545 | raise AiringIndexError("No content found on the given page number")
546 | except requests.exceptions.ConnectionError:
547 | raise NetworkError("Unable to connect to server")
--------------------------------------------------------------------------------
/anikimiapi/data_classes.py:
--------------------------------------------------------------------------------
1 | class ResultObject:
2 | def __init__(self, title: str, animeid: str):
3 | self.title = title
4 | self.animeid = animeid
5 |
6 | class MediaInfoObject:
7 | def __init__(self,
8 | title: str,
9 | year: int,
10 | other_names: str,
11 | season: str,
12 | status: str,
13 | genres: list,
14 | episodes: int,
15 | image_url: str,
16 | summary: str):
17 | self.title = title
18 | self.year = year
19 | self.other_names = other_names
20 | self.season = season
21 | self.status = status
22 | self.genres = genres
23 | self.episodes = episodes
24 | self.image_url = image_url
25 | self.summary = summary
26 |
27 | class MediaLinksObject:
28 | def __init__(self,
29 | link_360p=None,
30 | link_480p=None,
31 | link_720p=None,
32 | link_1080p=None,
33 | link_hdp=None,
34 | link_sdp=None,
35 | link_streamsb=None,
36 | link_xstreamcdn=None,
37 | link_streamtape=None,
38 | link_mixdrop=None,
39 | link_mp4upload=None,
40 | link_doodstream=None
41 | ):
42 | self.link_360p = link_360p
43 | self.link_480p = link_480p
44 | self.link_720p = link_720p
45 | self.link_1080p = link_1080p
46 | self.link_hdp = link_hdp
47 | self.link_sdp = link_sdp
48 | self.link_streamsb = link_streamsb
49 | self. link_xstreamcdn = link_xstreamcdn
50 | self.link_streamtape = link_streamtape
51 | self.link_mixdrop = link_mixdrop
52 | self.link_mp4upload = link_mp4upload
53 | self.link_doodstream = link_doodstream
54 |
--------------------------------------------------------------------------------
/anikimiapi/error_handlers.py:
--------------------------------------------------------------------------------
1 | class NetworkError(Exception):
2 | pass
3 |
4 | class NoSearchResultsError(Exception):
5 | pass
6 |
7 | class InvalidAnimeIdError(Exception):
8 | pass
9 |
10 | class InvalidTokenError(Exception):
11 | pass
12 |
13 | class InvalidGenreNameError(Exception):
14 | pass
15 |
16 | class AiringIndexError(Exception):
17 | pass
18 |
19 | class CountError(Exception):
20 | pass
--------------------------------------------------------------------------------
/assets/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CosmicPredator/anikimiapi/9e8b879b55760d84060298df92d6197abd4ff985/assets/1.jpg
--------------------------------------------------------------------------------
/assets/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CosmicPredator/anikimiapi/9e8b879b55760d84060298df92d6197abd4ff985/assets/2.jpg
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup
2 |
3 | with open("README_PYPI.md", "r") as fh:
4 | long_description = fh.read()
5 |
6 |
7 | setup(
8 | name='anikimiapi',
9 | packages=['anikimiapi'],
10 | version='0.1.2',
11 | license='LGPLv3+',
12 | description='A Simple, LightWeight, Statically-Typed Python3 API wrapper for GogoAnime',
13 | long_description=long_description,
14 | long_description_content_type="text/markdown",
15 | author='BaraniARR',
16 | author_email='baranikumar2003@outlook.com',
17 | url='https://github.com/BaraniARR/anikimiapi',
18 | download_url='https://github.com/BaraniARR/anikimiapi/releases/tag/v0.0.1-beta',
19 | keywords=['anime', 'gogoanime', 'download', 'sub', 'dub'],
20 | install_requires=[
21 | 'bs4',
22 | 'requests',
23 | 'requests_html',
24 | 'lxml'
25 | ],
26 | classifiers=[
27 | 'Development Status :: 4 - Beta',
28 | 'Intended Audience :: Developers',
29 | 'Topic :: Internet',
30 | 'License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)',
31 | 'Programming Language :: Python :: 3.6',
32 | 'Programming Language :: Python :: 3.7',
33 | 'Programming Language :: Python :: 3.8',
34 | 'Programming Language :: Python :: 3.9',
35 | 'Programming Language :: Python :: 3.10',
36 | ],
37 | )
38 |
--------------------------------------------------------------------------------