def setUpClass(cls): cls.test_response1 = Hentai(177013) cls.test_response2 = Hentai(269582) cls.test_response3 = Hentai(228922) cls.test_response4 = Hentai(297974) read = lambda id: json.load(open(f"./tests/{id}.json", mode='r')) cls.test_reference1 = read(177013) cls.test_reference2 = read(269582) cls.test_reference3 = read(228922) cls.test_reference4 = read(297974)
async def read(self, ctx, code): async with ctx.typing(): try: doujin = Hentai(code) except HTTPError: return UI.error_embed(f'Doujin dengan code {code} tidak ada') pages = [image for image in doujin.image_urls] curr_index = 1 max_index = len(pages) title = doujin.title(Format.Pretty) embed, components = self.helpers.generate_read_hentai_embed(title, pages[curr_index-1], curr_index, max_index) nhentai = await ctx.send(embed=embed, components=components) try: while True: btn = await nhentai.wait_for('button', self.bot, timeout=60) await btn.respond(ninja_mode=True) if btn.custom_id == 'hentai_first': curr_index = 1 if btn.custom_id == 'hentai_prev': curr_index -= 1 if btn.custom_id == 'hentai_next': curr_index += 1 if btn.custom_id == 'hentai_last': curr_index = max_index embed, components = self.helpers.generate_read_hentai_embed(title, pages[curr_index-1], curr_index, max_index) await nhentai.edit(embed=embed, components=components) except TimeoutError: embed, components = self.helpers.generate_read_hentai_embed(title, pages[curr_index-1], curr_index, max_index, disable_components=True) await nhentai.edit(components=components) except NotFound: pass
async def nhentai(self, ctx: commands.Context, djid=None, *, extra: str = ''): '''finds doujins on nhentai by id''' if ctx.invoked_subcommand is not None: return if djid is None: await ctx.send_help(ctx.command) return if not Hentai.exists(djid): return await self.search(ctx, tags=f'{djid} {extra}') result = Hentai(djid) tags = [_.name for _ in result.tag] e = discord.Embed(title=result.title(Format.Pretty), description=f'#{result.id}', url=result.url, color=int(djid)) e.set_image(url=result.cover) e.set_footer(text=result.upload_date) e.add_field(name="Tags", value=', '.join(tags)) artists = ', '.join([_.name for _ in result.artist ]) if result.artist != [] else 'None' e.add_field(name="Artist(s)", value=artists) await ctx.send(embed=e)
async def full(self, ctx, nuclear_code, limit=5): doujin = Hentai(nuclear_code) pointer = 0 for image in doujin.image_urls: await ctx.channel.send(image) pointer += 1 if pointer > limit: break
def searchby_id(cmd): id = int(cmd.replace('nh', '').replace('search', '').strip()) if len(str(id)) > 6: print(f'{id} is not a manga id! So... Zero Two.') id = 281415 manga = Hentai(id) Hentai.exists(manga.id) print(f'#{manga.id} :: {manga.title(Format.Pretty)} exists!')
async def _read(self, ctx: commands.Context, djid: int): '''opens a reader ''' try: dj = Hentai(djid) except HTTPError: return await ctx.send(content='Invalid code') m = DoujinMenu(ctx, self.bot, dj) await m.start(ctx)
def test_export(self): # case 1 selects three options at random for populating options in export print( f"CASE 1: Exports '{self.tiny_evil.title(Format.Pretty)}' as {self.tiny_evil_file} to '{Path().cwd()}'" ) random_options = random.sample( [opt for opt in Option if opt.value != 'raw'], k=3) print( f"CASE 1: Passing {','.join([opt.name for opt in random_options])} as options" ) self.tiny_evil.export(self.tiny_evil_file, options=random_options) with open(self.tiny_evil_file, mode='r', encoding='utf-8') as file_handler: test_data = json.load(file_handler)['result'][0] self.assertEqual(3, len(test_data.keys()), msg="Keys don't match up (expected 3)") self.assertIn(random_options[0].value, test_data, msg=f"KeyError: {random_options[0].name} (Option 1)") self.assertIn(random_options[1].value, test_data, msg=f"KeyError: {random_options[1].name} (Option 2)") self.assertIn(random_options[2].value, test_data, msg=f"KeyError: {random_options[2].name} (Option 3)") # case 2 checks if three randomly selected options are in test_data print(f"CASE 2: Passing all options available") self.tiny_evil.export(self.tiny_evil_file) with open(self.tiny_evil_file, mode='r', encoding='utf-8') as file_handler: test_data = json.load(file_handler)['result'][0] self.assertEqual(19, len(test_data.keys()), msg="Keys don't match up (expected 15)") self.assertIn(random_options[0].value, test_data, msg=f"KeyError {random_options[0].name} (Option 1)") self.assertIn(random_options[1].value, test_data, msg=f"KeyError {random_options[1].name} (Option 2)") self.assertIn(random_options[2].value, test_data, msg=f"KeyError {random_options[2].name} (Option 3)") # case 3 checks the raw export option print(f"CASE 3: Passing Option.Raw") self.tiny_evil.export(self.tiny_evil_file, options=[Option.Raw]) with open(self.tiny_evil_file, mode='r', encoding='utf-8') as file_handler: self.assertEqual( self.tiny_evil, Hentai(json=json.load(file_handler)[0]), msg=f"AssumptionError: Build from file should match request")
async def nh(message, sauce): try: doujin = Hentai(sauce) if (Hentai.exists(doujin.id) == True): base_url = 'https://nhentai.net/g/' final_url = base_url + sauce + "/" await message.channel.send(final_url) except: await message.channel.send("Esse sauce não existe parça.")
def downloadH(code): try: doujin = Hentai(code) if os.path.isdir('H7u7H\{}'.format(code)) == False: doujin.download(progressbar=True ) shutil.move('{}'.format(code), 'H7u7H') else: windowns.value = 0 except requests.HTTPError: windowns.value = 1 print('da error')
async def nh_get(self, ctx, id): """Search the manga from Nhentai with id""" try: hnt = Hentai(id) except Exception: await ctx.send(embed=ErrorEmbed("Doujin doesn't exist! Try another one.")) #raise ValueError("Doujin doesn't exist! Try another one.") else: embed = self.make_embed(hnt) await ctx.send(embed=embed)
async def rnd(self, ctx: commands.Context): """Random one""" doujin = Hentai(Utils.get_random_id()) embed_list = [] for i in doujin.image_urls: embed = Embed.default(ctx) embed.title = doujin.title(Format.Pretty) embed.set_image(url=i) embed_list.append(embed) await menus.MenuPages( source=EmbedListMenu(embed_list), clear_reactions_after=True, ).start(ctx=ctx, wait=False)
def read_manga(): code = request.args.get('code') if code: print(f"READER: {code}") if (Hentai.exists(code)): doujin = Hentai(code) return render_template('includes/reader.html', img_urls=enumerate(doujin.image_urls)) else: return render_template('includes/reader.html', img_urls=[]) return redirect('/')
async def hentai(ctx, n: int): doujin = Hentai(n) if ctx.channel.is_nsfw(): for link in doujin.image_urls: time.sleep(1) await ctx.send(link) await ctx.reply('Here you go!') else: embed = discord.Embed( title="You cannot use this command in this channel", color=discord.Color.red()) await ctx.send(embed=embed)
async def get(self, ctx: Context, id: int) -> None: """ get returns the NHentai manga that was requested. id: The id of the hentai manga. """ try: hnt = Hentai(id) except Exception: raise ValueError("[Doujin doesn't exist! Try another one.") else: embed = self.make_embed(hnt) await ctx.send(embed=embed)
async def read(self, ctx: commands.Context, digits): """Read doujins.""" if not digits.isdigit(): return await ctx.send("Only digits allowed.") if not Hentai.exists(digits): return await ctx.send("Doesn't exist.") doujin = Hentai(digits) embed_list = [] for i in doujin.image_urls: embed = Embed.default(ctx) embed.title = doujin.title(Format.Pretty) embed.set_image(url=i) embed_list.append(embed) await menus.MenuPages( source=EmbedListMenu(embed_list), clear_reactions_after=True, ).start(ctx=ctx, wait=False)
async def read(self, ctx, nuke_code): """ Read doujin here on Discord. """ message = await ctx.send("Loading sauce...") if Hentai.exists(nuke_code): doujin = Hentai(nuke_code) buttons = ("⏪", "◀", "⏹", "▶", "⏩") current = 0 images = tuple(doujin.image_urls) max_pages = doujin.num_pages await message.edit(content=f'Opening *{doujin.title(Format.Pretty)}*...') view = await ctx.send(images[current]) page_info = await ctx.send(f'Page: {str(current + 1)}/{str(max_pages)}') for button in buttons: await view.add_reaction(button) while True: try: reaction, user = await self.bot.wait_for('reaction_add', timeout=90.0, check=lambda reaction, user: user == ctx.author and reaction.emoji in buttons) except asyncio.TimeoutError: await view.edit(content="**Doujin has timed out.**") del images await page_info.delete() break else: previous_page = current switcher = { "⏪": 0, "◀": current - 1 if current > 0 else current, "⏹": -1, "▶": current + 1 if current < max_pages - 1 else current, "⏩": max_pages - 1 } current = switcher[reaction.emoji] if current != previous_page: if current == -1: await view.edit(content="**Doujin has been closed.**") del images await page_info.delete() break else: await view.edit(content=images[current]) await page_info.edit(content=f'Page: {str(current + 1)}/{str(max_pages)}') else: await message.edit(content="The sauce you want to read does not exist. 🤷♂️")
def getby_id(cmd): id = int(cmd.replace('nh', '').replace('get', '').strip()) if len(str(id)) > 6: print(f'{id} is not a manga id! So... Zero Two.') id = 281415 manga = Hentai(id) Hentai.exists(manga.id) print(f'#{manga.id} :: {manga.title(Format.Pretty)}') if id != 281415: if confirm('proceed download'): print('Starting download...\n') manga.download(progressbar=True) print(f'Downloading {manga.title(Format.Pretty)} Success!\n') else: print(f'Downloading {manga.title(Format.Pretty)} aborted.\n') else: manga.download(progressbar=True) print('Enjoy.')
def checkHentaiLangOnly(hentaiID, language): print(f'Checking Post ID: {hentaiID}') try: doujin = Hentai(hentaiID) except: print(' > Invalid post code.') return False if language in str(doujin.language): print(' > Valid Doujin! Language is', language, ".") print('downloading!') doujin.download() return True else: print('> Valid Post but language is not', language, '.') return False
async def lookup(self, ctx: commands.Context, doujin): """ Info about a doujin.""" if not doujin.isdigit(): return await ctx.send("Only digits allowed.") if not Hentai.exists(doujin): return await ctx.send("Doesn't exist.") doujin = Hentai(doujin) embed = Embed.default(ctx) embed.title = doujin.title(Format.Pretty) embed.add_field(name="Holy Digits", value=doujin.id, inline=True) embed.add_field(name="Languages", value=Tag.get(doujin.language, "name"), inline=True) embed.add_field(name="Uploaded", value=doujin.upload_date, inline=True) embed.add_field(name="Number of times liked", value=doujin.num_favorites, inline=True) embed.add_field(name="Tags", value=Tag.get(doujin.tag, "name")) embed.add_field(name="Number of pages", value=doujin.num_pages) embed.set_thumbnail(url=doujin.thumbnail) await ctx.send(embed=embed)
def checkHentaiExclude(hentaiID, language, tagexcluded): print(f'Checking Post ID: {hentaiID}') try: doujin = Hentai(hentaiID) except: print(' > Invalid post code.') return False if language in str(doujin.language) and tagexcluded not in str(doujin.tag): print(' > Valid Doujin! Language is', language, ".") print(' > Doujin does not contain tag: ', tagexcluded) print('downloading!') doujin.download() return True else: print('> Valid Post but language is not', language, '.') return False
async def nh(menu): id = menu.extraProcVars['id'] ctx = menu.extraProcVars['ctx'] # No ID? Send random if id is None: await ctx.send('No ID passed, getting random doujin...') d = Utils.get_random_hentai() # ID not digits elif not id.isdigit(): await ctx.send( 'Invalid ID\nIDs are usually 6 digit numbers, although there are some 5 digin and even shorter or longer IDs\nIf you don\'t have an ID just don\'t write one and we will send you a random doujin or use the nhs command to search or nhh command to view the current home page' ) # Does Doujin exist? elif Hentai.exists(id): d = Hentai(id) else: await ctx.send( f'No Doujin with id: {id} was found\n\nIf you don\'t have an ID just don\'t write one and we will send you a random doujin or use the nhs command to search or nhh command to view the current home page' ) return d
async def getpage(self, ctx: Context, id: int, page: int): """ Returns the image on the given page number. Syntax: ${prefix} getpage <id> <page> """ # This block checks if the asked hentai is a valid hentai if page < 1: raise ValueError("[Page number must be > 1.") try: hnt = Hentai(id) except: raise ValueError(f"page: {page}[Doujin not found!") else: # If the ID is a valid hentai then do these embed = self.make_page_embed(ctx, hnt, page) await ctx.send( embed=embed )
async def lookup_id(self, ctx, id: int): if not Hentai.exists(id): await ctx.send("Error: Invalid ID.") else: doujin = Hentai(id) embed = discord.Embed( title=doujin.title(Format.Pretty), description=f"🌍 {', '.join(Tag.get_names(doujin.language))}", url=doujin.url, color=discord.Color.red()) embed.add_field(name="Author", value=Tag.get_names(doujin.artist)) embed.add_field(name="Favorites", value=f"❤ {doujin.num_favorites}") embed.add_field(name="Pages", value=f"📕 {doujin.num_pages}") embed.set_thumbnail(url=doujin.thumbnail) embed.set_footer( text=f"Tags: {', '.join(Tag.get_names(doujin.tag))}") await self.client.change_presence( status=discord.Status.online, activity=discord.Game( f"Now reading {doujin.title(Format.Pretty)}🥰")) await ctx.send(embed=embed)
def nuke_codes(): if request.method == 'POST': data = request.get_json() code = data['code'] print(data) if (Hentai.exists(code)): doujin = Hentai(code) print(f"\n#{code} : success") print(f"title : {doujin.title()}") print(f"tags : {[tag.name for tag in doujin.tag]}") print(f"poster url : {doujin.image_urls[0]}\n") return { 'id': doujin.id, 'title_release': doujin.title(), 'title_pretty': doujin.title(Format.Pretty), 'tags': [tag.name for tag in doujin.tag], 'poster_link': doujin.image_urls[0], # 'poster_blob' : poster_blob, 'artist': [{ 'name': artist.name, 'url': artist.url, 'count': artist.count } for artist in doujin.artist], 'languages': [lang.name for lang in doujin.language], 'categories': [cat.name for cat in doujin.category], 'pages': doujin.num_pages, 'uploaded': doujin.upload_date } else: return None return None
async def nhentai(self, ctx: commands.Context, djid: int = None): '''finds doujins on nhentai by id''' if ctx.invoked_subcommand is not None: return if djid is None: await ctx.send_help(ctx.command) return if not Hentai.exists(djid): await ctx.send(content="Doujin does not exist!") return result = Hentai(djid) tags = [_.name for _ in result.tag] e = discord.Embed(title=result.title(Format.Pretty), description=f'#{result.id}', url=result.url, color=0x177013) e.set_image(url=result.cover) e.set_footer(text=result.upload_date) e.add_field(name="Tags", value=', '.join(tags)) e.add_field(name="Artist(s)", value=', '.join([_.name for _ in result.artist])) await ctx.send(embed=e)
async def read_id(self, ctx, id: int): if not Hentai.exists(id): await ctx.send("Error: Invalid ID.") else: doujin = Hentai(id) reactions = { 'prev': Emoji[':arrow_left:'], 'next': Emoji[':arrow_right:'] } embed = discord.Embed(title=doujin.title(Format.Pretty), description=f"Page 1 of {doujin.num_pages}", color=discord.Color.red()) embed.set_image(url=doujin.cover) # TODO: implement emoji reaction event handler for pagination message = await ctx.send(embed=embed) self.reader_id = message.id print(type(message)) print(self.reader_id) for emoji in reactions.values(): await message.add_reaction(emoji)
async def sauce(self, ctx, nuke_code): """ What's behind that nuke code? """ message = await ctx.send("Extracting sauce from nuke code... 👨💻") if Hentai.exists(nuke_code): doujin = Hentai(nuke_code) english = doujin.title() japanese = doujin.title(Format.Japanese) pages = str(doujin.num_pages) hentai_id = str(doujin.id) link = "||" + doujin.url + "||" tag = (getattr(i, 'name') for i in doujin.tag) content_list = ( f'**Hentai ID**: {hentai_id}', f'**Thumbnail**: {doujin.thumbnail}', f'** English Title**: {english if english else "none"}', f'**Japanese Title**: {japanese if japanese else "none"}', f'**Pages**: {pages}', f'**Tags**: {", ".join(tag)}', f'**Link**: {link}' ) await message.edit(content="\n".join(content_list)) else: await message.edit(content="The sauce you are looking for does not exist. 🤷♂️")
async def getfull(self, ctx: Context, id: int, from_page: int = 1): """ Sends you the entire manga as an image page by page. Be careful using this. """ if from_page < 1: raise ValueError("[Page number must start from 1") try: hnt = Hentai(id) except Exception: raise ValueError("[No such Douji found!") else: # TODO: Update this messy looking shit to something good looking using itertools LIMIT = 10 i = 1 for page in hnt.pages[from_page-1::]: i += 1 await ctx.author.send(page.url) if i > LIMIT: await ctx.author.send("Enter `n` for next 10 pages!") try: await self.bot.wait_for('message', timeout=60, check=lambda msg: msg.content=='n') i = 1 continue except asyncio.TimeoutError: await ctx.author.send("Timeout!") return
def embed_hentai(code): try: doujin = Hentai(code) except HTTPError: return Embed(title=f"Doujin dengan code {code} tidak ada") tags = [tag.name for tag in doujin.tag] artists = [artist.name for artist in doujin.artist] languages = [language.name for language in doujin.language] embed = Embed(title=f"{doujin.title(Format.Pretty)}") embed.set_image(url=doujin.thumbnail) embed.add_field(name='Code', value=code) embed.add_field(name='Artist', value=', '.join(artists)) embed.add_field(name='Release Date', value=str(doujin.upload_date)[0:10]) embed.add_field(name='Language', value=', '.join(languages)) embed.add_field(name='Pages Number', value=doujin.num_pages) embed.add_field(name="Start Reading", value=doujin.url) embed.set_footer(text=f"Tags: {', '.join(tags)}") return embed
def setUpClass(cls): cls.test_response = Hentai(177013) read = lambda id: json.load(open(f"./tests/{id}.json", mode='r')) cls.test_reference = Hentai(json=read(177013))