2008-09-24

Bug Fixed! 文章和回應連結錯亂的問題

我們知道 Blogger 的系統一直有在調整,不管是解 Bug、還是新增功能,原則上都是一直往好的方向前進。不過系統一調整,對 Blogger 的 Hack 來說都是一種挑戰,如果 Hack 的 Code 沒寫好,系統調整完某些功能就會開始不正常。從官方開發者的 Blogger Developer Network 的部落格新聞看來,系統最近調整的重點是 Feed (Atom or RSS) 的資料擴充和標準化,基本上應該是「無痛」的擴充才是,結果調整完我一堆透過 Feed 抓取資料內容當作模組的功能開始不正常,主要的現象是:連結的網址不正確了,跑去查了一下 Code、又翻了 Google Data API 的 Spec,都看不出有什麼異狀,後來 Search 了半天,總算找到原因,而且也找到了解決的辦法。

稍微解釋一下問題點好了(不會寫程式的這段可以跳過)。我有很多 Hack,都是透過 JSON、去抓取 Feed 的資料內容,然後再一個一個 Parse 到我需要的變數裡,串成我要的東西。在「網址連結」(link) 這個資料結構裡,基本上不是只有一個連結,而是一個陣列,之前這個陣列裡都只有一個元素,就是文章的網址,因此我在寫 Code 的時候沒想太多,當我需要文章網址的時候,就直接呼叫 link[0].href。問題來了,這次系統調整完,這個陣列裡變成不只一筆資料啊,而且關鍵是,原來我要的網址資料,被移到陣列的「最後一筆」去了,link[0] 不但不是我要的,這「最後一筆」還不知道會是那一筆哩(Comment 是 link[2] 、Post 是 link[4])~就算我又 Hard-code 特定一筆,根據這篇 Blogger Data API 討論區的這篇文章,負責開發的 RD 還說,「資料順序並不是規格裡有硬性規定的」,所以就算報 Bug 給官方要求修改,一則不知道什麼時候會改回來(或是改成怎樣),二則還不一定會被接受,所以 Hard-code 不是解決問題的辦法,看來還是要想其他方式解決。後來我查了我自己的所有模組,ㄟ?還是有模組不受此調整影響的耶!查了一下內容,喔~雖然「順序」會變,但文章網址的「屬性」不會變啊!從這篇文章提到 Feed 元素的資料結構得知,每個 link 元件有很多個屬性,像是 href、rel 和 type,一般我們取用的都是 href,而文章網址有一個確定屬性,就是 rel = "alternate" (至於為什麼,請查 W3C 的文件)。知道這個條件問題就好解決啦!只要我們找出 link 這個陣列裡如果 rel 的值是 alternate 的話,那筆 link 的 href 就是我們要的啦!

根據以上的發現,要做的調整也很簡單,多三行判斷檢查就行了。原先的程式大多像是這樣(以「最新文章」模組的程式為例):

var link = Post.link[0].href;

我修改後多了檢查,確定是原文網址才可以:

var j = 0;
while (j < Post.link.length && Post.link[j].rel != "alternate")
  j++;
var link = Post.link[j].href;

再舉個例子好了(因為用「最新回應」這個模組的人看來最多),原先程式那一行是這樣的:

var link = Comment.link[0].href;

依照以上的原則修改後,變成:

var j = 0;
while (j < Comment.link.length && Comment.link[j].rel != "alternate")
  j++;
var link = Comment.link[j].href;

最小修改、只多三行(含一個 while 迴圈檢查),這樣就能確定網址是對的啦~即便哪天 Blogger 又調整了 link 這個陣列裡資料的順序,也不會再影響到 Hack 的運作了。

在找問題翻規格的過程中,我發現搞 Hack 的王道,是直接用 Blogger Data API 裡的 Javascript Client Library,只要 include 該 library 的網址,就可以用 Google 自訂的方法來取得 Feed 資料,像是如果要抓標題,不需要什麼 title.$t,直接呼叫 getTitle() 就行啦(函式規格文件在這邊),當然,這個 API 會不會調整也很難講啦,但我想至少 Google 會兼顧這些 API 的正確性吧,閒來無事的話再玩玩看好了~

以下整理這個問題會牽扯到我的相關 Blogger Hack 連結,如果你也有用過以下的玩意,記得順手修正一下,才不會不正常。原文的程式碼我都修改過了,如果看得懂以上原理,建議可以自己動手改改看,而局部修改的原則就是先找「我的原始碼裡」 var j = 0; 這一行開始,把後面幾行蓋掉「你程式碼裡」像是 xxx.link[0].href 的那一行,如果懶得找的就直接重貼一次程式碼也行。

結合發表文章的日曆模組 (Feed Calendar)
「最新回應」模組 (Recent Comments)
首頁即時可展開的留言回應 (Comment Toggling) (這個沒有 Source Code,請自行查看我的網頁原始碼)
最新文章模組「終極版」
最新文章的加強版:其他的最新文章 (Other Recent Posts)
應用 JSON 實現「最新文章」、「最新回應」和「Blog 聯播」

除了以上模組,如果發現有修正無效、引發其他狀況的 Hack,也歡迎回報。

註:像是和「回應」有相關的 Hack,有人刻意拿掉我像是 .replace("#c", "#comment-") 這個部份,之所以這樣寫當然是有原因的!因為 Blogger 的 comment feed 裡的 link 值一直有問題,明明是某個人的回應連結,文章網址後面接的應該是網址加上該人留言的錨點 (就是 # 後面那個 ID),Blogger 的格式是 #comment-ID,可是連結卻總誤植為 #cID,所以我才「好心」把它取代成正確的,如果哪天 Blogger 找到這個 Bug 並且修好的話,才有必要拿掉(當然不改也行,還是會連結到正確文章,只是不會自動跳到留言者的那個留言,要自己翻...)。看來,我應該也去和官方「反應」一下,難道都沒有人發現有問題嗎?

註 2:以上修正 commment- 的問題經 LVCHEN 提醒後發現是舊樣板才有的問題,我調整過了,看來新的樣板都是以 #cID 作為連結,因此「預設」應該是不用去修正,我也把它從程式碼裡拿掉了。

回應: 15