discourse/plugins/chat/app/services/chat_publisher.rb
Martin Brennan db5ad34508
FEATURE: Allow editing channel slug (#19948)
This commit introduces the ability to edit the channel
slug from the About tab for the chat channel when the user
is admin. Similar to the create channel modal functionality
introduced in 641e94f, if
the slug is left empty then we autogenerate a slug based
on the channel name, and if the user just changes the slug
manually we use that instead.

We do not do any link remapping or anything else of the
sort, when the category slug is changed that does not happen
either.
2023-01-30 13:18:34 +10:00

267 lines
8.0 KiB
Ruby

# frozen_string_literal: true
module ChatPublisher
def self.new_messages_message_bus_channel(chat_channel_id)
"/chat/#{chat_channel_id}/new-messages"
end
def self.publish_new!(chat_channel, chat_message, staged_id)
content =
ChatMessageSerializer.new(
chat_message,
{ scope: anonymous_guardian, root: :chat_message },
).as_json
content[:type] = :sent
content[:stagedId] = staged_id
permissions = permissions(chat_channel)
MessageBus.publish("/chat/#{chat_channel.id}", content.as_json, permissions)
MessageBus.publish(
self.new_messages_message_bus_channel(chat_channel.id),
{
channel_id: chat_channel.id,
message_id: chat_message.id,
user_id: chat_message.user.id,
username: chat_message.user.username,
},
permissions,
)
end
def self.publish_processed!(chat_message)
chat_channel = chat_message.chat_channel
content = {
type: :processed,
chat_message: {
id: chat_message.id,
cooked: chat_message.cooked,
},
}
MessageBus.publish("/chat/#{chat_channel.id}", content.as_json, permissions(chat_channel))
end
def self.publish_edit!(chat_channel, chat_message)
content =
ChatMessageSerializer.new(
chat_message,
{ scope: anonymous_guardian, root: :chat_message },
).as_json
content[:type] = :edit
MessageBus.publish("/chat/#{chat_channel.id}", content.as_json, permissions(chat_channel))
end
def self.publish_refresh!(chat_channel, chat_message)
content =
ChatMessageSerializer.new(
chat_message,
{ scope: anonymous_guardian, root: :chat_message },
).as_json
content[:type] = :refresh
MessageBus.publish("/chat/#{chat_channel.id}", content.as_json, permissions(chat_channel))
end
def self.publish_reaction!(chat_channel, chat_message, action, user, emoji)
content = {
action: action,
user: BasicUserSerializer.new(user, root: false).as_json,
emoji: emoji,
type: :reaction,
chat_message_id: chat_message.id,
}
MessageBus.publish(
"/chat/message-reactions/#{chat_message.id}",
content.as_json,
permissions(chat_channel),
)
MessageBus.publish("/chat/#{chat_channel.id}", content.as_json, permissions(chat_channel))
end
def self.publish_presence!(chat_channel, user, typ)
raise NotImplementedError
end
def self.publish_delete!(chat_channel, chat_message)
MessageBus.publish(
"/chat/#{chat_channel.id}",
{ type: "delete", deleted_id: chat_message.id, deleted_at: chat_message.deleted_at },
permissions(chat_channel),
)
end
def self.publish_bulk_delete!(chat_channel, deleted_message_ids)
MessageBus.publish(
"/chat/#{chat_channel.id}",
{ typ: "bulk_delete", deleted_ids: deleted_message_ids, deleted_at: Time.zone.now },
permissions(chat_channel),
)
end
def self.publish_restore!(chat_channel, chat_message)
content =
ChatMessageSerializer.new(
chat_message,
{ scope: anonymous_guardian, root: :chat_message },
).as_json
content[:type] = :restore
MessageBus.publish("/chat/#{chat_channel.id}", content.as_json, permissions(chat_channel))
end
def self.publish_flag!(chat_message, user, reviewable, score)
# Publish to user who created flag
MessageBus.publish(
"/chat/#{chat_message.chat_channel_id}",
{
type: "self_flagged",
user_flag_status: score.status_for_database,
chat_message_id: chat_message.id,
}.as_json,
user_ids: [user.id],
)
# Publish flag with link to reviewable to staff
MessageBus.publish(
"/chat/#{chat_message.chat_channel_id}",
{ type: "flag", chat_message_id: chat_message.id, reviewable_id: reviewable.id }.as_json,
group_ids: [Group::AUTO_GROUPS[:staff]],
)
end
def self.user_tracking_state_message_bus_channel(user_id)
"/chat/user-tracking-state/#{user_id}"
end
def self.publish_user_tracking_state(user, chat_channel_id, chat_message_id)
MessageBus.publish(
self.user_tracking_state_message_bus_channel(user.id),
{ chat_channel_id: chat_channel_id, chat_message_id: chat_message_id.to_i }.as_json,
user_ids: [user.id],
)
end
def self.new_mentions_message_bus_channel(chat_channel_id)
"/chat/#{chat_channel_id}/new-mentions"
end
def self.publish_new_mention(user_id, chat_channel_id, chat_message_id)
MessageBus.publish(
self.new_mentions_message_bus_channel(chat_channel_id),
{ message_id: chat_message_id, channel_id: chat_channel_id }.as_json,
user_ids: [user_id],
)
end
NEW_CHANNEL_MESSAGE_BUS_CHANNEL = "/chat/new-channel"
def self.publish_new_channel(chat_channel, users)
users.each do |user|
# FIXME: This could generate a lot of queries depending on the amount of users
membership = chat_channel.membership_for(user)
# TODO: this event is problematic as some code will update the membership before calling it
# and other code will update it after calling it
# it means frontend must handle logic for both cases
serialized_channel =
ChatChannelSerializer.new(
chat_channel,
scope: Guardian.new(user), # We need a guardian here for direct messages
root: :channel,
membership: membership,
).as_json
MessageBus.publish(NEW_CHANNEL_MESSAGE_BUS_CHANNEL, serialized_channel, user_ids: [user.id])
end
end
def self.publish_inaccessible_mentions(
user_id,
chat_message,
cannot_chat_users,
without_membership,
too_many_members,
mentions_disabled
)
MessageBus.publish(
"/chat/#{chat_message.chat_channel_id}",
{
type: :mention_warning,
chat_message_id: chat_message.id,
cannot_see: cannot_chat_users.map { |u| { username: u.username, id: u.id } }.as_json,
without_membership:
without_membership.map { |u| { username: u.username, id: u.id } }.as_json,
groups_with_too_many_members: too_many_members.map(&:name).as_json,
group_mentions_disabled: mentions_disabled.map(&:name).as_json,
},
user_ids: [user_id],
)
end
CHANNEL_EDITS_MESSAGE_BUS_CHANNEL = "/chat/channel-edits"
def self.publish_chat_channel_edit(chat_channel, acting_user)
MessageBus.publish(
CHANNEL_EDITS_MESSAGE_BUS_CHANNEL,
{
chat_channel_id: chat_channel.id,
name: chat_channel.title(acting_user),
description: chat_channel.description,
slug: chat_channel.slug,
},
permissions(chat_channel),
)
end
CHANNEL_STATUS_MESSAGE_BUS_CHANNEL = "/chat/channel-status"
def self.publish_channel_status(chat_channel)
MessageBus.publish(
CHANNEL_STATUS_MESSAGE_BUS_CHANNEL,
{ chat_channel_id: chat_channel.id, status: chat_channel.status },
permissions(chat_channel),
)
end
CHANNEL_METADATA_MESSAGE_BUS_CHANNEL = "/chat/channel-metadata"
def self.publish_chat_channel_metadata(chat_channel)
MessageBus.publish(
CHANNEL_METADATA_MESSAGE_BUS_CHANNEL,
{ chat_channel_id: chat_channel.id, memberships_count: chat_channel.user_count },
permissions(chat_channel),
)
end
CHANNEL_ARCHIVE_STATUS_MESSAGE_BUS_CHANNEL = "/chat/channel-archive-status"
def self.publish_archive_status(
chat_channel,
archive_status:,
archived_messages:,
archive_topic_id:,
total_messages:
)
MessageBus.publish(
CHANNEL_ARCHIVE_STATUS_MESSAGE_BUS_CHANNEL,
{
chat_channel_id: chat_channel.id,
archive_failed: archive_status == :failed,
archive_completed: archive_status == :success,
archived_messages: archived_messages,
total_messages: total_messages,
archive_topic_id: archive_topic_id,
},
permissions(chat_channel),
)
end
private
def self.permissions(chat_channel)
{ user_ids: chat_channel.allowed_user_ids, group_ids: chat_channel.allowed_group_ids }
end
def self.anonymous_guardian
Guardian.new(nil)
end
end