178 lines
8.2 KiB
Python
178 lines
8.2 KiB
Python
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||
|
|
||
|
from werkzeug.exceptions import NotFound
|
||
|
|
||
|
from odoo import http
|
||
|
from odoo.http import request
|
||
|
from odoo.addons.mail.controllers.webclient import WebclientController
|
||
|
from odoo.addons.mail.models.discuss.mail_guest import add_guest_to_context
|
||
|
from odoo.addons.mail.tools.discuss import Store
|
||
|
|
||
|
|
||
|
class DiscussChannelWebclientController(WebclientController):
|
||
|
"""Override to add discuss channel specific features."""
|
||
|
def _process_request_for_all(self, store, **kwargs):
|
||
|
"""Override to return channel as member and last messages."""
|
||
|
super()._process_request_for_all(store, **kwargs)
|
||
|
if kwargs.get("channels_as_member"):
|
||
|
channels = request.env["discuss.channel"]._get_channels_as_member()
|
||
|
# fetch channels data before messages to benefit from prefetching (channel info might
|
||
|
# prefetch a lot of data that message format could use)
|
||
|
store.add(channels)
|
||
|
store.add(channels._get_last_messages(), for_current_user=True)
|
||
|
|
||
|
|
||
|
class ChannelController(http.Controller):
|
||
|
@http.route("/discuss/channel/members", methods=["POST"], type="json", auth="public", readonly=True)
|
||
|
@add_guest_to_context
|
||
|
def discuss_channel_members(self, channel_id, known_member_ids):
|
||
|
channel = request.env["discuss.channel"].search([("id", "=", channel_id)])
|
||
|
if not channel:
|
||
|
raise NotFound()
|
||
|
return channel._load_more_members(known_member_ids)
|
||
|
|
||
|
@http.route("/discuss/channel/update_avatar", methods=["POST"], type="json")
|
||
|
def discuss_channel_avatar_update(self, channel_id, data):
|
||
|
channel = request.env["discuss.channel"].search([("id", "=", channel_id)])
|
||
|
if not channel or not data:
|
||
|
raise NotFound()
|
||
|
channel.write({"image_128": data})
|
||
|
|
||
|
@http.route("/discuss/channel/info", methods=["POST"], type="json", auth="public", readonly=True)
|
||
|
@add_guest_to_context
|
||
|
def discuss_channel_info(self, channel_id):
|
||
|
channel = request.env["discuss.channel"].search([("id", "=", channel_id)])
|
||
|
if not channel:
|
||
|
return
|
||
|
return Store(channel).get_result()
|
||
|
|
||
|
@http.route("/discuss/channel/messages", methods=["POST"], type="json", auth="public")
|
||
|
@add_guest_to_context
|
||
|
def discuss_channel_messages(self, channel_id, search_term=None, before=None, after=None, limit=30, around=None):
|
||
|
channel = request.env["discuss.channel"].search([("id", "=", channel_id)])
|
||
|
if not channel:
|
||
|
raise NotFound()
|
||
|
domain = [
|
||
|
("res_id", "=", channel_id),
|
||
|
("model", "=", "discuss.channel"),
|
||
|
("message_type", "!=", "user_notification"),
|
||
|
]
|
||
|
res = request.env["mail.message"]._message_fetch(
|
||
|
domain, search_term=search_term, before=before, after=after, around=around, limit=limit
|
||
|
)
|
||
|
messages = res.pop("messages")
|
||
|
if not request.env.user._is_public() and not around:
|
||
|
messages.set_message_done()
|
||
|
return {
|
||
|
**res,
|
||
|
"data": Store(messages, for_current_user=True).get_result(),
|
||
|
"messages": Store.many_ids(messages),
|
||
|
}
|
||
|
|
||
|
@http.route("/discuss/channel/pinned_messages", methods=["POST"], type="json", auth="public", readonly=True)
|
||
|
@add_guest_to_context
|
||
|
def discuss_channel_pins(self, channel_id):
|
||
|
channel = request.env["discuss.channel"].search([("id", "=", channel_id)])
|
||
|
if not channel:
|
||
|
raise NotFound()
|
||
|
messages = channel.pinned_message_ids.sorted(key="pinned_at", reverse=True)
|
||
|
return Store(messages, for_current_user=True).get_result()
|
||
|
|
||
|
@http.route("/discuss/channel/mark_as_read", methods=["POST"], type="json", auth="public")
|
||
|
@add_guest_to_context
|
||
|
def discuss_channel_mark_as_read(self, channel_id, last_message_id, sync=False):
|
||
|
member = request.env["discuss.channel.member"].search([
|
||
|
("channel_id", "=", channel_id),
|
||
|
("is_self", "=", True),
|
||
|
])
|
||
|
if not member:
|
||
|
return # ignore if the member left in the meantime
|
||
|
member._mark_as_read(last_message_id, sync=sync)
|
||
|
|
||
|
@http.route("/discuss/channel/mark_as_unread", methods=["POST"], type="json", auth="public")
|
||
|
@add_guest_to_context
|
||
|
def discuss_channel_mark_as_unread(self, channel_id, message_id):
|
||
|
member = request.env["discuss.channel.member"].search([
|
||
|
("channel_id", "=", channel_id),
|
||
|
("is_self", "=", True),
|
||
|
])
|
||
|
if not member:
|
||
|
raise NotFound()
|
||
|
return member._set_new_message_separator(message_id, sync=True)
|
||
|
|
||
|
@http.route("/discuss/channel/notify_typing", methods=["POST"], type="json", auth="public")
|
||
|
@add_guest_to_context
|
||
|
def discuss_channel_notify_typing(self, channel_id, is_typing):
|
||
|
channel = request.env["discuss.channel"].search([("id", "=", channel_id)])
|
||
|
if not channel:
|
||
|
raise request.not_found()
|
||
|
member = channel._find_or_create_member_for_self()
|
||
|
if not member:
|
||
|
raise NotFound()
|
||
|
member._notify_typing(is_typing)
|
||
|
|
||
|
@http.route("/discuss/channel/attachments", methods=["POST"], type="json", auth="public", readonly=True)
|
||
|
@add_guest_to_context
|
||
|
def load_attachments(self, channel_id, limit=30, before=None):
|
||
|
"""Load attachments of a channel. If before is set, load attachments
|
||
|
older than the given id.
|
||
|
:param channel_id: id of the channel
|
||
|
:param limit: maximum number of attachments to return
|
||
|
:param before: id of the attachment from which to load older attachments
|
||
|
"""
|
||
|
channel = request.env["discuss.channel"].search([("id", "=", channel_id)])
|
||
|
if not channel:
|
||
|
raise NotFound()
|
||
|
domain = [
|
||
|
["res_id", "=", channel_id],
|
||
|
["res_model", "=", "discuss.channel"],
|
||
|
]
|
||
|
if before:
|
||
|
domain.append(["id", "<", before])
|
||
|
# sudo: ir.attachment - reading attachments of a channel that the current user can access
|
||
|
return Store(
|
||
|
request.env["ir.attachment"].sudo().search(domain, limit=limit, order="id DESC")
|
||
|
).get_result()
|
||
|
|
||
|
@http.route("/discuss/channel/fold", methods=["POST"], type="json", auth="public")
|
||
|
@add_guest_to_context
|
||
|
def discuss_channel_fold(self, channel_id, state, state_count):
|
||
|
member = request.env["discuss.channel.member"].search([("channel_id", "=", channel_id), ("is_self", "=", True)])
|
||
|
if not member:
|
||
|
raise NotFound()
|
||
|
return member._channel_fold(state, state_count)
|
||
|
|
||
|
@http.route("/discuss/channel/join", methods=["POST"], type="json", auth="public")
|
||
|
@add_guest_to_context
|
||
|
def discuss_channel_join(self, channel_id):
|
||
|
channel = request.env["discuss.channel"].search([("id", "=", channel_id)])
|
||
|
if not channel:
|
||
|
raise NotFound()
|
||
|
channel._find_or_create_member_for_self()
|
||
|
return Store(channel).get_result()
|
||
|
|
||
|
@http.route("/discuss/channel/sub_channel/create", methods=["POST"], type="json", auth="public")
|
||
|
def discuss_channel_sub_channel_create(self, parent_channel_id, from_message_id=None, name=None):
|
||
|
channel = request.env["discuss.channel"].search([("id", "=", parent_channel_id)])
|
||
|
if not channel:
|
||
|
raise NotFound()
|
||
|
sub_channel = channel._create_sub_channel(from_message_id, name)
|
||
|
return {
|
||
|
"data": Store(sub_channel).get_result(),
|
||
|
"sub_channel": Store.one_id(sub_channel),
|
||
|
}
|
||
|
|
||
|
@http.route("/discuss/channel/sub_channel/fetch", methods=["POST"], type="json", auth="public")
|
||
|
@add_guest_to_context
|
||
|
def discuss_channel_sub_channel_fetch(self, parent_channel_id, search_term=None, before=None, limit=30):
|
||
|
channel = request.env["discuss.channel"].search([("id", "=", parent_channel_id)])
|
||
|
if not channel:
|
||
|
raise NotFound()
|
||
|
domain = [("parent_channel_id", "=", channel.id)]
|
||
|
if before:
|
||
|
domain.append(("id", "<", before))
|
||
|
if search_term:
|
||
|
domain.append(("name", "ilike", search_term))
|
||
|
sub_channels = request.env["discuss.channel"].search(domain, order="id desc", limit=limit)
|
||
|
return Store(sub_channels).add(sub_channels._get_last_messages()).get_result()
|