日々是好日

プログラミングについてのあれこれ、ムダ知識など

はてな API を叩いて投稿

はてなブログへの記事投稿部分の実装。この記事も VSCode 拡張機能からの投稿です。

HatenaBlogUtil

Post するデータはまるっとoauth.postcontentに入れてしまえば OK らしい。

export default class HatenaBlogUtil{
    postMember() {
        ...
        const folders = vscode.workspace.workspaceFolders;
        if (folders !== undefined){
            //Macはfolders[0].uri.path
            const root = folders[0].uri.fsPath; 
            const converter = Converter.getInstance();
            this.oauthPOST(this.atomUri + "/entry", converter.createPostData(root), (err, result, responce) => {
                console.log(err);
                console.log(result);
            });
        }
    }

    private oauthPOST(uri: string, content: any, callback: OAuth.dataCallback) {
        if (this.authorizer.existAccessToken()){
            const oauth = this.authorizer.getOAuth();
            oauth.post(uri,
                'Access Token',
                'Access Token Secret',
                content,
                'text/x-markdown',
                callback
                );
        }
    }
}

Converter

Converterはとりあえずシングルトンで実装。 readFileSyncは非同期版のreadFile使いたいけど、軽度のコールバック地獄になりそうなので思案中。

export default class Converter{
    ...
    createPostData(root: string, draft?: boolean) {
        const prefs = vscode.workspace.getConfiguration('UserPreferences');
        const id = prefs.get<string | undefined>('id');
        const _content = fs.readFileSync(root + "\\content.md", {encoding: 'utf-8'});
        const content = this.escapeHtml(_content);
        const _config = fs.readFileSync(root + "\\config.json", {encoding: 'utf-8'});
        const config = JSON.parse(_config);
        const useDraft = draft? 'yes' : 'no';

        const data =
            '<?xml version="1.0" encoding="utf-8"?>' +
            '<entry xmlns="http://www.w3.org/2005/Atom" ' +
            'xmlns:app="http://www.w3.org/2007/app">' +
            `<title>${config.title}</title>` +
            `<author><name>${id}</name></author>` +
            `<content type="text/x-markdown">${content}</content>` +
            this.createCategoryTerms(config) +
            '<app:control>' +
            `<app:draft>${useDraft}</app:draft>` + 
            '</app:control>' +
            '</entry>';
        
        console.log(data);
        return data;
    }

    private createCategoryTerms(config: any) {
        const category = config.category;
        let terms: string = "";
        category.forEach((element: string) => {
            terms += (`<category term="${element}" />`);
        });

        return terms;
    }

    private escapeHtml (content: string) {
        const replaceMap: {[key: string]: string} = {
            "&": '&amp;',
            "'": '&#x27;',
            '`': '&#x60;',
            '"': '&quot;',
            '<': '&lt;',
            '>': '&gt;'
        };
        
        return content.replace(/[&'`"<>]/g, (match) => {
          return replaceMap[match];
        });
    }
}

content.md

はてな Markdown で書くだけ。

config.json

{
    "title": "はてな API を叩いて投稿",
    "category": [
        "VSCode",
        "VSCode拡張機能開発",
        "TypeScript",
        "プログラミング"
    ]
}

画像はまだ使えないけどショートカットとかハイライトとか使えるのでめっちゃ書きやすい!!ユーザスニペットも設定してるのでやばい!!(自画自賛

参考

Html エンコードについて。

qiita.com