Skip to content

Instantly share code, notes, and snippets.

@tateisu
Last active Feb 17, 2021
Embed
What would you like to do?
const util = require('hexo-util');
const { decycle, encycle } = require('json-cyclic');
const { encode, decode } = require('html-entities');
const fetch = require('node-fetch');
const jsonpath = require('jsonpath');
const fs = require('fs');
const verbose = false;
function errorHtml(msg){
console.log(`lemmyComment : error. ${msg}`);
return `<div>lemmyComment : error. ${ encode(msg).replace("\n","<br/>")}</div>`;
}
function encodeQuery(obj) {
const array = [];
for (var p in obj)
if (obj.hasOwnProperty(p))
array.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return array.join("&");
}
async function lemmyCommentImpl(self,args){
// const lemmyConfig = hexo.config.lemmyComment;
// if(!lemmyConfig)
// return errorHtml(`missing lemmyComment in _config.yml`)
// Hexoの作業フォルダ直下にある設定ファイルを読む
// このファイルはログイン情報を含むかもしれない
var lemmyConfigFile = "lemmyConfig.json";
var lemmyConfig ={};
try {
lemmyConfig = JSON.parse(fs.readFileSync(lemmyConfigFile, 'utf8'));
} catch (err) {
if (err.code !== 'ENOENT'){
console.log(`${err} ${lemmyConfigFile}`);
throw err;
}
}
if(verbose) console.log(`lemmyConfig=${ JSON.stringify(lemmyConfig, null, 2)}`)
if(!lemmyConfig.site)
return errorHtml("missing lemmyConfig.site in ${lemmyConfigFile}");
// assets フォルダに.json をおくと記事として認識されてしまうので、拡張子を画像のソレにする
var dataFile = `${self.asset_dir}lemmyComment.png`;
var data = {};
try {
data = JSON.parse(fs.readFileSync(dataFile, 'utf8'));
} catch (err) {
if (err.code !== 'ENOENT'){
console.log(`${err} ${dataFile}`);
throw err;
}
}
var postId = args[0] || data.postId;
if(verbose) console.log(`postId=${postId}`);
if(!postId){
// "https://earphones.juggler.jp/hexo-comment-lemmy-test/"
// 末尾の/ は除去する必要がある
var blogUrl = self.permalink
.replace(/\/$/, "");
if(verbose) console.log(`blogUrl=${blogUrl}`);
if( !blogUrl || !blogUrl.startsWith("https://") )
return errorHtml(`incorrect permalink. ${blogUrl}`);
var query ={
"q" : blogUrl,
"type_" : "Url",
"sort" : "TopAll",
"page" : 1,
"limit" : 3
};
var url = `${lemmyConfig.site}/api/v2/search?${encodeQuery(query)}`;
if(verbose) console.log(url);
var response = await fetch(url);
var root = await response.json();
var posts = root.posts;
// searchリクエスト自体が失敗したらエラー
if( !posts )
return errorHtml(`can't use search API. ${JSON.stringify(root, null, 2)}`);
postId = jsonpath.query(root, '$.posts.0.post.id')[0];
if( !postId ){
var warns = [];
if(self.layout != "posts")
warns.push(`- layout is not posts. "${self.layout}"`)
if(!self.published)
warns.push(`- this post is not published.`)
if(!lemmyConfig.community)
warns.push(`- missing lemmyComment.community in ${lemmyConfigFile}`);
if(!lemmyConfig.user)
warns.push(`- missing lemmyComment.user in ${lemmyConfigFile}`);
if(!lemmyConfig.password)
warns.push(`- missing lemmyComment.password in ${lemmyConfigFile}`);
if( warns.length > 0 )
return errorHtml(`autoPost disabled.\n${warns.join("\n")}`);
// 投稿先のコミュニティーIDを調べる
if(!lemmyConfig.communityId){
var query = { "name" : lemmyConfig.community};
var url = `${lemmyConfig.site}/api/v2/community?${encodeQuery(query)}`;
if(verbose) console.log(url);
var response = await fetch(url);
var root = await response.json();
if(verbose) console.log(`${JSON.stringify(root, null, 2)}`);
lemmyConfig.communityId = jsonpath.query(root, '$.community_view.community.id')[0];
if(!lemmyConfig.communityId)
return errorHtml(`can't find communityId fo "${lemmyConfig.community}". ${JSON.stringify(root, null, 2)}`);
}
// ログイン
if (!lemmyConfig.lemmyAuth){
var query = {
"username_or_email":lemmyConfig.user,
"password": lemmyConfig.password
};
var url = `${lemmyConfig.site}/api/v2/user/login`;
if(verbose) console.log(url);
var response = await fetch(url, {
method: 'POST',
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
body: JSON.stringify(query)
});
var root = await response.json();
if(verbose) console.log(`${JSON.stringify(root, null, 2)}`);
lemmyConfig.lemmyAuth = jsonpath.query(root, '$.jwt')[0];
if(!lemmyConfig.lemmyAuth)
return errorHtml(`login failed. ${JSON.stringify(root, null, 2)}`);
}
var query = {
"name" : self.title,
"url" : blogUrl,
"nsfw" : false,
"body" : "Auto-generated post.",
"community_id" : lemmyConfig.communityId,
"auth" : lemmyConfig.lemmyAuth
};
var url = `${lemmyConfig.site}/api/v2/post`;
if(verbose) console.log(url);
var response = await fetch(url, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(query)
});
var root = await response.json();
if(verbose) console.log(`${JSON.stringify(root, null, 2)}`);
postId = jsonpath.query(root,"$.post_view.post.id")[0];
if(!postId)
return errorHtml(`post failed. ${JSON.stringify(root, null, 2)}`);
}
if( !postId ){
return errorHtml(`missing postId`);
}else{
data.postId = postId;
fs.writeFileSync(dataFile,JSON.stringify(data),'utf8');
}
}
return `<div id="lemmyComment"></div><script>lemmyComment("${lemmyConfig.site}","${postId}")</script>`;
}
hexo.extend.tag.register('lemmyComment', function(args){
const self = decycle(this);
for( const key of ["date", "updated", "raw","tags","content","categories","site"] ){
self[key]=`(${typeof self[key]})`;
}
if(verbose) console.log(`self=${ JSON.stringify(self, null, 2)}`)
return lemmyCommentImpl(self,args);
}, {async: true});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment