Create a gist now

Instantly share code, notes, and snippets.

@monde /Gemfile
Last active Dec 14, 2015

What would you like to do?
A watcher script that pull URLs found in a Twitter feed and post them to the Capgun.io web thumb service for capture. Also, a Sintra App that will receive Capgun webhooks upon job completion and post the results to Tumblr.
ENV["RACK_ENV"] ||= "development"
require "rubygems"
require "bundler"
require 'logger'
Bundler.require(:default, ENV["RACK_ENV"].to_sym)
require 'tumblr_client'
##
# Poster - A Sintra App that receives post receive hooks from the capgun.io
# service and posts these results to a Tumblr
# Configuration options in ~/.capguntumblrrc YAML
#
# ---
# capgun_webhook_uri: The URI that Capgun will post its webhooks to
# tumblr_webhook_uri: The URI that Tumblr will post its webhooks to
# tumblr_name: The CNAME hostname of your Tumblr blog
# tumblr_consumer_key: Tumblr Consumer Key
# tumblr_consumer_secret: Tumbler Consumer Secret
# tumblr_oauth_token: Tumblr Access Token
# tumblr_oauth_token_secret: Tumblr Token Secret
#
rc = File.expand_path("~/.capguntumblrrc")
CAPGUNTUMBLR_CONFIG = YAML.load_file(rc).symbolize_keys
Tumblr.configure do |config|
config.consumer_key = CAPGUNTUMBLR_CONFIG[:tumblr_consumer_key]
config.consumer_secret = CAPGUNTUMBLR_CONFIG[:tumblr_consumer_secret]
config.oauth_token = CAPGUNTUMBLR_CONFIG[:tumblr_oauth_token]
config.oauth_token_secret = CAPGUNTUMBLR_CONFIG[:tumblr_oauth_token_secret]
end
class Poster < Sinatra::Application
use Rack::Logger
enable :logging, :dump_errors, :raise_errors
configure :production do
Dir.mkdir('log') unless File.exist?('log')
# Spit stdout and stderr to a file during production
# in case something goes wrong
$stdout.reopen("log/production.log", "a")
$stdout.sync = true
$stderr.reopen($stdout)
end
configure :development do
$logger = Logger.new(STDOUT)
$logger.level = Logger::DEBUG
end
helpers do
def logger
request.logger
end
end
before do
content_type 'application/json'
end
get '/' do
{ message: 'wut!?' }.to_json
end
# The Tumblr API service will post a notice back here
post CAPGUNTUMBLR_CONFIG[:tumblr_webhook_uri] do
data = JSON.parse request.body.read
logger.info "tumblr web hook: #{data.inspect}"
# just echo
data
end
# The Capgun API service will post a notice back here
post CAPGUNTUMBLR_CONFIG[:capgun_webhook_uri] do
request.body.rewind
data = JSON.parse request.body.read
image_url = data['order']['asset_urls']['xlarge']
cap_url = data['order']['url']
post_image(image_url, cap_url)
# just echo
data
end
def post_image(image_url, cap_url)
logger.info "posting image: #{image_url} of #{cap_url}"
client = Tumblr.new
photo = client.photo(CAPGUNTUMBLR_CONFIG[:tumblr_name], {
#:data => ['/home/mike/Desktop/wallace-face.jpg'],
# source is an option to the tumblr api, they download the image at the url
# :data file local to the script and :source urlr are mutually exclusive
:source => image_url,
:caption => cap_url,
})
logger.info "post result: #{photo.inspect}"
end
end
run Poster
source 'http://rubygems.org'
gem 'tumblr_client'
gem 'oauth'
gem 'sinatra'
gem 'json'
gem 'twitter'
gem 'capgun'
gem 'activesupport'
gem 'whenever'
gem 'redis-namespace'
group :development do
gem 'capistrano'
gem 'capistrano-ext'
end
#!/usr/bin/env ruby
require 'pp'
require "rubygems"
require "bundler/setup"
require 'yaml'
require 'twitter'
require 'capgun'
require 'redis-namespace'
require 'logger'
require 'active_support/core_ext/hash'
# $:.unshift "#{File.dirname(__FILE__)}/lib"
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), "../lib")
require 'watcher'
##
# This is a script to watch a twitter home timeline and post URLs found in the
# timeline to the capgun.io to be web thumbed. The script will look in a
# ~/.watcherrc file for it's runtime options. Presumably this script would be
# placed into a cron job of some sort. It also assumed that capgun.io's web
# hook callback would be used to trigger a follow task once the capture has
# completed.
#
# Configuration options in ~/.watcherrc YAML:
#
# ---
# twitter_consumer_key: Consumer key
# twitter_consumer_secret: Consumer secret
# twitter_oauth_token: Access token
# twitter_oauth_token_secret: Access token secret
# capgun_auth_token: Capgun Authorization token
# capgun_endpoint: https://api.capgun.io
Dir.mkdir('log') unless File.exist?('log')
# Spit stdout and stderr to a file during production
# in case something goes wrong
$stdout.reopen("log/watcher.log", "a")
$stdout.sync = true
$stderr.reopen($stdout)
rc = File.expand_path("~/.watcherrc")
WATCHER_CONFIG = YAML.load_file(rc).symbolize_keys
Twitter.configure do |config|
config.consumer_key = WATCHER_CONFIG[:twitter_consumer_key]
config.consumer_secret = WATCHER_CONFIG[:twitter_consumer_secret]
config.oauth_token = WATCHER_CONFIG[:twitter_oauth_token]
config.oauth_token_secret = WATCHER_CONFIG[:twitter_oauth_token_secret]
end
Capgun.configure do |config|
config.auth_token = WATCHER_CONFIG[:capgun_auth_token]
config.endpoint = WATCHER_CONFIG[:capgun_endpoint]
end
Watcher.process
##
# Watcher class encapsulates logic to watch a Twitter home timeline
# and post URLs found there to the capgun.io service.
# This file should be placed in lib/watcher.rb
class Watcher
def self.process
new.work
end
attr_reader :twitter_client, :capgun_client, :since_id
def initialize
@twitter_client = Twitter::Client.new
@capgun_client = Capgun::Client.new
redis = Redis.current || Redis.new
@redis = Redis::Namespace.new(:watcher, :redis => redis)
end
def work
timeline = self.fetch_timeline
urls = self.collect_urls(timeline)
self.capture_urls(urls)
end
def fetch_timeline
self.load_since_id
result = self.twitter_client.home_timeline(
include_entities: true,
since_id: self.since_id,
count: 200
)
self.save_since_id(result)
result
end
def collect_urls(timeline)
result = []
timeline.each_with_index do |status, index|
urls = status.urls
urls.each do |url|
result << url.expanded_url
end
end
puts "#{Time.now} #{result.inspect}"
result
end
def capture_urls(urls)
urls.each { |url| self.capgun_client.capture(url, :packages => [ :images, :viewport ], :viewport => "1000x1000") }
end
def load_since_id
@since_id = (@redis.get('since_id') || 1).to_i
@since_id = 1 if @since_id < 1
@since_id
end
def save_since_id(result)
result = result.max { |a,b| a.id <=> b.id }
result = result.nil? ? 1 : result.id
result = @since_id if @since_id > result
@redis.set('since_id', result)
@since_id = result
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment