<p>随笔 而已,能力所限,只是个人看法。</p>
<p>就向大家看见的这样,由于多说服务器的原因,路杨正在逐步把 多说的评论写回本地 Movable Type 的数据库。</p>
<p>过程不算难。通过 API 获得 JSON 数据,分析后写入MT评论数据库罢了。
为了区分和拓展,给 MT 数据库的评论表增加了3行,分别记录 远程服务器名(remote_service
),远程服务器ID (remote_id
) 和 UA (agent
)。</p>
<p>开始直接 Perl 脚本。核心代码为</p>
sub check_ds_comments {
my $list_ref;
my $log_id;
foreach my $a(@{$response} ) {
my $act = $a->{'action'};
if ( $act eq 'create') { my $ds = $a->{'meta'}; my $ds_id= $ds->{"post_id"}; $list_ref->{$ds_id} = $ds; }
else
{
foreach my $var ( @{$a->{'meta'}} ) { $list_ref->{$var}->{'status'} = ($act eq 'approve') ? 'approved' : $act ; }
}
$log_id = $a->{'log_id'};
}
my $str;
my $nos = 0;
my @ids =sort {$a <=> $b} keys %$list_ref;
foreach my $ids ( @ids )
{
# print "<br>$ids:n<br>";
my $dscs = $list_ref->{$ids};
print "<br>t$ids => $dscs->{'status'} n<br>";
next if ( ($dscs->{'status'} eq 'delete-forever') || ($dscs->{'status'} eq 'delete') || ($dscs->{'status'} eq 'spam'));
next if ($dscs->{"thread_key"} !~ /^\d+$/);
&import_comments($dscs);
$nos ++;
}
$str .= "<p>信息:</p>" ;
$str .= "<br>last_log_id=" .$log_id;
$str .= "<br>共有有效评论 " .$nos ." 条。OK!!!!<br>";
print $str;
}
sub import_comments {
my $ds = shift ;
print "<ul><li>--正常评论,开始处理----------------------------</li>";
print "<li>信息如下:<br />";
print "thread_key =". $ds->{"thread_key"}. "<br />";
print "post_id =". $ds->{"post_id"}. "<br />";
print "author_name =". $ds->{"author_name"}. "<br />";
print "message =". $ds->{"message"};
print "</li>";
print "<li>检查 id=". $ds->{"post_id"} ." 的多说评论是否存在于本地数据库</li>" ;
my $comment_id = &get_id_form_ds_id( $ds->{"post_id"},'no_output'); # comment_parent_id# ,
if ( $comment_id ne 'NULL' )
{
print "<li>这条多说评论已经存在。 本地数据库中 id=". $comment_id ."</li>" ;
print "</ul>" ;
return;
}
else { print "<li>没有在本地数据库中检查到这条评论,准备写入本地数据库..........</li>"; }
my $blog_id = 2;
my $mt_id = ($ds->{'author_id'} =='11415448' )? 1 : 'NULL';
&c_to_c($ds->{"message"});
&c_to_c($ds->{"agent"});
my $str ='INSERT INTO mt_comment
(comment_id
, comment_author
, comment_blog_id
, comment_commenter_id
, comment_created_by
, comment_created_on
, comment_email
, comment_entry_id
, comment_ip
, comment_junk_log
, comment_junk_score
, comment_junk_status
, comment_last_moved_on
, comment_modified_by
, comment_modified_on
, comment_parent_id
, comment_text
, comment_url
, comment_visible
, comment_remote_id
, comment_remote_service
, comment_agent
) VALUES
(';
$str .=$comment_id .',';# comment_id# ,
$str .='"'. $ds->{"author_name"} .'",'; # comment_author# ,
$str .='2,' ; # comment_blog_id# ,
$str .= $mt_id .','; #$ds->{"mt_author_id"}.','; # comment_commenter_id# ,
$str .='NULL,'; # comment_created_by# ,
$str .='"'. $ds->{"created_at"} .'",'; # comment_created_on# ,
$str .='"'. $ds->{"author_email"} .'",'; # comment_email# ,
$str .=int($ds->{"thread_key"}) .','; # comment_entry_id# ,
$str .='"'. $ds->{"ip"} .'",'; # comment_ip# ,
$str .='NULL,'; # comment_junk_log# ,
$str .='NULL,'; # comment_junk_score# ,
$str .='1,'; # comment_junk_status# ,
$str .="'2000-01-01 00:00:00',"; # comment_last_moved_on# ,
$str .='NULL,'; # comment_modified_by# ,
$str .='NULL,'; # comment_modified_on# ,
$str .= &get_id_form_ds_id( $ds->{"parent_id"} ).','; # comment_parent_id# ,
$str .="'". $ds->{"message"} ."',"; # comment_text# ,
$str .="'". $ds->{"author_url"} ."',"; # comment_url# ,
$str .='0,'; # comment_visible# , # 0 代表 等待发布。 1代表直接发布
$str .=$ds->{"post_id"}.','; # comment_remote_id# ,
$str .='"DUOSHUO",' ; # comment_remote_service# \
$str .='"'. $ds->{"agent"}. '"'; # comment_created_on# ,
$str .=');' ;
print "<li>";
print "str: n<br />";
print $str." n</li>";
my $rows = $dbh->do($str) or die "Can't execute sql: ".$dbh->errstr."n";
print "</ul>" ;
}
# 转码符号
sub c_to_c
{
my $str = shift ;
$$str =~ s/'/\'/gs;
$$str =~ s/"/\"/gs;
$$str =~ s/,/\,/gs;
$$str =~ s/;/\;/gs;
}
# 检查是否存在此条评论
sub get_id_form_ds_id
{
my $dsparent_id = shift ;
my $no_output = shift ;
unless ($no_output) { print "<br />dsparent_id -> comment_id \n<br />dsparent_id = ". $dsparent_id ."n<br />"; }
my $delim = 'NULL';
my $sql= "select comment_id
from mt_comment
where comment_remote_id
='". $dsparent_id ."'";
my $sth = $dbh->prepare($sql); #准备
$sth->execute() or die "Cannot execute: " . $sth->errstr(); #执行
while (my @result = $sth->fetchrow_array) {
$delim = @result[0];
}
$sth->finish;#结束句柄
unless ($no_output) { print '<br>检查到id=' . $delim. "n<br />"; }
$delim;
}
<p>代码很随意,设置读取 200
条评论, 几乎瞬间写入 MySQL 数据库。
界面代码为: http://mt.easun.org/cgi-bin/Util/ds.cgi</p>
<p>登录 MT 后台,查看评论,发现所有的多说远程评论都乖乖的显示在了本地评论列表里面。</p>
<p>本来一切都 OK 了。 但是突想:既为什么不写成 MT 的插件呢, 这样可以利用 MT 自身封装的函数操作数据库,也不用硬编码进 MySQL 的用户名和密码。 说干就干。 其实有了 Perl脚本,改起来也很容易:
核心代码改写如下:</p>
sub check_ds_comments {
my $app = shift ;
my $response = shift ;
my $list_ref;
my $log_id;
foreach my $a(@{$response} ) {
my $act = $a->{'action'};
if ( $act eq 'create') { my $ds = $a->{'meta'}; my $ds_id= $ds->{"post_id"}; $list_ref->{$ds_id} = $ds; }
else
{
foreach my $var ( @{$a->{'meta'}} ) { $list_ref->{$var}->{'status'} = ($act eq 'approve') ? 'approved' : $act ; }
}
$log_id = $a->{'log_id'};
}
my $str;
my $nos = 0;
my @ids =sort {$a <=> $b} keys %$list_ref;
foreach my $ids ( @ids )
{
# print "<br>$ids:n<br>";
my $dscs = $list_ref->{$ids};
$str .= "<br>\t$ids => $dscs->{'status'} n<br>";
next if ( ($dscs->{'status'} eq 'delete-forever') || ($dscs->{'status'} eq 'delete') || ($dscs->{'status'} eq 'spam'));
next if ($dscs->{"thread_key"} !~ /^\d+$/);
&import_comments($dscs);
$nos ++;
}
$str .= "<p>信息:</p>" ;
$str .= "<br>last_log_id=" .$log_id;
$str .= "<br>共有有效评论 " .$nos ." 条。OK!!!!<br>";
return $app->error($str);
}
sub import_comments {
my $ds = shift ;
require MT::Comment;
my @comments = MT::Comment->load(
{ remote_service =>'DUOSHUO', remote_id=>$ds->{"post_id"},},
{ sort => 'created_on', direction => 'ascend',}
);
my $comment = @comments[0] || MT::Comment->new;
my $str ;
if ( $comment->id )
{
$str= "<li>这个多说评论已经存在。 数据库中 id=". $comment->id ."</li>" ;
return;
}
else { $str .= "<li>没有检查到这个评论,准备写入...........</li>"; }
$comment->author($ds->{"author_name"} );# comment_ author# ,
$comment->blog_id(2); # comment_ blog_id# ,
$comment->commenter_id(1) if ($ds->{'author_id'} =='11415448' ) ; # comment_ commenter_id# ,
$comment->email($ds->{"author_email"} ); # comment_ email# ,
$comment->entry_id( int($ds->{"thread_key"}) ); # comment_ entry_id# ,
$comment->ip( $ds->{"ip"} ); # comment_ ip# ,
$comment->parent_id( &get_id_form_ds_id( $ds->{"parent_id"} ) ); # comment_ parent_id# ,
$comment->text( $ds->{"message"} ); # comment_ text# ,
$comment->url( $ds->{"author_url"} ); # comment_ url# ,
$comment->visible(0) unless ($comment->id) ; # comment_ visible# , # 0 代表 等待发布。 1代表直接发布
$comment->remote_id($ds->{"post_id"}); # comment_ remote_id# ,
$comment->remote_service('DUOSHUO' ); # comment_ remote_service# \
$comment->agent($ds->{"agent"}) ; # comment_ agent# ,
$comment->save or die $comment->errstr;
}
<p>代码的确简洁多了~~~~</p>
<p>在后台启用此插件。运行。。。、
浏览器漫长的等待,结果返回 504
。。。。。</p>
<p>My GOD .....
修改获取多说数据为 20
条,这次正常了。但是也几乎耗时5分钟。。。</p>
<p>MT 的代码太复杂了,几乎可以判断资源浪费在了 $comment->save
上,但是为什么不得而知。。</p>
<p>按理来说,同样是Perl脚本,同样是连接 MySQL 。为什么差别这么大呢? Movable Type 看来真的该减肥了。。</p>
<p>懒惰了。 就这样使用独立的 Perl 脚本了。</p>
<p>这次算是把 多说 的所有评论都反向同步到了本地,同时 将 http://mt.easun.org/cgi-bin/Util/ds.cgi
作为了多说系统的本地回调地址,这样,每次评论,都可以即时写进本地数据库。</p>
<p>PS: 顺手改了一下多说的 JS ,让它不重复显示已经同步并发表出来的多说评论, 仅仅显示没有发布出来的多说评论。</p>