Upload media to twitter using perl

时间:2015-07-08 15:39:04

标签: perl twitter media

Has anyone successfully uploaded media to Twitter, ie posted a tweet with an image using Perl?

I would like to upload images from my blog without doing it all manually.

update_with_media(status, media[]) is deprecated, and crashes. Twitter says to use plain update(), passing a media id. However it is first necessary to upload the media to get the id, and I can find no code examples.

Any experience in this area?

Cheers, Peter

3 个答案:

答案 0 :(得分:2)

我以为我会在这里添加更新,即使该帖子已经很老了。我也在寻找如何使用Perl将媒体上传到twitter的答案。

Net :: Twitter完全能够将PNG图像发送到Twitter,尽管文档很差。 OP是正确的,不推荐使用update_with_media并为我们崩溃。

您确实需要使用$ nt->上传AND $ nt->更新方法。你上传用base64编码的RAW PNG文件,我无法上传RAW PNG文件,但在base64编码时没有问题。成功时,upload方法返回一个包含media_ids的JSON结构。然后使用$ nt-> update方法传递这些id。这是一些实际的代码

use Net::Twitter;
use File::Slurp;
use MIME::Base64;
use Data::Dumper;

my $nt = Net::Twitter->new(
    ssl      => 1,
    traits   => [qw/API::RESTv1_1/],
    consumer_key        => $config->{twitter}{api_key},
    consumer_secret     => $config->{twitter}{api_secret},
    access_token        => $config->{twitter}{access_token},
    access_token_secret => $config->{twitter}{access_token_secret},
    );

my $filename = "<somelink to a PNG file>";
my $file_contents = read_file ($filename , binmode => ':raw');

my $status = $nt->upload(encode_base64($file_contents));
print "SendTweet: status = ".Dumper($status);

my $status2;

eval {
    $status2 = $nt->update({status => $s , media_ids => $status->{media_id} });
    print "status2 = ".Dumper($status2);
};

if ($@)
{
    print "Error: $@\n";
}

代码是直接从我们的工作测试代码中提取的,所以应该可行。此代码纯粹是概念证明,因此您需要添加所有Twitter身份验证等。

我们只完成了PNG文件,但我认为没有理由为什么视频等不能正常工作,因为我们只是按照Twitter文档。

罗布

答案 1 :(得分:0)

最后我用了twurl的readpipe。如果我在第一时间知道twurl,我可能不会对Net :: Twitter感到困扰! twurl工作得很好,并返回一个完整的json字符串,告诉你出了什么问题,如果有的话。

答案 2 :(得分:0)

前提条件:您需要获取Twitter帐户的Oauth密钥。 (请参阅此处-https://developer.twitter.com/en/docs/basics/authentication/guides/access-tokens.html)。其他地方的一些在线示例也可以提供帮助。

这是我最终得到的代码。

首先调用tweet模块(顺便说一句,这些不是有效的密钥-只需插入您的密钥即可)

use Jimtweet;

my $tweet=Jimtweet->new();

$tweet->consumer_key('KvfevhjwkKJvinvalidkeycvhejwkKJVCwe');
$tweet->consumer_secret('KvfevhjwkKJvcvnvalidkeyhejwkKJVCwe'); 
$tweet->oauth_token('KvfevhjwkKJvcvhenvalidkeyjwkKJVCwKvfevhjwkKJvcvhejwkKJVCweVU');
$tweet->oauth_token_secret('KvfevhjwkKJvcvhejwnvalidkeykKJVCwe');

my $res = $tweet->update_status($message, $ENV{DOCUMENT_ROOT}.$li);

Jimtweet是我在网上找到的免费模块(我忘了在哪里),但是我必须对其进行修改才能上传图像。如下。 $message是要发送的文本状态消息 $li包含我要上传的文件的本地路径。这是服务器上的本地文件。 $ENV{DOCUMENT_ROOT}包含我网站上公共HTML文件的服务器路径。

$res包含来自twitter的JSON答复,您可以根据需要查看。

如果要使用此功能,请剪切并粘贴“ package Jimtweet;”中的所有内容然后进入上述代码应使用的名为Jimtweet.pm的文件中。如果您的perl安装找不到模块,请尝试在use lib "/home/your/path/to/jimtweet/directory;"行之前添加use Jimtweet;行。

Twitter要求上传图片,然后返回media_id,然后在要发布的常规消息中包含media_id。请参见下面的Jimtweet软件包:

package Jimtweet;
#####JimTweet 0.1 By James Januszka 2010
#####Email:jimjanuszka@gmail.com
#####Twitter:@jamesjanuszka
#####Modifications by John Bell to include image upload. Twitter: @BellUkcbajr
use strict;
use warnings;
use LWP;
use HTTP::Headers;
use URI::Encode qw(uri_encode);
use URI::Escape qw(uri_escape);
use Digest::HMAC_SHA1;

####Constructor####
sub new {
    my $self={};
    $self->{OAUTH_VERSION}=uri_escape("1.0");
    $self->{OAUTH_SIGNATURE_METHOD}=uri_escape("HMAC-SHA1");
    $self->{OAUTH_TIMESTAMP}=undef;
    $self->{OAUTH_NONCE}=undef;
    $self->{AGENT}="jimtweet/0.1";

#####################
#Use this for status updates
    $self->{URLx}="https://api.twitter.com/1.1/statuses/update.json";

#####################
#Use this for image upload
    $self->{URL}="https://upload.twitter.com/1.1/media/upload.json";

    $self->{BROWSER}=LWP::UserAgent->new(agent =>$self->{AGENT});
    $self->{CONSUMER_KEY}=undef;
    $self->{CONSUMER_SECRET}=undef;
    $self->{OAUTH_TOKEN}=undef;
    $self->{OAUTH_TOKEN_SECRET}=undef;
    $self->{STATUS}=undef;
    $self->{MEDIAurl}=undef;
    bless($self);
    return $self;
} 

sub consumer_key{
    my $self=shift;
    if (@_) { $self->{CONSUMER_KEY}=uri_escape(shift) }
    return $self->{CONSUMER_KEY};
}

sub consumer_secret{
    my $self = shift;
    if (@_) { $self->{CONSUMER_SECRET}=uri_escape(shift) }
    return $self->{CONSUMER_SECRET};
}

sub oauth_token{
    my $self = shift;
    if (@_) { $self->{OAUTH_TOKEN}=uri_escape(shift) }
    return $self->{OAUTH_TOKEN};
}

sub oauth_token_secret{
    my $self = shift;
    if (@_) { $self->{OAUTH_TOKEN_SECRET}=uri_escape(shift) }
    return $self->{OAUTH_TOKEN_SECRET};
}

sub update_status(@){
    sleep(2);
    my $self = shift;
    if (@_) { $self->{STATUS}=uri_escape(shift) }
    if (@_) { $self->{MEDIAurl}=shift }


#Got parameters. Now create the POST to upload an image

    my $seconds = time(); 
    $self->{OAUTH_TIMESTAMP}=uri_escape($seconds);
    $self->{OAUTH_NONCE}=$self->{OAUTH_TIMESTAMP};

#####################
#Use this for uploads. Parameters have to be in alphabetical order! 
    my $query=qq(oauth_consumer_key=$self->{CONSUMER_KEY}&oauth_nonce=$self->{OAUTH_NONCE}&oauth_signature_method=$self->{OAUTH_SIGNATURE_METHOD}&oauth_timestamp=$self->{OAUTH_TIMESTAMP}&oauth_token=$self->{OAUTH_TOKEN}&oauth_version=$self->{OAUTH_VERSION});

    my $sig="POST&";

    $sig .=uri_encode($self->{URL},1);
    $sig .="&";
    $sig .=uri_encode($query,1);

    my $sig_key=$self->{CONSUMER_SECRET};
    $sig_key .="&";
    $sig_key .=$self->{OAUTH_TOKEN_SECRET};

    my $hmac = Digest::HMAC_SHA1->new($sig_key);
    $hmac->add($sig);

    my $oauth_signature_base64=$hmac->b64digest;
    $oauth_signature_base64 .="=";

    my $utf8_oauth_signature_base64=uri_escape($oauth_signature_base64);

    my $header=qq(OAuth oauth_nonce="$self->{OAUTH_NONCE}", oauth_signature_method="$self->{OAUTH_SIGNATURE_METHOD}", oauth_timestamp="$self->{OAUTH_TIMESTAMP}", oauth_consumer_key="$self->{CONSUMER_KEY}", oauth_token="$self->{OAUTH_TOKEN}", oauth_signature="$utf8_oauth_signature_base64", oauth_version="$self->{OAUTH_VERSION}");

    my $res = $self->{BROWSER}->post( 
        $self->{URL}, 
        'Authorization' => $header, 
        'content-type' => 'form-data', 
        'Content' => [ media => ["$self->{MEDIAurl}"] ]    
    );

    use JSON;
    my $response = decode_json  ($res->content);
    my $media_id = $response->{'media_id'};

    $seconds = time(); 
    $self->{OAUTH_TIMESTAMP}=uri_escape($seconds);
    $self->{OAUTH_NONCE}=$self->{OAUTH_TIMESTAMP}


    my $queryx=qq(media_ids=$media_id&oauth_consumer_key=$self->{CONSUMER_KEY}&oauth_nonce=$self->{OAUTH_NONCE}&oauth_signature_method=$self->{OAUTH_SIGNATURE_METHOD}&oauth_timestamp=$self->{OAUTH_TIMESTAMP}&oauth_token=$self->{OAUTH_TOKEN}&oauth_version=$self->{OAUTH_VERSION}&status=$self->{STATUS});

    my $sigx="POST&";

    $sigx .=uri_encode($self->{URLx},1);
    $sigx .="&";
    $sigx .=uri_encode($queryx,1);

    my $hmacx = Digest::HMAC_SHA1->new($sig_key);
    $hmacx->add($sigx);

    my $oauth_signature_base64x=$hmacx->b64digest;
    $oauth_signature_base64x .="=";

    my $utf8_oauth_signature_base64x=uri_escape($oauth_signature_base64x);

    my $headerx=qq(OAuth oauth_nonce="$self->{OAUTH_NONCE}", oauth_signature_method="$self->{OAUTH_SIGNATURE_METHOD}", oauth_timestamp="$self->{OAUTH_TIMESTAMP}", oauth_consumer_key="$self->{CONSUMER_KEY}", oauth_token="$self->{OAUTH_TOKEN}", oauth_signature="$utf8_oauth_signature_base64x", oauth_version="$self->{OAUTH_VERSION}");

#And done generating content. Now to POST to twitter. 

    $res = $self->{BROWSER}->post( 
        $self->{URLx},
        'Authorization' => $headerx, 
        'content-type' => 'application/x-www-form-urlencoded', 
        'Content' => qq(media_ids=$media_id&status=$self->{STATUS}) 
    );

    return $res;
}

####Footer####
1;  #so the require or use succeeds