Exemplo n.º 1
0
def message_edit(token, message_id, message):
    """
    Edits a message from the channel where message_id is found,
    Function willremove the messaage from the whole system if given message is empty

    Parameters:
        token (str): Used to authenticate and identify the user
        message_id (int): the unique id of a message in the system
        message (str): the string containing the new message

    Return:
    	{}
    """
    # Check if message exists in the data
    # Function will raise InputError if message does not exist
    msg_check = check_message_valid(message_id)
    ch_index = msg_check['ch_index']
    msg_index = msg_check['msg_index']

    channel = valid_channel_id(ch_index)

    # Check if token is valid
    user_id = authenticate_token(token)

    # Check if message_edit does not raise AccessError
    check_message_access(user_id, msg_check)

    # Edits the message or remove it if message is empty
    if message == '':
        channel.channel_messages.remove(msg_check['sent_msg'])
    else:
        channel.channel_messages[msg_index].update_message(message)
    return {}
Exemplo n.º 2
0
def test_valid_channel_id_valid_channel():
    clear()
    user1 = auth_register('*****@*****.**', 'password', 'Test', 'Test')
    channel1 = channels_create(user1['token'], "Test Channel", True)

    result = valid_channel_id(channel1['channel_id'])
    assert result.name == "Test Channel"
Exemplo n.º 3
0
def standup_send(token, channel_id, message):
    """
    Add a message to the queue that will be collated after the timer tuns out
    
    Parameters:
        token (str): Check that the user is validated to call.
        channel_id (int): Specifies which channel the standup is to be in.
        message (str): The message that is to be added.
    
    returns: {}
    """
    user_id = authenticate_token(token)
    user = valid_user_id(user_id)
    channel = valid_channel_id(channel_id)
    standup = channel.standup_details()

    # Check that user is in this channel
    if not channel.existing_member(user):
        raise AccessError('User is not in the target channel')

    # Checking for invalid input
    if len(message) > 1000:
        raise InputError(description="Mesage too long")

    # Check that the timer is running
    if standup['time_finish'] is None:
        raise InputError(description="Standup not active")

    # Get senders handle
    handle = user_profile(token, user_id)['user']['handle_str']

    # Add the message queue
    channel.standup_message_add(handle, message)
    return {}
Exemplo n.º 4
0
def timed_send(token, channel_id):
    """
    Called at the end of the timer set in the standup_start function.
    Calls message send, after checking some conditions.
    
    Parameters:
        token (str): Passed on to message_send.
        channel_id (int) Passed on to message_send. Also needed for channel data
    
    Returns:
        None
    """
    channel = valid_channel_id(channel_id)

    # Get standup details and reset
    standup = channel.standup_details()
    channel.standup_reset()

    # Abort if no message has been queued
    if standup['message_queue'] == "":
        return

    # Call message send otherwise, truncating trailing newline characters
    message_send(token, channel_id, standup['message_queue'])
    return
Exemplo n.º 5
0
def channel_details(token, channel_id):
    """
    Provides basic details about the channel a user is in.

    Parameters:
        token (str): a unique token (to determine authorisation)
        channel_id(int): a unique id for such channel

    Returns:
        {
            name (str): The name of the channel
            owner_members (list): List of dictionaries of the owner memebr of the channel,
                                  where each dictionary contains types { u_id, name_first, name_last }
            all_members (list): List of dictionaries of all the member in the channel,
                                where each dictionary contains types { u_id, name_first, name_last }
        }
    """
    # Check token and find index, aka u_id
    u_id = authenticate_token(token)
    user = valid_user_id(u_id)

    channel = valid_channel_id(channel_id)

    if not channel.existing_member(user):
        raise AccessError(description="User not in desired channel.")

    return channel.channel_details()
Exemplo n.º 6
0
def channel_messages(token, channel_id, start):
    """
    Returns a list of messages, start and end.

    Parameters:
        token (str): a unique token (to determine authorisation)
        channel_id(int): a unique id for such channel
        start (int): index indicating when the messages start

    Returns:
        {
            messages (str): the message which will be sent in the channel
            start (int): index indicating when the messages start
            end (int): index indicating when the messages end
        }
    """
    # Check that token is valid and gets it index(u_id)
    user_id = authenticate_token(token)
    user = valid_user_id(user_id)

    # Check that channel_id is valid
    channel = valid_channel_id(channel_id)

    # Check that user is part of the desired channel
    if not channel.existing_member(user):
        raise AccessError(description="User not in desired channel.")

    # Check that start is not greater
    # than the total number of messages in the channel and not negative
    msg_count = channel.num_messages()
    if (start > msg_count or start < 0):
        raise InputError("invalid start")

    # Initialize the desired return data
    ch_messages = {}
    ch_messages['messages'] = []

    msg_load = msg_count - start
    if msg_count == 0:  # No messages to load
        end = -1
    elif start == msg_count:  # Only loads a single message if start is equal to message_count
        msg = channel.channel_messages[msg_count - 1].message_details()
        ch_messages['messages'].append(msg)
        end = -1
    elif msg_load <= 50:  # Loads all the messages in the channel if there are less than 50 messages to load
        for i in range(msg_load, start, -1):
            msg = channel.channel_messages[i - 1].message_details()
            ch_messages['messages'].append(msg)
        end = -1
    else:  # Only loads the first 50 messages if there are more than 50 messages in the channel
        for i in range(start + 50, start, -1):
            msg = channel.channel_messages[i - 1].message_details()
            ch_messages['messages'].append(msg)
        end = start + 50

    # Updates the start and end value which needs to be returned
    ch_messages['start'] = start
    ch_messages['end'] = end

    return ch_messages
Exemplo n.º 7
0
def channel_join(token, channel_id):
    """
    Adds a user from a channel,
    User should have been authenticated and authorised to join the channel.

    Parameters:
        token (str): a unique token (to determine authorisation)
        channel_id(int): a unique id for such channel

    Returns:
        {}
    """
    # Check that token is valid
    user_id = authenticate_token(token)
    user = valid_user_id(user_id)

    # Check that channel_id is valid
    channel = valid_channel_id(channel_id)

    # Check that user is allowed to join
    if not channel.is_public and not user.permission_id == 1:
        raise AccessError("Channel is private, unable to join")

    # Check that the user is not in the channel yet
    if channel.existing_member(user):
        raise InputError(description="User is already a member.")

    # Adds user to the channel
    channel.new_member(user)

    # Promote to owner if user is flockr owner
    if user.permission_id == 1:
        channel.new_owner(user)

    return {}
Exemplo n.º 8
0
def channel_leave(token, channel_id):
    """
    Removes a user from a channel,
    User should have been authenticated and should be a member of this channel

    Parameters:
        token (str): a unique token (to determine authorisation)
        channel_id(int): a unique id for such channel

    Returns:
        {}
    """
    # Check that token is valid and gets it index(u_id)
    user_id = authenticate_token(token)
    user = valid_user_id(user_id)

    # Check that channel_id is valid
    channel = valid_channel_id(channel_id)

    # Check that user is a member of the channel
    if not channel.existing_member(user):
        raise AccessError(description="User not in desired channel.")

    # Removes user from all_members list
    channel.remove_member(user)

    # Check if user is owner and remove from owner_members if TRUE
    if user.u_id in [
            user['u_id'] for user in channel.channel_details()['owner_members']
    ]:
        channel.remove_owner(user)

    return {}
Exemplo n.º 9
0
def channel_invite(token, channel_id, u_id):
    """
    Invites user into channel.

    Parameters:
        token (str): a unique token (to determine authorisation)
        channel_id(int): a unique id for such channel
        u_id (int): A unique identidier to indicate the target of this function

    Return:
        {}
    """
    # raise InputError if any of the inputs is empty
    if token == '':
        raise InputError("Invalid Input")
    if channel_id == '':
        raise InputError("Invalid Input")
    if u_id == '':
        raise InputError("Invalid Input")

    # raise InputError if any of the inputs is an invalid type
    if not isinstance(token, str):
        raise AccessError("Token must be string")
    if not isinstance(channel_id, int):
        raise InputError("Channel_id must be integer")
    if not isinstance(u_id, int):
        raise InputError("u_id must be integer")

    # check that token is authorised
    caller_id = authenticate_token(token)
    caller = valid_user_id(caller_id)

    # Check that target exists
    target = valid_user_id(u_id)

    # raises InputError if channel_id doesn't refer to a valid channel
    channel = valid_channel_id(channel_id)

    # raises AccessError if caller is not member of channel
    if not channel.existing_member(caller):
        raise AccessError(description="Caller is not in target channel")

    # rasies InputError if target already a member
    if channel.existing_member(target):
        raise InputError(description="Target is already a member.")

    # Add user to channel
    channel.new_member(target)

    # if the new_member is also a global owner they need to be added as an owner_member
    if target.permission_id == 1:
        channel.new_owner(target)

    return {}
Exemplo n.º 10
0
def message_send(token, channel_id, message_in):
    """
    Sends a message from an authenticated user to a valid channel the user is in
    Generates a message_id and returns it.

    Parameters:
        token (str): Used to authenticate and identify the user
        channel_id (int): the unique id of a channel in the system
        message (str): the message which will be sent in the channel

    Return:
        message_id (int): the unique id of a message in the system
    """

    # Check message length, raise InputError if characters in message:
    # -> length of characters > 1000
    # -> length of characters == 0 (empty message)
    if len(message_in) > 1000 or len(message_in) == 0:
        raise InputError(description='Invalid message length')

    # Check if token and channel_id exists in data
    user_id = authenticate_token(token)
    user = valid_user_id(user_id)
    channel = valid_channel_id(channel_id)

    # Check if user is in the channel, raise AccessError if user is not in channel
    if not channel.existing_member(user):
        raise AccessError("User not in desired channel")

    # Check if message is related to hangman and edit it accordingly if it is
    msg_check = message_in.split()
    is_guess = False
    if msg_check[0] == "/guess" and channel.hangman.get_details()['mode']:
        if len(msg_check) == 2:
            message_in = msg_check[1]
            is_guess = True

    if message_in == "/hangman start" or is_guess:
        message_in = hangman(message_in, channel)

    message_id = data.message_index
    data.message_index += 1
    message_object = message(message_in, user_id, message_id)

    channel.new_message(message_object)

    return {'message_id': message_object.message_id}
Exemplo n.º 11
0
def message_sendlater(token, channel_id, message, time_sent):
    """
    Sends a message from an authenticated user to a valid channel the user is in
    Generates a message_id and returns it at the specified time_sent in the future.

    Parameters:
        token (str): Used to authenticate and identify the user
        channel_id (int): the unique id of a channel in the system
        message (str): the message which will be sent in the channel
        time_sent (int): unix integer timestamp for a given time (consist of year, month, day and time)

    Return:
        message_id (int): the unique id of a message in the system
    """
    # Check message length, raise InputError if characters in message is invalid
    if len(message) > 1000 or len(message) == 0:
        raise InputError(description='Invalid message length')

    # Check if token is valid and channel_id exists in data
    user_id = authenticate_token(token)
    channel = valid_channel_id(channel_id)
    user = valid_user_id(user_id)

    # Check if the time_sent is not a time in the past
    cur_time = int(time.time())
    if time_sent < cur_time:
        raise InputError(description='Time sent is a time in the past')

    # Check if user is in the channel, raise AccessError if user is not in channel
    if not channel.existing_member(user):
        raise AccessError("User not in desired channel")

    # Generate message id and increment the counter in the data
    # Message_id is generated when message_sendlater is called
    msg_id = data.message_index
    data.message_index += 1

    # Send the message according to the desired time
    timer = time_sent - cur_time
    send_after = threading.Timer(
        timer, send_msg, [msg_id, user_id, message, channel, time_sent])
    send_after.start()

    # Return the generated message_id
    return {'message_id': msg_id}
Exemplo n.º 12
0
def channel_addowner(token, channel_id, u_id):
    """
    Function that adds target user as owner. If global owner, then bypass check
    of caller being an owner or target being member.

    Parameters:
    	token (str): A unique token to determine authorisation
    	channel_id (int): A unique identifier of channels
    	u_id (int): A unique identidier to indicate the target of this function

    Returns:
    	{}
    """
    # Check that token is valid
    caller_id = authenticate_token(token)
    caller = valid_user_id(caller_id)

    target = valid_user_id(u_id)

    # Check that channel_id is valid
    channel = valid_channel_id(channel_id)

    # Check that the caller is a member and an owner
    if caller.u_id not in [
            user['u_id'] for user in channel.channel_details()['owner_members']
    ]:
        raise AccessError(description="Caller is not an owner / member")

    # Check that the target is a member (If global owner, make member first)
    if not channel.existing_member(target):
        if target.permission_id == 1:
            channel.new_member(target)
        else:
            raise InputError(description="Target is not a member")

    # Check that not targeted at an owner
    if target.u_id in [
            user['u_id'] for user in channel.channel_details()['owner_members']
    ]:
        raise InputError(description="Target is already an owner")

    # If reached, here then successful
    channel.new_owner(target)
    return {}
Exemplo n.º 13
0
def channel_removeowner(token, channel_id, u_id):
    """
    Function that removes target user as owner. Global owner cannot be removed
    except for by another global owner.

    Parameters:
    	token (str): A unique token to determine authorisation
    	channel_id (int): A unique identifier of channels
    	u_id (int): A unique identidier to indicate the target of this function

    Returns:
    	{}
    """
    # Check that token is valid
    caller_id = authenticate_token(token)
    caller = valid_user_id(caller_id)

    target = valid_user_id(u_id)

    # Check that channel_id is valid
    channel = valid_channel_id(channel_id)

    # Check that caller is a member
    if not channel.existing_member(caller):
        raise AccessError(description="Caller not in channel")

    # Check that access is from an owner and targeted at an owner
    if caller.u_id not in [
            user['u_id'] for user in channel.channel_details()['owner_members']
    ]:
        raise AccessError(description="Caller is not an owner")
    if target.u_id not in [
            user['u_id'] for user in channel.channel_details()['owner_members']
    ]:
        raise InputError(description="Target is not an owner")

    # Only a global owner can remove a global owner
    if caller.permission_id != 1 and target.permission_id == 1:
        raise AccessError('Need global permissions to remove global owner')

    # If reached, here then successful
    channel.remove_owner(target)
    return {}
Exemplo n.º 14
0
def standup_active(token, channel_id):
    """
    Checks if a timer to timed_send is currently running.
    
    Parameters:
        token (str): Checks that the user is validated to call the function
        channel_id (int): Needed to check the right channel
    
    Returns:
        {
            is_active (bool): Is there a standup running in that channel?
            time_finish (UNIX timestamp): If yes, when does it end, else None
        }
    """
    authenticate_token(token)
    channel = valid_channel_id(channel_id)
    standup = channel.standup_details()

    return {
        'time_finish': standup['time_finish'],
        'is_active': standup['is_active']
    }
Exemplo n.º 15
0
def standup_start(token, channel_id, length):
    """
    Starts the timer that calls timed_send when it finishes
    
    Parameters:
        token (str): Check that the user is validated to call.
        channel_id (int): Specifies which channel the standup is to be in.
        length (int): Specifies the duration of the standup ( > 0).
    
    Returns:
        {
            time_finish (UNIX timestamp): When will timed_send be called?
        }
    """
    u_id = authenticate_token(token)
    user = valid_user_id(u_id)
    # Check valid channel and user belongs to channel
    channel = valid_channel_id(channel_id)
    if not channel.existing_member(user):
        raise AccessError('User is not in the target channel')

    # Check that the object is not currently running
    if standup_active(token, channel_id)['is_active']:
        raise InputError(description="Standup already in progress")

    # Check length is positive
    if length <= 0:
        raise InputError("Duration must be positive")

    # Start the timer if reached here
    timer = threading.Timer(length, timed_send, [token, channel_id])
    timer.start()
    current_time = int(time.time())
    added = current_time + length
    channel.standup_end = added

    return {'time_finish': channel.standup_end}
Exemplo n.º 16
0
def message_react(token, message_id, react_id):
    """
    Given a valid user appointed with the token, react to an existing message under
    the user's u_id. If the given message does not have any of the react yet,
    it will create append a new dictionary for the react_id.

    Parameters:
        token (str): Used to authenticate and identify the user
        message_id (int): the unique id of a message in the system
        react_id (int): the unique id of a 'react' that will be reacted to

    Return:
    	{}
    """
    # Check if token is valid
    user_id = authenticate_token(token)
    user = valid_user_id(user_id)

    # Check if message exists in the data
    msg_check = check_message_valid(message_id)
    ch_index = msg_check['ch_index']
    msg_index = msg_check['msg_index']
    channel = valid_channel_id(ch_index)

    # Check if user is a member of the channel where the message was posted
    if not channel.existing_member(user):
        raise InputError(description="User is not in desired channel")

    # Check if the given react_id is a valid react_id, function will raise InputError if it is invalid
    check_valid_react_id(react_id)

    # Find the current user_id in the reacts u_id list
    cur_msg = data.channels[ch_index].channel_messages[msg_index]
    is_already_reacted = False
    for react in cur_msg.reacts:
        if react['react_id'] == react_id and user_id in react['u_ids']:
            is_already_reacted = True
    # Check if the current message has not been reacted by the user previously
    if is_already_reacted is True:
        raise InputError(
            description="Message has already been reacted by the user")

    # Get the index of the react_id in the list of reacts
    react_index = find_react_id_index(cur_msg.reacts, react_id)

    # react_id has yet to exist in the message, create a new react dictionary
    # with the current user data to append to the reacts list
    if react_index == -1:
        new_react_dict = {}
        new_react_dict['react_id'] = react_id
        new_react_dict['u_ids'] = [user_id]
        new_react_dict['is_this_user_reacted'] = False
        cur_msg.reacts.append(new_react_dict)
    else:  # Add react data on the current dictionary
        cur_react_dict = cur_msg.reacts[react_index]
        # Append the current user_id into the u_ids list
        cur_react_dict['u_ids'].append(user_id)

    # Updates the is_this_user_reacted value if the current user who reacted is the
    # same user who sent the message
    if user_id == cur_msg.u_id:
        cur_msg.reacts[react_index]['is_this_user_reacted'] = True

    return {}