Class: TurboChat::Configuration

Inherits:
Object
  • Object
show all
Includes:
BlockedWordsSupport, EmojiSupport, RoleSupport
Defined in:
lib/turbo_chat/configuration.rb,
lib/turbo_chat/configuration/defaults.rb,
lib/turbo_chat/configuration/role_support.rb,
lib/turbo_chat/configuration/emoji_support.rb,
lib/turbo_chat/configuration/blocked_words_support.rb

Defined Under Namespace

Modules: BlockedWordsSupport, EmojiSupport, RoleSupport Classes: Chat, ChatMessage, Events, ModeSettings, Moderation, Scope, Signals, Style

Constant Summary collapse

SCOPE_CLASSES =
{
  chat: Chat,
  chat_message: ChatMessage,
  style: Style,
  moderation: Moderation,
  events: Events,
  signals: Signals
}.freeze
DEFAULT_ROLE_DEFINITIONS =
{
  "member" => {
    name: "Member",
    rank: 0,
    permissions: i[view_chat post_message mention_member]
  },
  "moderator" => {
    name: "Moderator",
    rank: 1,
    permissions: i[
      view_chat post_message mention_member mention_all mention_role
      invite_member mute_member timeout_member ban_member delete_message
    ]
  },
  "admin" => {
    name: "Admin",
    rank: 2,
    permissions: i[
      view_chat post_message mention_member mention_all mention_role
      invite_member mute_member timeout_member ban_member delete_message
      close_chat reopen_chat grant_member_permissions
    ]
  }
}.freeze
DEFAULT_MESSAGE_HTML_TAGS =
%w[a b br code em i li ol p pre strong ul].freeze
DEFAULT_MESSAGE_HTML_ATTRIBUTES =
%w[href target rel class].freeze
DEFAULT_EMOJI_ALIASES =
{
  "smile" => "😄",
  "grin" => "😁",
  "laughing" => "😆",
  "blush" => "😊",
  "wink" => "😉",
  "heart" => "❤️",
  "thumbsup" => "👍",
  "+1" => "👍",
  "thumbsdown" => "👎",
  "-1" => "👎",
  "fire" => "🔥",
  "rocket" => "🚀",
  "thinking" => "🤔",
  "tada" => "🎉",
  "wave" => "👋",
  "eyes" => "👀"
}.freeze
DEFAULT_BLOCKED_WORDS_SCRAMBLE_CHARS =
%w[# * / ( = ) ! 8].freeze
DEFAULT_BLOCKED_WORDS_ACTION =
"reject".freeze
DEFAULT_MESSAGE_SOURCE_LABELS =
{
  "app" => "App",
  "whatsapp" => "WhatsApp"
}.freeze
CHAT_DEFAULTS =
{
  permission_adapter: -> { TurboChat::Permission },
  current_participant_resolver: nil,
  max_chat_participants: 10,
  active_chat_window: -> { 5.minutes },
  show_members: true,
  show_members_list: true,
  show_members_invite_controls: true,
  show_invite_fallback_when_members_hidden: true,
  system_messages: true,
  disable_input: false,
  show_header_title: true,
  show_header_status: true,
  show_header_close_action: true,
  show_header_leave_action: true,
  show_header_back_action: true
}.freeze
CHAT_MESSAGE_DEFAULTS =
{
  max_message_length: 1000,
  message_history_limit: 200,
  enable_mentions: true,
  mention_filter_exclude_self: true,
  mention_filter_hide_roles: true,
  enable_emoji_aliases: true,
  emoji_aliases: -> { DEFAULT_EMOJI_ALIASES.dup },
  blocked_words: -> { [] },
  blocked_words_action: DEFAULT_BLOCKED_WORDS_ACTION,
  blocked_words_scramble_chars: -> { DEFAULT_BLOCKED_WORDS_SCRAMBLE_CHARS.dup },
  message_insert_position: "append_end",
  message_source_labels: -> { DEFAULT_MESSAGE_SOURCE_LABELS.dup },
  render_message_html: false,
  message_html_tags: -> { DEFAULT_MESSAGE_HTML_TAGS.dup },
  message_html_attributes: -> { DEFAULT_MESSAGE_HTML_ATTRIBUTES.dup },
  timestamp_formatter: -> { ->(timestamp, _chat_message = nil) { I18n.l(timestamp.in_time_zone, format: :long) } },
  role_formatter: -> { ->(role, _chat_message = nil) { role.to_s.humanize } }
}.freeze
STYLE_DEFAULTS =
{
  mention_mark_hex_color: nil,
  mention_highlight_hex_color: nil,
  own_message_hex_color: nil,
  other_message_hex_color: nil,
  role_message_hex_colors: -> { {} },
  show_timestamp: true,
  show_role: false,
  composer_placeholder_text: "start chatting",
  composer_add_files_display: false,
  composer_add_files_active: false,
  composer_microphone_display: false,
  composer_microphone_active: false,
  chat_style: "chat_style_bounded",
  message_css_class_resolver: nil,
  signal_text_sheen: true
}.freeze
MODERATION_DEFAULTS =
{
  emit_moderation_events: false,
  emit_blocked_words_events: false
}.freeze
EVENTS_DEFAULTS =
{
  emit_typing_events: false,
  emit_message_events: false,
  emit_mention_events: false,
  emit_invitation_events: false,
  emit_chat_lifecycle_events: false
}.freeze
SIGNALS_DEFAULTS =
{
  signal_ttl_seconds: 60,
  show_self_signals: false,
  replace_signals_on_message_submit: false
}.freeze
SCOPED_DEFAULTS =
{
  chat: CHAT_DEFAULTS,
  chat_message: CHAT_MESSAGE_DEFAULTS,
  style: STYLE_DEFAULTS,
  moderation: MODERATION_DEFAULTS,
  events: EVENTS_DEFAULTS,
  signals: SIGNALS_DEFAULTS
}.freeze
ATTRIBUTE_SCOPES =
build_attribute_scopes(SCOPED_DEFAULTS)
DEFAULTS =
ATTRIBUTE_SCOPES.each_with_object({}) do |(attribute, scope_name), defaults|
  defaults[attribute] = SCOPED_DEFAULTS.fetch(scope_name).fetch(attribute)
end.freeze
ASSISTANT_MODE_DEFAULTS =
{
  max_chat_participants: 2,
  show_members: false,
  show_members_list: false,
  show_members_invite_controls: false,
  show_invite_fallback_when_members_hidden: false,
  system_messages: false,
  show_header_close_action: false,
  enable_mentions: false,
  emit_mention_events: false,
  emit_invitation_events: false,
  emit_chat_lifecycle_events: false,
  emit_moderation_events: false
}.freeze
MODE_DEFAULTS =
{
  standard: {}.freeze,
  assistant: ASSISTANT_MODE_DEFAULTS
}.freeze
MODE_NAMES =
MODE_DEFAULTS.keys.freeze
SCOPE_NAMES =
SCOPED_DEFAULTS.keys.freeze
ATTRIBUTES =
ATTRIBUTE_SCOPES.keys.freeze

Class Method Summary collapse

Instance Method Summary collapse

Methods included from BlockedWordsSupport

#effective_blocked_words, #effective_blocked_words_action, #effective_blocked_words_scramble_chars

Methods included from EmojiSupport

#add_emoji_alias, #clear_emoji_aliases!, #effective_emoji_aliases, #remove_emoji_alias, #reset_emoji_aliases!

Methods included from RoleSupport

#add_role, #additional_roles, #clear_additional_roles!, #remove_role, #role_definition, #role_definitions

Constructor Details

#initializeConfiguration

Returns a new instance of Configuration.



98
99
100
101
102
103
104
# File 'lib/turbo_chat/configuration.rb', line 98

def initialize
  SCOPE_CLASSES.each do |scope_name, klass|
    instance_variable_set("@#{scope_name}", klass.new)
  end
  @additional_roles = {}
  reset_modes!
end

Class Method Details

.config_boolean(method_name, default:, chat: nil) ⇒ Object



160
161
162
163
164
165
# File 'lib/turbo_chat/configuration.rb', line 160

def config_boolean(method_name, default:, chat: nil)
  value = config_value(method_name, default: default, chat: chat)
  ActiveModel::Type::Boolean.new.cast(value)
rescue NoMethodError, TypeError
  default
end

.config_value(method_name, default: nil, chat: nil) ⇒ Object



150
151
152
153
154
155
156
157
158
# File 'lib/turbo_chat/configuration.rb', line 150

def config_value(method_name, default: nil, chat: nil)
  config = TurboChat.configuration
  return config.resolved_value(method_name, chat: chat, default: default) if config.respond_to?(:resolved_value)
  return config.public_send(method_name) if config.respond_to?(method_name)

  default
rescue NoMethodError, TypeError, ArgumentError
  default
end

.extract_chat_mode(chat_or_mode) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/turbo_chat/configuration.rb', line 167

def extract_chat_mode(chat_or_mode)
  case chat_or_mode
  when nil
    nil
  when String, Symbol
    normalize_mode_name(chat_or_mode)
  else
    return nil unless chat_or_mode.respond_to?(:chat_mode)

    normalize_mode_name(chat_or_mode.chat_mode)
  end
end

.normalize_mode_name(value) ⇒ Object



180
181
182
183
184
185
186
187
188
# File 'lib/turbo_chat/configuration.rb', line 180

def normalize_mode_name(value)
  normalized = value.to_s.strip
  return nil if normalized.blank?

  mode_name = normalized.to_sym
  return nil unless MODE_NAMES.include?(mode_name)

  mode_name
end

.resolve_default_value(default_value) ⇒ Object



146
147
148
# File 'lib/turbo_chat/configuration.rb', line 146

def resolve_default_value(default_value)
  default_value.respond_to?(:call) ? default_value.call : (default_value.dup rescue default_value)
end

Instance Method Details

#mode(name) ⇒ Object

Raises:

  • (ArgumentError)


106
107
108
109
110
111
# File 'lib/turbo_chat/configuration.rb', line 106

def mode(name)
  normalized = self.class.normalize_mode_name(name)
  raise ArgumentError, "unknown chat mode: #{name.inspect}" if normalized.nil?

  @modes[normalized]
end

#reset_mode!(name) ⇒ Object

Raises:

  • (ArgumentError)


113
114
115
116
117
118
# File 'lib/turbo_chat/configuration.rb', line 113

def reset_mode!(name)
  normalized = self.class.normalize_mode_name(name)
  raise ArgumentError, "unknown chat mode: #{name.inspect}" if normalized.nil?

  @modes[normalized] = ModeSettings.new(MODE_DEFAULTS.fetch(normalized))
end

#reset_modes!Object



120
121
122
123
124
# File 'lib/turbo_chat/configuration.rb', line 120

def reset_modes!
  @modes = MODE_DEFAULTS.each_with_object({}) do |(mode_name, defaults), modes|
    modes[mode_name] = ModeSettings.new(defaults)
  end
end

#resolved_value(attribute, chat: nil, default: nil) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/turbo_chat/configuration.rb', line 126

def resolved_value(attribute, chat: nil, default: nil)
  base_value = if respond_to?(attribute)
                 public_send(attribute)
               else
                 default
               end

  mode_name = self.class.extract_chat_mode(chat)
  return base_value if mode_name.nil? || mode_name == :standard

  mode_settings = @modes[mode_name]
  return base_value unless mode_settings&.respond_to?(attribute)

  override_value = mode_settings.public_send(attribute)
  override_value.nil? ? base_value : override_value
rescue NoMethodError, TypeError, ArgumentError
  default
end