# frozen_string_literal: true class SharedAiConversation < ActiveRecord::Base DEFAULT_MAX_POSTS = 100 belongs_to :user belongs_to :target, polymorphic: true validates :user_id, presence: true validates :target, presence: true validates :context, presence: true validates :share_key, presence: true, uniqueness: true before_validation :generate_share_key, on: :create def self.share_conversation(user, target, max_posts: DEFAULT_MAX_POSTS) raise "Target must be a topic for now" if !target.is_a?(Topic) conversation = find_by(user: user, target: target) conversation_data = build_conversation_data(target, max_posts: max_posts) conversation = if conversation conversation.update(**conversation_data) conversation else create(user_id: user.id, target: target, **conversation_data) end ::Jobs.enqueue(:shared_conversation_adjust_upload_security, conversation_id: conversation.id) conversation end def self.destroy_conversation(conversation) conversation.destroy ::Jobs.enqueue( :shared_conversation_adjust_upload_security, target_id: conversation.target_id, target_type: conversation.target_type, ) end # Technically this may end up being a chat message # but this name works class SharedPost attr_accessor :user attr_reader :id, :user_id, :created_at, :cooked, :persona def initialize(post) @id = post[:id] @user_id = post[:user_id] @created_at = DateTime.parse(post[:created_at]) @cooked = post[:cooked] @persona = post[:persona] end end def populated_context return @populated_context if @populated_context @populated_context = context.map { |post| SharedPost.new(post.symbolize_keys) } populate_user_info!(@populated_context) @populated_context end def to_json posts = self.populated_context.map do |post| { id: post.id, cooked: post.cooked, username: post.user.username, created_at: post.created_at, } end { llm_name: self.llm_name, share_key: self.share_key, title: self.title, posts: posts } end def url "#{Discourse.base_uri}/discourse-ai/ai-bot/shared-ai-conversations/#{share_key}" end def html_excerpt html = +"" populated_context.each do |post| text = PrettyText.excerpt( post.cooked, 400, text_entities: true, strip_links: true, strip_details: true, ) html << "
#{post.user.username}: #{text}
" if html.length > 1000 html << "...
" break end end html << "#{I18n.t("discourse_ai.share_ai.read_more")}" html end def onebox <<~HTML