def channel_leave(token, channel_id): ''' User leaves a channel. Parameters: token - channel_id - Returns: {} Errors: InputError: Invalid channel id. AccessError: User is not inside channel. ''' check_token(token) data = get_data() if not find_id_in_list(data['channels'], channel_id, 'channel_id'): raise InputError(description='Channel does not exist') current_channel = data['channels'][channel_id - 1] target_u_id = get_user_from_token(token) if find_id_in_list(current_channel['all_members'], target_u_id, 'u_id'): target = get_user_data(target_u_id) user_info = { 'u_id': target['u_id'], 'name_first': target['name_first'], 'name_last': target['name_last'], } data['channels'][channel_id - 1]['all_members'].remove(user_info) return {} # the authorised user is not a member of channel with channel_id raise AccessError( description='The authorised user is not a member of this channel')
def message_sendlater(token, channel_id, message, time_sent): ''' Send a message from authorised_user to the channel \ specified by channel_id automatically at a specified time in the future Parameters: token - The user's token that was generated from their user id channel_id - The id of the channel the user wishes to message message - The message the user wishes to send time_sent Returns: A dictionary containing a bool is_sucess Errors: InputError: Channel ID is not a valid channel Message is more than 1000 characters Time sent is a time in the past AccessError: The authorised user has not joined the channel they are trying to post to ''' check_token(token) data = get_data() #check channel exist if not find_id_in_list(data['channels'], channel_id, 'channel_id'): raise InputError(description="Channel does not exist") if len(message) > 1000: raise InputError(description="Message is too long") curr_time = datetime.utcnow() time_stamp = int(time.mktime(curr_time.timetuple())) if time_sent < time_stamp: raise InputError(description="Cannot send messages in the past") curr_channel = data['channels'][int(channel_id) - 1] u_id = get_user_from_token(token) if not find_id_in_list(curr_channel['all_members'], u_id, 'u_id'): raise AccessError("Cannot send messages in channels you're not in") message_id = get_max_msg_id() + 1 new_message = { 'u_id': u_id, 'channel_id': channel_id, 'message_id': message_id, 'message': message, 'time_created': time_sent, 'send_later': True, 'react': [], 'is_pinned': False } curr_time = datetime.utcnow() time_stamp = int(time.mktime(curr_time.timetuple())) timer = threading.Timer(time_sent - time_stamp, data['messages'].insert(0, new_message)) timer.start() return {"message_id": new_message['message_id']}
def message_react(token, message_id, react_id): ''' Given a message within a channel the authorised user is part of, add a "react" to \ that particular message Parameters: token - The user's token that was generated from their user id message_id - The id of the message to be reacted to react_id - What type of reaction is shown Returns: An empty dictionary Errors: InputError: Message_id is not a valid message within a channel that the authorised user has joined React_id is not a valid React ID. The only valid react ID the frontend has is 1 Message with ID message_id already contains an active React with ID react_id \ from the authorised user ''' check_token(token) data = get_data() # The only valid react ID the frontend has is 1 if react_id != 1: raise InputError(description="Invalid React ID") if not find_id_in_list(data['messages'], message_id, 'message_id'): raise InputError( description="Message_id is not a valid message within a \ channel that the authorised user has joined") for message in data['messages']: if message['message_id'] == message_id: msg = message u_id = get_user_from_token(token) channel_id = msg['channel_id'] curr_channel = data['channels'][channel_id - 1] if not find_id_in_list(curr_channel['all_members'], u_id, 'u_id'): raise InputError( description="Message_id is not a valid message within a \ channel that the authorised user has joined") # check if user has already reacted for react in msg['react']: if react['u_id'] == u_id: raise InputError( description="User has already reacted to this message") new_react = {'react_id': react_id, 'u_id': u_id} for message in data['messages']: if message['message_id'] == message_id: message['react'].append(new_react) return {}
def standup_active(token, channel_id): ''' For a given channel, return whether a standup is active in it, and what time the standup finishes. If no standup is active, then time_finish returns None Parameters: token - The user's token that was generated from their user id channel_id - The id of the channel Returns: A dictionary containing the time the standup will finish and whether a standup is active Errors: InputError: Channel ID is not a valid channel ''' check_token(token) data = get_data() # Check if channel_id is valid if not find_id_in_list(data['channels'], channel_id, 'channel_id'): raise InputError(description="Channel ID is not a valid channel") curr_time = datetime.utcnow() time_stamp = int(curr_time.replace(tzinfo=timezone.utc).timestamp()) standup = data['standup'] if time_stamp > standup['time_finish'] or standup['channel_id'] != channel_id: is_active = False time_finish = None else: is_active = True time_finish = standup['time_finish'] return { 'is_active': is_active, 'time_finish': time_finish }
def channel_join(token, channel_id): ''' User joins a channel. Parameters: token - channel_id - Returns: {} Errors: InputError: Invalid channel id. AccessError: Channel is private. ''' check_token(token) data = get_data() if not find_id_in_list(data['channels'], channel_id, 'channel_id'): # Channel ID is not a valid channel raise InputError(description='Channel does not exist') current_channel = data['channels'][channel_id - 1] target_u_id = get_user_from_token(token) target = get_user_data(target_u_id) if not current_channel['is_public'] and target['permission_id'] != 1: raise AccessError(description='Private channel') user_info = { 'u_id': target['u_id'], 'name_first': target['name_first'], 'name_last': target['name_last'], } data['channels'][channel_id - 1]['all_members'].append(user_info) return {}
def channels_listall(token): ''' Provide a list of all channels (and their associated details) Parameters: token - The user's token that was generated from their user id Returns: A dictionary containing a list of channels that are public or the user is in Errors: ''' check_token(token) data = get_data() c_list = [] u_id = get_user_from_token(token) # Iterating through the list of channels for channel in data['channels']: # If the user is in the channel append the channel to the list if find_id_in_list(channel['all_members'], u_id, 'u_id') or channel['is_public']: current_channel = { 'channel_id': channel['channel_id'], 'name': channel['name'], } c_list.append(current_channel) return {'channels': c_list}
def standup_send(token, channel_id, message): ''' Sending a message to get buffered in the standup queue, assuming a standup is currently active Parameters: token - The user's token that was generated from their user id channel_id - The id of the channel message - The message being sent Returns: A dictionary containing the time the standup will finish and whether a standup is active Errors: InputError: Channel ID is not a valid channel Message is more than 1000 characters An active standup is not currently running in this channel AccessError: The authorised user is not a member of the channel that the message is within ''' check_token(token) data = get_data() # Check if channel_id is valid if not find_id_in_list(data['channels'], channel_id, 'channel_id'): raise InputError(description="Channel ID is not a valid channel") # Check if the message is too long if len(message) > 1000: raise InputError(description="Message is more than 1000 characters") # Check if a standup is already active if not standup_active(token, channel_id)['is_active']: raise InputError(description="An active standup is not currently running in this channel") # Check if the user is in the channel u_id = get_user_from_token(token) curr_channel = data['channels'][channel_id - 1] if not find_id_in_list(curr_channel['all_members'], u_id, 'u_id'): raise AccessError(description="The authorised user is not a member of the \ channel that the message is within") # Appending the packaged message for user in data['users']: if user['u_id'] == u_id: handle_str = user['handle_str'] data['standup']['buffer'].append(handle_str + ': ' + message) data['standup']['message'] = '\n'.join(data['standup']['buffer']) return { }
def channel_addowner(token, channel_id, u_id): ''' Add a member of channel to owner list. Parameters: token - channel_id - u_id - Returns: {} Errors: InputError: Invalid channel id. User is already an owner. AccessError: The authorised person is not an owner of channel or owner of slackr. ''' check_token(token) data = get_data() if not find_id_in_list(data['channels'], channel_id, 'channel_id'): raise InputError(description='Channel does not exist') current_channel = data['channels'][channel_id - 1] if find_id_in_list(current_channel['owner_members'], u_id, 'u_id'): raise InputError( description='User is already an owner of this channel') person_u_id = get_user_from_token(token) person = get_user_data(person_u_id) person_is_owner = find_id_in_list(current_channel['owner_members'], person_u_id, 'u_id') person_in_channel = find_id_in_list(current_channel['all_members'], person_u_id, 'u_id') if person_is_owner or (person_in_channel and person['permission_id'] == 1): target = get_user_data(u_id) user_info = { 'u_id': target['u_id'], 'name_first': target['name_first'], 'name_last': target['name_last'], } data['channels'][channel_id - 1]['owner_members'].append(user_info) if not find_id_in_list(current_channel['all_members'], u_id, 'u_id'): data['channels'][channel_id - 1]['all_members'].append(user_info) return {} raise AccessError(description='The authorised person has no permission')
def message_pin(token, message_id): ''' Given a message within a channel, mark it as "pinned" to be given special display treatment\ by the frontend Parameters: token - The user's token that was generated from their user id message_id - The message id which the user wishes to pin Returns: An empty dictionary Errors: InputError: Message_id is not a valid message Message with ID message_id is already pinned AccessError: The authorised user is not a member of the channel that the message is within The authorised user is not an owner ''' check_token(token) data = get_data() if not find_id_in_list(data['messages'], message_id, 'message_id'): raise InputError(description="Message does not exist") # msg exists for message in data['messages']: if message['message_id'] == message_id: msg = message if msg['is_pinned']: raise InputError(description="This message is already pinned") u_id = get_user_from_token(token) user = data['users'][u_id - 1] for channel in data['channels']: if not find_id_in_list(channel['all_members'], u_id, 'u_id'): raise AccessError( description='The authorised user is not in this channel') else: curr_channel = channel if find_id_in_list(curr_channel['owner_members'], u_id, 'u_id') or user['permission_id'] == 1: msg['is_pinned'] = True return {} raise InputError( description="The authorised user does not have owner priveledge \ to pin message in this channel")
def message_unreact(token, message_id, react_id): ''' Given a message within a channel the authorised user is part of, remove a "react" to \ that particular message Parameters: token - The user's token that was generated from their user id Returns: An empty dictionary Errors: InputError: Message_id is not a valid message within a channel that the authorised user has joined React_id is not a valid React ID Message with ID message_id does not contain an active React with ID react_id ''' check_token(token) data = get_data() if react_id != 1: raise InputError(description="Invalid React ID") if not find_id_in_list(data['messages'], message_id, 'message_id'): raise InputError( description="Message_id is not a valid message within a \ channel that the authorised user has joined") for message in data['messages']: if message['message_id'] == message_id: msg = message u_id = get_user_from_token(token) channel_id = msg['channel_id'] curr_channel = data['channels'][channel_id - 1] if not find_id_in_list(curr_channel['all_members'], u_id, 'u_id'): raise InputError( description="Message_id is not a valid message within a \ channel that the authorised user has joined") # check if user has already reacted for react in msg['react']: if react['u_id'] == u_id: for message in data['messages']: if message['message_id'] == message_id: message['react'].remove(react) return {} raise InputError(description="User has not reacted to this message")
def message_unpin(token, message_id): ''' Given a message within a channel, remove it's mark as unpinned Parameters: token - The user's token that was generated from their user id message_id - The id of the message to be unpinnned Returns: An empty dictionary Errors: InputError: Message_id is not a valid message Message with ID message_id is already unpinned AccessError: The authorised user is not a member of the channel that the message is within The authorised user is not an owner ''' check_token(token) data = get_data() if not find_id_in_list(data['messages'], message_id, 'message_id'): raise InputError(description="Message does not exist") for message in data['messages']: if message['message_id'] == message_id: msg = message if not msg['is_pinned']: raise InputError(description="This message is not pinned") u_id = get_user_from_token(token) user = data['users'][u_id - 1] for channel in data['channels']: if not find_id_in_list(channel['all_members'], u_id, 'u_id'): raise AccessError( description='The authorised user is not in this channel') else: curr_channel = channel if find_id_in_list(curr_channel['owner_members'], u_id, 'u_id') or user['permission_id'] == 1: msg['is_pinned'] = False return {} raise InputError( description="The authorised user does not have owner priveledge \ to unpin message in this channel")
def message_edit(token, message_id, message): ''' Given a message, update it's text with new text. If the new message is an empty string, \ the message is deleted. Parameters: token - The user's token that was generated from their user id message_id - The id of the message to be edited message - The edits to be made Returns: An empty dictionary Errors: AccessError when none of the following are true: Message with message_id was sent by the authorised user making this request The authorised user is an owner of this channel or the slackr ''' check_token(token) data = get_data() if not find_id_in_list(data['messages'], message_id, 'message_id'): raise InputError(description="Message does not exist") for item in data['messages']: if item['message_id'] == message_id: msg = item u_id = get_user_from_token(token) user = data['users'][u_id - 1] channel_id = msg['channel_id'] curr_channel = data['channels'][channel_id - 1] is_owner = find_id_in_list(curr_channel['owner_members'], u_id, 'u_id') if msg['u_id'] == u_id or user['permission_id'] == 1 or is_owner: if message is None: message_remove(token, message_id) return {} for item in data['messages']: if item['message_id'] == message_id: item['message'] = message return {} raise AccessError( description= 'The authorised user does not have privilege to edit message')
def message_remove(token, message_id): ''' Given a message_id for a message, this message is removed from the channel Parameters: token - The user's token that was generated from their user id message_id - Id of the message the user wishes to remove Returns: An empty dictionary Errors: InputError: Message (based on ID) no longer exists AccessError when none of the following are true: Message with message_id was sent by the authorised user making this request The authorised user is an owner of this channel or the slackr ''' check_token(token) data = get_data() # Check if message exists if not find_id_in_list(data['messages'], message_id, 'message_id'): raise InputError(description="Message no longer exists") u_id = get_user_from_token(token) for message in data['messages']: if message['message_id'] == message_id: channel_id = message['channel_id'] curr_channel = data['channels'][channel_id - 1] user = data['users'][u_id - 1] is_owner = find_id_in_list(curr_channel['owner_members'], u_id, 'u_id') if message['u_id'] == u_id or is_owner or user[ 'permission_id'] == 1: data['messages'].remove(message) return {} raise AccessError( description="You did not send this message or are not an owner")
def message_send(token, channel_id, message): ''' Send a message from authorised_user to the channel specified by channel_id Parameters: token - The user's token that was generated from their user id channel_id - The id the user wishes to message message - The message the user wishes to send Returns: A dictionary containing a message_id Errors: InputError: Message is more than 1000 characters AccessError: The authorised user has not joined the channel they are trying to post to ''' # Check if user is valid check_token(token) # Check if message is too long if len(message) > 1000: raise InputError(description="Message is too long") data = get_data() u_id = get_user_from_token(token) # Find the channel with channel_id curr_channel = data['channels'][channel_id - 1] # Check if user is in this channel if not find_id_in_list(curr_channel['all_members'], u_id, 'u_id') and u_id != 0: raise AccessError(description="User is not in channel") # Get the time when message is sent curr_time = datetime.utcnow() timestamp = curr_time.replace(tzinfo=timezone.utc).timestamp() # Get message id based on the lastest (max) message id message_id = get_max_msg_id() + 1 new_message = { 'u_id': u_id, 'channel_id': channel_id, 'message_id': message_id, 'message': message, 'time_created': timestamp, 'send_later': False, 'react': [], 'is_pinned': False } # insert new message to the start of list data['messages'].insert(0, new_message) return {'message_id': message_id}
def channel_invite(token, channel_id, u_id): ''' Invite someone to this channel. Parameters: token - channel_id - u_id - Returns: {} Errors: InputError: Invalid channel id, Invalid u_id. AccessError: The authorised person is not inside this channel. ''' check_token(token) data = get_data() if not find_id_in_list(data['channels'], channel_id, 'channel_id'): raise InputError(description='Channel does not exist') if u_id > get_max_u_id() or u_id <= 0: raise InputError(description='u_id does not refer to a valid user') current_channel = data['channels'][channel_id - 1] person_u_id = get_user_from_token(token) # Check if authorised person is in channel with channel_id for user in current_channel['all_members']: if user['u_id'] == person_u_id: target = get_user_data(u_id) user_info = { 'u_id': target['u_id'], 'name_first': target['name_first'], 'name_last': target['name_last'], } data['channels'][channel_id - 1]['all_members'].append(user_info) return {} # the authorised user is not already a member of the channel raise AccessError( description='The authorised user is not a member of this channel')
def standup_start(token, channel_id, length): ''' For a given channel, start the standup period whereby for the next "length" seconds if someone calls "standup_send" with a message, it is buffered during the X second window then at the end of the X second window a message will be added to the message queue in the channel from the user who started the standup. X is an integer that denotes the number of seconds that the standup occurs for Parameters: token - The user's token that was generated from their user id channel_id - The id of the channel length - The length of time in seconds that the standup will last for Returns: A dictionary containing the time the standup will finish Errors: InputError: Channel ID is not a valid channel An active standup is currently running in this channel ''' check_token(token) data = get_data() # Check if channel_id is valid if not find_id_in_list(data['channels'], channel_id, 'channel_id'): raise InputError(description="Channel ID is not a valid channel") # Check if a standup is already active if standup_active(token, channel_id)['is_active']: raise InputError(description="An active standup is currently running in this channel") standup = data['standup'] standup['u_id'] = get_user_from_token(token) standup['channel_id'] = channel_id curr_time = datetime.utcnow() time_stamp = int(curr_time.replace(tzinfo=timezone.utc).timestamp()) standup['time_finish'] = time_stamp + length timer = threading.Timer(length, send_standup_package) timer.start() return { 'time_finish': standup['time_finish'] }
def channel_details(token, channel_id): ''' Show details to a user. Parameters: token - channel_id - Returns: a dict including channel name, owner member list, and member list. Errors: InputError: Invalid channel id. AccessError: The authorised person is not inside this channel. ''' check_token(token) data = get_data() if not find_id_in_list(data['channels'], channel_id, 'channel_id'): raise InputError(description='Channel does not exist') current_channel = data['channels'][channel_id - 1] person_u_id = get_user_from_token(token) for user in current_channel['all_members']: if user['u_id'] == person_u_id: for member in current_channel['all_members']: info = get_user_data(user['u_id']) member['profile_img_url'] = info['profile_img_url'] # Output { name, owner_members, all_members } details = { 'name': current_channel['name'], 'owner_members': current_channel['owner_members'], 'all_members': current_channel['all_members'], } return details raise AccessError( description='he authorised user is not a member of this channel')
def channel_messages(token, channel_id, start): ''' Show message list inside channel to user. Parameters: token - channel_id - start - Returns: { 'messages': msg_list, 'start': start, 'end': end } Errors: InputError: Invalid channel id. Start is greater than the total number of messages inside channel. AccessError: User is not inside channel. ''' check_token(token) data = get_data() if not find_id_in_list(data['channels'], channel_id, 'channel_id'): # Channel ID is not a valid channel raise InputError(description='Channel does not exist') msg_list = [] curr_time = datetime.utcnow() timestamp = curr_time.replace(tzinfo=timezone.utc).timestamp() for message in data['messages']: if message['channel_id'] == channel_id and message[ 'time_created'] < timestamp: tmp_message = { 'message_id': message['message_id'], 'u_id': message['u_id'], 'message': message['message'], 'time_created': message['time_created'] } msg_list.append(tmp_message) msg_list.sort(key=itemgetter('time_created'), reverse=True) num_of_messages = len(msg_list) start = int(start) if start > num_of_messages or start < 0: # start is greater than the total number of messages in the channel raise InputError(description='Start exceed limit') person_u_id = get_user_from_token(token) current_channel = data['channels'][channel_id - 1] if find_id_in_list(current_channel['all_members'], person_u_id, 'u_id'): if start + 49 > num_of_messages: end = -1 msg_list = msg_list[start:] # Output { messages, start, end} else: end = start + 49 msg_list = msg_list[start:end] return {'messages': msg_list, 'start': start, 'end': end} # the authorised user is not a member of channel with channel_id raise AccessError( description='The authorised user is not a member of this channel')