示例#1
0
def channels_list(token):
    """Provide a list of all channels (and their associated details) that the
    authorised user is part of

    Args:
        token (string): unique identifer of user

    Returns:
        (dict): { channels }
    """

    data = pickle.load(open(DATA_FILE, "rb"))

    confirm_token(data, token)

    u_id = convert_token_to_u_id(data, token)
    user_details = data.get_user_details(u_id)

    # Add channels the user is a part of into joined_channels.
    joined_channels = []
    for channel in user_details['channels']:
        joined_channels.append({
            'channel_id': channel['channel_id'],
            'name': channel['name']
        })

    return {'channels': joined_channels}
def user_profile(token, u_id):
    """For a valid user, returns information about their user_id, email, first
    name, last name, and handle

    Args:
        token (string)
        u_id (int)

    Returns:
        (dict): { user }
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_u_id(data, u_id)

    # Search data.py for the valid user with matching u_id.
    user = data.get_user_details(u_id)
    return {
        'user': {
            'u_id': u_id,
            'email': user['email'],
            'name_first': user['name_first'],
            'name_last': user['name_last'],
            'handle_str': user['handle_str'],
            'profile_img_url': user['profile_img_url']
        }
    }
def user_profile_sethandle(token, handle_str):
    """Update authorised users handle

    Args:
        token (string)
        handle_str (string)

    Returns:
        (dict): {}
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)

    # Error check: handle_str must be between 3 and 20 characters
    if not validate_handle_str(handle_str):
        raise InputError(
            description=
            "InputError: Handle string must be between 3 and 20 characters (inclusive)"
        )

    # Error check: handle is already used by another user
    if not validate_handle_unique(data, handle_str):
        raise InputError(
            description="InputError: Handle is already used by another user")

    # updating in users list.
    u_id = convert_token_to_u_id(data, token)
    data.set_user_handle(u_id, handle_str)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {}
示例#4
0
def search(token, query_str):
    """Given a query string, return a collection of messages in all of the
    channels that the user has joined that match the query

    Args:
        token (string)
        query_str (string)

    Returns:
        (dict): { messages }
    """

    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)

    # Error check (Assumption): query_str must be atleast 1 character
    if len(query_str) == 0:
        raise InputError(description="InputError: query_str must be atleast 1 character long")

    all_messages = []
    for channel in data.get_channels():
        if validate_token_as_channel_member(data, token, channel['channel_id']):
            messages = get_messages_list(data, token, channel['channel_id'])
            for msg in messages:
                all_messages.append(msg)

    # Get the u_id
    matched_msg = []
    for message in all_messages:
        if message['message'].find(query_str) != INVALID_QUERY:
            matched_msg.insert(0, message)

    return { 'messages': matched_msg }
def channel_details(token, channel_id):
    """Given a Channel with ID channel_id that the authorised user is part of,
    provide basic details about the channel

    Args:
        token (string)
        channel_id (int)

    Returns:
        (dict): { name, owner_members, all_members }
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_channel_id(data, channel_id)

    # Error check: Authorised user is not a member of channel with channel_id
    if not validate_token_as_channel_member(data, token, channel_id):
        raise AccessError(
            description=
            "AccessError: Authorised user is not a member of the channel")

    channel_details = data.get_channel_details(channel_id)

    return {
        'name': channel_details['name'],
        'owner_members': channel_details['owner_members'],
        'all_members': channel_details['all_members'],
    }
示例#6
0
def users_all(token):
    """Returns a list of all users and their associated details

    Args:
        token (string)

    Returns:
        (dict): { users }
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)

    all_users = []
    for u_id in data.get_user_ids():
        user_details = data.get_user_details(u_id)
        all_users.append({
            'u_id': user_details['u_id'],
            'email': user_details['email'],
            'name_first': user_details['name_first'],
            'name_last': user_details['name_last'],
            'handle_str': user_details['handle_str'],
            'profile_img_url': user_details['profile_img_url']
        })

    return { 'users': all_users }
示例#7
0
def admin_userpermission_change(token, u_id, permission_id):
    """Given a User by their user ID, set their permissions to new permissions
    described by permission_id

    Args:
        token (string)
        u_id (int)
        permission_id (int)
    """

    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_u_id(data, u_id)


    if permission_id not in (MEMBER, OWNER):
        raise InputError(description="InputError: permission_id does not refer to a value permission")
    
    # Error check: The authorised user is not an owner
    user_id = convert_token_to_u_id(data, token)
    if not validate_flockr_owner(data, user_id):
        raise AccessError(description="AccessError: User is not a flockr owner")

    # Error check (Assumption): First flockr owner cannot have member permissions
    if u_id == data.get_first_owner_u_id() and permission_id == MEMBER:
        raise InputError(description="InputError: First flockr owner cannot be a member")

    data.set_user_permission_id(u_id, permission_id)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {}
def message_pin(token, message_id):
    """Given a message within a channel, mark it as "pinned" to be given
    special display treatment by the frontend

    Args:
        token (string)
        message_id (int)

    Returns:
        (dict)
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_message_id(data, message_id)

    # Error check: Message with ID message_id is already pinned
    channel_id = data.get_channel_id_with_message_id(message_id)
    channel_messages = data.get_channel_details(channel_id)['messages']
    for curr_message in channel_messages:
        if curr_message['message_id'] == message_id:
            if curr_message['is_pinned']:
                raise InputError(
                    description="InputError: Message is already pinned")

    # Check if user is a flockr owner.
    u_id = convert_token_to_u_id(data, token)
    flockr_owner = validate_u_id_as_flockr_owner(data, u_id)
    channel_member = validate_token_as_channel_member(data, token, channel_id)
    channel_owner = validate_token_as_channel_owner(data, token, channel_id)

    # Error check: The authorised user is not a member of the channel that the message is within
    if not flockr_owner and not channel_member:
        raise AccessError(
            description=
            "AccessError: Authorised user is not a member of the channel \
        that contains the message")

    # Error check: The authorised user is not an owner
    if not flockr_owner and not channel_owner:
        raise AccessError(
            description=
            "AccessError: The authorised user is not an owner of the channel")

    # Pin message (If user is a flockr owner or channel owner).
    for curr_channel in data.get_channels():
        for curr_message in curr_channel['messages']:
            if curr_message['message_id'] == message_id:
                curr_message['is_pinned'] = True

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {}
def message_react(token, message_id, react_id):
    """Given a message within a channel the authorised user is part of, add 
    a "react" to that particular message

    Args:
        token (string)
        message_id (int)
        react_id (int)

    Returns:
        (dict): {}
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_message_id(data, message_id)
    confirm_react_id(data, message_id, react_id)

    # Error check: Message with ID message_id already contains an active React
    # with ID react_id from the authorised user
    u_id = convert_token_to_u_id(data, token)
    if validate_active_react_id(data, u_id, message_id, react_id):
        raise InputError(
            description=f"InputError: Message already contains an active react"
        )

    # Error check (Assumption): Flockr member not in channel with message_id
    channel_id = data.get_channel_id_with_message_id(message_id)
    is_member = validate_u_id_as_channel_member(data, u_id, channel_id)
    is_flock_owner = validate_u_id_as_flockr_owner(data, u_id)
    if not is_member and not is_flock_owner:
        raise AccessError(
            description=
            f"AccessError: User is not in the channel that has the message_id {message_id}"
        )

    # unreact all active reacts (based on assumption)
    active_react_ids = data.get_active_react_ids(u_id, message_id)
    if active_react_ids != []:
        for active_react_id in active_react_ids:
            message_unreact(token, message_id, active_react_id)

    # reload to get updated data from message_unreact
    data = pickle.load(open(DATA_FILE, "rb"))

    message = data.get_message_details(channel_id, message_id)
    message['reacts'][react_id - 1]['u_ids'].append(u_id)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {}
def message_sendlater(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

    Args:
        token (string)
        channel_id (int)
        message (string)
        time_sent (int)

    Returns:
        (dict): { message_id }
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_channel_id(data, channel_id)

    # Error check: Message is more than 1000 characters or 0 characters
    if len(message) > 1000:
        raise InputError(
            description="InputError: Message has more than 1000 characters")
    if len(message) == 0:
        raise InputError(description="InputError: Message is empty")

    # Error check: Time sent is a time in the past
    curr_time = int(datetime.now(tz=timezone.utc).timestamp())
    if curr_time > time_sent:
        raise InputError(
            description="InputError: Time sent is a time in the past")

    # Error check: the authorised user has not joined the channel they are trying to post to
    if not validate_token_as_channel_member(data, token, channel_id):
        raise AccessError(
            description=
            "AccessError: Authorised user is not a member of the channel")

    # Send the message at the time_sent
    if curr_time == time_sent:
        send_message = message_send(token, channel_id, message)
        message_id = send_message['message_id']
    else:
        time_delay = int(time_sent - curr_time)
        message_id = data.generate_message_id()
        with open(DATA_FILE, 'wb') as FILE:
            pickle.dump(data, FILE)
        Thread(target=delay_message_send,
               args=(token, channel_id, message, time_delay),
               daemon=True).start()

    return {'message_id': message_id}
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

    Args:
        token (string)
        channel_id (int)
        length (int)

    Returns:
        (dict): { time_finish }
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_channel_id(data, channel_id)

    # Error check: An active standup is currently running in this channel
    if data.specify_standup_status(channel_id)['is_active']:
        raise InputError(
            description="Standup is already running in the channel")

    # Error check (Assumption): User must be in the channel to start a standup
    if not validate_token_as_channel_member(data, token, channel_id):
        raise AccessError(
            description="User must be in the channel to start a standup")

    # Error check (Assumption): Length specified is less than or equal to 0
    if length <= 0:
        raise InputError(
            description="Length of standup must be greater than 0 seconds")

    # set standup as active and calculate time_finish
    completion_time = int(datetime.now(tz=timezone.utc).timestamp()) + length
    data.set_standup_active_in_channel(channel_id, completion_time)

    # when completion time is met, set standup as inactive and send messages
    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)
    Thread(target=set_standup_inactive,
           args=(token, channel_id, length),
           daemon=True).start()

    return {'time_finish': completion_time}
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.

    Args:
        token (string)
        message_id (int)
        message (string)

    Returns:
        (dict): {}
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # remove message if new message is an empty string
    if message == '':
        return message_remove(token, message_id)

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_message_id(data, message_id)

    # Error check: Message is more than 1000 characters or 0 characters
    if len(message) > 1000:
        raise InputError(
            description="InputError: Message has more than 1000 characters")

    # edit the message if user is flockr owner or channel owner or sent by authorized user
    # (Assumption) flockr owner does not need to be a part of the channel to edit message
    u_id = convert_token_to_u_id(data, token)
    channel_id = data.get_channel_id_with_message_id(message_id)
    valid_permission = validate_universal_permission(data, token, channel_id)
    userAuthorized = False
    for channel in data.get_channels():
        for curr_message in channel['messages']:
            if curr_message['message_id'] == message_id:
                if curr_message['u_id'] == u_id or valid_permission:
                    userAuthorized = True
                    data.edit_message(channel_id, message_id, message)

    # Error check: User was not authorised to edit the message
    if not userAuthorized:
        raise AccessError("AccessError: User not authorized to edit message")

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {}
def standup_send(token, channel_id, message):
    """Sending a message to get buffered in the standup queue, assuming a
    standup is currently active

    Args:
        token (string)
        channel_id (int)
        message (string)

    Returns:
        (dict): {}
    """
    data = pickle.load(open(DATA_FILE, "rb"))
    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_channel_id(data, channel_id)

    # Error check: Message is more than 1000 characters or 0 characters
    if len(message) > 1000:
        raise InputError(
            description="InputError: Message has more than 1000 characters")
    if len(message) == 0:
        raise InputError(description="InputError: Message is empty")

    # Error check (Assumption): User must be in the channel to start a standup
    if not validate_token_as_channel_member(data, token, channel_id):
        raise AccessError(
            description="User must be in the channel to start a standup")

    # if an active standup is not currently running in this channel
    standup_information = data.specify_standup_status(channel_id)
    if not standup_information['is_active']:
        raise InputError(
            description="Standup is not currently running in this channel")

    # append message to 'standup_messages' string
    handle_name = token_to_handle_name(data, token)
    if data.show_standup_messages(channel_id) == "":
        new_message = f'{handle_name}: {message}'
    else:
        new_message = f'\n{handle_name}: {message}'
    data.append_standup_message(channel_id, new_message)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {}
def channel_removeowner(token, channel_id, u_id):
    """Remove user with user id u_id an owner of this channel

    Args:
        token (string)
        channel_id (int)
        u_id (int)

    Returns:
        (dict): {}
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_channel_id(data, channel_id)
    confirm_u_id(data, u_id)

    # Error check: When user with user id u_id is not an owner of the channel
    if not validate_u_id_as_channel_owner(data, u_id, channel_id):
        raise InputError(
            description=
            f"InputError: User with u_id {u_id} is not an owner of channel")

    # Error check: User is not an owner of the flockr, or an owner of this channel
    if not validate_token_as_channel_member(data, token, channel_id):
        raise AccessError(
            description=
            "AccessError: Authorised user is not an owner of the flockr, or an owner of the channel"
        )

    # Error check (Assumption): There must be at least one owner in the channel
    channel_data = data.get_channel_details(channel_id)
    if len(channel_data['owner_members']) == 1:
        raise InputError(
            description=
            "InputError: There must be at least one owner in the channel")

    data.remove_owner_from_channel(u_id, channel_id)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {}
示例#15
0
def user_profile_setname(token, name_first, name_last):
    """Update the authorised user's first and last name

    Args:
        token (string)
        name_first (string)
        name_last (string)

    Returns:
        (dict): {}
    """

    data = pickle.load(open(DATA_FILE, "rb"))
    # Error checks: Basic validation
    confirm_token(data, token)

    # Error check: Name validation
    if not validate_names(name_first):
        raise InputError(
            description=
            "First name must be between 1 to 50 characters long (inclusive)")
    if not validate_names(name_last):
        raise InputError(
            description=
            "Last name must be between 1 to 50 characters long (inclusive)")
    if not validate_names_characters(name_first):
        raise InputError(
            description=
            "First name can only include uppercase and lowercase alphabetical characters, hyphens or whitespaces"
        )
    if not validate_names_characters(name_last):
        raise InputError(
            description=
            "Last name can only include uppercase and lowercase alphabetical characters, hyphens or whitespaces"
        )

    # changing name in the users field
    u_id = convert_token_to_u_id(data, token)
    data.set_user_name(u_id, name_first, name_last)
    data.set_user_name_in_channels(u_id, name_first, name_last)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)
    return {}
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

    Args:
        token (string)
        channel_id (int)
        u_id (int):

    Returns:
        (dict): {}
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_channel_id(data, channel_id)
    confirm_u_id(data, u_id)

    # Error check: the authorised user is not already a member of the channel
    # (i.e. not in channel when calling this function)
    if not validate_token_as_channel_member(data, token, channel_id):
        raise AccessError(
            description=
            "AccessError: User not authorized to invite, please join channel")

    # Error check (Assumption): User with u_id is already in the channel but is
    # invited again
    if validate_u_id_as_channel_member(data, u_id, channel_id):
        raise InputError(
            description="InputError: User is already part of the channel")

    user = data.get_user_details(u_id)
    data.add_member_to_channel(u_id, channel_id)
    data.add_channel_to_user_list(u_id, channel_id)

    # if user is flockr owner: make him the group owner too
    if user['permission_id'] == OWNER:
        data.add_owner_to_channel(u_id, channel_id)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {}
def message_unreact(token, message_id, react_id):
    """Given a message within a channel the authorised user is part of, 
    remove a "react" to that particular message

    Args:
        token (string)
        message_id (int)
        react_id (int)

    Returns:
        (dict): {}
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_message_id(data, message_id)
    confirm_react_id(data, message_id, react_id)

    # Error check: Message with ID message_id does not contain an active React with ID react_id
    u_id = convert_token_to_u_id(data, token)
    if not validate_active_react_id(data, u_id, message_id, react_id):
        raise InputError(
            description=
            f"InputError: Message already contains a non-active react")

    # Error check (Assumption): Flockr member not in channel with message_id
    channel_id = data.get_channel_id_with_message_id(message_id)
    is_member = validate_u_id_as_channel_member(data, u_id, channel_id)
    is_flock_owner = validate_u_id_as_flockr_owner(data, u_id)
    if not is_member and not is_flock_owner:
        raise AccessError(
            description=
            f"AccessError: User is not in the channel that has the message_id {message_id}"
        )

    # Otherwise unreact the message with react_id.
    message = data.get_message_details(channel_id, message_id)
    message['reacts'][react_id - 1]['u_ids'].remove(u_id)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {}
def channel_join(token, channel_id):
    """Given a channel_id of a channel that the authorised user can join, adds
    them to that channel

    Args:
        token (string)
        channel_id (int)

    Returns:
        (dict): {}
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_channel_id(data, channel_id)

    # Error check (Assumption): Check whether user is a channel member already
    if validate_token_as_channel_member(data, token, channel_id):
        return {}

    # Error check: User cannot join a channel if they are a flockr member and
    # the channel is private
    u_id = convert_token_to_u_id(data, token)
    user = data.get_user_details(u_id)
    channel_details = data.get_channel_details(channel_id)
    if user['permission_id'] == MEMBER and not channel_details['is_public']:
        raise AccessError(
            description=
            "AccessError: Private channel cannot be joined unless user is a flockr owner"
        )

    data.add_member_to_channel(user['u_id'], channel_id)
    data.add_channel_to_user_list(user['u_id'], channel_id)

    # If the user is the flockr owner, make their permissions as a channel owner.
    if user['permission_id'] == OWNER:
        data.add_owner_to_channel(user['u_id'], channel_id)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {}
def channel_leave(token, channel_id):
    """Given a channel ID, the user removed as a member of this channel

    Args:
        token (string)
        channel_id (int)

    Returns:
        (dict): {}
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_channel_id(data, channel_id)

    # Error check: Authorised user is not a member of channel with channel_id
    if not validate_token_as_channel_member(data, token, channel_id):
        raise AccessError(
            description=
            "AccessError: Authorised user is not a member of the channel")

    u_id = convert_token_to_u_id(data, token)
    data.remove_member_from_channel(u_id, channel_id)
    data.remove_owner_from_channel(u_id, channel_id)
    data.delete_channel_from_user_list(u_id, channel_id)
    channel_details = data.get_channel_details(channel_id)

    # Case where all owners have left, assign the oldest member as the new
    # channel owner.
    if len(channel_details['owner_members']) == 0 and len(
            channel_details['all_members']) != 0:
        data.add_owner_to_channel(channel_details['all_members'][0]['u_id'],
                                  channel_id)

    # Case where all members have left, delete channel from database
    if len(channel_details['all_members']) == 0:
        data.delete_channel(channel_id)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {}
def channel_addowner(token, channel_id, u_id):
    """Make user with user id u_id an owner of this channel

    Args:
        token (string)
        channel_id (int)
        u_id (int)

    Returns:
        (dict): {}
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_channel_id(data, channel_id)
    confirm_u_id(data, u_id)

    # Error check: User id u_id is already an owner of the channel
    if validate_u_id_as_channel_owner(data, u_id, channel_id):
        raise InputError(
            description=
            f"InputError: User with u_id {u_id} is not an owner of channel")

    # Error check: User is not an owner of the flockr, or an owner of this channel
    if not validate_token_as_channel_member(data, token, channel_id):
        raise AccessError(
            description=
            "AccessError: Authorised user is not an owner of the flockr, or an owner of the channel"
        )

    # Add user as member if not already.
    if not validate_u_id_as_channel_member(data, u_id, channel_id):
        data.add_member_to_channel(u_id, channel_id)
        data.add_channel_to_user_list(u_id, channel_id)
    data.add_owner_to_channel(u_id, channel_id)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {}
示例#21
0
def channels_create(token, name, is_public):
    """Creates a new channel with that name that is either a public or private channel

    Args:
        token (string)
        name (string)
        is_public (bool)

    Returns:
        (dict): { channel_id }
    """

    data = pickle.load(open(DATA_FILE, "rb"))

    confirm_token(data, token)

    # Error check: Channel name validation
    if len(name) > 20 or len(name) < 1:
        raise InputError(
            description="Channel name must be between 1 to 20 characters")

    # Generate channel_id.
    channel_id = 1
    if len(data.get_channels()) != 0:
        channel_list = data.get_channels()
        channel_id = channel_list[-1]['channel_id'] + 1

    # Create new channel and store it into data structure.
    data.create_channel(name, is_public, channel_id)
    u_id = convert_token_to_u_id(data, token)
    data.add_channel_to_user_list(u_id, channel_id)

    # Add user to created channel as well as making them owner.
    data.add_member_to_channel(u_id, channel_id)
    data.add_owner_to_channel(u_id, channel_id)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {'channel_id': channel_id}
def message_send(token, channel_id, message):
    """Send a message from authorised_user to the channel specified by channel_id

    Args:
        token (string)
        channel_id (int)
        message (string)

    Returns:
        (dict): { message_id }
    """

    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_channel_id(data, channel_id)

    # Error check: Message is more than 1000 characters or 0 characters
    if len(message) > 1000:
        raise InputError(
            description="InputError: Message has more than 1000 characters")
    if len(message) == 0:
        raise InputError(description="InputError: Message is empty")

    # Error check: the authorised user has not joined the channel they are trying to post to
    if not validate_token_as_channel_member(data, token, channel_id):
        raise AccessError(
            description=
            "AccessError: Authorised user is not a member of the channel")

    # Add message to the channel
    message_id = data.generate_message_id()
    u_id = convert_token_to_u_id(data, token)
    data.create_message(u_id, channel_id, message_id, message)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {'message_id': message_id}
def message_remove(token, message_id):
    """Given a message_id for a message, this message is removed from the channel

    Args:
        token (string)
        message_id (int)

    Returns:
        (dict): {}
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_message_id(data, message_id)

    # remove the message if user is flockr owner or channel owner or sent by authorized user
    # (Assumption) flockr owner does not need to be a part of the channel to remove message
    channel_id = data.get_channel_id_with_message_id(message_id)
    u_id = convert_token_to_u_id(data, token)
    valid_permission = validate_universal_permission(data, token, channel_id)
    userAuthorized = False
    for channel in data.get_channels():
        for message in channel['messages']:
            if message['message_id'] == message_id:
                if message['u_id'] == u_id or valid_permission:
                    userAuthorized = True
                    data.remove_message(channel_id, message_id)

    # Error check: User was not authorised to remove the message
    if not userAuthorized:
        raise AccessError(
            description="AccessError: User not authorized to remove message")

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {}
示例#24
0
def channels_listall(token):
    """Provide a list of all channels (and their associated details)

    Args:
        token (string): unique identifer of user

    Returns:
        (dict): { channels }
    """

    data = pickle.load(open(DATA_FILE, "rb"))

    confirm_token(data, token)

    # Add all available channels into all_channels (both public and private).
    all_channels = []
    for curr_channel in data.get_channels():
        all_channels.append({
            'channel_id': curr_channel['channel_id'],
            'name': curr_channel['name']
        })

    return {'channels': all_channels}
示例#25
0
def user_profile_setemail(token, email):
    """Update the authorised user's email.

    Args:
        token (string): unique identifier of user.
        email (string): what the email will be set to.

    Returns:
        (dict): Contains no key types.
    """

    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)

    # Make the input email lowercase.
    email = email.lower()

    # Error check: Email validation
    if not validate_create_email(email):
        raise InputError(description="InputError: Invalid email address")
    # Check for whether email is already in use.
    for curr_user in data.get_users():
        if curr_user['email'] == email:
            raise InputError(
                description=
                f"InputError: Email address is already being used by another user"
            )

    u_id = convert_token_to_u_id(data, token)
    data.set_user_email(u_id, email)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    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

    Args:
        token (string)
        channel_id (int)

    Returns:
        (dict): { is_active, time_finish }
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_channel_id(data, channel_id)

    # Error check (Assumption): User must be in the channel to start a standup
    if not validate_token_as_channel_member(data, token, channel_id):
        raise AccessError(
            description="User must be in the channel to start a standup")

    return data.specify_standup_status(channel_id)
def channel_messages(token, channel_id, start):
    """Given a Channel with ID channel_id that the authorised user is 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.

    Args:
        token (string)
        channel_id (int)
        start (int)

    Returns:
        (dict): { messages, start, end }
    """

    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)
    confirm_channel_id(data, channel_id)

    # Error check: start is greater than the total number of messages in the channel
    channel_details = data.get_channel_details(channel_id)
    if start >= len(channel_details['messages']) and start != 0:
        raise InputError(
            description=f"InputError: start value ({start}) is greater than the \
        total number of messages in the channel ({len(channel_details['messages'])} messages)"
        )
    if start < 0:
        raise InputError(
            description=
            f"InputError: start value ({start}) must be greater than or equal to 0"
        )

    # Error check: Authorised user is not a member of channel with channel_id
    if not validate_token_as_channel_member(data, token, channel_id):
        raise AccessError(
            description=
            "AccessError: Authorised user is not a member of the channel")

    # (Assumption) Case where there are no messages in the channel
    if len(channel_details['messages']) == 0:
        return {
            'messages': [],
            'start': -1,
            'end': -1,
        }

    # Case where there are messages in the channel
    end = start + 50
    if end >= len(channel_details['messages']):
        end = -1

    # Create the messages list.
    messages_list = get_messages_list(data, token, channel_id)

    if end == -1:
        messages = messages_list[start:]
    else:
        messages = messages_list[start:end]

    return {'messages': messages, 'start': start, 'end': end}
示例#28
0
def user_profile_uploadphoto(token, img_url, x_start, y_start, x_end, y_end):
    """Given a URL of an image on the internet, crops the image within bounds (x_start, y_start) and (x_end, y_end). Position (0,0) is the top left.

    Args:
        token (string)
        img_url (string)
        x_start (int)
        y_start (int)
        x_end (int)
        y_end (int)

    Returns:
        (dict): {}
    """
    data = pickle.load(open(DATA_FILE, "rb"))

    # Error checks: Basic validation
    confirm_token(data, token)

    # Error check: img_url returns an HTTP status other than 200.
    try:
        response = requests.get(img_url)
    except:
        raise InputError(
            description="InputError: Image URL cannot be requested")
    if response.status_code != 200:
        raise InputError(
            description=
            "InputError: Image URL returns an HTTP status other than 200")

    # Generate file url path
    img_file_local_path = generate_img_file_path()

    # Error check: check if the image can be download. If can, download it.
    try:
        urllib.request.urlretrieve(img_url, 'src/' + img_file_local_path)
    except:
        raise InputError(
            description="InputError: Image URL cannot be retrieved")

    # Error check: Image uploaded is not a JPG
    if imghdr.what('src/' + img_file_local_path) != "jpeg":
        os.remove('src/' + img_file_local_path)
        raise InputError(description="InputError: Image uploaded is not a JPG")

    # Error check: Check if the x and y dimensions are within bounds
    img_object = Image.open('src/' + img_file_local_path)
    width, height = img_object.size
    if x_start not in range(0, width):
        os.remove('src/' + img_file_local_path)
        raise InputError(description="x_start not in boundary of the image")
    if x_end not in range(0, width + 1):
        os.remove('src/' + img_file_local_path)
        raise InputError(description="x_end not in boundary of the image")
    if y_start not in range(0, height):
        os.remove('src/' + img_file_local_path)
        raise InputError(description="y_start not in boundary of the image")
    if y_end not in range(0, height + 1):
        os.remove('src/' + img_file_local_path)
        raise InputError(description="y_end not in boundary of the image")
    if x_end <= x_start:
        os.remove('src/' + img_file_local_path)
        raise InputError(description="x_end must be greater than x_start")
    if y_end <= y_start:
        os.remove('src/' + img_file_local_path)
        raise InputError(description="y_end must be greater than y_start")

    # Crop the images
    img_object.crop(
        (x_start, y_start, x_end, y_end)).save('src/' + img_file_local_path)

    # Assign image to the user and save it on the server
    u_id = convert_token_to_u_id(data, token)
    try:
        server_img_url = f"{request.url_root}{img_file_local_path}"
    except:
        os.remove('src/' + img_file_local_path)
        raise AccessError(description="Server must be running to upload photo")
    data.set_user_photo(u_id, server_img_url)
    data.set_user_photo_in_channels(u_id, server_img_url)

    with open(DATA_FILE, 'wb') as FILE:
        pickle.dump(data, FILE)

    return {}