def users_stats_v1(token): """ Fetches the required statistics about the use of UNSW Dreams Parameters: token (string) - jwt encoded data structure of auth_user with session_id Exceptions: AccessError - Occurs when token is invalid Returns: dreams_stats (dict) - statistics about the use of UNSW Dreams """ with open("data.json") as json_file: data = load(json_file) token_check(token) dreams_stats = data["dreams_stats"] dreams_stats["utilization_rate"] = calculate_utilization_rate( data, dreams_stats) return {"dreams_stats": dreams_stats}
def users_all_v1(token): """ Returns a list of all users and their associated details Arguments: token (string) - jwt encoded data structure of auth_user with session_id Exceptions: AccessError - Occurs when token is invalid Return value: user (list of dict) - list of dict containing user_id, email, first name, last name and handle """ with open("data.json") as json_file: data = load(json_file) token_check(token) all_profiles = [] # we can be sure that there are no errors raised here because token has been # checked and u_id is valid because we are getting it straight from data for user in data["users"]: all_profiles.append(user_profile_v2(token, user["u_id"])["user"]) return {"users": all_profiles}
def channels_listall_v2(token): ''' <Provide a list of all channels (and their associated details)> Parameters: auth_user_id(int) = user id of user who authorised function Return Value: {channels} = list of all the channels with channel_id and name ''' with open("data.json") as json_file: data = load(json_file) #create a new dictionary for channels to return channels_list = {'channels': []} token_check(token) #loop through all the channels which stored in the data base for channel_detail in data["channels"]: #Get the information we need to store in the channels_list channel_id_tmp = channel_detail['channel_id'] channel_name_tmp = channel_detail['name'] #Update the channels_list channels_list["channels"].append( { "channel_id": channel_id_tmp, "name": channel_name_tmp, } ) return channels_list
def errorcheck_channel_invite_v2(token, channel_id, u_id): token_check(token) if is_valid_channel_id(channel_id) == False: raise InputError( description="Channel_id does not refer to a valid channel") if is_valid_u_id(u_id) == False: raise InputError(description="u_id does not refer to a valid user") if is_auth_user_memberof_channel_id(token, channel_id) == False: raise AccessError( description= "the authorised user is not already a member of the channel")
def errorcheck_removeowner_v1(token, channel_id, u_id): # assumes the user must be in the channel before being added as an owner # if not, raise an input error data_structure = token_check(token) if is_valid_u_id(u_id) == False: raise InputError("Invalid u_id") if is_valid_channel_id(channel_id) == False: raise InputError("Invalid channel_id") if is_user_channel_membertype(channel_id, u_id, CHANNEL_MEMBER) == False: raise InputError( "user with user id u_id is not already a member of the channel") if is_user_channel_membertype(channel_id, u_id, CHANNEL_OWNER) == False: raise InputError( "user with user id u_id is not already a channel owner") if is_user_channel_membertype( channel_id, int(data_structure["u_id"]), CHANNEL_OWNER) == False and find_auth_user_permission_id( int(data_structure["u_id"])) == 2: raise AccessError( "auth_user is not an owner of the channel or an owner of **Dreams**" ) if is_user_only_owner(channel_id) == True: raise InputError("user to be removed is the only owner in the channel")
def user_stats_v1(token): """ Fetches the required statistics about this user's use of UNSW Dreams Parameters: token (string) - jwt encoded data structure of auth_user with session_id Exceptions: AccessError - Occurs when token is invalid Returns: user_stats (dict) - statistics about this user's use of UNSW Dreams """ with open("data.json") as json_file: data = load(json_file) data_structure = token_check(token) for user in data["users"]: if user["u_id"] == data_structure["u_id"]: user_stats = user["user_stats"] user_stats["involvement_rate"] = calculate_involvement_rate(user_stats) with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return {"user_stats": user_stats}
def user_profile_sethandle_v1(token, handle_str): """ Update the authorised user's handle (i.e. display name) Arguments: token (string) - jwt encoded data structure of auth_user with session_id handle_str (string) - new handle_str to replace old handle_str Exceptions: InputError - Occurs when handle_str is not between 3 and 20 characters inclusive, handle is already used by another user, handle_str is not a string (assumption) AccessError - Occurs when token is invalid Return Value: Returns {} on Success """ with open("data.json") as json_file: data = load(json_file) data_structure = token_check(token) errorcheck_user_profile_sethandle_v1(token, handle_str) for user in data["users"]: if user["u_id"] == int(data_structure["u_id"]): user["handle_str"] = handle_str with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return {}
def message_unpin_v1(token, message_id): """ Given a message within a channel or DM, remove it's mark as unpinned Parameters: token (string) - jwt encoded data structure of auth_user_id message_id (int) - message to be pinned Exceptions: InputError - Occurs when message_id is not a valid message, message with ID message_id is already unpinned AccessError - Occurs when the authorised user is not a member of the channel or DM that the message is within, the authorised user is not an owner of the channel or DM, the token is invalid Returns: {} """ with open("data.json") as json_file: data = load(json_file) data_structure = token_check(token) message = error_check_message_pin_unpin(data_structure["u_id"], data, message_id, False) message["is_pinned"] = False with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return {}
def user_profile_setemail_v2(token, email): """ Update the authorised user's email address Arguments: token (string) - jwt encoded data structure of auth_user with session_id email (string) - new email to replace old email Exceptions: InputError - Occurs when email entered is not a valid email, email address is already being used by another user, AccessError - Occurs when a token is invalid Return Value: Returns {} on Success """ """ data_structure = check_token(token) """ with open("data.json") as json_file: data = load(json_file) data_structure = token_check(token) errorcheck_user_profile_setemail_v2(token, email) for user in data["users"]: if user["u_id"] == int(data_structure["u_id"]): user["email"] = email with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return {}
def dm_list_v1(token): """ Returns the list of DMs that the user is a member of Arguments: token (string) - jwt encoded data structure of auth_user Exceptions: InputError - N/A AccessError - N/A Return value: Returns user (dictionary) on success a dictionary with information about dms """ with open("data.json") as json_file: data = load(json_file) dms_list = {"dms": []} auth_user_id = token_check(token)["u_id"] for dm_detail in data["dms"]: dm_id_tmp = dm_detail["dm_id"] dm_name_tmp = dm_detail["name"] all_members_tmp = dm_detail["members"] for u_id in all_members_tmp: if u_id == auth_user_id: dms_list["dms"].append({ "dm_id": dm_id_tmp, "name": dm_name_tmp }) return dms_list
def user_profile_setname_v2(token, name_first, name_last): """ Update the authorised user's first and last name Arguments: token (string) - jwt encoded data structure of auth_user with session_id name_first (string) - new name_first to replace old name_first name_last (string) - new name_last to replace old name_last Exceptions: InputError - Occurs when name_first is not between 1 and 50 characters inclusively in length, name_last is not between 1 and 50 characters inclusively in length AccessError - Occurs when token is invalid Return Value: Returns {} on Success """ with open("data.json") as json_file: data = load(json_file) errorcheck_user_profile_setname_v2(token, name_first, name_last) data_structure = token_check(token) for user in data["users"]: if user["u_id"] == int(data_structure["u_id"]): user["name_first"] = name_first user["name_last"] = name_last with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return {}
def user_profile_v2(token, u_id): """ For a valid user, returns information about their user_id, email, first name, last name, and handle Arguments: token (string) - jwt encoded data structure of auth_user u_id (int) - user to build profile of Exceptions: InputError - Occurs when user with u_id is not a valid user AccessError - Occurs when token is invalid Return value: Returns user (dictionary) on success a dictionary with information about user with user id u_id """ with open("data.json") as json_file: data = load(json_file) token_check(token) if is_valid_u_id(u_id) == False: raise InputError(description="User with u_id is not a valid user") for user in data["users"]: if user["u_id"] == u_id: found_user = user return { 'user': { 'u_id': u_id, 'email': found_user["email"], 'name_first': found_user["name_first"], 'name_last': found_user["name_last"], 'handle_str': found_user["handle_str"], "profile_img_url": found_user["profile_img_url"], 'unscramble_record': found_user["unscramble_record"] } }
def dm_leave_v1(token, dm_id): """ Given a DM ID, the user is removed as a member of this DM Arguments: token (string) - jwt encoded data structure of auth_user dm_id (int) - target dm Exceptions: InputError - Occurs when dm_id is not a valid DM AccessError - Occurs when Authorised user is not a member of DM with dm_id Return value: Returns user (dictionary) on success a dictionary with information about nothing """ time_stamp = datetime.now().replace(microsecond=0).timestamp() with open("data.json") as json_file: data = load(json_file) auth_user_id = token_check(token)["u_id"] is_dm_exist = False for dm_data in data["dms"]: if dm_data["dm_id"] == dm_id: dm = dm_data is_dm_exist = True break if is_dm_exist is False: raise InputError("dm_id is not a valid DM") is_auth_user_member = False if auth_user_id in dm["members"]: is_auth_user_member = True if is_auth_user_member is False: raise AccessError("Authorised user is not a member of DM with dm_id") user_stats_update(data, auth_user_id, stat_types.DM_LEAVE, time_stamp) if auth_user_id != dm["original_creator"]: dm["members"].remove(auth_user_id) else: dm["members"].remove(auth_user_id) dm["original_creator"] = dm["members"][0] list(set(dm["members"])) with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return {}
def standup_start_v1(token, channel_id, length): with open("data.json") as json_file: data = load(json_file) auth_user_id = token_check(token)["u_id"] is_channel_exist = False for channel_data in data["channels"]: if channel_data["channel_id"] == channel_id: channel = channel_data is_channel_exist = True if is_channel_exist is False: raise InputError("Channel ID is not a valid channel") is_standup_already_active = False for standup_data in data["standups"]: if standup_data["channel_id"] == channel_id: is_standup_already_active = True if is_standup_already_active is True: raise InputError( "An active standup is currently running in this channel") is_auth_user_member = False if auth_user_id in channel["all_members"]: is_auth_user_member = True if is_auth_user_member is False: raise AccessError("Authorised user is not in the channel") time_finish = time.time() + length data["standups"].append({ "channel_id": channel_id, "message": [], "time_finish": time_finish }) with open("data.json", "w") as json_file: dump(data, json_file, indent=4) t = threading.Timer(length, standup_close_v1, kwargs={ "token": token, "channel_id": channel_id, "u_id": auth_user_id }) t.start() return {"time_finish": time_finish}
def channels_create_v2(token, name, is_public): ''' Creates a new channel with that name that is either a public or private channel Returns type: { channel_id } Input Error: Name is more than 20 characters long ''' time_stamp = datetime.now().replace(microsecond=0).timestamp() with open("data.json") as json_file: data = load(json_file) # Decode token (u_id) if valid, otherwise raise AccessError user = token_check(token) # Raise error if channel name is > 20 characters # or if there is no name given if len(name) > 20: raise InputError("Channel name is more than 20 characters.") if len(name) == 0: raise InputError("No channel name has been entered.") # Ensure users sets channel to private or public if is_public not in (True, False): raise InputError("Channel privacy is undefined") # Makes the channel id in order from 1 as they are created channel_id = len(data["channels"]) + 1 # Store data in data.py channels user_stats_update(data, user["u_id"], stat_types.CH_JOIN, time_stamp) dreams_stats_update(data, stat_types.CH_CREATE, time_stamp) data["channels"].append( { 'channel_id': channel_id, 'name': name, 'owner_members': [user['u_id']], 'all_members': [user['u_id']], 'invites' : [], 'is_public': is_public, 'messages': [] } ) with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return { 'channel_id': channel_id }
def errorcheck_channel_details_v2(token, channel_id): """ Checks the error cases for channel_details_v2 Arguments: token (string) - jwt encoded data structure of auth_user with session_id channel_id (int) - the channel to check for the u_id Exceptions: Refer to channel_details function Returns Value: N/A """ token_check(token) if is_valid_channel_id(channel_id) == False: raise InputError(description="Channel ID is not a valid channel") if is_auth_user_in_channel(token, channel_id) == False: raise AccessError( description= "Authorised user is not a member of channel with channel_id")
def message_sendlater_v1(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 - token of the sender channel_id - channel ID of the message to be sent at message - message to be sent later time_sent - time message will be sent at Returns { message_id } InputError when: Channel ID is not a valid channel Message is more than 1000 characters Time sent is a time in the past AccessError when: The authorised user has not joined the channel they are trying to post to """ # Check token if token_check(token): pass # Check if channel ID is valid if is_valid_channel_id(channel_id) is False: raise InputError("Invalid Channel ID") # Make sure authorised user is a member of the channel if is_auth_user_memberof_channel_id(token, channel_id) is False: raise AccessError(description="User is not a member of this channel") # InputError raised when empty message is sent if message == "": raise InputError(description="Cannot send an empty message") # Ensure message being sent is no more than 1000 characters if len(message) > 1000: raise InputError(description="Message is more than 1000 characters") # Find time now as a timestamp time_create_date = datetime.now().replace(microsecond=0) time_created = time_create_date.timestamp() # Check if time_sent is valid if time_sent < time_created: raise InputError(description='Time sent is invalid') # Find the difference in time between now and time_sent time_to_be_sent = time_sent - time_created # The sleep() function suspends execution of the current thread for a given number of seconds. time.sleep(time_to_be_sent) return message_send_v2(token, channel_id, message)
def dm_remove_v1(token, dm_id): """ Remove an existing DM. This can only be done by the original creator of the DM. Arguments: token (string) - jwt encoded data structure of auth_user dm_id (int) - dm_id that be removed Exceptions: InputError - Occurs when dm_id does not refer to a valid DM AccessError - Occurs when the user is not the original DM creator Return value: Returns user (dictionary) on success a dictionary with information about nothing """ time_stamp = datetime.now().replace(microsecond=0).timestamp() with open("data.json") as json_file: data = load(json_file) auth_user_id = token_check(token)["u_id"] is_dm_exist = False for dm_data in data["dms"]: if dm_data["dm_id"] == dm_id: dm = dm_data is_dm_exist = True break if is_dm_exist is False: raise InputError("dm_id does not refer to a valid DM") is_auth_user_creator = False if auth_user_id == dm["original_creator"]: is_auth_user_creator = True if is_auth_user_creator is False: raise AccessError("the user is not the original DM creator") dreams_stats_update(data, stat_types.DM_REMOVE, time_stamp) for member in dm["members"]: user_stats_update(data, member, stat_types.DM_LEAVE, time_stamp) data["dms"].remove(dm) with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return {}
def channel_invite_v2(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 Arguments: token (string) - jwt encoded data structure of auth_user channel_id (int) - channel_id of channel to have u_id invited into u_id (int) - u_id of individual to be invited Exceptions: InputError - Occurs when channel_id does not refer to a valid channel, u_id does not refer to a valid user AccessError - Occurs when the authorised user is not already a member of the channel, token is invalid Return value: {} ''' time_stamp = datetime.now().replace(microsecond=0).timestamp() with open("data.json") as json_file: data = load(json_file) data_structure = token_check(token) errorcheck_channel_invite_v2(token, channel_id, u_id) user_stats_update(data, data_structure["u_id"], stat_types.CH_JOIN, time_stamp) for channel in data["channels"]: if channel["channel_id"] == channel_id: found_channel = channel found_channel['all_members'].append(u_id) list(set(found_channel['all_members'])) found_channel['invites'].append({ "auth_user_id": data_structure["u_id"], "u_id": u_id, "time_invited": time_stamp }) with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return {}
def standup_send_v1(token, channel_id, message): with open("data.json") as json_file: data = load(json_file) auth_user_id = token_check(token)["u_id"] auth_user_handle = user_profile_v2(token, auth_user_id)["user"]["handle_str"] is_channel_exist = False for channel_data in data["channels"]: if channel_data["channel_id"] == channel_id: channel = channel_data is_channel_exist = True break if is_channel_exist is False: raise InputError("Channel ID is not a valid channel") if len(message) > 1000: raise InputError( "Message is more than 1000 characters (not including the username and colon)" ) is_standup_already_active = False for standup_data in data["standups"]: if standup_data["channel_id"] == channel_id: standup_channel = standup_data is_standup_already_active = True if is_standup_already_active is False: raise InputError( "An active standup is not currently running in this channel") is_auth_user_member = False if auth_user_id in channel["all_members"]: is_auth_user_member = True if is_auth_user_member is False: raise AccessError( "The authorised user is not a member of the channel that the message is within" ) standup_channel["message"].append(auth_user_handle + ": " + message) with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return {}
def dm_details_v1(token, dm_id): """ Users that are part of this direct message can view basic information about the DM Arguments: token (string) - jwt encoded data structure of auth_user dm_id (int) - dm to get information of Exceptions: InputError - Occurs when DM ID is not a valid DM AccessError - Occurs when Authorised user is not a member of this DM with dm_id Return value: Returns user (dictionary) on success a dictionary with information about name, members """ with open("data.json") as json_file: data = load(json_file) auth_user_id = token_check(token)["u_id"] is_dm_exist = False for dm_data in data["dms"]: if dm_data["dm_id"] == dm_id: dm = dm_data is_dm_exist = True break if is_dm_exist is False: raise InputError("DM ID is not a valid DM") is_auth_user_member = False if auth_user_id in dm["members"]: is_auth_user_member = True if is_auth_user_member is False: raise AccessError( "Authorised user is not a member of this DM with dm_id") dm_name = dm["name"] dm_members = [] for member in dm["members"]: dm_members.append(user_profile_v2(token, member)["user"]) return {"name": dm_name, "members": dm_members}
def userpermission_change_v1(token, u_id, permission_id): """ Given a User by their user ID, set their permissions to new permissions described by permission_id Arguments: token (string) - jwt encoded string of user changing the permission_id of user of u_id u_id (int) - u_id of the person getting their permission_id changed permission_id (int) - Owners have permissin_id 1, members have permission_id 2 ... Exceptions: InputError - Occurs when u_id does not refer to a valid use InputError - Occurs when permission_id does not refer to a value permission AccessError - Occurs when The authorised user is not an owner Return Value: Returns {} """ with open("data.json") as json_file: data = load(json_file) #check if token is valid token_u_id = token_check(token)["u_id"] #check u_id if is_valid_u_id(u_id) is False: raise InputError("u_id is invalid") #check if permission_id refers to a value permission if permission_id != 1 and permission_id != 2: raise InputError("permission_id does not refer to a value permission") #check if authorised user is not an owner for users in data["users"]: if users["u_id"] == token_u_id: if users["permission_id"] != 1: raise AccessError("The authorised user is not an owner") #change permission_id for user in data["users"]: if user["u_id"] == u_id: user["permission_id"] = permission_id with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return {}
def errorcheck_addowner_v1(token, channel_id, u_id): """ Checks the error cases for add_owner Arguments: token - jwt encoded data structure that stores auth_user info channel_id (int) - channel to be added into u_id (int) - user to be checked Exceptions: Refer to addowner function Return values: None """ data_structure = token_check(token) if is_valid_u_id(u_id) == False: raise InputError("u_id does not refer to a valid user") if is_valid_channel_id(channel_id) == False: raise InputError("Channel ID is not a valid channel") if is_user_channel_membertype(channel_id, u_id, CHANNEL_MEMBER) == False: raise InputError( "user with user id u_id is not already a member of the channel") if is_user_channel_membertype(channel_id, u_id, CHANNEL_OWNER) == True: raise InputError( "user with user id u_id is already an owner of the channel") if is_user_channel_membertype( channel_id, int(data_structure["u_id"]), CHANNEL_OWNER) == False and find_auth_user_permission_id( int(data_structure["u_id"])) == 2: raise AccessError( "the authorised user is not an owner of the Dreams or an owner of this channel" )
def channel_leave_v1(token, channel_id): ''' Given a channel ID, the user removed as a member of this channel. Their messages should remain in the channel Parameters: token (str): jwt encoded data structure for authorised user channel_id (int): id for channel Returns: {} InputError when: Channel ID is not a valid channel AccessError when: Authorised user is not a member of channel with channel_id ''' time_stamp = datetime.now().replace(microsecond=0).timestamp() with open("data.json") as json_file: data = load(json_file) user = token_check(token) errorcheck_leave_v2(token, channel_id) user_stats_update(data, user["u_id"], stat_types.CH_LEAVE, time_stamp) found_channel = find_channel(data, channel_id) found_channel['all_members'].remove(user['u_id']) if user['u_id'] in found_channel['owner_members']: found_channel['owner_members'].remove(user['u_id']) with open("data.json", "w+") as json_file: dump(data, json_file, indent=4) return {}
def user_profile_uploadphoto_v1(token, img_url, x_start, y_start, x_end, y_end): auth_user_id = token_check(token)["u_id"] response = requests.get(img_url) if response.status_code != 200: raise InputError("img_url returns an HTTP status other than 200.") path = generate_user_profile_photo(auth_user_id)["profile_img_path"] request.urlretrieve(img_url, path) image = Image.open(path) (left, top, right, bottom) = image.getbbox() if x_start < left or x_end > right or y_start < top or y_end > bottom: raise InputError( "any of x_start, y_start, x_end, y_end are not within the dimensions of the image at the URL." ) image = Image.open(path) img_crop = image.crop(box=(x_start, y_start, x_end, y_end)) img_crop.save(path) return {}
def channels_list_v2(token): ''' Provide a list of all channels (and their associated details) that the authorised user is part of Parameters: auth_user_id(int) = user id of user who authorised function Return Value: {channels} = list of channels with channel_id and name ''' with open("data.json") as json_file: data = load(json_file) #create a new dictionary for channels to return channels_list = {'channels': []} auth_user_id = token_check(token)["u_id"] #loop through all the channels which stored in the data base for channel_detail in data["channels"]: #Get the information we need to store in the channels_list channel_id_tmp = channel_detail["channel_id"] channel_name_tmp = channel_detail["name"] #Check the authorised user is part of the channel or not all_members_tmp = channel_detail["all_members"] for u_id in all_members_tmp: #If the authorised user is part of the channel update the channels_list if int(u_id) == int(auth_user_id): channels_list["channels"].append( { "channel_id": channel_id_tmp, "name": channel_name_tmp, } ) return channels_list
def channel_join_v2(token, channel_id): ''' Given a channel_id of a channel that the authorised user can join, adds them to that channel Arguments: token (string) - jwt encoded string containing auth_user_id info channel_id (int) - id of channel to join Exceptions: InputError - Occurs when channel ID is not a valid channel AccessError - Occurs when channel_id refers to a channel that is private (when the authorised user is not a global owner), token is invalid Return value: {} ''' time_stamp = datetime.now().replace(microsecond=0).timestamp() with open("data.json") as json_file: data = load(json_file) data_structure = token_check(token) errorcheck_channel_join_v2(data_structure, data, channel_id) user_stats_update(data, data_structure["u_id"], stat_types.CH_JOIN, time_stamp) found_channel = find_channel(data, channel_id) found_channel['all_members'].append(int(data_structure["u_id"])) list(set(found_channel['all_members'])) with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return {}
def message_sendlaterdm_v1(token, dm_id, message, time_sent): """ Send a message from authorised_user to the DM specified by dm_id automatically at a specified time in the future Parameters: token - token of the sender dm_id - dm ID of the message to be sent at message - message to be sent later time_sent - time message will be sent at Returns { message_id } InputError when: DM ID is not a valid channel Message is more than 1000 characters Time sent is a time in the past AccessError when: The authorised user has not joined the DM they are trying to post to """ with open("data.json") as json_file: data = load(json_file) # Check token and decode it user = token_check(token) is_dm_exist = False for dm_data in data["dms"]: if dm_data["dm_id"] == dm_id: dm = dm_data is_dm_exist = True break # Check DM ID given is valid if is_dm_exist is False: raise InputError(description="DM ID is not a valid DM") # Make sure authorised user is a member of the DM group is_auth_user_member = False if user['u_id'] in dm["members"]: is_auth_user_member = True if is_auth_user_member is False: raise AccessError( description="Authorised user is not a member of this DM with dm_id" ) # InputError raised when empty message is sent if message == "": raise InputError(description="Cannot send an empty message") # Ensure message being sent is no more than 1000 characters if len(message) > 1000: raise InputError(description="Message is more than 1000 characters") # Find time now as a timestamp time_create_date = datetime.now().replace(microsecond=0) time_created = time_create_date.timestamp() # Check if time_sent is valid if time_sent < time_created: raise InputError(description='Time sent is invalid') # Find the difference in time between now and time_sent time_to_be_sent = time_sent - time_created # The sleep() function suspends execution of the current thread for a given number of seconds. time.sleep(time_to_be_sent) return message_senddm_v1(token, dm_id, message)
def message_share_v1(token, og_message_id, message, channel_id, dm_id): """ og_message_id is the original message. channel_id is the channel that the message is being shared to, and is -1 if it is being sent to a DM. dm_id is the DM that the message is being shared to, and is -1 if it is being sent to a channel. message is the optional message in addition to the shared message, and will be an empty string "" if no message is given Parameters: token - token of the user sharing message og_message_id - message id of the original message message - optional message to be commented with shared message channel_id - channel_id of the channel msg is being shared to (default -1) dm_id - dm_id of the dm group that message is being sent to (default -1) Returns: { shared_message-id } InputError when: Optional message is more than 1000 characters (Assumption) AccessError when: Invalid token The authorised user has not joined the channel or DM they are trying to share the message to """ time_stamp = datetime.now().replace(microsecond=0).timestamp() with open("data.json") as json_file: data = load(json_file) # Decode token if token is valid user = token_check(token) optional_msg = message # Input Error when optional message is more than 1000 chars if len(optional_msg) > 1000: raise InputError( description="Your optional message is more than 1000 characters") # Let the channel/dm not being shared to be -1 not_shared = -1 # If channel_id and dm_id are both given # user should give either a channel_id or dm_id if channel_id is not not_shared and dm_id is not not_shared: raise InputError( description= "Both channel_id and dm_id is given, choose one or the other") # Both channel_id and dm_id are given as -1 elif channel_id is not_shared and dm_id is not_shared: raise InputError( description="Both channel_id and dm_id are given as -1") # ----SHARING TO CHANNEL---- # If channel_id is given and dm_id is -1 elif channel_id is not not_shared and dm_id is not_shared: user_stats_update(data, user["u_id"], stat_types.MSG_SEND, time_stamp) dreams_stats_update(data, stat_types.MSG_SEND, time_stamp) # Check if channel_id given is valid if is_valid_channel_id(channel_id) is False: raise InputError(description="Channel id not found") # Check if the authorised user is a member of the channel if is_auth_user_memberof_channel_id(token, channel_id) is False: raise AccessError( description="Authorised use is not a member of the channel") msg_found = False # Loop through channel data to look for message_id for ch in data["channels"]: # Loop through messages of channel for msg in ch["messages"]: # if og_message_id is found if msg["message_id"] == og_message_id: msg_found = True break # The message wasn"t found in channel # Loop through the DM messages and check if it is there for dm in data["dms"]: # Loop through messages of dms for dm_message in dm["messages"]: # If message_id is found if dm_message["message_id"] == og_message_id: msg_found = True # If the message is found, assign string of shared message if msg_found: og_message = msg["message"] else: raise InputError(description="message id could not be found") # Find the channel for channel id given channel = find_channel(data, channel_id) # Loop through to the channel given and return specified channel dictionary all_msgs = channel["messages"] # Keep track of last message id last_msg_id = data.get("last_message_id", 0) message_id = last_msg_id + 1 # Update data data["last_message_id"] = message_id # unix timestamp time_create_date = datetime.now().replace(microsecond=0) time_created = time_create_date.timestamp() # New message struct new_message = { "message_id": message_id, "u_id": user["u_id"], # E.g. Hi guys, look at this ----|funny cat meme|---- "message": optional_msg + " " + "----|" + og_message + "|----", "time_created": time_created, 'reacts': [{ 'react_id': 0, 'u_ids': [], 'is_this_user_reacted': False }], 'react_history': [], 'is_pinned': False, } # Append the new message to the end of the list all_msgs.append(new_message) # ----SHARING TO DM---- # If channel is -1 and dm_id is given elif channel_id is not_shared and dm_id is not not_shared: user_stats_update(data, user["u_id"], stat_types.MSG_SEND, time_stamp) dreams_stats_update(data, stat_types.MSG_SEND, time_stamp) # Check if dm_id given is valid is_dm_exist = False for dm_data in data["dms"]: if dm_data["dm_id"] == dm_id: # Assign dm dictionary of given dm_id dm = dm_data is_dm_exist = True break if is_dm_exist is False: raise InputError("DM ID is not a valid DM") # Check if user is a member of dm group is_auth_user_member = False if user["u_id"] in dm["members"]: is_auth_user_member = True if is_auth_user_member is False: raise AccessError( description= "Authorised user is not a member of this DM with dm_id") msg_found = False # Loop through channel data to look for message_id for ch in data["channels"]: # Loop through messages of channel for msg in ch["messages"]: # if og_message_id is found if msg["message_id"] == og_message_id: msg_found = True # The message wasn"t found in channel # Loop through the DM messages and check if it is there for dm in data["dms"]: # Loop through messages of dms for dm_message in dm["messages"]: # If message_id is found if dm_message["message_id"] == og_message_id: msg_found = True break # If the message is found, assign string of shared message if msg_found: og_message = dm_message["message"] else: raise InputError(description="message id could not be found") # Keep track of last message id last_msg_id = data["last_message_id"] message_id = last_msg_id + 1 # Update data data["last_message_id"] = message_id # unix timestamp time_create_date = datetime.now().replace(microsecond=0) time_created = time_create_date.timestamp() new_message = { "message_id": message_id, "u_id": user["u_id"], "message": message + " " + "----|" + og_message + "|----", "time_created": time_created, 'reacts': [{ 'react_id': 0, 'u_ids': [], 'is_this_user_reacted': False }], 'react_history': [], 'is_pinned': False, } all_msgs = dm["messages"] # Append the new message to the end of the list all_msgs.append(new_message) with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return {"shared_message_id": message_id}
def message_edit_v2(token, message_id, message): """ Given a message, update its text with new text. If the new message is an empty string, the message is deleted. Parameters: token - token of the user editing the message message_id - message id of the message being edited message - update message Returns {} InputError when: Length of the message is over than 1000 characters Message_id refers to a deleted message AccessError when NONE of these are true: Message with message_id was sent by auth user making request Auth user is an owner of the channel or Dreams owner """ complete = False with open("data.json") as json_file: data = load(json_file) # Decode u_id from token if valid user = token_check(token) # Edited Message updated_msg = message # InputError raised when message over 1000 chars if len(updated_msg) > 1000: raise InputError(description="Message is longer than 1000 characters") # If updated message is an empty string, call message_remove_v1 if len(updated_msg) == 0: message_remove_v1(token, message_id) return # Loop through channel data to look for message_id for channel in data["channels"]: # Loop through messages of channel for message in channel["messages"]: # if message_id is found if message["message_id"] == message_id: # check u_id belongs message sender or channel owner # Assumption(Dreams owner is added to owner_members) if message["u_id"] == user["u_id"] or user["u_id"] in channel[ "owner_members"]: # Update to edited message # (Assumption) Timestamp is not changed message["message"] = updated_msg complete = True else: raise AccessError( description= "user is not the sender of message or channel owner") # The message wasn"t found in channel # Loop through the DM messages and check if it is there for dm in data["dms"]: # Loop through messages of dms for dm_message in dm["messages"]: # If message_id is found if dm_message["message_id"] == message_id: # Check u_id belongs sender if dm_message["u_id"] == user["u_id"]: # Update to edited message # (Assumption) DM creator should not be able to edit/remove messages of others dm_message["message"] = updated_msg complete = True else: raise AccessError( description="user is not the sender of message") if complete != True: # Did not find message_id raise InputError( description="Message does not exist/Message no longer exists") with open("data.json", "w") as json_file: dump(data, json_file, indent=4) return {}