mirror of
https://github.com/Fishwaldo/huginn.git
synced 2025-03-15 19:31:26 +00:00
Merge branch 'master' of github.com:mustardhamsters/huginn
This commit is contained in:
commit
f92e848fa4
9 changed files with 324 additions and 27 deletions
|
@ -89,6 +89,9 @@ THIRTY_SEVEN_SIGNALS_OAUTH_SECRET=
|
|||
GITHUB_OAUTH_KEY=
|
||||
GITHUB_OAUTH_SECRET=
|
||||
|
||||
TUMBLR_OAUTH_KEY=
|
||||
TUMBLR_OAUTH_SECRET=
|
||||
|
||||
#############################
|
||||
# AWS and Mechanical Turk #
|
||||
#############################
|
||||
|
|
4
Gemfile
4
Gemfile
|
@ -20,6 +20,10 @@ gem 'twitter', '~> 5.8.0' # Must to be loaded before cantino-twitter-stream.
|
|||
gem 'cantino-twitter-stream', github: 'cantino/twitter-stream', branch: 'master'
|
||||
gem 'omniauth-twitter'
|
||||
|
||||
# Tumblr Agents
|
||||
gem 'tumblr_client'
|
||||
gem 'omniauth-tumblr'
|
||||
|
||||
# Optional Services.
|
||||
gem 'omniauth-37signals' # BasecampAgent
|
||||
# gem 'omniauth-github'
|
||||
|
|
11
Gemfile.lock
11
Gemfile.lock
|
@ -214,6 +214,8 @@ GEM
|
|||
multi_json (~> 1.3)
|
||||
oauth2 (~> 0.9.3)
|
||||
omniauth (~> 1.2)
|
||||
omniauth-tumblr (1.1)
|
||||
omniauth-oauth (~> 1.0)
|
||||
omniauth-twitter (1.0.1)
|
||||
multi_json (~> 1.3)
|
||||
omniauth-oauth (~> 1.0)
|
||||
|
@ -340,6 +342,13 @@ GEM
|
|||
treetop (1.4.15)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
tumblr_client (0.8.4)
|
||||
faraday (~> 0.9.0)
|
||||
faraday_middleware (~> 0.9.0)
|
||||
json
|
||||
mime-types
|
||||
oauth
|
||||
simple_oauth
|
||||
twilio-ruby (3.11.6)
|
||||
builder (>= 2.1.2)
|
||||
jwt (>= 0.1.2)
|
||||
|
@ -431,6 +440,7 @@ DEPENDENCIES
|
|||
nokogiri (~> 1.6.1)
|
||||
omniauth
|
||||
omniauth-37signals
|
||||
omniauth-tumblr
|
||||
omniauth-twitter
|
||||
pg
|
||||
protected_attributes (~> 1.0.8)
|
||||
|
@ -454,6 +464,7 @@ DEPENDENCIES
|
|||
spring
|
||||
spring-commands-rspec
|
||||
therubyracer (~> 0.12.1)
|
||||
tumblr_client
|
||||
twilio-ruby (~> 3.11.5)
|
||||
twitter (~> 5.8.0)
|
||||
typhoeus (~> 0.6.3)
|
||||
|
|
36
app/concerns/tumblr_concern.rb
Normal file
36
app/concerns/tumblr_concern.rb
Normal file
|
@ -0,0 +1,36 @@
|
|||
module TumblrConcern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
include Oauthable
|
||||
|
||||
valid_oauth_providers :tumblr
|
||||
end
|
||||
|
||||
def tumblr_consumer_key
|
||||
ENV['TUMBLR_OAUTH_KEY']
|
||||
end
|
||||
|
||||
def tumblr_consumer_secret
|
||||
ENV['TUMBLR_OAUTH_SECRET']
|
||||
end
|
||||
|
||||
def tumblr_oauth_token
|
||||
service.token
|
||||
end
|
||||
|
||||
def tumblr_oauth_token_secret
|
||||
service.secret
|
||||
end
|
||||
|
||||
def tumblr
|
||||
Tumblr.configure do |config|
|
||||
config.consumer_key = tumblr_consumer_key
|
||||
config.consumer_secret = tumblr_consumer_secret
|
||||
config.oauth_token = tumblr_oauth_token
|
||||
config.oauth_token_secret = tumblr_oauth_token_secret
|
||||
end
|
||||
|
||||
Tumblr::Client.new
|
||||
end
|
||||
end
|
163
app/models/agents/tumblr_publish_agent.rb
Normal file
163
app/models/agents/tumblr_publish_agent.rb
Normal file
|
@ -0,0 +1,163 @@
|
|||
require "tumblr_client"
|
||||
|
||||
module Agents
|
||||
class TumblrPublishAgent < Agent
|
||||
include TumblrConcern
|
||||
|
||||
cannot_be_scheduled!
|
||||
|
||||
description <<-MD
|
||||
#{'## Include `tumblr_client` and `omniauth-tumblr` in your Gemfile to use this Agent!' if dependencies_missing?}
|
||||
|
||||
The TumblrPublishAgent publishes Tumblr posts from the events it receives.
|
||||
|
||||
To be able to use this Agent you need to authenticate with Tumblr in the [Services](/services) section first.
|
||||
|
||||
|
||||
|
||||
**Required fields:**
|
||||
|
||||
`blog_name` Your Tumblr URL (e.g. "mustardhamsters.tumblr.com")
|
||||
|
||||
`post_type` One of [text, photo, quote, link, chat, audio, video]
|
||||
|
||||
|
||||
-------------
|
||||
|
||||
You may leave any of the following optional fields blank. Including a field not allowed for the specified `post_type` will cause a failure.
|
||||
|
||||
**Any post type**
|
||||
|
||||
* `state` published, draft, queue, private
|
||||
* `tags` Comma-separated tags for this post
|
||||
* `tweet` off, text for tweet
|
||||
* `date` GMT date and time of the post as a string
|
||||
* `format` html, markdown
|
||||
* `slug` short text summary at end of the post URL
|
||||
|
||||
**Text** `title` `body`
|
||||
|
||||
**Photo** `caption` `link` `source`
|
||||
|
||||
**Quote** `quote` `source`
|
||||
|
||||
**Link** `title` `url` `description`
|
||||
|
||||
**Chat** `title` `conversation`
|
||||
|
||||
**Audio** `caption` `external_url`
|
||||
|
||||
**Video** `caption` `embed`
|
||||
|
||||
|
||||
-------------
|
||||
|
||||
[Full information on field options](https://www.tumblr.com/docs/en/api/v2#posting)
|
||||
|
||||
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.
|
||||
MD
|
||||
|
||||
gem_dependency_check { defined?(Tumblr) }
|
||||
|
||||
def validate_options
|
||||
errors.add(:base, "expected_update_period_in_days is required") unless options['expected_update_period_in_days'].present?
|
||||
end
|
||||
|
||||
def working?
|
||||
event_created_within?(interpolated['expected_update_period_in_days']) && most_recent_event && most_recent_event.payload['success'] == true && !recent_error_logs?
|
||||
end
|
||||
|
||||
def default_options
|
||||
{
|
||||
'expected_update_period_in_days' => "10",
|
||||
'blog_name' => "{{blog_name}}",
|
||||
'post_type' => "{{post_type}}",
|
||||
'options' => {
|
||||
'state' => "{{state}}",
|
||||
'tags' => "{{tags}}",
|
||||
'tweet' => "{{tweet}}",
|
||||
'date' => "{{date}}",
|
||||
'format' => "{{format}}",
|
||||
'slug' => "{{slug}}",
|
||||
'title' => "{{title}}",
|
||||
'body' => "{{body}}",
|
||||
'caption' => "{{caption}}",
|
||||
'link' => "{{link}}",
|
||||
'source' => "{{source}}",
|
||||
'quote' => "{{quote}}",
|
||||
'url' => "{{url}}",
|
||||
'description' => "{{description}}",
|
||||
'conversation' => "{{conversation}}",
|
||||
'external_url' => "{{external_url}}",
|
||||
'embed' => "{{embed}}",
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
def receive(incoming_events)
|
||||
# if there are too many, dump a bunch to avoid getting rate limited
|
||||
if incoming_events.count > 20
|
||||
incoming_events = incoming_events.first(20)
|
||||
end
|
||||
incoming_events.each do |event|
|
||||
blog_name = interpolated(event)['blog_name']
|
||||
post_type = interpolated(event)['post_type']
|
||||
options = interpolated(event)['options']
|
||||
begin
|
||||
post = publish_post(blog_name, post_type, options)
|
||||
create_event :payload => {
|
||||
'success' => true,
|
||||
'published_post' => "["+blog_name+"] "+post_type,
|
||||
'post_id' => post["id"],
|
||||
'agent_id' => event.agent_id,
|
||||
'event_id' => event.id
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def publish_post(blog_name, post_type, options)
|
||||
options_obj = {
|
||||
:state => options['state'],
|
||||
:tags => options['tags'],
|
||||
:tweet => options['tweet'],
|
||||
:date => options['date'],
|
||||
:format => options['format'],
|
||||
:slug => options['slug'],
|
||||
}
|
||||
|
||||
case post_type
|
||||
when "text"
|
||||
options_obj[:title] = options['title']
|
||||
options_obj[:body] = options['body']
|
||||
tumblr.text(blog_name, options_obj)
|
||||
when "photo"
|
||||
options_obj[:caption] = options['caption']
|
||||
options_obj[:link] = options['link']
|
||||
options_obj[:source] = options['source']
|
||||
tumblr.photo(blog_name, options_obj)
|
||||
when "quote"
|
||||
options_obj[:quote] = options['quote']
|
||||
options_obj[:source] = options['source']
|
||||
tumblr.quote(blog_name, options_obj)
|
||||
when "link"
|
||||
options_obj[:title] = options['title']
|
||||
options_obj[:url] = options['url']
|
||||
options_obj[:description] = options['description']
|
||||
tumblr.link(blog_name, options_obj)
|
||||
when "chat"
|
||||
options_obj[:title] = options['title']
|
||||
options_obj[:conversation] = options['conversation']
|
||||
tumblr.chat(blog_name, options_obj)
|
||||
when "audio"
|
||||
options_obj[:caption] = options['caption']
|
||||
options_obj[:external_url] = options['external_url']
|
||||
tumblr.audio(blog_name, options_obj)
|
||||
when "video"
|
||||
options_obj[:caption] = options['caption']
|
||||
options_obj[:embed] = options['embed']
|
||||
tumblr.video(blog_name, options_obj)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
43
config/initializers/omniauth.rb
Normal file
43
config/initializers/omniauth.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
OMNIAUTH_PROVIDERS = {}.tap { |providers|
|
||||
if defined?(OmniAuth::Strategies::Twitter) &&
|
||||
(key = ENV["TWITTER_OAUTH_KEY"]).present? &&
|
||||
(secret = ENV["TWITTER_OAUTH_SECRET"]).present?
|
||||
providers['twitter'] = {
|
||||
omniauth_params: [key, secret, authorize_params: {force_login: 'true', use_authorize: 'true'}]
|
||||
}
|
||||
end
|
||||
|
||||
if defined?(OmniAuth::Strategies::ThirtySevenSignals) &&
|
||||
(key = ENV["THIRTY_SEVEN_SIGNALS_OAUTH_KEY"]).present? &&
|
||||
(secret = ENV["THIRTY_SEVEN_SIGNALS_OAUTH_SECRET"]).present?
|
||||
providers['37signals'] = {
|
||||
omniauth_params: [key, secret]
|
||||
}
|
||||
end
|
||||
|
||||
if defined?(OmniAuth::Strategies::GitHub) &&
|
||||
(key = ENV["GITHUB_OAUTH_KEY"]).present? &&
|
||||
(secret = ENV["GITHUB_OAUTH_SECRET"]).present?
|
||||
providers['github'] = {
|
||||
omniauth_params: [key, secret]
|
||||
}
|
||||
end
|
||||
|
||||
if defined?(OmniAuth::Strategies::Tumblr) &&
|
||||
(key = ENV["TUMBLR_OAUTH_KEY"]).present? &&
|
||||
(secret = ENV["TUMBLR_OAUTH_SECRET"]).present?
|
||||
providers['tumblr'] = {
|
||||
omniauth_params: [key, secret]
|
||||
}
|
||||
end
|
||||
}
|
||||
|
||||
def has_oauth_configuration_for?(provider)
|
||||
OMNIAUTH_PROVIDERS.key?(provider.to_s)
|
||||
end
|
||||
|
||||
Rails.application.config.middleware.use OmniAuth::Builder do
|
||||
OMNIAUTH_PROVIDERS.each { |name, config|
|
||||
provider name, *config[:omniauth_params]
|
||||
}
|
||||
end
|
51
db/schema.rb
51
db/schema.rb
|
@ -11,14 +11,11 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20140901143732) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
ActiveRecord::Schema.define(version: 20140906030139) do
|
||||
|
||||
create_table "agent_logs", force: true do |t|
|
||||
t.integer "agent_id", null: false
|
||||
t.text "message", limit: 16777215, null: false, charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.text "message", null: false, charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.integer "level", default: 3, null: false
|
||||
t.integer "inbound_event_id"
|
||||
t.integer "outbound_event_id"
|
||||
|
@ -28,7 +25,7 @@ ActiveRecord::Schema.define(version: 20140901143732) do
|
|||
|
||||
create_table "agents", force: true do |t|
|
||||
t.integer "user_id"
|
||||
t.text "options", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.text "options", charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.string "type", collation: "utf8_bin"
|
||||
t.string "name", charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.string "schedule", collation: "utf8_bin"
|
||||
|
@ -36,17 +33,17 @@ ActiveRecord::Schema.define(version: 20140901143732) do
|
|||
t.datetime "last_check_at"
|
||||
t.datetime "last_receive_at"
|
||||
t.integer "last_checked_event_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.text "memory", limit: 2147483647, charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.datetime "last_web_request_at"
|
||||
t.integer "keep_events_for", default: 0, null: false
|
||||
t.datetime "last_event_at"
|
||||
t.datetime "last_error_log_at"
|
||||
t.boolean "propagate_immediately", default: false, null: false
|
||||
t.boolean "disabled", default: false, null: false
|
||||
t.string "guid", null: false, charset: "ascii", collation: "ascii_bin"
|
||||
t.boolean "propagate_immediately", default: false, null: false
|
||||
t.boolean "disabled", default: false, null: false
|
||||
t.integer "service_id"
|
||||
t.string "guid", null: false
|
||||
end
|
||||
|
||||
add_index "agents", ["guid"], name: "index_agents_on_guid", using: :btree
|
||||
|
@ -67,8 +64,8 @@ ActiveRecord::Schema.define(version: 20140901143732) do
|
|||
create_table "delayed_jobs", force: true do |t|
|
||||
t.integer "priority", default: 0
|
||||
t.integer "attempts", default: 0
|
||||
t.text "handler", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.text "last_error", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.text "handler", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.text "last_error", charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.datetime "run_at"
|
||||
t.datetime "locked_at"
|
||||
t.datetime "failed_at"
|
||||
|
@ -83,11 +80,11 @@ ActiveRecord::Schema.define(version: 20140901143732) do
|
|||
create_table "events", force: true do |t|
|
||||
t.integer "user_id"
|
||||
t.integer "agent_id"
|
||||
t.decimal "lat", precision: 15, scale: 10
|
||||
t.decimal "lng", precision: 15, scale: 10
|
||||
t.text "payload", limit: 2147483647, charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.decimal "lat", precision: 15, scale: 10
|
||||
t.decimal "lng", precision: 15, scale: 10
|
||||
t.text "payload", limit: 16777215, charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.datetime "expires_at"
|
||||
end
|
||||
|
||||
|
@ -117,13 +114,13 @@ ActiveRecord::Schema.define(version: 20140901143732) do
|
|||
add_index "scenario_memberships", ["scenario_id"], name: "index_scenario_memberships_on_scenario_id", using: :btree
|
||||
|
||||
create_table "scenarios", force: true do |t|
|
||||
t.string "name", null: false, charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.integer "user_id", null: false
|
||||
t.string "name", null: false, charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.integer "user_id", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.text "description", charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.boolean "public", default: false, null: false
|
||||
t.string "guid", null: false, charset: "ascii", collation: "ascii_bin"
|
||||
t.text "description", charset: "utf8mb4", collation: "utf8mb4_bin"
|
||||
t.boolean "public", default: false, null: false
|
||||
t.string "guid", null: false, charset: "ascii", collation: "ascii_bin"
|
||||
t.string "source_url"
|
||||
t.string "tag_bg_color"
|
||||
t.string "tag_fg_color"
|
||||
|
@ -154,8 +151,8 @@ ActiveRecord::Schema.define(version: 20140901143732) do
|
|||
t.integer "user_id", null: false
|
||||
t.string "credential_name", null: false
|
||||
t.text "credential_value", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "mode", default: "text", null: false, collation: "utf8_bin"
|
||||
end
|
||||
|
||||
|
@ -172,8 +169,8 @@ ActiveRecord::Schema.define(version: 20140901143732) do
|
|||
t.datetime "last_sign_in_at"
|
||||
t.string "current_sign_in_ip"
|
||||
t.string "last_sign_in_ip"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.boolean "admin", default: false, null: false
|
||||
t.integer "failed_attempts", default: 0
|
||||
t.string "unlock_token"
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
APP_SECRET_TOKEN=notarealappsecrettoken
|
||||
TWITTER_OAUTH_KEY=twitteroauthkey
|
||||
TWITTER_OAUTH_SECRET=twitteroauthsecret
|
||||
TUMBLR_OAUTH_KEY=tumblroauthsecret
|
||||
TUMBLR_OAUTH_SECRET=tumblroauthsecret
|
||||
THIRTY_SEVEN_SIGNALS_OAUTH_KEY=TESTKEY
|
||||
THIRTY_SEVEN_SIGNALS_OAUTH_SECRET=TESTSECRET
|
||||
FAILED_JOBS_TO_KEEP=2
|
38
spec/models/agents/tumblr_publish_agent_spec.rb
Normal file
38
spec/models/agents/tumblr_publish_agent_spec.rb
Normal file
|
@ -0,0 +1,38 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Agents::TumblrPublishAgent do
|
||||
before do
|
||||
@opts = {
|
||||
:blog_name => "huginnbot.tumblr.com",
|
||||
:post_type => "text",
|
||||
:expected_update_period_in_days => "2",
|
||||
:options => {
|
||||
:title => "{{title}}",
|
||||
:body => "{{body}}",
|
||||
},
|
||||
}
|
||||
|
||||
@checker = Agents::TumblrPublishAgent.new(:name => "HuginnBot", :options => @opts)
|
||||
@checker.service = services(:generic)
|
||||
@checker.user = users(:bob)
|
||||
@checker.save!
|
||||
|
||||
@event = Event.new
|
||||
@event.agent = agents(:bob_weather_agent)
|
||||
@event.payload = { :title => "Gonna rain...", :body => 'San Francisco is gonna get wet' }
|
||||
@event.save!
|
||||
|
||||
stub.any_instance_of(Agents::TumblrPublishAgent).tumblr {
|
||||
stub!.text(anything, anything) { { "id" => "5" } }
|
||||
}
|
||||
end
|
||||
|
||||
describe '#receive' do
|
||||
it 'should publish any payload it receives' do
|
||||
Agents::TumblrPublishAgent.async_receive(@checker.id, [@event.id])
|
||||
@checker.events.count.should eq(1)
|
||||
@checker.events.first.payload['post_id'].should eq('5')
|
||||
@checker.events.first.payload['published_post'].should eq('[huginnbot.tumblr.com] text')
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Reference in a new issue