In this article, you will see: Low technical power poor efficiency Almost no portability and scalability
The only advantage: for the novice (myself), it can be realized without mastering many technologies
demand
hexo's friend chain page is the same as the article. If you want to update it, you have to regenerate and deploy it After using webhook, Github Action or vercel to realize automatic deployment, it becomes more convenient to update website content: after local modification, it is directly pushed to the warehouse, and the rest is handed over to the server However, to add a friend chain, copy and paste it from the comment area to link YML and then push, it's still troublesome At present, there are ways to add friend chains through issue, but for lazy people like me, if I can do it in the comment area, I don't want to open another web page, so I want to make a little change to automatically obtain the friend chain information in the comment and add it directly (this is based on the premise of automatic deployment) I don't care about auditing. There aren't many comments now
thinking
The comments in my blog use twikoo. I can't see the code of cloud function (of course, I can't understand it), so there is only JS left. Simply look at F12 and find that after clicking the send button, twikoo all. JS will send a post request to the twikoo cloud function to request the request of the load_ The data field contains comment content, comment link, etc
Just in twikoo all. When JS sends a post request to the twikoo cloud function, it also sends a post request for comment content to my own server. The json format string parsed by the back end can extract the nickname, avatar, mailbox and website information required by the new friend chain, and then update the link in the warehouse through Github API YML file, then trigger webhook, and the server deploying the blog will automatically pull the latest code
Specific steps
Build a simple flash application
Flash is a lightweight web framework. The following is the simplest flash application. Accessing the URL in route() will trigger the following function, which will return an html code and the browser will render it
from flask import Flask app = Flask(__name__) @app.route("/") def hello_world(): return "<p>Hello, World!</p>"
Start the application in the terminal and conduct local test, including flash_ hello in app = hello is the py file name
- bash
- cmd
- powershell
export FLASK_APP=hello flask run
set FLASK_APP=hello flask run
$env:FLASK_APP = "hello" flask run
The default port is 5000. Visit localhost:5000 to see Hello, World!

To process a post request, you just need to go to @ app Add methods=['post '] to the route decorator so that the route can only be accessed in post mode request.get_data can receive the payload of post requests
@app.route("/",methods=['post']) def hello_world(): print(request.get_data(as_text=True))
Click the send button and twikoo will launch a post request. The content of Request PayLoad is as follows:

As can be seen from the figure, you only need to parse the comment field
The comment field is html code, with the help of etree html parses text content from html code How to use JSON, XPath and subprocess tools will not be described here
Complete backend implementation:
The old version is obsolete
from flask import Flask from flask import request from markupsafe import escape from lxml import etree from flask_cors import * import re import time import subprocess import json app = Flask(__name__) CORS(app, supports_credentials=True) # Allow cross domain @app.route("/",methods=['post']) def hello_world(): data = json.loads(request.get_data(as_text=True)) data = json.loads(data['request_data']) # Check the source and replace it with your own if "comment" in data and data['href'] == 'https://www.bilibilianime.com/link/': with open('/var/hexo_source/hexo/source/_data/link.yml','a+')as f: # f.write(str(data)) dom = etree.HTML(str(data['comment'])) # f.write(s+'\n\n') info = [] try: info = dom.xpath("//code[@class='language-yml']//text()") info = [ainfo.strip() for ainfo in info[0].split("\n")] # f.write(str(info)) template = "\n\n {}\n {}\n {}\n {}" f.write(template.format(info[0],info[1],info[2],info[3])) with open('log.txt','a+')as logfile: logfile.write(time.asctime( time.localtime(time.time()))+": Add a friend chain: "+" ".join(info)+"\n") # link.yml directory, change to your own subprocess.Popen('cd /var/hexo_source/hexo/&&git add .&&git commit -m "update: friend link"&&git push>log.txt',shell=True) except: with open('log.txt','a+')as logfile: logfile.write(time.asctime( time.localtime(time.time()))+ ": Failed!"+"info: {}".format(" ".join(info))+"\n") else: return '<span>bad!</span>' return '<span>ok!</span>'
Using Github API
from flask import Flask from flask import request from markupsafe import escape from lxml import etree from flask_cors import * import re import time import subprocess import json import requests import base64 import traceback from twisted.internet import reactor from twisted.web import proxy, server # Fill in your token here token = '' # Fill in your link here Github API link for YML url = 'https://API.github.com/repos/ayasa520/hexo/contents/source/_data/link.yml' headers = {'Authorization': 'token ' + token} app = Flask(__name__) # Allow cross domain CORS(app, supports_credentials=True) @app.route("/",methods=['post']) def hello_world(): data = json.loads(request.get_data(as_text=True)) data = json.loads(data['request_data']) if "comment" in data and data['href'] == 'https://www.bilibilianime.com/link/': dom = etree.HTML(str(data['comment'])) info = [] try: info = dom.xpath("//code[@class='language-yml']//text()") info = [ainfo.strip() for ainfo in info[0].split("\n")] template = "\n\n {}\n {}\n {}\n {}" response_json = json.loads(requests.get(url, headers=headers).text) old_text = str(base64.b64decode(response_json['content']), encoding='utf-8') b64 = base64.b64encode((old_text +template.format(info[0],info[1],info[2],info[3])).encode('utf-8')).decode('ascii') data = { 'message': "update from Python", 'content': b64, 'sha': response_json['sha'] } requests.put(url=url, data=json.dumps( data), headers=headers) with open('log.txt','a+')as logfile: logfile.write(time.asctime( time.localtime(time.time()))+": Add a friend chain: "+" ".join(info)+"\n") except Exception as e: with open('log.txt','a+')as logfile: logfile.write(time.asctime( time.localtime(time.time()))+ ": Failed!"+"info: {}".format(" ".join(info))+"\n") logfile.write(traceback.format_exc()) else: return '<span>bad</span>' return '<span>ok!</span>'
In the non development environment, it is not appropriate to use the server provided by flash. Here I wrote a startup script and used Gunicorn as the server
source /var/hexo_source/simpleSever/# Flash source directory gunicorn -w 2 -b :5000 flask_web:app # Bind to 5000 port flask_web py file name
Run the script to complete the deployment How to deploy to your own virtual machine is very detailed on the Internet, so I won't repeat it
stay https://postwoman.com.cn/ You can test quickly:

Change twikoo all. js
In the formatted twikoo all. Insert the following code at line JS 5783:
$.ajax({ // This domain name points to port 5000. Replace it with your own url:'https://update-friend.bilibilianime.com/', type:'POST', dataType:'json', contentType:'application/json;charset=UTF-8', data:JSON.stringify(e.data), success:function(data, status){ console.log(data); } });
As shown in the figure:

Will theme_ config. Modify the CDN of twikoo in YML to the changed one All the work is finished
I didn't audit the friend chain, because there were not many critics, so I don't care about it now