包含关键字 typecho 的文章

目前,原“死了么”APP 在部分地区 App Store 上线 2.0 版本。更新记录显示,新版本新增签到提醒、短信通知,并修复若干问题。

值得注意的是,“死了么”APP 此前宣布要在新版本中正式启用全球化品牌名称“Demumu”,目前也已更名。


据介绍,该应用是为独居人群打造的轻量化安全工具。

用户需要设置紧急联系人并签到,若连续多日没在应用内签到,系统将于次日自动发送邮件告知紧急联系人。


6.99 刀,真的有人买么,我建议改成订阅制的🐶

前几天看到有小伙伴的帖子说他的开源被阮一峰老师的科技爱好者周刊选中了,我上周也去投稿了我的 EasyPostman,很开心也被选中了。
https://www.ruanyifeng.com/blog/2026/01/weekly-issue-382.html

10 月份我发布的 用 Java 写了个开源的 Postman 替代品,本地存储 + Git 协作 https://www.v2ex.com/t/1167863

EasyPostman 是一款开源的 API 调试与性能测试工具,对标 Postman + JMeter ,专为开发者优化,界面简洁、功能强大,内置 Git 集成,支持团队协作与版本控制。

test

https://imgur.com/a/c91Y7m3

项目地址: https://github.com/lakernote/easy-postman

国内镜像: https://gitee.com/lakernote/easy-postman

[Flutter 独立开发] 挑战千元机极限:纯客户端计算 K 线+指标,三星 A53 实测 70 FPS

大家好,我是《交易学徒》的独立开发者,祝大家周末愉快!

做过金融类 App 的朋友都知道,移动端的 K 线图( Candlestick Chart ) 渲染一直是性能优化的“深水区”。

为了降低服务器成本和网络延迟,我做了一个“违背祖宗”的决定:完全依赖客户端算力。 所有的技术指标( MA, BOLL, MACD 等)计算,全部在移动端本地实时完成,不依赖后端返回计算结果。

这意味着,一台三星 A53 ( Exynos 1280 处理器,典型的千元机性能)不仅要负责 UI 绘制,还要在主线程实时遍历数组计算指标。

在这种“地狱模式”下,优化成果如何?

📉 性能实测:A53 跑分数据

测试设备:三星 Galaxy A53 (Exynos 1280)
测试场景

  • GOLD 平均每秒 2.5 次报价
  • 加载 500 根 K 线数据
  • 同时开启 MA (移动平均线) + BOLL (布林带) + MACD 三组指标 + 图表网格
  • 所有指标数据均为 本地实时计算
  • 进行高频拖拽、缩放操作

实测结果

1. 三星 A53 (低端机代表)

A53 帧率测试图

70 FPS !
在这种重负载下,UI 线程依然保持极高的流畅度,超过 60Hz 的及格线。对于一款千元机来说,这个渲染性能我已经非常满意了。

2. 三星 S25+ (旗舰机代表)

S25+ 帧率图

旗舰机毫无压力,贵的还是好哇。


🏛️ 技术挑战:为何 Dart 能抗住?

很多人对 Flutter 的印象还停留在“套壳性能差”。但实际上,通过合理的架构,Dart 的性能完全够用。我的优化核心思路是:UI 渲染与数据计算分离,用空间换时间。

1. 极致的分层渲染 (Layered Rendering)

我利用 Stack 将视图拆解为三个独立的渲染层级:

  • **Layer A (底层)**:静态 K 线与网格。这是最“重”的层(包含数千个顶点),只有在缩放或平移时才重绘。
  • **Layer B (中间层)**:技术指标 (MA, BOLL)。与 K 线同步,但逻辑分离。
  • Layer C (交互层)这是优化的关键。包含当前的 Bid/Ask 价格线、十字光标。这一层极其轻量,且更新频率最高(每秒数次)。

通过 Stack + RepaintBoundary,实现了:价格跳动时,底层的几百根 K 线完全不需要参与重绘,GPU 只需要绘制那几条横线。

2. 动态 LOD (Level of Detail) 策略

在手机屏幕上展示 500 根 K 线时,GPU 光栅化压力巨大。
我在代码中加入了 LOD 策略:

  • Zoom In:渲染完整的 Candlestick(蜡烛图)。
  • Zoom Out:当可视区域数据点过多时,自动切换为 LineChart(收盘价连线)。

这极大地降低了 GPU 的顶点绘制数量,解决了缩放时的“卡顿感”。


📱 软件界面预览

目前的 UI 风格偏向现代扁平,针对移动端操作做了很多适配。

软件界面截图


🔗 下载与体验

软件目前已上架 Google Play ,名为“交易学徒”。如果你对高性能 Flutter 开发或者交易感兴趣,欢迎下载体验。

🎁 V 友专属福利

感谢大家看完这么枯燥的技术分析。
人肉送 VIP:在评论区留下你的 用户 ID(在“我的”页面可以看到),我会手动为你开通 1 个月的 VIP 会员

欢迎大家对 UI 、交互或者技术实现提出建议,每一条我都会认真看!

起因:连续讲了 30 多分钟故事,她还是不睡

每天晚上 9 点半是我家的固定节目:女儿洗完澡,躺在床上,把她最爱的几本绘本摆成一排。

"爸爸,今天讲这本小兔子,还有恐龙的,还有..."

通常的流程是

  • 9:30 开始讲第一本绘本
  • 9:45 "爸爸再讲一个"
  • 10:00 "这个讲过了,编一个新的"
  • 10:15 我开始口干舌燥,她开始挑刺:"爸爸你昨天说小熊是红色的"
  • 10:30 她终于睡着,我瘫在床边刷手机缓一会儿

有天晚上特别崩溃:讲完三本绘本,她说"爸爸你编一个恐龙和兔子一起玩的故事"。

我临时编了个"霸王龙帮小兔子找萝卜",讲到一半自己都接不下去了,因为前面埋的坑忘了怎么圆。

她睁着大眼睛看着我:"然后呢?萝卜找到了吗?"

那一刻看着她期待的眼神,突然有点心酸。

不是不想讲,是真的每天都在掏空脑子,还得记住前面自己说过什么。

更难受的是,有时候加班晚了,或者状态不好,讲着讲着就敷衍了,她能听出来。会小声说:"爸爸今天讲得不好玩。"

我当时就想:能不能有个东西,让我即使累到说不出话,也能给她讲一个像样的故事?


程序员的痛点,可能也是你的痛点

说实话,在我做这个东西之前,试过市面上所有能找到的方案:

  • 故事 App: 凯叔、口袋故事都买了会员,但听多了不光无趣,也没有个性化
  • GPT 生成: 文本确实能定制,但 TTS 合成音就像客服机器人,毫无感情
  • 录音: 自己录了 20 多个故事,但每次要翻半天找文件,而且孩子总想听"新的"

这些方案单独看都没问题,但放到每天晚上十点半这个场景里,就全都不太行。

最崩溃的是某天晚上:

  • 22:30 讲了三只小猪
  • 23:00 她说"再讲一个有兔子的"
  • 23:20 编到词穷,开始重复情节
  • 23:45 她睁着大眼睛说"爸爸你刚才讲过了"

我坐在床边看着天花板,想着明天还有早会,突然冒出个念头:能不能让 AI 用我的声音讲?

顺便说下我是怎么折腾这个东西的(技术相关,可跳)

1. 故事生成不是调 API 那么简单

  • 一开始直接用 GPT 生成,结果经常前后打架,只好自己加了一层检查,避免讲着讲着把前面的设定忘了。(避免重复/逻辑 bug )
  • 分龄模板: 2-3 岁重复句式多,4-5 岁加入简单因果,6+开始有小反转
  • 安全过滤: 硬编码了很多禁用词库(包括"死亡""分离"等敏感词)

2. 音色克隆的坑

  • 最开始用开源 TTS ,效果像变声器
  • 后来接了某云的语音定制 API ,需要录多句话做训练
  • 真正的难点是韵律: 同样的文本,讲给 3 岁和 6 岁要用不同的停顿节奏

3. 成本控制

  • 大模型生成一个故事约 0.2 元(目前提示词就几千 token )
  • 音频克隆+合成约 0.4 元
  • 单张图片 0.2-0.4 元
  • 算上服务器和存储,也就是说,这玩意儿要是真被孩子天天听,其实还挺烧钱的。

对用户来说只要三步:

  1. 使用官方音色或者录一句话( 15 秒左右)
  2. 填孩子的基本信息(年龄、爱好、最近关注的事)
  3. 自己可以定制场景、故事
  4. 点生成,1-2 分钟后收到一个 5-8 分钟的音频故事


真实效果:一些意外的反馈

我家的变化

  • 女儿的入睡时间从原来的 40 分钟缩短到 20 分钟
  • 有天她指着我说: "爸爸你今天声音怎么跟手机里不一样?" (我感冒了)
  • 现在有时候出差也不焦虑了,每天睡前会提前生成好第二天的故事

朋友的案例(他们催我做出来的)

  • @老王: 双胞胎爸爸,每天要讲两遍不同的故事,现在各生成一个,省了一半时间
  • @小林: 孩子有语言发育迟缓,医生建议多输入,他用这个每天给孩子听 3 个故事

最触动我的是有一位朋友的反馈,她说:"技术能做的不只是效率,还有情感的延续。"


目前的纠结:三个灵魂拷问

1. 这需求到底有多普遍?

我的假设是:

  • ✅ 认同"父母声音对孩子重要"
  • ✅ 工作忙/经常出差/没空编故事
  • ❓ 愿意为此付费(而不是凑合用免费 App )

V2EX 的各位宝爸宝妈,你们会为这种服务付费吗?你们觉得合理价格是多少?

2. 音色克隆是噱头还是刚需?

有朋友直言:"孩子听谁讲不是一样?"

但我观察女儿的反应,她听到"爸爸的声音"时,真的会下意识抱紧小枕头,这和听凯叔讲故事的状态完全不同。

可能儿童心理学上有答案?有相关背景的朋友求指点。

3. 定位是"解放家长"还是"陪伴工具"?

  • 如果定位成"让家长省时间",很容易被批"用技术逃避责任"
  • 但如果定位成"让陪伴更高质量",又显得太虚

我现在的想法是: 这不是替代父母讲故事,而是在父母不在场/不方便时,提供一种接近真人的补充方案

就像视频通话不能替代见面,但总比完全失联好。


想听听大家的真实想法

如果你是家长:

  • 每天哄睡要花多长时间?
  • 试过哪些方案?痛点在哪?
  • 如果有这个工具,最看重什么(声音相似度/故事质量/价格)?

如果你做过类似产品:

  • 定价策略怎么定的?(订阅制 vs 按次付费)
  • 怎么平衡"商业化"和"不制造焦虑"?
  • 推广渠道主要靠什么?


最后

这个东西现在还很粗糙,甚至都不确定该不该做成产品。

但每次看到女儿听着"爸爸"讲的新故事安静入睡,会觉得这件事可能有点意义。

不是为了让父母逃避陪伴,而是让那些想陪但确实分身乏术的爸妈,多一种选择。

如果你有想法,无论是吐槽还是建议,都欢迎留言。

先谢过各位。


留言区如果超过 50 楼,随机抽取 5 位送年度会员


P.S. 如果有宝爸宝妈想试用,可以留言或私信。目前还在内测阶段,大家可以多提意见。

附上小程序码(微信搜:妈咪故事屋):
地址: https://imgur.com/hMjpDCr (图片无法显示,尴尬)

分享下 Gemini 搓的一个 Github 文件夹下载器,妈妈再也不用担心我为了一个文件夹下载整个仓库啦

精修样式,完美融入原生页面:

脚本源码:

// ==UserScript==
// @name                GitHub Folder Downloader
// @name:zh-CN          GitHub 文件夹下载器
// @version             0.7.0.33
// @author              叁月柒
// @match               *://github.com/*
// @grant               none
// @run-at              document-idle
// ==/UserScript==

(function () {
    'use strict';

    const isFolder = () => {
        const path = window.location.pathname.split('/').filter(Boolean);
        return path.length >= 2 && (path.length === 2 || path[2] === 'tree');
    };

    const injectToMenu = () => {
        const portalRoot = document.querySelector('#__primerPortalRoot__');
        if (!portalRoot) return;

        const menu = portalRoot.querySelector('ul[role="menu"]');
        if (!menu || menu.querySelector('.gh-download-integrated')) return;

        const menuText = menu.innerText;
        // 确保是操作菜单
        if (!menuText.includes('Copy path') && !menuText.includes('Delete directory')) return;

        // 1. 分割线
        const dividerHtml = `<li role="none" class="ActionList-sectionDivider gh-download-integrated"></li>`;

        // 2. 标题
        const headerHtml = `
            <li class="ActionList-sectionHeader gh-download-integrated" style="padding: 8px 16px 4px 16px;">
                <span class="ActionList-sectionHeader-label" style="color: #9198a1; font-size: 12px; font-weight: 500; display: block; line-height: 1.5;">
                    Download folder
                </span>
            </li>`;

        // 3. 子选项
        const createItem = (text, url) => `
            <li role="none" class="ActionList-item gh-download-integrated">
                <a role="menuitem" class="ActionList-content ActionList-content--visual16" target="_blank" rel="noopener noreferrer" href="${url}" style="text-decoration: none; padding-left: 16px;">
                    <span class="ActionList-item-label" style="padding-left: 24px; font-weight: 400; font-size: 14px; color: var(--fgColor-default, #adbac7);">
                        ${text}
                    </span>
                </a>
            </li>`;

        const downloadDirUrl = `https://download-directory.github.io?url=${window.location.href}`;
        const downGitUrl = `https://downgit.github.io/#/home?url=${window.location.href}`;

        const fragment = dividerHtml +
                         headerHtml +
                         createItem('by Download-Directory', downloadDirUrl) +
                         createItem('by DownGit', downGitUrl);

        menu.insertAdjacentHTML('beforeend', fragment);
    };

    const observer = new MutationObserver((mutations) => {
        if (!isFolder()) return;
        for (const mutation of mutations) {
            if (mutation.addedNodes.length > 0) {
                injectToMenu();
            }
        }
    });

    observer.observe(document.body, { childList: true, subtree: true });
})();

📌 转载信息
原作者:
MarSeventh
转载时间:
2026/1/24 16:04:58

起因

之前看到 @fatekey 佬 写的 雨云无限白嫖 FRP 服务器攻略(无 aff) - 福利羊毛 / 福利羊毛,Lv2 - LINUX DO ,照着搭了个 FRP。

原帖提到了自动签到的 Docker 版本,但续费还得手动调 API。想着既然每天签到攒积分,不如直接做成全自动:签到 + 到期检测 + 自动续费,一劳永逸。

于是在 fatekey 佬的 Docker 版基础上改了改,加上了自动续费功能。

本来想 fork 后提合并建议的,但想了想改的太多了,于是把仓库独立出来了

功能

  • 每日自动签到(验证码识别)

  • 游戏云服务器到期检测

  • 积分自动续费(到期前 7 天自动续)

  • Server 酱通知 (也有其他通知,都是原版自带的,我把
    server 酱优化了一下)

部署


git clone https://github.com/Jielumoon/Rainyun-Qiandao.git

cd Rainyun-Qiandao

# 编辑 .env 填入账号 cp .env.example .env # 运行

docker-compose up --build

环境变量

| 变量 | 说明 |

|------|------|

| RAINYUN_USER | 雨云用户名 |

| RAINYUN_PWD | 雨云密码 |

| RAINYUN_API_KEY | API 密钥(可选,用于自动续费) |

| PUSH_KEY | Server 酱推送密钥(可选) |

| RENEW_PRODUCT_IDS | 续费白名单:只续费指定的产品 ID(可选) |

API 密钥在雨云后台 → 用户中心 → API 密钥获取。

定时任务

 # 每天早上 8 点执行

0 8 * * * docker compose -f /path/to/docker-compose.yml run --rm rainyun-qiandao

致谢

| 作者 | 仓库 | 说明 |

|------|------|------|

| SerendipityR | 原版 | Python 版本 |

| fatekey | 二改 | Docker 化 |

仓库

项目地址GitHub - Jielumoon/Rainyun-Qiandao: 三改版雨云签到工具的 docker 版


有问题欢迎反馈~


📌 转载信息
原作者:
JasonZhang
转载时间:
2026/1/24 16:04:51

问题描述

不知从何时,+86 注册的 TG 账号登陆时,无法正常收到验证码。看到有人说多登陆几次会提示绑定邮箱,可用邮箱验证,但尝试未果。

适用情况

当前有一台移动设备正处于登录状态

解决方法

核心思路:通过passkey绕过接码难题,进行登录。

如果你是单一设备登录,可直接使用手机自带的passkey 管理器

打开 TG ,选择Settings -> Privacy and Security -> Passkeys -> Create Passkey

移动端截图

如果你有跨平台登录需求,也可按照如下步骤操作。

  1. 注册Bitwarden(也可以使用 Chrome 自带 passkey 管理器)
  2. 安装Bitwarden客户端和浏览器插件
  3. 打开https://web.telegram.org,扫码登录
  4. 选择Settings -> Privacy and Security -> Passkeys -> Create Passkey
  5. 创建一个 passkey ,并由Bitwarden进行保存和同步。

Web 端截图

实现效果

移动设备登陆时,系统会自动拉起Bitwarden,从而实现无密码、无接码的安全登录。


正巧看到有 v 友在讨论这个问题,决定发帖分享一下方法。

花 2 年时间自研的终端工具,产品对标 Termius ,目前除了多人协作没有,其他全部功能都有了
支持 Mac/iPhone/iPad
纯 swift 语言 + 手工打造,性能体验一流,吊打一众网页套壳 ssh

Claude CLI


分屏


智能提示



下载链接: https://apps.apple.com/app/id6479238971

10 个 1 年期兑换码送上,用过的说一声,方便后人,有任何使用建议,欢迎评论

J66736LXNLFP
LK3LTH6H39EP
P9RWW4KN9EKA
4XNHH7E4JX3A
AJ7YRLY33KXY
9FJPTAFTWYXT
W636KAE9JKA9
6L4H7YFEAHME
RJ63PLRTA4RM
6TN76Y7MYL47

问题描述

不知从何时,+86 注册的 TG 账号登陆时,无法正常收到验证码。看到有人说多登陆几次会提示绑定邮箱,可用邮箱验证,但尝试未果。

适用情况

当前有一台移动设备正处于登录状态

解决方法

核心思路:通过passkey绕过接码难题,进行登录。

如果你是单一设备登录,可直接使用手机自带的passkey 管理器

打开 TG ,选择Settings -> Privacy and Security -> Passkeys -> Create Passkey

移动端截图

如果你有跨平台登录需求,也可按照如下步骤操作。

  1. 注册Bitwarden(也可以使用 Chrome 自带 passkey 管理器)
  2. 安装Bitwarden客户端和浏览器插件
  3. 打开https://web.telegram.org,扫码登录
  4. 选择Settings -> Privacy and Security -> Passkeys -> Create Passkey
  5. 创建一个 passkey ,并由Bitwarden进行保存和同步。

Web 端截图

实现效果

移动设备登陆时,系统会自动拉起Bitwarden,从而实现无密码、无接码的安全登录。


正巧看到有 v 友在讨论这个问题,决定发帖分享一下方法。

花 2 年时间自研的终端工具,产品对标 Termius ,目前除了多人协作没有,其他全部功能都有了
支持 Mac/iPhone/iPad
纯 swift 语言 + 手工打造,性能体验一流,吊打一众网页套壳 ssh

Claude CLI


分屏


智能提示



下载链接: https://apps.apple.com/app/id6479238971

10 个 1 年期兑换码送上,用过的说一声,方便后人,有任何使用建议,欢迎评论

J66736LXNLFP
LK3LTH6H39EP
P9RWW4KN9EKA
4XNHH7E4JX3A
AJ7YRLY33KXY
9FJPTAFTWYXT
W636KAE9JKA9
6L4H7YFEAHME
RJ63PLRTA4RM
6TN76Y7MYL47

我实在是受不了了,每次锁屏在解锁,都会在右上角弹出来一次,设置关了,还是弹出来。

image

尝试过一下方法,只对了一半,本来 2 个弹窗,现在只弹一个了。

defaults write com.apple.SoftwareUpdate MajorOSUserNotificationDate -date "2031-01-22 23:22:47 +0000"
defaults write com.apple.SoftwareUpdate UserNotificationDate -date "2031-01-22 23:22:47 +0000"
defaults write com.apple.appstored LastUpdateNotification -date "2031-01-22 23:22:47 +0000"

问问大家有没有更好的解决办法。

2025 一人公司年度复盘:从 0.1 到 1 的创业路

这一年花了很多时间在 UChart 的开发上面,不断迭代产品,从年初到年末,功能从少到多,从多到精。慢慢理解了为啥公司中产品经理总是改来改去,因为我自己在做产品的时候也是变来变去,年初把一种,年初把一种功能调整为另外一种形式。嗯,到年末又会把它重新改回来,这可能是产品经理经理常态总在不停不停的变化。
产品形态完成度约 20%,但核心功能已经能跑通
付费模式从单一$9.9 终身,调整到$16 终身,再升级到$30 终身+月付/年付多种模式

产品成果
✅ 每天稳定新增用户 100 人左右
✅ 付费转化率达到 5‰,虽然不高但已验证产品可行性
✅ 产品在同类竞品中具备竞争力,只要能获得流量就能留住用户

收入成果
✅ 2025 年付费总收入达到 900 美元
✅ 付费模式逐步完善,从单一到多元,商业化路径清晰

社媒成果
✅ 小红书:200+粉丝(从个位数起步)
✅ 推特:60+粉丝
✅ 积累了多个平台的运营经验,为 2026 年爆发做准备

2026 年我要做什么

战略调整
核心优先级:市场营销 > SEO 优化 > 产品迭代
从"开发驱动"转向"增长驱动"
优先解决获客问题,其次才是继续打磨产品

市场营销
提升小红书运营质量,从 200 粉丝突破到 1000+
持续运营推特,扩大影响力
尝试更多获客渠道,如 Reddit ,Product hunt

SEO 优化
优化网站 SEO ,提升自然搜索流量
产出高质量内容,建立行业权威
深入研究关键词,抓住精准流量

产品迭代
继续优化产品,但控制在合理的迭代节奏
基于用户反馈打磨核心功能
在保持产品竞争力的前提下,逐步提升完成度

闲着无聊让 codex 糊了个小工具,顺便混点赞(小白开发,各位佬轻喷~)

主要作用:
1、自动批量获取 Gemini Business 账号相关信息
2、将获取的信息整理转换,同步给 Business Gemini Pool
3、当同步数量少于设定数量时,自动创建新的账户补齐

ps:由于 Business token 有效期只有 12 小时,系统会每 6 小时自动执行 token 刷新、同步等,达到 token 保活的目的

使用到的项目(感谢~!):
Gemini Business2api:

Gemini Business 账号管理系统(使用 cf 邮件系统自动创建)

邮件系统搭建参考教程:

最后是中间件同步工具:
sync.zip
启动方式:
填写好.env 后
pip install -r requirements.txt
python app.py


📌 转载信息
转载时间:
2026/1/24 10:34:57

项目地址:

背景

楼主是学生党,去年为了帮忙开发毕业设计代码,也搭上了谷歌大善人的便车,照着论坛里佬们的思路,搭建了 Claude Code + Claude Code Router + Gemini Api (主要是 GCP 赠金和 done-hub)的框架。但是,在使用的时候,经常发生一些始料未及的报错(毕竟不是 Claude 自家模型)和缺陷(尤其是提示词的遗忘问题),因此在写毕设代码的同时,我也一直在迭代提示词组件,在这里小小分享一下,希望各位佬友能多多提出意见,交流 Claude Code 的提示词构建技巧和使用方法~


具体而言,在 Claude Code 中使用 Gemini 的优点和缺点都很明显:

优点:

  1. 科研思维与创新性:模型具备较强的跨领域知识理解能力,能够提供具有启发性的架构思路与创新方案。
  2. 百万级上下文窗口:1M Token 的上下文容量允许模型全量阅读大型代码库。模型能够维护函数签名、变量定义在长调用链与数据流中的一致性。
  3. 成本效益:基于调用次数的计费模式降低了大规模上下文注入的成本,适合科研场景下的大量文献与代码阅读。最重要的是,注入大批量的提示词一点也不心疼

缺点:

  1. Agent 调度迟缓:模型在使用 Subagent 时(尤其是 Explore)存在延迟与卡死现象。
  2. 遗忘风险:受限于滑窗注意力机制,模型在长对话中容易遗忘初始指令,特别是特定的格式约束;这导致模型一段时间后就会回归其初始的状态。
  3. 回复风格偏差:原生模型倾向于使用夸张、绝对化的词汇,并表现出过度的自信与讨好,不符合科研严谨性要求。(Gemini:你发现了问题的核心!
  4. 非专用编程模型缺陷:作为通用模型,其在 Bash 环境操作与文件系统细节(如文件名字符混淆、编码处理)上存在不稳定性。

此外,在科研与架构验证场景中,我更希望代码生成工具具备 “白盒性” 与 “可控性”。但是 Claude Code 自带的提示词天然倾向于自动化流程,例如使用 SubAgent 等等,但这往往是我不太期望的 (因为我需要提出具体的要求,并与 AI 共同讨论完整的设计方案和风险)。

针对上述局限,我设计了一套基于分层提示词系统与运行时钩子的小组件,以强化模型的工程约束(不过提示词是按照我自己的开发偏好来的,可能因人而异)。这套组件有以下特性:

运行时钩子体系

系统利用 Claude Code 的 Hooks 机制,部署了三个核心钩子以实现全生命周期的工程管控:

  1. 协议执行器 (env_enforcer.py)

    • 触发时机UserPromptSubmit(用户提问提交时)。
    • 功能:在上下文末端强制注入简短的提示词摘要和易遗忘的约束。这有效对抗了 Gemini 模型的长窗口遗忘问题,确保每一轮对话都重置回受控状态。
  2. 上下文管理器 (context_manager.py)

    • 触发时机PreCompact(压缩前)与 SessionStart(会话开始)。
    • 功能:自动扫描 Git 状态、目录结构及 skills/ 下的可用工具,生成 .compact_args.md 快照。在新会话启动时注入该快照,使模型能迅速恢复项目全貌认知,并感知可用的高级能力(Skills)。
  3. 工具安全检查 (pre_tool_guard.py)

    • 触发时机PreToolUse(工具调用前)。
    • 功能:实施多维度的即时修正与拦截。
      • 路径安全:将绝对路径自动修正为相对路径,拦截项目外的非授权访问。
      • 环境修正:自动向 Bash 命令注入 PYTHONIOENCODING 及环境激活脚本,解决 Windows 平台下的编码与环境一致性问题。

行为与风格约束

通过 CLAUDE.mdstyle.md 定义静态规范,修正模型的回复风格。

  • 语言规范:强制全中文回复,禁用营销性术语(如 “赋能”、“痛点”)。为此提供了完整的禁止词列表和 few-shot 替换示例。
  • 句式约束:要求使用无修饰的一般陈述句,禁止使用夸张的形容词与副词。
  • 操作规范
    • 静默执行:减少不必要的口语化确认。
    • 验证后执行:针对 Bash 操作与文件系统,强制先验证后执行。
    • 相对路径优先:规范文件路径的引用方式。

除此之外,output-styles\python-architect.md 中还插入了一些著名开发者的工程哲学(大概算 “请神” 吧…不过不会继承某些人的坏脾气),例如:

  • Linus Torvalds:以数据为中心, 优先考虑内存布局、清晰的数据结构
  • Rich Hickey:简单 容易,拒绝为了贪图方便而引入耦合。
  • Kent Beck: 执行严格的测试驱动开发(TDD),以及尽早识别并处理 “代码异味”。
    . . .

递归上下文完整性

针对代码生成,引入 “递归上下文完整性” 协议。该协议作为核心防幻觉机制,要求模型在生成或修改代码前严格遵循以下步骤:

  • 源头溯源:必须溯源至任何引用变量或函数的原始定义处,禁止仅凭调用处的上下文推断接口签名。
  • 继承链验证:若涉及类继承或接口实现,必须检索父类定义以验证完整的类型契约。
  • 上下文饱和:在消除所有类型歧义前,不得进行代码生成。


希望各位如果用的满意的话可以随手点个 stars ,也欢迎各位提出修改意见~(我没有系统的学过提示词工程,所以某些设计可能比较拙劣)


📌 转载信息
原作者:
ModestMouse
转载时间:
2026/1/24 10:34:21

随着自建节点的流量增长,节点管理员们可能会遇到的需要处理的情况也会增多。

所以,除了主题删除之外,今天的功能部署为节点管理员们增加了又一个新的管理工具:

屏蔽列表

你可以在自己的每个节点里添加最多 100 个屏蔽用户名。被屏蔽的用户将无法在你的节点里创建新主题或者回复。

如果节点管理员遇到一些更极端的恶意破坏或者 spam 行为,节点管理员觉得有必要通过 V2EX 全站对指定用户名进行彻底 ban ,那么可以在 /go/chamber 节点告知。


自从 node/create 功能在 2026 年 1 月 10 日上线,我们希望的是这能够成为一个可以用来创建自己的独特社区的工具。所以大部分情况下,我们想做的事情是为节点创建者提供更多更好的工具,而不是去审核所有新内容。

每个节点里的内容,是节点创建者及节点参与者自己的。

接:雨云无限白嫖 FRP 服务器攻略(无 aff)

@fatekey 大佬的方案是单独开一个容器,我想着反正我有青龙面板在跑脚本,站在巨人的肩膀上顺手写了一个,把多账户也写进来了

一、运行效果

先看实际运行的效果吧
【前两个账号运行已签到,仅测试多账户切换功能,临时注册的第三个号用于测试签到功能】

## 开始执行... 2026-01-23 16:57:53

2026-01-23 16:57:54.116950139 [W:onnxruntime:Default, cpuid_info.cc:91 LogEarlyWarning] Unknown CPU vendor. cpuinfo_vendor value: 16
2026-01-23 16:57:54,191 - INFO - --------------------------------------------------------------------------------
2026-01-23 16:57:54,191 - INFO - 雨云签到工具 by SerendipityR ~
2026-01-23 16:57:54,191 - INFO - Github发布页: https://github.com/SerendipityR-2022/Rainyun-Qiandao
2026-01-23 16:57:54,192 - INFO - --------------------------------------------------------------------------------
2026-01-23 16:57:54,192 - INFO - 雨云签到工具容器版 by fatekey ~
2026-01-23 16:57:54,192 - INFO - Github发布页: https://github.com/fatekey/Rainyun-Qiandao
2026-01-23 16:57:54,192 - INFO - --------------------------------------------------------------------------------
2026-01-23 16:57:54,192 - INFO -                    项目为二次开发青龙脚本化运行
2026-01-23 16:57:54,192 - INFO -                      本项目基于上述项目开发
2026-01-23 16:57:54,192 - INFO -                 本项目仅作为学习参考,请勿用于其他用途
2026-01-23 16:57:54,192 - INFO - --------------------------------------------------------------------------------
2026-01-23 16:57:54,192 - INFO - ✅ 成功解析3个账号
2026-01-23 16:57:54,192 - INFO - 
================= 处理第1个账号 ==================
2026-01-23 16:57:54,192 - INFO - 
========== 开始处理账号:TACGN ==========
2026-01-23 16:57:54,192 - INFO - ⏳ 随机延时 0 分钟 35 秒
2026-01-23 16:58:29,794 - INFO - ✅ Selenium驱动初始化成功,路径:/usr/bin/chromedriver
2026-01-23 16:58:29,809 - INFO - ✅ 已注入stealth.min.js反检测脚本
2026-01-23 16:58:29,809 - INFO - ⏳ 发起登录请求
2026-01-23 16:58:29,810 - INFO - 🌐 访问雨云登录页
2026-01-23 16:58:31,258 - INFO - 页面标题:登录 | 雨云
2026-01-23 16:58:31,258 - INFO - ⏳ 等待登录表单元素加载...
2026-01-23 16:58:31,376 - INFO - 📝 输入账号密码
2026-01-23 16:58:31,775 - INFO - ⏳ 正在登录中,耗时较长请稍等……
2026-01-23 16:58:54,899 - INFO - ✅ 未触发登录验证码
2026-01-23 16:58:59,906 - INFO - 当前页面: https://app.rainyun.com/dashboard
2026-01-23 16:58:59,910 - INFO - 页面标题: 总览 | 雨云
2026-01-23 16:58:59,940 - INFO - ✅ 账号登录成功:TACGN
2026-01-23 16:58:59,940 - INFO - 🌐 访问赚取积分页
2026-01-23 16:59:00,958 - INFO - 当前页面: https://app.rainyun.com/account/reward/earn
2026-01-23 16:59:00,962 - INFO - 页面标题: 赚取积分 | 雨云
2026-01-23 16:59:00,962 - INFO - 🔍 查找每日签到按钮
2026-01-23 16:59:01,016 - INFO - 📌 签到状态:已完成,无需重复签到
2026-01-23 16:59:01,047 - INFO - 💰 当前积分:700(约0.35元)
2026-01-23 16:59:01,131 - INFO - ✅ 账号TACGN浏览器已关闭
2026-01-23 16:59:01,131 - INFO - ✅ 临时文件清理完成
2026-01-23 16:59:01,131 - INFO - 
========== 账号TACGN处理完成 ==========

2026-01-23 16:59:05,996 - INFO - 
================= 处理第2个账号 ==================
2026-01-23 16:59:05,996 - INFO - 
========== 开始处理账号:ACGN_T ==========
2026-01-23 16:59:05,996 - INFO - ⏳ 随机延时 4 分钟 3 秒
2026-01-23 17:03:09,549 - INFO - ✅ Selenium驱动初始化成功,路径:/usr/bin/chromedriver
2026-01-23 17:03:09,564 - INFO - ✅ 已注入stealth.min.js反检测脚本
2026-01-23 17:03:09,564 - INFO - ⏳ 发起登录请求
2026-01-23 17:03:09,564 - INFO - 🌐 访问雨云登录页
2026-01-23 17:03:11,015 - INFO - 页面标题:登录 | 雨云
2026-01-23 17:03:11,016 - INFO - ⏳ 等待登录表单元素加载...
2026-01-23 17:03:11,155 - INFO - 📝 输入账号密码
2026-01-23 17:03:11,584 - INFO - ⏳ 正在登录中,耗时较长请稍等……
2026-01-23 17:03:34,692 - INFO - ✅ 未触发登录验证码
2026-01-23 17:03:39,699 - INFO - 当前页面: https://app.rainyun.com/dashboard
2026-01-23 17:03:39,703 - INFO - 页面标题: 总览 | 雨云
2026-01-23 17:03:39,733 - INFO - ✅ 账号登录成功:ACGN_T
2026-01-23 17:03:39,733 - INFO - 🌐 访问赚取积分页
2026-01-23 17:03:40,777 - INFO - 当前页面: https://app.rainyun.com/account/reward/earn
2026-01-23 17:03:40,782 - INFO - 页面标题: 赚取积分 | 雨云
2026-01-23 17:03:40,783 - INFO - 🔍 查找每日签到按钮
2026-01-23 17:03:40,858 - INFO - 📌 签到状态:已完成,无需重复签到
2026-01-23 17:03:40,881 - INFO - 💰 当前积分:4684(约2.34元)
2026-01-23 17:03:40,966 - INFO - ✅ 账号ACGN_T浏览器已关闭
2026-01-23 17:03:40,966 - INFO - ✅ 临时文件清理完成
2026-01-23 17:03:40,966 - INFO - 
========== 账号ACGN_T处理完成 ==========

2026-01-23 17:03:43,883 - INFO - 
================= 处理第3个账号 ==================
2026-01-23 17:03:43,883 - INFO - 
========== 开始处理账号:ACGN ==========
2026-01-23 17:03:43,883 - INFO - ⏳ 随机延时 4 分钟 50 秒
2026-01-23 17:08:34,684 - INFO - ✅ Selenium驱动初始化成功,路径:/usr/bin/chromedriver
2026-01-23 17:08:34,698 - INFO - ✅ 已注入stealth.min.js反检测脚本
2026-01-23 17:08:34,699 - INFO - ⏳ 发起登录请求
2026-01-23 17:08:34,699 - INFO - 🌐 访问雨云登录页
2026-01-23 17:08:36,143 - INFO - 页面标题:登录 | 雨云
2026-01-23 17:08:36,143 - INFO - ⏳ 等待登录表单元素加载...
2026-01-23 17:08:36,285 - INFO - 📝 输入账号密码
2026-01-23 17:08:36,657 - INFO - ⏳ 正在登录中,耗时较长请稍等……
2026-01-23 17:08:59,802 - INFO - ✅ 未触发登录验证码
2026-01-23 17:09:04,809 - INFO - 当前页面: https://app.rainyun.com/dashboard
2026-01-23 17:09:04,813 - INFO - 页面标题: 总览 | 雨云
2026-01-23 17:09:04,842 - INFO - ✅ 账号登录成功:ACGN
2026-01-23 17:09:04,842 - INFO - 🌐 访问赚取积分页
2026-01-23 17:09:05,841 - INFO - 当前页面: https://app.rainyun.com/account/reward/earn
2026-01-23 17:09:05,871 - INFO - 页面标题: 赚取积分 | 雨云
2026-01-23 17:09:05,871 - INFO - 🔍 查找每日签到按钮
2026-01-23 17:09:05,940 - INFO - 📌 签到状态:领取奖励,开始领取
2026-01-23 17:09:06,072 - INFO - ⚠️ 触发签到验证码
2026-01-23 17:09:06,253 - INFO - 🔄 验证码处理第1次尝试(最大10次)
2026-01-23 17:09:06,810 - INFO - 开始下载验证码图片(1):https://turing.captcha.qcloud.com/cap_union_new_getcapbysig?img_index=1&image=02680900003d283800000015123b75d53fed&sess=s0HtD0kpY6pcWGI6FzFpt6ZiszTr2EhH-VfdHwPwxIdqv34Z-7I44K0-_RhKCQ_D1pczn56AhHTy7TzWXqVjayAnecALMlUWYf152tXUBM_URxYIPDxvoDD7jXbk7mwSIeJKDAUtmTTnuuaRcoqdw3DlBpEXv3Xc4RbCewuRGJZUAkZPrzzB8njktvXIOPrqAhs4UafKm96GgAUPJExW9_2PkkRGBKSTS43H1uLzB9el3g70xLMDYSd2TywoxM5Ps2idtfMPBn_aMw93gVXYLGwpX0Iztn4QG1vFv9VJj6NgCvOU2YSfCmTrGyEXxdzPnGglGJAKJFB0FfuxP4bM3-0O4DQt4l-5NsT52KR_8WcG7rvohxQXZy1sRw9MY84c31oFqKfUyPsa49v1VdtmranaOtiaDLX6SjgI6rJPvt2_kSelSHRNUWtA**
2026-01-23 17:09:07,077 - INFO - 开始下载验证码图片(2):https://turing.captcha.qcloud.com/cap_union_new_getcapbysig?img_index=0&image=02680900003d283800000015123b75d53fed&sess=s0HtD0kpY6pcWGI6FzFpt6ZiszTr2EhH-VfdHwPwxIdqv34Z-7I44K0-_RhKCQ_D1pczn56AhHTy7TzWXqVjayAnecALMlUWYf152tXUBM_URxYIPDxvoDD7jXbk7mwSIeJKDAUtmTTnuuaRcoqdw3DlBpEXv3Xc4RbCewuRGJZUAkZPrzzB8njktvXIOPrqAhs4UafKm96GgAUPJExW9_2PkkRGBKSTS43H1uLzB9el3g70xLMDYSd2TywoxM5Ps2idtfMPBn_aMw93gVXYLGwpX0Iztn4QG1vFv9VJj6NgCvOU2YSfCmTrGyEXxdzPnGglGJAKJFB0FfuxP4bM3-0O4DQt4l-5NsT52KR_8WcG7rvohxQXZy1sRw9MY84c31oFqKfUyPsa49v1VdtmranaOtiaDLX6SjgI6rJPvt2_kSelSHRNUWtA**
2026-01-23 17:09:07,375 - ERROR - ⚠️ 图案2识别率0.0000低于阈值0.4
2026-01-23 17:09:07,376 - ERROR - ❌ 验证码坐标重复,答案无效
2026-01-23 17:09:07,376 - ERROR - ❌ 验证码处理失败:验证码答案无效
2026-01-23 17:09:07,376 - ERROR - ⏳ 刷新验证码中,稍后重试……
2026-01-23 17:09:13,495 - INFO - 🔄 验证码处理第2次尝试(最大10次)
2026-01-23 17:09:13,518 - INFO - 开始下载验证码图片(1):https://turing.captcha.qcloud.com/cap_union_new_getcapbysig?img_index=1&image=0268090000946c2b0000000bb5e61fd63312&sess=s0_hrS7I5bVMRdivCWNVX_5xijZd5qBztok8b_H7bwMciiNFNIe3KMmj4IPktJO-cbs-8dl7upCI40ZosuxWWRjpXlIbF-P3ZWNoFjjg5G9dMFSybpTUgmgQO1lGEy1QSjGIghi44ITJTpCGcF4ym8wD4iU0xLCVakXfJvTvPiJbxl055LMVFM8W1FM1TtThPXpkg5h9JgYXRHols_wYhIgOI_dRxdgl3r_h-dSKI109RxypesTYee-w0m-Lw_41AM1etin4G_Iamp3lveRUaOtNV1JT4ssYxJ3DR1NZ8SEfN3yxvn9Z-_dxfifqGBxz8hkBmv4vsmx4M9imY60mxrr32HJt0K1ODVgIkzXKA0mgcq1DsSXM0AlcE765_pI_-NP9BgOPXEivjsEDpnxrS-nUFA1DJEz6urpWBwjgZN80OGgAAIs1XL1A**
2026-01-23 17:09:13,731 - INFO - 开始下载验证码图片(2):https://turing.captcha.qcloud.com/cap_union_new_getcapbysig?img_index=0&image=0268090000946c2b0000000bb5e61fd63312&sess=s0_hrS7I5bVMRdivCWNVX_5xijZd5qBztok8b_H7bwMciiNFNIe3KMmj4IPktJO-cbs-8dl7upCI40ZosuxWWRjpXlIbF-P3ZWNoFjjg5G9dMFSybpTUgmgQO1lGEy1QSjGIghi44ITJTpCGcF4ym8wD4iU0xLCVakXfJvTvPiJbxl055LMVFM8W1FM1TtThPXpkg5h9JgYXRHols_wYhIgOI_dRxdgl3r_h-dSKI109RxypesTYee-w0m-Lw_41AM1etin4G_Iamp3lveRUaOtNV1JT4ssYxJ3DR1NZ8SEfN3yxvn9Z-_dxfifqGBxz8hkBmv4vsmx4M9imY60mxrr32HJt0K1ODVgIkzXKA0mgcq1DsSXM0AlcE765_pI_-NP9BgOPXEivjsEDpnxrS-nUFA1DJEz6urpWBwjgZN80OGgAAIs1XL1A**
2026-01-23 17:09:14,002 - ERROR - ⚠️ 图案2识别率0.1515低于阈值0.4
2026-01-23 17:09:14,003 - ERROR - ❌ 验证码坐标重复,答案无效
2026-01-23 17:09:14,003 - ERROR - ❌ 验证码处理失败:验证码答案无效
2026-01-23 17:09:14,003 - ERROR - ⏳ 刷新验证码中,稍后重试……
2026-01-23 17:09:23,108 - INFO - 🔄 验证码处理第3次尝试(最大10次)
2026-01-23 17:09:23,131 - INFO - 开始下载验证码图片(1):https://turing.captcha.qcloud.com/cap_union_new_getcapbysig?img_index=1&image=0268090000f13d2300000015123b75d53f2f&sess=s02qPcN6ye2H2TPQfQ9ghy_0L3jB722YFRMCmx-rWnjm4UgxUo3F4WLoUzz5JczVgNJMtQwRWLFRo4OvXls1zjaajvPXch4RMoo6YZOavScFvdGaB-9B-ecxWvfcPx7ZTEb03-5MTmG-P2LipAwhLGAYKO0JOK6Rb6z3KYkAy9pxHIXYP9FaLlwdRvLsEDbqKWJZKCP4IHJ9mav4XH2EoTFfWGYMR-sA53gKcavXkSbzg2J_3ntSL6rszaLREZi9ZCSn1bPIDt16NYUXhHhlPFCJmBzIh41fG-nFTtpB-A8_i_vPaNo3mwlxJ9KojhSP37q7CfeASWq8-DTtI3OnT-mZbyVzoDHvBgQOiiQu5o0_VxQtxzWD9vNmVbErvVsP1VxQEVv0GCFywapI0H-R2DimaJI87vvVkVIzVce2MZQJ_lxWICubZ-RA**
2026-01-23 17:09:23,352 - INFO - 开始下载验证码图片(2):https://turing.captcha.qcloud.com/cap_union_new_getcapbysig?img_index=0&image=0268090000f13d2300000015123b75d53f2f&sess=s02qPcN6ye2H2TPQfQ9ghy_0L3jB722YFRMCmx-rWnjm4UgxUo3F4WLoUzz5JczVgNJMtQwRWLFRo4OvXls1zjaajvPXch4RMoo6YZOavScFvdGaB-9B-ecxWvfcPx7ZTEb03-5MTmG-P2LipAwhLGAYKO0JOK6Rb6z3KYkAy9pxHIXYP9FaLlwdRvLsEDbqKWJZKCP4IHJ9mav4XH2EoTFfWGYMR-sA53gKcavXkSbzg2J_3ntSL6rszaLREZi9ZCSn1bPIDt16NYUXhHhlPFCJmBzIh41fG-nFTtpB-A8_i_vPaNo3mwlxJ9KojhSP37q7CfeASWq8-DTtI3OnT-mZbyVzoDHvBgQOiiQu5o0_VxQtxzWD9vNmVbErvVsP1VxQEVv0GCFywapI0H-R2DimaJI87vvVkVIzVce2MZQJ_lxWICubZ-RA**
2026-01-23 17:09:23,677 - INFO - 🎯 图案 1 坐标(37,277),匹配率:0.6552
2026-01-23 17:09:23,677 - INFO - 🎯 图案 2 坐标(598,114),匹配率:0.5641
2026-01-23 17:09:23,677 - INFO - 🎯 图案 3 坐标(437,197),匹配率:0.6207
2026-01-23 17:09:26,517 - INFO - 📤 提交验证码
2026-01-23 17:09:31,670 - INFO - ✅ 验证码验证通过
2026-01-23 17:09:36,676 - INFO - ✅ 签到奖励领取成功
2026-01-23 17:09:36,699 - INFO - 💰 当前积分:700(约0.35元)
2026-01-23 17:09:36,788 - INFO - ✅ 账号ACGN浏览器已关闭
2026-01-23 17:09:36,788 - INFO - ✅ 临时文件清理完成
2026-01-23 17:09:36,788 - INFO - 
========== 账号ACGN处理完成 ==========

2026-01-23 17:09:40,305 - INFO - 
🎉 所有账号处理完成!

## 执行结束... 2026-01-23 17:09:40  耗时 707 秒   

二、前置条件

青龙面板:我是直接用的 1panel 应用商店里的青龙面板
雨云账号密码:自个注册去

三、准备工作

青龙面板安装依赖:安装不上的,不会的请自行搜索教程或者请教 AI 了哦
—— NodeJs:chromium
—— Python3:selenium
—— Linux:chromium-driver
青龙面板配置环境变量:想设置多少自己设置就好了
—— RAINYUN_ACCOUNT
—— [[“账号 1”,“账号 1 密码”],[“账号 2”,“账号 2 密码”]]

四、创建文件

同目录下创建以下两个文件

stealth.min.js
stealth.min.js.txt

rainyun.py
rainyun.py.txt

删掉 [.txt] 后缀上传就好了,顺便贴出 rainyun.py 的代码如下

import json
import logging
import os
import random
import re
import sys
import time
from typing import Tuple, Optional, List

import cv2
import ddddocr
import requests
from selenium import webdriver
from selenium.common import TimeoutException, WebDriverException, NoSuchElementException
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

# ===================== 青龙面板专属配置(常量不抽离) =====================
CONFIG = {
    "timeout": 20,  # 青龙面板网络可能不稳定,延长超时时间
    "max_delay": 5,  # 最大随机等待分钟数
    "max_captcha_retry": 10,  # 验证码最大重试次数(防止递归栈溢出)
    "similarity_threshold": 0.4,  # 降低阈值提升识别率
    "script_path": os.path.dirname(os.path.abspath(__file__)),  # 青龙脚本所在目录
    "temp_path": os.path.join(os.path.dirname(os.path.abspath(__file__)), "temp"),  # 临时文件路径
    "rainyun_login_url": "https://app.rainyun.com/auth/login",
    "rainyun_earn_url": "https://app.rainyun.com/account/reward/earn"
}

# 全局日志对象(仅日志全局化,核心变量均函数内初始化)
logger = logging.getLogger(__name__)

def init_logger():
    """初始化青龙面板日志格式(增强版)"""
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(levelname)s - %(message)s',
        handlers=[logging.StreamHandler(sys.stdout)]
    )
    # 打印项目信息
    logger.info("-"*80)
    logger.info("雨云签到工具 by SerendipityR ~")
    logger.info("Github发布页: https://github.com/SerendipityR-2022/Rainyun-Qiandao")
    logger.info("-"*80)
    logger.info("雨云签到工具容器版 by fatekey ~")
    logger.info("Github发布页: https://github.com/fatekey/Rainyun-Qiandao")
    logger.info("-"*80)
    logger.info("                   项目为二次开发青龙脚本化运行")
    logger.info("                     本项目基于上述项目开发")
    logger.info("                本项目仅作为学习参考,请勿用于其他用途")
    logger.info("-"*80)

def init_selenium() -> WebDriver:
    """初始化青龙面板专用Selenium驱动(每次调用新建实例,避免缓存污染)"""
    ops = Options()
    # 容器环境必需配置
    ops.add_argument("--no-sandbox")
    ops.add_argument("--disable-dev-shm-usage")
    ops.add_argument("--headless=new")
    ops.add_argument("--disable-gpu")
    ops.add_argument("--window-size=1920,1080")
    ops.add_argument("--user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
    # 反爬配置
    ops.add_experimental_option("excludeSwitches", ["enable-automation"])
    ops.add_experimental_option('useAutomationExtension', False)
    ops.add_argument("--disable-blink-features=AutomationControlled")
    
    # 青龙面板固定驱动路径校验
    driver_path = "/usr/bin/chromedriver"
    if not os.path.exists(driver_path) or not os.access(driver_path, os.X_OK):
        raise FileNotFoundError(
            f"青龙面板未安装chromium-driver!\n"
            f"请在青龙终端执行:apt update && apt install -y chromium-driver"
        )

    try:
        service = Service(executable_path=driver_path)
        driver = webdriver.Chrome(service=service, options=ops)
        # 清空缓存(双重保障)
        driver.delete_all_cookies()
        logger.info(f"✅ Selenium驱动初始化成功,路径:{driver_path}")
        return driver
    except WebDriverException as e:
        logger.error(f"❌ 驱动启动失败:{str(e)}")
        raise

def check_stealth_js() -> str:
    """检查青龙脚本目录下的stealth.min.js"""
    js_path = os.path.join(CONFIG["script_path"], "stealth.min.js")
    if not os.path.exists(js_path):
        logger.error(f"❌ 未找到stealth.min.js!请将文件上传到青龙脚本目录:{CONFIG['script_path']}")
        logger.info("📥 下载地址:https://raw.githubusercontent.com/berstend/puppeteer-extra/master/packages/puppeteer-extra-plugin-stealth/evasions/stealth.min.js")
        sys.exit(1)
    return js_path

def inject_stealth_js(driver: WebDriver):
    """注入反检测脚本(传入driver实例,解耦全局变量)"""
    js_path = check_stealth_js()
    with open(js_path, "r", encoding="utf-8") as f:
        js = f.read()
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": js})
    logger.info("✅ 已注入stealth.min.js反检测脚本")

def download_image(url: str, filename: str, img_index: int) -> bool:
    """下载图片(带URL日志+青龙面板加请求头防拦截)"""
    os.makedirs(CONFIG["temp_path"], exist_ok=True)
    try:
        logger.info(f"开始下载验证码图片({img_index}):{url}")
        headers = {
            "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
            "Referer": "https://app.rainyun.com/"
        }
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status()
        path = os.path.join(CONFIG["temp_path"], filename)
        with open(path, "wb") as f:
            f.write(response.content)
        return True
    except Exception as e:
        logger.error(f"❌ 下载图片失败 {url}:{str(e)}")
        return False

# ========== 工具函数(精简+健壮性优化) ==========
def get_url_from_style(style: str) -> Optional[str]:
    """从style属性提取URL"""
    try:
        match = re.search(r'url\(["\']?(.*?)["\']?\)', style)
        return match.group(1) if match else None
    except Exception:
        return None

def get_width_from_style(style: str) -> str:
    """从style属性提取宽度"""
    match = re.search(r'width:\s*([\d.]+)px', style)
    return match.group(1) if match else "300"

def get_height_from_style(style: str) -> str:
    """从style属性提取高度"""
    match = re.search(r'height:\s*([\d.]+)px', style)
    return match.group(1) if match else "150"

def compute_similarity(img1_path: str, img2_path: str) -> Tuple[float, int]:
    """青龙面板适配:SIFT不可用时用ORB(增加异常兜底)"""
    try:
        img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)
        img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)
        if img1 is None or img2 is None:
            logger.warning(f"❌ 图片读取失败:{img1_path} 或 {img2_path}")
            return 0.0, 0

        # 优先SIFT,降级ORB
        try:
            sift = cv2.SIFT_create()
            norm = cv2.NORM_L2
        except AttributeError:
            sift = cv2.ORB_create()
            norm = cv2.NORM_HAMMING
            logger.warning("⚠️ SIFT不可用,使用ORB匹配")

        kp1, des1 = sift.detectAndCompute(img1, None)
        kp2, des2 = sift.detectAndCompute(img2, None)
        if des1 is None or des2 is None:
            return 0.0, 0

        bf = cv2.BFMatcher(norm, crossCheck=False)
        matches = bf.knnMatch(des1, des2, k=2)
        good = [m for m, n in matches if m.distance < 0.8 * n.distance]
        similarity = len(good) / len(matches) if matches else 0.0
        return similarity, len(good)
    except Exception as e:
        logger.error(f"❌ 相似度计算失败:{str(e)}")
        return 0.0, 0

def download_captcha_img(driver: WebDriver, wait: WebDriverWait) -> bool:
    """下载并分割验证码图片(解耦全局变量)"""
    try:
        # 清空旧临时文件
        if os.path.exists(CONFIG["temp_path"]):
            for f in os.listdir(CONFIG["temp_path"]):
                os.remove(os.path.join(CONFIG["temp_path"], f))

        # 定位验证码背景图
        slideBg = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="slideBg"]')))
        img1_url = get_url_from_style(slideBg.get_attribute("style"))
        if not img1_url or not download_image(img1_url, "captcha.jpg", 1):
            return False

        # 定位验证码碎片图
        sprite = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="instruction"]/div/img')))
        if not download_image(sprite.get_attribute("src"), "sprite.jpg", 2):
            return False

        # 分割碎片图
        raw = cv2.imread(os.path.join(CONFIG["temp_path"], "sprite.jpg"))
        if raw is None:
            logger.error("❌ 验证码碎片图读取失败")
            return False
        w = raw.shape[1]
        for i in range(3):
            cv2.imwrite(
                os.path.join(CONFIG["temp_path"], f"sprite_{i+1}.jpg"),
                raw[:, w//3*i : w//3*(i+1)]
            )
        return True
    except TimeoutException:
        logger.error("❌ 验证码图片加载超时")
        return False
    except Exception as e:
        logger.error(f"❌ 验证码图片处理失败:{str(e)}")
        return False

def check_answer(result: dict) -> bool:
    """检查验证码答案有效性(带识别率日志)"""
    valid = True
    for i in range(3):
        sim = float(result.get(f"sprite_{i+1}.similarity", 0))
        if sim < CONFIG["similarity_threshold"]:
            logger.error(f"⚠️ 图案{i+1}识别率{sim:.4f}低于阈值{CONFIG['similarity_threshold']}")
            valid = False
            break
    # 检查坐标唯一性
    positions = [result.get(f"sprite_{i+1}.position") for i in range(3)]
    if len(set(positions)) != 3:
        logger.error("❌ 验证码坐标重复,答案无效")
        valid = False
    return valid

def process_captcha(driver: WebDriver, wait: WebDriverWait) -> bool:
    """处理验证码(改递归为循环,提升健壮性,解耦全局变量)"""
    captcha_retry_count = 0
    ocr = ddddocr.DdddOcr(ocr=True, show_ad=False)
    det = ddddocr.DdddOcr(det=True, show_ad=False)

    while captcha_retry_count < CONFIG["max_captcha_retry"]:
        captcha_retry_count += 1
        logger.info(f"🔄 验证码处理第{captcha_retry_count}次尝试(最大{CONFIG['max_captcha_retry']}次)")
        try:
            # 下载验证码图片
            if not download_captcha_img(driver, wait):
                raise Exception("验证码图片下载失败")

            # 校验验证码有效性
            valid = True
            for i in range(3):
                sprite_path = os.path.join(CONFIG["temp_path"], f"sprite_{i+1}.jpg")
                with open(sprite_path, "rb") as f:
                    if ocr.classification(f.read()) in ["0", "1"]:
                        valid = False
                        break
            if not valid:
                raise Exception("验证码碎片无效")

            # 识别验证码
            captcha = cv2.imread(os.path.join(CONFIG["temp_path"], "captcha.jpg"))
            if captcha is None:
                raise Exception("验证码背景图读取失败")
            with open(os.path.join(CONFIG["temp_path"], "captcha.jpg"), "rb") as f:
                bboxes = det.detection(f.read())
            if not bboxes:
                raise Exception("未检测到验证码图案")

            # 匹配碎片与背景图
            result = {}
            for i, (x1, y1, x2, y2) in enumerate(bboxes):
                # 裁剪背景图中的图案
                cv2.imwrite(os.path.join(CONFIG["temp_path"], f"spec_{i+1}.jpg"), captcha[y1:y2, x1:x2])
                # 计算与每个碎片的相似度
                for j in range(3):
                    sim, _ = compute_similarity(
                        os.path.join(CONFIG["temp_path"], f"sprite_{j+1}.jpg"),
                        os.path.join(CONFIG["temp_path"], f"spec_{i+1}.jpg")
                    )
                    key_sim = f"sprite_{j+1}.similarity"
                    key_pos = f"sprite_{j+1}.position"
                    if sim > float(result.get(key_sim, 0)):
                        result[key_sim] = sim
                        result[key_pos] = f"{int((x1+x2)/2)},{int((y1+y2)/2)}"

            # 校验答案
            if not check_answer(result):
                raise Exception("验证码答案无效")

            # 打印匹配结果
            for i in range(3):
                pos = result[f"sprite_{i+1}.position"]
                sim = result[f"sprite_{i+1}.similarity"]
                x, y = pos.split(",")
                logger.info(f"🎯 图案 {i+1} 坐标({x},{y}),匹配率:{sim:.4f}")

            # 点击验证码图案
            slideBg = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="slideBg"]')))
            style = slideBg.get_attribute("style")
            width, height = float(get_width_from_style(style)), float(get_height_from_style(style))
            width_raw, height_raw = captcha.shape[1], captcha.shape[0]

            for i in range(3):
                pos = result[f"sprite_{i+1}.position"]
                x, y = map(int, pos.split(","))
                # 计算实际点击坐标(适配页面缩放)
                final_x = int(-width/2 + x/width_raw * width) + random.randint(-1, 1)
                final_y = int(-height/2 + y/height_raw * height) + random.randint(-1, 1)
                ActionChains(driver).move_to_element_with_offset(slideBg, final_x, final_y).click().perform()
                time.sleep(random.uniform(0.5, 1))

            # 提交验证码
            logger.info("📤 提交验证码")
            confirm = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="tcStatus"]/div[2]/div[2]/div/div')))
            confirm.click()
            time.sleep(5)

            # 校验验证码结果
            tc_operation = wait.until(EC.visibility_of_element_located((By.XPATH, '//*[@id="tcOperation"]')))
            if tc_operation.get_attribute("class") == "tc-opera pointer show-success":
                logger.info("✅ 验证码验证通过")
                return True
            else:
                raise Exception("验证码验证失败")

        except Exception as e:
            logger.error(f"❌ 验证码处理失败:{str(e)}")
            # 刷新验证码重试
            try:
                logger.error("⏳ 刷新验证码中,稍后重试……")
                reload = driver.find_element(By.XPATH, '//*[@id="reload"]')
                time.sleep(3)
                reload.click()
                time.sleep(min(3 * (2 ** (captcha_retry_count - 1)), 30))  # 指数退避重试间隔,上限30秒
            except NoSuchElementException:
                logger.error("❌ 验证码刷新按钮未找到,重试失败")
                return False

    logger.error(f"❌ 验证码重试{CONFIG['max_captcha_retry']}次仍失败,放弃")
    return False

def clean_temp():
    """清理青龙面板临时文件(增加容错)"""
    try:
        if os.path.exists(CONFIG["temp_path"]):
            for f in os.listdir(CONFIG["temp_path"]):
                file_path = os.path.join(CONFIG["temp_path"], f)
                try:
                    os.remove(file_path)
                except Exception as e:
                    logger.warning(f"⚠️ 删除临时文件{file_path}失败:{str(e)}")
            os.rmdir(CONFIG["temp_path"])
        logger.info("✅ 临时文件清理完成")
    except Exception as e:
        logger.warning(f"⚠️ 清理临时文件失败:{str(e)}")

def parse_accounts() -> List[List[str]]:
    """解析青龙面板RAINYUN_ACCOUNT环境变量"""
    account_str = os.getenv("RAINYUN_ACCOUNT")
    if not account_str:
        logger.error("❌ 未配置RAINYUN_ACCOUNT环境变量!格式应为[[账号1,密码1],[账号2,密码2]]")
        sys.exit(1)
    
    try:
        # 解析JSON格式的账号列表(兼容单引号/双引号)
        account_str = account_str.replace("'", "\"")  # 统一为双引号
        accounts = json.loads(account_str)
        # 校验格式
        if not isinstance(accounts, list):
            raise ValueError("环境变量值不是列表类型")
        for idx, account in enumerate(accounts):
            if not isinstance(account, list) or len(account) != 2:
                raise ValueError(f"第{idx+1}个账号格式错误,应为[账号,密码]")
            if not account[0] or not account[1]:
                raise ValueError(f"第{idx+1}个账号/密码为空")
        logger.info(f"✅ 成功解析{len(accounts)}个账号")
        return accounts
    except json.JSONDecodeError as e:
        logger.error(f"❌ RAINYUN_ACCOUNT格式解析失败:{str(e)},请检查格式是否为合法JSON")
        sys.exit(1)
    except ValueError as e:
        logger.error(f"❌ RAINYUN_ACCOUNT格式错误:{str(e)}")
        sys.exit(1)

def sign_in_rainyun(username: str, password: str):
    """单账号签到核心逻辑(独立封装,支持多账号循环调用)"""
    driver = None
    try:
        logger.info(f"\n========== 开始处理账号:{username} ==========")
        # 随机延时(可选)
        delay = random.randint(0, CONFIG["max_delay"])
        delay_sec = random.randint(0, 60)
        logger.info(f"⏳ 随机延时 {delay} 分钟 {delay_sec} 秒")
        time.sleep(delay * 60 + delay_sec)

        # 初始化Selenium(每次新建实例,清空缓存)
        driver = init_selenium()
        inject_stealth_js(driver)
        wait = WebDriverWait(driver, CONFIG["timeout"])

        # 访问登录页
        logger.info("⏳ 发起登录请求")
        logger.info("🌐 访问雨云登录页")
        driver.get(CONFIG["rainyun_login_url"])
        logger.info(f"页面标题:{driver.title}")

        # 输入账号密码
        logger.info("⏳ 等待登录表单元素加载...")
        username_elem = wait.until(EC.visibility_of_element_located((By.NAME, "login-field")))
        password_elem = wait.until(EC.visibility_of_element_located((By.NAME, "login-password")))
        login_btn = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="app"]/div[1]/div[1]/div/div[2]/fade/div/div/span/form/button')))
        logger.info("📝 输入账号密码")
        username_elem.send_keys(username)
        password_elem.send_keys(password)
        login_btn.click()
        logger.info("⏳ 正在登录中,耗时较长请稍等……")
        time.sleep(3)

        # 处理登录验证码
        try:
            wait.until(EC.visibility_of_element_located((By.ID, "tcaptcha_iframe_dy")))
            logger.warning("⚠️ 触发登录验证码")
            driver.switch_to.frame("tcaptcha_iframe_dy")
            if not process_captcha(driver, wait):
                raise Exception("登录验证码验证失败")
        except TimeoutException:
            logger.info("✅ 未触发登录验证码")

        # 校验登录状态
        time.sleep(5)
        driver.switch_to.default_content()
        logger.info(f"当前页面: {driver.current_url}")
        logger.info(f"页面标题: {driver.title}")
        if driver.current_url != "https://app.rainyun.com/dashboard":
            raise Exception("登录失败!请检查账号密码或网络")
        user_name = driver.find_element(By.XPATH, '//*[@id="app"]/div[1]/nav/div[1]/ul/div[6]/li/a/div/div/p').text.strip()
        logger.info(f"✅ 账号登录成功:{user_name}")
        
        # 访问签到页
        logger.info("🌐 访问赚取积分页")
        driver.get(CONFIG["rainyun_earn_url"])
        driver.implicitly_wait(5)
        logger.info(f"当前页面: {driver.current_url}")
        logger.info(f"页面标题: {driver.title}")

        # 查找并点击签到按钮
        logger.info("🔍 查找每日签到按钮")
        earn_btn_qddiv = driver.find_element(By.XPATH, '//*[@id="app"]/div[1]/div[3]/div[2]/div/div/div[2]/div[2]/div/div/div/div[1]/div')
        earn_btn_qd = earn_btn_qddiv.find_element(By.XPATH, './/span[contains(text(),"每日签到")]')
        status_elem = earn_btn_qd.find_element(By.XPATH, './following-sibling::span[1]')
        status_text = status_elem.text.strip()

        if status_text == "领取奖励":
            earn_btn = status_elem.find_element(By.XPATH, './a')
            logger.info(f"📌 签到状态:{status_text},开始领取")
            earn_btn.click()

            # 处理签到验证码
            logger.info("⚠️ 触发签到验证码")
            driver.switch_to.frame("tcaptcha_iframe_dy")
            if not process_captcha(driver, wait):
                raise Exception("签到验证码验证失败")
            driver.switch_to.default_content()

            # 校验签到结果
            time.sleep(5)
            logger.info("✅ 签到奖励领取成功")
        else:
            logger.info(f"📌 签到状态:{status_text},无需重复签到")

        # 获取当前积分
        try:
            points_elem = driver.find_element(By.XPATH, '//*[@id="app"]/div[1]/div[3]/div[2]/div/div/div[2]/div[1]/div[1]/div/p/div/h3')
            current_points = int(''.join(re.findall(r'\d+', points_elem.text)))
            logger.info(f"💰 当前积分:{current_points}(约{current_points/2000:.2f}元)")
        except Exception as e:
            logger.warning(f"⚠️ 积分获取失败:{str(e)}")

        

    except Exception as e:
        logger.error(f"❌ 账号{username}处理失败:{str(e)}", exc_info=True)
    finally:
        # 关闭浏览器,彻底清空缓存
        if driver:
            try:
                driver.quit()
                logger.info(f"✅ 账号{username}浏览器已关闭")
            except Exception as e:
                logger.warning(f"⚠️ 关闭浏览器失败:{str(e)}")
        # 清理临时文件
        clean_temp()
    logger.info(f"\n========== 账号{username}处理完成 ==========\n")

def main():
    """主函数:解析多账号,依次执行签到"""
    init_logger()
    # 解析账号列表
    accounts = parse_accounts()
    # 依次处理每个账号
    for idx, (username, password) in enumerate(accounts, 1):
        logger.info(f"\n================= 处理第{idx}个账号 ==================")
        sign_in_rainyun(username, password)
        # 账号间间隔(可选)
        time.sleep(random.uniform(2, 5))
    
    logger.info("\n🎉 所有账号处理完成!")

if __name__ == "__main__":
    main()

五、最后

后面的设置定时任务之类的就懒得写啦,顺便我也懒得写通知之类的了,感谢前人的开发让我站于巨人肩膀上,要是有后来者优化了就更好了

哦,对了,懒得上传 github 了,就丢 linux.do 里好了


📌 转载信息
原作者:
T_ACGN
转载时间:
2026/1/24 07:01:47

之前一直当作一个把网页保存到本地的剪辑工具
今天配置了一下里面的 AI 感觉用起来还不错推荐给大家

1 chrome 插件下载地址

2. 使用 AI 功能 对网页内容进行总结或者打标签

  1. 配置模型供应商 这里使用了薄荷佬的公益站

配置模型

  1. 新建一个模版

  2. 配置属性

tags 这里配置的是 可以自己写自己需要的提示词

{{"Analyze the article and create up to 5 tags in comma-separated format. Tags should be in Chinese unless necessary for company names, person names or abbreviations. One tag must be selected from: "资源, AI编程, AI画图 , 工具, 产品". Other tags should be based on the article's topic, mentioned people, companies or products."}}

描述

{{"One-sentence summary of the article content,translated to Chinese"}}
  1. 然后可以把模版进行导入导出

刚刚的模版复制出的 json 直接导入 就可以快速编辑了

{
  "schemaVersion": "0.1.0",
  "name": "剪藏模板",
  "behavior": "create",
  "noteContentFormat": "{{content}}",
  "properties": [
    {
      "name": "标题",
      "value": "{{title}}",
      "type": "text"
    },
    {
      "name": "来源",
      "value": "{{url}} ",
      "type": "text"
    },
    {
      "name": "创建时间",
      "value": "{{date}}",
      "type": "text"
    },
    {
      "name": "tags",
      "value": "{{\\\"Analyze the article and create up to 5 tags in comma-separated format. Tags should be in Chinese unless necessary for company names, person names or abbreviations. One tag must be selected from: \\\"UI设计, AI, 编程, 经济, 效率, 产品\\\". Other tags should be based on the article's topic, mentioned people, companies or products.\\\"}}",
      "type": "multitext"
    },
    {
      "name": "简单描述",
      "value": "{{\\\"One-sentence summary of the article content,translated to Chinese\\\"}}",
      "type": "text"
    }
  ],
  "triggers": [],
  "noteNameFormat": "{{title}}",
  "path": "para/Clippings"
}

  1. 其余属性自行探索,有小伙伴做出好用的模版 可以导出来进行交流

📌 转载信息
原作者:
mocheng
转载时间:
2026/1/24 06:57:22

由于我有读 PDF 的需求,所以做了一个 AI 定位器,可以聊天和定位 PDF 内容

配置自己的 api key 到这个网站

免费使用打开这个网站

GitHub (求个 Star):


📌 转载信息
原作者:
yeahhe
转载时间:
2026/1/24 06:55:23

之前一直当作一个把网页保存到本地的剪辑工具
今天配置了一下里面的 AI 感觉用起来还不错推荐给大家

1 chrome 插件下载地址

2. 使用 AI 功能 对网页内容进行总结或者打标签

  1. 配置模型供应商 这里使用了薄荷佬的公益站

配置模型

  1. 新建一个模版

  2. 配置属性

tags 这里配置的是 可以自己写自己需要的提示词

{{"Analyze the article and create up to 5 tags in comma-separated format. Tags should be in Chinese unless necessary for company names, person names or abbreviations. One tag must be selected from: "资源, AI编程, AI画图 , 工具, 产品". Other tags should be based on the article's topic, mentioned people, companies or products."}}

描述

{{"One-sentence summary of the article content,translated to Chinese"}}
  1. 然后可以把模版进行导入导出

刚刚的模版复制出的 json 直接导入 就可以快速编辑了

{
  "schemaVersion": "0.1.0",
  "name": "剪藏模板",
  "behavior": "create",
  "noteContentFormat": "{{content}}",
  "properties": [
    {
      "name": "标题",
      "value": "{{title}}",
      "type": "text"
    },
    {
      "name": "来源",
      "value": "{{url}} ",
      "type": "text"
    },
    {
      "name": "创建时间",
      "value": "{{date}}",
      "type": "text"
    },
    {
      "name": "tags",
      "value": "{{\\\"Analyze the article and create up to 5 tags in comma-separated format. Tags should be in Chinese unless necessary for company names, person names or abbreviations. One tag must be selected from: \\\"UI设计, AI, 编程, 经济, 效率, 产品\\\". Other tags should be based on the article's topic, mentioned people, companies or products.\\\"}}",
      "type": "multitext"
    },
    {
      "name": "简单描述",
      "value": "{{\\\"One-sentence summary of the article content,translated to Chinese\\\"}}",
      "type": "text"
    }
  ],
  "triggers": [],
  "noteNameFormat": "{{title}}",
  "path": "para/Clippings"
}

  1. 其余属性自行探索,有小伙伴做出好用的模版 可以导出来进行交流

📌 转载信息
原作者:
mocheng
转载时间:
2026/1/24 06:54:31

头回自己碰见,哥们你知道吗。
用着用着 gemini 抽风了,这你受得了吗。
抽风了大概 10 分钟,消息被吞了。
抽风的原因疑是是聊天记录太多了。
抽风前聊天记录全给我加载了然后每次切换窗口都给我跳到第一个对话,不过没想到最后这么癫。

为了不漏信息,所以只放抽风的截图。
image