async def quote_delete_command(self, ctx, quote_id: str): """ Delete a specific Quote with quote_id """ user = self.get_user(ctx.message.author) server = self.get_server(ctx.message.server) try: quote = Quote.objects.get(quote_id=quote_id.strip()) try: quote.delete() Log.objects.create( message="Quote ID {} deleted by {}.\nQuote Message:\n\n{}". format(quote_id, user, quote.message)) await self.bot.say( "{}, The Quote with ID `{}` has been deleted!".format( ctx.message.author.mention, quote_id)) except Exception as e: log_item = Log.objects.create( message="{}\nError deleting Quote\n{}\nquote_id: {}". format(logify_exception_info(), e, quote_id)) await self.bot.say( "{}, The Quote with ID `{}` could not be deleted! Please contact my owner with the following code: `{}`" .format(ctx.message.author.mention, quote_id, log_item.message_token)) except Quote.DoesNotExist as e: await self.bot.say( "{}, A Quote qith ID `{}` cannot be found!".format()) except Exception as e: log_item = Log.objects.create( message="{}\nError retrieving Quote\n{}\nquote_id: {}".format( logify_exception_info(), e, quote_id)) await self.bot.say( "{}, There was an error when trying to get your Quote. Please contact my Owner with the following code: `{}`" .format(ctx.message.author.mention, log_item.message_token), delete_after=30)
async def prune_channels(self): error = False channels = Channel.objects.filter(private=False, game_channel=True, expire_date__lte=timezone.now(), deleted=False) if channels.count() >= 1: log_item = Log(message="Running task to prune channels:\n{}\n\n".format(logify_object(channels))) for channel in channels: if channel is None: continue log_item.message += 'Deleting channel {}\n\n'.format(channel) try: c = await self.bot.get_channel(channel.channel_id) if c is not None: try: await self.bot.delete_channel(c) # log_item.message += '- Success' except Exception as e: error = True log_item.message += '- Failure\n\n{}{}\n'.format(logify_exception_info(), e) except Exception as e: # Channel no longer exists on server error = True log_item.message += '- Failure\n\n{}{}\n'.format(logify_exception_info(), e) finally: channel.deleted = True channel.save() log_item.message += "\n\n" await asyncio.sleep(1) if error: log_item.save() else: # No channels found to be deleted pass
async def run_scheduled_tasks(self): error = False tasks = Task.objects.filter(cancelled=False, completed=False, expire_date__lte=timezone.now()) log_item = Log(message="Starting task processing\n") for task in tasks: # log_item.message += 'Running task for {} at {}\n'.format(task.user, timezone.now()) if task.task == Task.ADD_TO_GAME_CHAT: try: user = DiscordUser.objects.get(pk=task.user.pk) game = Game.objects.get(pk=task.game.pk) channel = Channel.objects.get(pk=task.channel.pk) # log_item.message += 'Game: {}\nChannel: {}\nUser: {}\nTask PK: {}\n\n'.format(user, game, channel, task.pk) except Game.DoesNotExist as e: error = True log_item.message += '- Error finding game for task.\n{}{}\n'.format(logify_exception_info(), e) except Channel.DoesNotExist as e: error = True log_item.message += '- Error finding channel for game {}\n{}{}\n'.format(game, logify_exception_info(), e) except Exception as e: error = True log_item.message += '- Unknown error happened\n{}{}\n'.format(logify_exception_info(), e) else: # Not really a task for some reason # log_item.message += '- I don\'t recognize the task type \'{}\'...'.format() pass # log_item.message += '- Finished processing task\n' if error: log_item.save()
async def quote_add_command(self, ctx, user: discord.Member, *, message: str): """ Create a quote for a specific User """ quote_user = self.get_user(user) server = self.get_server(ctx.message.server) user = self.get_user(ctx.message.author) content = message.strip() try: quote = Quote.objects.create(timestamp=timezone.now(), user=quote_user, added_by=user, server=server, message=content) await self.bot.say( "{0}, Your quote was create successfully!\nThe Quote ID is `{1}`\nYou can use this to reference it in the future by typing `?quote get {1}`" .format(ctx.message.author.mention, quote.quote_id), delete_after=30) except Exception as e: log_item = Log.objects.create( message= "{}\nError creating Quote\n{}\nquote_user: {}\nuser: {}\nserver: {}\nmessage: {}\nmentions: {}" .format(logify_exception_info(), e, quote_user, user, server, message, mentions)) await self.bot.say( "{}, There was an error when trying to create your Quote. Please contact my Owner with the following code: `{}`" .format(ctx.message.author.mention, log_item.message_token), delete_after=30)
def email_log(sender, instance, *args, **kwargs): if isinstance(instance, Log): if instance.email: if instance.subject is None or instance.subject == '': subject = "Log item needs your attention" else: subject = instance.subject if instance.body is None or instance.body == '': body = instance.message else: body = instance.body try: divider = '-' * 50 send_mail( subject='{} {}'.format(settings.EMAIL_SUBJECT_PREFIX, subject), message="Message Token: {0}\n\n{1}\n\n{2}\n\n{1}".format( instance.message_token, divider, body), from_email=settings.SERVER_EMAIL, recipient_list=settings.ADMINS) except Exception as e: Log.objects.create( message="Error sending email about log {}\n\n{}".format( logify_exception_info()), message_token='ERROR_SENDING_EMAIL')
async def update_channels(self): error = False for server in Server.objects.all(): # This will be to populate Channels and Users s = self.bot.get_server(server.server_id) log_item = Log(message="Starting population of channels for server {}\n\n".format(server)) try: for c in s.channels: if c.is_private or c.type == ChannelType.voice: continue channel, created = Channel.objects.get_or_create(channel_id=c.id, server=server) channel.name = c.name channel.created_date = pytz.timezone('UTC').localize(c.created_at) channel.save() channels = Channel.objects.filter(server=server, deleted=False) # log_item.message += "Found channels:\n{}\n\n".format(logify_object(channels)) for channel in channels: try: # log_item.message += "Running for channel {}\n".format(channel) c = self.bot.get_channel(channel.channel_id) if c.is_default: # log_item.message += "- Channel is default channel, skipping...\n" continue if c is None: # log_item.message += "- Channel is not found, marking as deleted\n" c.deleted = True c.save() continue except Exception as e: error = True log_item.message += "- Failed:\n{}\n{}\n".format(logify_exception_info(), e) finally: # log_item.message += "- Finished channel processing\n\n" pass # log_item.message += "\n" except Exception as e: error = True log_item.message += "- Failed: {}\n{}\n".format(logify_exception_info(), e) finally: if error: log_item.save()
def update_account_view(request): template = 'gaming/update_account.html' user = request.user if not user.is_authenticated(): messages.add_message(request, messages.WARNING, 'Please login before accessing that page') return redirect('{}?next={}'.format(reverse('account_login'), reverse('account_update'))) if request.method == 'POST': form = UpdateAccountForm(request.POST, instance=user) if form.is_valid(): try: u = form.save() if u.is_active: messages.add_message(request, messages.SUCCESS, 'Profile saved successfully!') form = UpdateAccountForm(instance=u) else: return redirect('account_logout') except Exception as e: log_item = Log.objects.create( message="Error saving form for user {}\n{}".format( user, logify_exception_info())) messages.add_message(request, messages.ERROR, 'An error occurred saving the settings.') messages.add_message( request, messages.ERROR, 'Please contact your administrator with the following: {}'. format(log_item.message_token)) else: messages.add_message(request, messages.WARNING, 'The form is not valid, please try again.') else: form = UpdateAccountForm(instance=user) context = { 'form': form, } return render(request, template, context)
async def quote_get_command(self, ctx, quote_id: str): """ Get a specific Quote based on quote_id """ server = self.get_server(ctx.message.server) user = self.get_user(ctx.message.author) quote_id = quote_id.strip() try: quote = Quote.objects.get(quote_id=quote_id.strip()) await self.bot.say("{}".format( self.beautify_quote(quote, requester=user))) except Quote.DoesNotExist as e: await self.bot.say( "{}, I'm sorry but I can't find a quote with the ID `{}`". format(ctx.message.author.mention, quote_id), delete_after=30) except Exception as e: log_item = Log.objects.create( message="{}\nError retrieving Quote\n{}\nquote_id: {}".format( logify_exception_info(), e, quote_id)) await self.bot.say( "{}, There was an error when trying to get your Quote. Please contact my Owner with the following code: `{}`" .format(ctx.message.author.mention, log_item.message_token), delete_after=30)
def get_user(self, member): """ Returns a :class:`gaming.models.DiscordUser` object after getting or creating the user """ error = False u, created = DiscordUser.objects.get_or_create(user_id=member.id) try: u.name = member.name u.bot = member.bot avatar_url = member.avatar_url if avatar_url is None or avatar_url == "": avatar_url = member.default_avatar_url u.avatar_url = avatar_url # Log.objects.create(message="u: {0}\ncreated: {1}\nname: {0.name}\navatar_url: {0.avatar_url}\nbot: {0.bot}".format(u, created)) except Exception as e: error = True Log.objects.create(message="Error trying to get DiscordUser object for member: {}.\n{}".format(u, logify_exception_info())) finally: u.save() return u
def get_server(self, server): """ Returns a :class:`gaming.models.Server` object after getting or creating the server """ error = False s, created = Server.objects.get_or_create(server_id=server.id) try: s.name = server.name s.icon = server.icon s.owner = self.get_user(server.owner) s.save() # Log.objects.create(message="s: {0}\ncreated: {1}\nname: {0.name}\nicon: {0.icon}\nowner: {0.owner}".format(s, created)) except Exception as e: error = True Log.objects.create(message="Error trying to get Server object for server {}.\n{}".format(s, logify_exception_info())) finally: s.save() return s
def generate_log_token(self, save=True): """ Used to generate a unique token for this Log Called by a signal if no message_token is specified (recommended) If an error occurs generating a token, a new Log will be created with the exception information and a token of "ERROR_GENERATING_LOG_TOKEN" """ try: if self.message_token is None or self.message_token == '': self.message_token = self.generate_token() if save: self.save() return True except Exception as e: print(e) self.__class__.objects.create(message="{}\nError generating log token.\n\nException:\n{}".format(logify_exception_info(), e), message_token="ERROR_GENERATING_LOG_TOKEN") return False
def generate_quote_id(self, save=True): """ Used to generate a unique ID for this Quote Called by a signal if no quote_id is specified (recommended) If an error occurs generating an ID, a Log will be created with the exception information """ try: if self.quote_id is None or self.quote_id == '': self.quote_id = self.generate_id() if save: self.save() return True except Exception as e: print(e) Log.objects.create(message="{}\nError generating quote id.\n\nException:\n{}".format(logify_exception_info(), e)) return False
async def who_plays(self, ctx, *, game_search_key: str = None, page_number: str = None): """ See who has played a certain game in the past """ user = self.get_user(ctx.message.author) server = self.get_server(ctx.message.server) games = Game.objects.all() log_item = Log.objects.create( message="Log item for {} on {} searching for {}".format( user, server, game_search_key)) if not user or user.bot: return time_ran_out = False game = False page = 0 if page_number: if page_number.lower().startswith('p'): page = int(page_number[1::]) - 1 if game_search_key: current_searches = self.get_game_searches(user=user, server=server) current_searches_games = [ search.game for search in current_searches ] try: possible_games = Game.objects.filter(pk=int(game_search_key)) except: possible_games = Game.objects.filter( name__icontains=game_search_key) games = possible_games games = self.map_games(games) if len(games) == 1: game = games[1] game_search, created = self.create_game_search(user, game) else: msg = False temp_message = '{0.message.author.mention}: Which game did you want to search for?\n_Please only type in the number next to the game_\n_You have 30 seconds to respond_\n'.format( ctx) formatted_games = await self.game_beautify( games, reserve=len(temp_message), page=page) final_message = '{}{}'.format(temp_message, formatted_games) question_message = await self.bot.say(final_message) gameIDs = games.keys() def check(msg): try: return int(msg.content.strip()) in gameIDs except: return False msg = await self.bot.wait_for_message(author=ctx.message.author, check=check, timeout=30) if isinstance(msg, discord.Message): try: content = msg.content.strip() try: possible_game = Game.objects.filter( pk=games[int(content)].pk) except: possible_game = Game.objects.filter( name__icontains=content) if possible_game.count() == 1: game = possible_game[0] except Exception as e: log_item.message += '- Failed\n\n{}'.format( logify_exception_info()) await self.bot.delete_message(msg) else: time_ran_out = True await self.bot.delete_message(question_message) log_item.save() if game: temp_message = '{0.message.author.mention}\n'.format(ctx) await self.bot.say('{}{}'.format( temp_message, await self.game_user_beautify(game, server, user, reserve=len(temp_message), page=page)), delete_after=30) elif time_ran_out: await self.bot.say( 'Whoops... looks like your time ran out {0.message.author.mention}. Please re-run the command and try again.' .format(ctx), delete_after=30) else: await self.bot.say( "{0.message.author.mention}: I didn't quite understand your response, please run the command again." .format(ctx), delete_after=30) await self.bot.delete_message(ctx.message)
async def looking_for_game_remove(self, ctx, *, game_search_key: str = None, page_number: str = None): """ Stop searching for a game """ user = self.get_user(ctx.message.author) server = self.get_server(ctx.message.server) games_removed = [] log_item = Log.objects.create( message="Log item for {} on {} trying to stop searching for {}". format(user, server, game_search_key)) if not user or user.bot: return page = 0 if page_number: if page_number.lower().startswith('p'): page = int(page_number[1::]) - 1 game_search_cancelled = False time_ran_out = False no_game_searches = False if game_search_key: games = Game.objects.filter(name__icontains=game_search_key) else: game_pks = [] for search in self.get_game_searches(user=user): game_pks.append(search.game.pk) games = Game.objects.filter(pk__in=game_pks) game_removed = 'All Games' games = self.order_games(games) if games.count() == 1: game = games[0] game_search = self.get_game_searches(user=user, game=game) games_removed = [search.game for search in game_search] game_search.update(cancelled=True) game_search_cancelled = True else: game_searches = self.get_game_searches(user=user) games = [] for game in game_searches: if game.game not in games: games.append(game.game) if len(games) >= 1: games = self.map_games(games) temp_message = '{0.message.author.mention}: Which game would you like to stop searching for?\n_Please only type in the number next to the game_\n_You have 30 seconds to respond_\n'.format( ctx) formatted_games = await self.game_beautify(games, page=page) final_message = '{}{}'.format(temp_message, formatted_games) question_message = await self.bot.say(final_message) gameIDs = games.keys() def check(msg): try: return int(msg.content.strip()) in gameIDs except: return False msg = False msg = await self.bot.wait_for_message( author=ctx.message.author, check=check, timeout=30) if isinstance(msg, discord.Message): try: content = msg.content.strip() try: possible_game = Game.objects.filter( pk=games[int(content)].pk) except: possible_game = Game.objects.filter( name__icontains=game_pk) if possible_game.count() == 1: game = possible_game[0] game_searches = self.get_game_searches(user=user, game=game) game_searches.update(cancelled=True) games_removed = [game] game_search_cancelled = True except Exception as e: log_item.message += '- Failed\n\n{}'.format( logify_exception_info()) await self.bot.delete_message(msg) await self.bot.delete_message(question_message) else: no_game_searches = True log_item.save() if game_search_cancelled: await self.bot.say( "{0.message.author.mention}: You've stopped searching for the following game(s):\n{1}" .format( ctx, await self.game_beautify(games_removed, available=False)), delete_after=30) elif time_ran_out: await self.bot.say( 'Whoops... looks like your time ran out {0.message.author.mention}. Please re-run the command and try again.' .format(ctx), delete_after=30) elif no_game_searches: await self.bot.say( 'It doesn\'t look like you\'re currently searching for any games {0.message.author.mention}.\nIf you would like to start, type {0.prefix}lfg' .format(ctx), delete_after=30) else: await self.bot.say( "I didn't quite understand your response {0.message.author.mention}, please run the command again." .format(ctx), delete_after=30) await self.bot.delete_message(ctx.message)
async def looking_for_game(self, ctx, game_search_key: str = None, page_number: str = None): """Used when users want to play a game with others Example: ?lfg overwatch""" user = self.get_user(ctx.message.author) games = [game for game in Game.objects.all()] server = self.get_server(ctx.message.server) log_item = Log.objects.create( message="Log item for {} on {} searching for {}".format( user, server, game_search_key)) if not user or user.bot: return page = 0 if page_number: if page_number.lower().startswith('p'): page = int(page_number[1::]) - 1 game_search = False created = False create_search = False if game_search_key: current_searches = self.get_game_searches(user=user) current_searches_games = [ search.game for search in current_searches ] games = [] try: possible_games = Game.objects.filter(pk=int(game_search_key)) except: possible_games = Game.objects.filter( name__icontains=game_search_key) for game in possible_games: if game not in current_searches_games: if game not in games: games.append(game) if len(games) == 1: game = games[0] else: games = self.map_games(games) msg = False temp_message = '{0.message.author.mention}: Which game did you want to search for?\n_Please only type in the number next to the game_\n_You have 30 seconds to respond_\n'.format( ctx) formatted_games = await self.game_beautify( games, reserve=len(temp_message), page=page) final_message = '{}{}'.format(temp_message, formatted_games) question_message = await self.bot.say(final_message) time_ran_out = False gameIDs = games.keys() def check(msg): try: return int(msg.content.strip()) in gameIDs except: return False msg = await self.bot.wait_for_message(author=ctx.message.author, check=check, timeout=30) if isinstance(msg, discord.Message): try: content = msg.content.strip() try: possible_game = Game.objects.filter( pk=games[int(content)].pk) except: possible_game = Game.objects.filter( name__icontains=content) if possible_game.count() == 1: game = possible_game[0] except Exception as e: log_item.message += '- Failed\n\n{}'.format( logify_exception_info()) await self.bot.delete_message(msg) else: time_ran_out = True await self.bot.delete_message(question_message) if isinstance(game, Game): """ .. todo:: Ask the user if they want to join a currently (non-full) game group or if they want to start their own search Somehow limit the number of people per group to 5 (or some other good number) """ current_searches = self.get_game_searches(game=game) current_game_channels = self.get_game_channels(game=game) game_channel = None for channel in current_game_channels: c = await self.bot.get_channel(channel.channel_id) if c is None: channel.deleted = True channel.save() continue if channel.num_users > 5: continue else: game_channel = channel break if current_searches.count() == 0: create_search = True else: msg = False temp_message = '{0.message.author.mention}: There is a group with less than 5 people for {1.name}, would you like to join them?\n_Please only type in `yes` or `no`_\n_You have 30 seconds to respond_\n'.format( ctx, game) question_message = await self.bot.say(temp_message) time_ran_out = False def yesno_check(msg): try: return msg.content.strip().lower() in ['yes', 'no'] except: return False msg = await self.bot.wait_for_message( author=ctx.message.author, check=yesno_check, timeout=30) if isinstance(msg, discord.Message): try: log_item.message += "Response from user about joining existing group: '{}'\n".format( message.content) content = msg.content.strip().lower() if content == 'yes': # Put the user with the group already found pass elif content == 'no': # They said no, so start a new search create_search = True else: raise Exception("Content is not equal to yes/no") except Exception as e: log_item.message += '- Failed\n\n{}'.format( logify_exception_info()) await self.bot.delete_message(msg) else: time_ran_out = True await self.bot.delete_message(question_message) if create_search: game_search, created = self.create_game_search(user, game) log_item.message += "game_search: {0}\ncreated: {1}\ngame_found: {2}\ntime_ran_out: {3}\ncreate_search: {4}\n".format( game_search, created, game_found, time_ran_out, create_search) log_item.save() if created and game_search: await self.bot.say( "{0.message.author.mention}: You've been added to the search queue for `{1.name}`!" .format(ctx, game), delete_after=30) elif game_found: await self.bot.say( "{0.message.author.mention}: You've been added to the current group `{1.name}`!" .format(ctx, game), delete_after=30) elif game_search: await self.bot.say( "{0.message.author.mention}: You're already in the queue for `{1.name}`. If you would like to stop looking for this game, type {0.prefix}lfgstop {1.name}" .format(ctx, gaame), delete_after=30) elif time_ran_out: await self.bot.say( 'Whoops... looks like your time ran out `{0.message.author.mention}`. Please re-run the command and try again.' .format(ctx), delete_after=30) else: await self.bot.say( "{0.message.author.mention}: I didn't quite understand your response, please run the command again." .format(ctx), delete_after=30) await self.bot.delete_message(ctx.message)