0

新しいTwitterのエゴサーチツールを作った

2010年に作ったやつが動かなくなったので
エゴサーチツール feedim

コードみたらひどかったから、1から作りなおしたほうが速いかーと思って作りなおした。
shokai/twitter-egosearch-skype

すげークリーンなコードになってて良い。

機能

Twでtwitter searchして
本文中の短縮URLはhugeurlで展開して
mongodb/mongoidに保存する

というクローラーがevent_emitterでイベント投げてくるので
Skype gemでpostする。


YAMLの設定ファイルをHashie::Mashで包んだら使いやすくてよかった。sizeとかlengthとかHashやArrayにある値を設定ファイルで使えなくなるけど気をつければメリットの方が大きい。


コードがひどいから作り直そうと思っても大抵挫折するし、がんばっても大して良くならないんだけど、そういう設計をかっこ良く書けるようにするライブラリやフレームワークを作ってから再チャレンジすると革命が起こせる。今回はevent_emitterがそれ。便利すぎ。神。

0

GUIから起動してないTerminalからDBUSを使う

LinuxのcrontabやserviceからSkype APIが使えるようになった
https://github.com/shokai/skype-ruby


問題

Skype gemで使っているruby-dbusは環境変数DBUS_SESSION_BUS_ADDRESSを使ってSkypeアプリと通信させてくれるのだが、GUIから起動したTerminalでないとDBUS_SESSION_BUS_ADDRESSが設定されていない。
つまりcronやserviceから起動したプロセスはDBUSが使えなかった


解決方法

~/.dbus/session-bus/ にテキストファイルでDBUS_SESSION_BUS_ADDRESSが書いてあった

kde – Run a dbus program in crontab , how to know about the SESSION id? – Unix & Linux Stack Exchange

DBUSに接続する前に環境変数DBUS_SESSION_BUS_ADDRESSが無かったらファイルから読んで設定するようにした。


Virtual Box

Skype APIは起動済みのSkypeアプリと通信するものなので、Skype botを作るにはSkypeを常に起動しておかなければならない。
家のMacMiniにVirtual BoxにUbuntu12.04入れてその中でSkype起動して運用している。

0

CUIでSkype Chatできるコマンド作った

v0.2.1以降のskype gemに付いている。現在v0.2.2になった。
あまり便利ではないのでおすすめできない。

% gem install skype
% skype-chat

起動するとチャットを選ばされるので、選ぶ。

どの辺が便利でないかというと、そもそもSkype APIはそのマシンでGUIで起動済みのSkypeと通信しているわけなので、あえてCUIでチャットする必要が無い。

ただskype gemのサンプルコードとして有用だと思ったのでつけておいた次第。

これがそのskype-chatコマンド。あの恐ろしいSkype APIがとても綺麗に使えているでしょう。
https://github.com/shokai/skype-ruby/blob/master/bin/skype-chat
本当はreadlineとか使った方がいいんだけどgemに依存が増えてしまうのでこの程度で止めておく。まともなチャットツールにするならこれを元に改造すればいいと思う。

Skype gemはコストの高いAPIは内部で自動的にキャッシュしてくれて便利です。
MacとLinuxに対応しているから、botとか作るのに活用してください。

windows対応はpull request募集中です。

0

Skypeのrubygemをアップデートした

前:Skype API Rubyラッパーのgem作った

gem install skype
https://github.com/shokai/skype-ruby

今v0.2.1になった。

主にrb-appscript廃止と、Chat APIとCall APIのラッパーを作った。

SkypeのAPIは建てまし続けた旅館のようになっていて、素直にラッパーを作ると逆に意味不明になると思ったので俺が欲しい機能を俺が欲しい形式で使えるようにしていく方針。

もちろんSkype.execにSkype APIの文字列を渡せば全機能が使えるようになっているので問題ない。


rb-appscript廃止

新しいmacbook airにrb-appscriptインストールしようとしたらCarbon関係のネイティブがビルドできなくてインストールできなかったのでやめた。
開発停止しているらしいし。
/usr/bin/osascriptに-eでapplescript渡して実行することにした。


Chat APIのラッパー

Skypeはchatを選択するときにIDで指定するんだけど、IDは同じチャットでも人によっては違うIDに見えていたり時間経過で変化してしまっていて、botを作る時に使い勝手が悪かった。

こうなった。
require 'skype'

chat = Skype.chats.find{|c| c.members.include? "shokaishokai" and c.topic =~ /testchat/ }

chat.post "hello chat!!" # 投稿

chat.messages.each do |m|
puts m
end
chatはmessageを受信イベントで受け取れるようにしようか考えている。


Call APIのラッパー

たとえば相手が通話に出た瞬間に切るのはこうやる
require 'skype'

call = Skype.call "shokaishokai"

while !call.talking?
puts call.status
sleep 1
end

call.hangup if call.talking?

0

Skype API Rubyラッパーのgem作った

今日は早起きしたのでさくっと作った。

rb-skypemacがRuby1.8でしか動かなかったり、Ruby4Skypeがソースを修正しないと動かなかったり、どのskype gemもリポジトリが公開されてなくてパッチ送れなかったので1から作りなおした。

https://github.com/shokai/skype-ruby
https://rubygems.org/gems/skype


linuxだとruby-dbus、macだとrb-appscriptを使うんだけどOS毎に別のgemをdependencyに入れるのどうすればいいんだろう・・
gemspecの中でRUBY_PLATFORMを見てspec.add_dependencyしたらローカルでbundle installすると大丈夫だけど、rubygems.org経由でgem installするとlinuxなのにrb-appscriptが入ってしまってcocoa.hが無くてビルドエラーする。


インストール

for Mac
% gem install skype rb-appscript

for Linux
% gem install skype ruby-dbus

Gemfile でインストールする場合
gem 'skype'
gem 'rb-appscript' if RUBY_PLATFORM =~ /darwin/i
gem 'ruby-dbus' if RUBY_PLATFORM =~ /linux/i

使い方

これはRubyのメタプログラミングを使った超単純なラッパーなので、使う前にSkype Developer – Skype Desktop API Reference Manualを読んで理解してください
読めばわかると思う


require 'rubygems'
require 'skype'

Skype.config :app_name => "my_skype_app"

## send message
Skype.message "USER_NAME", "hello!!"

## call
Skype.call "USER_NAME"

## get recent chat list
puts Skype.search("recentchats")

## send message to group chat
Skype.chatmessage "#name1/name2;$a1b2cdef3456", "hello chat!!"

簡単に電話かけたりチャットに投稿したりできますね。やりましたね。
しかもMacでもLinuxでも動く。


くわしい内部実装

Skype.messageやSkype.callなどの関数は実装されていません。
実装されていませんが、method_missingを使った簡単なメタプログラミングでSkype.execに変換されて実行されます。
以下と等価です
## send message
Skype.exec "MESSAGED USER_NAME hello!!"

## call
Skype.exec "CALL USER_NAME"

## get recent chat list
puts Skype.exec "SEARCH recentchats"

## send message to group chat
Skype.exec "CHATMESSAGE #name1/name2;$a1b2cdef3456 hello chat!!"
Skypeには各OS毎に通信方法こそ違うものの、同じフォーマットのQuery StringでやりとりするAPIがあります。
それが”MESSAGE ユーザー名 本文”とか、”CALL ユーザー名”です。
messageという関数を呼び出すとmethod_missingによってexec “MESSAGE ~~”になるわけですね


これだけの実装です
module Skype
def self.method_missing(name, *args)
self.exec "#{name.upcase} #{args.join(' ')}"
end

def self.exec(command)
Appscript.app("skype").send_ :script_name => self.config[:app_name], :command => command
end
end
実際には、LinuxとMacでSkype.execの中の実装がわかれています。


返り値がまだ全部Stringなので、SEARCH RECENTCHATSとかGET CHATMESSAGEとかを自分でparseしないとならないのがつらい。そのうちなんとかする。