deepin上博客发送到为知笔记

1. 背景

之前已经做过一个版本的《deepin15和20使用命令行快捷键鼠标右键发布博客之博客园和为知笔记》,其主要思路是已经创建好markdown格式的博客。

typora是所见即所得的markdown的编辑器,提供了很棒的创作体验。

如果想把typora的博客,分享到网络平台,那么typora上粘贴的图片(存放在本地),就无法把图片上传。后来typora提供了对图床的支持,还有使用命令方式上传到服务器的支持。

我基于此,把之前的代码改了该,能够实现使用typora创作的博客,完美发布到博客园《deepin优雅地创作和分享博客》

但是尝试使用这个方式来实现使用typora创建博客并发送到为知笔记时,发现没法实现。最近改了代码,还是无法实现,主要原因可能是为知笔记提供的接口,其图片链接不是全局的,因为不像博客园那样,像个图床。

我思来想去 ,如果非要使用typora创作,简直就是自略。更何况现在为知笔记已经有Linux版本了(虽然它的编辑体验和markdown格式太low)

就这样吧,不折腾了。

不过,如果要用命令行来写的话,应该没啥问题。后面如果有兴趣了再完善吧,下面贴一下半成品代码

2. deepin上具体操作

  1. 把代码粘贴复制到一个目录下,比如/home/liwl/.liwl/deepin/scripts/目录
  2. 在/home/liwl/.liw/deepin/scripts/目录创建配置文件,格式看下文
  3. 创建deepin右键发送菜单选项

大致就是这三步,很简单

3. 代码

下面代码,粘贴复制为send_to_wiznote.js,放到一个目录下,在该目录下创建一个wiznote.json,内容如下:

#!/usr/bin/node
/*
1. sudo apt install nodejs,npm
2. npm install fs,commander,n-readlines,axiso //全局安装使用sudo npm install -g xxx,并且需要添加环境变量,NODE_PATH
3. update:
    2021-06-24 更新:在deepin20.2.2版本上,通过sudo apt install nodejs npm,npm的版本安装的commander调用是program.opts().file,而非之前的program.file
    2021-12-12 更新: 对相同标题的笔记,进行更新操作(先删除,后更新)
*/

//
//通过npm安装以下模块
const fs = require("fs")
const program = require("commander")
const linerByLine = require("n-readlines")
const FormData = require('form-data')
const path = require('path')
const axios = require('axios');
const AS_URL = 'https://as.wiz.cn';
const CONFIG_JSON = 'wiznote.json'

//通过命令行参数指定文件,便于使用命令行,或者右键
program
    .option('-f, --file <type>','add filename')
    .option('-i, --image <type>','add image')
    .option('-l, --list','list note')
    .parse(process.argv)

/***********************************************************************************
    execRequest:获取token
***********************************************************************************/
async function execRequest(method, url, body, token,headers) {
  const options = {
    url,
    method,
    data: body,
  };
  if (token) {
    options.headers = {
      'X-Wiz-Token': token,
    };
  }
  if (headers) {
    options.headers = Object.assign({}, options.headers || {}, headers);
  }

  const res = await axios(options);
  const data = res.data;
  if (data.returnCode !== 200) {
    console.error(`request error: ${data.returnMessage}`);
    const err = new Error(data.returnMessage);
    err.code = data.returnCode;
    err.externCode = data.externCode;
    throw err;
  }
  return data.result
}

/***********************************************************************************
*   login:登陆
***********************************************************************************/
async function login(userId, password) {
  return await execRequest('post', `${AS_URL}/as/user/login`, {userId, password});
}

/***********************************************************************************
* createNote: 创建笔记
***********************************************************************************/

async function createNote(kbServer, kbGuid, title, folder, html, extOptions, token) {
  const url = `${kbServer}/ks/note/create/${kbGuid}`;
  let note = {
    kbGuid,
    title,
    category: decodeURI(folder), //注意,这里对中文乱码进行解码
    html,
  };
  console.log(note) 
  if (extOptions) {
    note = Object.assign(note, extOptions);
  }
  return await execRequest('post', url, note, token);
}

/***********************************************************************************
* deleteNote: 删除笔记
***********************************************************************************/
async function delateNote(kbServer,kbGuid,docGuid,token){
    const deleteUrl = `${kbServer}/ks/note/delete/${kbGuid}/${docGuid}`
    console.log("准备删除")
    return await execRequest('delete',deleteUrl,null,token)
}

/***********************************************************************************
* listNote: 查询笔记
***********************************************************************************/
async function listNote(kbServer,kbGuid,folder,token){
    const listUrl = `${kbServer}/ks/note/list/category/${kbGuid}?category=${folder}&withAbstract=false&start=0&count=100&orderBy=created&ascending=desc`
    return await execRequest('get',listUrl,null,token)
}

/***********************************************************************************
* uploadImage: 上传图片
***********************************************************************************/
async function uploadImage(kbServer,kbGuid,docGuid,imageFile,token){
    const uploadUrl = `${kbServer}/ks/resource/upload/${kbGuid}/${docGuid}`
    const formData = new FormData();
    formData.append('kbGuid',kbGuid);
    formData.append('docGuid',docGuid);
    formData.append('data',fs.createReadStream(imageFile),{
       filename: path.basename(imageFile) 
    })
    const headers = {
        ...formData.getHeaders(),
    }
    return await execRequest('post',uploadUrl,formData,token,headers)
}

/******************************脚本主要功能***************************************/

/***********************************************************************************
* 创建或者更新笔记
* 逻辑还需要完善一下,删除的笔记,其图片不会其他笔记显示。
* 没有笔记时,创建空笔记,创建图床地址。新笔记通过更新的方式。
* 有笔记时,清空笔记内容(相当于创建笔记),然后上传图片
***********************************************************************************/
async function uploadNoteFile(noteFileAbsPath,imageFileAbsPath=null) {

    //从配置文件获取用户帐号,密码,默认上传目录
    let data = JSON.parse(fs.readFileSync(CONFIG_JSON,'utf-8'))
    const userId = data.userId
    const password = data.password
    const folder = encodeURI(data.category)

    //获取用户登陆信息
    const loginResult = await login(data.userId, data.password);
    const {kbServer, kbGuid, token} = loginResult;

    //获取笔记的名称.注意:xxx.md和xxx的笔记的guid不一样
        const noteTitle = noteFileAbsPath.split('/').pop()

    /*查询笔记是否已经存在。存在则删除*/
    await listNote(kbServer,kbGuid,folder,token).then(res=>{

        //获取目录笔记标题
        let titles = []
        let docGuid = []
        res.forEach(e =>{
            titles.push(e.title)
            docGuid.push(e.docGuid)
        })

        //判断要操作的笔记是否已经存在,存在通过docGuid删除笔记
        if (titles.includes(noteTitle)){
            let guid = docGuid[(titles.indexOf(noteTitle))]
            delateNote(kbServer,kbGuid,guid,token)
        }
    })


    /*创建笔记*/
    console.log("开始创建笔记")
    /**
    * 获取博客内容
    **/ 
    const liner = new linerByLine(noteFileAbsPath)
    let line;
    let noteContent = '';
    while (line = liner.next()){
        noteContent += line + '</br>'; //为markdown每一行添加换行,以便正确解析语法
    }
    //
    //const newNote1 = createNote(kbServer, kbGuid, noteTitle, folder, noteContent, null, token);
    //console.log("创建笔记结束");
    createNote(kbServer, kbGuid, noteTitle, folder, noteContent, null, token).then(res=>{
        //创建笔记结束后,把图片上传,返回图片的url
        guid = res.docGuid
        console.log(guid)
        if(imageFileAbsPath){
            uploadImage(kbServer,kbGuid,guid,imageFileAbsPath,token).then(res=>{
                console.log("图片url:")
                url = `https://www.wiz.cn/xapp/ks/note/view/${kbGuid}/${guid}/`+res.url
                //console.log('https://www.wiz.cn/xapp/ks/note/view/'res.url)
                console.log(url)
            }) //打印图片的url
        }
    });

}

if (program.opts().file){
        uploadNoteFile(program.opts().file);
    console.log("更新博客")
    if (program.opts().image){
        console.log("上传图片")
        uploadNoteFile(program.opts().file,program.opts().image);
    }
} 

4. 配置

创建配置文件名称:wiznote.json,路径跟脚本路径一致,格式如下:

配置文件可以随便改动,保证脚本代码能加载就行。其引入脚本的代码:const CONFIG_JSON = 'wiznote.json'

{
    "userId": "为知笔记帐号",
    "password": "为知笔记密码",
    "category": "/要上传的目录/"
}

5.deepin创建右键发送菜单选项

deepin操作系统下,终端执行sudo vim /usr/share/deepin/dde-file-manager/oem-menuextensions/deepin-send.desktop

内容如下,保存退出

[Desktop Entry]
Type=Application
Name=发布文档到
Actions=SendTocnblogs;SendTonsccwx;SendTowiznote
X-DFM-MenuTypes=SingleFile
MimeType=text/markdown

[Desktop Action SendTowiznote]
Name=为知笔记
Exec=nodejs /home/liwl/.liwl/deepin/scripts/send_to_wiznote.js --file %U
Icon=send-to

6. 总结

这个js脚本,仅仅实现了,不含图片的笔记创作及更新,然后右键发送。

相比以前的版本,也就是多了一个同一个笔记文件,更新发布的功能。

算是个半成品吧,以后有空再完善,这次就当练习js编程吧

posted @ 2021-12-13 10:26  liwldev  阅读(91)  评论(0编辑  收藏  举报