Odoo18-Base/addons/mail/controllers/discuss/channel.py
2025-01-06 10:57:38 +07:00

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()