def active(token, channel_id): ''' Requirements: correct channel_id. Checks whether a standup with channel_id exists in standup_list. It will simply retrieve from data.py and return it in a neat package. #Raises 1 possible InputError ''' # check for valid token common.token_valid(token) # check for valid channel if common.ch_id_exists(channel_id) == -1: raise InputError('This channel does not exist.') is_active = False time_finish = None for channel in data.standup_list: if channel["channel_id"] == channel_id: is_active = True time_finish = int(channel["time_finish"].replace( tzinfo=datetime.timezone.utc).timestamp()) return {'is_active': is_active, 'time_finish': time_finish}
def start(token, channel_id, length): ''' Requirements: correct channel_id and token This will start a standup session for 'length' seconds. Messages sent to this session must be through 'send'. A message sent will be appended to the final message using send. At time = length, the message package will be sent over to message_data. #Raises 2 possible InputErrors ''' # preliminary checks if common.ch_id_exists(channel_id) == -1: raise InputError('Invalid Channel. Cannot start standup.') if active(token, channel_id)['is_active']: raise InputError( 'A standup is active. Only 1 standup may be running at a time.') authorized_caller = common.decode_token(token) if authorized_caller["u_id"] == { "u_id": "error_invalid_token" } or not common.user_in_channel(authorized_caller["u_id"], channel_id): raise AccessError('You do not have permission to do this.') # check if length is valid. Assuming that a standup lasts for at least 1 second. if length < 1: raise InputError( description= 'You cannot start a standup for a time less than 1 second.') # keep start and finish for better accuracy time_start = datetime.datetime.utcnow() time_finish = time_start + datetime.timedelta(seconds=length) discrete.standup_data(time_start, time_finish, channel_id, authorized_caller['u_id']) index = discrete.find_standup(channel_id) # at length = length seconds, sends all the messages from the queue as a complete package Timer(length, discrete.send_standup, [token, channel_id, index]).start() Timer(length + 1, data.standup_list.pop, [index]).start() return { 'time_finish': int(time_finish.replace(tzinfo=datetime.timezone.utc).timestamp()) }
def send(token, channel_id, message): ''' Requirements: correct token, channel_id and len(message) <= 1000 Appends a message to the standup_messages list. It will depend on an aux_ function buffering it first before appending at the end of the list. #Raises 3 Possible InputErrors, 1 Access Error ''' # ch_id is invalid -> InputError index = common.ch_id_exists(channel_id) if index == -1: raise InputError('Channel does not exist.') # message > 1000 characters if len(message) > 1000 or len(message) == 0: raise InputError( description= f'Your message is {len(message)-1000} over the limit. Your message cannot be over 1000 \ characters') # user is not authorized -> AccessError authorized_caller = common.decode_token(token) if authorized_caller == {"u_id": "error_invalid_token"} or \ not common.user_in_channel(authorized_caller["u_id"], channel_id): raise AccessError( 'You cannot send a standup message in this channel which you are not part of.' ) # active standup false -> InputError if not active(token, channel_id)['is_active']: raise InputError('Standup not active.') index = discrete.find_standup(channel_id) u_index = discrete.find_user(authorized_caller['u_id']) data.standup_list[index][ 'message'] += f"\n{data.user_data[u_index]['handle']}: {message}" print(f"message now {data.standup_list[index]['message']}", flush=True) return {}
def start(token, channel_id, word): ''' Input - valid token, channel_id and word. Word validity is handled in the frontend. Behavior: Starts a hangman session in a channel. Takes a word from the random_word mod, and parses it so that it only contains alphabetical characters. All hangman sessions are stored in a hangman data structure. Output - {} ''' # ch_id is invalid -> InputError index = common.ch_id_exists(channel_id) if index == -1: raise InputError( description='The channel you are attempting to start a hangman in does not exist.') # check if token is valid authorized_caller = common.decode_token(token) if authorized_caller == {"u_id": "error_invalid_token"} or \ not common.user_in_channel(authorized_caller["u_id"], channel_id): raise AccessError( description='You do not have permission to start hangman.') # check if a hangman session is ongoing for session in hangman_sessions: if session["channel_id"] == channel_id: raise InputError( description='A hangman session is already ongoing in this channel') final_word = word[0].split(' ') # if word not specified (is list), generate a random word if len(final_word) == 1: _site = "http://svnweb.freebsd.org/csrg/share/dict/words?view=co&content-type=text/plain" response = requests.get(_site) _words = response.content.splitlines() final_word = random.choice(_words).decode() else: final_word = final_word[1].strip() # add to hangman sessions hangman_sessions.append({ "channel_id": channel_id, "word": final_word.lower(), "decrement_word": final_word.lower(), "guesses": [], "remaining_guesses": 8, "bad_attempts": 0 }) # send message as the bot idX = discrete.find_user(authorized_caller["u_id"]) starter_name = user_data[idX]["first_name"] bot_message = f"{starter_name} has just started a hangman!" bot_message += _missing([], final_word) bot_send(bot_message, channel_id) return {}
def guess(token, channel_id, X): ''' Input - valid token, channel ID and a guess X. Behavior: Given a message with some 2nd string 'X', determines whether the guess is correct or not. Output - {} ''' # ch_id is invalid -> InputError index = common.ch_id_exists(channel_id) if index == -1: raise InputError( description='The channel you are guessing on does not exist.') # check if token is valid authorized_caller = common.decode_token(token) if authorized_caller == {"u_id": "error_invalid_token"} or \ not common.user_in_channel(authorized_caller["u_id"], channel_id): raise AccessError( description='You do not have permission to do this.') # ensure channel has a hangman session # NOTE YOU must abstract these functions ASAP. index = None for session in hangman_sessions: if session["channel_id"] == channel_id: index = hangman_sessions.index(session) if index == None: raise InputError(description='A hangman session is not running right now') X = X[0].split(' ') # if word not specified (is list), generate a random word if len(X) != 1: X = X[1] # check if X has been guessed already if X in hangman_sessions[index]['guesses']: raise InputError(description='Your guess has already been guessed.') # catch empty input error if not isinstance(X, str): raise InputError(description='Usage: /guess [letter]') # SEND THE /guess X as a message to message data. message.send(token, channel_id, '/guess ' + X) # check if the guess results in the complete answer hm_word = hangman_sessions[index]['word'] guesses = hangman_sessions[index]['guesses'] guesses.append(X) prev_word = hangman_sessions[index]['decrement_word'] hangman_sessions[index]['decrement_word'] = hangman_sessions[index]['decrement_word'].replace(X, '') word_decrement = hangman_sessions[index]['decrement_word'] if prev_word == word_decrement: hangman_sessions[index]["bad_attempts"] += 1 # render ASCII or some image art. bot_message = _render_ascii( hangman_sessions[index]["bad_attempts"], channel_id, guesses, hm_word) if hm_word.replace(X, '') == hm_word: hangman_sessions[index]['remaining_guesses'] -= 1 # if guess results in complete answer, then done and send congratulations if word_decrement == '': hangman_sessions.pop(index) bot_message += "\n\(^O^)/\nYou've correctly guessed the word!" # decrement the amount of guesses available, and if no more guesses, # remove hangman session and send taunting message else: if hangman_sessions[index]['remaining_guesses'] == 0: hangman_sessions.pop(index) bot_message += f"\n(✖╭╮✖)\nThe word is {hm_word}, you have lost\nF to pay respects" else: bot_message += "\nLetters guessed:" for word in hangman_sessions[index]['guesses']: bot_message += f" {word}" # send message as the bot bot_send(bot_message, channel_id) return {}