@@ -0,0 +1,92 @@ |
||
1 |
+module Agents |
|
2 |
+ class BasecampAgent < Agent |
|
3 |
+ cannot_receive_events! |
|
4 |
+ |
|
5 |
+ description <<-MD |
|
6 |
+ The BasecampAgent checks a Basecamp project for new Events |
|
7 |
+ |
|
8 |
+ It is required that you enter your Basecamp credentials (`username` and `password`). |
|
9 |
+ |
|
10 |
+ You also need to provide your Basecamp `user_id` and the `project_id` of the project you want to monitor. |
|
11 |
+ If you have your Basecamp project opened in your browser you can find the user_id and project_id as follows: |
|
12 |
+ |
|
13 |
+ `https://basecamp.com/` |
|
14 |
+ user_id |
|
15 |
+ `/projects/` |
|
16 |
+ project_id |
|
17 |
+ `-explore-basecamp` |
|
18 |
+ MD |
|
19 |
+ |
|
20 |
+ event_description <<-MD |
|
21 |
+ Events are the raw JSON provided by the Basecamp API. Should look something like: |
|
22 |
+ |
|
23 |
+ { |
|
24 |
+ "creator": { |
|
25 |
+ "fullsize_avatar_url": "https://dge9rmgqjs8m1.cloudfront.net/global/dfsdfsdfdsf/original.gif?r=3", |
|
26 |
+ "avatar_url": "http://dge9rmgqjs8m1.cloudfront.net/global/dfsdfsdfdsf/avatar.gif?r=3", |
|
27 |
+ "name": "Dominik Sander", |
|
28 |
+ "id": 123456 |
|
29 |
+ }, |
|
30 |
+ "attachments": [], |
|
31 |
+ "raw_excerpt": "test test", |
|
32 |
+ "excerpt": "test test", |
|
33 |
+ "id": 6454342343, |
|
34 |
+ "created_at": "2014-04-17T10:25:31.000+02:00", |
|
35 |
+ "updated_at": "2014-04-17T10:25:31.000+02:00", |
|
36 |
+ "summary": "commented on whaat", |
|
37 |
+ "action": "commented on", |
|
38 |
+ "target": "whaat", |
|
39 |
+ "url": "https://basecamp.com/12456/api/v1/projects/76454545-explore-basecamp/messages/76454545-whaat.json", |
|
40 |
+ "html_url": "https://basecamp.com/12456/projects/76454545-explore-basecamp/messages/76454545-whaat#comment_76454545" |
|
41 |
+ } |
|
42 |
+ MD |
|
43 |
+ |
|
44 |
+ default_schedule "every_10m" |
|
45 |
+ |
|
46 |
+ def default_options |
|
47 |
+ { |
|
48 |
+ 'username' => '', |
|
49 |
+ 'password' => '', |
|
50 |
+ 'user_id' => '', |
|
51 |
+ 'project_id' => '', |
|
52 |
+ } |
|
53 |
+ end |
|
54 |
+ |
|
55 |
+ def validate_options |
|
56 |
+ errors.add(:base, "you need to specify your basecamp username") unless options['username'].present? |
|
57 |
+ errors.add(:base, "you need to specify your basecamp password") unless options['password'].present? |
|
58 |
+ errors.add(:base, "you need to specify your basecamp user id") unless options['user_id'].present? |
|
59 |
+ errors.add(:base, "you need to specify the basecamp project id of which you want to receive events") unless options['project_id'].present? |
|
60 |
+ end |
|
61 |
+ |
|
62 |
+ def working? |
|
63 |
+ (events_count.present? && events_count > 0) |
|
64 |
+ end |
|
65 |
+ |
|
66 |
+ def check |
|
67 |
+ log "Requesting events from #{request_url}" |
|
68 |
+ reponse = HTTParty.get request_url, auth_options.merge(:headers => {"User-Agent" => "Huginn (https://github.com/cantino/huginn)"}) |
|
69 |
+ memory[:last_run] = Time.now.utc.iso8601 |
|
70 |
+ if last_check_at != nil |
|
71 |
+ JSON.parse(reponse.body).each do |event| |
|
72 |
+ create_event :payload => event |
|
73 |
+ end |
|
74 |
+ end |
|
75 |
+ save! |
|
76 |
+ end |
|
77 |
+ |
|
78 |
+ private |
|
79 |
+ def first_run? |
|
80 |
+ memory[:first_run].nil? |
|
81 |
+ end |
|
82 |
+ |
|
83 |
+ def request_url |
|
84 |
+ since = memory[:last_run] ? "?since=#{memory[:last_run]}" : '' |
|
85 |
+ "https://basecamp.com/#{URI.encode(options[:user_id].to_s)}/api/v1/projects/#{URI.encode(options[:project_id].to_s)}/events.json#{since}" |
|
86 |
+ end |
|
87 |
+ |
|
88 |
+ def auth_options |
|
89 |
+ {:basic_auth => {:username =>options[:username], :password=>options[:password]}} |
|
90 |
+ end |
|
91 |
+ end |
|
92 |
+end |
@@ -0,0 +1,21 @@ |
||
1 |
+[ |
|
2 |
+ { |
|
3 |
+ "creator": { |
|
4 |
+ "fullsize_avatar_url": "https://dge9rmgqjs8m1.cloudfront.net/global/dfsdfsdfdsf/original.gif?r=3", |
|
5 |
+ "avatar_url": "http://dge9rmgqjs8m1.cloudfront.net/global/dfsdfsdfdsf/avatar.gif?r=3", |
|
6 |
+ "name": "Dominik Sander", |
|
7 |
+ "id": 123456 |
|
8 |
+ }, |
|
9 |
+ "attachments": [], |
|
10 |
+ "raw_excerpt": "test test", |
|
11 |
+ "excerpt": "test test", |
|
12 |
+ "id": 6454342343, |
|
13 |
+ "created_at": "2014-04-17T10:25:31.000+02:00", |
|
14 |
+ "updated_at": "2014-04-17T10:25:31.000+02:00", |
|
15 |
+ "summary": "commented on whaat", |
|
16 |
+ "action": "commented on", |
|
17 |
+ "target": "whaat", |
|
18 |
+ "url": "https://basecamp.com/12456/api/v1/projects/5476464-explore-basecamp/messages/24598238-whaat.json", |
|
19 |
+ "html_url": "https://basecamp.com/12456/projects/5476464-explore-basecamp/messages/24598238-whaat#comment_150756301" |
|
20 |
+ } |
|
21 |
+] |
@@ -0,0 +1,80 @@ |
||
1 |
+require 'spec_helper' |
|
2 |
+ |
|
3 |
+describe Agents::BasecampAgent do |
|
4 |
+ before(:each) do |
|
5 |
+ stub_request(:get, /json$/).to_return(:body => File.read(Rails.root.join("spec/data_fixtures/basecamp.json")), :status => 200, :headers => {"Content-Type" => "text/json"}) |
|
6 |
+ stub_request(:get, /Z$/).to_return(:body => File.read(Rails.root.join("spec/data_fixtures/basecamp.json")), :status => 200, :headers => {"Content-Type" => "text/json"}) |
|
7 |
+ @valid_params = { |
|
8 |
+ :username => "user", |
|
9 |
+ :password => "pass", |
|
10 |
+ :user_id => 12345, |
|
11 |
+ :project_id => 6789, |
|
12 |
+ } |
|
13 |
+ |
|
14 |
+ @checker = Agents::BasecampAgent.new(:name => "somename", :options => @valid_params) |
|
15 |
+ @checker.user = users(:jane) |
|
16 |
+ @checker.save! |
|
17 |
+ end |
|
18 |
+ |
|
19 |
+ describe "validating" do |
|
20 |
+ before do |
|
21 |
+ @checker.should be_valid |
|
22 |
+ end |
|
23 |
+ |
|
24 |
+ it "should require the basecamp username" do |
|
25 |
+ @checker.options['username'] = nil |
|
26 |
+ @checker.should_not be_valid |
|
27 |
+ end |
|
28 |
+ |
|
29 |
+ it "should require the basecamp password" do |
|
30 |
+ @checker.options['password'] = nil |
|
31 |
+ @checker.should_not be_valid |
|
32 |
+ end |
|
33 |
+ |
|
34 |
+ it "should require the basecamp user_id" do |
|
35 |
+ @checker.options['user_id'] = nil |
|
36 |
+ @checker.should_not be_valid |
|
37 |
+ end |
|
38 |
+ |
|
39 |
+ it "should require the basecamp project_id" do |
|
40 |
+ @checker.options['project_id'] = nil |
|
41 |
+ @checker.should_not be_valid |
|
42 |
+ end |
|
43 |
+ |
|
44 |
+ end |
|
45 |
+ |
|
46 |
+ describe "helpers" do |
|
47 |
+ it "should generate a correct auth hash" do |
|
48 |
+ @checker.send(:auth_options).should == {:basic_auth=>{:username=>"user", :password=>"pass"}} |
|
49 |
+ end |
|
50 |
+ |
|
51 |
+ it "should not provide the since attribute on first run" do |
|
52 |
+ @checker.send(:request_url).should == "https://basecamp.com/12345/api/v1/projects/6789/events.json" |
|
53 |
+ end |
|
54 |
+ |
|
55 |
+ it "should provide the since attribute after the first run" do |
|
56 |
+ time = (Time.now-1.minute).iso8601 |
|
57 |
+ @checker.memory[:last_run] = time |
|
58 |
+ @checker.save |
|
59 |
+ @checker.reload.send(:request_url).should == "https://basecamp.com/12345/api/v1/projects/6789/events.json?since=#{time}" |
|
60 |
+ end |
|
61 |
+ end |
|
62 |
+ describe "#check" do |
|
63 |
+ it "should not emit events on its first run" do |
|
64 |
+ expect { @checker.check }.to change { Event.count }.by(0) |
|
65 |
+ end |
|
66 |
+ it "should check that initial run creates an event" do |
|
67 |
+ @checker.last_check_at = Time.now - 1.minute |
|
68 |
+ expect { @checker.check }.to change { Event.count }.by(1) |
|
69 |
+ end |
|
70 |
+ end |
|
71 |
+ |
|
72 |
+ describe "#working?" do |
|
73 |
+ it "it is working when at least one event was emited" do |
|
74 |
+ @checker.should_not be_working |
|
75 |
+ @checker.last_check_at = Time.now - 1.minute |
|
76 |
+ @checker.check |
|
77 |
+ @checker.reload.should be_working |
|
78 |
+ end |
|
79 |
+ end |
|
80 |
+end |