anime.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. # Part of Pull Req #2 by @MaskedVirus | github.com/swatv3nub
  2. import time
  3. from datetime import timedelta
  4. import requests
  5. from pyrogram import filters
  6. from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
  7. from wbb import app
  8. from wbb.core.decorators.errors import capture_err
  9. __MODULE__ = "Anime"
  10. __HELP__ = """
  11. /anime - search anime on AniList
  12. /manga - search manga on Anilist
  13. /char - search character on Anilist
  14. """
  15. def shorten(description, info="anilist.co"):
  16. ms_g = ""
  17. if len(description) > 700:
  18. description = description[0:500] + "...."
  19. ms_g += f"\n**Description**: __{description}__[More here]({info})"
  20. else:
  21. ms_g += f"\n**Description**: __{description}__"
  22. return (
  23. ms_g.replace("<br>", "")
  24. .replace("</br>", "")
  25. .replace("<i>", "")
  26. .replace("</i>", "")
  27. )
  28. def t(milliseconds: int) -> str:
  29. """Inputs time in milliseconds, to get beautified time,
  30. as string"""
  31. seconds, milliseconds = divmod(int(milliseconds), 1000)
  32. minutes, seconds = divmod(seconds, 60)
  33. hours, minutes = divmod(minutes, 60)
  34. days, hours = divmod(hours, 24)
  35. tmp = (
  36. ((str(days) + " Days, ") if days else "")
  37. + ((str(hours) + " Hours, ") if hours else "")
  38. + ((str(minutes) + " Minutes, ") if minutes else "")
  39. + ((str(seconds) + " Seconds, ") if seconds else "")
  40. + ((str(milliseconds) + " ms, ") if milliseconds else "")
  41. )
  42. return tmp[:-2]
  43. airing_query = """
  44. query ($id: Int,$search: String) {
  45. Media (id: $id, type: ANIME,search: $search) {
  46. id
  47. episodes
  48. title {
  49. romaji
  50. english
  51. native
  52. }
  53. siteUrl
  54. nextAiringEpisode {
  55. airingAt
  56. timeUntilAiring
  57. episode
  58. }
  59. }
  60. }
  61. """
  62. fav_query = """
  63. query ($id: Int) {
  64. Media (id: $id, type: ANIME) {
  65. id
  66. title {
  67. romaji
  68. english
  69. native
  70. }
  71. }
  72. }
  73. """
  74. anime_query = """
  75. query ($id: Int,$search: String) {
  76. Media (id: $id, type: ANIME,search: $search) {
  77. id
  78. idMal
  79. title {
  80. romaji
  81. english
  82. native
  83. }
  84. description (asHtml: false)
  85. startDate{
  86. year
  87. }
  88. episodes
  89. season
  90. type
  91. format
  92. status
  93. duration
  94. siteUrl
  95. studios{
  96. nodes{
  97. name
  98. }
  99. }
  100. trailer{
  101. id
  102. site
  103. thumbnail
  104. }
  105. averageScore
  106. genres
  107. bannerImage
  108. }
  109. }
  110. """
  111. character_query = """
  112. query ($query: String) {
  113. Character (search: $query) {
  114. id
  115. name {
  116. first
  117. last
  118. full
  119. }
  120. siteUrl
  121. favourites
  122. image {
  123. large
  124. }
  125. description
  126. }
  127. }
  128. """
  129. manga_query = """
  130. query ($id: Int,$search: String) {
  131. Media (id: $id, type: MANGA,search: $search) {
  132. id
  133. title {
  134. romaji
  135. english
  136. native
  137. }
  138. description (asHtml: false)
  139. startDate{
  140. year
  141. }
  142. type
  143. format
  144. status
  145. siteUrl
  146. averageScore
  147. genres
  148. bannerImage
  149. }
  150. }
  151. """
  152. def format_bytes(size):
  153. size = int(size)
  154. power = 1024
  155. n = 0
  156. power_labels = {0: "", 1: "K", 2: "M", 3: "G", 4: "T"}
  157. while size > power:
  158. size /= power
  159. n += 1
  160. return f"{size:.2f} {power_labels[n]+'B'}"
  161. def return_progress_string(current, total):
  162. filled_length = int(30 * current // total)
  163. return "[" + "=" * filled_length + " " * (30 - filled_length) + "]"
  164. def calculate_eta(current, total, start_time):
  165. if not current:
  166. return "00:00:00"
  167. end_time = time.time()
  168. elapsed_time = end_time - start_time
  169. seconds = (elapsed_time * (total / current)) - elapsed_time
  170. thing = "".join(str(timedelta(seconds=seconds)).split(".")[:-1]).split(", ")
  171. thing[-1] = thing[-1].rjust(8, "0")
  172. return ", ".join(thing)
  173. url = "https://graphql.anilist.co"
  174. @app.on_message(filters.command("anime"))
  175. @capture_err
  176. async def anime_search(_, message):
  177. if len(message.command) < 2:
  178. await message.delete()
  179. return
  180. search = message.text.split(None, 1)[1]
  181. variables = {"search": search}
  182. json = (
  183. requests.post(url, json={"query": anime_query, "variables": variables})
  184. .json()["data"]
  185. .get("Media", None)
  186. )
  187. if json:
  188. msg = f"**{json['title']['romaji']}**(`{json['title']['native']}`)\n**Type**: {json['format']}\n**Status**: {json['status']}\n**Episodes**: {json.get('episodes', 'N/A')}\n**Duration**: {json.get('duration', 'N/A')} Per Ep.\n**Score**: {json['averageScore']}\n**Genres**: `"
  189. for x in json["genres"]:
  190. msg += f"{x}, "
  191. msg = msg[:-2] + "`\n"
  192. msg += "**Studios**: `"
  193. for x in json["studios"]["nodes"]:
  194. msg += f"{x['name']}, "
  195. msg = msg[:-2] + "`\n"
  196. info = json.get("siteUrl")
  197. trailer = json.get("trailer", None)
  198. if trailer:
  199. trailer_id = trailer.get("id", None)
  200. site = trailer.get("site", None)
  201. if site == "youtube":
  202. trailer = "https://youtu.be/" + trailer_id
  203. description = (
  204. json.get("description", "N/A")
  205. .replace("<i>", "")
  206. .replace("</i>", "")
  207. .replace("<br>", "")
  208. )
  209. msg += shorten(description, info)
  210. image = info.replace("anilist.co/anime/", "img.anili.st/media/")
  211. if trailer:
  212. buttons = [
  213. [
  214. InlineKeyboardButton("More Info", url=info),
  215. InlineKeyboardButton("Trailer", url=trailer),
  216. ]
  217. ]
  218. else:
  219. buttons = [[InlineKeyboardButton("More Info", url=info)]]
  220. if image:
  221. try:
  222. await message.reply_photo(
  223. image,
  224. caption=msg,
  225. reply_markup=InlineKeyboardMarkup(buttons),
  226. )
  227. except Exception:
  228. msg += f" [✔️️]({image})"
  229. await message.edit(msg)
  230. else:
  231. await message.edit(msg)
  232. @app.on_message(filters.command("manga"))
  233. @capture_err
  234. async def manga_search(_, message):
  235. if len(message.command) < 2:
  236. await message.delete()
  237. return
  238. search = message.text.split(None, 1)[1]
  239. variables = {"search": search}
  240. json = (
  241. requests.post(url, json={"query": manga_query, "variables": variables})
  242. .json()["data"]
  243. .get("Media", None)
  244. )
  245. ms_g = ""
  246. if json:
  247. title, title_native = json["title"].get("romaji", False), json["title"].get(
  248. "native", False
  249. )
  250. start_date, status, score = (
  251. json["startDate"].get("year", False),
  252. json.get("status", False),
  253. json.get("averageScore", False),
  254. )
  255. if title:
  256. ms_g += f"**{title}**"
  257. if title_native:
  258. ms_g += f"(`{title_native}`)"
  259. if start_date:
  260. ms_g += f"\n**Start Date** - `{start_date}`"
  261. if status:
  262. ms_g += f"\n**Status** - `{status}`"
  263. if score:
  264. ms_g += f"\n**Score** - `{score}`"
  265. ms_g += "\n**Genres** - "
  266. for x in json.get("genres", []):
  267. ms_g += f"{x}, "
  268. ms_g = ms_g[:-2]
  269. image = json.get("bannerImage", False)
  270. ms_g += f"_{json.get('description', None)}_"
  271. if image:
  272. try:
  273. await message.reply_photo(image, caption=ms_g)
  274. except Exception:
  275. ms_g += f" [✔️️]({image})"
  276. await message.reply(ms_g)
  277. else:
  278. await message.reply(ms_g)
  279. @app.on_message(filters.command("char"))
  280. @capture_err
  281. async def character_search(_, message):
  282. if len(message.command) < 2:
  283. await message.delete()
  284. return
  285. search = message.text.split(None, 1)[1]
  286. variables = {"query": search}
  287. json = (
  288. requests.post(url, json={"query": character_query, "variables": variables})
  289. .json()["data"]
  290. .get("Character", None)
  291. )
  292. if json:
  293. ms_g = (
  294. f"**{json.get('name').get('full')}**(`{json.get('name').get('native')}`)\n"
  295. )
  296. description = f"{json['description']}"
  297. site_url = json.get("siteUrl")
  298. ms_g += shorten(description, site_url)
  299. image = json.get("image", None)
  300. if image:
  301. image = image.get("large")
  302. await message.reply_photo(image, caption=ms_g)
  303. else:
  304. await message.reply(ms_g)