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 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 register(email, password, name_first, name_last): ''' Registers a user using given parameters and stores in data (email, password, name, name_first, name_last) Will fail when the entered email is already in use or any of the inputs are invalid. Returns a dictionary with the users u_id and token ''' data = get_data() if (check_email(email) and find_user(data, email) is None and len(password) > 5 and check_name_len(name_first) and check_name_len(name_last)): # these functions are in the auth_helper file token = generate_token(email) handle = generate_handle(data, name_first, name_last) u_id = len(data['users']) perm_id = MEMBER_ID if u_id == 0: perm_id = OWNER_ID profile = generate_profile(u_id, email, password, name_first, name_last, handle, perm_id, token) #profile['tokens'].append(token) # add the profile, email and token to the "database" data['users'].append(profile) pickle_data(data) return {"u_id": profile['u_id'], "token": token} if find_email(data, email): raise ValueError( description="The entered email has already been registered.") raise ValueError( description="Invalid email, password, first name or last name")
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 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 active_standup(token, channel_id): ''' check if standup is active ''' data = get_data() channel = get_channel(data, channel_id) if channel == None: raise ValueError(description='Invalid Channel') return { 'is_active': channel['standup_active'], 'time_finish': channel['standup_finish'] }
def stop_standup(token, channel_id): ''' stop current standup ''' data = get_data() channel = get_channel(data, channel_id) channel['standup_active'] = False channel['standup_finish'] = None message = ' '.join(channel['standup_messages']) channel['standup_messages'] = [] pickle_data(data) send_message(token, channel['channel_id'], message)
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 get_user_profile(token, u_id): ''' set_get_profile For a valid user, returns information about their email, first name, last name, and handle ''' data = get_data() user = get_user_from_u_id(data, u_id) # If the user is not valid if user == None: raise ValueError(description="User with u_id is not a valid user") # If the user is valid user_profile = generate_user_info(user) #pickle_data(data) return user_profile
def request_reset(email): ''' Given an email address, if the user is registered, sends them an email containing a secret code, that when entered allows user to reset password Will return Value Errors if: email is invalid, password is invalid, code is invalid. Returns an empty dictionary. ''' data = get_data() code = generate_request_code() data['valid_reset'][code] = email pickle_data(data) if find_user(data, email) is not None: return code raise ValueError(description='Invalid email')
def message_search(token, query_str): """ Search the entire message history for any message containing the substring query_str """ data = get_data() search_results = [] # loop though every message in the 'database' for message in data['messages']: # if query_str is a substring of message, add the relevent details # to search_results list if query_str in message['message']: # create search_result function here result = generate_search_result(message) search_results.append(result) return search_results
def list_all_user_channels(token): ''' Given a user's token, this function will list all the channels in slackr ''' data = get_data() channels = [] # loop through the channels and add them to the channels list for channel in data['channels']: user_channel = { 'channel_id': channel['channel_id'], 'name': channel['name'] } channels.append(user_channel) pickle_data(data) return {'channels': channels}
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_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 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_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 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 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 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 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 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 login(email, password): ''' Given an email and a password, logs a user in with correct credentials. Will raise a ValueError if incorrect credentials have been inputted. Returns a dictionary consisting of users u_id and token. ''' data = get_data() #print(data) # variables to the keep the result to reduce clutter email_ok = check_email(email) and find_email(data, email) password_ok = check_password(data, email, password) if not email_ok or not password_ok: raise ValueError(description="Invalid email or password") token = generate_token(email) user = find_user(data, email) # add the token to the logged in users user['tokens'].append(token) pickle_data(data) return {"u_id": user['u_id'], "token": token}
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 reset_reset(code, new_password): ''' Given a reset code for a user, set that user's new password to the password provided. Will raise ValueErrors if: password is invalid, or code is invalid. Returns an empty dictionary. ''' data = get_data() if len(new_password) < 5: raise ValueError(description="Invalid password") if code not in data['valid_reset']: raise ValueError(description="Invalid code") # get associated email and token email = data['valid_reset'][code] user = find_user(data, email) # set the new password del data['valid_reset'][code] user['password'] = hash_password(new_password) 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 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 {}