Ejemplo n.º 1
0
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
    """
    # Validate token
    if not validator.is_valid_token(token):
        raise AccessError(INVALID_TOKEN)

    # Decode token
    u_id = jwt_handler.decode_token(token)

    user = database.get_user_by_id(u_id)
    message = database.get_message_by_id(message_id)
    if message is None:
        raise ValueError(MESSAGE_PIN_NOT_EXIST)
    channel = database.get_channel_by_id(message["channel_id"])

    if user["permission"] not in [OWNER, ADMIN] \
            and u_id not in channel["owner_ids"]:
        raise ValueError(MESSAGE_PIN_NO_AUTH)

    # Checking data
    if u_id not in channel["auth_ids"]:
        raise AccessError(CHANNEL_CANT_VIEW_DETAIL)

    if message["is_pinned"] is True:
        raise ValueError(MESSAGE_ALREADY_PINNED)

    # Pinning message
    database.update_message_by_id(message_id, {"is_pinned": True})
    return {}
Ejemplo n.º 2
0
def message_unpin(token, message_id):
    """Given a message within a channel, remove it's mark as unpinned"""
    # Validate token
    if not validator.is_valid_token(token):
        raise ValueError(INVALID_TOKEN)

    # Decode token
    u_id = jwt_handler.decode_token(token)

    user = database.get_user_by_id(u_id)
    message = database.get_message_by_id(message_id)
    if message is None:
        raise ValueError(MESSAGE_UNPIN_NOT_EXIST)
    channel = database.get_channel_by_id(message["channel_id"])

    if user["permission"] not in [OWNER, ADMIN] \
            and u_id not in channel["owner_ids"]:
        raise AccessError(MESSAGE_UNPIN_NO_AUTH)

    # Checking data
    if u_id not in channel["auth_ids"]:
        raise AccessError(CHANNEL_CANT_VIEW_DETAIL)

    if message["is_pinned"] is False:
        raise ValueError(MESSAGE_NOT_PINNED)

    # Unpinning message
    database.update_message_by_id(message_id, {"is_pinned": False})
    return {}
Ejemplo n.º 3
0
def message_edit(token, message_id, message):
    """Given a message, update it's text with new text"""
    # Validate token
    if not validator.is_valid_token(token):
        raise AccessError(INVALID_TOKEN)

    # If the message is empty, perform deletion instead
    if message == "":
        return message_remove(token, message_id)

    if not validator.is_valid_message(message):
        raise ValueError(INVALID_MESSAGE)

    # Convert token to u_id
    u_id = jwt_handler.decode_token(token)

    user = database.get_user_by_id(u_id)
    message_dict = database.get_message_by_id(message_id)
    if message_dict is None:
        raise ValueError(MESSAGE_EDIT_NOT_EXIST)

    channel_id = message_dict["channel_id"]
    channel = database.get_channel_by_id(channel_id)

    # Check if user can edit this message
    if u_id == message_dict["u_id"] or user["permission"] in [OWNER, ADMIN] \
            or u_id in channel["owner_ids"]:
        database.update_message_by_id(message_id, {"message": message})
        return {}
    raise AccessError(MESSAGE_EDIT_NO_AUTH)
Ejemplo n.º 4
0
def message_remove(token, message_id):
    """
    Given a message_id for a message, this message is removed from the chxnel
    """
    # Validate token
    if not validator.is_valid_token(token):
        raise AccessError(INVALID_TOKEN)

    if not isinstance(message_id, int):
        message_id = int(message_id)

    # Convert token to u_id
    u_id = jwt_handler.decode_token(token)

    # Check u_id is authorised
    user = database.get_user_by_id(u_id)
    message = database.get_message_by_id(message_id)
    if message is None:
        raise ValueError(MESSAGE_REMOVE_NOT_EXIST)

    channel_id = message["channel_id"]
    channel = database.get_channel_by_id(channel_id)
    # if sender of message
    if u_id == message["u_id"] or\
            user["permission"] in [OWNER, ADMIN] or\
            u_id in channel["owner_ids"]:
        # Delete message from database
        database.delete_message_by_id(message_id)
        # Delete message from channel
        channel["messages"].remove(message_id)
        database.update_channel_by_id(channel_id, channel)
        return {}
    raise AccessError(MESSAGE_EDIT_NO_AUTH)
Ejemplo n.º 5
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"""
    if not validator.is_valid_token(token):
        raise AccessError(INVALID_TOKEN)

    # If the query is whitespace
    if (query_str.isspace() or len(query_str) == 0):
        return {"messages": []}

    u_id = jwt_handler.decode_token(token)

    result = []
    for channel in database.get_all_channels():
        if u_id in channel["auth_ids"]:
            for message_id in channel["messages"]:
                message = database.get_message_by_id(message_id)
                if query_str in message["message"]:
                    # Create output-able list of reacts
                    react_list = get_react_list(message, u_id)
                    # Write to file
                    time_created = json_time_translator.json_to_timestamp(
                        message["time_created"])
                    result_entry = {
                        "message_id": message_id,
                        "u_id": message["u_id"],
                        "message": message["message"],
                        "time_created": time_created,
                        "reacts": react_list,
                        "is_pinned": message["is_pinned"]
                    }
                    result.append(result_entry)
    return {"messages": result}
Ejemplo n.º 6
0
def message_sendlater(token, channel_id, message, time_sent):
    """
    Send a message from authorised_user to the channel specified by channel_id
    """
    # Validate data
    if not validator.is_valid_token(token):
        raise AccessError(INVALID_TOKEN)
    if not validator.is_valid_message(message):
        raise ValueError(INVALID_MESSAGE)

    # Convert token to u_id
    u_id = jwt_handler.decode_token(token)
    # Check channel exists
    channel = database.get_channel_by_id(channel_id)
    if channel is None:
        raise ValueError(INVALID_CHANNEL)

    # Read time_sent
    time_to_send = json_time_translator.timestamp_to_datetime(time_sent)
    # Check time_to_send is not in the past
    if time_to_send <= datetime.utcnow():
        raise ValueError(MESSAGE_TIME_INVALID)

    if u_id not in channel["auth_ids"]:
        raise AccessError(MESSAGE_SEND_NO_AUTH)

    # Create message
    message_id = database.add_message({
        "u_id":
        u_id,
        "message":
        message,
        "channel_id":
        int(channel_id),
        "time_created":
        json_time_translator.datetime_to_json(time_to_send),
        "is_pinned":
        False,
        "reacts": []
    })
    # Insert into channel's list of messages in order of time
    message_id_list = channel["messages"]

    inserted = False
    for i in reversed(range(len(message_id_list))):
        json_time = database.get_message_by_id(
            message_id_list[i])["time_created"]
        timestamp = json_time_translator.json_to_timestamp(json_time)
        if timestamp <= int(float(time_sent)):
            message_id_list.insert(i + 1, message_id)
            inserted = True
            break
    if inserted is False:
        message_id_list.insert(0, message_id)
    database.update_channel_by_id(channel_id, {"messages": message_id_list})
    return {"message_id": message_id}
Ejemplo n.º 7
0
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
    """
    # Validate
    if not validator.is_valid_token(token):
        raise AccessError(INVALID_TOKEN)

    # Decode token
    u_id = jwt_handler.decode_token(token)

    # Change react_id to an integer
    if not isinstance(react_id, int):
        react_id = int(react_id)
    if not isinstance(message_id, int):
        message_id = int(message_id)

    # Validate data
    message = database.get_message_by_id(message_id)
    channel = database.get_channel_by_id(message["channel_id"])

    if u_id not in channel["auth_ids"]:
        raise AccessError(CHANNEL_CANT_VIEW_DETAIL)

    if react_id != 1:
        print(react_id)
        raise ValueError(INVALID_REACT)

    react_id_exists = False
    for react in message["reacts"]:
        if react_id == react["react_id"]:
            react_id_exists = True
            if u_id in react["u_id"]:
                raise ValueError(MESSAGE_ALREADY_REACTED)
            break

    # Add react to message
    react_list = message["reacts"]
    if not react_id_exists:
        react_list.append({"react_id": react_id, "u_id": [u_id]})
    else:
        for react in react_list:
            if react_id == react["react_id"]:
                react["u_id"].append(u_id)
                break

    database.update_message_by_id(message_id, {"reacts": react_list})
    return {}
Ejemplo n.º 8
0
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
    """
    # Validate
    if not validator.is_valid_token(token):
        raise AccessError(INVALID_TOKEN)
    # Decode token
    u_id = jwt_handler.decode_token(token)

    # Change react_id to an integer
    if not isinstance(react_id, int):
        react_id = int(react_id)
    if not isinstance(message_id, int):
        message_id = int(message_id)

    # Validate data
    message = database.get_message_by_id(message_id)
    channel = database.get_channel_by_id(message["channel_id"])

    if u_id not in channel["auth_ids"]:
        raise AccessError(CHANNEL_CANT_VIEW_DETAIL)

    if react_id != 1:
        print(react_id)
        raise ValueError(INVALID_REACT)

    react_list = message["reacts"]
    react_found = False
    for react in react_list:
        if react_id == react["react_id"] and u_id in react["u_id"]:
            react_found = True
            break

    if not react_found:
        raise ValueError(MESSAGE_NOT_REACTED)

    # Remove react from message
    for react in react_list:
        if react_id == react["react_id"]:
            react["u_id"].remove(u_id)

    database.update_message_by_id(message_id, {"reacts": react_list})
    return {}
Ejemplo n.º 9
0
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."""
    # Convert 'start' to an integer
    start = int(start)

    # Validate token and channel ID
    if not validator.is_valid_token(token):
        raise AccessError(INVALID_TOKEN)
    if not validator.is_valid_channel(channel_id):
        raise ValueError(INVALID_CHANNEL)

    # Locate channel
    channel = database.get_channel_by_id(channel_id)

    # Validate that token user is in channel
    u_id = jwt_handler.decode_token(token)
    if u_id not in channel["auth_ids"]:
        raise AccessError(CHANNEL_CANT_VIEW_MSG)

    # Validate messages exist
    total_messages = len(channel['messages'])
    if total_messages <= 0:
        return {
            "messages": [],
            "start": start,
            "end": -1
        }

    # Validate start point
    if start > (total_messages - 1) or start < 0:
        raise ValueError(CHANNEL_NO_MORE_MSG)

    # Find index for the most recent message (reference list backwards)
    start_index = len(channel['messages']) - 1 - start
    # Get all recent messages up to 50
    messages = []
    end = start + 49
    for msg_num in range(50):
        index = start_index - msg_num
        # If there are less than 50 msgs
        if index < 0:
            end = -1
            break

        # Get message object
        message_id = channel['messages'][index]
        message = database.get_message_by_id(message_id)

        # If message is sent later or not there
        if message is None or\
                json_time_translator.json_to_datetime(message["time_created"]) >= datetime.utcnow():
            continue

        # Create output-able list of reacts
        react_list = []
        reacted_ids = []
        all_reacts = database.get_all_reacts(message_id)
        react_id = 1
        for react in all_reacts:
            is_this_user_reacted = False
            if react["react_id"] == react_id:
                reacted_ids.extend(react["u_id"])
                if u_id in react["u_id"]:
                    is_this_user_reacted = True
                # Only add the reaction if it has at least one count of a user
                react_list.append({
                    "react_id": react_id,
                    "u_ids": reacted_ids,
                    "is_this_user_reacted": is_this_user_reacted
                })

        # print(message["time_created"])
        # print(json_time_translator.json_to_datetime(message["time_created"]))
        # print(json_time_translator.json_to_timestamp(message["time_created"]))
        # Append to file
        messages.append({
            "message_id": message_id,
            "u_id": message["u_id"],
            "message": message["message"],
            "time_created": json_time_translator.json_to_timestamp(message["time_created"]),
            "reacts": react_list,
            "is_pinned": message["is_pinned"]
        })

    return {
        "messages": messages,
        "start": start,
        "end": end
    }