def channel_removeowner(token, channel_id, u_id): """ Remove user with user ID 'u_id' as an owner of this channel. Parameters: token (str): Authorisation hash for the user channel_id (int): Channels' channel ID u_id (int): Users' user ID Returns: {} (dict): Empty dictionary """ if not isinstance(token, str): raise AccessError('Token is invalid') if not valid_channel_id(token, channel_id): raise InputError('Channel ID is not a valid channel') owner_id = get_user_id(token) channel_data = get_channel(channel_id) if not u_id in channel_data["owner_members"]: raise InputError('User is not an owner of the channel') list_of_auth_users = data["permissions"][0]["users"] if owner_id not in channel_data["owner_members"] + list_of_auth_users: raise AccessError( 'User is not an owner of the channel or an owner of the flockr') channel_data["owner_members"].remove(u_id) channel_data["all_members"].append(u_id) channel_data = get_channel(channel_id) return {}
def channel_leave(token, channel_id): """ Given a channel ID, the user is removed as a member of this channel. Parameters: token (str): Authorisation hash for the user channel_id (int): Channels' channel ID Returns: {} (dict): Empty dictionary """ if not isinstance(token, str): raise AccessError('Token is invalid') if not valid_channel_id(token, channel_id): raise InputError('Channel ID is not a valid channel') channel_data = get_channel(channel_id) user_id = get_user_id(token) result_access = user_id in channel_data["all_members"] + channel_data["owner_members"] and \ channel_data["channel_id"] == channel_id if not result_access: raise AccessError('User is not a member of the channel') # If member of channel wants to leave we remove it. Otherwise we remove a owner member. if user_id in channel_data["all_members"]: channel_data["all_members"].remove(user_id) else: # Remove user_id for owner. channel_data["owner_members"].remove(user_id) return {}
def channel_join(token, channel_id): """ Given a channel ID of a channel that the authorised user can join, adds them to the channel. Parameters: token (str): Authorisation hash for the user channel_id (int): Channels' channel ID Returns: {} (dict): Empty dictionary """ if not isinstance(token, str): raise AccessError('Token is invalid') # Check Token exists. if not valid_channel_id(token, channel_id): raise InputError('Channel ID is not a valid channel') u_id = get_user_id(token) channel_data = get_channel(channel_id) if verify_user_member(channel_id, u_id): raise InputError("User already exists in channel.") list_of_auth_users = data["permissions"][0]["users"] # If channel not public and user not authorised. if not channel_data["public"] and (u_id not in list_of_auth_users): raise AccessError("Channel is private and user is not a global owner") channel_data["all_members"].append(u_id) return {}
def standup_active(token, channel_id): """ For a given channel, return whether a standup is active in it, and what time the standup finishes. If no standup is active, then time_finish returns None. Parameters: token (str): Authorisation hash for user channel_id (int): Channels' channel ID Returns: is_active (bool): Whether or not a standup is active time_finish (int): Time standup finishes - Unix timestamp """ if not isinstance(token, str): raise AccessError('Token is invalid') if not auth.check_token_exists(token): raise AccessError("User does not exist.") if not valid_channel_id(token, channel_id): raise InputError('Channel ID is not a valid channel') channel_data = get_channel(channel_id) return { 'is_active': channel_data["is_active"], 'time_finish': channel_data["time_finish"], }
def standup_send(token, channel_id, message): """ Send a message to get buffered in the standup queue, assuming a standup is currently active. Parameters: token (str): Authorisation hash for user channel_id (int): Channels' channel ID message (str): Message from userz Returns: {} (dict): Empty dictionary """ if not isinstance(token, str): raise AccessError('Token is invalid') if auth.check_token_exists(token): auth_user = get_user_id(token) else: raise AccessError("User does not exist.") if not valid_channel_id(token, channel_id): raise InputError('Channel ID is not a valid channel') if len(message) > 1000: raise InputError("The message is longer than 1000 characters") channel_data = get_channel(channel_id) if channel_data["is_active"] is False: raise InputError( 'An active standup is not currently running in this channel') auth_id = get_user_id(token) if not verify_user_member(channel_id, auth_id): raise AccessError('Authorised user is not a member of the channel') usr = get_user_profile(auth_user) handle = usr["handle_str"] global msg msg += f"{handle}: {message}\n" return {}
def standup_start(token, channel_id, length): """ For a given channel, start the standup period whereby for the next "length" seconds if someone calls "standup_send" with a message, it is buffered during the X second window then at the end of the X second window a message will be added to the message queue in the channel from the user who started the standup. X is an integer that denotes the number of seconds that the standup occurs for. Parameters: token (str): Authorisation hash for user channel_id (int): Channels' channel ID length (int): Number of seconds Returns: time_finish (int): Time standup finishes - Unix timestamp """ if not isinstance(token, str): raise AccessError('Token is invalid') if not auth.check_token_exists(token): raise AccessError("User does not exist.") if not valid_channel_id(token, channel_id): raise InputError('Channel ID is not a valid channel') channel_data = get_channel(channel_id) if channel_data["is_active"]: raise InputError( 'An active standup is currently running in this channel') else: channel_data["is_active"] = True current_time = int(math.floor(time.time())) time_finish = current_time + length channel_data["time_finish"] = time_finish t = threading.Timer(length, reset_and_delay_messages, [channel_data, token]) t.start() return {'time_finish': time_finish}
def message_sendlater(token, channel_id, message, time_sent): """ Send a message from the authorised_user to the channel specified by channel_id automatically at a specified time in the future. Parameters: token (str): Authorisation hash for user channel_id (int): Channels' channel ID message (str): Message from user time_sent (int): Unix timestamp Returns: message_id (int): Messages' message ID """ if not isinstance(token, str): raise AccessError('Token is invalid') if len(message) > 1000: raise InputError("The message is longer than 1000 characters") if not valid_channel_id(token, channel_id): raise InputError('Channel ID is not a valid channel') auth_id = get_user_id(token) if not verify_user_member(channel_id, auth_id): raise AccessError('User is not a member of the channel') current_date = datetime.today() current_unix_time = time.mktime(current_date.timetuple()) time_difference = time_sent - current_unix_time if time_difference < 0: raise InputError('Time specified is a time in the past') with concurrent.futures.ThreadPoolExecutor() as executor: executor_instance = executor.submit(message_send, token, channel_id, message, time_difference) msg_result = executor_instance.result() return {"message_id": msg_result["message_id"]}
def channel_invite(token, channel_id, u_id): """ Invites a user with ID 'u_id' to join a channel with ID 'channel_id'. Once invited, the user is added to the channel immediately. Parameters: token (str): Authorisation hash for user channel_id (int): Channels' channel ID u_id (int): Users' user ID Returns: {} (dict): Empty dictionary """ #step 0: error testing if not isinstance(token, str): raise AccessError('Token is invalid') if not valid_channel_id(token, channel_id): raise InputError('Channel ID is not a valid channel') # Check user id exists. if not check_uid_exists(u_id): raise InputError('User ID does not refer to a valid user') # Check auth user exists. # if check_user_exists(token): auth_id = get_user_id(token) if not verify_user_member(channel_id, auth_id): raise AccessError('Authorised user is not a member of the channel') channel_data = get_channel(channel_id) # Check for user exists. if u_id in channel_data["all_members"] + channel_data["owner_members"]: raise InputError("User already exists!") channel_data["all_members"].append(u_id) return {}
def channel_details(token, channel_id): """ Given a channel with ID 'channel_id' that the authorised user is a part of, provide basic details about the channel. Parameters: token (str): Authorisation hash for the user channel_id (int): Channels' channel ID Returns: {} (dict): Empty dictionary """ #step 0: error testing if not isinstance(token, str): raise AccessError('Token is invalid') if not valid_channel_id(token, channel_id): raise InputError('Channel ID is not a valid channel') channel_data = get_channel(channel_id) auth_user = get_user_id(token) if auth_user not in channel_data["owner_members"] + channel_data[ "all_members"]: raise AccessError('User is not a member of the channel') owners_list = list(map(list_members, channel_data["owner_members"])) members_list = owners_list + list( map(list_members, channel_data["all_members"])) return { "name": channel_data["name"], "owner_members": owners_list, "all_members": members_list, # ensure that profile_img_url is also returned }
def channel_messages(token, channel_id, start): """ Given a channel with ID 'channel_id' that the authorised user is a 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. Parameters: token (str): Authorisation hash for the user channel_id (int): Channels' channel ID start (int): start index of messages to return Returns: Dictionary containing: messages (list): List of dictionaries containing messages and their basic details start (int): Start index of messages to return end (int): End index of messages to return """ if not isinstance(token, str): raise AccessError('Token is invalid') if not valid_channel_id(token, channel_id): raise InputError('Channel ID is not a valid channel') # Case for invalid start if start < 0: raise InputError("Invalid start index provided") channel_msgs = list(filter(lambda msg_list: msg_list["channel_id"]\ == channel_id, data["messages"])) end = start + 50 # Doesn't return an error if splice end index is too high. channel_msgs_spliced = channel_msgs[start:end] # if start of messages is greater than total number of messages in the # channel, then raise InputError if start > len(channel_msgs): raise InputError("Start greater than channel messages length.") if channel_msgs != []: min_time_found = min( list(map(lambda x: x["time_created"], channel_msgs))) else: return {"messages": [], "start": start, "end": -1} # if channel_msgs_spliced is not None: min_time_in_spliced = min( list(map(lambda x: x["time_created"], channel_msgs_spliced))) if min_time_found == min_time_in_spliced: end = -1 # Sorted in descending order (biggest larger time means more recent in UNIX) # and key is sorting by time_created. # channel_msgs_spliced.sort(reverse=False, key=lambda x: x.get("time_created")) channel_msgs_spliced.sort(reverse=True, key=lambda x: x.get("time_created")) user_id = get_user_id(token) for msg in channel_msgs_spliced: if user_id in msg["reacts"][0]["u_ids"]: msg["reacts"][0]["is_this_user_reacted"] = True else: msg["reacts"][0]["is_this_user_reacted"] = False return { 'messages': channel_msgs_spliced, 'start': start, 'end': end, }