Example #1
0
async def patch_message(req: web.Request) -> web.Response:
    message_id = req["match_info"]["message_id"]

    params = {k: v for k, v in req["body"].items() if v is not None}
    if not params:
        raise web.HTTPNotModified()

    record = await req.config_dict["pg_conn"].fetchval(
        MESSAGE.update_query_for(
            "messages", message_id, params.keys(), returning=False
        ),
        *params.values(),
        req.config_dict["sf_gen"].gen_id(),
    )

    if record is None:
        raise web.HTTPNotModified

    # FIXME: reduce number of queries!!! (3 here)
    new_row = await req.config_dict["pg_conn"].fetchrow(
        f"SELECT {MESSAGE} FROM messages_with_author WHERE id = $1", message_id
    )

    diff = MESSAGE.diff_to_json(req["message"], new_row)

    req.config_dict["emitter"].emit(events.MESSAGE_UPDATE(payload=diff))

    return web.json_response(diff)
Example #2
0
async def create_channel(req: web.Request) -> web.Response:
    query = req["body"]

    user_id = req["access_token"].user_id

    recipients = set(query["recipients"])

    channel_id = req.config_dict["sf_gen"].gen_id()

    async with req.config_dict["pg_conn"].acquire() as conn:
        async with conn.transaction():
            channel = await conn.fetchrow(
                f"SELECT {CHANNEL} FROM create_channel($1, $2, $3, $4)",
                channel_id,
                user_id,
                query["name"],
                recipients,
            )

            message = await conn.fetchrow(
                f"SELECT {MESSAGE} FROM create_message($1, $2, $3, $4, type:=$5)",
                req.config_dict["sf_gen"].gen_id(),
                channel_id,
                user_id,
                "",
                MessageTypes.CHANNEL_CREATE.value,
            )

    req.config_dict["emitter"].emit(
        events.MESSAGE_CREATE(payload=MESSAGE.to_json(message))
    )

    return web.json_response(CHANNEL.to_json(channel))
Example #3
0
async def delete_message(req: web.Request) -> web.Response:
    channel_id = req["match_info"]["channel_id"]
    message_id = req["match_info"]["message_id"]

    message = await req.config_dict["pg_conn"].fetchrow(
        f"SELECT {MESSAGE} FROM messages_with_author WHERE channel_id = $1 AND id = $2",
        channel_id,
        message_id,
    )

    if message is None:
        raise web.HTTPNotFound(reason="Unknown message")

    message_data = MESSAGE.to_json(message)

    if int(message_data["author"]["id"]) != req["access_token"].user_id:
        await helpers.ensure_permissions(
            Permissions.DELETE_MESSAGES, request=req
        )

    await req.config_dict["pg_conn"].fetch(
        f"SELECT FROM delete_message($1, $2)", channel_id, message_id
    )

    req.config_dict["emitter"].emit(
        events.MESSAGE_DELETE(payload=message_data)
    )

    raise web.HTTPNoContent()
Example #4
0
async def remove_pin(req: web.Request) -> web.Response:
    channel_id = req["match_info"]["channel_id"]
    message_id = req["match_info"]["message_id"]

    async with req.config_dict["pg_conn"].acquire() as conn:
        async with conn.transaction():
            unpin_success = await conn.fetchval(
                "SELECT * FROM remove_channel_pin($1, $2)",
                message_id,
                channel_id,
            )
            if not unpin_success:
                raise web.HTTPBadRequest(
                    reason="Failed to unpin message. Does it belong to channel?"
                )

            message = await conn.fetchrow(
                f"SELECT {MESSAGE} FROM create_message($1, $2, $3, $4, type:=$5)",
                req.config_dict["sf_gen"].gen_id(),
                channel_id,
                req["access_token"].user_id,
                "",
                MessageTypes.CHANNEL_PIN_REMOVE.value,
            )

    req.config_dict["emitter"].emit(
        events.MESSAGE_CREATE(payload=MESSAGE.to_json(message))
    )

    raise web.HTTPNoContent()
Example #5
0
async def add_channel_recipient(req: web.Request) -> web.Response:
    await helpers.ensure_permissions(Permissions.INVITE_MEMBERS, request=req)

    channel_id = req["match_info"]["channel_id"]
    user_id = req["match_info"]["user_id"]

    await ensure_existance(req, "users", user_id, "User")

    async with req.config_dict["pg_conn"].acquire() as conn:
        async with conn.transaction():
            success = await conn.fetchval(
                "SELECT * FROM add_channel_user($1, $2)", channel_id, user_id
            )

            if not success:
                raise web.HTTPNotModified(reason="Is user already in channel?")

            message = await conn.fetchrow(
                f"SELECT {MESSAGE} FROM create_message($1, $2, $3, $4, type:=$5)",
                req.config_dict["sf_gen"].gen_id(),
                channel_id,
                user_id,
                "",
                MessageTypes.RECIPIENT_ADD.value,
            )

    req.config_dict["emitter"].emit(
        events.MESSAGE_CREATE(payload=MESSAGE.to_json(message))
    )

    raise web.HTTPNoContent()
Example #6
0
async def get_messages(req: web.Request) -> web.Response:
    channel_id = req["match_info"]["channel_id"]

    offset = req["query"]["offset"]
    limit = req["query"]["limit"]

    records = await req.config_dict["pg_conn"].fetch(
        f"SELECT {MESSAGE} FROM messages_with_author WHERE channel_id=$1 ORDER BY id LIMIT $2 OFFSET $3",
        channel_id,
        limit,
        offset,
    )

    return web.json_response([MESSAGE.to_json(record) for record in records])
Example #7
0
async def get_message(req: web.Request) -> web.Response:
    channel_id = req["match_info"]["channel_id"]
    message_id = req["match_info"]["message_id"]

    record = await req.config_dict["pg_conn"].fetchrow(
        f"SELECT {MESSAGE} FROM messages_with_author WHERE channel_id=$1 AND id=$2",
        channel_id,
        message_id,
    )

    if record is None:
        raise web.HTTPNotFound(reason="Message not found")

    return web.json_response(MESSAGE.to_json(record))
Example #8
0
async def create_message(req: web.Request) -> web.Response:
    message = await req.config_dict["pg_conn"].fetchrow(
        f"SELECT {MESSAGE} FROM create_message($1, $2, $3, $4)",
        req.config_dict["sf_gen"].gen_id(),
        req["match_info"]["channel_id"],
        req["access_token"].user_id,
        req["body"]["content"],
    )

    data = MESSAGE.to_json(message)

    req.config_dict["emitter"].emit(events.MESSAGE_CREATE(payload=data))

    return web.json_response(data)
Example #9
0
async def get_pins(req: web.Request) -> web.Response:
    channel_id = req["match_info"]["channel_id"]

    async with req.config_dict["pg_conn"].acquire() as conn:
        async with conn.transaction():
            pin_ids = await conn.fetchval(
                "SELECT pinned_ids FROM channels WHERE id = $1", channel_id
            )

        records = await conn.fetch(
            f"SELECT {MESSAGE} FROM messages_with_author WHERE id = ANY($1)",
            pin_ids,
        )

    return web.json_response([MESSAGE.to_json(record) for record in records])
Example #10
0
async def edit_channel(req: web.Request) -> web.Response:
    await helpers.ensure_permissions(Permissions.MODIFY_CHANNEL, request=req)

    channel_id = req["match_info"]["channel_id"]

    async with req.config_dict["pg_conn"].acquire() as conn:
        async with conn.transaction():
            old_channel = await conn.fetchrow(
                f"SELECT {CHANNEL} FROM channels WHERE id = $1", channel_id
            )

            channel = await req.config_dict["pg_conn"].fetchrow(
                CHANNEL.update_query_for(
                    "channels", channel_id, req["body"].keys()
                ),
                req["body"]["name"],
            )

            if channel is None:
                raise web.HTTPNotModified

            message = await conn.fetchrow(
                f"SELECT {MESSAGE} FROM create_message($1, $2, $3, $4, type:=$5)",
                req.config_dict["sf_gen"].gen_id(),
                channel_id,
                req["access_token"].user_id,
                "",
                MessageTypes.CHANNEL_NAME_UPDATE.value,
            )

    diff = CHANNEL.diff_to_json(old_channel, channel)

    req.config_dict["emitter"].emit(events.CHANNEL_UPDATE(payload=diff))
    req.config_dict["emitter"].emit(
        events.MESSAGE_CREATE(payload=MESSAGE.to_json(message))
    )

    return web.json_response(diff)
Example #11
0
async def add_pin(req: web.Request) -> web.Response:
    channel_id = req["match_info"]["channel_id"]
    message_id = req["match_info"]["message_id"]

    async with req.config_dict["pg_conn"].acquire() as conn:
        async with conn.transaction():
            pins_ids = await conn.fetchval(
                "SELECT pinned_ids FROM channels WHERE id = $1", channel_id
            )
            if len(pins_ids) >= 50:
                raise web.HTTPBadRequest(reason="Too many pins (>= 50)")

            if message_id in pins_ids:
                raise web.HTTPNotModified(reason="Already pinned")

            pin_success = await conn.fetchval(
                "SELECT * FROM add_channel_pin($1, $2)", message_id, channel_id
            )
            if not pin_success:
                raise web.HTTPBadRequest(
                    reason="Failed to pin message. Does it belong to channel?"
                )

            message = await conn.fetchrow(
                f"SELECT {MESSAGE} FROM create_message($1, $2, $3, $4, type:=$5)",
                req.config_dict["sf_gen"].gen_id(),
                channel_id,
                req["access_token"].user_id,
                "",
                MessageTypes.CHANNEL_PIN_ADD.value,
            )

    req.config_dict["emitter"].emit(
        events.MESSAGE_CREATE(payload=MESSAGE.to_json(message))
    )

    raise web.HTTPNoContent()