构建每日随想

前言

2017-8 至 2018-1

这套系统很多工具都提供了类似的甚至更好的实现,比如 Drafts 自带的 Journal 相关动作,但我认为做出使用一套系统的决定过程,这其中免不了对比各种工具,试验各种方式去寻找最适合自己的方法

比如 IBM Watson 的结构已经透露的差不多了,但是为什么这么设计,为什么否掉其他的设计方案,这些一路走过来的坑,那是更加重要的

所以才有了这个总结文章,整理了一路过来的各种实现,以及每种实现的特色

名词解释

  • PATH:
    • 在手机上指的是 Dropbox 下的目录,比如 /Apps/DailyNotes/2018/2018-01-01 中的 /Apps/DailyNotes/ 部分,年份是需要调用若干脚本来完成自动填充的,Launch Center Pro 中用 Textexpander 即可,Drafts 用 [[time|%Y]] 即可完成
    • 电脑上指的是文件夹在电脑上的绝对路径
  • 识别码
    • Drafts: UUID
    • Bear: 全称 identifier,URL Schemes 中为 id
    • Ulysses: identifier

背景:每日随想需要怎样的工具

这一套系统仅适合于纯文本记录,如果涉及到图像则无能为力,除非上传到图床上
也许可以试试 Google Keep

每日随想是我在手机上使用的一套东西,在不同的场景调用 Launch Center Pro + Drafts + Workflow 中的一个,将输入的文本合并到 Dropbox 特定目录下的以日期命名的文本中

这个想法的来源是 Bitcron 微信公众号提供的服务,使用过之后觉得很好,就开始尝试自己实现一套工具

基本工作模式就是可以随时合并一段文本到设定的地方,而且不需要我手工维护,手工修改存储地点,同时每天的位置都是唯一可确定的,最简易的办法就是时间日期为文件名/笔记名。还可以导出全文到 Day One 中

这时遇到个问题:是采用笔记类 App 还是直接操作 Dropbox 文件呢

iOS 上笔记类 App 的操作

iOS 上返回笔记类 App 内的单一条目,无外乎两种方法:

  1. 基于 App 分配的笔记/条目识别码
  2. 通过标题搜索获取

而具体的实现又分两种方法:

  1. 本地 URL Schemes 实现
  2. 联网的 API 实现

基于 App 分配的识别码

以下 Workflow 都提供了支持动作,利用 URL Schemes 跳转实现

Bear

Bear 的导出基于 /open-note 动作,很有意思,值得详细解释一下 官网页面 的内容

根据笔记的 identified 或者标题打开笔记并返回内容

参数

  • id 可选 笔记的唯一识别吗
  • title 可选 笔记的标题
  • exclude_trashed 可选 如果 yes 不包括删除的笔记
  • new_window 可选 如果 yes 在新的窗口打开笔记
  • show_window 可选 如果 no 不会打开 Bear 的主界面 (这个我并不清楚是什么)

x-success 返回结果:返回的是 json 格式的文本,以下是 key

  • note 笔记正文.
  • identifier 笔记识别码
  • title 笔记标题
  • modificationDate 笔记的修改时间格式为 ISO 8601
  • creationDate 笔记的创建时间格式为 ISO 8601

例子

bear://x-callback-url/open-note?id=7E4B681B

因为 URL Schemes 返回的是一整个 JSON 字符串,形如

{"creationDate":"2018-01-18T07:38:54Z","":"","title":"2018-01-01","modificationDate":"2018-01-18T07:40:52Z","note":"# 2018-01-01\n\ntest","identifier":"03B6B2AE-A029-4EA3-A21F-DC27AFA61EB6-9709-0000063AFA917F87"}

这样的内容无法在纯 URL Schemes 环境下完成解析,需要脚本程序来完成提取:

  • Workflow 的 Dictionary 相关动作
  • Python 中的 import json; notes = json.loads(bear_return_json)
  • 会 Javascript 的可以考虑动手实现一段简单的程序完成 JSON 的提取,然后放到 textexpander 中

node.js 下的例子,抛砖引玉之用

var bear = {"creationDate":"2018-01-18T07:38:54Z","":"","title":"2018-01-01","modificationDate":"2018-01-18T07:40:52Z","note":"# 2018-01-01\n\ntest","identifier":"03B6B2AE-A029-4EA3-A21F-DC27AFA61EB6-9709-0000063AFA917F87"}
console.log(bear['note'])

实际使用时直接用 Workflow 自带的 Get Contents of Bear Note 就好

添加文本 大同小异,不过返回的是标题和笔记正文

Ulysses + Drafts

Ulysses 和 Drafts 的 URL Schemes 比 Bear 多了一个验证功能,其中 Drafts 是可选的(用户手动输入一个 key 即可),Ulysses 是强制的, 初次使用需要进行验证,来返回一个访问令牌 ,在 Workflow 中利用 Open X-Callback URL 可以获取 Ulysses 生成的令牌,选择保存到 iCloud Drive 即可方便日后使用, 这是一个获取令牌 Workflow

Workflow 自带了完整的 Ulysses 和 Drafts URL Schemes 支持,就不一一实现了

通过标题获取

基于 URL Schemes 实现 -> Bear

这里表扬 Bear 可以实现,以 Workflow 为例子 日记自动生成 Bear

bear://x-callback-url/open-note?title=2018

基于 API 实现 -> Evernote

Workflow 自带的 Get Notes 动作

小结

通过识别码固然很方便,但是每天生成的识别码都是变化的,没有规则可循,需要手工维护每天的识别码才可以。

通过标题方便直观地多,但是用笔记类 App 有一个同步问题,需要打开才能同步。以 Bear 为例,如果电脑添加/修改记录后,手机直接走 Launch Center Pro 添加记录,Bear 在那个瞬间是没有同步的,于是就创建出新的一条记录,或者会检测到冲突,显示出冲突笔记条目。如果是利用 Dropbox 来进行同步就没有这个问题了

iOS 上 Dropbox 文件操作

Dropbox 应是唯一的选择,在 Launch Center Pro, Drafts 中都有很好的支持,同时也是唯一一个在两者中都不用进行跳转的内建服务。既然要使用云盘,那就不应当再进行来回来去的跳转 1

就个人来说,x-callback-url 固然能实现很有意思的事情,但是跳转过程本身就造成了割裂,所以更倾向于通过云服务来存储

Launch Center Pro

比如 Launch Center Pro 内的动作是:

launch://dropbox/append?text={{[textexpander:ttime] [prompt:Text]}}&path={{/Apps/DailyNotes/2018}}&name={{[textexpander:ddate].txt}}

其中 textexpander 模版如下格式(自带的):

textexpander:ttime -> %Y-%m-%d %H:%M:%S -> 2018-01-18 18:00:24
textexpander:ddate -> %Y-%m-%d -> 2018-01-18

返回内容并添加到 Day One 则类似:

launch://dropbox/clipboard?path={{/Apps/DailyNotes/2018/[textexpander:ddate].txt}}&x-success={{dayone://post?entry=[clipboard]}}

Drafts

动作安装 连接 ,其 Action 结构如下:

x-drafts4://x-callback-url/import_action?v=2&tintColor=[
 
]&shouldConfirm=0&logLevel=1&uuid=FC5C65F4-AB6D-49F4-A514-705764ECEEA2&disposition=2&actionSteps=[
  {
    "writeType" : "append",
    "fileTemplate" : "[[time|%Y-%m-%d %H:%M:%S]] [[draft]]\n",
    "actionStepType" : "Dropbox",
    "folderTemplate" : "\/Apps\/DailyNotes\/[[time|%Y]]\/",
    "fileExtTemplate" : "txt",
    "fileNameTemplate" : "[[date|%Y-%m-%d]]"
  }
]&description=&modifiedAt=2018-01-18 10:23:58 +0000&name=每日随想 (Copy)&iconImageName=action_dropbox

小结

显而易见,当连接 Dropbox 的网络相对通畅,不影响少量的文本上传下载时,这种交互远比利用笔记类 App 要省心,不用去想各种跳转,也不会有各种同步冲突出现

也正是这个原因,坚定了我用 Dropbox 记录每日随想

macOS 上的操作

macOS 目前我只进行记录,分两种场景

  1. Alfred
  2. 终端

两个的基础依赖是通用的:一段 Python 脚本。我日常的使用是 Python3 的,Alfred 目前支持的是 Python2,所以程序也是 2.x 和 3.x 兼容的 ~~恍惚间仿佛回到了一年前在 Python2 的脚本中翻腾编码的状态~\~

电脑上存储的目录结构大致是如下形式的

/Users/[用户名]/Dropbox//Apps/DailyNotes/2018/2018-01-15.txt

电脑和手机用的路径是不一样的,电脑上用的整个系统是绝对路径,而手机上用的是存储目录在网盘中的相对路径

使用的时候把 /Users/[用户名]/Dropbox//Apps/DailyNotes/ 替换程序中的 主存储目录

"""DailyNotes"""
import os
import sys
import time

DEBUG = 0 # 0 for use; 1 for debug
YEAR = str(int(time.strftime("%Y", time.localtime())) + DEBUG)
DATE = time.strftime("%Y-%m-%d", time.localtime())
TIME = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

FOLDER_PATH = '主存储目录'  # /Users/[用户名]/Dropbox//Apps/DailyNotes/
FILE_PATH = '/'.join([FOLDER_PATH, YEAR, DATE]) + '.txt'

NOTE = ' '.join(sys.argv[1:])

if os.path.exists(FILE_PATH):
    # exists -> append
    with open(FILE_PATH, 'a') as f:
        f.write('\n%s %s\n' %(TIME, NOTE))
else:
    # not exists -> create
    with open(FILE_PATH, 'w') as f:
        f.write('# %s\n' %(DATE))
        f.write('\n%s %s\n' %(TIME, NOTE))

终端中,我用的是添加 alias

alias note="python3 [脚本程序路径]"

结语

本文是对我在过去几个月尝试记录日常思考的总结,这套随手记系统目前运行良好,跨平台同步,导出都很顺利。当然,我自己也并不满意,我很希望为每一个条目都能分配上标签,方便他们的归类整理,而不是现在这样按照时间的线性顺序排列,有点像数据库,按照时间顺序线性存储,但是支持更高级的查找与过滤。

也许有时间弄个程序来完成?CSV 文件格式 或者通过 Airtable 我觉得是可以考虑的

前不久看到锤子手机的闪念胶囊功能,觉得也挺好,有机会尝试一下?

Live long and prosper.

相关阅读


  1. iOS 操作 WebDAV 网盘的重量级 App Transmit 于近日宣布停止开发并将下架: The Future of Transmit iOS ,所以放弃了尝试使用坚果云完成同步的想法  

Comments
Write a Comment