自动化数字生活:收藏网页 - 聊天工具

浏览器在桌面操作系统之间达成了一个「平台」的效果,使得我们可以直接编写基于浏览器的脚本,来方便地在不同桌面操作系统之间使用自动化工具。于是我们有了油猴脚本

但是手机上呢?为了在移动设备和桌面系统中都能使用同一个自动化工具,我尝试了一些聊天工具。由于良好的跨平台适配,Telegram 和微信都能够比较好地运作。

由于这两个聊天工具中都是纯编码实现的,我也不准备分享完整的代码,所以只是提个扼要,看看一种可能性。

Telegram Bot

官方的 API 库提供了非常详细的文档,我使用了一个第三方库来更加方便地处理。

造个 Bot

@BotFather/newbot 之后,他会引导你一步步完成 Bot 的创建。

同时获得一个 token 用来访问 API,在代码实现中会用到:

const bot = new TelegramBot(token, { polling: true });

接着我们继续跟 BotFather 聊天,给我们的 Bot 加入一些快捷功能。我们跟他讲 /setcommands 之后,他会让我们按格式输入命令列表:

这样,我们在跟 Bot 聊天时就可以输入 / 来唤起功能菜单了:

处理这些命令

对于其中的每一个命令,都设置一个消息处理,如果不包含命令就视为新增书签。

bot.onText(/\/add(.*)/, (msg, match) => {
//...
});

bot.onText(/\/pull/, (msg) => {
//...
});

bot.onText(/\/untagged/, (msg) => {
//...
});

bot.onText(/\/search(.*)/, (msg, match) => {
//...
});

bot.onText(/\/recent/, (msg) => {
//...
});

bot.onText(/^[^/]/, (msg, match) => {
//...
});

在后台处理时,可以给 Bot 加一个「Typing」的提示:

bot.sendChatAction(msg.chat.id, 'typing');

msg 中包含了消息的所有信息,可以查看官方对 Message 的详细说明。

增加书签

直接发送链接或者通过系统分享发消息给这个 Bot,就可以收藏书签。Bot 会直接回复那条信息,并提示标题和保存结果。

添加到 Pinboard 后,直接回复:

if (info == 'done') {
opts['disable_web_page_preview'] = true;
bot.sendMessage(chatid, title + '[提示] 祝贺!已添加新条目到 Pinbaord', opts);
}

拉取书签

其他几个功能是在一次 Pinboard 服务器崩溃之后所做的,那时候服务器经常访问不上,中文搜索也崩溃,于是我自己在本地搭了个数据库,方便使用。

通过 pull 的功能,是可以把服务器上的书签全部拉取到本地。这个过程本身是定时启动的,也可以手动执行。

搜索书签:按钮功能

搜索功能每 5 条一页,点击按钮可以直接翻页。

在代码中,每一个按钮都被赋予了一个 callback_data 作为标识:

markup = [
[{
text: '继续',
callback_data: 'fnext' + cache_id
},
{
text: '翻页',
callback_data: 'fgoto' + cache_id
}]
];

bot.sendMessage(msg.chat.id, msg_to_bot, {
reply_to_message_id: msg.message_id,
disable_web_page_preview: true,
reply_markup: {
inline_keyboard: markup
}
});

接收到按钮点击事件时,直接根据传入的标识进行不同的处理:

bot.on('callback_query', (query) => {
const action = query.data;
if (action.startsWith('http')) {
} else if (action.startsWith('fnext')) {
} else if (action.startsWith('rnext')) {
} else if (action.startsWith('rgoto')) {
} else if (action.startsWith('fgoto')) {
} else {
}
});

根据官方文档:

After the user presses a callback button, Telegram clients will display a progress bar until you call answerCallbackQuery.

因此在处理 callback_query 之后要记得加上:

bot.answerCallbackQuery(query_id);

也可以跟一些提示信息,这个信息可以设置直接弹窗,也可以在聊天窗口顶部弹出,对用户来说比较醒目:

bot.answerCallbackQuery(query_id, {
text: '结果已过期,请重新执行搜索',
show_alert: true,
});

查看最近书签

使用 recent 命令查看最近书签时,同样加入了按钮来翻页。

翻页后,会回复前一条消息,方便回退。

给书签加标签:快捷动作

untagged 命令可以提取没有加标签的书签,一条条地加上标签。消息中带有 / 的短语是可以直接点击并发送的,跟按钮的作用类似,非常方便。

所以代码中还需要加几个处理:

bot.onText(/\/clear/, (msg) => {
//...
});

bot.onText(/\/cancel/, (msg) => {
//...
});
bot.onText(/\/next/, (msg) => {
//...
});

微信公众号

去微信公众平台申请个公众号吧。现在个人号的权限实在太小,如果能上微信认证,就可以更好地运用微信平台了。

除了直接跟着官方文档走,微信公众号的开发也可以借用第三方库

进入管理界面之后,打开「开发」菜单下面的「基本配置」,根据提示配置好后,把相应的内容填入代码:

const config = {
token: '',
appid: '',
encodingAESKey: '',
checkSignature: true,
};

另外需要一个服务器库配合,这里使用 Express

const express = require('express');
const app = express();
app.use(
'/your-wechat-url',
wechat(config)
.text(async function(message, req, res, next) {
const url = message.Content.match(/http.*(\s|$)/);
const result = await pin(url.toString());
return res.reply(result);
})
.link(async function(message, req, res, next) {
const result = await pin(message.Url);
return res.reply(result);
})
.middlewarify()
);

我对 text 类型和 link 类型进行了处理,读取链接并保存到 Pinboard 中。

保存的函数也很简单:

async function pin(url) {
const resp = await post('https://demo.pin.o2as.com/bookmark', {
json: true,
body: { url: url },
headers: {
Authorization: 'Basic blogO2AScom',
},
});
let result = resp.body.message;
if (result.includes('done')) {
result = resp.body.title;
}
return result;
}

这样,服务起来之后,直接在微信中发送一个链接就可以保存啦。

不过微信不支持直接转发公众号给公众号,不然通过这种方式保存书签会更加方便得多。