anime.py 11 KB

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