【发布时间】:2019-01-06 22:34:10
【问题描述】:
有没有人成功地将媒体上传到 Twitter,即使用 Perl 发布带有图片的推文?
我想从我的博客上传图片,而不是手动完成。
update_with_media(status, media[]) 已弃用并崩溃。 Twitter 说要使用普通的 update(),传递一个媒体 ID。但是需要先上传媒体来获取id,我找不到代码示例。
有这方面的经验吗?
干杯, 彼得
【问题讨论】:
有没有人成功地将媒体上传到 Twitter,即使用 Perl 发布带有图片的推文?
我想从我的博客上传图片,而不是手动完成。
update_with_media(status, media[]) 已弃用并崩溃。 Twitter 说要使用普通的 update(),传递一个媒体 ID。但是需要先上传媒体来获取id,我找不到代码示例。
有这方面的经验吗?
干杯, 彼得
【问题讨论】:
我想我会在这里添加一个更新,即使这个帖子已经很老了。我也在寻找如何使用 Perl 将媒体上传到 twitter 的答案。
Net::Twitter 完全能够将 PNG 图像发送到 Twitter,尽管文档很差。 OP 是正确的,update_with_media 已被弃用并为我们崩溃。
您确实需要结合使用 $nt->upload 和 $nt->update 方法。您上传了用 base64 编码的 RAW PNG 文件,我无法让 RAW PNG 文件上传工作,但 base64 编码时没有问题。上传方法成功时返回一个 JSON 结构,其中包含 media_ids。然后这些 id 与 $nt->update 方法一起传递。这是一些实际的代码
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 文档。
罗伯
【讨论】:
最后我使用了带有 twurl 的 readpipe。如果我一开始就知道 twurl,我可能不会打扰 Net::Twitter! twurl 效果很好,它会返回一个完整的 json 字符串来告诉你出了什么问题(如果有的话)。
【讨论】:
先决条件:您需要为您的 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 Jimtweet; 行之前添加行 use lib "/home/your/path/to/jimtweet/directory;"。
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
【讨论】: