def react_message(token, message_id, react_id): """ React message with message_id with react_id """ data = get_data() user = get_user_from_token(data, token) message = get_msg_from_msg_id(data, message_id) if message is None or not user_in_channel_with_msg(data, user['u_id'], message): raise ValueError('Message is not in the channel') if not valid_react_id(react_id): raise ValueError('Invalid react id') if message_contains_react(message, user['u_id']): raise ValueError('Message already has that react') react = get_react_from_react_id(message, react_id) # if there are no current reacts, create a new data structure # and store the information. Otherwise, add only the user id if react is None: react_info = generate_react_info(react_id, user['u_id']) message['reacts'].append(react_info) else: react['u_ids'].append(user['u_id']) pickle_data(data) return {}
def upload_photo(token, img_url, x_start, y_start, x_end, y_end): ''' Upload a photo for the user's profile ''' data = get_data() user = get_user_from_token(data, token) tmp_file_name = f"./frontend/prebundle/images/tmp.jpg" save_file_name = f"./frontend/prebundle/images/{user['u_id']}.jpg" # save the url under the temp file name if the url is valid try: urllib.request.urlretrieve(img_url, tmp_file_name) except: raise ValueError(description='Invalid Image Url') image = Image.open(tmp_file_name) width, height = image.size # check the boundaries of the image if not valid_image_coords(x_start, y_start, x_end, y_end, width, height): raise ValueError(description='Cropping values are out of bounds') # check for invalid image type if imghdr.what(tmp_file_name) != 'jpeg': raise ValueError(description='Image is not a JPEG') # crop the image and save under the save file name cropped = image.crop((x_start, y_start, x_end, y_end)) cropped.save(save_file_name) user['profile_img_url'] = f"/images/{user['u_id']}.jpg" pickle_data(data) return {}
def get_messages(token, channel_id, start): ''' given a token, channel_id and the start, show all th emessages in channel with channel_id after the start as long as the user with token is part of the channel ''' data = get_data() user = get_user_from_token(data, token) channel = get_channel(data, channel_id) if channel is None: raise ValueError('Channel does not exist') num_messages = len(channel['message_ids']) if start > num_messages: raise ValueError('Start is greater than the total number of messages') if not user_in_channel(user['u_id'], channel): raise AccessError('User is not in channel') end = start + 50 if end > num_messages: end = -1 messages = return_messages(data, channel['message_ids'][start:], token) else: messages = return_messages(data, channel['message_ids'][start:end], token) return {'messages': messages, 'start': start, 'end': end}
def send_message(token, channel_id, message_str): """ Send a message to the channel associated with channel_id """ data = get_data() channel = get_channel(data, channel_id) user = get_user_from_token(data, token) message_id = get_next_message_id(data) if not valid_message_len(message_str): raise ValueError("Message too long") if not user_in_channel(user['u_id'], channel): raise AccessError("User is not in channel") # get the current time in utc now = datetime.utcnow().replace(tzinfo=timezone.utc).timestamp() # set up the information to save in the 'database' message_info = generate_message_info(channel_id, message_id, user['u_id'], message_str, now) # insert the message into the front of the message ids # stored in the channel channel['message_ids'].insert(0, message_id) # add the message object to the messages list data['messages'].append(message_info) pickle_data(data) return {'message_id': message_id}
def start_standup(token, channel_id, length): ''' Start a standup Length is in seconds ''' data = get_data() channel = get_channel(data, channel_id) user = get_user_from_token(data, token) # If the channel is Invalid if channel == None: raise ValueError(description='Invalid Channel') # If the channel is alreay in stadup mode if is_standup_active(channel): raise ValueError(description='Standup is already active') # If the user is not in this channel if not user_in_channel(user['u_id'], channel): raise AccessError(description='User is not in channel') # Else start a start up session channel['standup_active'] = True # setup the timer for with the length specified timer = threading.Timer(length, stop_standup, [token, channel_id]) time_finish = (datetime.now() + timedelta(seconds=length)).timestamp() channel['standup_finish'] = time_finish pickle_data(data) timer.start() return {'time_finish': time_finish}
def get_all_users(token): ''' Get all user information ''' data = get_data() user = get_user_from_token(data, token) users = [] for user in data['users']: users.append(generate_user_info(user)) return {'users': users}
def logout(token): ''' Logs user out given their token. Returns True if succesful and false otherwise. ''' data = get_data() # if the user with token has logged in, log them out user = get_user_from_token(data, token) if user is not None: user['tokens'].remove(token) pickle_data(data) return {"is_success": True} return {"is_success": False}
def join_channel(token, channel_id): ''' given a user's token and a channel_id, the user can join the channel as long as the channel is private or the user has permissions such as being an admin or owner of slackr ''' data = get_data() user = get_user_from_token(data, token) channel = get_channel(data, channel_id) #print(user_in_channel(user['email'], channel)) if channel is None or user_in_channel(user['u_id'], channel): raise ValueError('invalid channel id') if user['perm_id'] == MEMBER_ID and not channel['is_public']: raise AccessError('User is not an admin or owner of slackr') user_info = generate_user_info(user) channel['members'].append(user_info) pickle_data(data) return {}
def set_user_email(token, email): ''' set_user_email Update the authorised user's email ''' data = get_data() user = get_user_from_token(data, token) if not check_email(email): raise ValueError("Email entered is not a valid email") for index in data['users']: if email in index['email']: raise ValueError( description= "Email address is already being used by another user") user['email'] = email pickle_data(data) return {}
def leave_channel(token, channel_id): ''' given a user's token and a channel_id, the user will leave the channel with channel_id as long as the user is part of the channel ''' data = get_data() user = get_user_from_token(data, token) channel = get_channel(data, channel_id) #checks if the user is in the channel if not user_in_channel(user['u_id'], channel): raise ValueError("User not part of channel") user_info = generate_user_info(user) remove_user_with_u_id(channel, user_info['u_id']) pickle_data(data) return {}
def set_user_name(token, name_first, name_last): ''' set_user_name Update the authorised user's first and last name ''' data = get_data() user = get_user_from_token(data, token) # If the name is not valid if len(name_first) > 50: raise ValueError(description="First name too long") if len(name_last) > 50: raise ValueError(description="Last name too long") # Else update the name user['name_first'] = name_first user['name_last'] = name_last pickle_data(data) return {}
def details_channel(token, channel_id): ''' given a token of a user and a channel_id, show the owners and members of the channel with channel_id as long as the user is a member of the channel ''' data = get_data() user = get_user_from_token(data, token) channel = get_channel(data, channel_id) if channel is None: raise ValueError('invalid channel id') if not user_in_channel(user['u_id'], channel): raise AccessError('user not part of channel') pickle_data(data) return { 'name': channel['name'], 'owner_members': get_members(channel['owners']), 'all_members': get_members(channel['members']) }
def create_channel(token, name, is_public): ''' create a channel using a token, the name of the channel and whether the channel is public or private. ''' data = get_data() # check if the name is valid if not valid_channel_name(name): raise ValueError('Name is too long') user = get_user_from_token(data, token) channel_id = len(data['channels']) user_info = generate_user_info(user) # create a dict for all the information of a channel channel_info = generate_channel_info(channel_id, name, user_info, is_public) data['channels'].append(channel_info) pickle_data(data) return {'channel_id': channel_id}
def list_user_channels(token): ''' Given a user's token, this function will list all the channels that this user is in ''' data = get_data() user = get_user_from_token(data, token) channels = [] # loop through the channels and find if the user is either an owner or member for channel in data['channels']: if user_in_channel(user['u_id'], channel): user_channel = { 'channel_id': channel['channel_id'], 'name': channel['name'] } channels.append(user_channel) pickle_data(data) return {'channels': channels}
def edit_message(token, message_id, message_str): """ Edit message with message_id with new message If message is empty, delete the message """ if len(message_str) == 0: return remove_message(token, message_id) data = get_data() og_message = get_msg_from_msg_id(data, message_id) user = get_user_from_token(data, token) channel = get_channel(data, og_message['channel_id']) # check if user did not send original message and user is admin/owner if (not user_sent_message(user['u_id'], og_message) and not user_is_admin_or_owner(user, channel)): raise AccessError("User did not send message or not enough privileges") # edit the original message with the new message og_message['message'] = message_str pickle_data(data) return {}
def removeowner_channel(token, channel_id, u_id): ''' given a token, channel_id and a u_id, remove ownership of the user with u_id as long as the user was originally an owner and the user with token is also an owner ''' data = get_data() owner_user = get_user_from_token(data, token) channel = get_channel(data, channel_id) removed_user = get_user_from_u_id(data, u_id) if channel is None or not user_in_channel(owner_user['u_id'], channel): raise ValueError('invalid channel id') if not user_is_owner_channel(removed_user, channel) or owner_user['perm_id'] != OWNER_ID: raise ValueError('User is not an owner of channel or slackr') user_info = generate_user_info(removed_user) #channel['owners'].remove(user_info) remove_user_with_u_id(channel, user_info['u_id'], mode='owners') pickle_data(data) return {}
def set_user_handle(token, handle_str): ''' set_user_handle Update the authorised user's handel ''' data = get_data() user = get_user_from_token(data, token) # If the size of the token is out of range if not (3 <= len(handle_str) <= 20): raise ValueError( description="Handle must be between 3 and 20 characters") # If the handle is registered under a different user for index in data['users']: if handle_str in index['handle']: raise ValueError( description="Handle is already used by another user") # Else set current user's handle to the new handle user['handle'] = handle_str pickle_data(data) return {}
def remove_message(token, message_id): """ Remove message with message_id from channel """ data = get_data() user = get_user_from_token(data, token) message = get_msg_from_msg_id(data, message_id) if message is None: raise ValueError('Message no longer exists') channel = get_channel(data, message['channel_id']) if not user_sent_message(user['u_id'], message) and not user_is_admin_or_owner( user, channel): raise AccessError("User did not send message or not enough privileges") # remove the message object and the message_id from the 'database' data['messages'].remove(message) channel['message_ids'].remove(message_id) pickle_data(data) return {}
def unreact_message(token, message_id, react_id): """ Unreact message with message_id with react_id """ data = get_data() user = get_user_from_token(data, token) message = get_msg_from_msg_id(data, message_id) if message is None or not user_in_channel_with_msg(data, user['u_id'], message): raise ValueError('Message is not in the channel') if not valid_react_id(react_id): raise ValueError('Invalid react id') if not message_contains_react(message, user['u_id']): raise ValueError('Message does not have that react') # get the react object and delete the user u_id react = get_react_from_react_id(message, react_id) react['u_ids'].remove(user['u_id']) react['is_this_user_reacted'] = False pickle_data(data) return {}
def unpin_message(token, message_id): """ Unpin message with message_id """ data = get_data() user = get_user_from_token(data, token) message = get_msg_from_msg_id(data, message_id) if message is None: raise ValueError("Invalid message_id") channel = get_channel(data, message['channel_id']) if not perm_id_is_admin_owner(user['perm_id']): raise ValueError("User is not an admin or owner") if not message['is_pinned']: raise ValueError("Message is not pinned") if not user_in_channel(user['u_id'], channel): raise AccessError( "User not part of channel that the message is within") # set the pin flag on the message to False message['is_pinned'] = False pickle_data(data) return {}
def addowner_channel(token, channel_id, u_id): ''' given a token of a user and a channel_id and another user's u_id, the user with u_id is promoted to being an owner of the channel with channel_id as long as the user with token has permissions to do so (is an admin or owner) ''' data = get_data() owner_user = get_user_from_token(data, token) channel = get_channel(data, channel_id) promoted_user = get_user_from_u_id(data, u_id) if channel is None: raise ValueError("Channel does not exist") if user_is_owner_channel(promoted_user, channel): raise ValueError("User with u_id is already owner of channel") if not user_is_admin_or_owner(owner_user, channel): raise AccessError("Not enough permissions to add user as owner") user_info = generate_user_info(promoted_user) channel['owners'].append(user_info) pickle_data(data) return {}
def permission_change(token, u_id, permission_id): ''' Given a user by their u_id, set their permissions to new permissions described by permission_id. Will raise a ValueError if: u_id is invalid, permission is invalid, or authorized user is not an owner or admin. Returns an empty dictionary. ''' data = get_data() auth_user = get_user_from_token(data, token) changing_user = get_user_from_u_id(data, u_id) if changing_user is None: raise ValueError(description='Invalid u_id') if permission_id not in [1, 2, 3]: raise ValueError(description='Invalid permission_id') if auth_user['perm_id'] == MEMBER_ID: raise AccessError( description='Authorised user is not an owner or admin') changing_user['perm_id'] = permission_id pickle_data(data) return {}
def invite_user(token, channel_id, u_id): ''' Given a user's token, channel_id, and another user's u_id, invite the user with the given u_id into the channel with the channel_id so long as the user with token has the correct permissions (is an admin or owner of channel) ''' data = get_data() inviting_user = get_user_from_token(data, token) user_to_add = get_user_from_u_id(data, u_id) channel = get_channel(data, channel_id) #if channel does not exist or the user is not in the channel if channel is None: raise ValueError('invalid channel id') if user_to_add is None: raise ValueError('invalid user id') if not user_in_channel(inviting_user['u_id'], channel): raise AccessError('user not part of channel') # add user to the channel user_info = generate_user_info(user_to_add) channel['members'].append(user_info) pickle_data(data) return {}
def send_later(token, channel_id, message_str, time_sent): """ Send a message to channel with channel_id at time time_sent """ data = get_data() user = get_user_from_token(data, token) channel = get_channel(data, channel_id) now = datetime.now().timestamp() # get the difference between the time_sent parameter and the current time time_diff = time_sent - now if channel is None: raise ValueError('channel does not exist') if not valid_message_len(message_str): raise ValueError('message is too long') if time_diff < 0: # time_sent is in the past raise ValueError('invalid date') if not user_in_channel(user['u_id'], channel): raise ValueError('user not part of channel') # set a timer to call send_message once time_diff seconds are finished timer = threading.Timer(time_diff, send_message, [token, channel_id, message_str]) timer.start()
def send_standup(token, channel_id, message_str): ''' Send message to standup ''' data = get_data() channel = get_channel(data, channel_id) user = get_user_from_token(data, token) # If the channel is invalid if channel == None: raise ValueError(description='Invalid Channel') # If the message is too long if not valid_message_len(message_str): raise ValueError(description='Invalid Channel') # If the channel is already in stand up mode if not is_standup_active(channel): raise ValueError(description='No active standup') # If the curret user is not in the channel if not user_in_channel(user['u_id'], channel): raise AccessError(description='User is not in channel') user_message = f"{user['name_first']}: {message_str}" channel['standup_messages'].append(user_message) pickle_data(data) return {}