[Scala] 九十六行的簡易噗浪備份工具。

上面一樣,將微網誌上的訊息匯整成一個網頁,方便尋找。

雖然網路上已經有許多現成的噗浪備份工具,但不知道為什麼,我就是沒辦法成功備份我所有的噗文……所以,那就自己寫一個吧!

這個備份工具是用昨天發佈的 SPlurk 寫成的,與其他的備份工具相比,非常陽春,甚至可以說是沒有任何功能,但他至少可以完全備份完我河道上的噗文就是了。

使用說明

  1. 下載 PlurkBackup.zip
  2. 安裝 Java Runtime
  3. 解壓縮 PlurkBackup.zip
  4. 執行 run.bat,接著會看到像右邊一樣的視窗
  5. 輸入帳號密碼就會開始備份,備份完以後會出現 allBackups.html 和 myPlurks.html 兩個檔案,分別是河道上全部的噗和只有自己的噗

程式碼說明

以下就是這次噗浪備份工具的程式碼,總共只有 96 行。:)

重點說明如下:

  • 66 行定義的 fetchPlurks 遞迴取得所有的噗--如果這次取回來的噗文列表不是空的,就繼續從最後一則噗文的時間點再往後抓舊的噗文,直到沒有噗文為止。
  • 在 83 行的時候用上述的函式,並將時間設定成執行程式的時間--那他就會從最新的噗抓到最舊的噗,也就是說,會抓回來使用者河道上所有的噗文(包括自己和其他人的)
  • 86 行會將 83 行抓回來的噗依時間先後排序。
  • 89 行會將 83 行抓回來的噗依時間先後排序,並過慮出使用者自己的噗(噗文的 ownerID = 登入使用者的 userID)
  • 用 50 行定義的 outputHTMLFile 輸出成 HTML 檔案
    • 先輸出 HTML 和表格標頭
    • 將傳入的 List 裡每一則噗文都用 convertToHTML 函式轉成 HTML 格式後輸出
    • 輸出表格和 HTML 結束標籤
  • 收工回家
package org.bone.plurkbackup

import org.bone.splurk._
import org.bone.splurk.constant._
import org.bone.splurk.model._
import java.util.Date
import java.text.SimpleDateFormat

object Main
{
    val apiKey = "wQsqUmmcp69aCblemZ34pM5wywnlAyS9"
    val plurkClient = new PlurkClient(apiKey)
    val dateFormatter = new SimpleDateFormat ("yyyy-MM-dd")
    val timeFormatter = new SimpleDateFormat ("hh:mm:ss")

    var allUsers: Map[Long, PlurkUser] = Map()
    lazy val username = {
        print ("Enter your Plurk username:")
        Console.readLine()
    }
    lazy val password = {
        print ("Enter your Plurk password:")
        Console.readLine()
    }

    // 將噗文轉成 HTML 格式
    def convertToHTML (plurk: Plurk) = {

        val userInfo = allUsers(plurk.ownerID)
        val dateWithLink = <a href={plurk.plurkURL}>{dateFormatter.format(plurk.posted)}</a>
        val time = timeFormatter.format(plurk.posted)
        val userURL = "http://plurk.com/" + userInfo.nickName
        val username = userInfo.displayName.getOrElse(userInfo.fullName.getOrElse(userInfo.nickName))
        val userLink = <a href={userURL}>{username}</a>
        val qualifier = plurk.qualifierTranslated.getOrElse(plurk.qualifier.text)
        val content = plurk.content;

        """
        |<tr>
        |    <td>%s</td>
        |    <td>%s</td>
        |    <td>%s</td>
        |    <td>%s</td>
        |    <td>%s</td>
        |</tr>
        """.stripMargin.format(dateWithLink, time, userLink, qualifier, content)
    }

    // 輸出成檔案
    def outputHTMLFile (filename: String, plurks: List[Plurk])
    {
        import java.io._
        val printWriter = new PrintWriter(new File(filename), "utf-8")

        printWriter.println("<html>")
        printWriter.println("<body>")
        printWriter.println("<table border=\"1\" cellpadding=\"3\">")
        printWriter.println(plurks.map(convertToHTML).mkString)
        printWriter.println("</table>")
        printWriter.println("</body>")
        printWriter.println("</html>")
        printWriter.close()
    }

    // 遞迴取得河道上所有的噗文
    def fetchPlurks (dateBound: Date, filter: Option[PlurkFilter.PlurkFilter] = None): List[Plurk] = {
        val (users, plurks) = plurkClient.Timeline.getPlurks (limit = 30,
                                                              olderThan = Some(dateBound), 
                                                              filter = filter)
        allUsers = allUsers ++ users

        plurks match {
            case Nil => Nil
            case xs: List[_] =>
                println ("Chunk:" + xs.length)
                xs.foreach {x => println ("Processing plurkID %d..." format(x.plurkID)) }
                fetchPlurks(xs.last.posted, filter) ++ xs
        }
    }

    def main (args: Array[String]) {
        val profile   = plurkClient.Users.login (username, password)
        val allPlurks = fetchPlurks (new Date)

        // 河道上所有的噗
        val allPlurksBackup = allPlurks.sortWith(_.posted.getTime > _.posted.getTime)

        // 只有自己的噗
        val myPlurksBackup = allPlurks.sortWith(_.posted.getTime > _.posted.getTime).
                                       filter(_.ownerID == profile.userInfo.userID)

        // 備份啦
        outputHTMLFile ("allPlurks.html", allPlurksBackup)
        outputHTMLFile ("myPlurks.html", myPlurksBackup)
    }
}

回響