async def birthday(self, ctx, birthday_str=None): """Add a birthday to the database. Usage: `-birthday YYYY-MM-DD`""" author = ctx.message.author uid = author.id user = session.query(Birthday_Table).filter_by(uid=uid).first() # Try to enter args into db if birthday_str: birthday = self._parse_birthday(birthday_str) if not birthday: await self.bot.say( content=None, embed=create_error( "creating birthday. Format: `YYYY-MM-DD`")) return False if not user: birthday = Birthday_Table(uid=uid, birthday=birthday, times_changed=1) session.add(birthday) else: user.birthday = birthday if uid != config["owner_ids"]: user.times_changed = user.times_changed + 1 try: session.commit() except Exception as e: print(e) await self.bot.say( content=None, embed=create_error("entering into database.")) return False emb = discord.Embed(color=0x76f2ac) emb.set_author( name=f"{author.nick if author.nick else author.name}") emb.description = f"Birthday set. Changed {user.times_changed if user else 1}/3 times." await self.bot.say(content=None, embed=emb) elif user: year = user.birthday.year month = user.birthday.month day = user.birthday.day emb = discord.Embed(color=0xffffff) emb.set_author( name=f"{author.nick if author.nick else author.name}") emb.description = f"Birthday set to {year}-{month}-{day}." emb.description += f"\n_You have changed your birthday {user.times_changed} times ({3-user.times_changed} times left)._" await self.bot.say(content=None, embed=emb) else: await self.bot.say( content=None, embed=create_error( "- use -birthday `YYYY-MM-DD` to enter your birthday."))
async def togglerole(self, ctx): """toggle a role""" def check(message): try: return int(message.content) < 6 and int(message.content) > 0 except: return False async def cancel_action(): await self.bot.say("Cancelled.") await self._deletion_queue(None, delete=True) return False msg = "" counter = 1 roles = await self._getrole(ctx, None, True) rolenames = [] for role in roles: msg += f"` {counter} ` _{role}_\n" rolenames.append(role) counter += 1 user = await self._parse_user(ctx) if not user: return False manager = ctx.message.author msg = await self.bot.say(msg) await self._deletion_queue(msg) user_msg = await self.bot.wait_for_message(timeout=120.0, author=manager, check=check) if not user_msg: await self.bot.say( content=None, embed=create_error("that's not a valid response")) return False await self._deletion_queue(user_msg) role = rolenames[int(user_msg.content) - 1] if not await self._confirm_action( f"Toggle `{role}` on <@!{user.id}>. Is this correct?", manager): return await cancel_action() if not await self._toggle_role(ctx, role, user): await self.bot.say(content=None, embed=create_error("toggling role")) return False
def check(message): """Check if the strike to remove is indeed valid""" try: return int(message.content) in ids except: self.bot.say(content=None, embed=create_error("- enter a valid strike ID")) return False
async def _parse_user(self, ctx, author=False): """Parse user from message""" user = ctx.message.mentions mentions = len(user) if mentions > 1: await self.bot.say( content=None, embed=create_error("- too many users specified")) return False elif mentions == 1: return user[0] elif mentions == 0 and not author: try: members = ctx.message.server.members query = ' '.join(ctx.message.content.lower().split(' ') [1:]) #get command outta there if not query: return False for member in members: if query == member.id: return member elif query == f"{member.name}#{str(member.discriminator)}".lower( ): return member elif query == member.name.lower(): return member elif member.nick: if query == member.nick.lower(): return member except Exception as e: await self.bot.say(content=None, embed=create_error(f"getting user: {e}")) return False elif mentions == 0 and author: return ctx.message.author await self.bot.say(content=None, embed=create_error("no user found in your message")) return False
async def _get_user_strikes(self, id): headers = {"authorization": self.API_KEY} text = "" # Get the strikes and the strike IDs for the specified user async with aiohttp.ClientSession() as session: async with session.get(f'{self.BASE_URL}/user/{id}', headers=headers) as resp: try: text = await resp.json() except: await self.bot.say(content=None, embed=create_error("- something went wrong getting strikes")) return False try: text['user'] except: await self.bot.say(content=None, embed=create_error("- this user doesn't have any strikes, it seems")) return False return text
async def daily(self, ctx): """Gives you the daily bible verse.""" await self.bot.send_typing(ctx.message.channel) try: msg = await self._get_verse("votd") emb = self._build_embed(msg, ctx.message.author, "daily") await self.bot.say(content=None, embed=emb) except Exception as e: print(e) await self.bot.say(content=None, embed=create_error("getting daily verse"))
async def verse(self, ctx, *args): """Gives you a specified bible verse. Use as: -verse genesis 1:3""" await self.bot.send_typing(ctx.message.channel) try: requested_verse = f"{args[0]} {args[1]}" msg = await self._get_verse(requested_verse) emb = self._build_embed(msg, ctx.message.author, "verse") await self.bot.say(content=None, embed=emb) except Exception as e: print(e) await self.bot.say(content=None, embed=create_error("getting your verse"))
async def removestrike(self, ctx): """Remove strike from user""" def check(message): """Check if the strike to remove is indeed valid""" try: return int(message.content) in ids except: self.bot.say(content=None, embed=create_error("- enter a valid strike ID")) return False user = await self._parse_user(ctx) if not user: return False mod = ctx.message.author await self._deletion_queue(ctx.message) # Get the strikes and the strike IDs for the specified user message, ids = self._get_strike_message(user.id, ids=True) strike_msg = await self.bot.say(message) await self._deletion_queue(strike_msg) prompt_msg = await self.bot.say(content="Strike to remove:") await self._deletion_queue(prompt_msg) user_msg = await self.bot.wait_for_message(timeout=120.0, author=mod, check=check) if user_msg: await self._deletion_queue(user_msg) if not user_msg.content: return False removal_message = '' try: index = ids[int(user_msg.content)] record = session.query(Strike_Table).get(index) session.delete(record) session.commit() removal_message += f"<@!{mod.id}> removed strike from <@!{user.id}>.\n" removal_message += f"Removed item: {record.reason}" await self.bot.say(removal_message) except Exception as e: await self.bot.say(content=None, embed=create_error(f"deleting from DB: {e}")) return False await self._deletion_queue(delete=True)
async def _build_list(self, twitch_status, main): """Builds a list of everyone currently streaming""" try: emb = discord.Embed(color=0x933bce) if not main: if twitch_status["_total"] > 0: emb.description = f"**[Northernlion](https://twitch.tv/Northernlion)**\n" emb.description += f"Northernlion is not streaming at the moment." when_url = "http://whenisnlss.com/when" try: response = await fetch(when_url) emb.description += f"\n{response}" except: print('Error getting when') else: emb.color = 0x333333 emb.description = "**Offline**\nNo NLSS members are streaming at the moment." when_url = "http://whenisnlss.com/when" try: response = await fetch(when_url) emb.description += f"\n{response}" except: print('Error getting when') return emb if twitch_status["_total"] > 0: build_string = "" for stream in twitch_status["streams"]: timestr = self._build_uptime(stream["created_at"]) build_string += f'**[{stream["channel"]["display_name"]}]({stream["channel"]["url"]})**\n' build_string += f'**{stream["channel"]["status"]}**\n' build_string += f'Playing {stream["channel"]["game"]}\n' build_string += f'`{timestr} uptime | {stream["viewers"]} viewers`\n\n' emb.add_field(name="Streamers to watch", value=build_string) return emb except Exception as e: print(e) return create_error("building stream list")
async def strikes(self, ctx): """Check strikes of user or self""" user = await self._parse_user(ctx, author=True) if not user: return False message = self._get_strike_message(user.id) if ctx.message.channel.id == config["channels"]["mod-commands"]: await self.bot.say(message) else: if ctx.message.author.id == user.id: await self.bot.send_message(user, content=message) else: await self.bot.say( content=None, embed=create_error("- you may only view your own strikes"))
def _build_embed(self, msg: dict, author, type: str): colors = {"random": 0xff84a7, "daily": 0xffffff, "verse": 0xc3f945} try: for key in self.replacements: msg['text'] = msg['text'].replace(key, self.replacements[key]) emb = discord.Embed( title=f"{msg['bookname']} {msg['chapter']}:{msg['verse']}", description=f"{msg['text']}", color=colors[type]) #Create the embed object emb.set_footer( text= f"And bless you, {author.nick if author.nick else author.name}" ) return emb except Exception as e: print(e) return create_error("building embed")
async def rolelist(self, ctx): """Generate complete list of peeps""" members = ctx.message.server.members members_with_role = [] roles = await self._getrole(ctx, None, True) for member in members: for role in roles: if roles[role] in member.roles: members_with_role.append((member.id, role)) message = "" for member in members_with_role: message += f"<@!{member[0]}> has `{member[1]}`\n" if message == "": await self.bot.say( content=None, embed=create_error("- no members with relevant roles")) await self.bot.say(message)
async def _toggle_mute(self, ctx, mute): async def cancel_action(): await self.bot.say("Cancelled.") await self._deletion_queue(None, delete=True) return False user = await self._parse_user(ctx) if not user: return False action = "mute" if mute else "unmute" manager = ctx.message.author role = await self._pick_channel(manager, action, user) if not role: return await cancel_action() if not await self._toggle_role(ctx, role, user, strict=action): await self.bot.say( content=None, embed=create_error( f"toggling role on <@!{user.id}>. Maybe they already have it?" ))
async def status(self, ctx, *args): """Shows the status of NL's stream. Use -status others to see a list of other live NLSS members.""" arg = "" try: arg = args[0] except: arg = "None given" channels = ','.join(self.streamers["other"]) twitch_url = "https://api.twitch.tv/kraken/streams/" params = dict(channel=channels, client_id=self.twitch_token) await self.bot.send_typing(ctx.message.channel) try: response = await fetch(twitch_url, params=params) twitch_status = json.loads(response) main = self._check_main( twitch_status, self.streamers["main"]) # can be bool or object # Show status of main streamer if online if main and arg != "others": emb = self._build_embed(twitch_status, main) await self.bot.say(content=None, embed=emb) # Else or if specified, show other streamers instead elif not main or arg == "others": emb = await self._build_list(twitch_status, main) await self.bot.say(content=None, embed=emb) except Exception as e: print(f"{type(e).__name__}, {str(e)}") print(e) await self.bot.say( content=None, embed=create_error("getting stream information"))
async def strike(self, ctx): """Add a strike to the database""" async def cancel_action(): await self.bot.say("Cancelled.") await self._deletion_queue(None, delete=True) return False user = await self._parse_user(ctx) if not user: return False mod = ctx.message.author await self._deletion_queue(ctx.message) date = datetime.datetime.now() if not await self._confirm_action( f"Strike: <@!{user.id}>. Is this correct?", mod): return await cancel_action() reason = await self._get_reason(mod) #Get a reason if not reason: return await cancel_action() notes = await self._get_notes(mod) #Get any further notes if not await self._confirm_action( f"Striking <@!{user.id}> for {reason}. Is this correct?", mod): return await cancel_action() notes = '' if not notes else notes strike = Strike_Table(user_id=user.id, created_by=mod.id, created_on=date, reason=reason, notes=notes) session.add(strike) try: session.commit() # Add it to the DB except Exception as e: print(e) await self.bot.say( content=None, embed=create_error("entering strike into database: {e}")) # Tell the mod and the user about the strike count = session.query(Strike_Table).filter_by(user_id=user.id).count() mod_message = f"<@!{mod.id}> has given user <@!{user.id}> a strike.\n\n" mod_message += f"**Reason:** {reason}\n" if notes: mod_message += f"**Notes:** {notes}\n" mod_message += f"\nUser has **{count} {'strikes' if count > 1 else 'strike'}**." await self.bot.say(mod_message) await self._deletion_queue(None, delete=True) user_message = f"Hi {user.name},\n\nYou have received a strike in Eggserver Alpha.\n\n" user_message += f"**Reason:** {reason}.\n" user_message += f"You have **{count} {'strikes' if count > 1 else 'strike'}**.\n\n" user_message += f"If you have any further questions or concerns, please ask the mods." try: await self.bot.send_message(user, content=user_message) except Exception as e: await self.bot.say( content=None, embed=create_error( f"DMing <@!{user.id}>. Please follow up. <@!{mod.id}>, ({e})" ))
async def strike(self, ctx): """Add a strike to the database""" async def cancel_action(): await self.bot.say("Cancelled.") await self._deletion_queue(None, delete=True) return False user = await self._parse_user(ctx) if not user: return False mod = ctx.message.author await self._deletion_queue(ctx.message) if not await self._confirm_action(f"Strike: <@!{user.id}>. Is this correct?", mod): return await cancel_action() reason = await self._get_reason(mod) #Get a reason if not reason: return await cancel_action() notes = await self._get_notes(mod) #Get any further notes tier_id = await self._get_tier(mod) #Get any further notes if not tier_id: return await cancel_action() if not await self._confirm_action(f"Giving <@!{user.id}> a tier {tier_id} strike for {reason}. Is this correct?", mod): return await cancel_action() notes = '' if not notes else notes strike = { "user_id": user.id, "created_by": mod.id, "reason": reason, "attachment": notes, "tier_id": tier_id } headers = {"authorization": self.API_KEY} text = "" async with aiohttp.ClientSession() as session: async with session.post(f'{self.BASE_URL}/strike', data=strike, headers=headers) as resp: text = await resp.json() mod_message = f"<@!{mod.id}> has given user <@!{user.id}> a strike.\n\n" mod_message += f"**Reason:** {reason}\n" if notes: mod_message += f"**Notes:** {notes}\n" mod_message += f"\nUser has **{text['user_points']} strike points**. " if text['user_points'] < self.MAX_STRIKE_POINTS: mod_message += f"Mute this user for {text['mute']} hours." else: mod_message += "**This user should be banned.**" mod_message += f"\nView strikes at {self.BASE_URL}/#user/{user.id}" await self.bot.say(mod_message) await self._deletion_queue(None, delete=True) user_message = f"Hi {user.name},\n\nYou have received a strike in Eggserver.\n\n" user_message += f"**Reason:** {reason}.\n" user_message += f"You now have **{text['user_points']} strike points**, " user_message += f"view your strikes at {self.BASE_URL}/#user/{user.id}.\n" user_message += f"If you have any further questions or concerns, please ask the mods." try: await self.bot.send_message(user, content=user_message) except Exception as e: await self.bot.say(content=None, embed=create_error(f"DMing <@!{user.id}>. Please follow up. <@!{mod.id}>, ({e})"))
async def removestrike(self, ctx): """Remove strike from user""" def check(message): """Check if the strike to remove is indeed valid""" try: return int(message.content) in ids except: self.bot.say(content=None, embed=create_error("- enter a valid strike ID")) return False user = await self._parse_user(ctx) if not user: return False mod = ctx.message.author await self._deletion_queue(ctx.message) text = await self._get_user_strikes(user.id) if not text: return False ids = {} counter = 1 message = "" for item in text["strikes"]: strike = f"Strike {counter} ({item['tier']} tier)\n - {item['reason']}" if item['removed']: strike = f"```haskell\n#REMOVED\n{strike}```\n" elif item['expired']: strike = f"```haskell\n#EXPIRED\n{strike}```\n" else: strike = f"```haskell\n{strike}```\n" if len(message) + len(strike) < 2000: message += strike else: await self.bot.say(message) message = strike if not item['expired'] and not item['removed']: ids[counter] = item['id'] counter += 1 await self.bot.say(message) prompt_msg = await self.bot.say(content="**Strike to remove:**") await self._deletion_queue(prompt_msg) user_msg = await self.bot.wait_for_message(timeout=120.0, author=mod, check=check) if user_msg: await self._deletion_queue(user_msg) if not user_msg.content: return False removal_message = f'<@!{mod.id}> removed strike {user_msg.content} from <@!{user.id}>.' try: index = ids[int(user_msg.content)] data = { "removed_by": mod.id } headers = {"authorization": self.API_KEY} async with aiohttp.ClientSession() as session: async with session.delete(f'{self.BASE_URL}/strike/{index}', data=data, headers=headers) as resp: text = await resp.json() await self.bot.say(removal_message) except Exception as e: await self.bot.say(content=None, embed=create_error(f"deleting from DB: {e}")) return False await self._deletion_queue(delete=True)