MoreRSS

site iconEST修改

EST = Extrospect, Sein & Tao ,后端工程师。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

EST的 RSS 预览

gitweets:单html实现独立微博,拿git历史当feed流发推

2025-08-17 00:00:00

twitter争议不断持续多年,先是各种 cancel culture 闹得动静很大,被一龙马买了之后更甚,社区分裂到 mstdn nostr bsky支流,各种话题炒上天,在众多替代品里,2022年看到个最别具一格的:

拿 git 当微博使

  • 发推: git commit --allow-empty
  • 加关注: git remote add <alias> <their fork url>
  • 转发: git cherry-pick <their "tweet">

脑洞大开。而且git基于merkle tree的,p2p 历史不可篡改,有web3那味了。

当时就饶有兴趣,挖了个坑准备搓个web界面。但是限于涣散的注意力,以及对css这种抽象排版玩不转,一直拖沓没做好。

周末心血来潮,外带 AI 工具加持,进展神速。目前已经基本可用。

项目叫 gitweets ,意思是用 git 发 tweets,网址在 https://f.est.im/ 。二级域名 ffeedf.est 也就是 fest 表示。。。 盛会的意思。

feature list

  1. 把任意 github repo 渲染成微博
  2. 给任意 github repo 发推。其原理是,通过REST API新增一条 commit 。
  3. 发图!如果 commit message 以冒号结尾,而且恰好也在本次新增加了位于 static 下面的图片文件 那么会尝试去加载图片作为附件渲染
  4. 写 commit 基于 OAuth app 实现。浏览器记录 access_token 到 cookie,理论上可用 8个小时。过期重登
  5. 如果你的 commit 有是通过 -S 参数提交带签名 ,那么展示为蓝色表示verified

记录一些坑

  1. OAuth app vs Github App。前者是代客做事;后者是独立主体单独账号,类人行为,多用于 CI/CD
  2. OAuth app 的 scope 如果是 repo 可以读写你所有仓库代码,包括私有仓库!网上的很多基于 github 的第三方评论系统有这个隐患!
  3. 我这里用的是 public_repo,读写所有公开仓库。毕竟 github是个开源社区,拿公开git来当feed使,要安全一些。
  4. 更安全的办法是只能读写单个指定的repo。要实现API读写git,在github有下列几种方法:
    • REST API。可以用 fine grained PAT 读写一个repo
    • GraphQL API。
    • git 协议。走 github.com:22 端口。可以采用 deploy key 或者私人账号 ssh key
    • git-http。走 https://github.com:443
  5. Private Access Token (缩写 PAT) 可以完全控制个人或者团队账号,fine grained PAT 可以只控制指定的几个仓库
  6. deploy key默认只读,可以改成读写,一库一用,不能复用
  7. REST API 列举 commits 不能获得当前 commit 改了哪些文件。需要额外N+1每个commit再次查询详情。背后的原因估计是 git 内部 ref 和 blob 是严格区分的。甚至可能是分开存的数据库表
  8. 网站是跑在赛博菩萨 cloudflare worker 上的。这种所谓“serverless”平台很强大了。功能齐全没啥缺的。甚至可以发起 tcp 连接。
  9. 本来计划走 git-ssh 或者 git-http 协议,想了下js操作binary太复杂了,弄个 libgit2 之类的库估计很重。还是REST方便
  10. REST API 新增一个 empty commit 有多复杂? 1. 获得当前branch 的 sha 2. 获得该 sha 的 tree 3. 新增一个 sha+tree 的commit 4. 把 ref 指向第三步的 sha 。啊,就不能一步完成么。下次有机会看看GraphQL 能不能一次调用完成
  11. Github 的API 强制要求 User-Agent 。你可以乱写但是不能没有
  12. Github 虽然返回了 Access-Control-Allow-Origin: *,但是现代浏览器他妈的不认这个 * 。所以在浏览器只能匿名调用 GET ,如果 POSTPATCH 带了 credentials: "include" 直接拒绝。网站必须显式指定允许哪个具体的 origin
  13. cloudflare的 Response.redirect('/') 直接挂掉。原来是 3xx 跳转不允许相对路径。

why?

由于习惯,古法写web,一个html包含了 css js 。无二次加载,无第三方依赖库。除了不能写死的全部写死 🤣。无需build。

源码放在 https://github.com/est/gitweets/ 。该仓库的 commit 历史也作为feed展示在 https://f.est.im/

接下来准备用类似的思路实现网站评论系统,代替现在的 disqus ,虽然它是免费的,但是广告太多了。

可能有人要问:why ?闲的蛋痛?

我想,首先的确蛋痛,because we can。其次是不想在平台,处处受人限制。然后也是最重要的,self-host。所有数据资料都在一个repo打包带走,备份什么的很方便。比如以前wordpress受众多功能全,但是后来大家都 hexo 之类的静态blog了。

我心目中 gitweets 就是“静态”微博的一种。虽然它现在还是依赖 github API。等有空了可以试试生成纯静态页面。

ToDo

  1. 如何发视频 音频
  2. 如何转发
  3. 如何混合展示多个repo的feed。基于 pull request ?

欢迎评论或者提 issue

敬语和咒语

2025-08-12 00:00:00

因为旅游瞎逛,才了解有这样一种东西:

字库塔又叫“惜字宫”、“敬字亭”、“惜字塔”、“焚字炉”等,它是收存和焚烧字纸的专用设施,沿自古人有“敬惜字纸”之风,“惜字得福”之说。而在我国传统文化中有一种独特习俗——“惜字如金”,“敬天惜字”。
于是,焚烧字纸就变得非常的郑重,不但有专门的礼仪,还建有专门的场所和设施,于是“字库塔”就应运而生,也就成了古人专门修建来焚烧字纸的小型建筑。据史料记载,字库塔始建于宋代,到元明清时已经相当普及了。
在古代,民间有种说法,糟蹋字纸会生疮害病、瞎眼睛,受到惩罚并祸及子孙等,因此字纸不可秽用,而应该“羽化成蝶”,而糟蹋字纸会得罪神灵,受到惩罚并祸及子孙。所有用过的字纸或废书,都要统一收集起来,放到一个地方集中焚化。

小时候,一直把语言和文字当成知识的载体,是语文和英语这样的学科,一种很客观的工具。没想到古人对待文字是如此的神圣,甚至达到需要单独做祭坛的程度。最近几年也一直有感触,语言和文字肯定以及必然在上古时期是有魔法的。

这个魔法怎么来的,比如人类最原始,最古老的语言词汇,肯定是 妈妈,爸爸。

一个孩子叫你一声父母,你身上就多出来一份悲怜和责任。据我观察,很多成年人和家庭,都是因为孩子,苦苦撑下去。没有软肋的中年人是无敌的。

所以我觉得,某种程度上,这个称谓是一种咒语。为什么是咒语?拿魔幻小说《哈利波特》为例,最入门的打架咒语就是 “除你武器” (Expelliarmus)。这是哈利的招牌咒语,作用是让对手手里的武器(通常是魔杖)飞出去,有时也会直接把人震退。如果你在网上或者现实中骂架,让对方直接破防的咒语是啥呢?

我是你爹!

对方要破除你这个咒语,那么多半会使出类似下面这样的咒语:

我今天非教训你这孙子不可

爹,孙子 这些人类最基础的代词,居然有如此调动情绪魔力。

又看到最近和长久以来一个被反复提起的话题:

媒体呼吁「同志」称呼重归主流

曾几何时,招呼人无须刻意措辞,一声“同志”便可,听者坦然、舒泰。后来,经济发展、文化多元,称呼也花样百出,“先生”“小姐”“老板”满天飞,开初尚觉新鲜,久之不免腻味,尤其是“小姐”这一称呼,常给人轻薄之感。如今,“小姐”似乎被“美女”取代,后者也逐渐失掉了赞美之意,变成了泛称。
称呼自有其潮流,随时代而动。譬如“同志”,在民风淳朴的年头,人们不论是在工作中,还是在生活里,都讲究人人平等,因而“同志”这种一视同仁的称呼也被长久使用,且“同志”也有志同道合之感。再如“师傅”,使用的时间也不短,于我个人而言倍觉亲切。我年轻时在机务段当过3年机车钳工学徒工,满师后又独立干了一年左右车辆修理活计。当时,早我几天入行的师兄师姐,我见了一律都得叫“师傅”。在技术为先的机车维修一线,学艺是头等大事,称呼关乎传道授业的礼仪,自然马虎不得。“师傅”之谓,是对有一技之长劳动者的尊称,也是对德厚者的敬重。几十年之后,虽然热火朝天的劳动场景已远去,但是这声“师傅”,我沿用至今。我想,只要对方形容不轻慢,精神不委琐,不论老少,皆可尊称一声“师傅”。

中年人应该对这个最有感触的。小时候以为所有人都叫 叔叔阿姨 就够了。直到有一天,你被别人叫了 叔叔阿姨。身份的转变带来一个困境:原来的叔叔和阿姨,你如何称呼?

能否避免让别人觉得太老?能否不区分职业、职级?能否不区分性别?

有没有一个通用敬语?想来想去,排除上面的“同志”,似乎只有 老师?

没有一个咒语拿来起手破冰,所以一旦脱离了乡土的熟人社会,陌生的人际交往在大城市就很难发生。

身份认同、权力关系、情感负担,这些都是心理学上焦虑和矛盾的根源

想起一个孙猴子那个经典笑话

“原来你就是那闹天宫的弼马温么”
行者道:“是你也认不得你老外公哩。你老外公乃大唐上国驾前御弟三藏法师之徒弟,姓孙,名悟空行者。若问老孙的手段,说出来,教你魂飞魄散,死在眼前。”那怪道:“我不曾会,你有甚么手段,说来我听。”行者笑道:“我儿子,你站稳著,仔细听之。我:

自小神通手段高,随风变化逞英豪。
养性修真熬日月,跳出轮回把命逃。
一点诚心曾访道,灵台山上采药苗。
那山有个老仙长,寿年十万八千高。
老孙拜他为师父,指我长生路一条。
他说身内有丹药,外边采取枉徒劳。
得传大品天仙诀,若无根本实难熬。
回光内照宁心坐,身中日月坎离交。
万事不思全寡欲,六根清净体坚牢。
返老还童容易得,超凡入圣路非遥。
三年无漏成仙体,不同俗辈受煎熬。
十洲三岛还游戏,海角天涯转一遭。
活该三百多馀岁,不得飞升上九霄。
下海降龙真宝贝,才有金箍棒一条。
花果山前为帅首,水帘洞里聚群妖。
玉皇大帝传宣诏,封我齐天极品高。
几番大闹灵霄殿,数次曾偷王母桃。
天兵十万来降我,层层密密布枪刀。
战退天王归上界,哪吒负痛领兵逃。
显圣真君能变化,老孙硬赌跌平交。
道祖观音同玉帝,南天门上看降妖。
却被老君助一阵,二郎擒我到天曹。
将身绑在降妖柱,即命神兵把首枭。
刀砍锤敲不得坏,又教雷打火来烧。
老孙其实有手段,全然不怕半分毫。
送在老君炉里炼,六丁神火慢煎熬。
日满开炉我跳出,手持铁棒绕天跑。
纵横到处无遮挡,三十三天闹一遭。
我佛如来施法力,五行山压老孙腰。
整整压该五百载,幸逢三藏出唐朝。
吾今皈正西方去,转上雷音见玉毫。
你去乾坤四海问一问,我是历代驰名第一妖。”

那怪闻言笑道:“你原来是那闹天宫的弼马温么?”

行者最恼的是人叫他弼马温,听见这一声,心中大怒

这一切也发生在职场。现在流行把同事叫 “同学”。我对此能接受,但是总感觉哪哪不对。

比如你求其他部门的人办事,你又没身份来安排别人,叫 “同学” 恐怕不行吧?的还是叫 “大佬”?你也不清楚对方职级,叫 “同事” 会不会太对等了?

对于我这种社交白痴,万分纠结。

职场混久了,感悟很多事儿其实是跟业务无关的。规章制度更多的都围绕一个核心:不信任成本。官场也一样,不要看什么AI 智慧城市 什么的,哪里有那么多 intelligence。全都是 diligence 不够。

为什么 diligence 不够?现代社会分工太细,你使唤不动别人。

很多事你是有心无力的。

或许,离开了原生家庭,这个世界没有魔法了。

原研哉《棍子和碗》

2025-06-18 13:55:00

之前看到个 棍子和碗 的说法,印象很深,觉得很扯,总觉得哪里不对,但是没想明白。查了下居然是 原研哉 说的。也就是传说中200w给小米logo倒了个圆角的日本设计师。

日本设计家原研哉有一个说法,他说,这个世界上,我们用的所有东西只有两样,一个是碗,一个是棍子。什么意思?
碗,就是用它围合起来的那个内部空间。比如水缸、冰箱、液化气罐、汽车、房子、手机,本质上都是碗。它内部装了什么,决定它是什么。
而棍子呢?就是用它去作用于其他东西。比如弓箭、螺丝刀、枪炮、键盘,本质上都是棍子。它作用于什么,才决定它是什么。
其实,我们中国人在文化中也有类似的分类法。我们经常说一个词“器具”。所谓“器”,就是装东西的,就是原研哉说的“碗”;而“具”呢,就是作用于其他东西的,就是原研哉说的“棍子”。这两样东西合起来就是“器具”,也就是人类造出来的所有东西的统称了。
之所以提这个分类方法,是想说,我们观察任何东西,都有两个角度,一个是看它内部装的是什么,就是它作为一只“碗”的特质。还有一个,就是看它作用于什么,就是它作为一支“棍子”的特质。
比如说,我们了解一个人,当然可以把它看成一只碗,看他身体内部的状况,给他做体检,和他谈心,看他的所思所想,这是了解一个人的方法。但是我们也可以把他看成是一根棍子,在他周边的社会关系中进行访谈,看他干了什么,成就了谁,又祸害了谁,他在自己的社交网络里面填补了什么空白,他的每一个行动是在应对什么挑战。

刚中午小憩的时候,突然想通了,这个二元论分类太内涵,太隐晦了。我不妨帮日本人把这个分类说得更直白一些:

  • 棍子就是 JJ
  • 碗就是 子宫

A single Python function for both async/sync

2025-05-14 14:35:00

Scenario: I often need to write Python functions like:

  1. take some parameters and format them
  2. call an API with the formatted parameters
  3. parse the result and return chosen values

There's a huge problem in step #2.

In today's Python world, troubles arise because async/await are "infectious", In practice this function is splitted - like in Python stdlib, where a vanilla method and its async counterpart amethod often come in pairs. Package authors scramble to provide sync transport and another async transport. I discovered this ugly fact while reading the source code ofredis-py, httpx and elasticsearch-py. Duplicate and lookalike code was always written twice. All it takes is some random async IOs in one place and your code would be forced to change forever.

Is there a way to write the function in one place, but callable both with async and without?

I pondered this question for ages, and today I stumbled upon something interesting:


  def s1():
    return asyncio.sleep(1)

  async def s2():
    return await async.sleep(1)

There's virtually no difference when calling await s1() and await s2()

I vaguely remembered how Python’s coroutines were designed, and after some tinkering, I came up with this snippet:


import asyncio, types, functools

def aa(f):
    """
    make a function both awaitable and sync
    idk how to property name this. anti-asyncio (aa) maybe?
    """
    @functools.wraps(f)
    def wrapper(func, *args, **kwargs):
        if asyncio.iscoroutinefunction(func):
            return types.coroutine(f)(func, *args, **kwargs)
        else:
            async def afunc(*a, **kw):
                return func(*a, **kw)
            g = types.coroutine(f)(afunc, *args, **kwargs)
            try:
                while True: next(g)
            except StopIteration as ex:
                return ex.value
    return wrapper


@aa
def my_func(func, *args, **kwargs):
    # prepare args, kwargs here
    # add a prefix `yield from` everywhere, for either sync/async
    result = yield from func(*args, **kwargs)
    # handle the result here
    return result


import httpx

# async
async def main():
    # the same as `await httpx.AsyncClient(timeout=3).get('https://est.im')`
    print(await my_func(httpx.AsyncClient(timeout=3).get, 'https://est.im/'))
asyncio.run(main())


# sync
print(my_func(httpx.get, 'https://est.im'))
# works the same as httpx.get('https://est.im')

The above shows a single function called my_func, dependency injection of an HTTP get call of either sync/async, allows for customizable pre- and post-processing logic, and returns the result with clean syntax.

The only mental tax: inside my_func, you have to replace all await keyword with `yield from.

Update 2025-05-16: The only mental tax: add a yield from prefix for every funccalls for IO or API, either sync or async.

It solves all problems for my scenario and I’ve yet to find a simpler solution. If you have a good name for the @aa decorator please comment!

A sidenote, I am not sure if this method affects async schedulers and blocks something maybe? Like the while True might be a new kind of GIL. Also i haven't looked at problems with contextvars.

听 彭罗斯 吹了90分钟波函数的坍塌

2025-04-30 16:31:00

https://www.youtube.com/watch?v=sGm505TFMbU

Roger Penrose: I don't believe it is consciousness that collapses the wave function, instead it's the collapse of the wave functions that produces consciousness

这句话很美妙啊。一下子把唯物和唯心给联系起来了。

我一直觉得,人的意识,就是因果律的推演。这个推演明显是一个离散的,有清晰步骤的,quantized 的和决定论的。

人的潜意识和直觉可能是概率的。

看完这个 90分钟的访谈,我大概明白为啥 量子力学 和 神棍 经常联系在一起了。一切都源于这个薛定谔方程 和 “观察者”

观察者不是一个真实存在的定义。你甚至无法严格定义 观察。欧美神棍一般喜欢往三位一体,意识,灵性上面靠。感觉物理世界是混沌的,一下子有了光,状态就坍缩了。哈哈哈。

国内的话 遇事不决,量子力学。民科重灾区。甚至还有量子佛学这种离谱的。

他还写了一本书,Fashion , Faith and Fantacy,fashion就是弦论,faith 就是量子力学。fantacy是宇宙膨胀理论。哈!

光 的本质是什么?

2025-04-29 14:20:00

来自 Curt Jaimungal

Guy:什么是光?
Chap:嗯,光是使物体可见的东西……
Bloke:其实,光也可以是不可见光谱的一部分,比如紫外线和红外线……
Lass:其实,光是光子,是电磁场中的一种波动……
Dude:其实,光子是电磁场中量子化的波动……
Fellow:其实,光子是与狄拉克方程的 U(1) 对称性相关的规范玻色子……
Guy:其实,光子是与狄拉克方程的局域 U(1) 对称性相关联的规范玻色子……
Fellow:其实,光子场来源于 SU(2)ʟ × U(1)ʏ 的一个子群——该子群保持希格斯真空态不变……
Chap:其实,光子一种导数……
Guy:其实,光子是为了使导数具有规范不变性而进行的修改,和刚才那位说的一样……
Lass:其实,光子是庞加莱群的一个表示……
Dude:其实,光子是庞加莱群的一个不可约表示……
Fellow:其实,光子是庞加莱群不可约表示的一个基底元素……
Guy:其实,光子是一个四维时空中无质量、自旋为 1 的粒子……
Chap:其实,庞加莱群本来就在四维时空中,所以这是多余的细节……
Bloke:其实,庞加莱群可以推广为任意维度 d 下的 ISO(1,d−1) 群……
Lass:其实,d 必须大于 2,否则系统会出现简并结构……
Dude:你才简并呢……哦不好意思……我是说,其实,光子是从超图的底层更新规则中涌现出来的一种现象……
Fellow:其实,光子是统一规范势 ϖ 中与结构群 Spin(4) 子群相关的一个特定分量,而这些规范分量是通过观测嵌入被拉回到我们 4D 时空中的……
Guy:其实,我们原本是在谈“光“这个词,它源自古英语 lēoht,意思是“亮度“……
Chap:其实,它是原始日耳曼语 leuhtam,也表示亮度——所以你这次总算说对一件事……
Dude:其实,词源更早是原始印欧语 leuk-,意为“光、亮“,同源词有拉丁语 lux、希腊语 leukos(意为“明亮、白“)……
Lass:其实,还可以追溯到梵语 rochis,意思也是“亮度“……
Dude:其实,你不该说“其实“,你破坏了节奏……
Fellow:其实,词源顺序是:古英语 → 拉丁语 → 原始日耳曼语 → 希腊语 → 梵语 → 原始印欧语……
Guy:其实,光是黑暗的缺失,而黑暗的定义是邪恶……
Chap:其实,“邪恶“可以在扭量空间中建模为全纯对象……
Bloke:其实,我们回到光子的问题,它在弦论中是 H¹(T, O(−2)) 的一个上同调类,其中 T 是扭量空间,O(−2) 是一个全纯线丛,用于编码自旋为 1 的无质量场的螺旋度……
Lass:其实,光子是共形场论中的边界激发……
Dude:其实,光子是电子-正电子对自纠缠形成的涡旋结构,可能包含 T4G 框架下的虫洞子结构……
Bloke:其实,光子是由弦局域场表示的,属于庞加莱群下零质量、无限自旋的表示……
Fellow:其实,光子是一个沿零测地线传播的无质量粒子……
Guy:其实,引力子和其他假设粒子也可以是无质量的,并沿零测地线传播,所以……
Chap:其实,光子是光中微子的超对称伴粒子……
Bloke:其实,在弦论中,光子是开放弦的第一个激发态,通常出现在 Neveu–Schwarz 扇区……
Lass:其实,你们已经这样说了五十年……
Dude:其实,我没说五十年,不然我一直在呼气早就不能呼吸了……
Fellow:其实,你太咬文嚼字了……
Dude:其实,我只是在追求表达的精确性……
Chap:其实,你表现出对“其实”准确性的过度执着,并在越来越细微的细节上纠缠,以至于忽视了整体,这正是咬文嚼字的体现……
Bloke:其实,你的指责本身是主观观点,而不是“其实”判断……
Dude:好吧,这有点失控了。
Chap:其实没有,一切都在掌控之中。
Fellow:你是个傻子。
Guy:而你没有动用你整个大脑。
Fellow:这没关系,因为人类本来也只使用了 10% 的大脑……
Bloke:……
(众人互望)
(沉默十秒)
Fellow:……
Guy:(看着 Dude)还是别说这个了——
Dude:其实……

Curt Jaimungal 的视频看着真过瘾。我是从他 youtube 频道 Theories of Everything 最近一期喷真理元素 (Veritasium) 了解这个人物的。北美何教授。