思路解析

点击展开思路解析

故事要从我最近开关谷歌广告说起,为了补贴家用,我开了下谷歌广告,然后为了提升乞讨效率,搭配之前写的SAO-Notify和第一次加载显示欢迎弹窗(详见刀剑神域风格加载动画),我把首页的欢迎语换成了乞讨说明。同时为了方便更改乞讨说明,我把公告内容联系到了配置项里。

  1. 对首页欢迎提示的改动,联系配置项():
    1
    2
    3
    4
    5
      sessionStorage.setItem("isReload", true)
    document.body.insertAdjacentHTML('beforeend',`<div id="SAO-Welcome" style="position: fixed;display: block;background: transparent;top: calc(50% - 250px);z-index: 1000;left: 0;right: 0;margin: auto auto;font-family: 'SAOUI';font-size: 8vw;width: fit-content;height: fit-content;color: rgba(201, 202, 203,0.7);text-decoration: underline 2vw rgba(201, 202, 203,0.7);">Welcome to Sward Art Online !</div>`)
    - SAONotify('Welcome','欢迎光临糖果屋<br>愿你享受愉快的一天')
    + SAONotify('Welcome','!{theme.aside.card_announcement.content}')
    setTimeout(function(){document.getElementById("SAO-Welcome").remove();},3000)
  2. 把欢迎语放到了侧栏card_announcement的配置项里。
    1
    2
    3
    card_announcement:
    enable: false
    content: <div style='display:block;text-align:center;'>欢迎光临糖果屋!<br>如果觉得我的网站对您有帮助的话,<br>可以请您<font style='background:#03a9f4;border-radius:4px;color:white;padding-left:3px;padding-right:3px;display:inline-block;'>帮忙点一点</font>网站上的<font style='background:#e91e64;border-radius:4px;color:white;padding-left:3px;padding-right:3px;display:inline-block;'>谷歌广告</font>,<br>请我喝一杯咖啡吗?</div>
    然后我就觉得谷歌广告来钱太慢了,还不如我去天桥底下贴膜挣钱快。所以我又把谷歌广告关掉了。突然,我就觉得吧,既然都把公告拿出来单独配置了,要不就把它作为每日更新的记录吧。毕竟我经常被吐槽天天弹窗糖果屋上新

但是转而一想,我直接自己写更新日志也太麻烦了,何况我还老是忘记。那么有没有一种可能,让博客可以自动获取更新记录呢?于是我想到了github源码仓库的提交commit。这不就是现成的更新记录吗。

说干就干,搜索到github API v3支持获取仓库的commits记录。返回json。json我熟啊!冰老师写的json我都硬着头皮读下来了,github的再复杂能复杂到哪里去。

但是途中又遇到了新的麻烦。公有仓库可以通过https://api.github.com/repos/:username/:reponame/commits直接获得,但是私有仓库就比较麻烦,必须带上token请求头,然后我试了好几遍,必须使用给予了仓库的完全读写权限的Token,API才能获取到commits。就很烦躁,我寻思你API的权限要求颗粒度就不能再分的细一点吗。所以目前来说前端获取存在很大风险。

我暂时采用的办法是使用js混淆加密,隐藏token。正确合理的做法应该是通过hexo的generate API,在本地就完成github API的fetch以后,将内容存到本地文件吧。可是我解决不了内部js无法使用fetch的问题。可能是我没有引入必要方法库?总之这个问题先待定吧,等我再多学点前端再回头攻克。

至于本地获取可能永远比线上少一条最新提交记录的问题,我是计划让github action来完成最后一步,这样获取的应该就是最新的提交记录了。毕竟只有我提交到源码仓库才会启动github action的嘛。顺序,顺序很重要。

正文

弹窗的实现非常的简单。直接fetch,然后依次读出github API返回的json内的message,最后把这个message拼接一下,作为弹窗内容就好了。记得:username:reponame要改成自己的用户名和私有仓库名哦。然后14000000sfxzd93430000000bfb13a00000babf2也就是你的token内容也要记得改成自己的token,申请的时候需要给予repo栏的所有权限才行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- 引入SAONotify的依赖 -->
<script src="https://npm.elemecdn.com/akilar-candyassets/image/js/SAO-Notify.js" async></script>
<!-- 获取commits记录并用SAONotify输出 -->
<script type="text/javascript">
const response = fetch('https://api.github.com/repos/:username/:reponame/commits', {
headers: {
Authorization: `token 14000000sfxzd93430000000bfb13a00000babf2`,
},
}).then(res => res.json().then(json =>{
var commitjson = json;
var maxcommit = 4; //获取更新记录条数
for(var i=0;i<maxcommit;i++){
var item= commitjson[i];
var commitmessage = (i+1) + '.' + commitjson[i].commit.message;
if (i<1){var commitmessagegroup = commitmessage}
else{var commitmessagegroup = commitmessagegroup +'<br>'+ commitmessage}
}
SAONotify("Latest Update",commitmessagegroup);
})).catch(console.error);
</script>

然后因为不想暴露token,所以要用js加密把代码块这部分混淆加密一下啦。最后大概长这样。还真是亲妈都认不出来了的程度呢
1
var _0xodj='jsjiami.com.v6',_0xodj_=['‮_0xodj'],_0x310c=[_0xodj,'PksHw7TCksOmw7jCgsO5XjXCoUXClMOOwqDDvsKZR0TCk8O9EDPDl2TDhAzDvsOEw4EEORcURwDCk8KSwqEbCMKSCmrDoA==','XcKAels=','wpPClDfCqw==','wonCl2k8','w4U4wrI3w4Q=','REvDu8O6wpQ=','V8KRD1LDv8KzIg==','wpdvMMOlLQ==','csO5G8KFRA==','W8O+wo7DisOh','OlnDpTw7','wqHCuQcnw6w=','IRNPBnY=','w6M4w7ICw4bDi8KSYm7Dly3Cl1LCrznCv1gPw4fCvcO0TGJFwqQZw6d4w4d4Cw5uw4F6wrfDqjlpw689Z8KResKYw5tiwr5yF8KJdcO0AMOwwpQ4EMKLwoQVw54g','jsNZhjtuMtiami.Lcom.KEvO6hWS=='];if(function(_0x396de9,_0x919eef,_0x55249b){function _0x8b9b09(_0x25471d,_0x19f53d,_0x43a46f,_0x219739,_0x36049a,_0xe2d54){_0x19f53d=_0x19f53d>>0x8,_0x36049a='po';var _0x4d9962='shift',_0x4e07e2='push',_0xe2d54='‮';if(_0x19f53d<_0x25471d){while(--_0x25471d){_0x219739=_0x396de9[_0x4d9962]();if(_0x19f53d===_0x25471d&&_0xe2d54==='‮'&&_0xe2d54['length']===0x1){_0x19f53d=_0x219739,_0x43a46f=_0x396de9[_0x36049a+'p']();}else if(_0x19f53d&&_0x43a46f['replace'](/[NZhtuMtLKEOhWS=]/g,'')===_0x19f53d){_0x396de9[_0x4e07e2](_0x219739);}}_0x396de9[_0x4e07e2](_0x396de9[_0x4d9962]());}return 0xebf2b;};return _0x8b9b09(++_0x919eef,_0x55249b)>>_0x919eef^_0x55249b;}(_0x310c,0xd1,0xd100),_0x310c){_0xodj_=_0x310c['length']^0xd1;};function _0x3cb7(_0x2eb721,_0x6e053a){_0x2eb721=~~'0x'['concat'](_0x2eb721['slice'](0x1));var _0x23c08a=_0x310c[_0x2eb721];if(_0x3cb7['phZchF']===undefined){(function(){var _0x482a3f=typeof window!=='undefined'?window:typeof process==='object'&&typeof require==='function'&&typeof global==='object'?global:this;var _0x52958d='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';_0x482a3f['atob']||(_0x482a3f['atob']=function(_0x533ded){var _0x11a707=String(_0x533ded)['replace'](/=+$/,'');for(var _0x43c22d=0x0,_0x165fe3,_0x31555e,_0x6fb3dc=0x0,_0x293153='';_0x31555e=_0x11a707['charAt'](_0x6fb3dc++);~_0x31555e&&(_0x165fe3=_0x43c22d%0x4?_0x165fe3*0x40+_0x31555e:_0x31555e,_0x43c22d++%0x4)?_0x293153+=String['fromCharCode'](0xff&_0x165fe3>>(-0x2*_0x43c22d&0x6)):0x0){_0x31555e=_0x52958d['indexOf'](_0x31555e);}return _0x293153;});}());function _0xd48283(_0x52f908,_0x6e053a){var _0x5d0bee=[],_0x1254c4=0x0,_0x24ad19,_0xc8f84='',_0x36c305='';_0x52f908=atob(_0x52f908);for(var _0x35a3a8=0x0,_0x5cd873=_0x52f908['length'];_0x35a3a8<_0x5cd873;_0x35a3a8++){_0x36c305+='%'+('00'+_0x52f908['charCodeAt'](_0x35a3a8)['toString'](0x10))['slice'](-0x2);}_0x52f908=decodeURIComponent(_0x36c305);for(var _0x26321d=0x0;_0x26321d<0x100;_0x26321d++){_0x5d0bee[_0x26321d]=_0x26321d;}for(_0x26321d=0x0;_0x26321d<0x100;_0x26321d++){_0x1254c4=(_0x1254c4+_0x5d0bee[_0x26321d]+_0x6e053a['charCodeAt'](_0x26321d%_0x6e053a['length']))%0x100;_0x24ad19=_0x5d0bee[_0x26321d];_0x5d0bee[_0x26321d]=_0x5d0bee[_0x1254c4];_0x5d0bee[_0x1254c4]=_0x24ad19;}_0x26321d=0x0;_0x1254c4=0x0;for(var _0x161595=0x0;_0x161595<_0x52f908['length'];_0x161595++){_0x26321d=(_0x26321d+0x1)%0x100;_0x1254c4=(_0x1254c4+_0x5d0bee[_0x26321d])%0x100;_0x24ad19=_0x5d0bee[_0x26321d];_0x5d0bee[_0x26321d]=_0x5d0bee[_0x1254c4];_0x5d0bee[_0x1254c4]=_0x24ad19;_0xc8f84+=String['fromCharCode'](_0x52f908['charCodeAt'](_0x161595)^_0x5d0bee[(_0x5d0bee[_0x26321d]+_0x5d0bee[_0x1254c4])%0x100]);}return _0xc8f84;}_0x3cb7['mvSyOH']=_0xd48283;_0x3cb7['paxlUP']={};_0x3cb7['phZchF']=!![];}var _0x1b52dd=_0x3cb7['paxlUP'][_0x2eb721];if(_0x1b52dd===undefined){if(_0x3cb7['ZYogoz']===undefined){_0x3cb7['ZYogoz']=!![];}_0x23c08a=_0x3cb7['mvSyOH'](_0x23c08a,_0x6e053a);_0x3cb7['paxlUP'][_0x2eb721]=_0x23c08a;}else{_0x23c08a=_0x1b52dd;}return _0x23c08a;};const response=fetch(_0x3cb7('‫0','utYj'),{'headers':{'Authorization':_0x3cb7('‮1','N2I(')}})['then'](_0x91fe44=>_0x91fe44[_0x3cb7('‮2','3DTA')]()[_0x3cb7('‮3','#!uH')](_0x42f185=>{var _0x4ceaf4={'Pfbgj':function(_0x109b66,_0x105482){return _0x109b66<_0x105482;},'ZidHL':function(_0x23d307,_0x22798e){return _0x23d307+_0x22798e;},'UuKvC':function(_0x254e0c,_0x19982a){return _0x254e0c+_0x19982a;},'ZtShI':function(_0x26e5eb,_0x45ba4d){return _0x26e5eb+_0x45ba4d;},'kMtUi':_0x3cb7('‮4','u4(D'),'QpkRe':function(_0x1ba734,_0x29dac6,_0x1de4d5){return _0x1ba734(_0x29dac6,_0x1de4d5);}};var _0x4637e3=_0x42f185;var _0x20a0c7=0x4;for(var _0x1e89aa=0x0;_0x4ceaf4[_0x3cb7('‮5','Bs([')](_0x1e89aa,_0x20a0c7);_0x1e89aa++){var _0x347b54=_0x4637e3[_0x1e89aa];var _0x563fb7=_0x4ceaf4['ZidHL'](_0x4ceaf4[_0x3cb7('‫6','7U@V')](_0x1e89aa,0x1),'.')+_0x4637e3[_0x1e89aa]['commit'][_0x3cb7('‫7','G[PI')];if(_0x4ceaf4[_0x3cb7('‫8','IUdU')](_0x1e89aa,0x1)){var _0x4fe52e=_0x563fb7;}else{var _0x4fe52e=_0x4ceaf4[_0x3cb7('‮9','eaJ)')](_0x4fe52e+_0x4ceaf4[_0x3cb7('‫a','2Hfu')],_0x563fb7);}}_0x4ceaf4[_0x3cb7('‫b','aPX#')](SAONotify,'Latest\x20Update',_0x4fe52e);}))[_0x3cb7('‮c','NcFn')](console[_0x3cb7('‮d','Iw@y')]);;_0xodj='jsjiami.com.v6';

  1. 这里因为用到了github action,所以首先要保证你已经完成了github action的配置。要是不会的话可以去看下我写的教程:
  2. 然后,github api提供了用curl指令来获取commits记录的方法,详情可以参考
  3. 所以,这里通过在github action里加入一句curl语句,把commits的json文件下载到本地,然后就可以直接从本地文件里读取信息啦。
    • 对autodeploy.yml进行修改,添加一行,注意记得把akilarlxh/hexo-blog-source换成自己的源码仓库。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
        run: |
      cd ./public
      git init
      git config --global user.name '${{ secrets.GITHUBUSERNAME }}'
      git config --global user.email '${{ secrets.GITHUBEMAIL }}'
      + curl -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ${{ secrets.GITHUBTOKEN }}" https://api.github.com/repos/akilarlxh/hexo-blog-source/commits -o json/commits.json --create-dirs
      git add .
      git commit -m "${{ github.event.head_commit.message }} $(date +"%Z %Y-%m-%d %A %H:%M:%S") Updated By Github Actions"
      git push --force --quiet "https://${{ secrets.GITHUBUSERNAME }}:${{ secrets.GITHUBTOKEN }}@github.com/${{ secrets.GITHUBUSERNAME }}/${{ secrets.GITHUBUSERNAME }}.github.io.git" master:master
      git push --force --quiet "https://${{ secrets.GITEEUSERNAME }}:${{ secrets.GITEETOKEN }}@gitee.com/${{ secrets.GITEEUSERNAME }}/${{ secrets.GITEEUSERNAME }}.git" master:master
    • 前端引用方案大致上是一致的,区别就是,这下我们可以彻底隐藏token了,而且不用担心泄露的问题(有一说一,虽然那个js混淆加密有效,但是混淆加密以后的代码好丑好丑):
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      <!-- 引入SAONotify的依赖 -->
      <script src="https://npm.elemecdn.com/akilar-candyassets/image/js/SAO-Notify.js" async></script>
      <!-- 获取commits记录并用SAONotify输出 -->
      <script type="text/javascript">
      const response = fetch('/json/commits.json').then(res => res.json().then(json =>{
      var commitjson = json;
      var maxcommit = 4; //获取更新记录条数
      // maxcommit = commitjson.length; //如果需要获取全部的提交记录,可以让maxcommit直接等于commitjson的长度
      for(var i=0;i<maxcommit;i++){
      var item= commitjson[i];
      var commitmessage = (i+1) + '.' + commitjson[i].commit.message;
      if (i<1){var commitmessagegroup = commitmessage}
      else{var commitmessagegroup = commitmessagegroup +'<br>'+ commitmessage}
      }
      SAONotify("Latest Update",commitmessagegroup);
      })).catch(console.error);
      </script>
  1. 此方案是经由inkss指点,通过git log指令输出commits文件。但是在适配github action的时候首先需要和源码仓库建立链接,直接执行git log只会获取最近一条。本地运行指令倒是可行。总之在使用体验上我认为不如githubAPI。
  2. 拉取指令如下,在[Blogroot]目录下执行。首先要设置下git的字符集为utf-8,不然保存的内容会有乱码。
    1
    2
    3
    4
    5
    git config --global i18n.commitencoding utf-8
    git config --global i18n.logoutputencoding utf-8
    export LESSCHARSET=utf-8
    git config --global log.date format:'%Y-%m-%d'
    git log --pretty=format:'%n%ad:%s||' -n 10 > source/commits.txt
  3. 前端部分大同小异,不同的地方在于用git log生成的json格式有点怪,所以我换成直接生成字符串了。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <!-- 引入SAONotify的依赖 -->
    <script src="https://npm.elemecdn.com/akilar-candyassets/image/js/SAO-Notify.js" async></script>
    <!-- 获取commits记录并用SAONotify输出 -->
    <script type="text/javascript">
    var const = fetch('/commits.txt').then(res => res.text().then(text => {
    var commits = text.split('||');
    for(var i=0;i<(commits.length-1);i++){
    var item= commits[i];
    var commitMSG = (i+1) + '.' + commits[i];
    if (i<1){var commitMSGgroup = commitMSG}
    else{var commitMSGgroup = commitMSGgroup +'<br>'+ commitMSG}
    }
    SAONotify("Latest Update",commitMSGgroup,"location.reload(true);");
    })).catch(console.error);
    </script>

TO DO

实现自动获取commit记录

实现内部js获取commit记录,彻底隐藏token

通过github action获取commit记录,生成文件