Obsidian 是一款优秀的双链笔记软件,这里不多做介绍,能搜索到这篇文章的读者应该对此有了解。 我的笔记使用历程非常久远了,简单而不完全的回忆包括:Evernote、vimwiki、simplenote、onenote 、notion、roam research、logseq、obsidian。这些笔记软件都有各自的优势,但是目前我使用的是 Obsidian。
在桌面的使用场景下,使用 Dropbox 同步可以满足 Windows、Ubuntu、MacOS 三个平台的同步需求。 但是移动端 iOS 场景下,由于 iOS 的机制问题,Dropbox 同步无法获得好的体验。下面整理相关同步方案, 供读者备选。先后顺序表示优先级。
官方链接 <obsidian.md/sync>
除了贵没有什么缺点,正常用户年付价格 8 USD/month,学生年付价格6折即 4.8 USD/month。早鸟用户 年付价格5折即 4 USD/month。
一个降低费用的方法是合租,因为一个 Obsidian Sync 付费账可以建立5个 remote vault (< https://help.obsidian.md/Obsidian+Sync/Limitations>) 每个 vault 可设置独立的密码 ( https://help.obsidian.md/Obsidian+Sync/Set+up+Obsidian+Sync ) 因此不用担心你的数据泄漏。 但是账户密码公开,每个成员均有权限删除仓库、删除账户、修改账户邮箱及密码,以上风险后果是损失一年的订阅费用,但是数据是安全的。相关信息可参考参考链接部分中的论坛合租讨论。 以及淘宝/闲鱼中也有相关车位出售。
来自高中生 @acheong08 大神的逆向实现。
相关链接
https://github.com/vrtmrz/obsidian-livesync
Self-hosted LiveSync (自搭建在线同步) 是一个社区实现的在线同步插件。 使用一个自搭建的或者购买的 CouchDB 作为中转服务器。兼容所有支持 Obsidian 的平台。
使用 CounchDB 数据库,可以做到实时同步,我自己折腾了两次,移动端使用体验一言难尽。
https://github.com/remotely-save/remotely-save
https://github.com/oscarspalk/obsidian-git-sync
对于比较大的仓库,手机上 git pull 的效率较低。
我使用 beancount 记账流程中的有一步是这样的,将每张信用卡的账单日添加到滴答清单中,每月重复。
每当到达账单日时,提醒我在 beancount 文件中添加一条对应帐目的 balance 断言语句,由于大部分信用卡
的出账是有滞后的,所以该balance断言通常需要同时加上!标记,便于后续账单出来后修改。
这个过程是比较机械的,所以我想到了使用 chatGPT 来自动化这个过程,这样我只需要在出账后手动更新自动添加
的断言语句,将金额修改为正确的还款金额,同时去除!标记。最终的脚本如下。
import datetime
def add_balance_statement(ledger_path, account, date, balance, currency):
with open(ledger_path, 'a') as file:
file.write(f"{date} balance {account} {balance} {currency}\n")
def auto_add_balance_statements(ledger_path, credit_cards):
today = datetime.date.today()
for card in credit_cards:
bill_date = card['bill_date']
accounts = card['accounts']
balance = card['balance']
currency = card['currency']
if today.day == bill_date:
for account in accounts:
add_balance_statement(ledger_path, account, today, balance, currency)
print(f"Balance statement added for {account} on {today}.")
# Specify the path to your Beancount ledger file
ledger_file_path = "<ledger_path>"
# Specify your credit card details (bill date, accounts, balance, and currency)
credit_cards = [
{
'bill_date': 1, # Example: 1st of the month
'accounts': [
{'account': 'Assets:CreditCards:Card1:Account1', 'currency': 'USD'}, # Example: Account1 for Card1 with USD currency
{'account': 'Assets:CreditCards:Card1:Account2', 'currency': 'EUR'}, # Example: Account2 for Card1 with EUR currency
],
'balance': 1000.00, # Example: Current balance for Card1
'currency': 'USD' # Example: Currency for Card1
},
{
'bill_date': 15, # Example: 15th of the month
'accounts': [
{'account': 'Assets:CreditCards:Card2:Account1', 'currency': 'USD'}, # Example: Account1 for Card2 with USD currency
{'account': 'Assets:CreditCards:Card2:Account2', 'currency': 'GBP'}, # Example: Account2 for Card2 with GBP currency
],
'balance': 2000.00, # Example: Current balance for Card2
'currency': 'USD' # Example: Currency for Card2
},
# Add more credit card details as needed
]
# Call the function to automatically add balance statements
auto_add_balance_statements(ledger_file_path, credit_cards)
对于有兴趣的读者,可以看我和 chatgpt 的几轮对话。
#ING
Q: Write a python script, it check today’s date, if it match a specific day in a month, writing some content to a file, whois path is <path>.
A: Certainly! Here’s a Python script that checks if today’s date matches a specific day in a month and writes some content to a file:
import datetime
def write_content_to_file(path, content):
with open(path, 'a') as file:
file.write(content + '\n')
def check_and_write_content(path, day, month, content):
today = datetime.date.today()
if today.day == day and today.month == month:
write_content_to_file(path, content)
print("Content written to the file.")
else:
print("Today's date does not match the specified day.")
# Specify the path, day, month, and content
file_path = "<path>"
day = 15
month = 7
content = "This is the content to be written."
# Call the function to check and write content
check_and_write_content(file_path, day, month, content)
In the script above, you need to replace "<path>" with the actual path to the file where you want to write the content. Also, specify the day, month, and content variables according to your requirements.
The script checks if today’s date matches the specified day and month. If it does, it calls the write_content_to_file function to append the content to the file. If the date doesn’t match, it prints a message indicating that today’s date doesn’t match the specified day.
Q:I have many credit cards, each card have different bill date. I want a python script can auto add a balance statement to my beancount ledger. please help me writing this script. A:Certainly! Here’s a Python script that can help you automatically add a balance statement to your Beancount ledger based on the bill dates of your credit cards:
import datetime
def add_balance_statement(ledger_path, account, date, balance):
with open(ledger_path, 'a') as file:
file.write(f"{date} balance {account} {balance}\n")
def auto_add_balance_statements(ledger_path, credit_cards):
today = datetime.date.today()
for card in credit_cards:
bill_date = card['bill_date']
account = card['account']
balance = card['balance']
if today.day == bill_date:
add_balance_statement(ledger_path, account, today, balance)
print(f"Balance statement added for {account} on {today}.")
# Specify the path to your Beancount ledger file
ledger_file_path = "<ledger_path>"
# Specify your credit card details (bill date, account, and balance)
credit_cards = [
{
'bill_date': 1, # Example: 1st of the month
'account': 'Assets:CreditCards:Card1', # Example: Account for Card1
'balance': 1000.00 # Example: Current balance for Card1
},
{
'bill_date': 15, # Example: 15th of the month
'account': 'Assets:CreditCards:Card2', # Example: Account for Card2
'balance': 2000.00 # Example: Current balance for Card2
},
# Add more credit card details as needed
]
# Call the function to automatically add balance statements
auto_add_balance_statements(ledger_file_path, credit_cards)
In the script above, you need to replace "<ledger_path>" with the actual path to your Beancount ledger file. Also, specify the bill_date, account, and balance for each of your credit cards in the credit_cards list.
The script checks if today’s date matches the bill date for each credit card. If it does, it calls the add_balance_statement function to add a balance statement to the ledger file. The balance statement includes the account, date, and balance for the credit card. If the date doesn’t match the bill date for a particular credit card, it moves on to the next card.
Q:one bill_date can have multiple accounts, refine your code. A:Certainly! Here’s an updated version of the script that allows multiple accounts for a single bill date:
import datetime
def add_balance_statement(ledger_path, account, date, balance):
with open(ledger_path, 'a') as file:
file.write(f"{date} balance {account} {balance}\n")
def auto_add_balance_statements(ledger_path, credit_cards):
today = datetime.date.today()
for card in credit_cards:
bill_date = card['bill_date']
accounts = card['accounts']
balance = card['balance']
if today.day == bill_date:
for account in accounts:
add_balance_statement(ledger_path, account, today, balance)
print(f"Balance statement added for {account} on {today}.")
# Specify the path to your Beancount ledger file
ledger_file_path = "<ledger_path>"
# Specify your credit card details (bill date, accounts, and balance)
credit_cards = [
{
'bill_date': 1, # Example: 1st of the month
'accounts': [
'Assets:CreditCards:Card1:Account1', # Example: Account1 for Card1
'Assets:CreditCards:Card1:Account2', # Example: Account2 for Card1
],
'balance': 1000.00 # Example: Current balance for Card1
},
{
'bill_date': 15, # Example: 15th of the month
'accounts': [
'Assets:CreditCards:Card2:Account1', # Example: Account1 for Card2
'Assets:CreditCards:Card2:Account2', # Example: Account2 for Card2
],
'balance': 2000.00 # Example: Current balance for Card2
},
# Add more credit card details as needed
]
# Call the function to automatically add balance statements
auto_add_balance_statements(ledger_file_path, credit_cards)
In this updated version, each credit card in the credit_cards list has a bill_date, accounts, and balance. The accounts field is a list of all the accounts associated with that credit card. The script iterates through each credit card and its associated accounts. If today’s date matches the bill date, it adds a balance statement for each account with the specified balance.
Please replace "<ledger_path>" with the actual path to your Beancount ledger file. Also, update the credit card details in the credit_cards list according to your specific accounts and balances.
Q:different accounts can have different currency, please add currency info to account. A:Certainly! Here’s an updated version of the script that includes currency information for each account:
import datetime
def add_balance_statement(ledger_path, account, date, balance, currency):
with open(ledger_path, 'a') as file:
file.write(f"{date} balance {account} {balance} {currency}\n")
def auto_add_balance_statements(ledger_path, credit_cards):
today = datetime.date.today()
for card in credit_cards:
bill_date = card['bill_date']
accounts = card['accounts']
balance = card['balance']
currency = card['currency']
if today.day == bill_date:
for account in accounts:
add_balance_statement(ledger_path, account, today, balance, currency)
print(f"Balance statement added for {account} on {today}.")
# Specify the path to your Beancount ledger file
ledger_file_path = "<ledger_path>"
# Specify your credit card details (bill date, accounts, balance, and currency)
credit_cards = [
{
'bill_date': 1, # Example: 1st of the month
'accounts': [
{'account': 'Assets:CreditCards:Card1:Account1', 'currency': 'USD'}, # Example: Account1 for Card1 with USD currency
{'account': 'Assets:CreditCards:Card1:Account2', 'currency': 'EUR'}, # Example: Account2 for Card1 with EUR currency
],
'balance': 1000.00, # Example: Current balance for Card1
'currency': 'USD' # Example: Currency for Card1
},
{
'bill_date': 15, # Example: 15th of the month
'accounts': [
{'account': 'Assets:CreditCards:Card2:Account1', 'currency': 'USD'}, # Example: Account1 for Card2 with USD currency
{'account': 'Assets:CreditCards:Card2:Account2', 'currency': 'GBP'}, # Example: Account2 for Card2 with GBP currency
],
'balance': 2000.00, # Example: Current balance for Card2
'currency': 'USD' # Example: Currency for Card2
},
# Add more credit card details as needed
]
# Call the function to automatically add balance statements
auto_add_balance_statements(ledger_file_path, credit_cards)
In this updated version, each account in the accounts list of each credit card includes both the account name and the currency. The add_balance_statement function is modified to include the currency parameter when writing the balance statement to the ledger.
Please replace "<ledger_path>" with the actual path to your Beancount ledger file. Also, update the credit card details in the credit_cards list according to your specific accounts, balances, and currencies.
Miniflux 是一个非常好用的 RSS 自托管方案,支持自建,支持多种客户端,支持多种订阅方式。 最近由于在折腾 Archivebox,需要将 Miniflux 中的 Starred Feed 作为一个 Feed 输出,以便于 导入星标条目到 Archivebox。 Miniflux 本身并不支持这个功能,但是其提供了 API,可以比较简单的导出 Starred 内容。
如果是自己使用 Python 写的话,可以利用 https://github.com/miniflux/python-client 这个库,配合 feedgen 也能写个大概的,核心代码大概如下:
import miniflux
from feedgen.feed import FeedGenerator
client = miniflux.Client("https://miniflux.example.com", api_key="api_key")
entries = client.get_entries(starred=True, limit=50)
def create_rss_page(data):
fg = FeedGenerator()
fg.title('Miniflux Starred Feed')
fg.link(href='https://miniflux.wogong.net', rel='self')
fg.language('en')
fg.description('Miniflux Starred Feed')
for entry in data['entries']:
fe = fg.add_entry()
fe.id(entry['id'])
fe.title(entry['title'])
fe.link(href=entry['url'])
fe.description('nothing')
fe.author(name=entry['author'])
fe.pubDate(entry['published_at'])
rss_feed = fg.rss_str(pretty=True)
fg.rss_file('rss.xml')
return rss_feed
但是本着不自己造轮子的原则,找到了一些现成的工具,例如
两个项目的 star 数都寥寥,miniflux 有这么小众么,第一个工具尝试了一下,导出 starred item 出问题了, 估计太久没维护,提交了一个 issue https://github.com/rogierlommers/miniflux-exporter/issues/8
第二个项目同样有问题,编译都没通过,我对 go 也是两眼抹黑,同样提交了 issue https://github.com/erdnaxe/miniflux-luma/issues/1
这个作者反应迅速,直接修复了,而且可以通过 web 方式提供 feed,决定就用他了。
当然可以选择直接用编译好的二进制文件,但是我还是喜欢用 docker-compose 来部署,方便管理。
这也不只是一个偏好问题,多维护一个独立的 Web 服务显然是不合理的,而且这个服务只是 Miniflux
的附属,所以要是能集成到 miniflux 的 docker-compose 中就好了。一番折腾,获得如下的
docker-compose.yaml 文件:
version: '3.4'
services:
miniflux:
image: miniflux/miniflux:latest
ports:
- "127.0.0.1:8080:8080"
depends_on:
- db
environment:
- DATABASE_URL=postgres://miniflux:secret@db/miniflux?sslmode=disable
- RUN_MIGRATIONS=1
- DEBUG=0
- CREATE_ADMIN=1
- ADMIN_USERNAME=
- ADMIN_PASSWORD=
db:
image: postgres:latest
environment:
- POSTGRES_USER=miniflux
- POSTGRES_PASSWORD=
volumes:
- miniflux-db:/var/lib/postgresql/data
- ./back:/back
healthcheck:
test: ["CMD", "pg_isready", "-U", "miniflux"]
interval: 10s
start_period: 30s
luma:
build: miniflux-luma
ports:
- "127.0.0.1:8081:8080"
command: -endpoint http://miniflux:8080 -listen-addr 0.0.0.0:8080
volumes:
- ./miniflux-luma/api_token:/api_token
volumes:
miniflux-db:
miniflux-luma 官方并没有提供 Dockerfile,可参考我的仓库 https://github.com/wogong/miniflux-luma
之后无论是自己反代 8081 端口还是通过 Cloudflare Tunnel 反代,都可以方便的使用了。 和 miniflux 共同维护也比较方便,挂了一个另一个也没意义了反正。