# frozen_string_literal: true require 'uri' module Integrations class Irker < Integration validates :recipients, presence: true, if: :validate_recipients? before_validation :get_channels field :server_host, placeholder: 'localhost', title: -> { s_('IrkerService|Server host (optional)') }, help: -> { s_('IrkerService|irker daemon hostname (defaults to localhost).') } field :server_port, placeholder: 6659, title: -> { s_('IrkerService|Server port (optional)') }, help: -> { s_('IrkerService|irker daemon port (defaults to 6659).') } field :default_irc_uri, title: -> { s_('IrkerService|Default IRC URI (optional)') }, help: -> { s_('IrkerService|URI to add before each recipient.') }, placeholder: 'irc://irc.network.net:6697/' field :recipients, type: 'textarea', title: -> { s_('IrkerService|Recipients') }, placeholder: 'irc[s]://irc.network.net[:port]/#channel', required: true, help: -> do recipients_docs_link = ActionController::Base.helpers.link_to( s_('IrkerService|How to enter channels or users?'), Rails.application.routes.url_helpers.help_page_url( 'user/project/integrations/irker', anchor: 'enter-irker-recipients' ), target: '_blank', rel: 'noopener noreferrer' ) ERB::Util.html_escape( s_('IrkerService|Channels and users separated by whitespaces. %{recipients_docs_link}') ) % { recipients_docs_link: recipients_docs_link.html_safe } end field :colorize_messages, type: 'checkbox', title: -> { _('Colorize messages') } # NOTE: This field is only used internally to store the parsed # channels from the `recipients` field, it should not be exposed # in the UI or API. prop_accessor :channels def title s_('IrkerService|irker (IRC gateway)') end def description s_('IrkerService|Send update messages to an irker server.') end def self.to_param 'irker' end def self.supported_events %w[push] end def execute(data) return unless supported_events.include?(data[:object_kind]) Integrations::IrkerWorker.perform_async( project_id, channels, colorize_messages, data, settings ) end def settings { server_host: server_host.presence || 'localhost', server_port: server_port.presence || 6659 } end def help docs_link = ActionController::Base.helpers.link_to( _('Learn more.'), Rails.application.routes.url_helpers.help_page_url( 'user/project/integrations/irker', anchor: 'set-up-an-irker-daemon' ), target: '_blank', rel: 'noopener noreferrer' ) format(s_( 'IrkerService|Send update messages to an irker server. ' \ 'Before you can use this, you need to set up the irker daemon. %{docs_link}' ).html_safe, docs_link: docs_link.html_safe) end private def get_channels return true unless activated? return true if recipients.nil? || recipients.empty? map_recipients errors.add(:recipients, 'are all invalid') if channels.empty? true end def map_recipients self.channels = recipients.split(/\s+/).map do |recipient| format_channel(recipient) end channels.reject!(&:nil?) end def format_channel(recipient) uri = nil # Try to parse the chan as a full URI begin uri = consider_uri(URI.parse(recipient)) rescue URI::InvalidURIError end unless uri.present? && default_irc_uri.nil? begin new_recipient = URI.join(default_irc_uri, '/', recipient).to_s uri = consider_uri(URI.parse(new_recipient)) rescue StandardError log_error("Unable to create a valid URL", default_irc_uri: default_irc_uri, recipient: recipient) end end uri end def consider_uri(uri) return unless uri.is_a?(URI) && uri.scheme.present? # Authorize both irc://domain.com/#chan and irc://domain.com/chan return unless uri.scheme =~ /\Aircs?\z/ && !uri.path.nil? uri.to_s end end end