[Chrome extension] 新北市/台北市圖書館 – 多重帳戶登入
最近迷上了寫 Google Chrome extension,也就是擴充功能…
因為發現它實在蠻容易寫的,也很容易上手~~
這次想要解決的問題是關於新北市圖書館多重登入的問題~
因為家人每個人都有一張借書證,因此通常我們就會各自拿別人的去用,
這樣就可以一次借很多本書回來一起看…
只是新北市圖書館的網頁上,並沒有辦法支援多個帳號登入,
因此如果想要看看家人是否有哪幾本書快到期了,或是是否有通閱和預約的書到館的話,
就必須一一登入每個人的帳號,然後才能檢視,
其實是蠻不方便的…
因此,這次的想法就是做一個 chrome extension,
當按下這個 extension 的時候,就會自動登入所有家人的帳號,
將相關的借書、預約、通閱等等狀態全部一次取回來顯示~~
當然這個東西直接作成一個網頁 .html 也是可以的,
不過作成 chrome extension 有兩個好處:
1. Google 會自動雲端同步有安裝的 chrome extensions,因此每台電腦都會裝上。
2. Chrome extension 可以有選項頁,這樣可以更方便的選擇一些選項(像是加帳號等等)。
這次就不太多提上次已經提過的,製作 chrome extension 的一些基本概念,
只提一些較重要的部分了~~
Manifest.json
這次的 manifest.json 裡面,我們並沒有用到 background_page,
因為我們只需要在按下按鈕時,直接顯示一個頁面就好,
就不需要一個背景頁面在那邊佔 chrome 的資源了~
{ "name": "新北市圖書館 - 多重帳戶登入", "version": "1.2", "description": "如果你的家庭裡有多張新北市圖書館證時,本程式可以幫助你登入所有的帳戶,一次檢視全部的借書狀況。", "icons": { "16": "icon16.png", "48": "icon48.png", "128": "icon128.png" }, "options_page": "options.html", "browser_action": { "default_icon" : "icon128.png", "default_title" : "新北市圖書館 - 多重帳戶登入", "default_popup" : "baloon.html" }, "permissions": [ "http://library.tphcc.gov.tw/*" ] }
baloon.html
正常來說,chrome 會把 default_popup 指向的網頁顯示在它的一個氣泡框裡面,
不過因為這個氣泡框只要點一下就會消失,
對於需要檢視各帳號借書狀態的我來說,覺得不太方便,
因此這邊的實作方式是開一個新的分頁 popup.html,
然後就直接用 window.close() 把不必要的氣泡窗關了~
<html> <head> <script> chrome.tabs.create({ url: "popup.html" }); window.close(); </script> </head> <body> </body> </html>
popup.html
基本上這個網頁的架構很簡單,就是登入帳號 -> 查詢借書狀況 -> 查詢通閱狀況 -> 查詢xxx …
如果有多個帳號的話,就重覆上面的步驟~
最後,再把查詢完的結果整合起來顯示就可以了~~
不過,在實作的時候,發現如果用同步 (sync) 的方式來做登入與查詢的動作,
整個網頁在查詢完成之前是無法回應的,
這在有多個帳號的時候問題更明顯,實在不是很好,
一般人可能會以為網頁當掉了,然後再按一次重新整理 =_=…
因此,後來對網頁作了大翻修,全部改用非同步 (async) 的方式作登入與查詢,
不過僅限於同一帳號而言才能這麼做,
只有等到同一帳號的借書、通閱、預約狀態等等都查詢完了,
才能去登入下一個帳號,
不然 server 那邊的 session 是會阻止我們直接用帳號 A 的 session 去查帳號 B 的資訊的!!
下面這段程式,簡而言之,就是將所支援的每個服務(借書、通閱等等),
都顯示在一個 jQuery tab 分頁裡面,每個分頁裡面都是空的,
接著就執行 jsLoginAccount(0) 開始登入第一個帳號~
function jsOnload() { if (g_arrayAccounts != null && g_arrayAccounts.length > 0) { // Initialize tab html $("#divResult").html('<div id="divResultTabCollection"><ul id="ulTabLinks"></ul></div>'); for (var iService = 0; iService < g_arrayServices.length; iService++) { // Check if this service is enabled if (g_arrayServices[iService].enable != false) { $("#ulTabLinks").append("<li><a href='#divResultTab" + g_arrayServices[iService].output + "'>" + g_arrayServices[iService].tab + "</a></li>"); $("#divResultTabCollection").append("<div id='divResultTab" + g_arrayServices[iService].output + "'><div class='classLoading'><img src='ajax-loader.gif'> 正在查詢相關資訊,請稍候...</div></div>"); } } // Show result tabs $("#divResultTabCollection").tabs(); // Login first account jsLoginAccount(0); } }
下面這段程式主要就是先看看是否所有的帳號都已登入過,
如果還沒有的話就進去執行,
首先是去呼叫登入的 URL,如果登入成功了,
就會用非同步的方式,同時用 jsQueryService() 去查詢所有的服務狀態(借書、通閱、預約等等),
每回來一筆服務結果,就會用 jsAppendQueriedServiceInfo() 將結果加到 jQuery 分頁上,
同時也呼叫 jsIncQueriedServiceCount() 去累計目前已經完成查詢的服務數目。
當所有的服務結果都回來之後,就再呼叫 jsLoginAccount() 去登入下一個帳號,
直到所有的帳號都處理完成為止~~
function jsLoginAccount(iAccount) { // Check if this account index is valid if (iAccount < g_arrayAccounts.length) { // Check if this account is enabled if (jsIsAccountEnable(iAccount)) { g_bAnyAccountEnable = true; jQuery.ajax({ url: g_sCGIURL, type: "POST", data: { "PG_NAME": "BRW", "UMODE": "FIRST", "ULG": "CHI", "UCODE": "BIG5", "BRWID": g_arrayAccounts[iAccount].name, "BRWPWD": g_arrayAccounts[iAccount].pass }, async: true, success: function(html) { if (html.indexOf("<hr ") >= 0) { // After login, the first page is the currently borrowed books, // so we can save this into array first. jsAppendQueriedServiceInfo(0, html); g_nNumQueriedServices = 1; // Search for all CGI links g_arrayCGILinks = html.match(/<a href="/cgi-bin/spydus.+">/gi); if (g_arrayCGILinks != null) { // Query every listed service info in async mode at the same time for (var iService = 1; iService < g_arrayServices.length; iService++) { // Check if the service link index is valid if (g_arrayServices[iService].index >= 0 && g_arrayServices[iService].index < g_arrayCGILinks.length && g_arrayServices[iService].enable != false) { // Query the service jsQueryService(g_sWebRoot + g_arrayCGILinks[g_arrayServices[iService].index].replace(/<a href="(.+)">/gi, "$1"), iService, iAccount); } else { // Does not query this service, but still accumulate queried service count jsIncQueriedServiceCount(iAccount); } } } } else { alert("無法成功登入帳號 " + g_arrayAccounts[iAccount].name + (g_arrayAccounts[iAccount].desc != "" ? "("+g_arrayAccounts[iAccount].desc+")" : "") + "!n請檢查一下帳號密碼是不是輸入正確喔!"); // Login failed. Login next account jsLoginAccount(iAccount+1); } }, error: function(jqXHR, textStatus, errorThrown) { // Login failed. Login next account jsLoginAccount(iAccount+1); } }); } else { // This account is not enabled. Continue login next account jsLoginAccount(iAccount+1); } } else if (!g_bAnyAccountEnable) { $("#divResult").html("您尚未輸入或啟用任何的帳號!<br>請到<a href='options.html' target='_blank'>選項頁</a>輸入至少一個圖書館的帳號,謝謝!"); } else { // Hide the loading div after all data is loaded $(".classLoading").hide(); } } function jsIsAccountEnable(iAccount) { return (g_arrayAccounts[iAccount].enable != false); } function jsAppendQueriedServiceInfo(iService, sHtml) { // Extract html var iPos = sHtml.indexOf("<hr "); if (iPos >= 0) { sHtml = sHtml.substr(iPos); } // Replace links of library to absolute links sHtml = sHtml.replace(/"(/cgi-bin/.+)"/gi, '"' + g_sWebRoot + '$1"'); // Add the output to tab $("#divResultTab" + g_arrayServices[iService].output).append(sHtml); } function jsQueryService(sURL, iService, iAccount) { // Query the link to get output jQuery.ajax({ url: sURL, type: "GET", async: true, success: function(html) { // Append queried service info for this account for this service jsAppendQueriedServiceInfo(iService, html); }, complete: function(jqXHR, textStatus) { jsIncQueriedServiceCount(iAccount); } }); } function jsIncQueriedServiceCount(iAccount) { // Check if all services for this account are queried if (++g_nNumQueriedServices >= g_arrayServices.length) { // Login next account setTimeout("jsLoginAccount(" + (iAccount+1) + ")", 0); } }
有興趣的人,可以到這裡下載回去試用看看喔~
也歡迎給我任何的意見或建議~ ^^
3 thoughts on “[Chrome extension] 新北市/台北市圖書館 – 多重帳戶登入”
請問帳戶是否限定輸入的借書證數量~~日前輸入8張借書證後只顯示7張借書證的資料??
版主回覆:(05/02/2013 03:55:44 PM)
沒有限制耶,有可能是 bug…
最近有空再來找找看,真抱歉 =_=…
希望可以出付費版去廣告
謝謝您的支持,
但目前暫時還沒有打算出付費版…
因為付費版的話,
使用者對 app 的 bug 忍受力會降低。
像我只是業餘偶爾改善一下 app,
可能對於付費版的使用者,
會比較不好交待… 😛