记弃用多说牵扯出来的一堆坑

由于多说近期极不稳定而且严重影响站点加载速度,最终咱还是把多说撤了。

于是因此扯出来了一堆坑……

先送歌单,鉴于最近有人说自动播放不太友好咱就不设置自动播放喽,不过我还是觉得听歌比较带感啊←_←

总览

“关插件一时爽,DEBUG火葬场。” 这句话也许最能体现这几天的情况。
在撤出多说评论后,lwl与朋友们 (如 @fly @kn007 @ClassicOldSong @Bing )一起工作了三天时间,最后解决了如下几个问题集合

  • 撤除多说后的回复以及审核通知
  • 主题原生评论与强行加上去的 Ajax Load Page 功能的兼容性问题
  • 多说带来的历史遗留问题

 

其中前两点调试过程各位可以移步留言板感受一下,然后应该就能有个大概的了解了 🙂

这篇文章主要是摘取几点我觉得各位也有可能遇到的问题讲讲解决方案,所以牢骚在前面发完,下面直接开始 show code.

 

 

关于使用多说期间 User-Agent 数据的回写

多说的 WordPress 插件众所周知是有一个自动往本地数据库回写的功能的,也是这个功能让不少站长很开心的入了坑。然而有一个比较坑的地方是,这个回写并不会把正确的 User-Agent 写到本地数据库,而是用一个 “Duoshuo/1.2:0000000000000000000” 这样的字符串来代替。所以如果你把多说给撤了,那么不做处理的话这些 UA 数据就是相当于丢了。

啊我当然不可能允许这种事发生喽,所以写了一个 Python 程序来解决这个问题。

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import sys
import MySQLdb
import requests
import json

reload(sys)
sys.setdefaultencoding('utf-8')

import requests

url = "https://你的多说管理后台前缀.duoshuo.com/api/posts/list.json"

querystring = {"order": "asc", "max_depth": "0",
               "limit": "你的总计评论数再往上加个几百保险就差不多", "nonce": "请自行查找本参数"}

headers = {
    'cookie': "duoshuo_unique=这个值……别告诉我你不会找cookie"
}

response = requests.request("GET", url, headers=headers, params=querystring)
replydata = json.loads(response.text)["parentPosts"]

# 打开数据库连接
db = MySQLdb.connect("数据库链接地址", "用户名", "密码",
                     "wordpress所在库名", charset='utf8')
# 使用cursor()方法获取操作游标
cursor = db.cursor()

#如果你更改了wordpress默认表前缀,请务必修改以下的表名 wp_comments 
sql = "SELECT `comment_ID`,`comment_agent` FROM `wp_comments` WHERE `comment_agent` LIKE 'duoshuo%'"
cursor.execute(sql)
results = cursor.fetchall()
for row in results:
    dsid = row[1].split(":")[1]
    print str(dsid)
    print str(row[0])
    try:
        if replydata[dsid]["agent"]:
            print replydata[dsid]["agent"]
            try:
                cursor.execute("UPDATE `wp_comments` SET `comment_agent` = '" + replydata[dsid][
                               "agent"] + "' WHERE `wp_comments`.`comment_ID` = " + str(row[0]) + ";")
            except BaseException as x:
                print x
                db.rollback()
                exit()
    except BaseException as e:
        print e


try:
    db.commit()
except BaseException as e:
    print e
    db.rollback()
    exit()

# 关闭数据库连接
db.close()

以上代码里参数 nonce 的查找方法是,用 Chrome 打开 https://你站点多说域名/admin/approved/ ,打开开发者工具,切换到network选项卡,在搜索框里写上“list”然后刷新,接着左边栏应该会有一个list.json的文件,点击并在打开的右栏完整url里找到nonce参数复制到代码里即可。

至于其他的修改点我都一并写代码里了,使用的时候记得注意替换,如果代码执行有问题也别在评论区问(雾)

评论通知

其实这个大家应该都很清楚我采用的解决方案了呢,显然还是用邮件……但是现在的各类评论回复插件都不是很满足我的需求。所以咱和 @kn007 一起重新改(luan)写了一个评论回复与通过审核的通知函数。具体函数我就不贴了,这次重写主要就做了这三件微小的事情:

  • 对纯文本版本+HTML版本的多版本邮件做了一个支持
  • 用一个和反正你现在在网上找不着的方法强制限定了 WordPress 的发件人(也就是 From: ) 信息
  • 用一个还凑合的方法解决了 Gmail 在合并会话的时候自动识别重复内容然后强行加 破坏邮件结构的问题

很惭愧。

其中前两点我使用了一个似乎比较偏门的 WordPress Action 挂载点 phpmailer_init,从而比较好的绕过了整个一点用都没有辣鸡的不行七年前的BUG还留着的WP_MAIL函数来做一些高级修改。这里就直接简单的贴一下代码(虽然写的时候并不简单(可能是因为我不是菊苣))。

多版本邮件:这个功能主要是因为我和 kn 都是使用的自建邮件服务器(这里面门道也不少,回头可能有空出一篇文章单独说说),为了保证到信率而且同时给收件人那边体验好一点。代码如下

//Hook phpmailer init action, then force change message_type to alt.
global $phpmailer;
add_action('phpmailer_init', function (&$phpmailer) use ($message_html, $message_plain) {
    $phpmailer->isHTML(true);
    $phpmailer->Body = $message_html;
    $phpmailer->AltBody = $message_plain;
    $phpmailer->CharSet = 'utf-8';
    $phpmailer->Encoding = 'base64';
});
wp_mail("$parent_comment_author <$to>", $subject, $message_html, $headers); //There <$message_html> is just for backup, you can't change content after add_action().

其实原理也是非常的简单,这个 action 在 WP_MAIL 里被执行的位置是发送函数的前一句,所以通过这个点插进去直接操作比 WP_MAIL 强大的多的 phpmailer 就能够实现很多高级功能。使用这个代码之后正如注释所述,实际上向 WP_MAIL 函数传递的内容就不重要了,最终是通过上方代码直接重新赋给 phpmailer 的内容进行发送。

这段代码是单独从完整函数里拎出来的,所以你并不能直接使用它,如果要用的话按照这个代码改改应该差不多也能用……总之可以自己钻研一下啦,这里只是介绍一下有这么个方法。

限定发件人这个就更简单了,强行限定的原因是因为我用 WordPress 自带的几个 filter 发现根本不管用啊,所以没办法只好用暴力一点的方案解决问题了。这个代码是可以直接用的,你改改地址扔你主题的 function.php 里就行。

global $phpmailer;
add_action('phpmailer_init', function (&$phpmailer) {
   $phpmailer->From = "期待的发送邮箱地址";
   $phpmailer->FromName = "发件人名称";
});

第三点 Gmail 这件事,是一个坑…… 可劲折腾了大概有一天之后才发现具体原因。

在 Gmail/Inbox 当中,会自动将主题相同的邮件合并成一个会话。当然你合并没关系,只是它们会自动将后续邮件内容和前序邮件比对,如果有内容相同的行,就加上一个样式(在 Gmail 里是变紫,在 Inbox 里更惨,会加一个折叠按钮……而且严重破坏邮件结构)

很好,现在知道问题了,然而尝试了很久也没办法优雅的绕过,只能用了一个土方法。我们在邮件可能重复的每一行后面加上了一个 display:none 而且颜色设置和背景一致的 span,在span里放上一个随机的五位代码,从而干扰自动检测。这个方法在本站用着挺舒服的,也没出啥问题,根本看不出来。然而 kn 的站有点小尴尬,他的站邮件前面内容太少了于是在某些客户端里显示预览(忽略html)的时候直接把干扰码显示出来……所以……是……土方法……嘛……(逃

历史遗留问题?

其实这个也没什么,就是之前多说评论启用了表情,然后之前 HTTPS 代理替换原 url 的操作是在 js 里操作的,多说下掉之后原有的表情就全变成 http 导致我可爱的小绿锁和安全标志掉了。如果你也有一个 https 图片反代的话,将下列代码放入正在使用主题的 function.php 中即可解决问题

function comment_pic_https($commentdata)
{
    return preg_replace('/src=(["|\'])http:\/\//', 'src="//Your_Proxy_Url/http://', $commentdata);
}
add_filter('comment_text', 'comment_pic_https');
});

那么这篇文章就到这里了,咱先睡觉去了…… 最后祝你身体健康(逃

(本来自动播放的时候应该放在这的播放器,啊放前面好丑啊)

-EOF-

106 条评论

昵称
  1. 老杨

    限定发件人地址和名称这段我是怎么都折腾不出来,后来加 header 就好了。多版本邮件邮件代码少了个 },这个代码用上了,感谢。

    1. liwanglin12

      这个文章目前的版本有问题,可能是我启用新编辑器导致的……
      我检查一下

    2. liwanglin12

      改好了,再试试?

      1. 老杨

        $phpmailer->From = “期待的发送邮箱地址”; 这段代码我用上没有效果,直接 subject 和 from 都变成未知的了。

        我是通过 $headers = “From: “.get_option(‘blogname’).” <“.$wp_email.”>” . “\n”; 实现指定发件人名称的。

  2. 狂放

    多说倒闭惹

  3. superzhang

    我来评论一下试试|´・ω・)ノ