はてなダイアリーコマンドライン

gistpのコードを参考にしてコマンドラインからはてなダイアリーにポストするコードを書いてみた(ただ、ポストするだけ)。
任意のファイルの中身を読み込んでそのままポストできる。
echoなどを使って、一行テキストなどもポストできる。
複数ファイルを一気にダイアリーにアップしたりもできたりする。
デフォルトは下書き投稿となっている。投稿後にはてなインタフェースで校正確認後に公開というフローでもいいかも。

#!/usr/bin/perl

use strict;
use warnings;
use Getopt::Long;
use File::Slurp qw(slurp);
use FindBin;
use File::Spec;
use YAML ();
use DateTime;
use XML::Atom::Entry;
use XML::Atom::Client;
use Data::Dumper;

my $api_base = "http://d.hatena.ne.jp/";
my $dt = DateTime->now( time_zone => 'Asia/Tokyo' ); 
my $config = YAML::LoadFile(File::Spec->catfile($FindBin::Bin, 'config.yaml'))
		or die "Can't load config file: $!";
my %options;
GetOptions(\%options, "--title=s", "--blog");

run(\%options, @ARGV);

sub run {
	my($opts, @args) = @_;
	my @files = setup_files($opts, @args);
	
	my %fields;
	$fields{mode} = 'blog' if $opts->{blog};

	foreach my $file (@files) {
		$fields{title} = $file->{title};
		$fields{content} = $file->{content};
		&post(\%fields, $config);
	}
}

sub setup_files {
	my($opts, @args) = @_;
	my @files;
	if (@args == 0 or $args[0] eq '-') {
		my $content = join '', do{ local $/; <STDIN>};
		@files = ({ title => $opts->{title} || "$dt", content => $content });
	} else {
		for my $arg (@args) {
			push @files, {
				title => $arg,
				content => scalar slurp($arg),
			};
		}

	}
	return @files;
}

sub post {
	my($fields, $config) = @_;
	my $username = $config->{hatena_user};
	my $password = $config->{hatena_pass};
	my $client = XML::Atom::Client->new;
	   $client->username($username);
	   $client->password($password);
	my $entry = XML::Atom::Entry->new;
	   $entry->title($fields->{title});
	   $entry->content($fields->{content});
    my ($edit_url);		
	if ($fields->{mode} && $fields->{mode} eq 'blog') {
		my $api_url = $api_base. $username. '/atom/blog';
		$edit_url = $client->createEntry($api_url, $entry)
				or die $client->errstr;
		$edit_url =~ s/(\/atom\/blog)//i;
		print $edit_url."\n";
	} else {
		my $api_url = $api_base. $username. '/atom/draft';
		$edit_url = $client->createEntry($api_url, $entry)
				or die $client->errstr;
		my $id = ($edit_url =~ /(\d+)$/)[0];
		my $res_url = $api_base. $username. "/draft?epoch=". $id;
		print $res_url."\n";
	}
}

twitter グルメ情報 ボット ”地域名 夜景”でオススメグルメスポットを教えてくれます。 

ホットペッパー Webサービス を利用してtwitter グルメ情報 返信ボットを作成しました。(リクルートより承認いただけました。 )
ask go!go! (askgo) on Twitter

使い方

@askgo help 使い方についての説明を取り出せます。

@askgo help ジャンル[or genru] 検索候補ワード(ジャンル)を取り出せます。

@askgo フリーワード[スペースで複数指定可能] >pc[or mb](出力をPC用か携帯用で分けて取り出せます。デフォルトは携帯用出力で) >半角数字[検索結果順位指定](1件のみ返信ですが、その他該当する情報順位を指定することができます。)
例)

@askgo 名古屋 金山 イタリアン >pc >3
場所:名古屋市中区金山 ジャンル:イタリアン 出力:PC用で 検索結果:3番目の情報

@askgo ダイニングバー 神戸 >mb >2
ジャンル:ダイニングバー 場所:神戸 携帯用出力で 検索結果:2番目の情報

@askgo 銀座 ダイニングバー
場所:銀座 ジャンル:ダイニングバー デフォルトで携帯用出力 検索結果は1番目

@askgo 金山駅
場所:金山駅名古屋市中区) デフォルトで携帯用出力 検索結果は1番目

@askgo 三ノ宮駅 >PC
場所:三ノ宮駅(神戸) 出力:PC用 検索結果は1番目

@askgo 北野 >PC
場所:北野(神戸) 出力:PC用 検索結果は1番目

@askgo 神戸 夜景
場所:神戸 出力:携帯用 検索結果は1番目

といった具合に検索をかけて情報を取り出せます(返信される)。

※フリーワードには、店名かな、店名、住所、駅名、お店ジャンルキャッチ、キャッチのフリーワード検索(部分一致)が可能です。ホットペッパー | APIリファレンス | リクルートWEBサービスより

お店ジャンル

居酒屋 ダイニングバー 創作料理 和食 洋食 イタリアン・フレンチ 中華 焼肉・韓国料理 アジアン 各国料理 カラオケ・パーティ バー・カクテル ラーメン お好み焼き・もんじゃ・鉄板焼き カフェ・スイーツ その他グルメ

出力内容

@アカウント 最寄駅名 店名 住所 交通アクセス 携帯用クーポン掲載有無 ホットペッパーPC向けURL(携帯向けURL) 店舗位置(googlemap画像) 店舗位置(googlemapリンク) 検索該当件数

以上のような並びで情報を返信します。

該当件数が多い場合は、同じ検索ワードで最後の>半角数字を変えて、検索順位を変えて他の情報を取り出してください。

ホットペッパー | ご利用案内 | リクルートWEBサービスより引用:

利用できない地域


グルメサーチAPI未対応エリア

以下の17県は、グルメサーチAPIでは情報を提供しておりません。

青森、秋田、山形、茨城、群馬、山梨、富山、福井、三重、滋賀、奈良、和歌山、鳥取、島根、山口、佐賀、沖縄 (2009年6月現在)

Powered by ホットペッパー Webサービス

詳細はこちらの記事でも紹介しています。
Twitter reply bot グルメ情報返信ボット @askgoを作成しました

Twitter search api

Net::Twitterを使ってTwitter search APIを出力する
環境 windows xp sp3 lenovo s10e(netbook)
ppmからconfig::pitがインストールできないのでログイン情報はそのまま)

#!/usr/bin/perl
use strict;
use warnings;
use Encode;
use Encode::Guess qw/ shiftjis euc-jp 7bit-jis utf8 /;
use Net::Twitter;

my $username ='username'; #username
my $pass = 'password'; #password


my $twit = Net::Twitter->new(
                              username => $username,
                              password => $pass,
                            ); 
my $query = 'twitter'; #検索ワード:今回は'twitter'

my $response = $twit->search($query);

my @lines;
while ( my ($key, $value) = each %{ $response } ){
	print $key."::".$value,"\n";
}

出力
page::1
query::twitter
completed_in::0.031903
refresh_url::?since_id=2813960057&q=twitter
next_page::?page=2&max_id=2813960057&q=twitter
results_per_page::15
max_id::2813960057
results::ARRAY(0x2bafb2c)
since_id::0

results 出力

my $twit = Net::Twitter->new(
                              username => $username,
                              password => $pass,
                            ); 
my $query = 'twitter';

my $response = $twit->search($query);

my @lines;
foreach my $key ( @{ $response->{results} } ){
	while ( my ($res_key , $res_val) =  each %{ $key }  ){
		print $res_key."::".$res_val,"\n";
	}
}

出力
15件出力されるが1件分
source::<a href="TweetMeme">http://tweetmeme.com">TweetMeme
Use of uninitialized value in concatenation (.) or string at twitter_search_hash
.pl line 23.
to_user_id::
created_at::Fri, 24 Jul 2009 07:08:50 +0000
Wide character in print at twitter_search_hash.pl line 23.
text::RT @tweetmeme Twitter 101 for Business 窶・A Special Guide http://cli.gs/u
LA2z
profile_image_url::http://s3.amazonaws.com/twitter_production/profile_images/329
564050/avatar_3714_normal.jpg
from_user_id::30879573
id::2814645841
iso_language_code::en
from_user::bea3300

resultsの中の任意の値を配列に収める

今回はtext, id , userを配列に収める。

my $twit = Net::Twitter->new(
                              username => $username,
                              password => $pass,
                            ); 
my $query = 'twitter';

my $response = $twit->search($query);

my @lines;
foreach my $key ( @{ $response->{results} } ){
	my $text = decode('Guess', $key->{text} );
	my $id = $key->{id};
	my $user = $key->{from_user};
	push @lines, ( join(":::", $user, $id, $text ) );
}

for (@lines) {
	print $_,"\n";
}

出力は
user:::id:::text
で15件出力される。

Twitter search api

Net::Twitterを使ってTwitter search APIを出力する
環境 windows xp sp3 lenovo s10e(netbook)
ppmからconfig::pitがインストールできないのでログイン情報はそのまま)

#!/usr/bin/perl
use strict;
use warnings;
use Encode;
use Encode::Guess qw/ shiftjis euc-jp 7bit-jis utf8 /;
use Net::Twitter;

my $username ='username'; #username
my $pass = 'password'; #password


my $twit = Net::Twitter->new(
                              username => $username,
                              password => $pass,
                            ); 
my $query = 'twitter'; #検索ワード:今回は'twitter'

my $response = $twit->search($query);

my @lines;
while ( my ($key, $value) = each %{ $response } ){
	print $key."::".$value,"\n";
}

出力
page::1
query::twitter
completed_in::0.031903
refresh_url::?since_id=2813960057&q=twitter
next_page::?page=2&max_id=2813960057&q=twitter
results_per_page::15
max_id::2813960057
results::ARRAY(0x2bafb2c)
since_id::0

twitter reply bot お天気予報返信ボット @askwb

twitter reply bot お天気予報返信ボットをperlを使って作成。ask_weather_bot askwbです。
http://twitter.com/askwb

使い方

askwbをフォロー

@askwb 地域 [今日 or 明日 or 明後日(ひらがな、カタカナでもOK)] でポストする。
例)

  • askwb 東京 あさって
  • @askwb 名古屋 今日
  • @京都 アス,など

地域名については、天気予報 きょうの気象情報 - livedoor 天気情報に準じます。気をつけてください。市などをつけると情報を取得できないです。
たとえば、愛知県では情報取得ができません。名古屋もしくは豊橋でポストください。

@askwb help (使い方についての説明を返信します)

以下でもtwitter reply bot お天気予報返信ボットについて紹介しています。
Perlでtwitter reply bot お天気予報返信ボットを作成しました

TODO

今現在フォローしてもらう形で返信するようにしていますが、
フォローしなくても返信できるように改善する予定。
repliesから問い合わせ内容を取得していますが、
searchから@askwbへの問い合わせ内容取得する方向でテスト中です。
しばらくしたら、フォローなしでも天気予報返信できるようにします。

指定したハッシュの値を取り出す

例えば、twitter botperlを使って作るとして、
何かのメッセージを投げかければ、オウム返しで何かの値を返してくれるものをつくろうと思ったときに、必要な要素は、
keyのなかで、

created_at
text
user

このkeyの値を取得するためには、

use Encord;

foreach my $tweet (  @$response ){
        my $text = $tweet->{text};
        my $date = $tweet->{created_at};
        my $user = $tweet->{user}->{screen_name};
           $text = encode('utf-8',$text);

        print $date,"\n";
        print $text,"\n";
        print $user, "\n";
}

これで指定した値が取得できる。

text部分に@ユーザ−名が入るためにそれを取り除くのに、

          $text =~ s#\@username\s##;

を追加すれば、テキストのみ抽出できると。

ハッシュの値表示

ハッシュリファレンスの値表示は、

my @value_of_replies = values( %{ @{ $response }[0] } );
foreach my $value ( @value_of_replies ){
        print $value, "\n";
}

ハッシュの配列。宣言と初期化。要素の参照。すべての要素の出力。 - Perl入門〜サンプルコードによるPerl入門〜から

foreach my $index (0...@{$response}-1 ) {
        foreach my $key ( keys %{ $response->[$index] } ){
                print $response->[$index]{$key},"\n";
        }
}

上記のコードを追加すると値が表示される。

twitux
0
0
Fri Jan 23 15:36:59 +0000 2009
@XXXX test post perl practice enjoy!
14431529
HASH(0xa5de1d8)
1142178554
Use of uninitialized value $value in print at
XXX

userの部分は、さらにハッシュのリファレンスが返ってくる。