def assert_can_chat(self, race, user): can_moderate = race.category.can_moderate(user) can_monitor = race.can_monitor(user) if (not can_monitor and not race.allow_prerace_chat and race.is_preparing): raise SafeException( 'You do not have permission to chat prior to the race.') if (not can_monitor and not race.allow_midrace_chat and (race.is_pending or race.is_in_progress)): raise SafeException( 'You do not have permission to chat during the race.') if (not can_monitor and not race.allow_non_entrant_chat and not race.in_race(user) and (race.is_pending or race.is_in_progress)): raise SafeException( 'You do not have permission to chat during the race.') if not can_moderate and race.chat_is_closed: raise SafeException( 'This race chat is now closed. No new messages may be added.') if (not can_moderate and models.Message.objects.filter( user=user, race=race, posted_at__gte=timezone.now() - timedelta(seconds=5), ).count() > 10): raise SafeException( 'You are chatting too much. Please wait a few seconds.')
def action(self, race, user, data): comment = data.get('comment', '').strip() if comment in self.shortcuts: pattern = self.shortcuts[comment] else: pattern = comment if pattern and re.match('.*[#*?]', pattern): if len(pattern) > self.MAX_LENGTH: raise SafeException( 'Pattern too long. It should be at most %d characters.' % self.MAX_LENGTH) else: result = re.sub('#', lambda *args: random.choice(string.digits), pattern) result = re.sub( '\\*', lambda *args: random.choice(string.ascii_letters), result) result = re.sub( '\\?', lambda *args: random.choice(string.ascii_letters + string.digits), result) models.Message.objects.create( user=user, race=race, message='.random %s' % comment, ) race.add_message('Random string result: ##bot##%(result)s##' % {'result': result}) else: raise SafeException( 'Usage: .random #*? (use # for a digit, * for a letter, ? for either)' )
def action(self, race, user, data): team_str = (data.get('team') or data.get('comment', '')).lower().strip() available_teams = race.get_available_teams(user) if not team_str: raise SafeException( 'You must specify a team. Available teams are: "new" (create ' 'a new team), "%(teams)s".' % {'teams': '", "'.join(sorted(available_teams.keys()))} if available_teams else 'You must specify a team. Available teams are: "new" (create ' 'a new team).') if team_str == 'new': race.create_team(user) elif team_str in available_teams: race.join_team(user, available_teams[team_str]) else: for team in available_teams.values(): if team.name.lower() == team_str: race.join_team(user, team) return raise SafeException( 'Team not found. Available teams are: "new" (create a new ' 'team), "%(teams)s".' % {'teams': '", "'.join(sorted(available_teams.keys()))} if available_teams else 'Team not found. Available teams are: "new" (create a new team).' )
def assert_can_chat(self, race, user): can_moderate = race.category.can_moderate(user) can_monitor = race.can_monitor(user) if (not can_monitor and not race.allow_midrace_chat and race.is_in_progress): raise SafeException( 'You do not have permission to chat during the race.') if (not can_monitor and not race.allow_non_entrant_chat and not race.in_race(user) and race.is_in_progress): raise SafeException( 'You do not have permission to chat during the race.') if (not can_moderate and race.is_done and (race.recorded or (not race.recordable and (race.ended_at or race.cancelled_at) <= timezone.now() - timedelta(hours=1)))): raise SafeException( 'This race chat is now closed. No new messages may be added.') if (not can_moderate and len( models.Message.objects.filter( user=user, race=race, posted_at__gte=timezone.now() - timedelta(seconds=5), )) > 10): raise SafeException( 'You are chatting too much. Please wait a few seconds.')
def action(self, race, user, data): if not self.guid_is_new(data.get('guid', '')): return form = forms.ChatForm(data) if not form.is_valid(): raise SafeException(form.errors) message = form.save(commit=False) if message.message[0] == '.': command, msg = (message.message[1:] + ' ').split(' ', 1) command = command.lower() if command in commands: race_action = commands[command]() if isinstance(race_action, AddComment) and not msg.strip(): raise SafeException('Your comment cannot be blank.') try: return race_action.action(race, user, {'comment': msg}) except SafeException as ex: if str(ex) == 'Possible sync error. Refresh to continue.': raise SafeException( f'You cannot .{command} at this time (is your stream live yet?).' if command == 'ready' and race.streaming_required else f'You cannot .{command} at this time (try reloading if you get stuck).' ) raise self.assert_can_chat(race, user) message.user = user message.race = race message.save()
def action(self, race, user, data): form = forms.CommentForm(data) if not form.is_valid(): raise SafeException(form.errors) entrant = race.in_race(user) comment = form.cleaned_data.get('comment', '').strip() if entrant and comment: entrant.add_comment(comment) else: raise SafeException('Possible sync error. Refresh to continue.')
def action(self, race, bot, data): user = self.get_user(data) if race.in_race(user): raise SafeException('%(user)s is already an entrant.' % {'user': user}) elif not race.can_join(user): raise SafeException('%(user)s is not allowed to join this race.' % {'user': user}) race.invite(user, bot)
def assert_can_chat(self, race, bot): if (race.is_done and (race.recorded or (not race.recordable and (race.ended_at or race.cancelled_at) <= timezone.now() - timedelta(hours=1)))): raise SafeException( 'This race chat is now closed. No new messages may be added.')
def action(self, race, user, data): entrant = race.in_race(user) if entrant and entrant.finish_time: entrant.undone() elif entrant and entrant.dnf: entrant.unforfeit() else: raise SafeException('Possible sync error. Refresh to continue.')
def get_entrant(self, race, data): try: return models.Entrant.objects.get( user=self.get_user(data), race=race, ) except models.Entrant.DoesNotExist: raise SafeException('Specified user is not a race entrant.')
def action(self, race, user, data): entrant = race.in_race(user) if entrant: if race.is_preparing: entrant.leave() else: entrant.forfeit() else: raise SafeException('Possible sync error. Refresh to continue.')
def action(self, race, bot, data): form = RaceSetInfoForm(data=data) if not form.is_valid(): raise SafeException(form.errors) race.info = form.cleaned_data.get('info') race.version = F('version') + 1 race.save() race.add_message('##bot##%(bot)s## updated the race information.' % {'bot': bot})
def action(self, race, bot, data): if not self.guid_is_new(data.get('guid', '')): return form = forms.ChatForm(data) if not form.is_valid(): raise SafeException(form.errors) self.assert_can_chat(race, bot) message = form.save(commit=False) message.bot = bot message.race = race message.save()
def guid_is_new(self, guid): """ Check if we've seen the GUID posted with this message in the last 5 minutes. If so, it's almost certainly a duplicate message and we should silently ignore it. """ if not re.match(r'^[0-9a-z\-]+$', guid): raise SafeException( 'Bad request, no GUID supplied. A unique string is required ' 'to prevent duplicate messaging.') if cache.get('guid/message/' + guid): return False cache.set('guid/message/' + guid, True, 300) return True
def action(self, race, bot, data): if 'info' in data: # Backwards compatibility. data = {'info_user': data['info']} form = forms.RaceSetInfoForm(data=data) if not form.is_valid(): raise SafeException(form.errors) if 'info_bot' in form.changed_data: race.info_bot = form.cleaned_data.get('info_bot') if 'info_user' in form.changed_data: race.info_user = form.cleaned_data.get('info_user') race.version = F('version') + 1 race.save() race.add_message('##bot##%(bot)s## updated the race information.' % {'bot': bot})
def assert_can_chat(self, race, bot): if race.chat_is_closed: raise SafeException( 'This race chat is now closed. No new messages may be added.' )
def get_user(self, data): try: return models.User.objects.get_by_hashid(data.get('user')) except models.User.DoesNotExist: raise SafeException('No user found matching the given ID.')
def action(self, race, user, data): entrant = race.in_race(user) if entrant: entrant.decline_invite() else: raise SafeException('Possible sync error. Refresh to continue.')
def action(self, race, user, data): entrant = race.in_race(user) if entrant: entrant.cancel_request() else: raise SafeException('Possible sync error. Refresh to continue.')