anime.py 10 KB

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