随笔 而已,能力所限,只是个人看法。
就向大家看见的这样,由于多说服务器的原因,路杨正在逐步把 多说的评论写回本地 Movable Type 的数据库。
过程不算难。通过 API 获得 JSON 数据,分析后写入MT评论数据库罢了。
为了区分和拓展,给 MT 数据库的评论表增加了3行,分别记录 远程服务器名(remote_service
),远程服务器ID (remote_id
) 和 UA (
agent
)。
开始直接 Perl 脚本。核心代码为
code 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 )
{
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;
}
代码很随意,设置读取 200
条评论, 几乎瞬间写入 MySQL 数据库。
界面代码为: http://mt.easun.org/cgi-bin/Util/ds.cgi
登录 MT 后台,查看评论,发现所有的多说远程评论都乖乖的显示在了本地评论列表里面。
本来一切都 OK 了。 但是突想:既为什么不写成 MT 的插件呢, 这样可以利用 MT 自身封装的函数操作数据库,也不用硬编码进 MySQL 的用户名和密码。 说干就干。 其实有了 Perl脚本,改起来也很容易: 核心代码改写如下:
code 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->blog_id(2);
$comment->commenter_id(1) if ($ds->{'author_id'} =='11415448' ) ;
$comment->email($ds->{"author_email"} );
$comment->entry_id( int($ds->{"thread_key"}) );
$comment->ip( $ds->{"ip"} );
$comment->parent_id( &get_id_form_ds_id( $ds->{"parent_id"} ) );
$comment->text( $ds->{"message"} );
$comment->url( $ds->{"author_url"} );
$comment->visible(0) unless ($comment->id) ; # 0 代表 等待发布。 1代表直接发布
$comment->remote_id($ds->{"post_id"});
$comment->remote_service('DUOSHUO' );
$comment->agent($ds->{"agent"}) ;
$comment->save or die $comment->errstr;
}
代码的确简洁多了~~~~
在后台启用此插件。运行。。。、
浏览器漫长的等待,结果返回 504
。。。。。
My GOD .....
修改获取多说数据为 20
条,这次正常了。但是也几乎耗时5分钟。。。
MT 的代码太复杂了,几乎可以判断资源浪费在了 $comment->save
上,但是为什么不得而知。。
按理来说,同样是Perl脚本,同样是连接 MySQL 。为什么差别这么大呢? Movable Type 看来真的该减肥了。。
懒惰了。 就这样使用独立的 Perl 脚本了。
这次算是把 多说 的所有评论都反向同步到了本地,同时 将 http://mt.easun.org/cgi-bin/Util/ds.cgi
作为了多说系统的本地回调地址,这样,每次评论,都可以即时写进本地数据库。
PS: 顺手改了一下多说的 JS ,让它不*重复*显示已经同步并发表出来的多说评论, 仅仅显示没有发布出来的多说评论。
会编程,会perl,真好,能自己hack MT。
我觉得MT3是最简洁的,已经实现了大部分的功能,不过当时MTML没现在多……
MT3 的确不错,只是已经回不去了。。 至少跟着官方升级会避免一些大的安全漏洞。安全漏洞具体细节不公开,想自己修复也没有办法。
PS: 反正 6A 没有免费的 MT6 授权了。估计 MT5 会是绝响。。。
PPS: 用了 pjax 后,经常刷新不出新的本地评论。。。
6A的日本官网上可以免费下载6,最新版的6带了dataapi,有ios的app了。
嗯。 究竟不是正式授权。理论上只针对日本授权。
算了。还是继续5吧 :)
这个博客系统我还是第一次见到人用。
欢迎来访。
这个系统以前用的挺多。现在变小众了。
反向同步没有判断 blog_id 所以不适合多blog使用。