# [Obcsapi v2] 微信到 Obsidian 2.0 微信到 Obsidian 2.0,以前出过一个1.0版本。最近发现了一个 Obsidian 的 Memos 插件,跟 flomo 界面非常像,或者说一样。不过数据来源用的是 Obsidian 。我使用了多端同步插件 remotely save插件,选择腾讯云COS同步。我想,如果能够在微信测试号中,信息发送过去,然后存储到COS中。在 Obsidian 中一刷新就能看到了。 1.0 版本 [微信使用 Remotely Save S3 兼容 发送到 Obsidian 1.0版本](/posts/wechat2obsidian/)。不太好用 !!! 注意 新项目已发布 [Obsidian 从本地到云端 obcsapi v3.0](https://www.ftls.xyz/posts/obcsapi-fc-simple/) 下面文章属于 2.0 版本,新项目是 3.0 版本。请读者根据自身实际情况酌情选择!!! ## 2.0 说明 因此我写下了2.0版本。实现了以下功能: - 支持图片和文字 - 图片下载到存储本地,而非链接(微信发送的图片,会给咱们的服务器返回图片URL) - 对用户的判断,仅限特定用户存储笔记。(根据 OpenID 判断) - 检索文字中含有 "todo" ,则生成勾选框。如 `- [ ] 13:11 somethingtodo` - 正常生成 `- 13:11 something` - 内容能在 Memos 中正常显示 - 支持收藏链接(部分支持),位置,**语音(转文字存储)**。(2.1 新增) - 返回可点击的链接,可以在微信内置浏览器中使用 Memos (2.1 新增,需要[kkbt/obweb](https://gitee.com/kkbt/obweb)支持,[参考页面](https://kkbt.gitee.io/obweb/#/Memos),支持查看三天,修改一天) BUG: - 不推荐批量传图片,推荐显示已保存后依次上传。 - 不推荐一秒内上传多个文件,图片命名精确到1S。1S内多图片会覆盖。 - 不要使用微信自带的表情符号,请使用输入法表情。 - 如果微信输入框换行或分段,只会在这一条消息最开始有 `- 13:11 `。也就是说,第二行、第二段不会在 Memos 中显示。 说明: 不推荐批量传图片,程序对图片处理非常粗糙。。例如1M带宽服务器,连续传五个图片时。造成费时间会超过五秒,触发微信重传机制。这个机制带来的问题有很多。比如会多上传几份重复的文件,并且在微信测试号显示服务故障。(其实解决方案有很多,如使用任务队列或者是异步的方式。先返回success,另外开线程上传文件。留着以后有机会解决吧)。 ## 程序 开源地址: https://gitee.com/kkbt/obsidian-csapi 微信发送到 Obsidian 是该项目的最初的功能,后进一步拓展出更多功能。 依赖 - werobot - cos-python-sdk-v5 程序思路 >程序思路运行一个测试号服务器,使用werobot。根据message的公共属性source,即微信用户的唯一openid,判断用户。是自己的ID,如果是文字消息,判断消息字符串是否包含todo,包含则在消息字符串增加勾选框markdown语法,否则使用无序列表。然后根据当日时间,判断当日日志是否存在。若存在,下载本日日志并添加处理好的字符串,然后上传。不存在则直接上传处理好的字符串。 >如果是图片消息,从消息中获取图片url并下载。下载完成之后上传至COS中,图片命名为当前的时间精确到秒。图片名包装成md图片链接。处理好的字符串按照文字消息的处理方法保存。 **注意:以下代码仅为参考,最新代码请带 https://gitee.com/kkbt/obsidian-csapi 获取。** 主文件 wechat.py 和 get_add.py 需要放到同一级目录下。运行 `python wechat.py` ```python # -*- coding=utf-8 # README # 需要安装的依赖 # werobot cos-python-sdk-v5 # 可用 Alist 或其他可挂载 S3 的开源网盘 实现web编辑.md from qcloud_cos import CosConfig from qcloud_cos import CosS3Client import werobot import time import get_add as cosga # 相关信息 token = "token" # 自定义 APP_ID = "wxxxxxxxxxxxxxxxxx" # 微信公众号测试号APP_ID APP_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx" # 微信公众号测试号APP_SECRET # werobot 配置 robot = werobot.WeRoBot(token=token) robot.config["APP_ID"] = APP_ID robot.config["APP_SECRET"] = APP_SECRET rob_client = robot.client rob_client.delete_menu() # # rob_client.create_menu({ # "button":[{ # "type": "click", # "name": "今日", # "key": "info" # }] # }) # message.source 为 OpenID 。获取->测试号二维码->用户列表(最多100个)->微信号 @robot.key_click("info") def menu_click(message): if (message.source != "o6_bmjrPTlm6_2sgVt7hMZOPfL2M"): return '你不是恐咖兵糖' return cosga.get_daily_today() # 关注回复 @robot.subscribe def subscribe(message): return "这是恐咖兵糖的测试公众号" # 文字消息回复 put_object append_object @robot.text def text_reply(message): if (message.source != "o6_bmjrPTlm6_2sgVt7hMZOPfL2M"): return '你不是恐咖兵糖' str = cosga.add_memos_in_daily(message.content) # ETag return "📩 已保存" # 图片消息 @robot.image def image_reply(message): if (message.source != "o6_bmjrPTlm6_2sgVt7hMZOPfL2M"): return '你不是恐咖兵糖' now_key = cosga.save_asset(message.img) str = cosga.add_memos_in_daily("![]("+now_key+")") # ETag return "📩 已保存" @robot.error_page def make_error_page(url): return "404" @robot.handler def error_message(message): return "不支持的消息类型" robot.config["HOST"] = "0.0.0.0" robot.config["PORT"] = "8008" robot.run() ``` get_add.py ```python # -*- coding=utf-8 # 需要安装的依赖 # werobot cos-python-sdk-v5 from qcloud_cos import CosConfig from qcloud_cos import CosS3Client import time import requests # 相关信息 secret_id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx" # 腾讯云 secret_i secret_key = "xxxxxxxxxxxxxxxxxxxxxxxxx" # 腾讯云 secret_key region = "ap-nanjing" # 腾讯云 COS cos_token = None # 腾讯云 COS token scheme = "https" # 腾讯云 COS 访问模式 bucket = "test-0123456789" # 腾讯云 Bucket config = CosConfig( Region=region, SecretId=secret_id, SecretKey=secret_key, Token=cos_token, Scheme=scheme, ) client = CosS3Client(config) # name = time.strftime("%Y%m%d%H%M%S", time.localtime()) def add_memos_in_daily(text): # 生成ObjectKey => 日志/2022-08-08.md daily_note_dir_path = "日志/" today_daily_file_key = daily_note_dir_path + time.strftime("%Y-%m-%d", time.localtime()) + ".md" todo = "todo" if todo in text: message = time.strftime("\n- [ ] %H:%M ", time.localtime()) + text else: message = time.strftime("\n- %H:%M ", time.localtime()) + text response3 = client.object_exists( Bucket=bucket, Key=today_daily_file_key ) # 判断本日日志是否存在 if(response3==True): # 存在 读取文件 response2 = client.get_object( Bucket=bucket, Key=today_daily_file_key ) str1=response2['Body'].get_raw_stream().read().decode('utf-8') btyes = bytes(str1+ message, encoding="utf8") else: btyes = bytes(message, encoding="utf8") #btyes = bytes(str1+"- 20:01 somgthing", encoding="utf8") # name = time.strftime("%Y%m%d%H%M%S", time.localtime()) response_sum = client.put_object( Bucket=bucket, Body=btyes, Key=today_daily_file_key ) return response_sum["ETag"] def save_asset(file): # 生成ObjectKey => 日志/附件/202208/20220808131104.jpg file = requests.get(file).content # wechat file is url 为了防止过期,下载下来。 # file = bytes("![]("+file+")", encoding = "utf8") # 直接使用腾讯微信链接显示图片 daily_asset_dir_path = "日志/附件/" + time.strftime("%Y%m",time.localtime()) + "/" today_daily_asset_file_key = daily_asset_dir_path + time.strftime("%Y%m%d%H%M%S", time.localtime()) + ".jpg" now_key = today_daily_asset_file_key response_file = client.put_object( Bucket=bucket, Body=file, Key=now_key ) print(response_file["ETag"]) return now_key # 已弃用 原因: 超过一定长度后微信显示服务错误 def get_daily_today(): # 生成ObjectKey => 日志/2022-08-08.md daily_note_dir_path = "日志/" today_daily_file_key = daily_note_dir_path + time.strftime("%Y-%m-%d", time.localtime()) + ".md" response3 = client.object_exists( Bucket=bucket, Key=today_daily_file_key ) if(response3==True): # 存在 读取文件 response2 = client.get_object( Bucket=bucket, Key=today_daily_file_key ) str1=response2['Body'].get_raw_stream().read().decode('utf-8') return str1 else: return '今日无日志' ``` ## 效果图 > 微信测试号建议直接放在桌面 {{< image src="https://cdn.ftls.xyz/images/2022/07/Screenshot_2022-08-08-18-39-24-000_com.jpg" caption="微信测试号建议直接放在桌面" >}} {{< image src="https://cdn.ftls.xyz/images/2022/07/Screenshot_2022-08-08-18-33-33-695_com.jpg" caption="微信测试号" >}} {{< image src="https://cdn.ftls.xyz/images/2022/06/20220808183650.png" caption="Memos 效果" >}} {{< image src="https://cdn.ftls.xyz/images/2022/06/20220808183750.jpg" caption="源码效果" >}} **以上效果图为早期版本效果图,新的版本已经返回已保存,和可点击的链接文字。即可在微信内置浏览器使用 Memeos** 希望以后会有优秀的类似转发服务提供商,而且按量付费不太贵那种。能用很简单,好用很困难。Knuth 大佬(发明 KMP 算法的那位),说二分 > Although the basic idea of binary search is comparatively straightforward, the details can be surprisingly tricky... 这软件也是如此,思路很简单,细节是魔鬼