ishiducaの日記 このページをアンテナに追加 RSSフィード

2011-11-15

[][]AnyEventの文脈でFriendFeedに画像とか音声とかのファイルをポストする 14:19 AnyEventの文脈でFriendFeedに画像とか音声とかのファイルをポストする - ishiducaの日記 を含むブックマーク はてなブックマーク - AnyEventの文脈でFriendFeedに画像とか音声とかのファイルをポストする - ishiducaの日記 AnyEventの文脈でFriendFeedに画像とか音声とかのファイルをポストする - ishiducaの日記 のブックマークコメント

ポストするだけ。

feed馬鹿には FriendFeed は必須コンテンツなので、簡単になくなってもらうと困りますね。

post.pl

#!/usr/bin/env perl
use strict;
use warnings;
use MyApp::AnyEvent::FriendFeed;

my $message = "hogehoge";
my @files   = qw( path/to/image/1.jpg );

for my $file (@files) {
    die qq(! failed: "$file" not found) unless -e $file;
}

my %options = (
    file    => [ @files ],
    comment => 'comment of hogehoge',
);

my $client = MyApp::AnyEvent::FriendFeed->new(
    username => 'your username', remotekey => 'remotekey',
);

my $cv = AE::cv;

$client->post($message, %options, sub {
    my($response, $headers) = @_;

    if ($headers->{Status} ne '200') {
        warn qq(! failed $headers->{Status} $headers->{Reason}\n);
    }

    if ($response->{errorCode}) {
        warn qq(! failed $response->{errorCode}\n);
    }

    print join '\t',
        $response->{date},
        "(id: $response->{id})",
        "url: $response->{uri}",
        "$response->{body}\n";

    $cv->send;

});

$cv->recv;


今更だけど、Tatsumaki::HTTPClient をベースにしたほうが筋いいよね...orz

package MyApp::AnyEvent::FriendFeed;
use strict;
use warnings;
use Carp;
use AnyEvent;
use AnyEvent::HTTP;
use MIME::Base64;
use HTTP::Request::Common;
use HTTP::Request;
use JSON;

our $VERSION = '0.01';

my $api = 'http://friendfeed-api.com/v2/entry';

sub new {
    my $class = shift;
    my %args  = @_;

    $args{'username'}  || Carp::croak qq(! failed: "username" not found\n);
    $args{'remotekey'} || Carp::croak qq(! failed: "remotekey" not found\n);
 
    chomp(my $auth = MIME::Base64::encode( join ':', $args{username}, $args{remotekey}));

    bless {
        authorization => "Basic ${auth}",
    }, $class;
}

sub post {
    my $self = shift;
    my $body = shift || Carp::croak qq(! failed: "body" parameter not found\n);
    my $cb   = pop   || Carp::croak qq(! failed: "callback" not found\n);
    my %opts = @_;

    my $on_error  = delete $opts{on_error}  || sub { die @_; return; };
    my $on_header = delete $opts{on_header} || sub {
        my $headers = shift;
        unless ($headers->{Status} =~ /^2/) {
            $on_error->(qq(! failed: $headers->{Status} "$headers->{Reason}"\n));
            return;
        }
        return 1;
    };

    $opts{body} = $body;

    my @request_params = ($api,
        Authorization => $self->{authorization},
        Content       => \%opts
    );

    push @request_params, qw/Content_Type form-data/ if $opts{file};
    
    my $request = HTTP::Request::Common::POST(@request_params);

    my $p; $p = http_request('POST' => $api,
        headers   => $request->headers,
        body      => $request->content,
        on_header => $on_header,
        sub {
            undef $p;
            my($body, $headers) = @_;
            my $res = JSON::decode_json $body;
            $cb->($res, $headers);
        }
    );
}

1;

__END__

こっちにも https://gist.github.com/1366140

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20111115

2011-06-27

[][][]AnyEvent::HTTPでFrinedFeedにポストしてコケる(未解決->解決 6/28 0:33) 20:53 AnyEvent::HTTPでFrinedFeedにポストしてコケる(未解決->解決 6/28 0:33) - ishiducaの日記 を含むブックマーク はてなブックマーク - AnyEvent::HTTPでFrinedFeedにポストしてコケる(未解決->解決 6/28 0:33) - ishiducaの日記 AnyEvent::HTTPでFrinedFeedにポストしてコケる(未解決->解決 6/28 0:33) - ishiducaの日記 のブックマークコメント

(追記)ブックマークid:mattn さんから頂いたコメント

_authの最下行の手前に chomp $auth; 入れるときっと動くナリ

をやってみたら、ポスト出来ました。 id:mattn さんありがとうございます!

--

AnyEvent::HTTP(と Tatsumaki::HTTPClient)でFriendFeedBasic認証付きのポストをしようとするとステータスコード 404 が返ってきて、bodyパラメータが必要ですって言われる!

FriendFeedAPIのドキュメントは「FriendFeed API Documentation」にある。

use strict;
use AnyEvent;
use AnyEvent::HTTP;
use MIME::Base64;
use Data::Dumper;

my $api = 'http://friendfeed-api.com/v2/entry';

my $cv = AnyEvent->condvar;
http_request('POST' => $api,
    headers => {
	    'Authorization' => _auth('my username', 'my remotekey') 
    },
    body    => "body=test",
    sub {
        warn Dumper \@_;
        $cv->send;
    },
);

$cv->recv;
exit 0;

sub _auth {
    my($username, $remote_key) = @_;
    my $auth = MIME::Base64::encode(join(":", $username, $remote_key));
    chomp $auth; # add
    "Basic $auth";
}

結果: 401が返ってきてないから、Basic認証は通ってるけど、errorCode で "body-required" って言ってるので、リクエストボディに問題があるっぽい。ちなみにFriendfeedAPIではリクエストボディに必ず body パラメータが必要で、それがリクエストボディに記述がないってエラーコードなんだけど、、、リクエストボディの送信ができてないのか、それともリクエストボディの記述が間違いなのか?

$VAR1 = [
          '{"errorCode":"body-required"}',
          {
            'URL' => 'http://friendfeed-api.com/v2/entry',
            'connection' => 'close',
            'set-cookie' => 'HASFF=1; Path=/,AT=3295780562084656563_1309173742; Path=/',
            'Status' => '404',
            'HTTPVersion' => '1.1',
            'date' => 'Mon, 27 Jun 2011 11:22:22 GMT',
            'content-length' => '29',
            'Reason' => 'Not Found',
            'content-type' => 'text/javascript; charset=UTF-8',
            'server' => 'FriendFeedServer/0.1'
          }
        ];

AnyEvent::HTTPのラッパーの Tatsumaki::HTTPClient を使ってみる

my $client = Tatsumaki::HTTPClient->new;

my $cv = AnyEvent->condvar;
$client->post(
    $api,
    [ body => 'TEST' ],
    Authorization => _auth('my username', 'my remotekey'), 
    sub {
        warn Dumper shift;
        $cv->send;
    }
);

$cv->recv;
exit 0;

結果: 同じ結果

$VAR1 = bless( {
      '_content' => '{"errorCode":"body-required"}',
      '_rc' => '404',
      '_headers' => bless( {
           'connection' => 'close',
           'set-cookie' => 'HASFF=1; Path=/,AT=2762172806905182125_1309174542; Path=/',
           'date' => 'Mon, 27 Jun 2011 11:35:42 GMT',
           'status' => '404',
           'reason' => 'Not Found',
           'httpversion' => '1.1',
           'content-length' => '29',
           'content-type' => 'text/javascript; charset=UTF-8',
           'url' => bless( do{\(my $o = 'http://friendfeed-api.com/v2/entry')}, 'URI::http' ),
           'server' => 'FriendFeedServer/0.1'
         }, 'HTTP::Headers' ),
      '_msg' => 'Not Found'
    }, 'HTTP::Response' );

ちなみに

  • LWP::UserAgent を使うとポストできる
  • 他のコンテンツへのポストは成功している

yamada-22yamada-222011/06/28 00:17リクエストのContent-Typeがapplication/x-www-form-urlencodedになっていない

yamada-22yamada-222011/06/28 00:22ああ!MIME::Base64::encodeが改行を付けてくれるんだw
MIME::Base64::encode('user:password', '')

DrewDrew2012/06/07 21:10Kick the tires and light the fires, pobrlem officially solved!

agxmfhaagxmfha2012/06/09 21:02Io5KaW <a href="http://fyaycxcrdhjp.com/">fyaycxcrdhjp</a>

cispuamcispuam2012/06/11 04:218CoSjX , [url=http://bjktioecdzru.com/]bjktioecdzru[/url], [link=http://oflrgnwvwvst.com/]oflrgnwvwvst[/link], http://tjepxvynitpm.com/

bzjdqwzbflbzjdqwzbfl2012/06/13 10:29UmydyD , [url=http://wyoyiunnomhj.com/]wyoyiunnomhj[/url], [link=http://vgnlnayohkwz.com/]vgnlnayohkwz[/link], http://iqvgphlofwhj.com/

トラックバック - http://perl.g.hatena.ne.jp/ishiduca/20110627