async def search(*tags: str): """seraches derpibooru""" try: imgs = [img for img in Search().query(*tags).sort_by(sort.RANDOM)] url = imgs[0].full await bot.say(url) except: await bot.say("Invalid search term")
def main(): logger = logging.getLogger("derpiboorudl") setup_logger(logger) # Parse args parser = argparse.ArgumentParser() parser.add_argument( "-d", "--destdir", required=True, help="Location where downloaded images will be dropped off") parser.add_argument("-q", "--query", default="", help="The Derpibooru query you wish to execute") parser.add_argument("-c", "--count", default=100, help="The count of images you wish to download", type=int) parser.add_argument( "-k", "--key", default=None, help="Specify the API key (normally present as env variable)") args = parser.parse_args() destdir, query, maximages = args.destdir, args.query, args.count # Read API key from --key if present or else read from env apikey = args.key if args.key else os.getenv("DERPIBOORUAPIKEY") if not apikey: logger.info("No API key was set! (DERPIBOORUAPIKEY)") search = Search().key(apikey).query(query).limit(maximages) if not os.path.isdir(destdir): os.mkdir(destdir) for image in search: filename = os.path.basename(image.full) path = os.path.join(destdir, filename) if not os.path.isfile(path): logger.info("Now downloading image with id {0}".format( image.id_number)) download = download_file(image.full) if download: if image.sha512_hash == sha512_hash(download): with open(path, "wb") as f: f.write(download) else: logger.error("sha512 hashes for {0} don't match up".format( image.id_number)) else: logger.error("download for {0} didn't complete".format( image.id_number))
def test_query(): """ Tests whether the results in a query contain the tag that was being searched for """ limit, tag = 10, "sunset shimmer" images = [image for image in Search().query(tag).limit(limit)] assert len(images) == limit for image in images: assert tag in image.tags
def test_descending(): """ Tests whether descending search is in the correct order """ limit = 10 images = [image for image in Search().descending().limit(limit)] assert len(images) == limit for image in images: # Check if the image IDs are listed in descending order # by comparing the ID of the next image if image is not images[-1]: next_image = images[images.index(image) + 1] assert image.id_number > next_image.id_number
def send_art(chat_id): if os.path.isfile(LOCKER): return open(LOCKER, 'w').close() with open(BAYANS) as b: bayan_ids = set(b.read().split()) N = 10 while True: for pic in Search().sort_by(sort.SCORE).limit(N)\ .query("first_seen_at.gt:30 days ago", "safe", "-animated", "-comic", "-screencap", "-anthro"): if pic.id not in bayan_ids: bot.send_photo(chat_id, pic.large) with open(BAYANS, 'a') as b: b.write(pic.id + '\n') os.remove(LOCKER) print("Anti-Hibonicus art sent!") return N *= 3
async def on_message(message): #Event for when message gets recieved if not message.server: #DMs if message.author == client.user: return if message.content.startswith(COMMAND_PREFIX): command = message.content.split(' ' , maxsplit=1) if command[0] == COMMAND_PREFIX+'mute': await cog_notifications.mute(client, message) if command[0] == COMMAND_PREFIX+'unmute': await cog_notifications.unmute(client, message) else: print('({1.hour:02d}:{1.minute:02d}){0.author.name} send us a message in DM.'.format(message, datetime.now())) print('\"{0.author.name}:{0.clean_content}\"'.format(message)) #await client.send_message(client.get_channel('303603185514184705'), '{0.author.name}(`{0.author.id}`) send me a message in DM. He said:\n"{0.clean_content}"'.format(message)) if message.server: #not DMs if message.server.id in authorized_servers: #Accessing global variables with ability to write global DERPIBOORU_ENABLED global EQD_FEED_ENABLED global MEME_ENABLED global ME_ENABLED global MENTION_ENABLED global undo_posts global derpi_undo_posts global meme_timer global mention_timer global derpi_timer if message.channel.id in meme_commands: #For commands in meme channel if message.content.startswith(COMMAND_PREFIX): command = message.content.split(' ' , maxsplit=1) if command[0] == COMMAND_PREFIX+'undo': #Pmeme undo command. Deletes last pmeme message sender got print('({1.hour:02d}:{1.minute:02d}) undo command by {0}'.format(message.author.name, datetime.now())) for msg, user in reversed(undo_posts): if user == message.author: await client.delete_message(msg) undo_posts.remove((msg, user)) #print([i[1] for i in undo_posts]) return await client.send_message(message.channel, 'Nothing to undo for you, silly') print('nothing to undo') if command[0] == COMMAND_PREFIX+'pmeme': #Pmeme command. Gets a random derpi image tagged "meme" if not MEME_ENABLED: await client.send_message(message.channel, random.choice(command_off_quotes)) return if len(command) == 1: meme_query = '' else: meme_query = command[1] print('({1.hour:02d}:{1.minute:02d}) pmeme command by {0} with tags "{2}"'.format(message.author.name, datetime.now(), meme_query)) if meme_timer.is_alive(): await client.send_message(message.channel, random.choice(cooldown_quotes)) print('pmeme cooldown'.format(datetime.now())) return if message.channel.id not in commands_channels: meme_timer = Timer(MEME_COOLDOWN, empty) #cooldown meme_timer.start() for image in Search().sort_by(sort.RANDOM).query(meme_query).filter(DERPI_MEME_FILTER): msg = await client.send_message(message.channel, image.url) undo_posts.append((msg, message.author)) if len(undo_posts) > 10: undo_posts.pop(0) #print(undo_posts) return await client.send_message(message.channel, "I can't find anything") meme_timer.cancel() print('nothing found') if message.channel.id in art_commands: #For commands in art channel if message.content.startswith(COMMAND_PREFIX): command = message.content.split(' ' , maxsplit=1) if command[0] == COMMAND_PREFIX+'undo': #pony undo command. Deletes last ponyr or pony message sender got print('({1.hour:02d}:{1.minute:02d}) undo command by {0}'.format(message.author.name, datetime.now())) for msg, user in reversed(derpi_undo_posts): if user == message.author: await client.delete_message(msg) derpi_undo_posts.remove((msg, user)) #print(derpi_undo_posts) return await client.send_message(message.channel, 'Nothing to undo for you, silly') print('nothing to undo') if command[0] == COMMAND_PREFIX+'ponyr': #Ponyr command. Gets a random derpi image with or without user tags. if not DERPIBOORU_ENABLED: await client.send_message(message.channel, random.choice(command_off_quotes)) return derpi_filter = DERPI_GENERAL_FILTER if len(command) == 1: derpi_query = '' else: derpi_query = command[1] if command[1].find('artist:') != -1: derpi_filter = DERPI_GENERAL_ARTIST_FILTER print('({1.hour:02d}:{1.minute:02d}) Pony with tags:"{0}"'.format(derpi_query, datetime.now())) if derpi_timer.is_alive(): await client.send_message(message.channel, random.choice(cooldown_quotes)) print('ponyr cooldown'.format(datetime.now())) return if message.channel.id not in commands_channels: derpi_timer = Timer(DERPI_COOLDOWN, empty) derpi_timer.start() for image in Search().sort_by(sort.RANDOM).query(derpi_query).filter(filter_id=derpi_filter): msg = await client.send_message(message.channel, image.url) derpi_undo_posts.append((msg, message.author)) if len(derpi_undo_posts) > 10: derpi_undo_posts.pop(0) #print(derpi_undo_posts) return await client.send_message(message.channel, "I can't find anything") derpi_timer.cancel() print('nothing found') if command[0] == COMMAND_PREFIX+'pony': #Pony command. Gets newest derpi image with or without user tags. if not DERPIBOORU_ENABLED: await client.send_message(message.channel, random.choice(command_off_quotes)) return derpi_filter = DERPI_GENERAL_FILTER if len(command) == 1: derpi_query = '' else: derpi_query = command[1] if command[1].find('artist:') != -1: derpi_filter = DERPI_GENERAL_ARTIST_FILTER print('({1.hour:02d}:{1.minute:02d}) Pony with tags:"{0}"'.format(derpi_query, datetime.now())) if derpi_timer.is_alive(): await client.send_message(message.channel, random.choice(cooldown_quotes)) print('pony cooldown'.format(datetime.now())) return if message.channel.id not in commands_channels: derpi_timer = Timer(DERPI_COOLDOWN, empty) derpi_timer.start() for image in Search().query(derpi_query).filter(filter_id=derpi_filter): msg = await client.send_message(message.channel, image.url) derpi_undo_posts.append((msg, message.author)) if len(derpi_undo_posts) > 10: derpi_undo_posts.pop(0) #print([v.name for v in derpi_undo_posts.values()]) return await client.send_message(message.channel, "I can't find anything") derpi_timer.cancel() print('nothing found') if message.channel.id in commands_channels: #For general (staff) commands. Preferably to add mod user filter if message.content.startswith(COMMAND_PREFIX): command = message.content.split(' ' , maxsplit=1) if command[0] == COMMAND_PREFIX+'mute': #Mute command. Mutes sub notifications await cog_notifications.mute(client, message) if command[0] == COMMAND_PREFIX+'unmute': #Unmute command. Unmutes sub notifications await cog_notifications.unmute(client, message) if command[0] == COMMAND_PREFIX+'subscribe': #Subscribe command. Adds your id to the list of recievers of something. await cog_notifications.subscribe(client, message, command) if command[0] == COMMAND_PREFIX+'unsubscribe': #Unsubscribe command. Removes your id form the list of recievers of something. await cog_notifications.unsubscribe(client, message, command) if command[0] == COMMAND_PREFIX+'names': #Names command. Prints the last recorded 20 names and nicknames of a user. await cog_commands.names(client, message, command) if command[0] == COMMAND_PREFIX+'togglemention': #Togglemention command. Enables/disables responce to a mention MENTION_ENABLED = not MENTION_ENABLED if MENTION_ENABLED: await client.send_message(message.channel, 'Reaction to mentions is now enabled') else: await client.send_message(message.channel, 'Reaction to mentions is now disabled') if command[0] == COMMAND_PREFIX+'togglememe': #Togglememe command. Enables/disables pmeme MEME_ENABLED = not MEME_ENABLED if MEME_ENABLED: await client.send_message(message.channel, 'Meme commands are now enabled') else: await client.send_message(message.channel, 'Meme commands are now disabled') if command[0] == COMMAND_PREFIX+'toggleme': #Togglememe command. Enables/disables me ME_ENABLED = not ME_ENABLED if ME_ENABLED: await client.send_message(message.channel, 'Me command is now enabled') else: await client.send_message(message.channel, 'Me command is now disabled') if command[0] == COMMAND_PREFIX+'me': #Me command. Makes bot say the message given in specified channel if not ME_ENABLED: return if len(command) > 1: me_command = command[1].split(' ', maxsplit=1) print('({1.hour:02d}:{1.minute:02d}) me command with args {0}'.format((message.clean_content.split(' ' , maxsplit=1))[1], datetime.now())) me_channel_id = me_command[0].strip('<>#!') if len(me_command) > 1 and me_channel_id.isdecimal() and client.get_channel(me_channel_id) and me_channel_id not in serious_channels: try: await client.send_typing(client.get_channel(me_channel_id)) await asyncio.sleep(min(len(me_command[1])*0.05*random.uniform(0.8,1.1), 6)) #"Typing..." length formula await client.send_message(client.get_channel(me_channel_id), stop_mass_mentions(me_command[1])) except discord.errors.Forbidden as e: await client.send_message(message.channel, 'I can\'t post there') return await client.send_message(message.channel, '```\n'+command[0]+' #channel <text_you_want_me_to_say>\n```') if command[0] == COMMAND_PREFIX+'togglederpi': #Togglederpi command. Enables/disables pony and ponyr DERPIBOORU_ENABLED = not DERPIBOORU_ENABLED if DERPIBOORU_ENABLED: await client.send_message(message.channel, 'Derpibooru commands are now enabled') else: await client.send_message(message.channel, 'Derpibooru commands are now disabled') if command[0] == COMMAND_PREFIX+'togglefeed': #Togglefeed command. Enables/disables feed EQD_FEED_ENABLED = not EQD_FEED_ENABLED if EQD_FEED_ENABLED: await client.send_message(message.channel, 'EQD feed is now enabled') else: await client.send_message(message.channel, 'EQD feed is now disabled') if command[0] == COMMAND_PREFIX+'urban': #Urban command. Gets Urbandictionary definition for the word if len(command) == 1: return print('({0.hour:02d}:{0.minute:02d}){1.author.name} used urban for word "{2}"'.format(datetime.now(), message, command[1])) defs = ud.define(command[1]) if not defs: print('Nothing found') await client.send_message(message.channel, 'Nothing found') return n = 0 em = discord.Embed(title=defs[n].word, description=defs[n].definition.replace('[', '').replace(']', ''), colour=0x134FE6) em.add_field(name='Example:', value=defs[n].example.replace('[', '').replace(']', '')) em.set_footer(text='{0} at UTC/GMT+0'.format(datetime.utcnow())) await client.send_message(message.channel, embed=em) if command[0] == COMMAND_PREFIX+'urbanr': #UrbanR command. Gets random Urbandictionary word and its definition defs = ud.random() if not defs: print('Urbanr Nothing found') await client.send_message(message.channel, 'Nothing found') return n = 0 print('({0.hour:02d}:{0.minute:02d}){1.author.name} used urbanr and got the word "{2}"'.format(datetime.now(), message, defs[n].word)) em = discord.Embed(title=defs[n].word, description=defs[n].definition.replace('[', '').replace(']', ''), colour=0x134FE6) em.add_field(name='Example:', value=defs[n].example.replace('[', '').replace(']', '')) em.set_footer(text='{0} at UTC/GMT+0'.format(datetime.utcnow())) await client.send_message(message.channel, embed=em) if command[0] == COMMAND_PREFIX+'ping': #Ping command. Simply replies with pong. Used to check if bot is alive print('({0.hour:02d}:{0.minute:02d}) pong'.format(datetime.now())) await client.send_message(message.channel, 'pong') if command[0] == COMMAND_PREFIX+'reason': #Reason command. Logs the ban in ban channel with given case and reason. await cog_banning.reason(client, message, command) if command[0] == COMMAND_PREFIX+'userinfo': #Userinfo command. Prints information about given user or sender, if no user given if len(command) == 1: userinfo_command = message.author.id else: userinfo_command = command [1] print('({1.hour:02d}:{1.minute:02d}){0.author.name} used `userinfo command'.format(message, datetime.now())) print('\"{0.author.name}:{0.content}\"'.format(message)) if userinfo_command.isdecimal(): #by id user = message.server.get_member(userinfo_command) elif (userinfo_command.strip('<>@!')).isdecimal(): #by ping user = message.server.get_member(userinfo_command.strip('<>@!')) else: #by name user = message.server.get_member_named(userinfo_command) if not user: await client.send_message(message.channel, 'User not found.\nUse \`userinfo <id/mention/name> to get info about user.') return if user.avatar_url: user_avatar_url = user.avatar_url else: user_avatar_url = user.default_avatar_url em = discord.Embed(title=':information_source: User info', colour=user.colour) em.set_author(name='User: @{0.name}#{0.discriminator} - {0.id}'.format(user)) em.set_thumbnail(url=user_avatar_url) em.add_field(name='User:'******'Nickname:', value=user.nick, inline=True) em.add_field(name="User created on:", value=user.created_at.strftime("%d %b %Y %H:%M") + ' ({} days ago) '.format((message.timestamp - user.created_at).days), inline=False) em.add_field(name="User joined on:", value=user.joined_at.strftime("%d %b %Y %H:%M") + ' ({} days ago)'.format((message.timestamp - user.joined_at).days), inline=False) if len(user.roles) > 1: em.add_field(name="Roles:", value=", ".join([x.name for x in user.roles if x.name != "@everyone"]), inline=False) em.set_footer(text='{0} at UTC/GMT+0'.format(datetime.utcnow())) await client.send_message(message.channel, embed=em) if command[0] == COMMAND_PREFIX+'serverinfo': #Serverinfo command. Prints information about current server print('({1.hour:02d}:{1.minute:02d}){0.author.name} used `serverinfo command'.format(message, datetime.now())) print('\"{0.author.name}:{0.content}\"'.format(message)) em = discord.Embed(title=':information_source: Server info', colour=0x80A0EE) em.set_author(name=message.server.name + ' - ' + message.server.id) em.set_thumbnail(url=message.server.icon_url) em.add_field(name='Members:', value=message.server.member_count) em.add_field(name='Owner:', value=message.server.owner.mention) ver_levels = {discord.VerificationLevel.none:'None - No criteria set.', discord.VerificationLevel.low:'Low - Member must have a verified email on their Discord account.', discord.VerificationLevel.medium:'Medium - Member must have a verified email and be registered on Discord for more than five minutes.', discord.VerificationLevel.high:'High - Member must have a verified email, be registered on Discord for more than five minutes, and be a member of the server itself for more than ten minutes.', discord.VerificationLevel.table_flip:'High - Member must have a verified email, be registered on Discord for more than five minutes, and be a member of the server itself for more than ten minutes.'} em.add_field(name='Verification level:', value=ver_levels.get(message.server.verification_level, 'None'), inline=False) em.add_field(name='Created on:', value=message.server.created_at.strftime("%d %b %Y %H:%M") + ' ({} days ago)'.format((message.timestamp - message.server.created_at).days), inline=False) em.set_footer(text='{0} at UTC/GMT+0'.format(datetime.utcnow())) await client.send_message(message.channel, embed=em) if message.server.me in message.mentions: #If someone mentions the bot if not MENTION_ENABLED: return print('({1.hour:02d}:{1.minute:02d}){0.author.name} mentioned bot in {0.channel.name} at {0.server.name}.'.format(message, datetime.now())) print('\"{0.author.name}:{0.clean_content}\"'.format(message)) if mention_timer.is_alive(): return if message.channel.id not in commands_channels: mention_timer = Timer(MENTION_COOLDOWN, empty) #mention cooldown mention_timer.start() rand = random.randint(5,15) if '?' in message.content: rand_q = emojify(random.choice(ball8_quotes), message.server) elif ':boop:' in message.content: rand_q = emojify(':boop:', message.server) + message.author.mention print(rand_q) elif ':hugs:' in message.content: rand_q = emojify(':hugs:', message.server) + message.author.mention else: rand_q = emojify(random.choice(mention_quotes), message.server) print('And we answered in {0} sec with \"{1}\"'.format(rand, rand_q)) await asyncio.sleep(rand) await client.send_message(message.channel, rand_q) if message.server: if message.server.id in authorized_servers: if message.channel.id not in serious_channels and message.channel.id != '151834220841533440': #staff for i in banned_words: if i in message.content.lower(): if message.author.nick is None: print('({1.hour:02d}:{1.minute:02d}){0.author.name} said banned word in #{0.channel.name} at {0.server.name}.'.format(message, datetime.now())) print('\"{0.author.name}:{0.content}\"'.format(message)) dmsg = '{0.author.name}`({0.author.id})` said banned word in #{0.channel.name} at {0.server.name}.\n\"{0.author.name}:{0.content}\"'.format(message) await cog_notifications.dispatch(client, 'banned words', dmsg) else: print('({1.hour:02d}:{1.minute:02d}){0.author.nick}({0.author.name}) said banned word in #{0.channel.name} at {0.server.name}.'.format(message, datetime.now())) print('\"{0.author.nick}:{0.content}\"'.format(message)) dmsg = '{0.author.nick}({0.author.name})`({0.author.id})` said banned word in #{0.channel.name} at {0.server.name}.\n\"{0.author.nick}:{0.content}\"'.format(message) await cog_notifications.dispatch(client, 'banned words', dmsg) break if message.channel.id in general_channels: if message.attachments: for i in message.attachments: if i: try: if(i.get('width') is not None) and (i.get('height') > 128): if i.get('width') > 400: if (i.get('height')*0.75) < 128: break if message.author.nick is None: dmsg = '{0.author.name}`({0.author.id})` posted a picture({1}x{2}) in #{0.channel.name} at {0.server.name}.'.format(message, i.get('width'),i.get('height')) print('({0.hour:02d}:{0.minute:02d})'.format(datetime.now())+dmsg) await cog_notifications.dispatch(client, 'oversized images', dmsg) else: dmsg = '{0.author.nick}({0.author.name})`({0.author.id})` posted a picture({1}x{2}) in #{0.channel.name} at {0.server.name}.'.format(message, i.get('width'),i.get('height')) print('({0.hour:02d}:{0.minute:02d})'.format(datetime.now())+dmsg) await cog_notifications.dispatch(client, 'oversized images', dmsg) break except AttributeError: print('({1.hour:02d}:{1.minute:02d}){0.author.name} posted weird embed in #{0.channel.name} at {0.server.name}.'.format(message, datetime.now())) break if message.embeds: for i in message.embeds: if i.get('type') == 'image': if(i.get('thumbnail').get('width')) and (i.get('thumbnail').get('height') > 128): if i.get('thumbnail').get('width') > 400: if (i.get('thumbnail').get('height')*0.75) < 128: break if message.author.nick is None: dmsg = '{0.author.name}`({0.author.id})` posted a picture({1}x{2}) in #{0.channel.name} at {0.server.name}.'.format(message, i.get('thumbnail').get('width'),i.get('thumbnail').get('height')) print('({0.hour:02d}:{0.minute:02d})'.format(datetime.now())+dmsg) await cog_notifications.dispatch(client, 'oversized images', dmsg) else: dmsg = '{0.author.nick}({0.author.name})`({0.author.id})` posted a picture({1}x{2}) in #{0.channel.name} at {0.server.name}.'.format(message, i.get('thumbnail').get('width'),i.get('thumbnail').get('height')) print('({0.hour:02d}:{0.minute:02d})'.format(datetime.now())+dmsg) await cog_notifications.dispatch(client, 'oversized images', dmsg) break
def __init__(self, client): self.client = client self.searcher = Search(filter_id=56027) # "everything" filter
class search(commands.Cog): def __init__(self, client): self.client = client self.searcher = Search(filter_id=56027) # "everything" filter async def do_sfw_snark(self, ctx, tags): if 'grimdark' in tags and 'explicit' in tags: await ctx.channel.send("Absolutely not.") elif 'explicit' in tags or 'questionable' in tags or 'suggestive' in tags: if 'lyra' in tags: await ctx.channel.send( "Hey, at least take me out to dinner first!") else: await ctx.channel.send( "Ponies are NOT for sexual ||at least not in this channel||" ) elif 'grimdark' in tags: await ctx.channel.send("I'd rather not see that") elif 'anthro' in tags: await ctx.channel.send("Get some better taste!") elif 'scootabuse' in tags: await ctx.channel.send("Imagine all the people") else: return False return True async def do_nsfw_snark(self, ctx, tags): if 'grimdark' in tags or 'anthro' in tags or 'scootabuse' in tags: await ctx.channel.send("<:ew:532536050350948376>") return True return False async def do_escape_paren_snark(self, ctx, tags): searchstring = ", ".join(tags) quoted = False escaped = False balance = 0 for char in searchstring: if quoted: if char == "\"": quoted = False continue elif char == "\"": quoted = True continue if escaped: escaped = False continue elif char == "\\": escaped = True continue if char == "(": balance += 1 elif char == ")": balance -= 1 if balance < 0: await ctx.channel.send("Very funny.") return True return False @commands.command() @commands.cooldown(1, 5, commands.BucketType.user) async def search(self, ctx, *, args="*"): """ Searches derpibooru for a given set of tags """ tags = [] if "_" in args: args = args.replace(" ", ",") args = args.replace("_", " ") tags = list(filter(None, [tag.strip() for tag in args.split(",")])) # meme joke youremom = ["you're mom", "youre mom", "you'remom", "youremom"] for mom in youremom: try: index = tags.index(mom) tags[index] = "gay" except ValueError: pass results = None # validate and choose content filtering tags if await self.do_escape_paren_snark(ctx, tags): return extratags = [] if not ctx.channel.is_nsfw(): if await self.do_sfw_snark(ctx, tags): return extratags = [ "-explicit", "-questionable", "-suggestive", "-grimdark", "-anthro", "-scootabuse" ] else: # in nsfw channel if await self.do_nsfw_snark(ctx, tags): return else: extratags = ["-grimdark", "-anthro", "-scootabuse"] for attempt in range(2): results = self.searcher.query(*extratags, "(" + ", ".join(tags) + ")").sort_by(sort.RANDOM).limit(1) if results is not None: posted = False # ugly workaround because results doesn't say if there's anything inside unless you look for post in results: await ctx.channel.send(post.url) posted = True if posted: break # first attempt didn't work, try splitting on spaces tags = " ".join(tags).split(" ") if not posted: await ctx.channel.send('No results for search "' + args + '". Too niche!')
class search(commands.Cog): def __init__(self, client): self.client = client self.searcher = Search(filter_id=56027) # "everything" filter def get_derpi_embed(self, image_id, image_url, oembed): url = f'https://derpibooru.org/images/{image_id}' title = oembed["title"] if len(title) > 70: title = f'{title[:67]}...' embed = discord.Embed(title=title, url=url, color=6393795).set_author( name=oembed["author_name"]).set_image(url=image_url) return embed async def do_sfw_snark(self, ctx, tags): if 'grimdark' in tags and 'explicit' in tags: await ctx.channel.send("Absolutely not.") elif 'explicit' in tags or 'questionable' in tags or 'suggestive' in tags: if 'lyra' in tags: await ctx.channel.send( "Hey, at least take me out to dinner first!") else: await ctx.channel.send( "Ponies are NOT for sexual ||at least not in this channel||" ) elif 'grimdark' in tags: await ctx.channel.send("I'd rather not see that") elif 'anthro' in tags: await ctx.channel.send("Get some better taste!") else: return False return True async def do_nsfw_snark(self, ctx, tags): if 'grimdark' in tags or 'anthro' in tags: await ctx.channel.send("<:ew:532536050350948376>") return True return False async def do_escape_paren_snark(self, ctx, tags): searchstring = ", ".join(tags) quoted = False escaped = False balance = 0 for char in searchstring: if quoted: if char == "\"": quoted = False continue elif char == "\"": quoted = True continue if escaped: escaped = False continue elif char == "\\": escaped = True continue if char == "(": balance += 1 elif char == ")": balance -= 1 if balance < 0: await ctx.channel.send("Very funny.") return True return False @commands.Cog.listener() async def on_message(self, message): if message.author.bot: return await asyncio.sleep(1) # let embeds show up regex = re.compile("derpicdn.net") for embed in message.embeds: print("## embed found -- checking if image present and from derpi") thumb = embed.thumbnail if thumb == discord.Embed.Empty: thumb = embed.image if thumb == discord.Embed.Empty: continue # direct links to derpicdn render fine and do not have titles if embed.title == discord.Embed.Empty: continue if regex.search(thumb.url): print( "## found derpi image embed -- checking if fixup required") oembed_url = f'https://derpibooru.org/api/v1/json/oembed?url={thumb.url}' data = requests.get(oembed_url).json() # derpi embeds are only screwy if source author_url is None if data["author_url"] is not None: continue print("## fixup required -- sending") image_id = data["derpibooru_id"] derpi_url = f'https://derpibooru.org/images/{image_id}' await message.channel.send(f"<{derpi_url}>", embed=self.get_derpi_embed( image_id, thumb.url, data)) @commands.command(aliases=["rollzig"]) @commands.cooldown(1, 5, commands.BucketType.user) async def rollzigger(self, ctx): """ Posts a random zigzog """ await self.search(ctx, args="Zecora") @commands.command() @commands.cooldown(1, 5, commands.BucketType.user) async def search(self, ctx, *, args="*"): """ Searches derpibooru for a given set of tags """ tags = [] if "_" in args: args = args.replace(" ", ",") args = args.replace("_", " ") tags = list(filter(None, [tag.strip() for tag in args.split(",")])) # meme joke youremom = ["you're mom", "youre mom", "you'remom", "youremom"] for mom in youremom: try: index = tags.index(mom) tags[index] = "gay" except ValueError: pass results = None # validate and choose content filtering tags if await self.do_escape_paren_snark(ctx, tags): return extratags = [] if (not ctx.channel.type == discord.ChannelType.private and not ctx.channel.type == discord.ChannelType.group and not ctx.channel.is_nsfw()): if await self.do_sfw_snark(ctx, tags): return extratags = [ "-explicit", "-questionable", "-suggestive", "-grimdark", "-anthro" ] else: # in nsfw channel if await self.do_nsfw_snark(ctx, tags): return else: extratags = ["-grimdark", "-anthro"] for attempt in range(2): results = self.searcher.query(*extratags, "(" + ", ".join(tags) + ")").sort_by(sort.RANDOM).limit(1) if results is not None: posted = False # ugly workaround because results doesn't say if there's anything inside unless you look for post in results: oembed_url = f'https://derpibooru.org/api/v1/json/oembed?url=https://derpibooru.org/{post.id}' data = requests.get(oembed_url).json() if data["author_url"] is not None: await ctx.send(post.url) else: derpi_url = f'https://derpibooru.org/images/{post.id}' await ctx.send(f'<{derpi_url}>', embed=self.get_derpi_embed( post.id, post.full, data)) posted = True if posted: break # first attempt didn't work, try splitting on spaces tags = " ".join(tags).split(" ") if not posted: await ctx.channel.send('No results for search "' + args + '". Too niche!')
from derpibooru import Search, sort import requests from glob import glob image_path = "data/images/" def download(id, url): r = requests.get(url, stream=True) if r.status_code == 200: with open(image_path + "{}.png".format(id), 'wb') as f: for chunk in r: f.write(chunk) query = "width.gt:1024, height.gt:1024, -animated" print(query) existing_files = [f[len(image_path):] for f in glob(image_path + "*")] for image in Search().query(query).sort_by(sort.SCORE).limit(100000): try: if "{}.png".format(image.id) not in existing_files: download(image.id, image.full) else: print('.', end='', flush=True) except (IndexError, AttributeError): print("failed at image " + image.id)
#### END OF CONFIG. DO NOT TOUCH ANYTHING ELSE UNLESS YOU WANT TO CHANGE THE FUNCTIONALITY #### print("Running!") oldValues = [] newValues = [] try: for image in Search().key(key).filter(searchFilter).query(tags): #Initialising the initial value oldValues.append(image.url) except: print("Error initialising picture search. Check your internet connection") while True: time.sleep(60*delaytime) try: for image in Search().key(key).filter(searchFilter).query(tags): #Fetch all image urls on first page newValues.append(image.url) checkForNewImages = set(newValues[0:int((len(newValues)*oldPicTolerance))]).difference(set(oldValues)) #Checks for the difference in NEW pics uploaded, not old ones. Might cause some bugs if a huge number of pics are uploaded in the span of delaytime. except: print("Error connecting to the Derpibooru servers") newValues = [] continue
with open(os.path.join(THIS_DIR, 'past.json'), 'w') as f: f.write(json.dumps(pastPosts)) # Load past ids file with open(os.path.join(THIS_DIR, 'past.json')) as d: pastPosts = json.load(d) # Login to Twitter API t = twitter.Api(consumer_key=config['twitter']['key'], consumer_secret=config['twitter']['secret'], access_token_key=config['twitter']['token'], access_token_secret=config['twitter']['tokenSecret']) # Looks for our watched list posts dt_delay = datetime.utcnow() - timedelta(minutes=30) for post in Search().key(config['derpi']).query( 'my:watched, %s' % dt_delay.strftime("%Y-%m-%d %H:%MZ")): # If the post is rendered and not already in our past ids if (post.is_rendered and post.id not in pastPosts): # Add hashtags hashtags = ['#Spoilers'] eps = [] for tag in post.tags: tag = tag.lower() if 'spoiler:s08' in tag: hashtags.append('#MLPSeason8') if 'spoiler:s08e' in tag: eps.append(tag.replace('spoiler:', '')) if 'spoiler:s09' in tag: