《红楼梦》碎碎念

个人读《红楼梦》之所感所思,想到哪儿,写到哪儿,不拘章法,也无体系,不求闻达,但求深思。

2023-05-07 word 1 min

Telegram bot 入门实践

什么是 Bot Bot 的概念在官网的介绍稍微有点繁琐和复杂,详细可以了解官网介绍, 简单来说,bot 就是你在 telegram 中的一个特殊账号,你申请了 bot,这个 bot 就是你的代理人,你发号施令到 bot,bot 会响应你的指令,仅此而已。 申请 bot 需要找 BotFather(名字起的很形象),具体过程官网说的比较详细,此处不赘言。但是需要强调的一点是,bot 仅仅是你的代理人而已,真正执行你指令的是你自己部署的脚本,如果你不部署自己的脚本,在 bot 中输入指令,是没有任何响应的。 你、bot和你部署的脚本关系如下: 脚本 上面说过了,bot 只是你在 telegram 的一个代理,真正干活的是你的脚本。既然自己写脚本,就会存在两个问题:接受指令、做出响应。 接受指令 对于如何让脚本接受指令,官方提供了两种思路:推模式 、拉模式。 拉模式 这种模式,官方不太推荐。简单而言,就是自己部署一个脚本,不断执行 get 请求,获取自己 bot 的更新信息,就好比一个仆人一直在问你: 有没有需要我做的? 有没有需要我做的? 有没有需要我做的? 询问的方式也比较简单: curl -X GET https://api.telegram.org/bot[token]/getUpdates 这里的 token,就是上面申请 bot 完毕后,得到的 token, 出于脱敏,我使用 [token] 代替,下同。这种方法比较笨拙,轮询的频次太高和太低都不行,而且你在 bot 中发布一条指令后,可能并不能够马上得到执行,会有延迟。 这种方式的好处是:可以让 bot 启在本地,不需要部署到服务器上,因为 telegram 不知道你的存在,他也不需要知道你的存在。 推模式 这种方式是官方比较推荐的一种方式,这种类似事件驱动的原理。只有有任务了,才会通知脚本去做。但前提是:在向 bot 发号施令前,需要在 bot 中注册一个 callback url。 bot 在接受你的指令后,会调用此 url,通知你的脚本,让他执行任务。 注册方式也比较简单:...

基于 PostgreSQL 的群聊搜索实践

背景 2021年年初,探探上线了群聊功能,并且支持按照群名进行模糊搜索。 对于复杂场景的搜索,业界一般使用非常流行的 ElasticSearch。由于我们的群数据较少,截止到目前还没有达到千万级的量级,且搜索场景比较简单,而 PostgreSQL 对全文搜索又支持得比较好,所以选择了 PostgreSQL 来实现群搜索需求。 在使用 PostgreSQL 做群搜索的过程中,也经历了由简单到复杂的迭代过程,中间也踩了不少坑。 下面的几个例子说明了方案的演进过程和我们的优化思路,希望能够对大家有所帮助。 LIKE 模糊查询 提到模糊搜索,最简单的办法就是对搜索列进行 like 匹配: 在输入词的前后加上 % 即可,如下所示: SELECT * FROM groups WHERE name LIKE '%探探%'; 这种方案可行是可行了,但是实现过于简单粗暴。对此方案进行测试: 建一张简单的表进行测试,表结构如下: lixuehan=# \d groups; Table "public.groups" Column | Type | Collation | Nullable | Default --------+-----------------------+-----------+----------+------------------------------------ id | bigint | | not null | nextval('groups_id_seq'::regclass) name | character varying(50) | | | Indexes: "groups_pkey" PRIMARY KEY, btree (id) 表中只有两列:主键 id 以及群名 name。...

Hugo 中的命令行模式

最近在用 hugo 构建了个人博客之后,便有兴趣想研究下其源码。但是源码的体量之大,逻辑之复杂出乎我的意料。不过好在源码的结构比较清晰,有许多地方值得借鉴。 比如它的程序入口,非常简洁: func main() { resp := commands.Execute(os.Args[1:]) if resp.Err != nil { if resp.IsUserError() { resp.Cmd.Println("") resp.Cmd.Println(resp.Cmd.UsageString()) } os.Exit(-1) } } 它将所有根据命令行参数传入的指令统一封装到 commands 包中。后面有新命令需求时,只需要新建一个 cmd 文件即可。 它是怎么做到的呢? 简而言之,就是在程序入口处将所有的命令类汇总,然后再根据输入参数args,决定要执行哪个cmd,看似增加了代码的复杂度,但是对于后续命令的扩展显得非常方便。 hugo 中使用了 builder 模式将所有的命令汇总,我这里简单起见,只初始化了一个数组,主要是体会其开闭原则的思想即可。 Talk is cheap, show me the code 借鉴它的思路,我写了一个简化版,可以参看,代码链接.

2020-06-26 43 words 1 min