Beispiel #1
0
def channel_leave_v1(token, channel_id):
    """Given channel id, removes an authorised user from that channel.

    Arguments:
        token (string)              - token of an authenticated user
        channel_id (integer)        - id of channel to leave

    Exceptions:
        InputError  - Occurs when channel_id is not a valid channel
                    - Occurs when the last owner tries to leave
        AccessError - Occurs when token refers to a user who is not
                      a member of the channel
                    - Occurs when token is not a valid

    Return value:
        {}
    """

    # Load .json data store
    data_store = getData()

    # Check validity of channel_id
    ch_index = check_validity(data_store["channels"], channel_id, "channel_id",
                              INVALID_CHANNEL_ID)
    ch_src = data_store["channels"][ch_index]

    # Check validity of token
    u_index = findUser(token) - 1
    u_src = data_store["users"][u_index]

    # Check user is actually a member
    if not is_member(ch_src, u_src):
        raise AccessError(description="user is not a member of this channel.")

    # Check not last owner
    owner = is_owner(ch_src, u_src)
    if owner and len(ch_src["owner_members"]) == 1:
        raise InputError(description="last owner cannot leave the channel.")

    # Remove user from *_members
    user_remove = {
        "u_id": u_src["u_id"],
        "name_first": u_src["name_first"],
        "name_last": u_src["name_last"],
        "email": u_src["email"],
        "handle_str": u_src["handle_str"],
        "profile_img_url": u_src["profile_img_url"],
    }
    if owner:
        ch_src["owner_members"].remove(user_remove)
    ch_src["all_members"].remove(user_remove)

    append_user_stats(findUser(token), data_store)
    append_dream_stats(findUser(token), data_store)

    writeData(data_store)

    return {}
def dm_remove_v1(user_token, dm_id):
    '''
    the function is given a token and a dm_id. we need to user the parameters to
    remove the exactly dm with the dm_id. also, we need to check the validity of the 
    paremeters. 
    Arguments:
        user_token (string)    - some encoded information about one auth user
        dm_id (int)    -  the id of the dm needed removing
    ...

    Exceptions:
        AccessError - Occurs when the token is not a valid token
        InputError - Occurs when dm_id is not valid
        AccessError - Occurs when the auth_user is not the owner of the dm

    Return Value:
        Returns {}
    '''


    database = {}
    with open(file_address, "r") as f:
        database = json.load(f)
    
    #get the required value
    kicker_id = findUser(user_token)

    #check if the input is valid
    if dm_id > database['dms'][len(database['dms']) - 1]['dm_id'] or database['dms'][dm_id - 1]['dm_id'] == -1:
        raise InputError(description="The dm_id is not valid.")

    
    if kicker_id != database['dms'][dm_id - 1]['dm_owner']:
        raise AccessError(description="The one who wants to remove the dm_id does not have right.")

    for msg_id in database['dms'][dm_id - 1]['message_ids']:
        for message in database['messages']:
            if message['message_id'] == msg_id:
                msg = message
                dm = get_dm_details(msg, database)
                dm_key = database['dms'].index(dm)
                database['dms'][dm_key]['message_ids'].remove(msg['message_id'])
                database['messages'].remove(msg)

    #remove the dm with some specific dm_id
    database['dms'][dm_id - 1]['dm_id'] = -1

    append_user_stats(findUser(user_token), database)
    for u_id in database['dms'][dm_id - 1]['dm_members']:
            append_user_stats(u_id, database)
    append_dream_stats(findUser(user_token), database) 

    #put the data back to the data file
    with open(file_address, "w") as f:
        json.dump(database, f)

    return {}
def message_edit_v2(token, message_id, message):
    '''
    Arguments:
        token (string) - the token of the user who wants to create a channel
        message_id (int) - the id of the message being edited
        message (string) - the new message

    Exceptions:
        InputError - Message is more than 1000 characters or the message id refers to a deleted message
        AccessError - The authorised user has not joined the channel they are trying to post to

    Return value:
        Returns {}
    '''

    # get data
    data = getData()

    # get id
    auth_user_id = findUser(token)

    # Checks that the length is not above 1000 characters
    if len(message) > 1000:
        raise InputError(
            description="Message must be less than 1000 characters")

    # Finds the message
    msg = get_message(message_id, data)

    if msg == -1:
        raise AccessError(description="Message does not exist")

    # Checks the message was sent by the user requesting to edit it or
    # the user is a channel owner
    if msg['u_id'] != auth_user_id and get_user_details(
            auth_user_id, data)['permission_id'] != 1:
        raise AccessError(
            description=
            "User requesting edit did not post message or not channel owner")

    # Delete the message if message is empty, updates the message if it isn't
    if message == '':
        remove_msg_from_channel_or_dm(data, msg)
    else:
        msg_key = data['messages'].index(msg)
        data['messages'][msg_key]['message'] = message

    # Sends notification
    send_msg_notification(data, token, message, msg['channel_id'],
                          msg['dm_id'], False, -1)

    append_user_stats(findUser(token), data)
    append_dream_stats(findUser(token), data)

    writeData(data)

    return {}
def message_senddm_v1(token, dm_id, message):
    '''
    Arguments:
        token (string) - the token of the user who wants to create a channel
        dm_id (int) - the id of the dm the message is being sent to
        message (string) - the message being sent

    Exceptions:
        InputError - Message is more than 1000 characters
        AccessError - The authorised user has not joined the dm they are trying to post to

    Return value:
        Returns {'message_id': message_id}
    '''

    # get data
    data = getData()

    # get id
    auth_user_id = findUser(token)

    # Checks the message is not more than 1000 characters
    if len(message) > 1000:
        raise InputError(
            description="Message must be less than 1000 characters")

    # Checks the auth_user_id is part of the dm
    dm_members = get_dm_members(dm_id, data)
    if auth_user_id not in dm_members:
        raise AccessError(description="User not in DM being posted to")

    # Get new message id
    new_message_id = get_new_message_id(data)

    # Adds message to data dictionary
    add_data(data, new_message_id, auth_user_id, -1, dm_id, message,
             int(time.time()), [], False)

    # Adds message to dm
    for dm in data['dms']:
        if dm_id == dm['dm_id']:
            dm['message_ids'].append(new_message_id)

    # Sends notification
    send_msg_notification(data, token, message, -1, dm_id, False, -1)

    append_user_stats(findUser(token), data)
    append_dream_stats(findUser(token), data)

    # Adds message to dm and makes notification
    writeData(data)

    return {
        'message_id': new_message_id,
    }
Beispiel #5
0
def channel_join_v2(token, channel_id):
    """Given channel id, adds an authorised user to that channel.

    Arguments:
        token (string)              - token of an authenticated user
        channel_id (integer)        - id of channel to be joined

    Exceptions:
        InputError  - Occurs when channel_id is not a valid channel
        AccessError - Occurs when channel_id refers to private channel
                      and user is not a global owner
                    - Occurs when token is not a valid id

    Return value:
        {}
    """

    # Load .json data store
    data_store = getData()

    # Check validity of channel_id
    ch_index = check_validity(data_store["channels"], channel_id, "channel_id",
                              INVALID_CHANNEL_ID)
    ch_src = data_store["channels"][ch_index]

    # Check validity of token
    u_id = findUser(token)
    for user in data_store["users"]:
        if user["u_id"] == u_id:
            u_src = user

    # Check permissions of channel and user
    u_permission = u_src["permission_id"]

    if not ch_src["is_public"] and u_permission != 1:
        raise AccessError(description="Can't join a private channel")

    # Add user to the channel
    user_add = {
        "u_id": u_src["u_id"],
        "name_first": u_src["name_first"],
        "name_last": u_src["name_last"],
        "email": u_src["email"],
        "handle_str": u_src["handle_str"],
        "profile_img_url": u_src["profile_img_url"],
    }
    ch_src["all_members"].append(user_add)

    append_user_stats(findUser(token), data_store)
    append_dream_stats(findUser(token), data_store)

    writeData(data_store)

    return {}
def dm_leave_v1(user_token, dm_id):
    '''
    The function is given the token who is gonna leave the dm without destroy the dm.
    Arguments:
        user_token (string)    - some encoded information about one auth user
        dm_id (int)    -  the id of the dm needed removing
    ...

    Exceptions:
        AccessError - Occurs when the token is not a valid token
        InputError - Occurs when dm_id is not valid
        AccessError - Occurs when the auth_user is not the member of the dm

    Return Value:
        Returns {}
    '''
    database = {}
    with open(file_address, "r") as f:
        database = json.load(f)

    #get the required value
    auth_user_id = findUser(user_token)
    
    #check if the input is valid
    if dm_id > database['dms'][-1]['dm_id'] or database['dms'][dm_id - 1]['dm_id'] == -1:
        raise InputError(description="The dm_id is not valid.")

    
    if auth_user_id not in database['dms'][dm_id - 1]['dm_members']:
        raise AccessError(description="The one who wants to leave the dm is not in the dm.")

    #remove the dm with some specific dm_id

    pos = database['dms'][dm_id - 1]['dm_members'].index(auth_user_id, 0, len(database['dms'][dm_id - 1]['dm_members']))
    
    database['dms'][dm_id - 1]['dm_members'].pop(pos)

    if len(database['dms'][dm_id - 1]['dm_members']) == 0:
        database['dms'][dm_id - 1]['dm_id'] = -1
    elif database['dms'][dm_id - 1]['dm_owner'] == auth_user_id:
        database['dms'][dm_id - 1]['dm_owner'] = database['dms'][dm_id - 1]['dm_members'][0]
 
    append_user_stats(findUser(user_token), database)
    append_dream_stats(findUser(user_token), database)    
       
    #put the data back to the data file
    with open(file_address, "w") as f:
        json.dump(database, f)
        
    return {}
def message_remove_v1(token, message_id):
    '''
    Arguments:
        token (string) - the token of the user who wants to create a channel
        message_id (int) - the id of the message being removed

    Exceptions:
        InputError - Message id no longer exists
        AccessError - User did not send message and is not an owner of the channel/dm or dreams

    Return value:
        Returns {}
    '''

    # get data
    data = getData()

    # get id
    auth_user_id = findUser(token)

    # Checks the message was sent by the user requesting to edit it or
    # the user is a channel owner
    msg = get_message(message_id, data)

    if msg == -1:
        raise AccessError(description="Message does not exist")

    chan_owners = []
    if msg['channel_id'] != -1:
        chan = get_channel_details(msg, data)
        chan_owners = get_channel_owners(chan['channel_id'], data)

    if msg['u_id'] != auth_user_id and get_user_details(
            auth_user_id,
            data)['permission_id'] != 1 and auth_user_id not in chan_owners:
        raise AccessError(
            description=
            "User requesting edit did not post message or not channel/DREAMS owner"
        )

    # Remove from channels/dms list
    remove_msg_from_channel_or_dm(data, msg)

    append_user_stats(findUser(token), data)
    append_dream_stats(findUser(token), data)

    writeData(data)

    return {}
def dm_invite_v1(user_token, dm_id, u_id):
    '''
    the function is given a invitor token, a dm id, and the invited's id.
    the invited id should be added into the member list in the dm.
    Arguments:
        user_token (string)    - some encoded information about one auth user
        dm_id (int)    -  the id of the dm needed removing
        u_id (int)    -  the id of the user been invited
    ...

    Exceptions:
        AccessError - Occurs when the token is not a valid token
        InputError - Occurs when dm_id is not valid
        InputsError - Occurs when the u_id is not valid
        AccessError - Occurs when the auth_user is not the member of the dm

    Return Value:
        Returns {}
    '''
    #get the value
    invited_id = u_id
    database = {}
    with open(file_address, "r") as f:
        database = json.load(f)
    
    #get the required value
    invitor_id = findUser(user_token)
    
    #check if the dm id valid
    if dm_id > database['dms'][len(database['dms']) - 1]['dm_id'] or database['dms'][dm_id - 1]['dm_id'] == -1:
        raise InputError(description="The dm_id is not valid.")

    invited_user = use_id_to_find_user(invited_id)
    if invited_user == {} or invited_id in database['dms'][dm_id - 1]['dm_members']:
        raise InputError(description="The user who will be invited does not have the correct id.")

    if invitor_id not in database['dms'][dm_id - 1]['dm_members']:
        raise AccessError(description="The one who wants to invite someone to the dm is not in the dm.")

    database['dms'][dm_id - 1]['dm_members'].append(invited_id)

    #put the data back to the data file
    with open(file_address, "w") as f:
        json.dump(database, f)
        
    # Open file again to get updated database
    with open(file_address, "r") as f:
        database = json.load(f)
    
    # Create a notification for the added user
    user_notification = new_added_notification(user_token, -1, dm_id, u_id)
    database['user_notifications'].append(user_notification)

    append_user_stats(invited_id, database)
    append_dream_stats(findUser(user_token), database)    
        
    # Put the data back to the data file
    with open(file_address, "w") as f:
        json.dump(database, f)
    
    return {}
def dm_create_v1(user_token, u_id_list):

    '''
    the function is given a user_token, which is encoded and is a string. Also, the function
    is given a list of user id. We need to use the proper parameters to create a direct message\
    and return the dm_id as a integer
    Arguments:
        user_token (string)    - some encoded information about one auth user
        u_id_list (list of int)    -  a list of user ids who are going to be in the dm
    ...

    Exceptions:
        AccessError - Occurs when the token is not a valid token

    Return Value:
        Returns {'dm_id': dm_id,
                 'dm_name': dm_name,}

    '''

    database = {}
    with open(file_address, "r") as f:
        database = json.load(f)
    
    auth_user_id = findUser(user_token)


    #the user_id of the creater of the dm
    user_name_list = []
    u_id_list.append(auth_user_id)

    #check all if all the u_id is valid and get their handle to generate the name of dm
    for some_u_id in u_id_list:
        new_user = use_id_to_find_user(some_u_id)
        if new_user == {}:
            raise InputError(description="Invalid u_id in the u_ids list.")
        user_name_list.append(new_user['handle_str'])
    

    user_name_list.sort(reverse=False)

    #generate the name of the new dm
    dm_name = ""
    dm_name += user_name_list[0]
    for i in range(1, len(user_name_list)):
        dm_name += ", "
        dm_name += user_name_list[i]

    #generate the new dm_id
    if len(database['dms']) == 0:
        dm_id = 1
    else:
        dm_id = database['dms'][len(database['dms']) - 1]['dm_id'] + 1

    #store the new dm into the database
    new_dm = {'dm_id' : dm_id,
              'dm_name': dm_name,
              'dm_owner': auth_user_id,
              'dm_members': u_id_list,
              'message_ids':[],}
    
    database['dms'].append(new_dm)
    
    #put the data back to the data file
    with open(file_address, "w") as f:
        json.dump(database, f)

    # Open file again to get updated database
    with open(file_address, "r") as f:
        database = json.load(f)
    
    # Create a notification for the added users
    for user in u_id_list:
        if auth_user_id != user:    
            user_notification = new_added_notification(user_token, -1, dm_id, user)
            database['user_notifications'].append(user_notification)

    append_user_stats(findUser(user_token), database)
    for u_id in u_id_list:
            append_user_stats(u_id, database)
    append_dream_stats(findUser(user_token), database)   

    # Put the data back to the data file
    with open(file_address, "w") as f:
        json.dump(database, f)
        
    return {'dm_id': dm_id,
            'dm_name': dm_name,}
Beispiel #10
0
def channel_removeowner_v1(token, channel_id, u_id):
    """Given channel id, removes u_id from owners of the channel.

    Arguments:
        token (string)              - token of an authenticated user who is
                                      either an owner of the channel or a global owner
        channel_id (integer)        - id of channel with ownership
        u_id (integer)              - id of user to be removed of channel ownership

    Exceptions:
        InputError  - Occurs when channel_id is not a valid channel
                    - Occurs when u_id refers to a user who is not an owner
                    - Occurs when u_id is currently the only owner
        AccessError - Occurs when token refers to a user who is not a global owner
                      or an owner of the target channel
                    - Occurs when token is not valid

    Return value:
        {}
    """

    # Load .json data store
    data_store = getData()

    # Check validity of channel_id
    ch_index = check_validity(data_store["channels"], channel_id, "channel_id",
                              INVALID_CHANNEL_ID)
    ch_src = data_store["channels"][ch_index]

    # Check validity of token
    token_index = findUser(token) - 1
    token_src = data_store["users"][token_index]

    # Check validity of u_id
    u_index = check_validity(data_store["users"], u_id, "u_id", INVALID_U_ID)
    u_src = data_store["users"][u_index]

    # Check user to be removed of ownership is actually an owner
    if not is_owner(ch_src, u_src):
        raise InputError(description="user is not an owner of this channel.")

    # Check token user is either global owner or an owner of the channel
    token_permission = token_src["permission_id"]
    if token_permission != 1 and not is_owner(ch_src, token_src):
        raise AccessError(
            description="token does not have permission to remove owner.")

    # Check user is not the only owner
    if len(ch_src["owner_members"]) == 1:
        raise InputError(description="user is the only owner remaining.")

    # Remove user from owner_members
    owner_remove = {
        "u_id": u_src["u_id"],
        "name_first": u_src["name_first"],
        "name_last": u_src["name_last"],
        "email": u_src["email"],
        "handle_str": u_src["handle_str"],
        "profile_img_url": u_src["profile_img_url"],
    }
    ch_src["owner_members"].remove(owner_remove)

    append_user_stats(u_id, data_store)
    append_dream_stats(u_id, data_store)

    writeData(data_store)

    return {}
Beispiel #11
0
def channel_addowner_v1(token, channel_id, u_id):
    """Given channel id, makes a u_id owner of that channel.

    Arguments:
        token (string)              - token of an authenticated user who is
                                      either an owner of the channel or a global owner
        channel_id (integer)        - id of channel for ownership
        u_id (integer)              - id of user to be granted ownership of channel

    Exceptions:
        InputError  - Occurs when channel_id is not a valid channel
                    - Occurs when u_id refers to a user who is already an owner
        AccessError - Occurs when token refers to a user who is not a global owner
                      or an owner of the target channel
                    - Occurs when token is not valid

    Return value:
        {}
    """

    # Load .json data store
    data_store = getData()

    # Check validity of channel_id
    ch_index = check_validity(data_store["channels"], channel_id, "channel_id",
                              INVALID_CHANNEL_ID)
    ch_src = data_store["channels"][ch_index]

    # Check validity of token
    token_index = findUser(token) - 1
    token_src = data_store["users"][token_index]

    # Check validity of u_id
    u_index = check_validity(data_store["users"], u_id, "u_id", INVALID_U_ID)
    u_src = data_store["users"][u_index]

    # Check user to be added is not already an owner
    if is_owner(ch_src, u_src):
        raise InputError(
            description="user is already an owner of this channel.")

    # Check token user is either global owner
    # or an owner of the channel
    token_permission = token_src["permission_id"]
    if token_permission != 1 and not is_owner(ch_src, token_src):
        raise AccessError(
            description="token does not have permission to add owner")

    # Add user to owner_members
    owner_add = {
        "u_id": u_src["u_id"],
        "name_first": u_src["name_first"],
        "name_last": u_src["name_last"],
        "email": u_src["email"],
        "handle_str": u_src["handle_str"],
        "profile_img_url": u_src["profile_img_url"],
    }
    ch_src["owner_members"].append(owner_add)

    # If user was not originally member of channel,
    # add them to all_members too
    if not is_member(ch_src, u_src):
        ch_src["all_members"].append(owner_add)

        # Create a notification for the added user
        user_notification = new_added_notification(token, channel_id, -1, u_id)
        data_store["user_notifications"].append(user_notification)

    append_user_stats(u_id, data_store)
    append_dream_stats(u_id, data_store)

    writeData(data_store)

    return {}
Beispiel #12
0
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 (str)           - token passed in to the function
        channel_id (int)      - the id of the channel to invite to
        u_id (int)            - the id of the user that is being invited

    Exceptions:
        InputError  - Occurs when channel_id does not refer to a valid channel.
        InputError  - Occurs when u_id does not refer to a valid user.
        AccessError - Occurs when token pass in is not a valid id.
        AccessError - Occurs when the authorised user is not already a member of the channel.

    Return Value:
        Returns {} on successful invite

    """

    auth_user_id = findUser(token)

    database = getData()

    # Check for exceptions
    channel_index = check_validity(database["channels"], channel_id,
                                   "channel_id", INVALID_CHANNEL_ID)
    channel_src = database["channels"][channel_index]

    user_index = check_validity(database["users"], u_id, "u_id", INVALID_U_ID)
    user_src = database["users"][user_index]

    check_validity(channel_src["all_members"], auth_user_id, "u_id",
                   UNAUTHORISED_AUTH_U_ID)

    # Only add the user if they are not already in the channel
    for member in channel_src["all_members"]:
        if u_id in member.values():
            return {}

    # Create a new dictionary for the added user with their details
    # and add them to the channel
    new_member = {
        "u_id": user_src["u_id"],
        "name_first": user_src["name_first"],
        "name_last": user_src["name_last"],
        "email": user_src["email"],
        "handle_str": user_src["handle_str"],
        "profile_img_url": user_src["profile_img_url"],
    }

    channel_src["all_members"].append(new_member)

    # Create a notification for the added user
    user_notification = new_added_notification(token, channel_id, -1, u_id)
    database["user_notifications"].append(user_notification)

    append_user_stats(u_id, database)
    append_dream_stats(u_id, database)

    writeData(database)

    return {}
def channels_create_v2(token, name, is_public):
    '''
    Arguments:
        token (string) - the token of the one who wants to create a channel
        name (string) - the name of the channel which is going to be created
        is_public (boolean) - whether the channel is public or private

    Exceptions:
        Inputerror - occur when the name of channel is larger than 20 characters
        Accesserror - occur when the token is not valid or hasn't been registered.

    Return value:
        Returns {'channel_id': } when there is no exception being raised
    '''
    
    data = getData()
    auth_user_id = findUser(token)
    
    if len(name) > 20:
        raise InputError(description="Name too long.")
    else:
        new_channel_id = len(data['channels']) + 1
        name_last = data['users'][auth_user_id - 1]['name_last']
        name_first = data['users'][auth_user_id - 1]['name_first']
        email = data['users'][auth_user_id - 1]['email']
        handle_str = data['users'][auth_user_id - 1]['handle_str']

        is_active = False
        stand_up_finished_time = 0
        stand_up_length = 0

        data['channels'].append({  
            'channel_id': new_channel_id,  
            'channel_name' : name,      
            'all_members':  [{
                                'u_id':auth_user_id,
                                'name_last': name_last,
                                'name_first': name_first,
                                'email': email,
                                'handle_str': handle_str,
                                'profile_img_url' : data['users'][auth_user_id - 1]['profile_img_url'],

                            },],   
            'owner_members':[{
                                'u_id':auth_user_id,
                                'name_last': name_last,
                                'name_first': name_first,
                                'email': email,
                                'handle_str': handle_str,
                                'profile_img_url' : data['users'][auth_user_id - 1]['profile_img_url'],

                            },],
            'is_public' : is_public,
            'standup': {        
                                'is_active': is_active,
                                'messages':"",
                                'time_finish': stand_up_finished_time,
                                'stand_up_length': stand_up_length,
                        },

            'messages' : [],
        })

        append_user_stats(auth_user_id, data)
        append_dream_stats(auth_user_id, data)  
    
        writeData(data)
    
        return {
            'channel_id': new_channel_id,
        }
Beispiel #14
0
def standup_package(index, user_token, channel_id, time_finish):
    """a helper function to store the messages sent in the standup period
    """

    database = getData()
    new_message = database['channels'][index]['standup']['messages']
    
    auth_user_id = findUser(user_token)

    if database['messages'] == []:
        new_message_id = 1
    else:
        new_message_id = database['messages'][-1]['message_id'] + 1
    
    database['messages'].append({
        'message_id' : new_message_id,
        'u_id' : auth_user_id,
        'channel_id': channel_id,
        'dm_id' : -1,
        'message' : new_message,         
        'time_created' : time_finish,
        'reacts' : [],
        'is_pinned' : False,           
    })

    database['channels'][index]['messages'].append(new_message_id)

    database['channels'][index]['standup']['is_active'] = False
    database['channels'][index]['standup']['standup_length'] = 0
    database['channels'][index]['standup']['time_finish'] = 0
    database['channels'][index]['standup']['messages'] = ""

    append_user_stats(auth_user_id, database)
    append_dream_stats(auth_user_id, database)
    
    words = new_message.split()
    handle_list = []
    for word in words:
        if word[0] == '@':
            word = word.replace(',','')
            handle_list.append(word[1:])
    
    u_id = -1
    handle_status = False
    member_status = False   
    for handle in handle_list:
        u_id = -1
        handle_status = False
        member_status = False        
        for user in database['users']:
            if handle == user['handle_str']:
                handle_status = True
                u_id = user['u_id']
                
        channel_ids = {'channel_id' : channel_id}
        channel = get_channel_details(channel_ids, database)
        for members in channel['all_members']:
            if u_id == members['u_id']:
                member_status = True

        with open(file_address, "w") as f:
            json.dump(database, f)

        if handle_status == True and member_status == True:
            user_notification = new_tagged_notification(user_token, channel_id, -1, u_id, new_message)
            database['user_notifications'].append(user_notification)


    with open(file_address, "w") as f:
        json.dump(database, f)
def message_sendlater_v1(token, channel_id, message, time_sent):
    ''' Send a message from authorised user to the channel, 
    automatically at a specified time in the future

    Arguments:
        token (string)              - token of an authenticated user
                                      who is part of the channel
        channel_id (integer)        - id of channel to send message in
        message (string)            - actual message content
        time_sent (integer)         - unix timestamp of when message will be sent
    
    Exceptions:
        InputError  - Occurs when channel_id is not a valid channel
                    - Occurs when message is more than 1000 characters
                    - Occurs when time_sent before current time
        AccessError - Occurs when authorised user is not a member of channel
                    - Occurs when token is not valid

    Return value:
        {
            message_id
        }
    '''
    current_time = int(time.time())

    # Load .json data store
    data_store = getData()

    # Check validity of channel_id
    check_validity(data_store["channels"], channel_id, "channel_id", 0)

    # Check message is less than 1000 characters
    if len(message) > 1000:
        raise InputError(
            description="Message must be less than 1000 characters")

    # Check time_sent is in the future
    if time_sent < current_time:
        raise InputError(description="Cannot send a message in the past")

    # Get user from token and check they are member of channel
    u_id = findUser(token)
    channel_members = get_channel_members(channel_id, data_store)
    if u_id not in channel_members:
        raise AccessError(description="User not in channel!")

    # Get new message_id
    new_message_id = get_new_message_id(data_store)

    # Add message to data_store
    add_data(data_store, new_message_id, u_id, channel_id, -1, message,
             time_sent, [], False)

    # Set up thread to send message in channel later
    if (time_sent == current_time):
        # Append message to channel messages
        for channel in data_store["channels"]:
            if channel_id == channel["channel_id"]:
                channel["messages"].append(new_message_id)
        send_msg_notification(data_store, token, message, channel_id, -1,
                              False, new_message_id)
    else:
        sendlater_thread = Timer(time_sent - current_time,
                                 send_msg_notification,
                                 args=[
                                     data_store, token, message, channel_id,
                                     -1, True, new_message_id
                                 ])
        sendlater_thread.start()

    append_user_stats(findUser(token), data_store)
    append_dream_stats(findUser(token), data_store)

    writeData(data_store)

    return {"message_id": new_message_id}
def message_share_v1(token, og_message_id, message, channel_id, dm_id):
    '''
    Arguments:
        token (string) - the token of the user who wants to create a channel
        og_message_id - the id of the inital message
        message (string) - the message being appended at the end of the share
        channel_id (int) - the id of the channel the message is being sent to
        dm_id (int) - the id of the dm the message is being sent to

    Exceptions:
        InputError - Message is more than 1000 characters
        AccessError - The authorised user has not joined the channel/dm they are trying to share to

    Return value:
        Returns {'shared_message_id': shared_message_id}
    '''

    # get data
    data = getData()

    # get id
    auth_user_id = findUser(token)

    # Checks that the user is part of the channel or dm they are sharing to
    channel_members = get_channel_members(channel_id, data)
    dm_members = get_dm_members(dm_id, data)

    if auth_user_id not in channel_members and auth_user_id not in dm_members:
        raise AccessError(description="User not member of channel")

    # Get og message
    msg = get_message(og_message_id, data)

    # Check user has access to og message
    if auth_user_id != msg['u_id']:
        raise AccessError(
            "User not member of channel from which the message comes from")

    # Checks the new message is not more than 1000 characters
    if len(msg['message'] + '\n' + message) > 1000 and message != '':
        raise InputError(
            description="Message must be less than 1000 characters")

    # Get new message id
    new_message_id = get_new_message_id(data)

    # Copies og message
    new_msg = msg['message']

    # Add optional message at end
    if message != '':
        new_msg = msg['message'] + '\n' + message

    # Adds message to data dictionary field 'messages'
    add_data(data, new_message_id, auth_user_id, channel_id, -1, new_msg,
             int(time.time()), [], False)

    # Share to DM/Channel
    if channel_id != -1 and dm_id != -1:
        raise InputError("Usage: One of channel_id or dm_id must be -1.")
    elif channel_id == -1:
        # Adds message to dm
        for dm in data['dms']:
            if dm_id == dm['dm_id']:
                dm['message_ids'].append(new_message_id)

    else:
        # Adds message to channel
        for chan in data['channels']:
            if channel_id == chan['channel_id']:
                chan['messages'].append(new_message_id)

    # Sends notification
    send_msg_notification(data, token, new_msg, channel_id, dm_id, False, -1)

    append_user_stats(findUser(token), data)
    append_dream_stats(findUser(token), data)

    writeData(data)

    return {'shared_message_id': new_message_id}