def message_remove(token, message_id): """ Given a message_id for a message, this message is removed from the channel. """ u_id = get_current_user(token) message_location = get_message_location(message_id) channel_id = message_location["channel_id"] channel_data = get_channel_data(channel_id) if u_id not in channel_data['member_ids']: raise AccessError( description="User must be a member of the channel they are trying" + " to access.") # Find the message to be deleted. At this point # The message definitely exists and the user is definitely a member of the channel # it exists in. for message in channel_data["messages"]: if message['message_id'] == message_id: if message["u_id"] != u_id and get_permission_dict(u_id).get( 'permission_id') != 1: raise AccessError( description="Authorised user did not send the message " + "and is not a server/channel owner.") else: remove_message(message_id) return {}
def standup_send(token, channel_id, message): """ Add a message to standup queue """ # If token is valid, take u_id which is used to look through users u_id = database.get_current_user(token) # Check if user is member of channel that message is within # if not then raise an AccessError channel_data = database.get_channel_data(channel_id) if u_id not in channel_data['member_ids']: raise error.AccessError( description="You are not a member of this channel") # Check if message if more than 1000 characters long and raise InputError if that is the case if len(message) > 1000: raise error.InputError( description="The message entered is more than 1000 characters long" ) # Check if standup is currently active in channel, raise InputError if not if standup_active(token, channel_id)['is_active'] is False: raise error.InputError( description="There are no standups active in this channel") # Format message to "handle_str: message" handle_str = database.get_user_data(u_id)['handle_str'] string = handle_str + ": " + message # Now add string to the appropriate list in queues QUEUES[str(channel_id)].append(string) return {}
def message_unpin(token, message_id): """ Given a message within a channel, remove it's mark as unpinned. """ u_id = get_current_user(token) message_location = get_message_location(message_id) message_file = get_message(message_id) ################### START ERROR CHECKS ############################ channel_data = get_channel_data(message_location['channel_id']) check = next((i for i in channel_data['member_ids'] if i == u_id), False) if check is False: raise AccessError(description='The authorised user is not ' + 'a member of the channel that the message is within') if u_id not in channel_data['owner_ids']: raise AccessError(description='The authorised user is not an owner') ##################### END ERROR CHECKS ######################## if message_file['is_pinned'] is False: raise InputError( description='Message with ID message_id is already unpinned') else: message_file['is_pinned'] = False return {}
def channels_create(token, name, is_public): """ Create a channel using the given parameters """ # Check if name is more than 20 characters long and return InputError if this is the case if len(name) > 20: raise error.InputError( description="The name you entered is more than 20 characters long") # Generate a channel_id for the new channel # Simply done in order of time of creation (1..) # Generation of channel_id will be done in this way as long as ability to delete channels # remains unimplemented num_channels = len(database.get_channels()) channel_id = num_channels + 1 # Use database.set_channel to create channel in the database channel = {'channel_id': channel_id, 'name': name} database.set_channel(channel) channel_data = database.get_channel_data(channel_id) channel_data['is_public'] = is_public database.set_channel_data(channel_data) # User who creates the channel joins it automatically channel_join(token, channel_id) return {'channel_id': channel_id}
def is_user_channel_member(channel_id, u_id): """ Helper function to check if a user is part of a channel """ for selected_id in database.get_channel_data(channel_id)["member_ids"]: if selected_id == u_id: return True return False
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 """ if database.get_current_user(token) not in database.get_channel_data(channel_id)['member_ids']: raise error.AccessError(description="""Authorised user is not a member of channel with that channel_id.""") if u_id in database.get_channel_data(channel_id).get('member_ids'): raise error.InputError(description="This user is already a part of the channel.") new_channel_data = database.get_channel_data(channel_id) new_channel_data['member_ids'].append(u_id) if database.get_permission_dict(u_id).get('permission_id') == 1: new_channel_data['owner_ids'].append(u_id) database.set_channel_data(new_channel_data) return {}
def call_bot(channel_id): """ Bot is registered if not a user. Bot is logged in if not logged in. Bot joins the channel if not a member of the channel. """ if database.get_user_data(-1) is None: register_bot() elif database.get_token_from_user(-1) is None: login_bot() channel_data = database.get_channel_data(channel_id) if -1 not in channel_data['member_ids']: channel.channel_join(BOT_TOKEN, channel_id) return {"bot_id": -1}
def search(token, query_str): """ returns all messages that user is in with certain quesry string """ if query_str == "": raise error.InputError(description="search received an empty query string") # user_channels = {'channels': [], []} user_channels = channels.channels_list(token) message_list = [] for channel in user_channels['channels']: channel_data = database.get_channel_data(channel['channel_id']) for message in channel_data['messages']: if query_str in message['message']: message_list.append(message) message_list.sort(key=itemgetter('time_created'), reverse=True) return {"messages" : message_list}
def channels_list(token): """ Returns {channels}, where channels is a list of channels that the user is part of. i.e. {'channels': [{channel_id, name}, {channel_id, name}]} """ u_id = database.get_current_user(token) output = {'channels': []} # obtain channels so that I can see lists of members # insert channel into the output list if user is a member for channel in database.get_channels(): channeldata = database.get_channel_data(channel['channel_id']) if u_id in channeldata['member_ids']: output['channels'].append(channel) return output
def wrapper_func(*args, **kwargs): """ Wrapper function """ try: cidarg_index = argspec.args.index("channel_id") target_channel = database.get_channel_data(args[cidarg_index]) # Check the u_id is valid. if target_channel is None: # u_id is invalid raise error.InputError( description="Channel ID is not a valid channel") else: return func(*args, **kwargs) except ValueError: print("\033[93m" + "WARNING: c_id arg not found - running function " + f"{func.__name__} without c_id check." + "\033[0m") return func(*args, **kwargs)
def channel_addowner(token, channel_id, u_id): """ This function intakes the token of current authorised (auth) user, channel_id and a user u_id It then adds the user u_id as an owner of the channel, as long as the current auth user is an owner of slackr/channel """ # Check if token is valid and raise AccessError if not curr_id = database.get_current_user(token) # gets current channel data curr_channel = database.get_channel_data(channel_id) # gets the permissions of current user from database user_perms = database.get_permission_dict(curr_id) # check if user u_id is already an owner of the channel and raise InputError if so # also checks to see if current auth user is a owner of channel # a counter to check if user is a member of the channel is_curr_owner = False for owner_id in curr_channel["owner_ids"]: if u_id == owner_id: raise error.InputError(description="user u_id is already an owner of this channel") # checks if curr_id is an owner of channel if curr_id == owner_id: is_curr_owner = True # checks if the user u_id is a member of the channel already is_u_member = False for member_id in curr_channel["member_ids"]: if u_id == member_id: is_u_member = True # if the auth user is an owner of the slackr, allow him to add u_id as owner of channel if is_u_member is True: if user_perms["permission_id"] == 1: # adds the user into channel_owner curr_channel["owner_ids"].append(u_id) # if the auth user is an owner of the channel, allow him to add u_id as owner of channel elif is_curr_owner is True: # adds the user into channel_owner curr_channel["owner_ids"].append(u_id) # else the auth user is not an owner and thus cannot use addowner else: raise error.AccessError(description="""current user is not an owner of the channel, or of the slackr""")
def channel_details(token, channel_id): """ This function is given a valid token and channel_id. It then returns the name, owners and members of the channel """ # Check if token is valid and raise AccessError if not curr_id = database.get_current_user(token) # check if user is a member of channel with channel_ID and return AccessError if not if is_user_channel_member(channel_id, curr_id) is False: raise error.AccessError(description="""You must be a member of the channel to view its details.""") # now we return the name, owners and members of the channel details = {"name": "", "owner_members": [], "all_members": []} # for owner/all_members we need a list of dictionaries containing u_id, first name and last name # {"u_id": [], "name_first": "", "name_last": ""} channel = database.get_channel(channel_id) members = database.get_channel_data(channel_id) details["name"] = channel["name"] for user_id in members["owner_ids"]: owner_id = user_id user_data = database.get_user_data(owner_id) name_first = user_data["name_first"] name_last = user_data["name_last"] profile_img_url = user_data['profile_img_url'] details["owner_members"].append({"u_id": owner_id, "name_first": name_first, "name_last": name_last, "profile_img_url": profile_img_url}) for user_id in members["member_ids"]: member_id = user_id user_data = database.get_user_data(member_id) name_first = user_data["name_first"] name_last = user_data["name_last"] profile_img_url = user_data['profile_img_url'] details["all_members"].append({"u_id": member_id, "name_first": name_first, "name_last": name_last, "profile_img_url": profile_img_url}) return details
def remove_user(token, u_id): """ Given a u_id, remove the user from the Slackr. """ # we get the current user data terminator = database.get_current_user(token) # Raise AccessError if user is not an owner of the Slackr terminator_perm = database.get_permission_dict(terminator) if terminator_perm['permission_id'] != 1: raise error.AccessError(description="""Action cannot be performed because you are not a Slackr owner.""") # Do a soft remove # they stay a part of everything, but they are removed from owner/memberID # in channels, and they are also banned from ever logging in again. # we get the token of the user to be removed # introduce a new permission ID 66: # terminated and set the user to be removed to perm_id 66: terminated terminated_id = 66 database.set_permissions(u_id, terminated_id) # remove the user from every channel's member_id and owner_id #first we call a list of every channel all_channels = database.get_channels() # we then get the data for each channel for each_channel in all_channels: channel_data = database.get_channel_data(each_channel["channel_id"]) # remove user u_id from owner_ids for owner_id in channel_data['owner_ids']: if u_id == owner_id: channel.channel_removeowner(token, channel_data["channel_id"], u_id) # remove user u_id from member_ids if u_id in channel_data['member_ids']: channel_data['member_ids'].remove(u_id) database.set_channel_data(channel_data) # finally we log the user out of the session (invalidating terminated token) terminated_token = database.get_token_from_user(u_id) if terminated_token is not None: auth.auth_logout(terminated_token)
def user_in_message_channel(message_id, u_id): """ A helper function to check whether the user is in channel with channel_id provided Returns True if passes check - otherwise raises InputError. """ message_location = get_message_location(message_id) channel_id = message_location["channel_id"] channel_data = get_channel_data(channel_id) check = False for user in channel_data["member_ids"]: if user == u_id: check = True if check is False: raise InputError( description='message_id is not a valid message within' + 'a channel that the authorised user has joined') else: return check
def channel_removeowner(token, channel_id, u_id): """ This function intakes the token of current authorised (auth) user, channel_id and a user u_id It then removes the user u_id as an owner of the channel, as long as the current auth user is an owner of slackr/channel and the user u_id is an owner """ # Check if token is valid and raise AccessError if not curr_id = database.get_current_user(token) # gets current channel data curr_channel = database.get_channel_data(channel_id) # gets the permissions of current user from database user_perms = database.get_permission_dict(curr_id) u_id_permission = database.get_permission_dict(u_id) if u_id_permission["permission_id"] == 1: raise error.AccessError(description="user being removed is the owner of the slackr") # checks if u_id is not an owner of the channel # also checks if current auth user is an owner of the channel is_u_owner = False is_curr_owner = False for owner_id in curr_channel["owner_ids"]: if u_id == owner_id: is_u_owner = True if curr_id == owner_id: is_curr_owner = True if is_u_owner is False: raise error.InputError(description="user being removed is not an owner of the channel") # if the auth user is owner of slackr, allows him to remove u_id as owner if user_perms["permission_id"] == 1: # removes the user from channel_owner curr_channel["owner_ids"].remove(u_id) # if the auth user is an owner of the channel, allow him to remove u_id as owner of channel elif is_curr_owner is True: # adds the user into channel_owner curr_channel["owner_ids"].remove(u_id) # else the auth user is not an owner and thus cannot use addowner else: raise error.AccessError(description="""Authorised user user is not an owner of the channel, or of the slackr""")
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. """ u_id = get_current_user(token) message_location = get_message_location(message_id) # if message is longer than 1000 an Inputerror should be raised. if len(message) > 1000: raise InputError( description= 'Message is more than 1000 characters or try to send an empty message' ) channel_id = message_location["channel_id"] channel_data = get_channel_data(channel_id) if u_id not in channel_data['member_ids']: raise AccessError( description="User must be a member of the channel they are trying" + " to access.") # Find the message to be deleted (assume it definitely exists) msg_to_edit = next(msg for msg in channel_data['messages'] if msg['message_id'] == message_id) if msg_to_edit['u_id'] != u_id and get_permission_dict( u_id)['permission_id'] != 1: raise AccessError( description="Authorised user did not send the message " + "and is not a server/channel owner.") if message == '': remove_message(message_id) else: msg_to_edit['message'] = message set_message(channel_id, msg_to_edit) return {}
def channel_join(token, channel_id): """ this function is passed a valid token and channel_id. It adds the user associated with the token into the channel, unless the channel is private """ # Check if token is valid and raise AccessError if not curr_id = database.get_current_user(token) # gets current channel data curr_channel = database.get_channel_data(channel_id) # gets the permissions of current user from database user_perms = database.get_permission_dict(curr_id) # checks if user is already a part of channel for user_id in curr_channel["member_ids"]: if curr_id == user_id: raise error.InputError(description="user is joining a channel user is already in") # this checks if the channel is empty (or new) in this case we make the new member an owner. if curr_channel["member_ids"] == []: # adds the user into channel_member curr_channel["member_ids"].append(curr_id) # adds the user into channel_owner curr_channel["owner_ids"].append(curr_id) # this checks if the user is an owner of the slacker # if they are they are given owner privelages in the channel # else they are a member elif user_perms["permission_id"] == 1: # adds the user into channel_member curr_channel["member_ids"].append(curr_id) # adds the user into channel_owner curr_channel["owner_ids"].append(curr_id) elif curr_channel["is_public"] is True: # adds the user into the channel_member curr_channel["member_ids"].append(curr_id) elif curr_channel["is_public"] is False: raise error.InputError(description="""channel_join recieved a channel_id for a private channel""")
def channel_leave(token, channel_id): """ This function takes in a token and channel ID. if both are valid, it will then remove the member from channel """ # Check if token is valid and raise AccessError if not curr_id = database.get_current_user(token) # check if user is a member of channel with channel_ID and return AccessError if not user_channel = is_user_channel_member(channel_id, curr_id) if user_channel is False: raise error.AccessError(description="user is not a member of this channel") # remove user with u_id from the channel (from member_ids) curr_channel = database.get_channel_data(channel_id) curr_channel["member_ids"].remove(curr_id) # if user is an owner it removes them as an owner as well for owner_id in curr_channel["owner_ids"]: if owner_id == curr_id: curr_channel["owner_ids"].remove(curr_id) database.set_channel_data(curr_channel)
def channel_messages(token, channel_id, start): """ Retrieve a set of 50 or less messages from the channel. Returns a {messages, start, end} dictionary. """ # Check if token is valid and raise AccessError if not curr_id = database.get_current_user(token) # check if user is a member of channel with channel_ID and return AccessError if not if is_user_channel_member(channel_id, curr_id) is False: raise error.AccessError(description="user is not a member of this channel") #get channel data curr_channel = database.get_channel_data(channel_id) # find the length of messages messages_length = len(curr_channel["messages"]) # if start is after the oldest message in messages InputError is raised # if messages is called and start is 0 on an empty channel, it returns an empty channel. # if start is after the oldest message in messages InputError is raised if messages_length <= start and (messages_length != 0 or start > 0): raise error.InputError(description="""The start value selected is past the oldest message in the list""") if messages_length == 0 and start == 0: return {"messages": [], "start": start, "end": -1} # get the list of dictionaries 'message' curr_messages = curr_channel["messages"] messages_returned = [] end = start + 50 num_msgs_to_check = messages_length - start # If end is larger than the total no. of messages, # the function will print till end and return -1 if num_msgs_to_check < 50: counter = 0 while counter < num_msgs_to_check: target_message_index = start + counter messages_returned.append(curr_messages[target_message_index]) counter += 1 end = -1 # else if end is within total no of messages, # function will print 50 messaages from start and return start + 50 else: # loop to add each message to return up till 50 messages is returned counter = 0 while counter < 50: target_message_index = start + counter messages_returned.append(curr_messages[target_message_index]) counter += 1 for msg in messages_returned: for react in msg['reacts']: react['is_this_user_reacted'] = curr_id in react['u_ids'] return {"messages": messages_returned, "start": start, "end": end}