def channels_list(token): """Provide a list of all channels (and their associated details) that the authorised user is part of Args: token (string): unique identifer of user Returns: (dict): { channels } """ data = pickle.load(open(DATA_FILE, "rb")) confirm_token(data, token) u_id = convert_token_to_u_id(data, token) user_details = data.get_user_details(u_id) # Add channels the user is a part of into joined_channels. joined_channels = [] for channel in user_details['channels']: joined_channels.append({ 'channel_id': channel['channel_id'], 'name': channel['name'] }) return {'channels': joined_channels}
def user_profile(token, u_id): """For a valid user, returns information about their user_id, email, first name, last name, and handle Args: token (string) u_id (int) Returns: (dict): { user } """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_u_id(data, u_id) # Search data.py for the valid user with matching u_id. user = data.get_user_details(u_id) return { 'user': { 'u_id': u_id, 'email': user['email'], 'name_first': user['name_first'], 'name_last': user['name_last'], 'handle_str': user['handle_str'], 'profile_img_url': user['profile_img_url'] } }
def user_profile_sethandle(token, handle_str): """Update authorised users handle Args: token (string) handle_str (string) Returns: (dict): {} """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) # Error check: handle_str must be between 3 and 20 characters if not validate_handle_str(handle_str): raise InputError( description= "InputError: Handle string must be between 3 and 20 characters (inclusive)" ) # Error check: handle is already used by another user if not validate_handle_unique(data, handle_str): raise InputError( description="InputError: Handle is already used by another user") # updating in users list. u_id = convert_token_to_u_id(data, token) data.set_user_handle(u_id, handle_str) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}
def search(token, query_str): """Given a query string, return a collection of messages in all of the channels that the user has joined that match the query Args: token (string) query_str (string) Returns: (dict): { messages } """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) # Error check (Assumption): query_str must be atleast 1 character if len(query_str) == 0: raise InputError(description="InputError: query_str must be atleast 1 character long") all_messages = [] for channel in data.get_channels(): if validate_token_as_channel_member(data, token, channel['channel_id']): messages = get_messages_list(data, token, channel['channel_id']) for msg in messages: all_messages.append(msg) # Get the u_id matched_msg = [] for message in all_messages: if message['message'].find(query_str) != INVALID_QUERY: matched_msg.insert(0, message) return { 'messages': matched_msg }
def channel_details(token, channel_id): """Given a Channel with ID channel_id that the authorised user is part of, provide basic details about the channel Args: token (string) channel_id (int) Returns: (dict): { name, owner_members, all_members } """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_channel_id(data, channel_id) # Error check: Authorised user is not a member of channel with channel_id if not validate_token_as_channel_member(data, token, channel_id): raise AccessError( description= "AccessError: Authorised user is not a member of the channel") channel_details = data.get_channel_details(channel_id) return { 'name': channel_details['name'], 'owner_members': channel_details['owner_members'], 'all_members': channel_details['all_members'], }
def users_all(token): """Returns a list of all users and their associated details Args: token (string) Returns: (dict): { users } """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) all_users = [] for u_id in data.get_user_ids(): user_details = data.get_user_details(u_id) all_users.append({ 'u_id': user_details['u_id'], 'email': user_details['email'], 'name_first': user_details['name_first'], 'name_last': user_details['name_last'], 'handle_str': user_details['handle_str'], 'profile_img_url': user_details['profile_img_url'] }) return { 'users': all_users }
def admin_userpermission_change(token, u_id, permission_id): """Given a User by their user ID, set their permissions to new permissions described by permission_id Args: token (string) u_id (int) permission_id (int) """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_u_id(data, u_id) if permission_id not in (MEMBER, OWNER): raise InputError(description="InputError: permission_id does not refer to a value permission") # Error check: The authorised user is not an owner user_id = convert_token_to_u_id(data, token) if not validate_flockr_owner(data, user_id): raise AccessError(description="AccessError: User is not a flockr owner") # Error check (Assumption): First flockr owner cannot have member permissions if u_id == data.get_first_owner_u_id() and permission_id == MEMBER: raise InputError(description="InputError: First flockr owner cannot be a member") data.set_user_permission_id(u_id, permission_id) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}
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 Args: token (string) message_id (int) Returns: (dict) """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_message_id(data, message_id) # Error check: Message with ID message_id is already pinned channel_id = data.get_channel_id_with_message_id(message_id) channel_messages = data.get_channel_details(channel_id)['messages'] for curr_message in channel_messages: if curr_message['message_id'] == message_id: if curr_message['is_pinned']: raise InputError( description="InputError: Message is already pinned") # Check if user is a flockr owner. u_id = convert_token_to_u_id(data, token) flockr_owner = validate_u_id_as_flockr_owner(data, u_id) channel_member = validate_token_as_channel_member(data, token, channel_id) channel_owner = validate_token_as_channel_owner(data, token, channel_id) # Error check: The authorised user is not a member of the channel that the message is within if not flockr_owner and not channel_member: raise AccessError( description= "AccessError: Authorised user is not a member of the channel \ that contains the message") # Error check: The authorised user is not an owner if not flockr_owner and not channel_owner: raise AccessError( description= "AccessError: The authorised user is not an owner of the channel") # Pin message (If user is a flockr owner or channel owner). for curr_channel in data.get_channels(): for curr_message in curr_channel['messages']: if curr_message['message_id'] == message_id: curr_message['is_pinned'] = True with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}
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 Args: token (string) message_id (int) react_id (int) Returns: (dict): {} """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_message_id(data, message_id) confirm_react_id(data, message_id, react_id) # Error check: Message with ID message_id already contains an active React # with ID react_id from the authorised user u_id = convert_token_to_u_id(data, token) if validate_active_react_id(data, u_id, message_id, react_id): raise InputError( description=f"InputError: Message already contains an active react" ) # Error check (Assumption): Flockr member not in channel with message_id channel_id = data.get_channel_id_with_message_id(message_id) is_member = validate_u_id_as_channel_member(data, u_id, channel_id) is_flock_owner = validate_u_id_as_flockr_owner(data, u_id) if not is_member and not is_flock_owner: raise AccessError( description= f"AccessError: User is not in the channel that has the message_id {message_id}" ) # unreact all active reacts (based on assumption) active_react_ids = data.get_active_react_ids(u_id, message_id) if active_react_ids != []: for active_react_id in active_react_ids: message_unreact(token, message_id, active_react_id) # reload to get updated data from message_unreact data = pickle.load(open(DATA_FILE, "rb")) message = data.get_message_details(channel_id, message_id) message['reacts'][react_id - 1]['u_ids'].append(u_id) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}
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 Args: token (string) channel_id (int) message (string) time_sent (int) Returns: (dict): { message_id } """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_channel_id(data, channel_id) # Error check: Message is more than 1000 characters or 0 characters if len(message) > 1000: raise InputError( description="InputError: Message has more than 1000 characters") if len(message) == 0: raise InputError(description="InputError: Message is empty") # Error check: Time sent is a time in the past curr_time = int(datetime.now(tz=timezone.utc).timestamp()) if curr_time > time_sent: raise InputError( description="InputError: Time sent is a time in the past") # Error check: the authorised user has not joined the channel they are trying to post to if not validate_token_as_channel_member(data, token, channel_id): raise AccessError( description= "AccessError: Authorised user is not a member of the channel") # Send the message at the time_sent if curr_time == time_sent: send_message = message_send(token, channel_id, message) message_id = send_message['message_id'] else: time_delay = int(time_sent - curr_time) message_id = data.generate_message_id() with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) Thread(target=delay_message_send, args=(token, channel_id, message, time_delay), daemon=True).start() return {'message_id': message_id}
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 Args: token (string) channel_id (int) length (int) Returns: (dict): { time_finish } """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_channel_id(data, channel_id) # Error check: An active standup is currently running in this channel if data.specify_standup_status(channel_id)['is_active']: raise InputError( description="Standup is already running in the channel") # Error check (Assumption): User must be in the channel to start a standup if not validate_token_as_channel_member(data, token, channel_id): raise AccessError( description="User must be in the channel to start a standup") # Error check (Assumption): Length specified is less than or equal to 0 if length <= 0: raise InputError( description="Length of standup must be greater than 0 seconds") # set standup as active and calculate time_finish completion_time = int(datetime.now(tz=timezone.utc).timestamp()) + length data.set_standup_active_in_channel(channel_id, completion_time) # when completion time is met, set standup as inactive and send messages with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) Thread(target=set_standup_inactive, args=(token, channel_id, length), daemon=True).start() return {'time_finish': completion_time}
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. Args: token (string) message_id (int) message (string) Returns: (dict): {} """ data = pickle.load(open(DATA_FILE, "rb")) # remove message if new message is an empty string if message == '': return message_remove(token, message_id) # Error checks: Basic validation confirm_token(data, token) confirm_message_id(data, message_id) # Error check: Message is more than 1000 characters or 0 characters if len(message) > 1000: raise InputError( description="InputError: Message has more than 1000 characters") # edit the message if user is flockr owner or channel owner or sent by authorized user # (Assumption) flockr owner does not need to be a part of the channel to edit message u_id = convert_token_to_u_id(data, token) channel_id = data.get_channel_id_with_message_id(message_id) valid_permission = validate_universal_permission(data, token, channel_id) userAuthorized = False for channel in data.get_channels(): for curr_message in channel['messages']: if curr_message['message_id'] == message_id: if curr_message['u_id'] == u_id or valid_permission: userAuthorized = True data.edit_message(channel_id, message_id, message) # Error check: User was not authorised to edit the message if not userAuthorized: raise AccessError("AccessError: User not authorized to edit message") with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}
def standup_send(token, channel_id, message): """Sending a message to get buffered in the standup queue, assuming a standup is currently active Args: token (string) channel_id (int) message (string) Returns: (dict): {} """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_channel_id(data, channel_id) # Error check: Message is more than 1000 characters or 0 characters if len(message) > 1000: raise InputError( description="InputError: Message has more than 1000 characters") if len(message) == 0: raise InputError(description="InputError: Message is empty") # Error check (Assumption): User must be in the channel to start a standup if not validate_token_as_channel_member(data, token, channel_id): raise AccessError( description="User must be in the channel to start a standup") # if an active standup is not currently running in this channel standup_information = data.specify_standup_status(channel_id) if not standup_information['is_active']: raise InputError( description="Standup is not currently running in this channel") # append message to 'standup_messages' string handle_name = token_to_handle_name(data, token) if data.show_standup_messages(channel_id) == "": new_message = f'{handle_name}: {message}' else: new_message = f'\n{handle_name}: {message}' data.append_standup_message(channel_id, new_message) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}
def channel_removeowner(token, channel_id, u_id): """Remove user with user id u_id an owner of this channel Args: token (string) channel_id (int) u_id (int) Returns: (dict): {} """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_channel_id(data, channel_id) confirm_u_id(data, u_id) # Error check: When user with user id u_id is not an owner of the channel if not validate_u_id_as_channel_owner(data, u_id, channel_id): raise InputError( description= f"InputError: User with u_id {u_id} is not an owner of channel") # Error check: User is not an owner of the flockr, or an owner of this channel if not validate_token_as_channel_member(data, token, channel_id): raise AccessError( description= "AccessError: Authorised user is not an owner of the flockr, or an owner of the channel" ) # Error check (Assumption): There must be at least one owner in the channel channel_data = data.get_channel_details(channel_id) if len(channel_data['owner_members']) == 1: raise InputError( description= "InputError: There must be at least one owner in the channel") data.remove_owner_from_channel(u_id, channel_id) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}
def user_profile_setname(token, name_first, name_last): """Update the authorised user's first and last name Args: token (string) name_first (string) name_last (string) Returns: (dict): {} """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) # Error check: Name validation if not validate_names(name_first): raise InputError( description= "First name must be between 1 to 50 characters long (inclusive)") if not validate_names(name_last): raise InputError( description= "Last name must be between 1 to 50 characters long (inclusive)") if not validate_names_characters(name_first): raise InputError( description= "First name can only include uppercase and lowercase alphabetical characters, hyphens or whitespaces" ) if not validate_names_characters(name_last): raise InputError( description= "Last name can only include uppercase and lowercase alphabetical characters, hyphens or whitespaces" ) # changing name in the users field u_id = convert_token_to_u_id(data, token) data.set_user_name(u_id, name_first, name_last) data.set_user_name_in_channels(u_id, name_first, name_last) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}
def channel_invite(token, channel_id, u_id): """Invites a user (with user id u_id) to join a channel with ID channel_id. Once invited the user is added to the channel immediately Args: token (string) channel_id (int) u_id (int): Returns: (dict): {} """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_channel_id(data, channel_id) confirm_u_id(data, u_id) # Error check: the authorised user is not already a member of the channel # (i.e. not in channel when calling this function) if not validate_token_as_channel_member(data, token, channel_id): raise AccessError( description= "AccessError: User not authorized to invite, please join channel") # Error check (Assumption): User with u_id is already in the channel but is # invited again if validate_u_id_as_channel_member(data, u_id, channel_id): raise InputError( description="InputError: User is already part of the channel") user = data.get_user_details(u_id) data.add_member_to_channel(u_id, channel_id) data.add_channel_to_user_list(u_id, channel_id) # if user is flockr owner: make him the group owner too if user['permission_id'] == OWNER: data.add_owner_to_channel(u_id, channel_id) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}
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 Args: token (string) message_id (int) react_id (int) Returns: (dict): {} """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_message_id(data, message_id) confirm_react_id(data, message_id, react_id) # Error check: Message with ID message_id does not contain an active React with ID react_id u_id = convert_token_to_u_id(data, token) if not validate_active_react_id(data, u_id, message_id, react_id): raise InputError( description= f"InputError: Message already contains a non-active react") # Error check (Assumption): Flockr member not in channel with message_id channel_id = data.get_channel_id_with_message_id(message_id) is_member = validate_u_id_as_channel_member(data, u_id, channel_id) is_flock_owner = validate_u_id_as_flockr_owner(data, u_id) if not is_member and not is_flock_owner: raise AccessError( description= f"AccessError: User is not in the channel that has the message_id {message_id}" ) # Otherwise unreact the message with react_id. message = data.get_message_details(channel_id, message_id) message['reacts'][react_id - 1]['u_ids'].remove(u_id) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}
def channel_join(token, channel_id): """Given a channel_id of a channel that the authorised user can join, adds them to that channel Args: token (string) channel_id (int) Returns: (dict): {} """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_channel_id(data, channel_id) # Error check (Assumption): Check whether user is a channel member already if validate_token_as_channel_member(data, token, channel_id): return {} # Error check: User cannot join a channel if they are a flockr member and # the channel is private u_id = convert_token_to_u_id(data, token) user = data.get_user_details(u_id) channel_details = data.get_channel_details(channel_id) if user['permission_id'] == MEMBER and not channel_details['is_public']: raise AccessError( description= "AccessError: Private channel cannot be joined unless user is a flockr owner" ) data.add_member_to_channel(user['u_id'], channel_id) data.add_channel_to_user_list(user['u_id'], channel_id) # If the user is the flockr owner, make their permissions as a channel owner. if user['permission_id'] == OWNER: data.add_owner_to_channel(user['u_id'], channel_id) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}
def channel_leave(token, channel_id): """Given a channel ID, the user removed as a member of this channel Args: token (string) channel_id (int) Returns: (dict): {} """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_channel_id(data, channel_id) # Error check: Authorised user is not a member of channel with channel_id if not validate_token_as_channel_member(data, token, channel_id): raise AccessError( description= "AccessError: Authorised user is not a member of the channel") u_id = convert_token_to_u_id(data, token) data.remove_member_from_channel(u_id, channel_id) data.remove_owner_from_channel(u_id, channel_id) data.delete_channel_from_user_list(u_id, channel_id) channel_details = data.get_channel_details(channel_id) # Case where all owners have left, assign the oldest member as the new # channel owner. if len(channel_details['owner_members']) == 0 and len( channel_details['all_members']) != 0: data.add_owner_to_channel(channel_details['all_members'][0]['u_id'], channel_id) # Case where all members have left, delete channel from database if len(channel_details['all_members']) == 0: data.delete_channel(channel_id) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}
def channel_addowner(token, channel_id, u_id): """Make user with user id u_id an owner of this channel Args: token (string) channel_id (int) u_id (int) Returns: (dict): {} """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_channel_id(data, channel_id) confirm_u_id(data, u_id) # Error check: User id u_id is already an owner of the channel if validate_u_id_as_channel_owner(data, u_id, channel_id): raise InputError( description= f"InputError: User with u_id {u_id} is not an owner of channel") # Error check: User is not an owner of the flockr, or an owner of this channel if not validate_token_as_channel_member(data, token, channel_id): raise AccessError( description= "AccessError: Authorised user is not an owner of the flockr, or an owner of the channel" ) # Add user as member if not already. if not validate_u_id_as_channel_member(data, u_id, channel_id): data.add_member_to_channel(u_id, channel_id) data.add_channel_to_user_list(u_id, channel_id) data.add_owner_to_channel(u_id, channel_id) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}
def channels_create(token, name, is_public): """Creates a new channel with that name that is either a public or private channel Args: token (string) name (string) is_public (bool) Returns: (dict): { channel_id } """ data = pickle.load(open(DATA_FILE, "rb")) confirm_token(data, token) # Error check: Channel name validation if len(name) > 20 or len(name) < 1: raise InputError( description="Channel name must be between 1 to 20 characters") # Generate channel_id. channel_id = 1 if len(data.get_channels()) != 0: channel_list = data.get_channels() channel_id = channel_list[-1]['channel_id'] + 1 # Create new channel and store it into data structure. data.create_channel(name, is_public, channel_id) u_id = convert_token_to_u_id(data, token) data.add_channel_to_user_list(u_id, channel_id) # Add user to created channel as well as making them owner. data.add_member_to_channel(u_id, channel_id) data.add_owner_to_channel(u_id, channel_id) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {'channel_id': channel_id}
def message_send(token, channel_id, message): """Send a message from authorised_user to the channel specified by channel_id Args: token (string) channel_id (int) message (string) Returns: (dict): { message_id } """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_channel_id(data, channel_id) # Error check: Message is more than 1000 characters or 0 characters if len(message) > 1000: raise InputError( description="InputError: Message has more than 1000 characters") if len(message) == 0: raise InputError(description="InputError: Message is empty") # Error check: the authorised user has not joined the channel they are trying to post to if not validate_token_as_channel_member(data, token, channel_id): raise AccessError( description= "AccessError: Authorised user is not a member of the channel") # Add message to the channel message_id = data.generate_message_id() u_id = convert_token_to_u_id(data, token) data.create_message(u_id, channel_id, message_id, message) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {'message_id': message_id}
def message_remove(token, message_id): """Given a message_id for a message, this message is removed from the channel Args: token (string) message_id (int) Returns: (dict): {} """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_message_id(data, message_id) # remove the message if user is flockr owner or channel owner or sent by authorized user # (Assumption) flockr owner does not need to be a part of the channel to remove message channel_id = data.get_channel_id_with_message_id(message_id) u_id = convert_token_to_u_id(data, token) valid_permission = validate_universal_permission(data, token, channel_id) userAuthorized = False for channel in data.get_channels(): for message in channel['messages']: if message['message_id'] == message_id: if message['u_id'] == u_id or valid_permission: userAuthorized = True data.remove_message(channel_id, message_id) # Error check: User was not authorised to remove the message if not userAuthorized: raise AccessError( description="AccessError: User not authorized to remove message") with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}
def channels_listall(token): """Provide a list of all channels (and their associated details) Args: token (string): unique identifer of user Returns: (dict): { channels } """ data = pickle.load(open(DATA_FILE, "rb")) confirm_token(data, token) # Add all available channels into all_channels (both public and private). all_channels = [] for curr_channel in data.get_channels(): all_channels.append({ 'channel_id': curr_channel['channel_id'], 'name': curr_channel['name'] }) return {'channels': all_channels}
def user_profile_setemail(token, email): """Update the authorised user's email. Args: token (string): unique identifier of user. email (string): what the email will be set to. Returns: (dict): Contains no key types. """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) # Make the input email lowercase. email = email.lower() # Error check: Email validation if not validate_create_email(email): raise InputError(description="InputError: Invalid email address") # Check for whether email is already in use. for curr_user in data.get_users(): if curr_user['email'] == email: raise InputError( description= f"InputError: Email address is already being used by another user" ) u_id = convert_token_to_u_id(data, token) data.set_user_email(u_id, email) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) 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 Args: token (string) channel_id (int) Returns: (dict): { is_active, time_finish } """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_channel_id(data, channel_id) # Error check (Assumption): User must be in the channel to start a standup if not validate_token_as_channel_member(data, token, channel_id): raise AccessError( description="User must be in the channel to start a standup") return data.specify_standup_status(channel_id)
def channel_messages(token, channel_id, start): """Given a Channel with ID channel_id that the authorised user is part of, return up to 50 messages between index "start" and "start + 50". Message with index 0 is the most recent message in the channel. This function returns a new index "end" which is the value of "start + 50", or, if this function has returned the least recent messages in the channel, returns -1 in "end" to indicate there are no more messages to load after this return. Args: token (string) channel_id (int) start (int) Returns: (dict): { messages, start, end } """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) confirm_channel_id(data, channel_id) # Error check: start is greater than the total number of messages in the channel channel_details = data.get_channel_details(channel_id) if start >= len(channel_details['messages']) and start != 0: raise InputError( description=f"InputError: start value ({start}) is greater than the \ total number of messages in the channel ({len(channel_details['messages'])} messages)" ) if start < 0: raise InputError( description= f"InputError: start value ({start}) must be greater than or equal to 0" ) # Error check: Authorised user is not a member of channel with channel_id if not validate_token_as_channel_member(data, token, channel_id): raise AccessError( description= "AccessError: Authorised user is not a member of the channel") # (Assumption) Case where there are no messages in the channel if len(channel_details['messages']) == 0: return { 'messages': [], 'start': -1, 'end': -1, } # Case where there are messages in the channel end = start + 50 if end >= len(channel_details['messages']): end = -1 # Create the messages list. messages_list = get_messages_list(data, token, channel_id) if end == -1: messages = messages_list[start:] else: messages = messages_list[start:end] return {'messages': messages, 'start': start, 'end': end}
def user_profile_uploadphoto(token, img_url, x_start, y_start, x_end, y_end): """Given a URL of an image on the internet, crops the image within bounds (x_start, y_start) and (x_end, y_end). Position (0,0) is the top left. Args: token (string) img_url (string) x_start (int) y_start (int) x_end (int) y_end (int) Returns: (dict): {} """ data = pickle.load(open(DATA_FILE, "rb")) # Error checks: Basic validation confirm_token(data, token) # Error check: img_url returns an HTTP status other than 200. try: response = requests.get(img_url) except: raise InputError( description="InputError: Image URL cannot be requested") if response.status_code != 200: raise InputError( description= "InputError: Image URL returns an HTTP status other than 200") # Generate file url path img_file_local_path = generate_img_file_path() # Error check: check if the image can be download. If can, download it. try: urllib.request.urlretrieve(img_url, 'src/' + img_file_local_path) except: raise InputError( description="InputError: Image URL cannot be retrieved") # Error check: Image uploaded is not a JPG if imghdr.what('src/' + img_file_local_path) != "jpeg": os.remove('src/' + img_file_local_path) raise InputError(description="InputError: Image uploaded is not a JPG") # Error check: Check if the x and y dimensions are within bounds img_object = Image.open('src/' + img_file_local_path) width, height = img_object.size if x_start not in range(0, width): os.remove('src/' + img_file_local_path) raise InputError(description="x_start not in boundary of the image") if x_end not in range(0, width + 1): os.remove('src/' + img_file_local_path) raise InputError(description="x_end not in boundary of the image") if y_start not in range(0, height): os.remove('src/' + img_file_local_path) raise InputError(description="y_start not in boundary of the image") if y_end not in range(0, height + 1): os.remove('src/' + img_file_local_path) raise InputError(description="y_end not in boundary of the image") if x_end <= x_start: os.remove('src/' + img_file_local_path) raise InputError(description="x_end must be greater than x_start") if y_end <= y_start: os.remove('src/' + img_file_local_path) raise InputError(description="y_end must be greater than y_start") # Crop the images img_object.crop( (x_start, y_start, x_end, y_end)).save('src/' + img_file_local_path) # Assign image to the user and save it on the server u_id = convert_token_to_u_id(data, token) try: server_img_url = f"{request.url_root}{img_file_local_path}" except: os.remove('src/' + img_file_local_path) raise AccessError(description="Server must be running to upload photo") data.set_user_photo(u_id, server_img_url) data.set_user_photo_in_channels(u_id, server_img_url) with open(DATA_FILE, 'wb') as FILE: pickle.dump(data, FILE) return {}