lib/slack/smart-bot/comm/respond.rb in slack-smart-bot-1.14.2 vs lib/slack/smart-bot/comm/respond.rb in slack-smart-bot-1.15.0

- old
+ new

@@ -1,242 +1,271 @@ class SlackSmartBot def respond(msg = "", dest = nil, unfurl_links: true, unfurl_media: true, thread_ts: "", web_client: true, blocks: [], dont_share: false, return_message: false, max_chars_per_message: 4000) result = true resp = nil - if (msg.to_s != "" or !msg.to_s.match?(/^A\s*\z/) or !blocks.empty?) and Thread.current[:routine_type].to_s != "bgroutine" - if !web_client.is_a?(TrueClass) and !web_client.is_a?(FalseClass) - (!unfurl_links or !unfurl_media) ? web_client = true : web_client = false - end - begin - msg = msg.to_s - web_client = true if !blocks.empty? - on_thread = Thread.current[:on_thread] - if dest.nil? and Thread.current.key?(:dest) - dest = Thread.current[:dest] - elsif dest.is_a?(Symbol) and dest == :on_thread - on_thread = true - dest = Thread.current[:dest] - elsif dest.is_a?(Symbol) and dest == :direct - dest = Thread.current[:user].id - end - if thread_ts.to_s.match?(/^\d+\.\d+$/) - on_thread = true - #thread id - elsif thread_ts.to_s.match?(/^p\d\d\d\d\d+$/) - on_thread = true - #a thread id taken from url fex: p1622549264010700 - thread_ts = thread_ts.scan(/(\d+)/).join - thread_ts = "#{thread_ts[0..9]}.#{thread_ts[10..-1]}" - else - thread_ts = Thread.current[:thread_ts] if thread_ts == "" - end + if Thread.current.key?(:prompt) and !Thread.current[:prompt].empty? #don't send response to slack since chatgpt will get the response from stdout + Thread.current[:stdout] += "#{msg}\n" + return true + else + if (msg.to_s != "" or !msg.to_s.match?(/^A\s*\z/) or !blocks.empty?) and Thread.current[:routine_type].to_s != "bgroutine" + if !web_client.is_a?(TrueClass) and !web_client.is_a?(FalseClass) + (!unfurl_links or !unfurl_media) ? web_client = true : web_client = false + end + begin + msg = msg.to_s + web_client = true if !blocks.empty? - dest = @channels_id[dest] if @channels_id.key?(dest) #it is a name of channel - - on_thread ? txt_on_thread=':on_thread:' : txt_on_thread='' - - if blocks.empty? - if !config.simulate #https://api.slack.com/docs/rate-limits - msg.size > 500 ? wait = 0.5 : wait = 0.1 - sleep wait if Time.now <= (@last_respond + wait) - else - wait = 0 + on_thread = Thread.current[:on_thread] + if dest.nil? and Thread.current.key?(:dest) + dest = Thread.current[:dest] + elsif dest.is_a?(Symbol) and dest == :on_thread + on_thread = true + dest = Thread.current[:dest] + elsif dest.is_a?(Symbol) and dest == :direct + dest = Thread.current[:user].id end - msgs = [] # max of max_chars_per_message characters per message - if max_chars_per_message.nil? - txt = msg + if thread_ts.to_s.match?(/^\d+\.\d+$/) + on_thread = true + #thread id + elsif thread_ts.to_s.match?(/^p\d\d\d\d\d+$/) + on_thread = true + #a thread id taken from url fex: p1622549264010700 + thread_ts = thread_ts.scan(/(\d+)/).join + thread_ts = "#{thread_ts[0..9]}.#{thread_ts[10..-1]}" else - txt = "" - msg.split("\n").each do |m| - if (m + txt).size > max_chars_per_message - unless txt == "" - txt[0] = '.' if txt.match?(/\A\s\s\s/) #first line of message in slack don't show spaces at the begining so we force it by changing first char - t = txt.chars.each_slice(max_chars_per_message).map(&:join) - msgs << t - txt = "" - end - end - txt += (m + "\n") - txt[0] = '.' if txt.match?(/\A\s\s\s/) #first line of message in slack don't show spaces at the begining so we force it by changing first char - txt[0] = ". " if txt.match?(/\A\t/) - end + thread_ts = Thread.current[:thread_ts] if thread_ts == "" end - msgs << txt - msgs.flatten! - msgs.delete_if{|e| e.match?(/\A\s*\z/)} - if dest.nil? - if config[:simulate] - open("#{config.path}/buffer_complete.log", "a") { |f| - f.puts "|#{@channel_id}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{msg}~~~" - } + + dest = @channels_id[dest] if @channels_id.key?(dest) #it is a name of channel + + on_thread ? txt_on_thread=":on_thread:" : txt_on_thread='' + + if blocks.empty? + if !config.simulate #https://api.slack.com/docs/rate-limits + msg.size > 500 ? wait = 0.5 : wait = 0.1 + sleep wait if Time.now <= (@last_respond + wait) else - if on_thread - msgs.each do |msg| - if web_client - resp = client.web_client.chat_postMessage(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts) - else - resp = client.message(channel: @channel_id, text: msg, as_user: true, thread_ts: thread_ts, unfurl_links: unfurl_links, unfurl_media: unfurl_media) + wait = 0 + end + msgs = [] # max of max_chars_per_message characters per message + if max_chars_per_message.nil? + txt = msg + else + txt = "" + in_a_code_block = false + print_previous = false + all_lines = msg.split("\n") + + all_lines.each_with_index do |m, i| + if m.match?(/^\s*```/) + in_a_code_block = !in_a_code_block + num_chars_code = 0 + print_previous = false + if in_a_code_block + all_lines[i+1..-1].each do |l| + num_chars_code += l.size + break if l.match?(/^\s*```/) + end + if num_chars_code + (m + txt).size > max_chars_per_message + print_previous = true + end end - sleep wait - end - else - msgs.each do |msg| - if web_client - resp = client.web_client.chat_postMessage(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media) - else - resp = client.message(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media) + end + if ((m + txt).size > max_chars_per_message and !in_a_code_block) or print_previous + unless txt == "" + txt[0] = '.' if txt.match?(/\A\s\s\s/) #first line of message in slack don't show spaces at the begining so we force it by changing first char + if m.match?(/^\s*```\s*$/) and !in_a_code_block + txt += (m + "\n") + m = "" + end + t = txt.chars.each_slice(max_chars_per_message).map(&:join) + msgs << t + txt = "" + print_previous = false if print_previous end - sleep wait end + txt += (m + "\n") + txt[0] = '.' if txt.match?(/\A\s\s\s/) #first line of message in slack don't show spaces at the begining so we force it by changing first char + txt[0] = ". " if txt.match?(/\A\t/) end end - if config[:testing] and config.on_master_bot and !@buffered - @buffered = true - open("#{config.path}/buffer.log", "a") { |f| - f.puts "|#{@channel_id}|#{config[:nick_id]}|#{config[:nick]}|#{msg}" - } - end - elsif dest[0] == "C" or dest[0] == "G" # channel - if config[:simulate] - open("#{config.path}/buffer_complete.log", "a") { |f| - f.puts "|#{dest}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{msg}~~~" - } - else - if on_thread - msgs.each do |msg| - if web_client - resp = client.web_client.chat_postMessage(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts) - else - resp = client.message(channel: dest, text: msg, as_user: true, thread_ts: thread_ts, unfurl_links: unfurl_links, unfurl_media: unfurl_media) + msgs << txt + msgs.flatten! + msgs.delete_if{|e| e.match?(/\A\s*\z/)} + if dest.nil? + if config[:simulate] + open("#{config.path}/buffer_complete.log", "a") { |f| + f.puts "|#{@channel_id}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{msg}~~~" + } + else + if on_thread + msgs.each do |msg| + if web_client + resp = client.web_client.chat_postMessage(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts) + else + resp = client.message(channel: @channel_id, text: msg, as_user: true, thread_ts: thread_ts, unfurl_links: unfurl_links, unfurl_media: unfurl_media) + end + sleep wait end - sleep wait + else + msgs.each do |msg| + if web_client + resp = client.web_client.chat_postMessage(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media) + else + resp = client.message(channel: @channel_id, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media) + end + sleep wait + end end + end + if config[:testing] and config.on_master_bot and !@buffered + @buffered = true + open("#{config.path}/buffer.log", "a") { |f| + f.puts "|#{@channel_id}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{msg}" + } + end + elsif dest[0] == "C" or dest[0] == "G" # channel + if config[:simulate] + open("#{config.path}/buffer_complete.log", "a") { |f| + f.puts "|#{dest}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{msg}~~~" + } else - msgs.each do |msg| - if web_client - resp = client.web_client.chat_postMessage(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media) - else - resp = client.message(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media) + if on_thread + msgs.each do |msg| + if web_client + resp = client.web_client.chat_postMessage(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts) + else + resp = client.message(channel: dest, text: msg, as_user: true, thread_ts: thread_ts, unfurl_links: unfurl_links, unfurl_media: unfurl_media) + end + sleep wait end - sleep wait + else + msgs.each do |msg| + if web_client + resp = client.web_client.chat_postMessage(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media) + else + resp = client.message(channel: dest, text: msg, as_user: true, unfurl_links: unfurl_links, unfurl_media: unfurl_media) + end + sleep wait + end end end - end - if config[:testing] and config.on_master_bot and !@buffered - @buffered = true - open("#{config.path}/buffer.log", "a") { |f| - f.puts "|#{dest}|#{config[:nick_id]}|#{config[:nick]}|#{msg}" - } - end - elsif dest[0] == "D" or dest[0] == "U" or dest[0] == "W" # Direct message - msgs.each do |msg| - resp = send_msg_user(dest, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media) - sleep wait - end - elsif dest[0] == "@" - begin - user_info = @users.select { |u| u.id == dest[1..-1] or u.name == dest[1..-1] or (u.key?(:enterprise_user) and u.enterprise_user.id == dest[1..-1]) }[-1] + if config[:testing] and config.on_master_bot and !@buffered + @buffered = true + open("#{config.path}/buffer.log", "a") { |f| + f.puts "|#{dest}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{msg}" + } + end + elsif dest[0] == "D" or dest[0] == "U" or dest[0] == "W" # Direct message msgs.each do |msg| - resp = send_msg_user(user_info.id, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media) + resp = send_msg_user(dest, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts) sleep wait end - rescue Exception => stack - @logger.warn("user #{dest} not found.") - @logger.warn stack - if Thread.current.key?(:dest) - respond("User #{dest} not found.") + elsif dest[0] == "@" + begin + user_info = @users.select { |u| u.id == dest[1..-1] or u.name == dest[1..-1] or (u.key?(:enterprise_user) and u.enterprise_user.id == dest[1..-1]) }[-1] + msgs.each do |msg| + resp = send_msg_user(user_info.id, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, thread_ts: thread_ts) + sleep wait + end + rescue Exception => stack + @logger.warn("user #{dest} not found.") + @logger.warn stack + if Thread.current.key?(:dest) + respond("User #{dest} not found.") + end + result = false end + else + @logger.warn("method respond not treated correctly: msg:#{msg} dest:#{dest}") result = false end else - @logger.warn("method respond not treated correctly: msg:#{msg} dest:#{dest}") - result = false - end - else - wait = 0.1 - if dest.nil? - if config[:simulate] - open("#{config.path}/buffer_complete.log", "a") { |f| - f.puts "|#{@channel_id}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{blocks.join}~~~" - } - else - if on_thread - blocks.each_slice(40).to_a.each do |blockstmp| - resp = client.web_client.chat_postMessage(channel: @channel_id, blocks: blockstmp, as_user: true, thread_ts: thread_ts) - sleep wait - end + wait = 0.1 + if dest.nil? + if config[:simulate] + open("#{config.path}/buffer_complete.log", "a") { |f| + f.puts "|#{@channel_id}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{blocks.join}~~~" + } else - blocks.each_slice(40).to_a.each do |blockstmp| - resp = client.web_client.chat_postMessage(channel: @channel_id, blocks: blockstmp, as_user: true) - sleep wait + if on_thread + blocks.each_slice(40).to_a.each do |blockstmp| + resp = client.web_client.chat_postMessage(channel: @channel_id, blocks: blockstmp, as_user: true, thread_ts: thread_ts) + sleep wait + end + else + blocks.each_slice(40).to_a.each do |blockstmp| + resp = client.web_client.chat_postMessage(channel: @channel_id, blocks: blockstmp, as_user: true) + sleep wait + end end end - end - if config[:testing] and config.on_master_bot and !@buffered - @buffered = true - open("#{config.path}/buffer.log", "a") { |f| - f.puts "|#{@channel_id}|#{config[:nick_id]}|#{config[:nick]}|#{blocks.join}" - } - end - elsif dest[0] == "C" or dest[0] == "G" # channel - if config[:simulate] - open("#{config.path}/buffer_complete.log", "a") { |f| - f.puts "|#{dest}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{blocks.join}~~~" - } - else - if on_thread - blocks.each_slice(40).to_a.each do |blockstmp| - resp = client.web_client.chat_postMessage(channel: dest, blocks: blockstmp, as_user: true, thread_ts: thread_ts) - sleep wait - end + if config[:testing] and config.on_master_bot and !@buffered + @buffered = true + open("#{config.path}/buffer.log", "a") { |f| + f.puts "|#{@channel_id}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{blocks.join}" + } + end + elsif dest[0] == "C" or dest[0] == "G" # channel + if config[:simulate] + open("#{config.path}/buffer_complete.log", "a") { |f| + f.puts "|#{dest}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{txt_on_thread}#{blocks.join}~~~" + } else - blocks.each_slice(40).to_a.each do |blockstmp| - resp = client.web_client.chat_postMessage(channel: dest, blocks: blockstmp, as_user: true) - sleep wait + if on_thread + blocks.each_slice(40).to_a.each do |blockstmp| + resp = client.web_client.chat_postMessage(channel: dest, blocks: blockstmp, as_user: true, thread_ts: thread_ts) + sleep wait + end + else + blocks.each_slice(40).to_a.each do |blockstmp| + resp = client.web_client.chat_postMessage(channel: dest, blocks: blockstmp, as_user: true) + sleep wait + end end end - end - if config[:testing] and config.on_master_bot and !@buffered - @buffered = true - open("#{config.path}/buffer.log", "a") { |f| - f.puts "|#{dest}|#{config[:nick_id]}|#{config[:nick]}|#{blocks.join}" - } - end - elsif dest[0] == "D" or dest[0] == "U" or dest[0] == "W" # Direct message - blocks.each_slice(40).to_a.each do |blockstmp| - resp = send_msg_user(dest, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, blocks: blockstmp) - sleep wait - end - elsif dest[0] == "@" - begin - user_info = @users.select { |u| u.id == dest[1..-1] or (u.key?(:enterprise_user) and u.enterprise_user.id == dest[1..-1]) }[-1] + if config[:testing] and config.on_master_bot and !@buffered + @buffered = true + open("#{config.path}/buffer.log", "a") { |f| + f.puts "|#{dest}|#{thread_ts}|#{config[:nick_id]}|#{config[:nick]}|#{blocks.join}" + } + end + elsif dest[0] == "D" or dest[0] == "U" or dest[0] == "W" # Direct message blocks.each_slice(40).to_a.each do |blockstmp| - resp = send_msg_user(user_info.id, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, blocks: blockstmp) + resp = send_msg_user(dest, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, blocks: blockstmp, thread_ts: thread_ts) sleep wait end - rescue Exception => stack - @logger.warn("user #{dest} not found.") - @logger.warn stack - if Thread.current.key?(:dest) - respond("User #{dest} not found.") + elsif dest[0] == "@" + begin + user_info = @users.select { |u| u.id == dest[1..-1] or (u.key?(:enterprise_user) and u.enterprise_user.id == dest[1..-1]) }[-1] + blocks.each_slice(40).to_a.each do |blockstmp| + resp = send_msg_user(user_info.id, msg, on_thread, unfurl_links: unfurl_links, unfurl_media: unfurl_media, blocks: blockstmp, thread_ts: thread_ts) + sleep wait + end + rescue Exception => stack + @logger.warn("user #{dest} not found.") + @logger.warn stack + if Thread.current.key?(:dest) + respond("User #{dest} not found.") + end + result = false end + else + @logger.warn("method respond not treated correctly: msg:#{msg} dest:#{dest}") result = false end - else - @logger.warn("method respond not treated correctly: msg:#{msg} dest:#{dest}") - result = false end + @last_respond = Time.now + rescue Exception => stack + @logger.warn stack + result = false end - @last_respond = Time.now - rescue Exception => stack - @logger.warn stack - result = false end + if Thread.current.key?(:routine) and Thread.current[:routine] + File.write("#{config.path}/routines/#{@channel_id}/#{Thread.current[:routine_name]}_output.txt", msg, mode: "a+") + end + result = resp if return_message + return result end - if Thread.current.key?(:routine) and Thread.current[:routine] - File.write("#{config.path}/routines/#{@channel_id}/#{Thread.current[:routine_name]}_output.txt", msg, mode: "a+") - end - result = resp if return_message - return result end end