自己組一套個人搜尋引擎的構想

最近意識到:

  1. google 搜尋上大部分的中文結果都很糟,很多內容農場之外,也有很多就是賣東西的,偶爾可以遇到內容比較好的網站通常 SEO 都不好所以會被埋在第二頁後面。
  2. 意外發現,其實有時候在 google 搜尋框裡面加上 site:tw ,只搜尋網域是 .tw 結尾的網站,就可以相當有效地過濾上述那些無用的內容。
  3. 不管是中英文的內容,我傾向還是會從幾個固定的「入口網站」去發現其他內容,比如說 Hacker News, Reddit, 聯合新聞網之類的。也就是說,我所看的大部分內容,都是從幾個固定的網站出發的。
  4. 通常被上述這些入口網站連到的內容都有一些特定屬性,或是有些基本的品質保證。而且我的習慣是到了一個網站會順便看看這個網站上面有什麼其他東西,快速看過之後大概可以判斷這個網站的內容品質。

既然如此,我在想,基於這些特性,或許建造一套自己個人用的搜尋引擎在技術上和算力、儲存空間成本上其實是可行的:

  1. 既然大部分我會看的內容都是從幾個固定的入口網站去發現,那麼我的爬蟲其實只需要從這幾個固定的網站出發就好了。
  2. 因為入口網站的數量不會太多,我其實可以手動為每個網站「評分」。也可以為特定的網域評分,比如說 .tw 評分比較高。
  3. 接下來,應該就可以簡單計算出每一個爬到的頁面的分數,比如說如果有被高分網站連到的網頁就自動增加評分。
  4. 傳統的搜尋引擎頁面評分標準也一樣納入參考但是降低權重。

其實想了一想,整個構想就只是在搜尋引擎評分機制上面手動加上個人偏好而已。

這個搜尋引擎其實也不需要很厲害,因為如果真的找不到想要的結果,去用 google 就好了。

之前有調查過一套開源的搜尋引擎 YaCy ,之後再看看他能不能做到我想的事情。

聯邦式 OAuth 構想

剛剛在架 wallabag ,開源的 Pocket / Instapaper 替代品。

然後突然想到,我架一個這個就只有自己用、自己維護耶,而且又是另外一組帳號密碼。

不知道有沒有辦法設計一套聯邦式的 OAuth 認證機制,不同的組織(網域)可以加入聯邦,所有人使用同一個 OAuth endpoint 但帳號的後綴不同,這樣志願的服務供應者(譬如說我很樂意讓別人一起使用我維護的 Wallabag)就可以直接選用這個 OAuth 認證服務,再選擇要讓哪一些組織的人登入。

這樣的話,既能達到單一帳號的功能(在不同服務間可以使用同一帳號,不用記多組帳號密碼),也不像直接採用 Google OAuth 這種任何人都可以擁有帳號的服務,志願的服務供應者就可以只允許他信任的組織的使用者使用他的服務。

可能有點難理解,舉個例子說明:

姑且把這個中央代理 OAuth 服務叫做 Distauth,接下來有志願的服務供應者 A, B 和組織 X, Y, Z,還有組織 X, Y, Z 的成員甲、乙、丙。

A 因為自己的需求,架了一個 Nextcloud ,他願意分享一些伺服器空間給其他人使用,但是又怕有人濫用。

B 為了要自己作筆記,架了一個 hackmd ,他也願意讓其他人使用他維護的 hackmd 服務。

X 組織是某個資訊社群,他們擁有一個 xxxx.tw 的網域,也有一套自己的帳號系統,要申請 xxxx.tw 的帳號需要經過組織訂定的審查流程,並簽署不濫用的同意書,甲已經通過,因此有 jia@xxxx.tw 這個帳號。

Y 組織是另一個鬆散的社群,他們提供所有成員一個帳號,只要填一個線上表單就可以申請,乙擁有 yee@yyyy.tw 這個帳號。

Z 組織是一間大學,所有的在校生都有帳號,帳號會在畢業之後失效,丙擁有 bing@zzzz.tw 這個帳號。

X, Y, Z 都加入了 Distauth 聯盟。

Distauth 是一個特殊的 OAuth 認證伺服器 (Authorization Server) ,任何組織(只要有一套帳號系統)都可以加入 Distauth , 任何服務供應者、應用程式都可以和 Distauth 註冊,成為 OAuth client (application) ,取得獨特的 App ID 和 App Secret 。

A 因為伺服器空間有限,而且他想要確保來使用的人不會濫用他提供的服務,他認為 X 的審查流程足夠嚴格,Y, Z 則不,所以他在 Distauth 取得 App ID 和 Secret 的時候就設定,只有組織 X 的人可以登入。

如此一來,甲已經擁有了 X 的帳號,所以他可以直接使用 A 提供的 Nextcloud 服務,X 組織未來任何的新成員也都可以直接使用 A 的 Nextcloud ;同時,乙和丙雖然可以成功登入 Distauth ,但 Distauth 不會授權乙丙使用 A 的 Nextcloud 。

B 架設的 hackmd ,因為只有純文字儲存功能,所以佔用資源很少,他認為不需要嚴謹限制使用者,但還是希望是認識的社群的成員才能使用,所以他在 Distauth 設定 X, Y, Z 的成員都可以使用,但其他組織不行。

整個概念大概就是這樣,現在看來好像沒有類似的東西,自認這構想還不錯,不過一樣,要獲得廣泛採用本來就很困難 :-p

計劃太多,徵人(?)

想做的專案太多,時間能力不夠,只好先把想法記下來。更希望可以找到人一起來合作一個專案啦,自己做太容易放棄了。

owncloud-registration

讓 ownCloud/Nextcloud 支援註冊帳號的插件,原本 ownCloud/Nextcloud 只能管理員自己建立帳號然後把帳密交給新使用者。

開發其實很簡單,沒什麼技術難度,知道怎麼接 ownCloud public API (PHP 的 API)和基本的資料庫連接 code 的撰寫能力就可以了。已經很久沒有碰 code,有個 admin-approval 的 branch ,已經拖了兩年多了 :-/ ,要做的功能是管理員審核功能,讓管理員可以審核新註冊的使用者,也沒什麼技術難度,就是 glue code 接一接,所以實在沒什麼動力把它做完。前端部分會用 handlebar.js 去 hook 官方的使用者管理頁,然後去呼叫後端插件內的 HTTP API 。

facebook-not-typing 和 facebook-micromanage

這兩個都在我的 github 帳號底下,facebook-not-typing 應該看了 readme 就知道是幹嘛的。

facebook-micromanage 則是比較有野心的計劃,想要以瀏覽器插件來提供很多 Facebook 不給的功能,現階段已經完成撈朋友清單,接下來利用已經有的基礎建設,也就是撈 cookie 和 localStorage 的 code ,想要突破 Facebook 過濾泡泡,去撈每一個朋友和粉絲專頁的牆,然後存進 IndexedDB (雖然說這已經是 deprecate 的標準,但我真的需要結構化的資料儲存),再依照時間順序顯示出來。現在遇到的問題是撈朋友牆的 request ,分頁的參數不知道怎麼填,有幾個變動的神奇數字還沒有辦法看出產生的方式。

不過或許以後也可以直接開大絕用 phantomjs 撈更快,不過這要跑在瀏覽器插件裡面就比較有困難。不對,開一個隱藏的 content page 應該就可以?

第二個想做的功能是管理朋友清單,可以用交集和聯集產生新的清單,還有朋友清單備份時間點,也就是在每一個朋友清單後面加個時間戳記,最新的則不加戳記,在有變動(譬如說你把人加進那個清單)的時候,加入前的版本會加上戳記(清單重新命名),然後把原本的人加到新的清單,再加入那個新的人,這樣新的人就看不到你以前的貼文。

bsd-cloudinit

  • 弄好 Jenkins… 有夠難 debug 設定,應該接近完成了,等 Github Pull Request Plugin 的那個 bug (在 Firefox 按 Rebuild PR 沒反應)修好應該會比較好 debug,噢,還得再次砍掉 ghprb 。(每次要測試 build 還得去 github PR 下面留言 “retest" 實在有點蠢)
  • 跟上游 cloudbase-init 同步 code (因為他們是一個 framework 了,我們只是加幾個 FreeBSD 專屬的 class 來實作在 FreeBSD 上面的操作)
  • 同步 code 以後,把舊的 code 改寫成符合新架構的形式,然後開始收 PR ,也改成新架構
  • 弄個 cronjob 去檢查 FreeBSD releng 的更新,有更新的時候自動觸發 build

ownCloud Music Koel

從 Koel 幹來的前端,插在 ownCloud Music app 上面,還有很多功能沒有做完:

  • 歌詞,Last.fm,YouTube 整合壞掉了
  • 觸發掃描的按鈕
  • 樂曲長度偵測、顯示
  • 上架 apps.nextcloud.com

中文斷詞加貝式機率過濾垃圾郵件

附中信箱的垃圾郵件自從用了 bogofilter 之後算是蠻少的,不過有時候還是會有一整批的 Spam 抓不到。所以希望可以用結巴斷詞函式庫先把信內容斷一斷然後再進 bogofilter ,當然斷詞之前還有很多麻煩事要做,像是 parse MIME multipart ,幸好發現了個 library 可以解決。

現在是卡在要設計一個有效的 benchmark 方法,測量偵測的準確度。(跟其他專案一樣,就是好像怎麼做都可以,怎麼做都有點問題,沒辦法決定怎麼做,所以先擱置)

筆記會依照相關性記在 CNMC Wiki

要是中文垃圾郵件過濾可以做得好的話希望可以架台 mail server 給認識的人付成本價使用,也可以提供 domain email 代管,help re-decentralize the web

豐原計劃

是個自幹 Google Drive 的計劃,ownCloud 現在還是有很多問題,所以想要重新用 Django 實作,構想都記在 HackMD 裡面了。目前我在弄前端,雖然我跟前端真的沒那麼熟,但 @M157q 更不熟 :-p 所以只好我來弄。週末不定時黑客松。

skicka-fuse

拋棄很久的專案,想要用 skicka (非官方的 Google Drive CLI client,Go 寫的)和 bazil-fuse 重新做一套 Google Drive 的 FUSE, 希望用 Go 會讓一切變得很快,還有計劃要用大量的本地快取增加速度,但快取可以隨時被 free ,類似 ZFS 或 memcached 那樣。

逆向 iCloud Drive

希望可以找到方法 hack ,讓深度整合 Finder 的 iCloud Drive 可以被 hack 成其他 backend ,像是上述的豐原。

裝了 mitmproxy (在 OSX 上面用 pip 裝似乎會爛,放棄了直接裝上游 package),攔截了一些 request ,基本上 iCloud Drive 就是用 CloudKit 實作的,所以得先弄懂 CloudKit 的認證方式。

筆記也在 HackMD

Octowall

某次在 GitHub 亂逛看別人都在幹嘛的時候想到的主意:

//platform.twitter.com/widgets.js

Django 的初始 scaffolding 已經有了,但是埋藏在某個硬碟可能已經損毀的虛擬機器裡面,要繼續的話得設法撈出來。

桌面環境與豐原計劃(GNOME)

希望桌面環境和雲端環境能夠更深度整合,想修改 GNOME apps ,讓它們可以和豐原運作,譬如說 Nautilus 兼雲端檔案瀏覽器,類似 Dropbox Project Infinite 的概念。還有也想改改 Shotwell ,讓它可以做類似 Apple Photos 或 Google Photos 的事情,自動上傳照片,然後可以瀏覽遠端照片,就像在本地。

多虧 lantw ,已經在 Ubuntu 上面弄出 GNOME 的開發環境(這真的是最難的部分,讀懂 Nautilus 的 code 都比這個簡單,大概是因為我用 Ubuntu 的關係,然後官方在不久以前把 Ubuntu 從支援的開發環境中移除了,現在要開發的話,官方支持的就只有 Fedora。但是我不想重新學用 rpm 系的東西啊 :-p )。

第一步就是應該要可以 build 出一個跟 Nautilus 一模一樣但是可以和 Nautilus 獨立運作的應用程式,這樣才能方便開發和使用者測試,否則每次測試我們的東西 Nautilus 就有可能壞掉,多麻煩啊。可能主要是 DBUS 的註冊名稱要改一下之類的,但光是這個就挺麻煩,我跟 DBUS 不熟 :-p

目前擱置中,先做豐原,Web 畢竟還算是我稍微有能力做的事情,桌面環境的 build system 什麼的好複雜啊 @_@

BitTorrent tracker proxy

發現很多環境,像是學術網路,阻擋 BT 的方式多半是用阻擋特定的 port ,UDP tracker 會用的 port ,像是 6969, 1337 。然後 tracker 協定其實支援 TCP, HTTP, HTTPS ,但幾乎所有的知名 tracker 都用 UDP ,而且都用那幾個 port 。

所以想法是,做一個 tracker proxy ,可以在未受阻擋的網路,用 HTTPS tracker 協定和受阻擋的網路內的 client 溝通(計中總不可能 block HTTPS 吧),然後再代理 client 向上游的 tracker 用 UDP 溝通。

這樣有幾個問題,一是計中還是可以擋我們 proxy 的 IP ,但這應該不會那麼快發生,而且我們只是跑普通的 HTTPS 啊,為什麼要擋我們捏?完全杜絕的方法就是用 public cloud, 讓他們一擋就要擋所有服務,不過 Heroku app 沒辦法送 UDP 的樣子,得用其他共用 IP ,又可以送 UDP 的 public cloud。問題二是,這樣使用者每次要新增 torrent 的時候就得手動新增我們的 proxy 到 tracker 清單裡面,很麻煩。這應該可以用在 client 做插件的方式解決,Deluge 是 Python 寫的,也可以用 Python 寫插件,應該不會太難。問題三是代理沒辦法知道要幫使用者代理哪幾個 tracker ,這個解法一是用自訂的協定去溝通,client 端用插件送額外的資訊;解法二是我們就只是 proxy 幾大 tracker ,其他就不管,這樣應該至少可以達到一點點效果吧(其實不算是解法啦…),還可以開個網頁允許使用者自己加入想要 proxy 的上游 tracker 。

本專案還沒有任何 code ,不過我在 trace bittorrent-tracker 的 code 了。

徵人啊

以上專案全部都徵人和我一起做,沒有很懂沒關係,我可以教,不然這些構想真的都沒辦法實現了。

inotify on FUSE

http://sourceforge.net/p/fuse/mailman/message/24625009/

因為最近自己想做 FUSE ,為了加速,希望能夠做到 inotify 的功能。基本上我想做的事情是類似 Google Drive 網頁界面會做的事情,開啟一個目錄的時候先使用本地的快取回應,同時在背景發出 request 向 server 請求新目錄資料,收到請求之後再更新顯示畫面。也就是說在一個資料夾點兩下,會馬上進去並且看到資料夾的內容,這份內容由 cache 提供,同時在背景向 server 發出更新請求,從 server 取回新的結果之後,更新 cache ,並且顯示新的結果。

這東西用網頁做當然很容易,可是如果讓桌面應用程式像是檔案管理員(譬如說 Nautilus )做到這個功能,就必須支援 FUSE 。因為爬了一下文之後發現 Nautilus 裡面這部分的功能應該是用 GIO 實作的,而 GIO 達到檔案系統通知的方法又是依賴 kernel 的 inotify 。

所以要達到的話很自然就是需要讓 FUSE 也能夠支援 inotify 。

我原本以為 inotify 會提供 filesystem module 一個 system call 來通知某個路徑有更新,filesystem module 只要呼叫這個 syscall 就可以了。在 FUSE 的狀況下則是 FUSE 的 kernel filesystem module 會再接收來自 userspace libfuse 的呼叫,然後 FUSE 實作只要呼叫 libfuse 的這個 function 就可以了。

結果發現 inotify 完全不是這樣實作的。

inotify 的實作依賴 VFS ,也就是說,inotify 之所以知道某個物件被動過是因為有其他程式透過 VFS 來修改這個物件,而不是由 VFS 底層的 filesystem module 來通知 inotify 。事實上 VFS 並不提供任何方法讓 filesystem module 通知它物件的更動。

螢幕快照 2015-06-13 下午5.58.16

也就是說,圖中的 FUSE 沒有任何方法可以通知 VFS 某個物件被修改了。VFS 知道物件被修改(VFS 知道就等於 inotify 知道,應該是每個 VFS 的操作都有 inotify 的 hook 之類的)是因為有除了圖中 ls -l 之外其他的 userspace 程式呼叫 VFS ,這時候就會一併 invoke inotify 的 hook ,inotify 進而通知 watcher 。

所以基本上,要達到我想要的功能,這個 userspace 的 FUSE 程式本身要去戳 VFS ,才會觸發 inotify 。

可是這樣顯然非常容易造成 deadlock ,因為 VFS 收到呼叫會再呼叫 FUSE filesystem module ,然後又會呼叫 userspace 的 FUSE 程式,要詳加調查有什麼不會造成 deadlock 的方式……

或是說另一個方式是直接去改 VFS ,讓 VFS 支援由底層的 filesystem module 來 trigger inotify 。這樣可行性不知道如何。

或是說要做到我所說的效果,似乎應該直接 patch Nautilus ,讓 userspace FUSE 程式和 Nautilus 有溝通的機制,某種程度上的整合。

參考資料:

  • 巴西某大學的課程簡報,講 VFS 和一點點 FUSE ,蠻易懂的快速入門:http://www.ic.unicamp.br/~islene/2s2013-mo806/vfs/andre-zhen.pdf

瀏覽器分頁群組、歷史管理與同步

Firefox 覺得 Panorama (Tab Group) 不是個很重要的功能啊⋯⋯他們說很少人用

翻到 Tab Candy 這個計劃,我有一陣子也想要做幾乎一模一樣的東西,只是後來因為 Firefox addon 太難寫所以放棄,他的構想和我根本一模一樣。

要是真的有的話我覺得會是個革命性的功能,分頁管理應該是很多人共同的頭痛⋯⋯

一直覺得現在的瀏覽器並不是針對目前人們的瀏覽行為所設計。

上網很多時候是為了尋找解答,像是解 bug 、找衣服、筆電、螢幕、相機,而且常會同時進行不同主題的搜尋。我記得 IE 的分頁會自動上色,還有 Firefox 的分頁群組功能都部分解決了這個問題。

另一個我覺得很頭痛的點是很難找到以前曾經瀏覽的網頁,因為我通常記不住網頁的標題,只有關鍵字。要是瀏覽歷史會記住我是怎麼打開這個頁面就更好了(我是從哪裏點開這個連結的?)

可惜 Tab Candy 的提案者跑去開公司,不做這個專案了⋯⋯

我是真的很希望有這些功能,但是這些貌似是要直接改 Firefox 核心,就算寫成 addon 形式也要用比較底層的 API 。我不想寫 C++ 啊⋯⋯而且就算是用 Javascript 寫 addon 還是要了解 Firefox 那複雜的架構。

資訊服務社藍圖

資訊服務社是我構想中的一種社團,或是說社群,這篇文章描述這種社團的特性、意義和宗旨。

資訊服務社發想的基礎是一羣朋友合租或買伺服器。一羣人共同擁有伺服器,但是交由其中比較熟悉技術的人來管理,管理員依據社員的需要來架設服務,像是電子郵件、部落格、檔案分享。

起因:

  1. 我的 blog 在 wordpress.com ,但是我想要看 HTTPd access log ,想要 block 某些 IP
  2. 我想要分享大量的照片原檔給朋友,而且不想把檔案給任何一家公司

像上面這2個 case ,最適合的就是自己架伺服器了。

如果每個有類似需求的人都要自己架伺服器,那豈不是很麻煩,而且又不是每個人家裏都有 100M/100M 的寬頻。

如果把這些人聚集起來,合資買/租伺服器、大寬頻,每個人花的錢和心力減低很多,又可以達到比較好的效果,因爲某些服務會有羣聚效應,例如 mail server 的使用者越多,就有越多人幫忙分類垃圾郵件,垃圾郵件分類會更準。

有點像學校的資訊社,但是學校資訊社的資源來自學校,因此無法拿來做個人用途或營利用途;社員也限定是學生,畢業後就無法再使用。

學校資訊社的限制,讓我覺得爲了要完全自由,東西都得要自己買,機器、頻寬、domain 等等,自己出錢的沒人能管。

社員的組成是互相認識的朋友,或至少要是管理員都認識的人。在傳統的大型服務,如 wordpress.com 上面,使用者數量很多,而且使用服務只要線上申請即可,因此管理員無法非常信任使用者,給他們很大的權限,像是看 log, 改 CSS 、安裝佈景主題;對於 wordpress.com 的付費使用者,也只能提供統一的服務,難以客製化,例如安裝各個使用者所想要的佈景主題。在資訊服務社,大家都認識,新社員必須要經過引薦和同意才能加入,管理員可以更信任使用者,可以開給他們更大的權限、給予更好的協助。

比起一個人架起所有的服務,電子郵件、DNS、部落格,卻又只有一個人用,由少數人維運多數人使用可以達到接近一個人使用的自由度,降低個人所需付出的心力,同時又可以享受一定程度的羣聚效應產生的好處,如分析 SPAM 越多人用就越準確。

比起把郵件放在你不認識(甚至不信任)的 Gmail ,放在資訊服務社的郵件至少是在信任的人的手中,因此資訊服務社同時可以降低網路上的資料集中在 Google, Facebook 等大企業的情形。管理者和使用者之間沒有利益關係,而是合作社的互惠關係。

這樣的社團類似學生網管組織,但社員的身份更不受限制,只要是認識的、社員同意的,都可以加入,提供的服務也不限於個人和非營利用途,社團可以允許個人用途、社員所維運的營利服務利用社團的資源(或許加入某些回饋條件),甚至可能造成爭議的服務如 TOR relay 都可以營運。

伺服器放置點必須要能提供相對應的自由度,像是如果把伺服器放在 AWS,又在上面架檔案分享服務,可能會太貴。像是 DigitalOcean 這種有限流量的虛擬主機又會造成使用者斤斤計較流量。最自由的環境應該是某人的家中,使用大頻寬的網路,由社團支付一部分的網路費、電費。

如果是我,初期我會先:

  • 註冊網域名稱
  • 取得伺服器及網路

剛開始基本的服務最適合:

  • 電子郵件
  • 部落格
  • 工作站 (Shell access)
  • FTP、檔案共享的空間
  • delegate subdomain
  • domain 代管

更進階的服務:

  • 網路電話
  • 虛擬機器
  • Diaspora pod
  • VPN
  • BT 代抓

能夠取得、自己架設的軟體都可以。

資訊服務社的社員比較適合稍微比較懂電腦,有資訊安全觀念、使用者道德的人,才適合提供他們更高自由度的服務,因爲自由越多、限制越少,就越容易被濫用。

社員很有可能需要付費,付越多錢的結果是拿到更好的服務、更大的空間,社團的經費總是會回饋給社員。