Twitter は使おうとするとなぜか気が滅入ってくる、なぜか分からないけどとても疲れる。
なので全然使っていないのですが、Evernote にちょっと保存しておきたいものがあったとき、
Twitter を間に入れるのが一番手っ取り早いような気がしていました。
Evernote に直接送れなくても、Twitter 連携しているサービスは多いですからね。
Shazam のタグとか。
で、Twitter と Evernote の連携ぐらい誰でも考えるだろうし、
さぞ色んなやりかたがあるだろうと思ったら、あんまりないみたいでした。
ツイエバ、っていうのがあるようだけれど、登録とかが必要で、
とても大変そうなので作った方が早そうでしたので作りました。
必要なものの準備
Ruby
Ruby で書いたので、動作には Ruby が必要です。
今のところ最新の 2.1 で動かしていますが、1.9 までなら動くんじゃないかな・・・
それと、以下の gem を使っているので bundler などで準備しておいてください。
- evernote_oauth
Twitter API Key
Twitter へアプリケーションからアクセスするためのキーが必要です。
この辺りのやり方は変わると思いますが、現在のやり方だと、
- Twitter Developers に Twitter アカウントでログイン
- アバターアイコンから "My Application" を選択
- "Create New App" を選択
- 情報を適切に(テキトーに)埋める
すると、新しいアプリケーションが登録されるので、
- API key
- API secret
を控えておいてください。
Twitter Access Token
上記で作成したアプリケーションから、"Create my Access Token" を選択すると、
以下が生成されるので、控えておきます。
- Access token
- Access token secret
これで、アプリケーションから Twitter に OAuth 認証する準備ができました。
Evernote Developer Key
Evernote の API を利用する場合、個人的に使うだけであれば、Developer Key を利用すると簡単です。
Developer Token は Evernote にログインした状態で、以下にアクセスすると取得できます。
https://www.evernote.com/api/DeveloperToken.action
これで、アプリケーションから Evernote に認証する準備ができました。
スクリプトの実行
仕様
ここで紹介するスクリプトは以下を実行します。
- 自分のツイートのタイムラインから、引数に指定したキーワードを含むツイートを抽出
- Evernote にキーワード名のノートブックを作成
- ノートブックに1ツイートを1ノートとして作成
実行方法
コードの以下の部分を、取得した認証キーに書き換えてください。
YOUR_TWITTER_CONSUMER_KEY = 'Enter your API key'
YOUR_TWITTER_CONSUMER_SECRET = 'Enter yout API secret'
YOUR_TWITTER_ACCESS_TOKEN = 'Enter your Access token'
YOUR_TWITTER_ACCESS_TOKEN_SECRET = 'Enter your Access token secret'
YOUR_EVENOTE_DEVELOPER_KEY = 'Enter your Developer key'
実行
引数に抽出したいキーワードを指定して実行します。
例えば、「もういやだ」というキーワードで検索する場合は以下のようにします。
$ ruby twieve.rb もういやだ
注意
- 実行環境が utf-8 以外の文字コードでの動作は未確認です。
- 複数回の抽出でツイートが重複しないよう、スクリプトと同フォルダに
history.yaml
というファイルを作成し、取得済みのツイートのIDを記録しています。
再取得したい場合には、history.yaml
の該当行か、ファイルごと削除してください。
スクリプト
名前が思いっきり「ツイエバ」パクリですが気にしないでくださいね!!!
# !/usr/bin/env ruby
# coding: utf-8
require 'twitter'
require "evernote_oauth"
require 'yaml'
require 'cgi'
YOUR_TWITTER_CONSUMER_KEY = 'Enter your API key'
YOUR_TWITTER_CONSUMER_SECRET = 'Enter yout API secret'
YOUR_TWITTER_ACCESS_TOKEN = 'Enter your Access token'
YOUR_TWITTER_ACCESS_TOKEN_SECRET = 'Enter your Access token secret'
YOUR_EVENOTE_DEVELOPER_KEY = 'Enter your Developer key'
class Twieve
attr_accessor :config
attr_reader :twitter_user
def initialize
@config = {}
end
def authorize
# Twitterクライアントを設定
begin
@twitter_client = Twitter::REST::Client.new do |config|
config.consumer_key = @config[:twitter_consumer_key]
config.consumer_secret = @config[:twitter_consumer_secret]
config.access_token = @config[:twitter_access_token]
config.access_token_secret = @config[:twitter_access_token_secret]
end
@twitter_user = @twitter_client.user
rescue => e
puts "ERROR: Cannot setup Twitter client. Please make sure you have entered valid access credentials. [#{e}]"
return false
end
# Evernoteクライアントを設定
begin
# Developer Tokenをセット
token = @config[:evernote_developer_token]
client = EvernoteOAuth::Client.new(:token => token, :sandbox => false)
@evernote_note_store = client.note_store
rescue => e
puts "ERROR: Cannot setup Evernote client. Please make sure you have entered valid access credentials. [#{e}]"
return false
end
end
def get_tweets_match_pattern(user_screen_name, pattern, since_id)
# ユーザーのタイムラインからパターンにマッチするツイートのみ抽出
begin
tweets = @twitter_client.user_timeline(user_screen_name,
:since_id=>since_id,
:count=>300).select do |tweet|
tweet.text =~ pattern
end
rescue => e
puts "ERROR: Cannot fetch timeline data of #{user_screen_name}. [#{e}]"
return false
end
end
def get_notebook_guid(notebook_name)
begin
notebooks = @evernote_note_store.listNotebooks.select do |notebook|
notebook.name == notebook_name
end
rescue => e
puts "ERROR: Cannot fetch notebooks. [#{e}]"
return false
end
# ノートブックが無かったら作る
if notebooks.empty?
begin
notebook = Evernote::EDAM::Type::Notebook.new
notebook.name = notebook_name
@evernote_note_store.createNotebook(@config[:evernote_developer_token],
notebook).guid
rescue => e
puts "ERROR: Cannot create notebook. [#{e}]"
return false
end
else
notebooks.first.guid
end
end
def create_evernote_note(notebook_name, note_title, note_content)
notebook_guid = get_notebook_guid(notebook_name)
return false unless notebook_guid
# ノートのタイトル
note_title = note_title
# ノートのENMLヘッダ
enml_header = <<-HEADER
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
HEADER
# ノートの本文
note_content = <<-CONTENT
# {enml_header}
<en-note>#{CGI.escapeHTML(note_content)}</en-note>
CONTENT
note = Evernote::EDAM::Type::Note.new(:title => note_title,
:notebookGuid => notebook_guid,
:content => note_content)
# ノートの作成
begin
@evernote_note_store.createNote(@config[:evernote_developer_token], note)
rescue => e
puts "ERROR: Cannot create a note. [#{e}]"
return false
end
end
end
unless ARGV[0]
puts 'ERRPOR: You must specify a search word.'
exit 1
end
twieve = Twieve.new
twieve.config[:twitter_consumer_key] = YOUR_TWITTER_CONSUMER_KEY
twieve.config[:twitter_consumer_secret] = YOUR_TWITTER_CONSUMER_SECRET
twieve.config[:twitter_access_token] = YOUR_TWITTER_ACCESS_TOKEN
twieve.config[:twitter_access_token_secret] = YOUR_TWITTER_ACCESS_TOKEN_SECRET
twieve.config[:evernote_developer_token] = YOUR_EVENOTE_DEVELOPER_KEY
unless twieve.authorize
puts 'ERROR: Failed to authorize.'
exit 1
end
pattern = Regexp.new(ARGV[0].downcase, Regexp::IGNORECASE)
history_file = Pathname.new(File.expand_path(File.dirname($PROGRAM_NAME))) + 'history.yaml'
if File.exist?(history_file)
yaml_data = YAML.load_file(history_file)
end
if yaml_data && yaml_data.has_key?(pattern.source)
since_id = yaml_data[pattern.source]
else
since_id = 1
yaml_data = {}
end
tweets = twieve.get_tweets_match_pattern(twieve.twitter_user.id,
pattern,
since_id)
unless tweets
puts 'ERROR: Failed to get Twitter timeline.'
exit 1
end
unless tweets.empty?
tweets.reverse_each do |tweet|
#puts "DEBUG: #{tweet.text}... (ID: #{tweet.id})"
unless twieve.create_evernote_note("#{twieve.twitter_user.name}'s Tweets (#{pattern.source})",
"#{tweet.created_at} (ID: #{tweet.id})",
tweet.full_text)
puts 'ERROR: Failed to create Evernote note.'
exit 1
end
puts "INFO: #{tweet.text[0, 10]}... (ID: #{tweet.id}) has been successfully created."
end
# 取得したIDの一番新しいものを保存
yaml_data[pattern.source] = tweets.first.id
open(history_file, "w") do |file|
file.write(YAML.dump(yaml_data))
end
end