anime.py 8.5 KB

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