讓 BOOX 也使用繁體中文辭典

由於最近讀原文書讀得挺辛苦,邊用電子閱讀器看書,騰不出手用手機查字典,內建的辭典又只有英文翻譯簡體中文,在網上衝浪也找不到繁體中文的 mdx 英漢辭典可以直接使用。 所需依賴 任何英漢辭典 文內以 BOOX 內下載的英漢辭典,參考教學。 python 環境,用以安裝 mdict-utils 經測試後 windows 與 wsl 中均能完成,文內 python 環境以 wsl 為主。 任何繁簡轉換軟體 文內以新發現的 ConvertZZ 最為 GUI 簡轉繁示例。 文末有使用 OpenCC 作為 CLI 示例。 主要流程 將 mdx 拆成 txt 簡轉繁 將 txt 包成 mdx 安裝 安裝 mdict-utils ❯ pip install mdict-utils Defaulting to user installation because normal site-packages is not writeable Collecting mdict-utils Downloading mdict_utils-1.3.12-py3-none-any.whl (36 kB) Collecting xxhash Downloading xxhash-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (212 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 212.5/212.5 KB 1.6 MB/s eta 0:00:00 Collecting tqdm Downloading tqdm-4.65.0-py3-none-any.whl (77 kB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 77.1/77.1 KB 7.4 MB/s eta 0:00:00 Installing collected packages: xxhash, tqdm, mdict-utils Successfully installed mdict-utils-1.3.12 tqdm-4.65.0 xxhash-3.2.0 unpack 將英漢辭典重新命名為 dict.mdx ...

如何優雅地批次安裝 Nerd font 字型

fonts repo 接觸 wsl/ubuntu 的這幾年,經常會需要安裝 zsh 以及字型,因此誕生了 cheat sheet,久而久之連下載->解壓縮->安裝這個過程,都懶了。 於是寫了一個批次下載並安裝最新版本的 Nerd Fond 字型的 shell script,讓 wsl 可以安裝 windows 的字型,linux 可以安裝 linux 字型。 #!/bin/bash declare target="linux" declare repo="ryanoasis/nerd-fonts" declare -a fonts=( BitstreamVeraSansMono CodeNewRoman DroidSansMono FiraCode FiraMono Go-Mono Hack Hermit JetBrainsMono Meslo Noto Overpass ProggyClean RobotoMono SourceCodePro SpaceMono Ubuntu UbuntuMono ) ARGS=`getopt -o p --long windows -- "$@"` if [ $? -ne 0 ]; then echo "getopt failed: " $ARGS exit 1 fi eval set -- "${ARGS}" while true do case "$1" in -p|--windows) target=windows shift ;; --) shift break ;; esac done get_latest_release() { echo $(curl --silent "https://api.github.com/repos/$@/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') } function install_linux_fonts() { local fonts_dir fonts_dir="${HOME}/.local/share/fonts" if [[ ! -d "$fonts_dir" ]]; then mkdir -p "$fonts_dir" fi mv $@/*.ttf $fonts_dir/ # fc-cache -fv } # Install font for the current user. It'll appear in "Font settings". function install_windows_fonts() { local dst_dir dst_dir=$(wslpath $(cmd.exe /c "echo %LOCALAPPDATA%\Microsoft\\Windows\\Fonts" 2>/dev/null | sed 's/\r$//')) mkdir -p "$dst_dir" local src for src in "$@"; do local file=$(basename "$src") test -f "$dst_dir/$file" || cp -f "$src" "$dst_dir/" local win_path win_path=$(wslpath -w "$dst_dir/$file") echo $win_path reg.exe add \ "HKCU\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts" \ /v "${file%.*} (TrueType)" /t REG_SZ /d "$win_path" /f 2>/dev/null done } function main() { local version version=$( get_latest_release $repo ) local tmp_dir tmp_dir="$(mktemp -d)" trap "rm -rf ${tmp_dir@Q}" INT TERM EXIT for font in "${fonts[@]}"; do zip_file="${font}.zip" download_url="https://github.com/$repo/releases/download/${version}/${zip_file}" echo "Downloading $download_url" wget -q --show-progress -P "$tmp_dir" "$download_url" # unzip -o means replace file without asking. unzip -o "$tmp_dir/$zip_file" -d "$tmp_dir" rm "$tmp_dir/$zip_file" done find "$tmp_dir" -name '*Windows Compatible*' -delete if [ "$target" = "linux" ] then install_linux_fonts $tmp_dir elif [ "$target" = "windows" ] then install_windows_fonts $tmp_dir/*.ttf fi } main echo -e '\033[0;32m' echo 'Fonts successfully installed.' echo -e '\033[0m' 若沒有要改目標字型也可以直接透過 github 上的檔案來安裝 ...

golang 中使用 Line LIFF 實作 Single Sign-On

文章中的程式碼放在https://github.com/omegaatt36/line-verify-id-token中。 Requirements Line Login Channel channel id channel secret Line LIFF APP 用 liff.getIDToken() 獲取 ID Token 在現代網站中,單一登錄 (Single Sign-On, SSO) 已經成為了一個普遍存在的功能,它能夠讓使用者在不同的應用程式和服務之間自動地登錄,而不需要再輸入帳號和密碼。這樣可以方便使用者的使用,並且也能夠增加安全性,減少帳號密碼被盜用的風險。 我們將使用 Golang 語言來實作單一登錄功能,並且使用 Line LIFF 來進行身份驗證。在此之前,我們需要先了解幾個概念。 Line LIFF (Line Front-end Framework) 是一個由 Line 提供的 Web 應用程式框架,開發者可以使用它來建立 Line 的客戶端應用程式。使用 Line LIFF 開發的應用程式可以在 Line 客戶端中被直接執行,而不需要額外安裝或下載。此外,Line LIFF 還提供了一些功能,例如使用者的身份驗證、分享資料等等。 JWT (JSON Web Token) 則是一種開放標準,用於在不同系統之間安全地傳輸訊息。它通常用於認證和授權,因為它可以確保傳輸的訊息是可信的,而且在傳輸過程中不會被竄改。 我們可以使用 Line 的 Verify API,同時也可以選擇後端自己驗證,解出 jwt 中的資訊。 我們的目的是拿到每個使用者在 Line 的 UserID,做為身分識別。於是根據 Line 提供的 JWT 欄位對應,定義一個結構用來存放驗證後的資訊。 // DecodedIDToken defines decoded payload by id token. type DecodedIDToken struct { Amr []string ChannelID string Email string ExpiredAt int64 IssuedAt int64 Issuer string Name string Picture string UserID string } 接著撰寫一個驗證 ID Token 的 function 用來驗證 ...

跟風寫了個使用 OpenAI API 的 Telegram Chat Bot

前言 放在最前面 Github repo 原本打算使用別人寫好的 bot,免費的版本均是透過儲存 cookies 的方式,直接透過 ChatGPT 網頁建立新的 「Chat」。好景不常,OpenAI 馬上把登入頁面到聊天頁面中間安插了類似 reCaptcha,來驗證是否為真人。看到有好心人提供了 go 版本的 OpenAi API,就打算自己寫一寫,順便當作 《Clean Architecture》 的讀後作業。 依賴注入 架構圖待補 我需要對 OpenAI 詢問,並用 stream(逐字)的方式回給我,也需要對 Telegram 逐字回答。 在這個 8931bf 版本中,很明確定義對於 OpenAI 與 Telegram 的 usecase chatgpt_usecase.go // ChatGPTUseCase defines ChatGPT send question use case. type ChatGPTUseCase interface { Stream(ctx context.Context, question string) (<-chan string, <-chan error) } telegram_usecase.go // TelegramUseCase defines telegram send message use case. type TelegramUseCase interface { SendAsLiveOutput(chatID int64, feed <-chan string) error } 在 *_repository.go 進行實作。並在 main.go 中依賴反轉,將實作注入近 bot service。 ...

Logitech Media Server 遷移紀錄:從 Bare Metal 到 Docker 再到 Podman

2021 年公司開始實施 322 WFH,少了通勤的時間,在家的時間也多了,就想在上班時也能好好對待自己,雖然是木耳但始終會想知道,網路上說的獨立訊源減少雜訊是有多重要,亦或只是玄學?於是誕生了Raspberry pi 4 + piCorePlayer 7.0.0 折騰筆記這篇筆記,到現在這個部落格的累積曝光最高的也是因為這篇吧。 雖然說現在已經出到 8.2.0,但也已經是 2022 年六月的版本了,起初因為 raspberry pi 4b 便宜而使用 piCorePlayer,後來也因 raspberry pi 4b 漲價(漲幅超過 100%)進而不使用 piCorePlayer,不知道官方後來沒更新了是因為樹莓派太穩定,還是真的太貴了…。 從 Bare Metal 到 Docker 當時在學習 HomeLab,首先是從 portainer 開始玩,也因此誕生了 logitech media server 搭配 docker 實現雙機分離。後來也用著同樣的 image 將 lms 建在 k8s cluster 內,遇到的比較髒的問題是 nginx 的 port 用非正式的方式解決。 這時候其實已經不在乎 logitech media server 是否帶來更好的音質了,也沒有連動 NAS 的音樂,主要是使用 Youtube Plugin 播放 Youtube 上的內容(即便有訂閱 Youtube Premium)。以及使用 Podcast Plugin 收聽 podcast。 使用 docker 的好處不外乎一個字,省,於是我把 raspberry pi 4b 也給賣了。 從 Docker 到 Podman 與 LXC 2022 年台灣疫情大爆發,公司也從 322 變成全遠端,但也在 2022 下半年恢復 322,於 2023 年正式恢復正常進辦公室。在這期間發現 logitech media server 使用 docker 做為執行環境,除了省物理機的錢(相較 bare metal),更省顯示卡資源。 ...

WSL2 中使用 systemd 管理 podman 的 container

原本使用 wsl-distrod 來作為 wsl 中 systemd 的實現方式,後來 microsoft 宣布 wsl 支持 systemd 後,distrod 等等 repo 就沒有在更新了呢,是巧合嗎?我不這麼認為。 這篇簡略紀錄 wsl2 中啟用 systemd 作為 process 管理工具以及配合紅帽推出的 podman 來取代(斷捨離)docker desktop。 環境 wsl2 + ubuntu 22.04 ❯ neofetch .-/+oossssoo+/-. raiven@raiven `:+ssssssssssssssssss+:` ------------- -+ssssssssssssssssssyyssss+- OS: Ubuntu 22.04.1 LTS on Windows 10 x86_64 .ossssssssssssssssssdMMMNysssso. Kernel: 5.10.43.3-microsoft-standard-WSL2 /ssssssssssshdmmNNmmyNMMMMhssssss/ Uptime: 3 hours, 10 mins +ssssssssshmydMMMMMMMNddddyssssssss+ Packages: 2005 (dpkg), 4 (snap) /sssssssshNMMMyhhyyyyhmNMMMNhssssssss/ Shell: zsh 5.8.1 .ssssssssdMMMNhsssssssssshNMMMdssssssss. Theme: Adwaita [GTK3] +sssshhhyNMMNyssssssssssssyNMMMysssssss+ Icons: Adwaita [GTK3] ossyNMMMNyMMhsssssssssssssshmmmhssssssso Terminal: Windows Terminal ossyNMMMNyMMhsssssssssssssshmmmhssssssso CPU: AMD Ryzen 9 5900X (24) @ 3.700GHz +sssshhhyNMMNyssssssssssssyNMMMysssssss+ GPU: dbac:00:00.0 Microsoft Corporation Device 008e .ssssssssdMMMNhsssssssssshNMMMdssssssss. Memory: 1427MiB / 15966MiB /sssssssshNMMMyhhyyyyhdNMMMNhssssssss/ +sssssssssdmydMMMMMMMMddddyssssssss+ /ssssssssssshdmNNNNmyNMMMMhssssss/ .ossssssssssssssssssdMMMNysssso. -+sssssssssssssssssyyyssss+- `:+ssssssssssssssssss+:` .-/+oossssoo+/-. wsl2 中啟用 systemd 請確保 wsl2 的版本是 version 2,可以在 cmd/powershell 中查看 ...

gin 搭配 html/template 包實現動態生成 HTML 文件

起因 在網站註冊流程中,若是用信箱驗證,網站會寄送一封驗證信到指定的電子信箱。信中可能含有 verify token 或是直接是寫好的 verify URL。至於實作方面我們可以透過 Go 1.16 推出的 Embedding Files 搭配 html/template,實現動態生成 HTML 信件,用以寄送至指定信箱。 本篇內容的詳細程式碼可以到 github 頁面查看。 實作 資料夾結構: project/ ├─ templates/ │ ├─ template.go │ ├─ success.tmpl │ ├─ verify.tmpl ├─ main.go templates project/templates/template.go 在包內宣告私有變數,透過 Embedding Files 讀出目錄內的所有檔案。 package template //go:embed * var f embed.FS 宣告需要被轉換成 HTML 模板的檔案名 TemplateName,可以用 go-enum 來自動生成變數。並將其註冊進陣列 _TemplateNameNames 內。 package template // ENUM( // success.tmpl // verify.tmpl // ) type TemplateName string func (x TemplateName) String() string { return string(x) } var _TemplateNameNames = []string{ string(TemplateNameVerifyTmpl), string(TemplateNameSuccessTmpl), } // TemplateNameNames returns a list of possible string values of TemplateName. func TemplateNameNames() []string { tmp := make([]string, len(_TemplateNameNames)) copy(tmp, _TemplateNameNames) return tmp } const ( TemplateNameVerifyTmpl TemplateName = "verify.tmpl" TemplateNameSuccessTmpl TemplateName = "success.tmpl" ) 最終將 embed files 與檔案名丟給 html/template 包請他們我們轉換成 template。 ...

後端工程師用 Golang 在 WSL 中寫 GUI 是不是搞錯了甚麼 - 安裝篇

由於先前將 raspberry pi 4b 給賣掉了,bmx280 中基於 bme280 而產生的 exporter 因此失去戰鬥能力,藉此玩玩 tinygo,透過 serial port 透過 raspberry pi pico 對 bme280 讀取溫溼度。在開發過程中發現,WSL 中,command line 輸入: GOOS=windows go run main.go 這樣會吃 windows 的環境,比如讀 serial port 需要 COM port,這樣就不是去讀 /dev/ttyS4 而是讀 COM4,這 cross compile 也太方便了吧…。 後續在工作上接收了需要寫一個 websocket server/client,而 client 需要: 有圖形化最好 (TUI or GUI) 跑在 windows 桌面上 ,開發過程中再次感受到 cross compile 的方便,有點慶幸是在這個一個方便的時代學習敲鍵盤(? Requirement Golang 1.16+ () Docker or Podman 在 WSL 中建立 X Window System 環境 因為我的 Golang 環境是基於 WSL,於是我需要先準備在 WSL 中能跑的 GUI 環境。 在 Unix like 使用的 GUI 被稱之為 X Window System 或 X11 或 X,以所需的情形來說即是需要在 Windows 中啟動 X server,來與 WSL 中的 X client 連線。 ...

解決 VM 關機時等待容器關閉

[ *] A stop job is running for libcontainer container xxxxxxxx (10s / 1m30s)_ 過去 kubernetes 還跟 docker-shim 手牽手時,在關閉 k8s node vm 時常常出現等待 docker-shim 關閉,直到一分三十秒被 time out 才正確關機。若是開發機就當作去尿尿的時間就好,但若是重要的環境停機備份,或是斷電時靠 UPS 提供電源等待系統關機,那浪費時間就不好了。 這次在 home lab 中採取省電措施,不用 1 master + 1 node 的組合,直接使用 k3s 作為家用 kubernetes 的實驗環境。但依然在關機時會需要等待 containerd-shim 等等被 time out kill 才會完成關機。 若是沒有做特別的設定,或是沒有過分的 stateful pod,找到了 k3s issue #2400 中的解決方法 Stopping K3s To allow high availability during upgrades, the K3s containers continue running when the K3s service is stopped. ...

2023 展望

TL;DR 今年還沒躺平。 你不是喜歡寫程式的人,是用程式吃飯的。 年前 CEO 這麼對我說,後面接著一段話: 像我跟他(指主管)是喜歡寫程式的,沒人打擾的話我們可以在家一直玩這些。 跟主管借了《Clean Architecture》來看,每次在看軟體「工程」的書時,都備感挫折。《程式設計師的自我修養-連結、載入、程式庫》 中提到的編譯器、連結器,我壓根就沒學過,這種滿滿的挫折感,在 Clean Architecture 中得到了解答。 台灣的資訊系在國外的最正統名稱是 Computer Science a.k.a. C.S.,而我的學士學位是資訊管理 Department of Information Management,我們接受的教育是怎麼去快速理解 domain,並在運用該領域的領域知識開發輔助用的資訊系統,課程著重在 ERP、CRM、KMS 等等資訊管理系統(MIS)。作業系統課程不會教你減少分支預測帶來的好處,資料庫管理課程不會教 Lock Level 把整張表鎖起來會被罵,資料結構課程不會教你怎麼用程式實作 linked list、tree,程式設計課程更不會去看你的時間/空間複雜度。 或許也只能怪自己在念書時得過且過,讓現在的自己需要花時間去補其他人早就知道的知識。 似乎也是因為這種挫折感給了自己莫大的動力,不想輸給「本科系」的學生,雖然已經 25 歲了,但及早發現及早治療吧?過去總是喜歡把不理解的部分都弄懂才往下一步走,也是慢慢地改變自己且戰且走、以戰養戰。 舉例來說,如果要把整個公司專案的程式碼、技術債的原因、神秘數字的由來、歷史共業等等,全部都摸熟才能開始寫 code,那可能就會失去許多成長的機會。 工作不像在學校,不會要求你每次都要一百分,應該是先做出 60 分,甚至 40 分,再慢慢迭代成 100 分。 CEO 如此說著,也符合軟體開發流程迭代機制,先拿 prototype 去撈錢再來修(?)。 除了有些設計原則是需要最初就先講好比較好(e.g. Cloud Native, API First),似乎沒有甚麼是「非這麼做不可」,更多的是「不要這麼做比較好」。 言歸正傳,對 2023 年的展望呢,希望身體健康,也希望能拉近與同儕間的距離,多少不想輸給碩畢的同學XD。