litecord/litecord/blueprints/dm_channels.py

153 lines
4.7 KiB
Python

"""
Litecord
Copyright (C) 2018-2019 Luna Mendes
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 3 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from quart import Blueprint, current_app as app, jsonify
from logbook import Logger
from litecord.blueprints.auth import token_check
from litecord.blueprints.checks import channel_check
from litecord.enums import ChannelType
from litecord.errors import BadRequest, Forbidden
from litecord.snowflake import get_snowflake
log = Logger(__name__)
bp = Blueprint('dm_channels', __name__)
async def _raw_gdm_add(channel_id, user_id):
await app.db.execute("""
INSERT INTO group_dm_members (id, member_id)
VALUES ($1, $2)
""", channel_id, user_id)
async def _raw_gdm_remove(channel_id, user_id):
await app.db.execute("""
DELETE FROM group_dm_members
WHERE id = $1 AND member_id = $2
""", channel_id, user_id)
async def _gdm_create(user_id, peer_id) -> int:
"""Create a group dm, given two users.
Returns the new GDM id.
"""
channel_id = get_snowflake()
await app.db.execute("""
INSERT INTO channels (id, channel_type)
VALUES ($1, $2)
""", channel_id, ChannelType.GROUP_DM.value)
await app.db.execute("""
INSERT INTO group_dm_channels (id, owner_id, name, icon)
VALUES ($1, $2, NULL, NULL)
""", channel_id, user_id)
await _raw_gdm_add(channel_id, user_id)
await _raw_gdm_add(channel_id, peer_id)
await app.dispatcher.sub('channel', channel_id, user_id)
await app.dispatcher.sub('channel', channel_id, peer_id)
chan = await app.storage.get_channel(channel_id)
await app.dispatcher.dispatch('channel', channel_id, 'CHANNEL_CREATE', chan)
return channel_id
async def _gdm_add_recipient(channel_id: int, peer_id: int, *, user_id=None):
"""Add a recipient to a Group DM.
Dispatches:
- A system message with the join (depending of user_id)
- A CHANNEL_CREATE to the peer.
- A CHANNEL_UPDATE to all remaining recipients.
"""
await _raw_gdm_add(channel_id, peer_id)
chan = await app.storage.get_channel(channel_id)
await app.dispatcher.dispatch('user', peer_id, 'CHANNEL_CREATE', chan)
await app.dispatcher.dispatch('channel', channel_id, 'CHANNEL_UPDATE', chan)
async def _gdm_remove_recipient(channel_id: int, peer_id: int, *, user_id=None):
"""Remove a member from a GDM.
Dispatches:
- A system message with the leave or forced removal (depending if user_id)
exists or not.
- A CHANNEL_DELETE to the peer.
- A CHANNEL_UPDATE to all remaining recipients.
"""
await _raw_gdm_remove(channel_id, peer_id)
chan = await app.storage.get_channel(channel_id)
await app.dispatcher.dispatch('user', peer_id, 'CHANNEL_DELETE', chan)
await app.dispatcher.dispatch('channel', channel_id, 'CHANNEL_UPDATE', chan)
@bp.route('/<int:dm_chan>/recipients/<int:peer_id>', methods=['PUT'])
async def add_to_group_dm(dm_chan, peer_id):
"""Adds a member to a group dm OR creates a group dm."""
user_id = await token_check()
# other_id is the owner of the group dm (gdm) if the
# given channel is a gdm
# other_id is the peer of the dm if the given channel is a dm
ctype, other_id = await channel_check(
user_id, dm_chan,
only=[ChannelType.DM, ChannelType.GROUP_DM]
)
# check relationship with the given user id
# and the user id making the request
friends = await app.user_storage.are_friends_with(user_id, peer_id)
if not friends:
raise BadRequest('Cant insert peer into dm')
if ctype == ChannelType.DM:
dm_chan = await _gdm_create(
user_id, other_id
)
await _gdm_add_recipient(dm_chan, peer_id, user_id=user_id)
return jsonify(
await app.storage.get_channel(dm_chan)
)
@bp.route('/<int:dm_chan>/recipients/<int:user_id>', methods=['DELETE'])
async def remove_from_group_dm(dm_chan, user_id):
"""Remove users from group dm."""
user_id = await token_check()
_ctype, owner_id = await channel_check(
user_id, dm_chan, only=ChannelType.GROUP_DM
)
if owner_id != user_id:
raise Forbidden('You are now the owner of the group DM')
await _gdm_remove_recipient(dm_chan, user_id)
return '', 204