[IMP] mail: clean up code of RTC join/leave
Part of task-2366708 closes odoo/odoo#76528 X-original-commit: 9a05dfe06d9d5706d0e45ad14d6ef8902d6b276e Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This commit is contained in:
@@ -418,7 +418,7 @@ class DiscussController(http.Controller):
|
||||
:param int channel_id: id of the channel to join
|
||||
"""
|
||||
channel_partner_sudo = request.env['mail.channel.partner']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
return channel_partner_sudo.channel_id._join_call()
|
||||
return channel_partner_sudo._rtc_join_call()
|
||||
|
||||
@http.route('/mail/rtc/channel/leave_call', methods=['POST'], type="json", auth="public")
|
||||
def channel_call_leave(self, channel_id):
|
||||
@@ -426,7 +426,7 @@ class DiscussController(http.Controller):
|
||||
:param int channel_id: id of the channel from which to disconnect
|
||||
"""
|
||||
channel_partner_sudo = request.env['mail.channel.partner']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
channel_partner_sudo.channel_id._leave_call()
|
||||
return channel_partner_sudo._rtc_leave_call()
|
||||
|
||||
@http.route('/mail/rtc/channel/cancel_call_invitation', methods=['POST'], type="json", auth="public")
|
||||
def channel_call_cancel_invitation(self, channel_id, partner_ids=None, guest_ids=None):
|
||||
@@ -437,7 +437,7 @@ class DiscussController(http.Controller):
|
||||
if either partner_ids or guest_ids is set, only the specified ids will be invited.
|
||||
"""
|
||||
channel_partner_sudo = request.env['mail.channel.partner']._get_as_sudo_from_request_or_raise(request=request, channel_id=int(channel_id))
|
||||
channel_partner_sudo.channel_id._cancel_rtc_invitations(partner_ids=partner_ids, guest_ids=guest_ids, inviting_member=channel_partner_sudo)
|
||||
return channel_partner_sudo.channel_id._rtc_cancel_invitations(partner_ids=partner_ids, guest_ids=guest_ids)
|
||||
|
||||
@http.route('/mail/rtc/audio_worklet_processor', methods=['GET'], type='http', auth='public')
|
||||
def audio_worklet_processor(self):
|
||||
|
||||
@@ -294,8 +294,8 @@ class Channel(models.Model):
|
||||
""" Adds the given partner_ids and guest_ids as member of self channels. """
|
||||
self.check_access_rights('write')
|
||||
self.check_access_rule('write')
|
||||
partners = self.env['res.partner'].browse(partner_ids or [])
|
||||
guests = self.env['mail.guest'].browse(guest_ids or [])
|
||||
partners = self.env['res.partner'].browse(partner_ids or []).exists()
|
||||
guests = self.env['mail.guest'].browse(guest_ids or []).exists()
|
||||
members_to_create = []
|
||||
for channel in self:
|
||||
if channel.public == 'groups':
|
||||
@@ -318,8 +318,6 @@ class Channel(models.Model):
|
||||
'channel_id': channel.id,
|
||||
} for partner in guests - existing_guests]
|
||||
new_members = self.env['mail.channel.partner'].sudo().create(members_to_create)
|
||||
if invite_to_rtc_call:
|
||||
self._invite_members_to_rtc(partner_ids=partner_ids, guest_ids=guest_ids)
|
||||
for channel_partner in new_members.filtered(lambda channel_partner: channel_partner.partner_id):
|
||||
user = channel_partner.partner_id.user_ids[0] if channel_partner.partner_id.user_ids else self.env['res.users']
|
||||
# notify invited members through the bus
|
||||
@@ -352,9 +350,19 @@ class Channel(models.Model):
|
||||
'id': channel_partner.channel_id.id,
|
||||
'memberCount': channel_partner.channel_id.member_count,
|
||||
'members': [('insert', new_partner_data)],
|
||||
'invitedPartners': [('insert', [{'id': new_partner_data['id']}] if invite_to_rtc_call else [])]
|
||||
},
|
||||
})
|
||||
if invite_to_rtc_call:
|
||||
if self.env.user._is_public() and 'guest' in self.env.context:
|
||||
guest = self.env.context.get('guest')
|
||||
partner = self.env['res.partner']
|
||||
else:
|
||||
guest = self.env['mail.guest']
|
||||
partner = self.env.user.partner_id
|
||||
for channel in self:
|
||||
current_channel_partner = self.env['mail.channel.partner'].sudo().search([('channel_id', '=', channel.id), ('partner_id', '=', partner.id), ('guest_id', '=', guest.id)])
|
||||
if current_channel_partner and current_channel_partner.rtc_session_ids:
|
||||
current_channel_partner._rtc_invite_members(partner_ids=partners.ids, guest_ids=guests.ids)
|
||||
|
||||
def _action_remove_members(self, partners):
|
||||
""" Private implementation to remove members from channels. Done as sudo
|
||||
@@ -389,165 +397,53 @@ class Channel(models.Model):
|
||||
# RTC
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def _cancel_rtc_invitations(self, partner_ids=None, guest_ids=None, inviting_member=None):
|
||||
def _rtc_cancel_invitations(self, partner_ids=None, guest_ids=None):
|
||||
""" Cancels the invitations of the RTC call from all invited members (or the specified partner_ids).
|
||||
:param list partner_ids: list of the partner ids from which the invitation has to be removed
|
||||
:param list guest_ids: list of the guest ids from which the invitation has to be removed
|
||||
if either partner_ids or guest_ids is set, only the specified ids will be invited.
|
||||
:param inviting_member: if specified, only removes invitations if they are coming
|
||||
from this channel member
|
||||
"""
|
||||
self.ensure_one()
|
||||
notifications = []
|
||||
domain = ['&', ('rtc_inviting_session_id', '!=', False), ('channel_id', '=', self.id)]
|
||||
if inviting_member:
|
||||
domain = expression.AND([domain, [('rtc_inviting_session_id.channel_partner_id', '=', inviting_member.id)]])
|
||||
channel_partner_domain = [
|
||||
('channel_id', '=', self.id),
|
||||
('rtc_inviting_session_id', '!=', False),
|
||||
]
|
||||
if partner_ids or guest_ids:
|
||||
domain = expression.AND([domain, ['|', ('partner_id', 'in', partner_ids or []), ('guest_id', 'in', guest_ids or [])]])
|
||||
channel_partners = self.env['mail.channel.partner'].search(domain)
|
||||
for member in channel_partners:
|
||||
member.write({'rtc_inviting_session_id': False})
|
||||
model, record_id = ('mail.guest', member.guest_id.id) if member.guest_id else ('res.partner', member.partner_id.id)
|
||||
notifications.append([
|
||||
(self._cr.dbname, model, record_id),
|
||||
{
|
||||
'type': 'rtc_incoming_invitation_update',
|
||||
'payload': {
|
||||
'channelId': self.id,
|
||||
},
|
||||
},
|
||||
])
|
||||
self.env['bus.bus'].sendmany(notifications)
|
||||
|
||||
def _invite_members_to_rtc(self, partner_ids=None, guest_ids=None):
|
||||
""" Sends invitations to join the RTC call to all connected members of the thread who are not already invited.
|
||||
:param list partner_ids: list of the partner ids to invite
|
||||
:param list guest_ids: list of the guest ids to invite
|
||||
|
||||
if either partner_ids or guest_ids is set, only the specified ids will be invited.
|
||||
"""
|
||||
self.ensure_one()
|
||||
|
||||
if self.env.user._is_public():
|
||||
guest = self.env.context.get('guest')
|
||||
partner = self.env['res.partner']
|
||||
else:
|
||||
guest = self.env['mail.guest']
|
||||
partner = self.env.user.partner_id
|
||||
|
||||
def is_current_user(r):
|
||||
return (guest and r.guest_id == guest) or r.partner_id == partner
|
||||
|
||||
current_rtc_session = self.rtc_session_ids.filtered(is_current_user)
|
||||
if not current_rtc_session:
|
||||
return [], []
|
||||
|
||||
current_sessions_channel_partners = self.rtc_session_ids.channel_partner_id
|
||||
notifications = []
|
||||
invited_partners = []
|
||||
invited_guests = []
|
||||
domain = ['&', '&', ('rtc_inviting_session_id', '=', False), ('channel_id', '=', self.id), ('id', 'not in', current_sessions_channel_partners.ids)]
|
||||
if partner:
|
||||
domain = expression.AND([domain, [('partner_id', '!=', partner.id)]])
|
||||
if guest:
|
||||
domain = expression.AND([domain, [('guest_id', '!=', guest.id)]])
|
||||
if partner_ids or guest_ids:
|
||||
domain = expression.AND([domain, ['|', ('partner_id', 'in', partner_ids or []), ('guest_id', 'in', guest_ids or [])]])
|
||||
channel_partners = self.env['mail.channel.partner'].search(domain)
|
||||
for member in channel_partners:
|
||||
member.rtc_inviting_session_id = current_rtc_session.id
|
||||
channel_partner_domain = expression.AND([channel_partner_domain, [
|
||||
'|',
|
||||
('partner_id', 'in', partner_ids or []),
|
||||
('guest_id', 'in', guest_ids or []),
|
||||
]])
|
||||
invited_partners = self.env['res.partner']
|
||||
invited_guests = self.env['mail.guest']
|
||||
invitation_notifications = []
|
||||
for member in self.env['mail.channel.partner'].search(channel_partner_domain):
|
||||
member.rtc_inviting_session_id = False
|
||||
if member.partner_id:
|
||||
invited_partners.append({
|
||||
'id': member.partner_id.id,
|
||||
'name': member.partner_id.name,
|
||||
})
|
||||
elif member.guest_id:
|
||||
invited_guests.append({
|
||||
'id': member.guest_id.id,
|
||||
'name': member.guest_id.name,
|
||||
})
|
||||
model, record_id = ('mail.guest', member.guest_id.id) if member.guest_id else ('res.partner', member.partner_id.id)
|
||||
notifications.append([
|
||||
(self._cr.dbname, model, record_id),
|
||||
{
|
||||
'type': 'rtc_incoming_invitation_update',
|
||||
'payload': {
|
||||
'channelId': self.id,
|
||||
'rtcSession': current_rtc_session._mail_rtc_session_format(),
|
||||
},
|
||||
},
|
||||
])
|
||||
notification = _("%s started a live conference", partner.name or guest.name)
|
||||
self.message_post(body=notification, message_type='notification')
|
||||
self.env['bus.bus'].sendmany(notifications)
|
||||
return invited_partners, invited_guests
|
||||
|
||||
def _join_call(self):
|
||||
self.ensure_one()
|
||||
session_data, session_id = self._update_call_participation(joining=True)
|
||||
if not session_id:
|
||||
return
|
||||
ice_servers = self.env['mail.ice.server']._get_ice_servers()
|
||||
invited_partners = []
|
||||
invited_guests = []
|
||||
if len(self.rtc_session_ids) == 1 and self.channel_type in {'chat', 'group'}:
|
||||
invited_partners, invited_guests = self._invite_members_to_rtc()
|
||||
return {
|
||||
'rtcSessions': session_data,
|
||||
'iceServers': ice_servers or False,
|
||||
'invitedGuests': invited_guests,
|
||||
'invitedPartners': invited_partners,
|
||||
'sessionId': session_id,
|
||||
}
|
||||
|
||||
def _leave_call(self):
|
||||
self.ensure_one()
|
||||
self._update_call_participation(joining=False)
|
||||
|
||||
def _update_call_participation(self, joining=True):
|
||||
""" Updates the call participation of the current partner and notifies members of
|
||||
the channel if necessary.
|
||||
:param bool joining : true if joining the call, false if leaving.
|
||||
"""
|
||||
if self.env.user._is_public():
|
||||
guest = self.env.context.get('guest')
|
||||
partner = self.env['res.partner']
|
||||
else:
|
||||
guest = self.env['mail.guest']
|
||||
partner = self.env.user.partner_id
|
||||
new_session_id = None
|
||||
current_channel_partner = self.env['mail.channel.partner'].search([('channel_id', '=', self.id), ('partner_id', '=', partner.id), ('guest_id', '=', guest.id)], limit=1)
|
||||
if not current_channel_partner:
|
||||
return
|
||||
current_channel_partner._remove_rtc_invitation()
|
||||
old_sessions = self.rtc_session_ids.filtered(lambda s: s.channel_partner_id == current_channel_partner)
|
||||
old_sessions._disconnect()
|
||||
if joining:
|
||||
new_session = self.env['mail.channel.rtc.session'].create({'channel_partner_id': current_channel_partner.id})
|
||||
new_session_id = new_session.id
|
||||
elif not old_sessions:
|
||||
return
|
||||
|
||||
session_data_by_channel = self._notify_rtc_sessions_change()
|
||||
return session_data_by_channel.get(self.id, []), new_session_id
|
||||
|
||||
def _notify_rtc_sessions_change(self):
|
||||
session_data_by_channel = self.rtc_session_ids._mail_rtc_session_format_by_channel()
|
||||
notifications = []
|
||||
for record in self:
|
||||
sessions_data = session_data_by_channel.get(record.id, [])
|
||||
if not sessions_data:
|
||||
# if there is no member left in the rtc call, all invitations are reset
|
||||
record._cancel_rtc_invitations()
|
||||
notifications.append([(self._cr.dbname, 'mail.channel', record.id), {
|
||||
'type': 'rtc_sessions_update',
|
||||
invited_partners |= member.partner_id
|
||||
target = (self._cr.dbname, 'res.partner', member.partner_id.id)
|
||||
else:
|
||||
invited_guests |= member.guest_id
|
||||
target = (self._cr.dbname, 'mail.guest', member.guest_id.id)
|
||||
invitation_notifications.append((target, {
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'channelId': record.id,
|
||||
'rtcSessions': sessions_data,
|
||||
'id': self.id,
|
||||
'rtcInvitingSession': [('unlink',)],
|
||||
},
|
||||
}])
|
||||
self.env['bus.bus'].sendmany(notifications)
|
||||
return session_data_by_channel
|
||||
}))
|
||||
self.env['bus.bus'].sendmany(invitation_notifications)
|
||||
channel_data = {'id': self.id}
|
||||
if invited_guests:
|
||||
channel_data['invitedGuests'] = [('insert-and-unlink', [{'id': guest.id} for guest in invited_guests])]
|
||||
if invited_partners:
|
||||
channel_data['invitedPartners'] = [('insert-and-unlink', [{'id': partner.id} for partner in invited_partners])]
|
||||
if invited_partners or invited_guests:
|
||||
self.env['bus.bus'].sendone((self._cr.dbname, 'mail.channel', self.id), {
|
||||
'type': 'mail.channel_update',
|
||||
'payload': channel_data,
|
||||
})
|
||||
return channel_data
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# MAILING
|
||||
@@ -660,9 +556,9 @@ class Channel(models.Model):
|
||||
self.env['bus.bus'].sudo().sendmany(bus_notifications)
|
||||
# Last interest is updated for a chat when posting a message.
|
||||
# So a notification is needed to update UI.
|
||||
if self.is_chat:
|
||||
if self.is_chat or self.channel_type == 'group':
|
||||
notifications = []
|
||||
for channel_partners in self.channel_last_seen_partner_ids:
|
||||
for channel_partners in self.channel_last_seen_partner_ids.filtered('partner_id'):
|
||||
notif = {
|
||||
'type': 'mail.channel_last_interest_dt_changed',
|
||||
'payload': {
|
||||
@@ -873,7 +769,7 @@ class Channel(models.Model):
|
||||
info['last_interest_dt'] = partner_channel.last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
if partner_channel.rtc_inviting_session_id:
|
||||
info['rtc_inviting_session'] = {'id': partner_channel.rtc_inviting_session_id.id}
|
||||
# add members infos
|
||||
# add members info
|
||||
if channel.channel_type != 'channel':
|
||||
# avoid sending potentially a lot of members for big channels
|
||||
# exclude chat and other small channels from this optimization because they are
|
||||
@@ -886,9 +782,12 @@ class Channel(models.Model):
|
||||
'seen_message_id': cp.seen_message_id.id,
|
||||
} for cp in channel_partners], key=lambda p: p['partner_id'])
|
||||
|
||||
# add rtc sessions infos
|
||||
if rtc_sessions_by_channel.get(channel.id):
|
||||
info['rtc_sessions'] = rtc_sessions_by_channel[channel.id]
|
||||
# add RTC sessions info
|
||||
info.update({
|
||||
'invitedGuests': [('insert-and-replace', [{'id': guest.id, 'name': guest.name} for guest in channel_partners.filtered('rtc_inviting_session_id').guest_id])],
|
||||
'invitedPartners': [('insert-and-replace', [{'id': partner.id, 'name': partner.name} for partner in channel_partners.filtered('rtc_inviting_session_id').partner_id])],
|
||||
'rtcSessions': [('insert-and-replace', rtc_sessions_by_channel.get(channel, []))],
|
||||
})
|
||||
|
||||
channel_infos.append(info)
|
||||
return channel_infos
|
||||
|
||||
@@ -5,6 +5,7 @@ from werkzeug.exceptions import NotFound
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import AccessError
|
||||
from odoo.osv import expression
|
||||
|
||||
|
||||
class ChannelPartner(models.Model):
|
||||
@@ -26,34 +27,13 @@ class ChannelPartner(models.Model):
|
||||
is_minimized = fields.Boolean("Conversation is minimized")
|
||||
is_pinned = fields.Boolean("Is pinned on the interface", default=True)
|
||||
last_interest_dt = fields.Datetime("Last Interest", default=fields.Datetime.now, help="Contains the date and time of the last interesting event that happened in this channel for this partner. This includes: creating, joining, pinning, and new message posted.")
|
||||
# RTC
|
||||
rtc_session_ids = fields.One2many(string="RTC Sessions", comodel_name='mail.channel.rtc.session', inverse_name='channel_partner_id')
|
||||
rtc_inviting_session_id = fields.Many2one('mail.channel.rtc.session', string='Ringing session')
|
||||
|
||||
def name_get(self):
|
||||
return [(record.id, record.partner_id.name or record.guest_id.name) for record in self]
|
||||
|
||||
def _remove_rtc_invitation(self):
|
||||
""" Removes the invitation to the rtc call and notifies the inviting partner if removed. """
|
||||
notifications = []
|
||||
for record in self:
|
||||
if not record.rtc_inviting_session_id:
|
||||
continue
|
||||
model, record_id = ('mail.guest', record.rtc_inviting_session_id.guest_id.id) if record.rtc_inviting_session_id.guest_id else (
|
||||
'res.partner', record.rtc_inviting_session_id.partner_id.id)
|
||||
payload = {'channelId': record.channel_id.id}
|
||||
if record.partner_id:
|
||||
payload['partnerId'] = record.partner_id.id
|
||||
else:
|
||||
payload['guestId'] = record.guest_id.id
|
||||
notifications.append([
|
||||
(self._cr.dbname, model, record_id),
|
||||
{
|
||||
'type': 'rtc_outgoing_invitation_ended',
|
||||
'payload': payload,
|
||||
},
|
||||
])
|
||||
self.write({'rtc_inviting_session_id': False})
|
||||
self.env['bus.bus'].sendmany(notifications)
|
||||
|
||||
def init(self):
|
||||
self.env.cr.execute("CREATE UNIQUE INDEX IF NOT EXISTS mail_channel_partner_partner_unique ON %s (channel_id, partner_id) WHERE partner_id IS NOT NULL" % self._table)
|
||||
self.env.cr.execute("CREATE UNIQUE INDEX IF NOT EXISTS mail_channel_partner_guest_unique ON %s (channel_id, guest_id) WHERE guest_id IS NOT NULL" % self._table)
|
||||
@@ -111,3 +91,83 @@ class ChannelPartner(models.Model):
|
||||
if guest:
|
||||
return guest.env['mail.channel.partner'].sudo().search([('channel_id', '=', channel_id), ('guest_id', '=', guest.id)], limit=1)
|
||||
return self.env['mail.channel.partner'].sudo()
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# RTC (voice/video)
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
def _rtc_join_call(self):
|
||||
self.ensure_one()
|
||||
self.channel_id._rtc_cancel_invitations(partner_ids=self.partner_id.ids, guest_ids=self.guest_id.ids)
|
||||
self.rtc_session_ids._disconnect()
|
||||
rtc_session = self.env['mail.channel.rtc.session'].create({'channel_partner_id': self.id})
|
||||
res = {
|
||||
'iceServers': self.env['mail.ice.server']._get_ice_servers() or False,
|
||||
'rtcSessions': [('insert-and-replace', self.channel_id.rtc_session_ids._mail_rtc_session_format_by_channel().get(self.channel_id))],
|
||||
'sessionId': rtc_session.id,
|
||||
}
|
||||
if len(self.channel_id.rtc_session_ids) == 1 and self.channel_id.channel_type in {'chat', 'group'}:
|
||||
self.channel_id.message_post(body=_("%s started a live conference", self.partner_id.name or self.guest_id.name), message_type='notification')
|
||||
invited_partners, invited_guests = self._rtc_invite_members()
|
||||
if invited_guests:
|
||||
res['invitedGuests'] = [('insert', [{'id': guest.id, 'name': guest.name} for guest in invited_guests])]
|
||||
if invited_partners:
|
||||
res['invitedPartners'] = [('insert', [{'id': partner.id, 'name': partner.name} for partner in invited_partners])]
|
||||
return res
|
||||
|
||||
def _rtc_leave_call(self):
|
||||
self.ensure_one()
|
||||
if self.rtc_session_ids:
|
||||
self.rtc_session_ids.unlink()
|
||||
else:
|
||||
return self.channel_id._rtc_cancel_invitations(partner_ids=self.partner_id.ids, guest_ids=self.guest_id.ids)
|
||||
|
||||
def _rtc_invite_members(self, partner_ids=None, guest_ids=None):
|
||||
""" Sends invitations to join the RTC call to all connected members of the thread who are not already invited.
|
||||
:param list partner_ids: list of the partner ids to invite
|
||||
:param list guest_ids: list of the guest ids to invite
|
||||
|
||||
if either partner_ids or guest_ids is set, only the specified ids will be invited.
|
||||
"""
|
||||
self.ensure_one()
|
||||
channel_partner_domain = [
|
||||
('channel_id', '=', self.channel_id.id),
|
||||
('rtc_inviting_session_id', '=', False),
|
||||
('rtc_session_ids', '=', False),
|
||||
]
|
||||
if partner_ids or guest_ids:
|
||||
channel_partner_domain = expression.AND([channel_partner_domain, [
|
||||
'|',
|
||||
('partner_id', 'in', partner_ids or []),
|
||||
('guest_id', 'in', guest_ids or []),
|
||||
]])
|
||||
invitation_notifications = []
|
||||
invited_partners = self.env['res.partner']
|
||||
invited_guests = self.env['mail.guest']
|
||||
for member in self.env['mail.channel.partner'].search(channel_partner_domain):
|
||||
member.rtc_inviting_session_id = self.rtc_session_ids.id
|
||||
if member.partner_id:
|
||||
invited_partners |= member.partner_id
|
||||
target = (self._cr.dbname, 'res.partner', member.partner_id.id)
|
||||
else:
|
||||
invited_guests |= member.guest_id
|
||||
target = (self._cr.dbname, 'mail.guest', member.guest_id.id)
|
||||
invitation_notifications.append((target, {
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': self.channel_id.id,
|
||||
'rtcInvitingSession': [('insert', self.rtc_session_ids._mail_rtc_session_format())],
|
||||
},
|
||||
}))
|
||||
self.env['bus.bus'].sendmany(invitation_notifications)
|
||||
if invited_guests or invited_partners:
|
||||
channel_data = {'id': self.channel_id.id}
|
||||
if invited_guests:
|
||||
channel_data['invitedGuests'] = [('insert', [{'id': guest.id, 'name': guest.name} for guest in invited_guests])]
|
||||
if invited_partners:
|
||||
channel_data['invitedPartners'] = [('insert', [{'id': partner.id, 'name': partner.name} for partner in invited_partners])]
|
||||
self.env['bus.bus'].sendone((self._cr.dbname, 'mail.channel', self.channel_id.id), {
|
||||
'type': 'mail.channel_update',
|
||||
'payload': channel_data,
|
||||
})
|
||||
return invited_partners, invited_guests
|
||||
|
||||
@@ -27,6 +27,35 @@ class MailRtcSession(models.Model):
|
||||
'There can only be one rtc session per channel partner')
|
||||
]
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
rtc_sessions = super().create(vals_list)
|
||||
self.env['bus.bus'].sendmany([((self._cr.dbname, 'mail.channel', channel.id), {
|
||||
'type': 'rtc_sessions_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert', sessions_data)],
|
||||
},
|
||||
}) for channel, sessions_data in rtc_sessions._mail_rtc_session_format_by_channel().items()])
|
||||
return rtc_sessions
|
||||
|
||||
def unlink(self):
|
||||
channels = self.channel_id
|
||||
for channel in channels:
|
||||
if channel.rtc_session_ids and len(channel.rtc_session_ids - self) == 0:
|
||||
# If there is no member left in the RTC call, all invitations are cancelled.
|
||||
# Note: invitation depends on field `rtc_inviting_session_id` so the cancel must be
|
||||
# done before the delete to be able to know who was invited.
|
||||
channel._rtc_cancel_invitations()
|
||||
self.env['bus.bus'].sendmany([((self._cr.dbname, 'mail.channel', channel.id), {
|
||||
'type': 'rtc_sessions_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert-and-unlink', [{'id': session_data['id']} for session_data in sessions_data])],
|
||||
},
|
||||
}) for channel, sessions_data in self._mail_rtc_session_format_by_channel().items()])
|
||||
return super().unlink()
|
||||
|
||||
def _update_and_broadcast(self, values):
|
||||
""" Updates the session and notifies all members of the channel
|
||||
of the change.
|
||||
@@ -35,10 +64,8 @@ class MailRtcSession(models.Model):
|
||||
self.write({key: values[key] for key in valid_values if key in valid_values})
|
||||
session_data = self._mail_rtc_session_format()
|
||||
self.env['bus.bus'].sendone((self._cr.dbname, 'mail.channel', self.channel_id.id), {
|
||||
'type': 'rtc_session_data_update',
|
||||
'payload': {
|
||||
'rtcSession': session_data,
|
||||
},
|
||||
'type': 'mail.rtc_session_update',
|
||||
'payload': session_data,
|
||||
})
|
||||
|
||||
@api.autovacuum
|
||||
@@ -47,34 +74,25 @@ class MailRtcSession(models.Model):
|
||||
this can happen when the server or the user's browser crash
|
||||
or when the user's odoo session ends.
|
||||
"""
|
||||
sessions = self.search([
|
||||
('write_date', '<', fields.Datetime.now() - relativedelta(days=1))
|
||||
])
|
||||
if not sessions:
|
||||
return
|
||||
channel_ids = sessions.channel_id
|
||||
sessions.unlink()
|
||||
channel_ids._notify_rtc_sessions_change()
|
||||
rtc_sessions = self.search([('write_date', '<', fields.Datetime.now() - relativedelta(days=1))])
|
||||
rtc_sessions._disconnect()
|
||||
|
||||
def action_disconnect(self):
|
||||
channels = self.channel_id
|
||||
self._disconnect()
|
||||
if channels:
|
||||
channels._notify_rtc_sessions_change()
|
||||
|
||||
def _disconnect(self):
|
||||
""" Unlinks the sessions and notifies the associated partners/guests that
|
||||
their session ended.
|
||||
"""
|
||||
notifications = []
|
||||
for record in self:
|
||||
model, record_id = ('mail.guest', record.guest_id.id) if record.guest_id else ('res.partner', record.partner_id.id)
|
||||
for rtc_session in self:
|
||||
model_name, record_id = ('mail.guest', rtc_session.guest_id.id) if rtc_session.guest_id else ('res.partner', rtc_session.partner_id.id)
|
||||
notifications.append([
|
||||
(self._cr.dbname, model, record_id),
|
||||
(self._cr.dbname, model_name, record_id),
|
||||
{
|
||||
'type': 'rtc_session_ended',
|
||||
'payload': {
|
||||
'sessionId': record.id,
|
||||
'sessionId': rtc_session.id,
|
||||
},
|
||||
},
|
||||
])
|
||||
@@ -105,27 +123,28 @@ class MailRtcSession(models.Model):
|
||||
return self.env['bus.bus'].sendmany(notifications)
|
||||
|
||||
def _mail_rtc_session_format(self):
|
||||
self.ensure_one()
|
||||
vals = {
|
||||
'id': self.id,
|
||||
'is_screen_sharing_on': self.is_screen_sharing_on,
|
||||
'is_muted': self.is_muted,
|
||||
'is_deaf': self.is_deaf,
|
||||
'is_camera_on': self.is_camera_on,
|
||||
'isCameraOn': self.is_camera_on,
|
||||
'isDeaf': self.is_deaf,
|
||||
'isMuted': self.is_muted,
|
||||
'isScreenSharingOn': self.is_screen_sharing_on,
|
||||
}
|
||||
if self.guest_id:
|
||||
vals['guest'] = {
|
||||
vals['guest'] = [('insert', {
|
||||
'id': self.guest_id.id,
|
||||
'name': self.guest_id.name,
|
||||
}
|
||||
})]
|
||||
else:
|
||||
vals['partner'] = {
|
||||
vals['partner'] = [('insert', {
|
||||
'id': self.partner_id.id,
|
||||
'name': self.partner_id.name,
|
||||
}
|
||||
})]
|
||||
return vals
|
||||
|
||||
def _mail_rtc_session_format_by_channel(self):
|
||||
data = {}
|
||||
for record in self:
|
||||
data.setdefault(record.channel_id.id, []).append(record._mail_rtc_session_format())
|
||||
for rtc_session in self:
|
||||
data.setdefault(rtc_session.channel_id, []).append(rtc_session._mail_rtc_session_format())
|
||||
return data
|
||||
|
||||
@@ -335,13 +335,14 @@ export class ModelManager {
|
||||
* @param {Listener} listener
|
||||
*/
|
||||
removeListener(listener) {
|
||||
this._listeners.delete(listener);
|
||||
this._listenersToNotifyInUpdateCycle.delete(listener);
|
||||
this._listenersToNotifyAfterUpdateCycle.delete(listener);
|
||||
for (const localId of this._localIdsObservedByListener.get(listener) || []) {
|
||||
this._listenersObservingLocalId.get(localId).delete(listener);
|
||||
if (this._listenersObservingFieldOfLocalId.has(localId)) {
|
||||
for (const [, componentsUsingField] of this._listenersObservingFieldOfLocalId.get(localId)) {
|
||||
componentsUsingField.delete(listener);
|
||||
for (const [, listenersUsingField] of this._listenersObservingFieldOfLocalId.get(localId)) {
|
||||
listenersUsingField.delete(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -794,7 +795,6 @@ export class ModelManager {
|
||||
this._createdRecords.delete(record);
|
||||
for (const listener of this._listenersObservingLocalId.get(record.localId)) {
|
||||
this._markListenerToNotify(listener);
|
||||
this._localIdsObservedByListener.get(listener).delete(record.localId);
|
||||
}
|
||||
for (const listener of this._listenersObservingAllByModel.get(Model)) {
|
||||
this._markListenerToNotify(listener);
|
||||
|
||||
+5
-36
@@ -93,20 +93,18 @@ function factory(dependencies) {
|
||||
return this.messaging.models['mail.guest'].insert(message.payload);
|
||||
case 'mail.message_update':
|
||||
return this.messaging.models['mail.message'].insert(message.payload);
|
||||
case 'mail.rtc_session_update':
|
||||
return this.messaging.models['mail.rtc_session'].insert(message.payload);
|
||||
case 'res.users_settings_changed':
|
||||
return this._handleNotificationResUsersSettings(message.payload);
|
||||
case 'rtc_peer_notification':
|
||||
return this._handleNotificationRtcPeerToPeer(message.payload);
|
||||
case 'rtc_incoming_invitation_update':
|
||||
return this._handleNotificationRtcInvitation(message.payload);
|
||||
case 'rtc_outgoing_invitation_ended':
|
||||
return this._handleNotificationRtcInvitationEnded(message.payload);
|
||||
case 'rtc_sessions_update':
|
||||
return this._handleNotificationRtcSessionUpdate(message.payload);
|
||||
case 'rtc_session_ended':
|
||||
return this._handleNotificationRtcSessionEnded(message.payload);
|
||||
case 'rtc_session_data_update':
|
||||
return this._handleNotificationRtcSessionDataUpdate(message.payload);
|
||||
case 'res_users_settings_volumes_update':
|
||||
return this._handleNotificationVolumeSettingUpdate(message.payload);
|
||||
}
|
||||
@@ -545,25 +543,6 @@ function factory(dependencies) {
|
||||
return channel.update({ rtcInvitingSession: unlink() });
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} data
|
||||
* @param {number} [data.channelId]
|
||||
* @param {number} [data.partnerId]
|
||||
*/
|
||||
async _handleNotificationRtcInvitationEnded({ channelId, partnerId, guestId }) {
|
||||
const channel = this.messaging.models['mail.thread'].findFromIdentifyingData({ id: channelId, model: 'mail.channel' });
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
const partner = partnerId && this.messaging.models['mail.partner'].findFromIdentifyingData({ id: partnerId });
|
||||
const guest = guestId && this.messaging.models['mail.guest'].findFromIdentifyingData({ id: guestId });
|
||||
channel.update({
|
||||
invitedPartners: partner && unlink(partner),
|
||||
invitedGuests: guest && unlink(guest),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} data
|
||||
@@ -574,16 +553,6 @@ function factory(dependencies) {
|
||||
this.messaging.mailRtc.handleNotification(sender, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} data
|
||||
* @param {Object} [data.rtcSession]
|
||||
*/
|
||||
async _handleNotificationRtcSessionDataUpdate({ rtcSession }) {
|
||||
const rtcSessionModel = this.messaging.models['mail.rtc_session'];
|
||||
rtcSessionModel.insert(rtcSessionModel.convertData(rtcSession));
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} data
|
||||
@@ -614,11 +583,11 @@ function factory(dependencies) {
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} data
|
||||
* @param {string} [data.channelId]
|
||||
* @param {string} [data.id]
|
||||
* @param {Object} [data.rtcSessions]
|
||||
*/
|
||||
async _handleNotificationRtcSessionUpdate({ channelId, rtcSessions }) {
|
||||
const channel = this.messaging.models['mail.thread'].findFromIdentifyingData({ id: channelId, model: 'mail.channel' });
|
||||
async _handleNotificationRtcSessionUpdate({ id, rtcSessions }) {
|
||||
const channel = this.messaging.models['mail.thread'].findFromIdentifyingData({ id, model: 'mail.channel' });
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -101,17 +101,16 @@ function factory(dependencies) {
|
||||
*/
|
||||
async filterCallees(currentSessions) {
|
||||
const currentSessionsTokens = new Set(currentSessions.map(session => session.peerToken));
|
||||
if (this.currentRtcSession && !currentSessionsTokens.has(this.currentRtcSession.peerToken)) {
|
||||
// if the current RTC session is not in the channel sessions, this call is no longer valid.
|
||||
this.channel && this.channel.endCall();
|
||||
return;
|
||||
}
|
||||
for (const token of Object.keys(this._peerConnections)) {
|
||||
if (!currentSessionsTokens.has(token)) {
|
||||
this._addLogEntry(token, 'session removed from the server');
|
||||
this._removePeer(token);
|
||||
}
|
||||
}
|
||||
if (this.channel && this.currentRtcSession && !currentSessionsTokens.has(this.currentRtcSession.peerToken)) {
|
||||
// if the current RTC session is not in the channel sessions, this call is no longer valid.
|
||||
this.channel.endCall();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+7
-7
@@ -2,7 +2,6 @@
|
||||
|
||||
import { registerNewModel } from '@mail/model/model_core';
|
||||
import { attr, many2one, one2one } from '@mail/model/model_field';
|
||||
import { unlink } from '@mail/model/model_field_command';
|
||||
|
||||
function factory(dependencies) {
|
||||
|
||||
@@ -33,10 +32,11 @@ function factory(dependencies) {
|
||||
* @param {MouseEvent} ev
|
||||
*/
|
||||
async onClick(ev) {
|
||||
if (!this.invitedPartner || this.invitedGuest) {
|
||||
if (!this.invitedPartner && !this.invitedGuest) {
|
||||
return;
|
||||
}
|
||||
await this.env.services.rpc(({
|
||||
const channel = this.channel;
|
||||
const channelData = await this.env.services.rpc(({
|
||||
route: '/mail/rtc/channel/cancel_call_invitation',
|
||||
params: {
|
||||
channel_id: this.channel.id,
|
||||
@@ -44,10 +44,10 @@ function factory(dependencies) {
|
||||
guest_ids: this.invitedGuest && [this.invitedGuest.id],
|
||||
},
|
||||
}));
|
||||
this.channel.update({
|
||||
invitedGuests: this.invitedGuest && unlink(this.invitedGuest),
|
||||
invitedPartners: this.invitedPartner && unlink(this.invitedPartner),
|
||||
});
|
||||
if (!channel.exists()) {
|
||||
return;
|
||||
}
|
||||
channel.update(channelData);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,42 +31,6 @@ function factory(dependencies) {
|
||||
// Public
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @param {Object} data
|
||||
* @return {Object}
|
||||
*/
|
||||
static convertData(data) {
|
||||
const data2 = {};
|
||||
if ('id' in data) {
|
||||
data2.id = data.id;
|
||||
}
|
||||
if ('is_camera_on' in data) {
|
||||
data2.isCameraOn = data.is_camera_on;
|
||||
}
|
||||
if ('is_deaf' in data) {
|
||||
data2.isDeaf = data.is_deaf;
|
||||
}
|
||||
if ('is_muted' in data) {
|
||||
data2.isMuted = data.is_muted;
|
||||
}
|
||||
if ('is_screen_sharing_on' in data) {
|
||||
data2.isScreenSharingOn = data.is_screen_sharing_on;
|
||||
}
|
||||
|
||||
// relations
|
||||
if ('partner' in data) {
|
||||
data2.partner = insert(data.partner);
|
||||
}
|
||||
if ('guest' in data) {
|
||||
data2.guest = insert(data.guest);
|
||||
}
|
||||
if ('channel' in data) {
|
||||
data2.channel = insert(data.channel);
|
||||
}
|
||||
return data2;
|
||||
}
|
||||
|
||||
/**
|
||||
* restores the session to its default values
|
||||
*/
|
||||
|
||||
@@ -200,6 +200,12 @@ function factory(dependencies) {
|
||||
if ('id' in data) {
|
||||
data2.id = data.id;
|
||||
}
|
||||
if ('invitedGuests' in data) {
|
||||
data2.invitedGuests = data.invitedGuests;
|
||||
}
|
||||
if ('invitedPartners' in data) {
|
||||
data2.invitedPartners = data.invitedPartners;
|
||||
}
|
||||
if ('is_minimized' in data && 'state' in data) {
|
||||
data2.serverFoldState = data.is_minimized ? data.state : 'closed';
|
||||
}
|
||||
@@ -261,8 +267,8 @@ function factory(dependencies) {
|
||||
if ('rtc_inviting_session' in data) {
|
||||
data2.rtcInvitingSession = insert(data.rtc_inviting_session);
|
||||
}
|
||||
if ('rtc_sessions' in data) {
|
||||
data2.rtcSessions = insert(data.rtc_sessions.map(record => this.messaging.models['mail.rtc_session'].convertData(record)));
|
||||
if ('rtcSessions' in data) {
|
||||
data2.rtcSessions = data.rtcSessions;
|
||||
}
|
||||
if ('seen_partners_info' in data) {
|
||||
if (!data.seen_partners_info) {
|
||||
@@ -325,8 +331,6 @@ function factory(dependencies) {
|
||||
this.messaging.soundEffects.channelLeave.play();
|
||||
}
|
||||
this.update({
|
||||
invitedGuests: clear(),
|
||||
invitedPartners: clear(),
|
||||
mailRtc: unlink(),
|
||||
rtcInvitingSession: unlink(),
|
||||
});
|
||||
@@ -776,12 +780,15 @@ function factory(dependencies) {
|
||||
channel_id: this.id,
|
||||
},
|
||||
}, { shadow: true }));
|
||||
if (!this.exists()) {
|
||||
return;
|
||||
}
|
||||
this.update({
|
||||
mailRtc: link(this.messaging.mailRtc),
|
||||
rtcInvitingSession: unlink(),
|
||||
rtcSessions: insertAndReplace(rtcSessions.map(record => this.messaging.models['mail.rtc_session'].convertData(record))),
|
||||
invitedGuests: insertAndReplace(invitedGuests),
|
||||
invitedPartners: insertAndReplace(invitedPartners),
|
||||
rtcSessions,
|
||||
invitedGuests,
|
||||
invitedPartners,
|
||||
});
|
||||
await this.async(() => this.messaging.mailRtc.initSession({
|
||||
currentSessionId: sessionId,
|
||||
@@ -806,9 +813,7 @@ function factory(dependencies) {
|
||||
*/
|
||||
updateRtcSessions(rtcSessions) {
|
||||
const oldCount = this.rtcSessions.length;
|
||||
this.update({
|
||||
rtcSessions: insertAndReplace(rtcSessions.map(record => this.messaging.models['mail.rtc_session'].convertData(record)))
|
||||
});
|
||||
this.update({ rtcSessions });
|
||||
if (this.mailRtc) {
|
||||
const newCount = this.rtcSessions.length;
|
||||
if (newCount > oldCount) {
|
||||
|
||||
@@ -10,4 +10,5 @@ from . import test_mail_template
|
||||
from . import test_mail_tools
|
||||
from . import test_res_partner
|
||||
from . import test_res_users_settings
|
||||
from . import test_rtc
|
||||
from . import test_update_notification
|
||||
|
||||
@@ -0,0 +1,574 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo import fields
|
||||
from odoo.addons.mail.tests.common import MailCommon
|
||||
from odoo.tests import tagged
|
||||
from odoo.tests.common import users
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
@tagged('RTC')
|
||||
class TestChannelInternals(MailCommon):
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_01_join_call(self):
|
||||
"""Join call should remove existing sessions, remove invitation, create a new session, and return data."""
|
||||
channel = self.env['mail.channel'].browse(self.env['mail.channel'].channel_create(name='Test Channel')['id'])
|
||||
channel_partner = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.partner_id == self.user_employee.partner_id)
|
||||
channel_partner._rtc_join_call()
|
||||
self.env['bus.bus'].sudo().search([]).unlink()
|
||||
with self.assertBus(
|
||||
[
|
||||
(self.cr.dbname, 'res.partner', self.user_employee.partner_id.id), # end of previous session
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update sessions
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update sessions
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'rtc_session_ended',
|
||||
'payload': {
|
||||
'sessionId': channel_partner.rtc_session_ids.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'rtc_sessions_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert-and-unlink', [{'id': channel_partner.rtc_session_ids.id}])],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'rtc_sessions_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert', [{
|
||||
'id': channel_partner.rtc_session_ids.id + 1,
|
||||
'isCameraOn': False,
|
||||
'isDeaf': False,
|
||||
'isMuted': False,
|
||||
'isScreenSharingOn': False,
|
||||
'partner': [('insert', {
|
||||
'id': self.user_employee.partner_id.id,
|
||||
'name': "Ernest Employee",
|
||||
})],
|
||||
}])],
|
||||
},
|
||||
},
|
||||
]
|
||||
):
|
||||
res = channel_partner._rtc_join_call()
|
||||
self.assertEqual(res, {
|
||||
'iceServers': False,
|
||||
'rtcSessions': [('insert-and-replace', [{
|
||||
'id': channel_partner.rtc_session_ids.id,
|
||||
'isCameraOn': False,
|
||||
'isDeaf': False,
|
||||
'isMuted': False,
|
||||
'isScreenSharingOn': False,
|
||||
'partner': [('insert', {
|
||||
'id': self.user_employee.partner_id.id,
|
||||
'name': "Ernest Employee",
|
||||
})],
|
||||
}])],
|
||||
'sessionId': channel_partner.rtc_session_ids.id,
|
||||
})
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_10_start_call_in_chat_should_invite_all_members_to_call(self):
|
||||
test_user = self.env['res.users'].sudo().create({'name': "Test User", 'login': 'test'})
|
||||
channel = self.env['mail.channel'].browse(self.env['mail.channel'].channel_get(partners_to=(self.user_employee.partner_id + test_user.partner_id).ids)['id'])
|
||||
channel_partner = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.partner_id == self.user_employee.partner_id)
|
||||
channel_partner._rtc_join_call()
|
||||
last_rtc_session_id = channel_partner.rtc_session_ids.id
|
||||
channel_partner._rtc_leave_call()
|
||||
|
||||
self.env['bus.bus'].sudo().search([]).unlink()
|
||||
with self.assertBus(
|
||||
[
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update new session
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # message_post "started a live conference" (not asserted below)
|
||||
(self.cr.dbname, 'res.partner', self.user_employee.partner_id.id), # update of last interest (not asserted below)
|
||||
(self.cr.dbname, 'res.partner', test_user.partner_id.id), # update of last interest (not asserted below)
|
||||
(self.cr.dbname, 'res.partner', test_user.partner_id.id), # incoming invitation
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update list of invitations
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'rtc_sessions_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert', [{
|
||||
'id': last_rtc_session_id + 1,
|
||||
'isCameraOn': False,
|
||||
'isDeaf': False,
|
||||
'isMuted': False,
|
||||
'isScreenSharingOn': False,
|
||||
'partner': [('insert', {
|
||||
'id': self.user_employee.partner_id.id,
|
||||
'name': "Ernest Employee",
|
||||
})],
|
||||
}])],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'invitedPartners': [('insert', [{'id': test_user.partner_id.id, 'name': 'Test User'}])],
|
||||
},
|
||||
},
|
||||
]
|
||||
):
|
||||
res = channel_partner._rtc_join_call()
|
||||
self.assertNotIn('invitedGuests', res)
|
||||
self.assertIn('invitedPartners', res)
|
||||
self.assertEqual(res['invitedPartners'], [('insert', [{'id': test_user.partner_id.id, 'name': "Test User"}])])
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_11_start_call_in_group_should_invite_all_members_to_call(self):
|
||||
test_user = self.env['res.users'].sudo().create({'name': "Test User", 'login': 'test'})
|
||||
test_guest = self.env['mail.guest'].sudo().create({'name': "Test Guest"})
|
||||
channel = self.env['mail.channel'].browse(self.env['mail.channel'].create_group(partners_to=(self.user_employee.partner_id + test_user.partner_id).ids)['id'])
|
||||
channel.add_members(guest_ids=test_guest.ids)
|
||||
channel_partner = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.partner_id == self.user_employee.partner_id)
|
||||
channel_partner._rtc_join_call()
|
||||
last_rtc_session_id = channel_partner.rtc_session_ids.id
|
||||
channel_partner._rtc_leave_call()
|
||||
|
||||
self.env['bus.bus'].sudo().search([]).unlink()
|
||||
with self.assertBus(
|
||||
[
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update new session
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # message_post "started a live conference" (not asserted below)
|
||||
(self.cr.dbname, 'res.partner', self.user_employee.partner_id.id), # update of last interest (not asserted below)
|
||||
(self.cr.dbname, 'res.partner', test_user.partner_id.id), # update of last interest (not asserted below)
|
||||
(self.cr.dbname, 'res.partner', test_user.partner_id.id), # incoming invitation
|
||||
(self.cr.dbname, 'mail.guest', test_guest.id), # incoming invitation
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update list of invitations
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'rtc_sessions_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert', [{
|
||||
'id': last_rtc_session_id + 1,
|
||||
'isCameraOn': False,
|
||||
'isDeaf': False,
|
||||
'isMuted': False,
|
||||
'isScreenSharingOn': False,
|
||||
'partner': [('insert', {
|
||||
'id': self.user_employee.partner_id.id,
|
||||
'name': "Ernest Employee",
|
||||
})],
|
||||
}])],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'rtc_sessions_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert', [{
|
||||
'id': last_rtc_session_id + 1,
|
||||
'isCameraOn': False,
|
||||
'isDeaf': False,
|
||||
'isMuted': False,
|
||||
'isScreenSharingOn': False,
|
||||
'partner': [('insert', {
|
||||
'id': self.user_employee.partner_id.id,
|
||||
'name': "Ernest Employee",
|
||||
})],
|
||||
}])],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'invitedGuests': [('insert', [{'id': test_guest.id, 'name': 'Test Guest'}])],
|
||||
'invitedPartners': [('insert', [{'id': test_user.partner_id.id, 'name': 'Test User'}])],
|
||||
},
|
||||
},
|
||||
]
|
||||
):
|
||||
res = channel_partner._rtc_join_call()
|
||||
self.assertIn('invitedGuests', res)
|
||||
self.assertEqual(res['invitedGuests'], [('insert', [{'id': test_guest.id, 'name': 'Test Guest'}])])
|
||||
self.assertIn('invitedPartners', res)
|
||||
self.assertEqual(res['invitedPartners'], [('insert', [{'id': test_user.partner_id.id, 'name': "Test User"}])])
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_20_join_call_should_cancel_pending_invitations(self):
|
||||
test_user = self.env['res.users'].sudo().create({'name': "Test User", 'login': 'test'})
|
||||
test_guest = self.env['mail.guest'].sudo().create({'name': "Test Guest"})
|
||||
channel = self.env['mail.channel'].browse(self.env['mail.channel'].create_group(partners_to=(self.user_employee.partner_id + test_user.partner_id).ids)['id'])
|
||||
channel.add_members(guest_ids=test_guest.ids)
|
||||
channel_partner = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.partner_id == self.user_employee.partner_id)
|
||||
channel_partner._rtc_join_call()
|
||||
|
||||
channel_partner_test_user = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.partner_id == test_user.partner_id)
|
||||
self.env['bus.bus'].sudo().search([]).unlink()
|
||||
with self.assertBus(
|
||||
[
|
||||
(self.cr.dbname, 'res.partner', test_user.partner_id.id), # update invitation
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update list of invitations
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update sessions
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcInvitingSession': [('unlink',)],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'invitedPartners': [('insert-and-unlink', [{'id': test_user.partner_id.id}])],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'rtc_sessions_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert', [
|
||||
{
|
||||
'id': channel_partner.rtc_session_ids.id + 1,
|
||||
'isCameraOn': False,
|
||||
'isDeaf': False,
|
||||
'isMuted': False,
|
||||
'isScreenSharingOn': False,
|
||||
'partner': [('insert', {
|
||||
'id': test_user.partner_id.id,
|
||||
'name': 'Test User',
|
||||
})],
|
||||
},
|
||||
])],
|
||||
},
|
||||
},
|
||||
]
|
||||
):
|
||||
channel_partner_test_user._rtc_join_call()
|
||||
|
||||
channel_partner_test_guest = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.guest_id == test_guest)
|
||||
self.env['bus.bus'].sudo().search([]).unlink()
|
||||
with self.assertBus(
|
||||
[
|
||||
(self.cr.dbname, 'mail.guest', test_guest.id), # update invitation
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update list of invitations
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update sessions
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcInvitingSession': [('unlink',)],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'invitedGuests': [('insert-and-unlink', [{'id': test_guest.id}])],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'rtc_sessions_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert', [
|
||||
{
|
||||
'id': channel_partner.rtc_session_ids.id + 2,
|
||||
'isCameraOn': False,
|
||||
'isDeaf': False,
|
||||
'isMuted': False,
|
||||
'isScreenSharingOn': False,
|
||||
'guest': [('insert', {
|
||||
'id': test_guest.id,
|
||||
'name': 'Test Guest',
|
||||
})],
|
||||
},
|
||||
])],
|
||||
},
|
||||
},
|
||||
]
|
||||
):
|
||||
channel_partner_test_guest._rtc_join_call()
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_21_leave_call_should_cancel_pending_invitations(self):
|
||||
test_user = self.env['res.users'].sudo().create({'name': "Test User", 'login': 'test'})
|
||||
test_guest = self.env['mail.guest'].sudo().create({'name': "Test Guest"})
|
||||
channel = self.env['mail.channel'].browse(self.env['mail.channel'].create_group(partners_to=(self.user_employee.partner_id + test_user.partner_id).ids)['id'])
|
||||
channel.add_members(guest_ids=test_guest.ids)
|
||||
channel_partner = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.partner_id == self.user_employee.partner_id)
|
||||
channel_partner._rtc_join_call()
|
||||
|
||||
channel_partner_test_user = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.partner_id == test_user.partner_id)
|
||||
self.env['bus.bus'].sudo().search([]).unlink()
|
||||
with self.assertBus(
|
||||
[
|
||||
(self.cr.dbname, 'res.partner', test_user.partner_id.id), # update invitation
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update list of invitations
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcInvitingSession': [('unlink',)],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'invitedPartners': [('insert-and-unlink', [{'id': test_user.partner_id.id}])],
|
||||
},
|
||||
},
|
||||
]
|
||||
):
|
||||
channel_partner_test_user._rtc_leave_call()
|
||||
|
||||
channel_partner_test_guest = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.guest_id == test_guest)
|
||||
self.env['bus.bus'].sudo().search([]).unlink()
|
||||
with self.assertBus(
|
||||
[
|
||||
(self.cr.dbname, 'mail.guest', test_guest.id), # update invitation
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update list of invitations
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcInvitingSession': [('unlink',)],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'invitedGuests': [('insert-and-unlink', [{'id': test_guest.id}])],
|
||||
},
|
||||
},
|
||||
]
|
||||
):
|
||||
channel_partner_test_guest._rtc_leave_call()
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_25_lone_call_participant_leaving_call_should_cancel_pending_invitations(self):
|
||||
test_user = self.env['res.users'].sudo().create({'name': "Test User", 'login': 'test'})
|
||||
test_guest = self.env['mail.guest'].sudo().create({'name': "Test Guest"})
|
||||
channel = self.env['mail.channel'].browse(self.env['mail.channel'].create_group(partners_to=(self.user_employee.partner_id + test_user.partner_id).ids)['id'])
|
||||
channel.add_members(guest_ids=test_guest.ids)
|
||||
channel_partner = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.partner_id == self.user_employee.partner_id)
|
||||
channel_partner._rtc_join_call()
|
||||
|
||||
self.env['bus.bus'].sudo().search([]).unlink()
|
||||
with self.assertBus(
|
||||
[
|
||||
(self.cr.dbname, 'res.partner', test_user.partner_id.id), # update invitation
|
||||
(self.cr.dbname, 'mail.guest', test_guest.id), # update invitation
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update list of invitations
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update sessions
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcInvitingSession': [('unlink',)],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcInvitingSession': [('unlink',)],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'invitedGuests': [('insert-and-unlink', [{'id': test_guest.id}])],
|
||||
'invitedPartners': [('insert-and-unlink', [{'id': test_user.partner_id.id}])],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'rtc_sessions_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert-and-unlink', [{'id': channel_partner.rtc_session_ids.id}])],
|
||||
},
|
||||
},
|
||||
]
|
||||
):
|
||||
channel_partner._rtc_leave_call()
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_30_add_members_while_in_call_should_invite_new_members_to_call(self):
|
||||
test_user = self.env['res.users'].sudo().create({'name': "Test User", 'login': 'test'})
|
||||
test_guest = self.env['mail.guest'].sudo().create({'name': "Test Guest"})
|
||||
channel = self.env['mail.channel'].browse(self.env['mail.channel'].create_group(partners_to=self.user_employee.partner_id.ids)['id'])
|
||||
channel_partner = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.partner_id == self.user_employee.partner_id)
|
||||
channel_partner._rtc_join_call()
|
||||
self.env['bus.bus'].sudo().search([]).unlink()
|
||||
with self.assertBus(
|
||||
[
|
||||
(self.cr.dbname, 'res.partner', test_user.partner_id.id), # channel joined (not asserted below)
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # message_post "invited" (not asserted below)
|
||||
(self.cr.dbname, 'res.partner', self.user_employee.partner_id.id), # update of last interest (not asserted below)
|
||||
(self.cr.dbname, 'res.partner', test_user.partner_id.id), # update of last interest (not asserted below)
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # new members (not asserted below)
|
||||
(self.cr.dbname, 'res.partner', test_user.partner_id.id), # incoming invitation
|
||||
(self.cr.dbname, 'mail.guest', test_guest.id), # incoming invitation
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update list of invitations
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcInvitingSession': [('insert', {
|
||||
'id': channel_partner.rtc_session_ids.id,
|
||||
'isCameraOn': False,
|
||||
'isDeaf': False,
|
||||
'isMuted': False,
|
||||
'isScreenSharingOn': False,
|
||||
'partner': [('insert', {
|
||||
'id': self.user_employee.partner_id.id,
|
||||
'name': "Ernest Employee",
|
||||
})],
|
||||
})],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcInvitingSession': [('insert', {
|
||||
'id': channel_partner.rtc_session_ids.id,
|
||||
'isCameraOn': False,
|
||||
'isDeaf': False,
|
||||
'isMuted': False,
|
||||
'isScreenSharingOn': False,
|
||||
'partner': [('insert', {
|
||||
'id': self.user_employee.partner_id.id,
|
||||
'name': "Ernest Employee",
|
||||
})],
|
||||
})],
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'mail.channel_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'invitedGuests': [('insert', [{'id': test_guest.id, 'name': 'Test Guest'}])],
|
||||
'invitedPartners': [('insert', [{'id': test_user.partner_id.id, 'name': 'Test User'}])],
|
||||
},
|
||||
},
|
||||
],
|
||||
):
|
||||
channel.add_members(partner_ids=test_user.partner_id.ids, guest_ids=test_guest.ids, invite_to_rtc_call=True)
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_40_leave_call_should_remove_existing_sessions_of_user_in_channel_and_return_data(self):
|
||||
channel = self.env['mail.channel'].browse(self.env['mail.channel'].create_group(partners_to=self.user_employee.partner_id.ids)['id'])
|
||||
channel_partner = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.partner_id == self.user_employee.partner_id)
|
||||
channel_partner._rtc_join_call()
|
||||
self.env['bus.bus'].sudo().search([]).unlink()
|
||||
with self.assertBus(
|
||||
[
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update list of sessions
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'rtc_sessions_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert-and-unlink', [{'id': channel_partner.rtc_session_ids.id}])],
|
||||
},
|
||||
},
|
||||
],
|
||||
):
|
||||
channel_partner._rtc_leave_call()
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_50_garbage_collect_should_remove_old_sessions_and_notify_data(self):
|
||||
channel = self.env['mail.channel'].browse(self.env['mail.channel'].create_group(partners_to=self.user_employee.partner_id.ids)['id'])
|
||||
channel_partner = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.partner_id == self.user_employee.partner_id)
|
||||
channel_partner._rtc_join_call()
|
||||
channel_partner.rtc_session_ids.flush()
|
||||
channel_partner.rtc_session_ids._write({'write_date': fields.Datetime.now() - relativedelta(days=2)})
|
||||
self.env['bus.bus'].sudo().search([]).unlink()
|
||||
with self.assertBus(
|
||||
[
|
||||
(self.cr.dbname, 'res.partner', self.user_employee.partner_id.id), # session ended
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update list of sessions
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'rtc_session_ended',
|
||||
'payload': {
|
||||
'sessionId': channel_partner.rtc_session_ids.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'rtc_sessions_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert-and-unlink', [{'id': channel_partner.rtc_session_ids.id}])],
|
||||
},
|
||||
},
|
||||
],
|
||||
):
|
||||
self.env['mail.channel.rtc.session'].sudo()._gc_inactive_sessions()
|
||||
self.assertFalse(channel_partner.rtc_session_ids)
|
||||
|
||||
@users('employee')
|
||||
@mute_logger('odoo.models.unlink')
|
||||
def test_51_action_disconnect_should_remove_selected_session_and_notify_data(self):
|
||||
channel = self.env['mail.channel'].browse(self.env['mail.channel'].create_group(partners_to=self.user_employee.partner_id.ids)['id'])
|
||||
channel_partner = channel.sudo().channel_last_seen_partner_ids.filtered(lambda channel_partner: channel_partner.partner_id == self.user_employee.partner_id)
|
||||
channel_partner._rtc_join_call()
|
||||
self.env['bus.bus'].sudo().search([]).unlink()
|
||||
with self.assertBus(
|
||||
[
|
||||
(self.cr.dbname, 'res.partner', self.user_employee.partner_id.id), # session ended
|
||||
(self.cr.dbname, 'mail.channel', channel.id), # update list of sessions
|
||||
],
|
||||
[
|
||||
{
|
||||
'type': 'rtc_session_ended',
|
||||
'payload': {
|
||||
'sessionId': channel_partner.rtc_session_ids.id,
|
||||
},
|
||||
},
|
||||
{
|
||||
'type': 'rtc_sessions_update',
|
||||
'payload': {
|
||||
'id': channel.id,
|
||||
'rtcSessions': [('insert-and-unlink', [{'id': channel_partner.rtc_session_ids.id}])],
|
||||
},
|
||||
},
|
||||
],
|
||||
):
|
||||
channel_partner.rtc_session_ids.action_disconnect()
|
||||
self.assertFalse(channel_partner.rtc_session_ids)
|
||||
@@ -115,6 +115,8 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'description': 'General announcements for all employees.',
|
||||
'group_based_subscription': True,
|
||||
'id': channel_general.id,
|
||||
'invitedGuests': [('insert-and-replace', [])],
|
||||
'invitedPartners': [('insert-and-replace', [])],
|
||||
'is_minimized': False,
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': channel_general.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
@@ -124,6 +126,7 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'message_unread_counter': 5,
|
||||
'name': 'general',
|
||||
'public': 'groups',
|
||||
'rtcSessions': [('insert-and-replace', [])],
|
||||
'seen_message_id': False,
|
||||
'state': 'open',
|
||||
'uuid': channel_general.uuid,
|
||||
@@ -137,6 +140,8 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'description': False,
|
||||
'group_based_subscription': False,
|
||||
'id': channel_channel_public_1.id,
|
||||
'invitedGuests': [('insert-and-replace', [])],
|
||||
'invitedPartners': [('insert-and-replace', [])],
|
||||
'is_minimized': False,
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': channel_channel_public_1.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
@@ -146,6 +151,7 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'message_unread_counter': 0,
|
||||
'name': 'public 1',
|
||||
'public': 'public',
|
||||
'rtcSessions': [('insert-and-replace', [])],
|
||||
'seen_message_id': next(res['message_id'] for res in channel_channel_public_1._channel_last_message_ids()),
|
||||
'state': 'open',
|
||||
'uuid': channel_channel_public_1.uuid,
|
||||
@@ -159,6 +165,8 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'description': False,
|
||||
'group_based_subscription': False,
|
||||
'id': channel_channel_public_2.id,
|
||||
'invitedGuests': [('insert-and-replace', [])],
|
||||
'invitedPartners': [('insert-and-replace', [])],
|
||||
'is_minimized': False,
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': channel_channel_public_2.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
@@ -168,6 +176,7 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'message_unread_counter': 0,
|
||||
'name': 'public 2',
|
||||
'public': 'public',
|
||||
'rtcSessions': [('insert-and-replace', [])],
|
||||
'seen_message_id': next(res['message_id'] for res in channel_channel_public_2._channel_last_message_ids()),
|
||||
'state': 'open',
|
||||
'uuid': channel_channel_public_2.uuid,
|
||||
@@ -181,6 +190,8 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'description': False,
|
||||
'group_based_subscription': False,
|
||||
'id': channel_channel_group_1.id,
|
||||
'invitedGuests': [('insert-and-replace', [])],
|
||||
'invitedPartners': [('insert-and-replace', [])],
|
||||
'is_minimized': False,
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': channel_channel_group_1.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
@@ -190,6 +201,7 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'message_unread_counter': 0,
|
||||
'name': 'group 1',
|
||||
'public': 'groups',
|
||||
'rtcSessions': [('insert-and-replace', [])],
|
||||
'seen_message_id': next(res['message_id'] for res in channel_channel_group_1._channel_last_message_ids()),
|
||||
'state': 'open',
|
||||
'uuid': channel_channel_group_1.uuid,
|
||||
@@ -203,6 +215,8 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'description': False,
|
||||
'group_based_subscription': False,
|
||||
'id': channel_channel_group_2.id,
|
||||
'invitedGuests': [('insert-and-replace', [])],
|
||||
'invitedPartners': [('insert-and-replace', [])],
|
||||
'is_minimized': False,
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': channel_channel_group_2.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
@@ -212,6 +226,7 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'message_unread_counter': 0,
|
||||
'name': 'group 2',
|
||||
'public': 'groups',
|
||||
'rtcSessions': [('insert-and-replace', [])],
|
||||
'seen_message_id': next(res['message_id'] for res in channel_channel_group_2._channel_last_message_ids()),
|
||||
'state': 'open',
|
||||
'uuid': channel_channel_group_2.uuid,
|
||||
@@ -225,6 +240,8 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'description': False,
|
||||
'group_based_subscription': False,
|
||||
'id': channel_channel_private_1.id,
|
||||
'invitedGuests': [('insert-and-replace', [])],
|
||||
'invitedPartners': [('insert-and-replace', [])],
|
||||
'is_minimized': False,
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': channel_channel_private_1.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
@@ -234,6 +251,7 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'message_unread_counter': 0,
|
||||
'name': 'private 1',
|
||||
'public': 'private',
|
||||
'rtcSessions': [('insert-and-replace', [])],
|
||||
'seen_message_id': next(res['message_id'] for res in channel_channel_private_1._channel_last_message_ids()),
|
||||
'state': 'open',
|
||||
'uuid': channel_channel_private_1.uuid,
|
||||
@@ -247,6 +265,8 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'description': False,
|
||||
'group_based_subscription': False,
|
||||
'id': channel_channel_private_2.id,
|
||||
'invitedGuests': [('insert-and-replace', [])],
|
||||
'invitedPartners': [('insert-and-replace', [])],
|
||||
'is_minimized': False,
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': channel_channel_private_2.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
@@ -256,6 +276,7 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'message_unread_counter': 0,
|
||||
'name': 'private 2',
|
||||
'public': 'private',
|
||||
'rtcSessions': [('insert-and-replace', [])],
|
||||
'seen_message_id': next(res['message_id'] for res in channel_channel_private_2._channel_last_message_ids()),
|
||||
'state': 'open',
|
||||
'uuid': channel_channel_private_2.uuid,
|
||||
@@ -269,6 +290,8 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'description': False,
|
||||
'group_based_subscription': False,
|
||||
'id': channel_group_1.id,
|
||||
'invitedGuests': [('insert-and-replace', [])],
|
||||
'invitedPartners': [('insert-and-replace', [])],
|
||||
'is_minimized': False,
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': channel_group_1.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
@@ -302,6 +325,7 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'message_unread_counter': 0,
|
||||
'name': '',
|
||||
'public': 'private',
|
||||
'rtcSessions': [('insert-and-replace', [])],
|
||||
'seen_message_id': False,
|
||||
'seen_partners_info': [
|
||||
{
|
||||
@@ -329,6 +353,8 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'description': False,
|
||||
'group_based_subscription': False,
|
||||
'id': channel_chat_1.id,
|
||||
'invitedGuests': [('insert-and-replace', [])],
|
||||
'invitedPartners': [('insert-and-replace', [])],
|
||||
'is_minimized': False,
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': channel_chat_1.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
@@ -362,6 +388,7 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'message_unread_counter': 0,
|
||||
'name': 'Ernest Employee, test14',
|
||||
'public': 'private',
|
||||
'rtcSessions': [('insert-and-replace', [])],
|
||||
'seen_partners_info': [
|
||||
{
|
||||
'fetched_message_id': False,
|
||||
@@ -389,6 +416,8 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'description': False,
|
||||
'group_based_subscription': False,
|
||||
'id': channel_chat_2.id,
|
||||
'invitedGuests': [('insert-and-replace', [])],
|
||||
'invitedPartners': [('insert-and-replace', [])],
|
||||
'is_minimized': False,
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': channel_chat_2.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
@@ -422,6 +451,7 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'message_unread_counter': 0,
|
||||
'name': 'Ernest Employee, test15',
|
||||
'public': 'private',
|
||||
'rtcSessions': [('insert-and-replace', [])],
|
||||
'seen_partners_info': [
|
||||
{
|
||||
'fetched_message_id': False,
|
||||
@@ -449,6 +479,8 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'description': False,
|
||||
'group_based_subscription': False,
|
||||
'id': channel_chat_3.id,
|
||||
'invitedGuests': [('insert-and-replace', [])],
|
||||
'invitedPartners': [('insert-and-replace', [])],
|
||||
'is_minimized': False,
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': channel_chat_3.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
@@ -482,6 +514,7 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'message_unread_counter': 0,
|
||||
'name': 'Ernest Employee, test2',
|
||||
'public': 'private',
|
||||
'rtcSessions': [('insert-and-replace', [])],
|
||||
'seen_partners_info': [
|
||||
{
|
||||
'fetched_message_id': False,
|
||||
@@ -509,6 +542,8 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'description': False,
|
||||
'group_based_subscription': False,
|
||||
'id': channel_chat_4.id,
|
||||
'invitedGuests': [('insert-and-replace', [])],
|
||||
'invitedPartners': [('insert-and-replace', [])],
|
||||
'is_minimized': False,
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': channel_chat_4.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
@@ -542,6 +577,7 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'message_unread_counter': 0,
|
||||
'name': 'Ernest Employee, test3',
|
||||
'public': 'private',
|
||||
'rtcSessions': [('insert-and-replace', [])],
|
||||
'seen_partners_info': [
|
||||
{
|
||||
'fetched_message_id': False,
|
||||
@@ -569,6 +605,8 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'description': False,
|
||||
'group_based_subscription': False,
|
||||
'id': channel_livechat_1.id,
|
||||
'invitedGuests': [('insert-and-replace', [])],
|
||||
'invitedPartners': [('insert-and-replace', [])],
|
||||
'is_minimized': False,
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': channel_livechat_1.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
@@ -608,6 +646,7 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'name': 'test1 Ernest Employee',
|
||||
'operator_pid': (self.users[0].partner_id.id, 'Ernest Employee'),
|
||||
'public': 'private',
|
||||
'rtcSessions': [('insert-and-replace', [])],
|
||||
'seen_partners_info': [
|
||||
{
|
||||
'fetched_message_id': False,
|
||||
@@ -635,6 +674,8 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'description': False,
|
||||
'group_based_subscription': False,
|
||||
'id': channel_livechat_2.id,
|
||||
'invitedGuests': [('insert-and-replace', [])],
|
||||
'invitedPartners': [('insert-and-replace', [])],
|
||||
'is_minimized': False,
|
||||
'is_pinned': True,
|
||||
'last_interest_dt': channel_livechat_2.channel_last_seen_partner_ids.filtered(lambda p: p.partner_id == self.users[0].partner_id).last_interest_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
@@ -674,6 +715,7 @@ class TestDiscussFullPerformance(TransactionCase):
|
||||
'name': 'anon 2 Ernest Employee',
|
||||
'operator_pid': (self.users[0].partner_id.id, 'Ernest Employee'),
|
||||
'public': 'private',
|
||||
'rtcSessions': [('insert-and-replace', [])],
|
||||
'seen_partners_info': [
|
||||
{
|
||||
'fetched_message_id': next(res['message_id'] for res in channel_livechat_2._channel_last_message_ids()),
|
||||
|
||||
Reference in New Issue
Block a user