| @@ -89,6 +89,9 @@ THIRTY_SEVEN_SIGNALS_OAUTH_SECRET= | ||
| 89 | 89 | GITHUB_OAUTH_KEY= | 
| 90 | 90 | GITHUB_OAUTH_SECRET= | 
| 91 | 91 |  | 
| 92 | +TUMBLR_OAUTH_KEY= | |
| 93 | +TUMBLR_OAUTH_SECRET= | |
| 94 | + | |
| 92 | 95 | ############################# | 
| 93 | 96 | # AWS and Mechanical Turk # | 
| 94 | 97 | ############################# | 
| @@ -20,6 +20,10 @@ gem 'twitter', '~> 5.8.0' # Must to be loaded before cantino-twitter-stream. | ||
| 20 | 20 | gem 'cantino-twitter-stream', github: 'cantino/twitter-stream', branch: 'master' | 
| 21 | 21 | gem 'omniauth-twitter' | 
| 22 | 22 |  | 
| 23 | +# Tumblr Agents | |
| 24 | +gem 'tumblr_client' | |
| 25 | +gem 'omniauth-tumblr' | |
| 26 | + | |
| 23 | 27 | # Optional Services. | 
| 24 | 28 | gem 'omniauth-37signals' # BasecampAgent | 
| 25 | 29 | # gem 'omniauth-github' | 
| @@ -214,6 +214,8 @@ GEM | ||
| 214 | 214 | multi_json (~> 1.3) | 
| 215 | 215 | oauth2 (~> 0.9.3) | 
| 216 | 216 | omniauth (~> 1.2) | 
| 217 | + omniauth-tumblr (1.1) | |
| 218 | + omniauth-oauth (~> 1.0) | |
| 217 | 219 | omniauth-twitter (1.0.1) | 
| 218 | 220 | multi_json (~> 1.3) | 
| 219 | 221 | omniauth-oauth (~> 1.0) | 
| @@ -340,6 +342,13 @@ GEM | ||
| 340 | 342 | treetop (1.4.15) | 
| 341 | 343 | polyglot | 
| 342 | 344 | polyglot (>= 0.3.1) | 
| 345 | + tumblr_client (0.8.4) | |
| 346 | + faraday (~> 0.9.0) | |
| 347 | + faraday_middleware (~> 0.9.0) | |
| 348 | + json | |
| 349 | + mime-types | |
| 350 | + oauth | |
| 351 | + simple_oauth | |
| 343 | 352 | twilio-ruby (3.11.6) | 
| 344 | 353 | builder (>= 2.1.2) | 
| 345 | 354 | jwt (>= 0.1.2) | 
| @@ -431,6 +440,7 @@ DEPENDENCIES | ||
| 431 | 440 | nokogiri (~> 1.6.1) | 
| 432 | 441 | omniauth | 
| 433 | 442 | omniauth-37signals | 
| 443 | + omniauth-tumblr | |
| 434 | 444 | omniauth-twitter | 
| 435 | 445 | pg | 
| 436 | 446 | protected_attributes (~> 1.0.8) | 
| @@ -454,6 +464,7 @@ DEPENDENCIES | ||
| 454 | 464 | spring | 
| 455 | 465 | spring-commands-rspec | 
| 456 | 466 | therubyracer (~> 0.12.1) | 
| 467 | + tumblr_client | |
| 457 | 468 | twilio-ruby (~> 3.11.5) | 
| 458 | 469 | twitter (~> 5.8.0) | 
| 459 | 470 | typhoeus (~> 0.6.3) | 
| @@ -0,0 +1,36 @@ | ||
| 1 | +module TumblrConcern | |
| 2 | + extend ActiveSupport::Concern | |
| 3 | + | |
| 4 | + included do | |
| 5 | + include Oauthable | |
| 6 | + | |
| 7 | + valid_oauth_providers :tumblr | |
| 8 | + end | |
| 9 | + | |
| 10 | + def tumblr_consumer_key | |
| 11 | + ENV['TUMBLR_OAUTH_KEY'] | |
| 12 | + end | |
| 13 | + | |
| 14 | + def tumblr_consumer_secret | |
| 15 | + ENV['TUMBLR_OAUTH_SECRET'] | |
| 16 | + end | |
| 17 | + | |
| 18 | + def tumblr_oauth_token | |
| 19 | + service.token | |
| 20 | + end | |
| 21 | + | |
| 22 | + def tumblr_oauth_token_secret | |
| 23 | + service.secret | |
| 24 | + end | |
| 25 | + | |
| 26 | + def tumblr | |
| 27 | + Tumblr.configure do |config| | |
| 28 | + config.consumer_key = tumblr_consumer_key | |
| 29 | + config.consumer_secret = tumblr_consumer_secret | |
| 30 | + config.oauth_token = tumblr_oauth_token | |
| 31 | + config.oauth_token_secret = tumblr_oauth_token_secret | |
| 32 | + end | |
| 33 | + | |
| 34 | + Tumblr::Client.new | |
| 35 | + end | |
| 36 | +end | 
| @@ -0,0 +1,163 @@ | ||
| 1 | +require "tumblr_client" | |
| 2 | + | |
| 3 | +module Agents | |
| 4 | + class TumblrPublishAgent < Agent | |
| 5 | + include TumblrConcern | |
| 6 | + | |
| 7 | + cannot_be_scheduled! | |
| 8 | + | |
| 9 | + description <<-MD | |
| 10 | +      #{'## Include `tumblr_client` and `omniauth-tumblr` in your Gemfile to use this Agent!' if dependencies_missing?} | |
| 11 | + | |
| 12 | + The TumblrPublishAgent publishes Tumblr posts from the events it receives. | |
| 13 | + | |
| 14 | + To be able to use this Agent you need to authenticate with Tumblr in the [Services](/services) section first. | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + **Required fields:** | |
| 19 | + | |
| 20 | + `blog_name` Your Tumblr URL (e.g. "mustardhamsters.tumblr.com") | |
| 21 | + | |
| 22 | + `post_type` One of [text, photo, quote, link, chat, audio, video] | |
| 23 | + | |
| 24 | + | |
| 25 | + ------------- | |
| 26 | + | |
| 27 | + You may leave any of the following optional fields blank. Including a field not allowed for the specified `post_type` will cause a failure. | |
| 28 | + | |
| 29 | + **Any post type** | |
| 30 | + | |
| 31 | + * `state` published, draft, queue, private | |
| 32 | + * `tags` Comma-separated tags for this post | |
| 33 | + * `tweet` off, text for tweet | |
| 34 | + * `date` GMT date and time of the post as a string | |
| 35 | + * `format` html, markdown | |
| 36 | + * `slug` short text summary at end of the post URL | |
| 37 | + | |
| 38 | + **Text** `title` `body` | |
| 39 | + | |
| 40 | + **Photo** `caption` `link` `source` | |
| 41 | + | |
| 42 | + **Quote** `quote` `source` | |
| 43 | + | |
| 44 | + **Link** `title` `url` `description` | |
| 45 | + | |
| 46 | + **Chat** `title` `conversation` | |
| 47 | + | |
| 48 | + **Audio** `caption` `external_url` | |
| 49 | + | |
| 50 | + **Video** `caption` `embed` | |
| 51 | + | |
| 52 | + | |
| 53 | + ------------- | |
| 54 | + | |
| 55 | + [Full information on field options](https://www.tumblr.com/docs/en/api/v2#posting) | |
| 56 | + | |
| 57 | + Set `expected_update_period_in_days` to the maximum amount of time that you'd expect to pass between Events being created by this Agent. | |
| 58 | + MD | |
| 59 | + | |
| 60 | +    gem_dependency_check { defined?(Tumblr) } | |
| 61 | + | |
| 62 | + def validate_options | |
| 63 | + errors.add(:base, "expected_update_period_in_days is required") unless options['expected_update_period_in_days'].present? | |
| 64 | + end | |
| 65 | + | |
| 66 | + def working? | |
| 67 | + event_created_within?(interpolated['expected_update_period_in_days']) && most_recent_event && most_recent_event.payload['success'] == true && !recent_error_logs? | |
| 68 | + end | |
| 69 | + | |
| 70 | + def default_options | |
| 71 | +      { | |
| 72 | + 'expected_update_period_in_days' => "10", | |
| 73 | +        'blog_name' => "{{blog_name}}", | |
| 74 | +        'post_type' => "{{post_type}}", | |
| 75 | +        'options' => { | |
| 76 | +          'state' => "{{state}}", | |
| 77 | +          'tags' => "{{tags}}", | |
| 78 | +          'tweet' => "{{tweet}}", | |
| 79 | +          'date' => "{{date}}", | |
| 80 | +          'format' => "{{format}}", | |
| 81 | +          'slug' => "{{slug}}", | |
| 82 | +          'title' => "{{title}}", | |
| 83 | +          'body' => "{{body}}", | |
| 84 | +          'caption' => "{{caption}}", | |
| 85 | +          'link' => "{{link}}", | |
| 86 | +          'source' => "{{source}}", | |
| 87 | +          'quote' => "{{quote}}", | |
| 88 | +          'url' => "{{url}}", | |
| 89 | +          'description' => "{{description}}", | |
| 90 | +          'conversation' => "{{conversation}}", | |
| 91 | +          'external_url' => "{{external_url}}", | |
| 92 | +          'embed' => "{{embed}}", | |
| 93 | + }, | |
| 94 | + } | |
| 95 | + end | |
| 96 | + | |
| 97 | + def receive(incoming_events) | |
| 98 | + # if there are too many, dump a bunch to avoid getting rate limited | |
| 99 | + if incoming_events.count > 20 | |
| 100 | + incoming_events = incoming_events.first(20) | |
| 101 | + end | |
| 102 | + incoming_events.each do |event| | |
| 103 | + blog_name = interpolated(event)['blog_name'] | |
| 104 | + post_type = interpolated(event)['post_type'] | |
| 105 | + options = interpolated(event)['options'] | |
| 106 | + begin | |
| 107 | + post = publish_post(blog_name, post_type, options) | |
| 108 | +          create_event :payload => { | |
| 109 | + 'success' => true, | |
| 110 | + 'published_post' => "["+blog_name+"] "+post_type, | |
| 111 | + 'post_id' => post["id"], | |
| 112 | + 'agent_id' => event.agent_id, | |
| 113 | + 'event_id' => event.id | |
| 114 | + } | |
| 115 | + end | |
| 116 | + end | |
| 117 | + end | |
| 118 | + | |
| 119 | + def publish_post(blog_name, post_type, options) | |
| 120 | +      options_obj = {  | |
| 121 | + :state => options['state'], | |
| 122 | + :tags => options['tags'], | |
| 123 | + :tweet => options['tweet'], | |
| 124 | + :date => options['date'], | |
| 125 | + :format => options['format'], | |
| 126 | + :slug => options['slug'], | |
| 127 | + } | |
| 128 | + | |
| 129 | + case post_type | |
| 130 | + when "text" | |
| 131 | + options_obj[:title] = options['title'] | |
| 132 | + options_obj[:body] = options['body'] | |
| 133 | + tumblr.text(blog_name, options_obj) | |
| 134 | + when "photo" | |
| 135 | + options_obj[:caption] = options['caption'] | |
| 136 | + options_obj[:link] = options['link'] | |
| 137 | + options_obj[:source] = options['source'] | |
| 138 | + tumblr.photo(blog_name, options_obj) | |
| 139 | + when "quote" | |
| 140 | + options_obj[:quote] = options['quote'] | |
| 141 | + options_obj[:source] = options['source'] | |
| 142 | + tumblr.quote(blog_name, options_obj) | |
| 143 | + when "link" | |
| 144 | + options_obj[:title] = options['title'] | |
| 145 | + options_obj[:url] = options['url'] | |
| 146 | + options_obj[:description] = options['description'] | |
| 147 | + tumblr.link(blog_name, options_obj) | |
| 148 | + when "chat" | |
| 149 | + options_obj[:title] = options['title'] | |
| 150 | + options_obj[:conversation] = options['conversation'] | |
| 151 | + tumblr.chat(blog_name, options_obj) | |
| 152 | + when "audio" | |
| 153 | + options_obj[:caption] = options['caption'] | |
| 154 | + options_obj[:external_url] = options['external_url'] | |
| 155 | + tumblr.audio(blog_name, options_obj) | |
| 156 | + when "video" | |
| 157 | + options_obj[:caption] = options['caption'] | |
| 158 | + options_obj[:embed] = options['embed'] | |
| 159 | + tumblr.video(blog_name, options_obj) | |
| 160 | + end | |
| 161 | + end | |
| 162 | + end | |
| 163 | +end | 
| @@ -0,0 +1,43 @@ | ||
| 1 | +OMNIAUTH_PROVIDERS = {}.tap { |providers| | |
| 2 | + if defined?(OmniAuth::Strategies::Twitter) && | |
| 3 | + (key = ENV["TWITTER_OAUTH_KEY"]).present? && | |
| 4 | + (secret = ENV["TWITTER_OAUTH_SECRET"]).present? | |
| 5 | +    providers['twitter'] = { | |
| 6 | +      omniauth_params: [key, secret, authorize_params: {force_login: 'true', use_authorize: 'true'}] | |
| 7 | + } | |
| 8 | + end | |
| 9 | + | |
| 10 | + if defined?(OmniAuth::Strategies::ThirtySevenSignals) && | |
| 11 | + (key = ENV["THIRTY_SEVEN_SIGNALS_OAUTH_KEY"]).present? && | |
| 12 | + (secret = ENV["THIRTY_SEVEN_SIGNALS_OAUTH_SECRET"]).present? | |
| 13 | +    providers['37signals'] = { | |
| 14 | + omniauth_params: [key, secret] | |
| 15 | + } | |
| 16 | + end | |
| 17 | + | |
| 18 | + if defined?(OmniAuth::Strategies::GitHub) && | |
| 19 | + (key = ENV["GITHUB_OAUTH_KEY"]).present? && | |
| 20 | + (secret = ENV["GITHUB_OAUTH_SECRET"]).present? | |
| 21 | +    providers['github'] = { | |
| 22 | + omniauth_params: [key, secret] | |
| 23 | + } | |
| 24 | + end | |
| 25 | + | |
| 26 | + if defined?(OmniAuth::Strategies::Tumblr) && | |
| 27 | + (key = ENV["TUMBLR_OAUTH_KEY"]).present? && | |
| 28 | + (secret = ENV["TUMBLR_OAUTH_SECRET"]).present? | |
| 29 | +    providers['tumblr'] = { | |
| 30 | + omniauth_params: [key, secret] | |
| 31 | + } | |
| 32 | + end | |
| 33 | +} | |
| 34 | + | |
| 35 | +def has_oauth_configuration_for?(provider) | |
| 36 | + OMNIAUTH_PROVIDERS.key?(provider.to_s) | |
| 37 | +end | |
| 38 | + | |
| 39 | +Rails.application.config.middleware.use OmniAuth::Builder do | |
| 40 | +  OMNIAUTH_PROVIDERS.each { |name, config| | |
| 41 | + provider name, *config[:omniauth_params] | |
| 42 | + } | |
| 43 | +end | 
| @@ -11,14 +11,11 @@ | ||
| 11 | 11 | # | 
| 12 | 12 | # It's strongly recommended that you check this file into your version control system. | 
| 13 | 13 |  | 
| 14 | -ActiveRecord::Schema.define(version: 20140901143732) do | |
| 15 | - | |
| 16 | - # These are extensions that must be enabled in order to support this database | |
| 17 | - enable_extension "plpgsql" | |
| 14 | +ActiveRecord::Schema.define(version: 20140906030139) do | |
| 18 | 15 |  | 
| 19 | 16 | create_table "agent_logs", force: true do |t| | 
| 20 | 17 | t.integer "agent_id", null: false | 
| 21 | - t.text "message", limit: 16777215, null: false, charset: "utf8mb4", collation: "utf8mb4_bin" | |
| 18 | + t.text "message", null: false, charset: "utf8mb4", collation: "utf8mb4_bin" | |
| 22 | 19 | t.integer "level", default: 3, null: false | 
| 23 | 20 | t.integer "inbound_event_id" | 
| 24 | 21 | t.integer "outbound_event_id" | 
| @@ -28,7 +25,7 @@ ActiveRecord::Schema.define(version: 20140901143732) do | ||
| 28 | 25 |  | 
| 29 | 26 | create_table "agents", force: true do |t| | 
| 30 | 27 | t.integer "user_id" | 
| 31 | - t.text "options", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin" | |
| 28 | + t.text "options", charset: "utf8mb4", collation: "utf8mb4_bin" | |
| 32 | 29 | t.string "type", collation: "utf8_bin" | 
| 33 | 30 | t.string "name", charset: "utf8mb4", collation: "utf8mb4_bin" | 
| 34 | 31 | t.string "schedule", collation: "utf8_bin" | 
| @@ -36,17 +33,17 @@ ActiveRecord::Schema.define(version: 20140901143732) do | ||
| 36 | 33 | t.datetime "last_check_at" | 
| 37 | 34 | t.datetime "last_receive_at" | 
| 38 | 35 | t.integer "last_checked_event_id" | 
| 39 | - t.datetime "created_at", null: false | |
| 40 | - t.datetime "updated_at", null: false | |
| 36 | + t.datetime "created_at" | |
| 37 | + t.datetime "updated_at" | |
| 41 | 38 | t.text "memory", limit: 2147483647, charset: "utf8mb4", collation: "utf8mb4_bin" | 
| 42 | 39 | t.datetime "last_web_request_at" | 
| 43 | 40 | t.integer "keep_events_for", default: 0, null: false | 
| 44 | 41 | t.datetime "last_event_at" | 
| 45 | 42 | t.datetime "last_error_log_at" | 
| 46 | - t.boolean "propagate_immediately", default: false, null: false | |
| 47 | - t.boolean "disabled", default: false, null: false | |
| 48 | - t.string "guid", null: false, charset: "ascii", collation: "ascii_bin" | |
| 43 | + t.boolean "propagate_immediately", default: false, null: false | |
| 44 | + t.boolean "disabled", default: false, null: false | |
| 49 | 45 | t.integer "service_id" | 
| 46 | + t.string "guid", null: false | |
| 50 | 47 | end | 
| 51 | 48 |  | 
| 52 | 49 | add_index "agents", ["guid"], name: "index_agents_on_guid", using: :btree | 
| @@ -67,8 +64,8 @@ ActiveRecord::Schema.define(version: 20140901143732) do | ||
| 67 | 64 | create_table "delayed_jobs", force: true do |t| | 
| 68 | 65 | t.integer "priority", default: 0 | 
| 69 | 66 | t.integer "attempts", default: 0 | 
| 70 | - t.text "handler", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin" | |
| 71 | - t.text "last_error", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin" | |
| 67 | + t.text "handler", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin" | |
| 68 | + t.text "last_error", charset: "utf8mb4", collation: "utf8mb4_bin" | |
| 72 | 69 | t.datetime "run_at" | 
| 73 | 70 | t.datetime "locked_at" | 
| 74 | 71 | t.datetime "failed_at" | 
| @@ -83,11 +80,11 @@ ActiveRecord::Schema.define(version: 20140901143732) do | ||
| 83 | 80 | create_table "events", force: true do |t| | 
| 84 | 81 | t.integer "user_id" | 
| 85 | 82 | t.integer "agent_id" | 
| 86 | - t.decimal "lat", precision: 15, scale: 10 | |
| 87 | - t.decimal "lng", precision: 15, scale: 10 | |
| 88 | - t.text "payload", limit: 2147483647, charset: "utf8mb4", collation: "utf8mb4_bin" | |
| 89 | - t.datetime "created_at", null: false | |
| 90 | - t.datetime "updated_at", null: false | |
| 83 | + t.decimal "lat", precision: 15, scale: 10 | |
| 84 | + t.decimal "lng", precision: 15, scale: 10 | |
| 85 | + t.text "payload", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin" | |
| 86 | + t.datetime "created_at" | |
| 87 | + t.datetime "updated_at" | |
| 91 | 88 | t.datetime "expires_at" | 
| 92 | 89 | end | 
| 93 | 90 |  | 
| @@ -117,13 +114,13 @@ ActiveRecord::Schema.define(version: 20140901143732) do | ||
| 117 | 114 | add_index "scenario_memberships", ["scenario_id"], name: "index_scenario_memberships_on_scenario_id", using: :btree | 
| 118 | 115 |  | 
| 119 | 116 | create_table "scenarios", force: true do |t| | 
| 120 | - t.string "name", null: false, charset: "utf8mb4", collation: "utf8mb4_bin" | |
| 121 | - t.integer "user_id", null: false | |
| 117 | + t.string "name", null: false, charset: "utf8mb4", collation: "utf8mb4_bin" | |
| 118 | + t.integer "user_id", null: false | |
| 122 | 119 | t.datetime "created_at" | 
| 123 | 120 | t.datetime "updated_at" | 
| 124 | - t.text "description", charset: "utf8mb4", collation: "utf8mb4_bin" | |
| 125 | - t.boolean "public", default: false, null: false | |
| 126 | - t.string "guid", null: false, charset: "ascii", collation: "ascii_bin" | |
| 121 | + t.text "description", charset: "utf8mb4", collation: "utf8mb4_bin" | |
| 122 | + t.boolean "public", default: false, null: false | |
| 123 | + t.string "guid", null: false, charset: "ascii", collation: "ascii_bin" | |
| 127 | 124 | t.string "source_url" | 
| 128 | 125 | t.string "tag_bg_color" | 
| 129 | 126 | t.string "tag_fg_color" | 
| @@ -154,8 +151,8 @@ ActiveRecord::Schema.define(version: 20140901143732) do | ||
| 154 | 151 | t.integer "user_id", null: false | 
| 155 | 152 | t.string "credential_name", null: false | 
| 156 | 153 | t.text "credential_value", null: false | 
| 157 | - t.datetime "created_at", null: false | |
| 158 | - t.datetime "updated_at", null: false | |
| 154 | + t.datetime "created_at" | |
| 155 | + t.datetime "updated_at" | |
| 159 | 156 | t.string "mode", default: "text", null: false, collation: "utf8_bin" | 
| 160 | 157 | end | 
| 161 | 158 |  | 
| @@ -172,8 +169,8 @@ ActiveRecord::Schema.define(version: 20140901143732) do | ||
| 172 | 169 | t.datetime "last_sign_in_at" | 
| 173 | 170 | t.string "current_sign_in_ip" | 
| 174 | 171 | t.string "last_sign_in_ip" | 
| 175 | - t.datetime "created_at", null: false | |
| 176 | - t.datetime "updated_at", null: false | |
| 172 | + t.datetime "created_at" | |
| 173 | + t.datetime "updated_at" | |
| 177 | 174 | t.boolean "admin", default: false, null: false | 
| 178 | 175 | t.integer "failed_attempts", default: 0 | 
| 179 | 176 | t.string "unlock_token" | 
| @@ -1,6 +1,8 @@ | ||
| 1 | 1 | APP_SECRET_TOKEN=notarealappsecrettoken | 
| 2 | 2 | TWITTER_OAUTH_KEY=twitteroauthkey | 
| 3 | 3 | TWITTER_OAUTH_SECRET=twitteroauthsecret | 
| 4 | +TUMBLR_OAUTH_KEY=tumblroauthsecret | |
| 5 | +TUMBLR_OAUTH_SECRET=tumblroauthsecret | |
| 4 | 6 | THIRTY_SEVEN_SIGNALS_OAUTH_KEY=TESTKEY | 
| 5 | 7 | THIRTY_SEVEN_SIGNALS_OAUTH_SECRET=TESTSECRET | 
| 6 | 8 | FAILED_JOBS_TO_KEEP=2 | 
| @@ -0,0 +1,38 @@ | ||
| 1 | +require 'spec_helper' | |
| 2 | + | |
| 3 | +describe Agents::TumblrPublishAgent do | |
| 4 | + before do | |
| 5 | +    @opts = { | |
| 6 | + :blog_name => "huginnbot.tumblr.com", | |
| 7 | + :post_type => "text", | |
| 8 | + :expected_update_period_in_days => "2", | |
| 9 | +      :options => { | |
| 10 | +        :title => "{{title}}", | |
| 11 | +        :body => "{{body}}", | |
| 12 | + }, | |
| 13 | + } | |
| 14 | + | |
| 15 | + @checker = Agents::TumblrPublishAgent.new(:name => "HuginnBot", :options => @opts) | |
| 16 | + @checker.service = services(:generic) | |
| 17 | + @checker.user = users(:bob) | |
| 18 | + @checker.save! | |
| 19 | + | |
| 20 | + @event = Event.new | |
| 21 | + @event.agent = agents(:bob_weather_agent) | |
| 22 | +    @event.payload = { :title => "Gonna rain...", :body => 'San Francisco is gonna get wet' } | |
| 23 | + @event.save! | |
| 24 | + | |
| 25 | +    stub.any_instance_of(Agents::TumblrPublishAgent).tumblr { | |
| 26 | +      stub!.text(anything, anything) { { "id" => "5" } } | |
| 27 | + } | |
| 28 | + end | |
| 29 | + | |
| 30 | + describe '#receive' do | |
| 31 | + it 'should publish any payload it receives' do | |
| 32 | + Agents::TumblrPublishAgent.async_receive(@checker.id, [@event.id]) | |
| 33 | + @checker.events.count.should eq(1) | |
| 34 | +      @checker.events.first.payload['post_id'].should eq('5') | |
| 35 | +      @checker.events.first.payload['published_post'].should eq('[huginnbot.tumblr.com] text') | |
| 36 | + end | |
| 37 | + end | |
| 38 | +end |