Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions app/jobs/regular/call_zapier_webhook.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module Jobs
class DiscourseAutomationCallZapierWebhook < ::Jobs::Base
def execute(args)
RateLimiter.new(nil, 'discourse_automation_call_zapier', 5, 30).performed!

result = Excon.post(args['webhook_url'],
body: args['context'].to_json,
headers: { 'Content-Type' => 'application/json', 'Accept' => 'application/json' }
)

if result.status != 200
Rails.logger.warn("Failed to call Zapier webhook at #{args['webhook_url']} Status: #{result.status}: #{result.status_line}")
end
end
end
end
22 changes: 22 additions & 0 deletions app/lib/discourse_automation/scripts/zapier_webhook.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

DiscourseAutomation::Scriptable::ZAPIER_WEBHOOK = 'zapier_webhook'

DiscourseAutomation::Scriptable.add(DiscourseAutomation::Scriptable::ZAPIER_WEBHOOK) do
field :webhook_url, component: :text, required: true

version 1

triggerables [:user_promoted, :user_added_to_group]

script do |context, fields|
webhook_url = fields.dig('webhook_url', 'value')

unless webhook_url.start_with?("https://hooks.zapier.com/hooks/catch/")
Rails.logger.warn "[discourse-automation] #{webhook_url} is not a valid Zapier webhook URL, expecting an URL starting with https://hooks.zapier.com/hooks/catch/"
next
end

Jobs.enqueue(:discourse_automation_call_zapier_webhook, webhook_url: webhook_url, context: context)
end
end
5 changes: 5 additions & 0 deletions config/locales/client.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ en:
description: Optional, allows to limit trigger execution to this category
scriptables:
not_found: Couldn’t find script `%{script}` for automation `%{automation}`, ensure the associated plugin is installed
zapier_webhook:
fields:
webhook_url:
label: Webhook URL
description: "Expects a valid Zapier webhook URL, eg: https://hooks.zapier.com/hooks/catch/xxx/yyy/"
auto_responder:
fields:
word_answer_list:
Expand Down
3 changes: 3 additions & 0 deletions config/locales/server.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ en:
description: Flags a post if it contains specified words
flag_message: "Post contains disallowed words: %{words}"
doc: Post containing all given words at once will be flagged and hidden. Note that defining multiple words delimited by a comma will be used as compound (each word has to be present).
zapier_webhook:
title: Zapier webhook
description: Calls a zap with the context of a trigger as body
auto_responder:
title: Auto Responder
description: Posts a reply to a post including specified keywords
Expand Down
2 changes: 2 additions & 0 deletions plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def handle_user_promoted(user_id, new_trust_level, old_trust_level)
'../app/models/discourse_automation/pending_pm',
'../app/models/discourse_automation/user_global_notice',
'../app/models/discourse_automation/field',
'../app/jobs/regular/call_zapier_webhook',
'../app/jobs/scheduled/discourse_automation_tracker',
'../app/jobs/scheduled/stalled_wiki_tracker',
'../app/jobs/scheduled/stalled_topic_tracker',
Expand All @@ -117,6 +118,7 @@ def handle_user_promoted(user_id, new_trust_level, old_trust_level)
'../app/lib/discourse_automation/scripts/send_pms',
'../app/lib/discourse_automation/scripts/topic_required_words',
'../app/lib/discourse_automation/scripts/flag_post_on_words',
'../app/lib/discourse_automation/scripts/zapier_webhook',
].each { |path| require File.expand_path(path, __FILE__) }

module ::DiscourseAutomation
Expand Down
29 changes: 29 additions & 0 deletions spec/jobs/call_zapier_webhook_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true

require_relative '../discourse_automation_helper'

describe Jobs::DiscourseAutomationCallZapierWebhook do
before do
SiteSetting.discourse_automation_enabled = true
freeze_time
Jobs::run_immediately!

stub_request(:post, 'https://foo.com/').
with(
body: 'null',
headers: {
'Host' => 'foo.com'
}
).to_return(status: 200, body: '', headers: {})
end

it 'is rate limited' do
RateLimiter.enable

expect do
6.times do
Jobs.enqueue(:discourse_automation_call_zapier_webhook, webhook_url: 'https://foo.com')
end
end.to raise_error(RateLimiter::LimitExceeded)
end
end
45 changes: 45 additions & 0 deletions spec/scripts/zapier_webhook_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# frozen_string_literal: true

require_relative '../discourse_automation_helper'

describe 'ZapierWebhook' do
fab!(:topic) { Fabricate(:topic) }

fab!(:automation) do
Fabricate(
:automation,
script: DiscourseAutomation::Scriptable::ZAPIER_WEBHOOK
)
end

context 'has valid webhook url' do
before do
automation.upsert_field!('webhook_url', 'text', { value: "https://hooks.zapier.com/hooks/catch/foo/bar" })
end

it 'enqueues the zapier call' do
expect {
automation.trigger!
}.to change { Jobs::DiscourseAutomationCallZapierWebhook.jobs.length }.by(1)
end
end

context 'has not valid webhook url' do
before do
@orig_logger = Rails.logger
Rails.logger = @fake_logger = FakeLogger.new
end

after do
Rails.logger = @orig_logger
end

it 'logs an error and do nothing' do
expect {
automation.trigger!
}.to change { Jobs::DiscourseAutomationCallZapierWebhook.jobs.length }.by(0)

expect(Rails.logger.warnings.first).to match(/is not a valid Zapier/)
end
end
end