пятница, 11 сентября 2009 г.

Мои скрипты blogger2lj и twitter2vkontakte

Решил выложить свои скрипты для кросспостинга, а то многие просят.

Сперва Кросспостринг из твиттера на вконтакте. В настройках укажите логин/пароль от сервисов. Также понадодобятся модули Net::Twitter, WWW::Curl::Easy, WWW::Curl::Share, Text::Iconv,
У меня скрипт запускается по крону каждые 10 минут

twi2vk.pl

#!/usr/bin/perl
use strict;
use warnings;
use Net::Twitter;
use WWW::Curl::Easy;
use WWW::Curl::Share;
use URI::Escape;
use Text::Iconv;
use CGI;
use CGI qw /unescapeHTML/;

my $c = Text::Iconv->new('utf-8','utf-8');
my $q = new CGI;

my $twlogin = 'neptunix';
my $twpass = '';
my $vklogin = '';
my $vkpass = '';
my $debug = 0;
my $add = '';
#my $add = ' « http://twitter.com/neptunix »'; # Что добавить в конец сообщения


my $nt = Net::Twitter->new(
traints => [qw/API::REST/],
username => $twlogin,
password => $twpass
);

my $twitterStatus;
eval {
my $statuses = $nt->user_timeline({count => 20});
for my $status (@$statuses){
if ($status->{text} !~ m/^\@/){ # Убираем реплаи
$twitterStatus = "$status->{text}";
last;
}
}
};

if (my $err = $@) {
die $@ unless $err && $err->isa('Net::Twitter::Error');

warn "HTTP Response Code: ", $err->code, "\n",
"HTTP Message: ", $err->message, "\n",
"Twitter error: ", $err->error, "\n";
}

# Vkontakte

my $curlsh = new WWW::Curl::Share;
$curlsh->setopt(CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
$curlsh->setopt(CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);

# Setting the options
my $curl = new WWW::Curl::Easy;
$curl->setopt(CURLOPT_HEADER,1);
$curl->setopt(CURLOPT_URL, 'http://pda.vkontakte.ru/login?pda=index&acknowledge=0');
my $response_body = '';
open (my $fileb, ">", \$response_body);
$curl->setopt(CURLOPT_WRITEDATA,$fileb);
$curl->setopt(CURLOPT_SHARE, $curlsh);
$curl->setopt(CURLOPT_POST, 1);
$curl->setopt(CURLOPT_POSTFIELDS, "email=$vklogin&pass=$vkpass");

# Starts the actual request
my $retcode = $curl->perform;
# Looking at the results...
if ($retcode == 0) {
print("Transfer went ok\n") if($debug==1);
my $response_code = $curl->getinfo(CURLINFO_HTTP_CODE);
# judge result and next action based on $response_code
print("Received response: $response_body\n") if($debug==1);
} else {
print("An error happened: ".$curl->strerror($retcode)." ($retcode)\n");
exit 0;
}

# Request status edit form
$curl->setopt(CURLOPT_URL, 'http://pda.vkontakte.ru/status');
$curl->setopt(CURLOPT_POST, 0);
# Starts the actual request
$retcode = $curl->perform;
# Looking at the results...
if ($retcode == 0) {
print("Transfer went ok\n") if($debug==1);
my $response_code = $curl->getinfo(CURLINFO_HTTP_CODE);
# judge result and next action based on $response_code
print("Received response: $response_body\n") if($debug==1);
} else {
print("An error happened: ".$curl->strerror($retcode)." ($retcode)\n");
exit 0;
}

my $activityhash = '';
if($response_body =~ /name="activityhash" value="(\w+)"/){
$activityhash = $1;
} else {
print "An error happened: no activityhash found\n";
exit 0;
}

my $status = '';
if($response_body =~ /class="pad">\s+(.*)<br\/>/){
$status = $1;
} else {
print "An error happened: no status found\n";
exit 0;
}

if($status !~ /\.\.$/) {$status =~ s/(.*)\.$/$1/;}
$status =~ s/\S+\s+\S+\s+\S+\s+(.*)/$1/;
$status = unescapeHTML($status);

$twitterStatus = $c->convert($twitterStatus);

$twitterStatus .= $add;

if ($status eq $twitterStatus) {
if($debug) {print "Same status: $status\n";}
}

else {
if($debug) {
print "$status\n";
print "$twitterStatus\n";
}

## Update status
$curl->setopt(CURLOPT_URL, 'http://pda.vkontakte.ru/setstatus?pda=1');
$curl->setopt(CURLOPT_POST, 1);
$curl->setopt(CURLOPT_POSTFIELDS, 'activityhash=' . $activityhash . '&setactivity=' . uri_escape($twitterStatus));

# Starts the actual request
$retcode = $curl->perform;
if ($retcode == 0) {
print("Transfer went ok\n") if($debug==1);
my $response_code = $curl->getinfo(CURLINFO_HTTP_CODE);
# judge result and next action based on $response_code
print("Received response: $response_body\n") if($debug==1);
} else {
print("An error happened: ".$curl->strerror($retcode)." ($retcode)\n");
}

}



Постинг из Blogger в LiveJournal
Для работы нужно создать файл lastid.txt в той же директории (или прописать путь к нему), что и скрипт с правами на запись: touch lastid.txt;
chown user:user lastid.txt (user - пользователь от которого запускается скрипт)
У меня постинг работает по крону раз в сутки ночью
Здесь используются модули LJ::Simple, XML::FeedPP, Time::ParseDate

blogger2lj.pl

#!/usr/bin/perl
use strict; # Silly not to be
use POSIX; # For strftime()
use LJ::Simple;
use XML::FeedPP; # Parse Atom feed
use Time::ParseDate; # Parse date from feed

## Lj posting code taken from from ljpost

my $source = 'http://blogger.feed.source';
my $idfile = "lastid.txt";
my $user='lj-login';
my $pass='lj-pass';
my $post;
my $autoformat=0;
my $allowcomments=1;
my $add_to_post; # Эта переменная добавляется к посту. Определена ниже.

##
## Получаем фид и берем ID из файла
##
my $feed = XML::FeedPP->new( $source );

my $lastid; # Последний id

if(open(FILE, "$idfile")){
$lastid = readline(FILE);
chomp($lastid);
close(FILE);
}

# Просмотр списка на наличие ID и ищем его в файле


my @add; # Массив для добавления постов

foreach my $item ( $feed->get_item() ) {
my $id = $item->guid(); $id =~ s/.*post-(\d+)/$1/;
if ($id != $lastid) {
# Если новый id не соответствует старому - добавить в очередь на постинг (в массив $add)
push @add, $id;
}
else { last; }
}


##
## Начало цикла постинга в ЖЖ
##

my $last_good_id;
$|=1;
($LJ::Simple::VERSION<0.07) && ($LJ::Simple::timeout = 300);
my $lj = new LJ::Simple({ user=>$user,pass=>$pass });
(defined $lj) || die "$0: Failed to log into LJ - $LJ::Simple::error\n";


for(my $i=$#add; $i>=0; $i--){
foreach my $item ( $feed->get_item() ) {
my $id = $item->guid(); $id =~ s/.*post-(\d+)/$1/;
if($id == $add[$i]) { # Мы нашли наш пост. Будем его обрабатывать

my %Event=();
$lj->NewEntry(\%Event) || die "$0: Failed to prepare event - $LJ::Simple::error\n";

my $time = parsedate( $item->pubDate );
my(undef,$mins,$hrs,$dy,$mn,$yr,undef,undef,$l8)=localtime($time);

my $goodtime = mktime(0,$mins,$hrs,$dy,$mn,$yr,0,0,$l8);
$lj->SetDate(\%Event,$goodtime);

my $subject = $item->title();
($subject ne "") && $lj->SetSubject(\%Event,$subject);

my $tags;
if(ref($item->category())){
$tags = join (",", @{$item->category()});
}
else {
$tags = $item->category();
}
($tags ne "") && $lj->Setprop_taglist(\%Event,split(/,\s*/,$tags));

if ($autoformat) {
print "Autoformat: yes\n";
$lj->Setprop_preformatted(\%Event,1) ||
die "$0: Failed to set entry as preformatted - $LJ::Simple::error\n";
}

my $link = $item->link();
$add_to_post = <<END;
<br/>
<div style="position: relative; background-color: #b8daee; border: #98c6e2 1px dotted; padding: 5px; margin: 2px; text-align: center; clear:both">Запись опубликована в блоге blog.brigadirov.com. Лучше оставляйте свои комментарии <a href="$link">там</a>. Но можно и тут.</div>
END

my $post = $item->description();
$post .= $add_to_post;
$lj->SetEntry(\%Event,$post) ||
die "$0: Failed to set entry - $LJ::Simple::error\n";

if($allowcomments==0){
$lj->Setprop_nocomments(\%Event,1) ||
die "$0: Failed to set property - $LJ::Simple::error\n";
}
my ($item_id,$anum,$html_id)=$lj->PostEntry(\%Event);

if (defined $item_id) {$last_good_id = $id;}

(defined $item_id) ||
die "$0: Failed to post entry - $LJ::Simple::error\n";

}
}
}

if(defined $last_good_id) {
if(open(FILE, ">$idfile")){
print FILE $last_good_id;
close(FILE);
}
}

3 коммент.:

Victor комментирует...

Ох-ты)
Доброе дело делаете :) очень было интересно посмотреть код) Я тоже на перле свое пишу)

neptune комментирует...

Рад что пригодилось :)

Админчик комментирует...

А можно по пунктам рассказать, как пользоваться скриптом? Я просто в Perlе не силён. Мне б на ПХП...

Отправить комментарий