神代綺凛

[Typecho] Gravatar & Qlogo 评论头像缓存
支持 Handsome 4.2.0 修改主题获取头像的函数,使得评论头像能够缓存在本地并加载,而不用每次都由来访...
扫描右侧二维码阅读全文
11
2017/12

[Typecho] Gravatar & Qlogo 评论头像缓存

支持 Handsome 4.2.0

修改主题获取头像的函数,使得评论头像能够缓存在本地并加载,而不用每次都由来访者从 Gravator 和 Qlogo 加载,节省加载时间。

Head Pic: 「ウォーロックジータちゃん」/「konomi★きのこのみ」のイラスト [pixiv]

评论头像缓存

2017-12-05:随 Handsome 4.1.1 主题同步更新
2017-12-11:增加一个检测头像下载失败重新下载的功能

说明

这次魔改是针对 handsome主题 的,即本站所使用的主题。实际上是从“Gravatar 头像缓存插件”获得的启发,也参考了其代码。如果这个插件(Github项目地址在最后)不支持你所使用的主题,比如 handsome主题,那么你也可以试试仿照着魔改一下。

2017-10-21 修复一个 Qlogo 默认头像不能识别的 bug

思路

  • 以一个每个邮箱独有的标志命名每个缓存文件,例如 Gravator 就是邮箱的 md5,Qlogo 就是QQ号。
  • 如果不存在已经缓存的头像,或者超出设定的缓存时限,则将头像下载到服务器本地。
    • 下载成功,则返回本地缓存图片路径。
    • 下载失败,或者得到的为 Gravator 或者 Qlogo 的默认头像,则返回自己设定的默认头像。
  • 如果存在已经缓存的头像,那么直接返回缓存的图片路径。

魔改代码

如果是 handsome 主题则直接修改/(网站根目录)/usr/themes/handsome/libs/Utils.php
在此文件的类的末端(即最后一个右大括号}之前)加上如下4个函数:

//缓存Qlogo头像
public static function getQlogoCache($avatar,$nk){
    //setting-start
    $options = mget();
    $default = '';
    if (strlen($options->defaultAvator) > 0){
        $default = $options->defaultAvator;
    }
    //缓存时间,单位秒,1209600秒=14天
    $timeCache = 1209600;
    //头像缓存目录
    $tempDir = "/usr/uploads/qlogoCache/";
    //setting-end

    $host = "https://q.qlogo.cn";
    $imgName = $nk . ".jpg";
    $localImgFile = __TYPECHO_ROOT_DIR__ . $tempDir . $imgName;

    if(!self::mkdirs(dirname($localImgFile))){
        throw new exception('GravatarCache 缓存目录创建失败,请检查指定的目录是否可写' );
    }
    if(!file_exists($localImgFile) || (time() - filemtime($localImgFile)) > $timeCache){
        if(!self::download($avatar, $host, $localImgFile)) return $default;
    }

    $fileSize = filesize($localImgFile);
    if($fileSize < 1){
        if(!self::download($avatar, $host, $localImgFile)) return $default;
    }
    if($fileSize == 1512 || $fileSize == 971) return $default;

    return $tempDir . $imgName;
}
//缓存Gravator头像
public static function getGravatorCache($email,$host){
    //setting-start
    $options = mget();
    $default = '';
    if (strlen($options->defaultAvator) > 0){
        $default = $options->defaultAvator;
    }
    //缓存时间,单位秒,1209600秒=14天
    $timeCache = 1209600;
    //头像缓存目录
    $tempDir = "/usr/uploads/avatarCache/";
    //setting-end

    $url = '/';//自定义头像目录,一般保持默认即可
    $size = '40';//自定义头像大小
    $rating = Helper::options()->commentsAvatarRating;
    $hash = md5(strtolower($email));
    $avatar = $host . $url . $hash . '?s=' . $size . '&r=' . $rating . '&d=' . urlencode($default);
    $imgName = $hash . ".jpg";
    $localImgFile = __TYPECHO_ROOT_DIR__ . $tempDir . $imgName;

    if(!self::mkdirs(dirname($localImgFile))){
        throw new exception('GravatarCache 缓存目录创建失败,请检查指定的目录是否可写' );
    }
    if(!file_exists($localImgFile) || (time() - filemtime($localImgFile)) > $timeCache){
        if(!self::download($avatar, $host, $localImgFile)) return $default;
    }

    $fileSize = filesize($localImgFile);
    if($fileSize < 1){
        if(!self::download($avatar, $host, $localImgFile)) return $default;
    }

    return $tempDir . $imgName;
}
//递归建立目录
public static function mkdirs($dir){
    return is_dir($dir) or (self::mkdirs(dirname($dir)) and mkdir($dir, 0777));
}
//下载头像
public static function download( $url, $referer, $imagePath ){
    $fpLocal = @fopen( $imagePath, 'w' );
    if( !$fpLocal ) {
        return false;
    }
    if( is_callable('curl_init') ) {
        $ch = curl_init();
        curl_setopt( $ch, CURLOPT_URL, $url );
        curl_setopt( $ch, CURLOPT_REFERER, $referer );
        curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 10 );
        curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 );
        curl_setopt( $ch, CURLOPT_HEADER, 0 );
        curl_setopt( $ch, CURLOPT_FILE, $fpLocal );
        if( !curl_exec($ch) ) {
            fclose( $fpLocal );
            curl_close( $ch );
            return false;
        }
        curl_close( $ch );
    }else {
        $opts = array(
            'http' => array(
                'method' => "GET",
                'header' => "Referer: $referer\r\n"
            )
        );
            $context = stream_context_create( $opts );
        $fpRemote = @fopen( $url, 'r', false, $context );
        if( !$fpRemote ) {
            fclose( $fpLocal );
            return false;
        }
            while( !feof( $fpRemote ) ) {
            fwrite( $fpLocal, fread($fpRemote, 8192) );
        }
        fclose( $fpRemote );
    }
        fclose( $fpLocal );
    return true;
}

接着,找到getAvator($email)函数,修改其中的3行:

public static function getAvator($email){
    $options = mget();
    $cdnUrl = $options->CDNURL;
    if (@ in_array('emailToQQ',$options->featuresetup)){
        $str = explode('@', $email);
        if (@$str[1] == 'qq.com') {
            $avatorSrc = 'https://q.qlogo.cn/g?b=qq&nk='.$str[0].'&s=40';
            $avatorSrc = self::getQlogoCache($avatorSrc,$str[0]);//修改1:直接加这一句
        }else{
            $avatorSrc = Utils::getGravatorCache($email,$cdnUrl);//修改2:改函数名
        }
    }else{
        $avatorSrc = Utils::getGravatorCache($email,$cdnUrl);//修改3:改函数名
    }
    return $avatorSrc;
}

后记

这样折腾其实还不如直接用好一点的 gravatar 镜像

参考

这次魔改参考了 羽飞Gravatar 头像缓存插件 For Typecho,参考了其部分代码,省了很多事还学到了点新姿势(。

搬瓦工VPS优惠套餐,建站稳如狗,支持支付宝,循环出账94折优惠码BWH3HYATVBJW
年付$47CN2线路,1核/1G内存/20G硬盘/1T@1Gbps【点击购买
季付$47CN2 GIA线路,1核/1G内存/20G硬盘/1T@2.5Gbps【点击购买
Last modification:August 12th, 2020 at 03:29 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment

19 comments

  1. 曦月  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 84.0.4147.105(Google Chrome 84.0.4147.105)
    想请教一下大大,最近正在做自己的博客(从头开始写那种),输入邮箱获取头像是怎么实现的啊,
    1. 神代綺凜  Mac OS X 10.15.5(Mac OS X 10.15.5) / Google Chrome 84.0.4147.105(Google Chrome 84.0.4147.105)
      @曦月 用的 Gravatar 服务
      1. 曦月  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 84.0.4147.125(Google Chrome 84.0.4147.125)
        @神代綺凜 啊x都快忘了注册过那个服务了xwx
  2. 平成五月  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 80.0.3987.132(Google Chrome 80.0.3987.132)
    该评论仅登录用户及评论双方可见
    1. 神代綺凜  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 80.0.3987.132(Google Chrome 80.0.3987.132)
      @平成五月
      该评论仅登录用户及评论双方可见
      1. 平成五月  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 80.0.3987.132(Google Chrome 80.0.3987.132)
        @神代綺凜
        该评论仅登录用户及评论双方可见
  3. Noob  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 71.0.3578.98(Google Chrome 71.0.3578.98)
    我还以为使用了redis缓存呢
    1. 神代綺凜  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 71.0.3578.98(Google Chrome 71.0.3578.98)
      @Noob 这个缓存我后来实际体验发现其实没有什么卵用而且首次载入时可能还没缓存好导致无法显示,还不如自己 nginx 反代缓存个(
      1. Noob  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 71.0.3578.98(Google Chrome 71.0.3578.98)
        @神代綺凜 我很久没有看你的博客了回来看到改动挺多的给全文检索改了一下,我还以为我打开错了
        1. 神代綺凜  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 71.0.3578.98(Google Chrome 71.0.3578.98)
          @Noob 你说的是搜索吗,那个是新版主题的啊,不过这个文章搜索十分傻逼,我找机会要改改……
          1. Noob  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 71.0.3578.98(Google Chrome 71.0.3578.98)
            @神代綺凜 额,我不想升级,太麻烦了
  4. Noob  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 69.0.3497.100(Google Chrome 69.0.3497.100)
    该评论仅登录用户及评论双方可见
    1. 神代綺凜  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 69.0.3497.100(Google Chrome 69.0.3497.100)
      @Noob handsome主题自带这个功能,去主题设置开
      1. Noob  Mac OS X(Mac OS X) / Mozilla Compatible(Mozilla Compatible)
  5. LuckyDog  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 64.0.3282.140(Google Chrome 64.0.3282.140)
    好像没有QQ和Gravatar显示不了默认|´・ω・)ノ
    1. 神代綺凜  Mac OS X(Mac OS X) / Safari(Safari)
      @LuckyDog 给handsome主题用的,其他主题可以直接找相关插件
  6. PrajnaSmoke  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 63.0.3239.108(Google Chrome 63.0.3239.108)
    支持缓存到又拍云就更棒了
    1. 神代綺凜  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 62.0.3202.89(Google Chrome 62.0.3202.89)
      @PrajnaSmoke 如果有镜像储存的话直接把返回地址加上cdn网址就行了
      1. PrajnaSmoke  Windows 10 x64 Edition(Windows 10 x64 Edition) / Google Chrome 63.0.3239.108(Google Chrome 63.0.3239.108)
        @神代綺凜 恩,这是一种办法,不过得手动上传头像