不歸錄

程式X鋼琴X雙馬尾

|=(2 影片下載器

| Comments

標題已用 1337 低調處理XD,筆者很喜歡到某站看影片,由於篩選、排序功能需要付費,筆者甚至為此製作了一些工具達到一樣的目的,例如依照收藏次數、評價排序等。不過這次是要分享如何從網站下載一部影片。

瀏覽器下載法

其實有一招不用寫程式就可以下載影片,而且適用在所有影音網站。首先在點選播放影片以前,先把瀏覽器的開發者工具打開,接著點下播放,同時觀看 HTTP 的封包狀況,找到一個下載時間最長的請求,就是影片網址。

如圖所示,影片下載網址是:

1
http://vip.video54000.fc2.com/up/flv/201405/28/b/20140528bpRKSJWR.flv?mid=023358550acbb0cadcf93f50edcfaf5a

大量下載

但如果要大量下載影片的話,瀏覽器這招還是得徒手一個一個把影片點開,這是一件很累的事情,要是有個爬蟲可以幫我做這件事情豈不是很方便嗎?再回顧一下剛剛的網址,可以知道前半段並不難產生,而下載影片的最大重點就在後面的 mid 到底怎麼來。

只是這段 023358550acbb0cadcf93f50edcfaf5a 並沒有在頁面原始碼出現,所以我猜應該是透過網路取得的,幸運的是,沿著影片網址的請求往上找,確實給我找到了一個用來取得網址資訊的請求:

1
http://video.fc2.com/ginfo.php?from=28&otag=0&fversion=MAC%2014%2C0%2C0%2C125&mimi=c5e51ed4de1f4e6246b851bef4a210de&lang=tw&gk=uMuxgWhewb&tk=TlRBeU1qUTNNREE9&href=http%3A%2F%2Fvideo%2Efc2%2Ecom%2Ftw%2Fcontent%2F20140528bpRKSJWR&v=20140528bpRKSJWR&upid=20140528bpRKSJWR

得到的回應:

1
filepath=http://vip.video54000.fc2.com/up/flv/201405/28/b/20140528bpRKSJWR.flv&mid=023358550acbb0cadcf93f50edcfaf5a&sec=71&oref=0&charger=0&charge_second=&err_code=&isadult=0&count=&adreopen=600&cm=1&payment=0&mb_id=60283252&chk_ns=60_256&ci=&play_min=1&play_query=i:0;c:5;f:28;o:0;p:0;u:20140528bpRKSJWR;m:60283252;l:11&test=&ad=1

其中我要的東西就在這個回應裡面,只要把 filepathmid 組起來就可以取得影片網址了。

分析變數

眼看就要成功了,接下來只要分析出 /ginfo.php 的變數怎麼製造即可。筆者是用 curl 做測試,發現上述的請求可以簡化,只保留 mimiupid 這兩個變數:

1
2
$ curl "http://video.fc2.com/ginfo.php?mimi=c5e51ed4de1f4e6246b851bef4a210de&upid=20140528bpRKSJWR"
filepath=http://vip.video54000.fc2.com/up/flv/201405/28/b/20140528bpRKSJWR.flv&mid=bd8bf22fae4cba798ae0b028dabc4784&sec=71&oref=1&charger=0&charge_second=&err_code=&isadult=0&count=&adreopen=600&cm=0&payment=0&mb_id=&chk_ns=60_256&title=ブラッシングされたいの?&seek_image=3&play_min=1&play_query=i:0;c:5;f:;o:;p:0;u:20140528bpRKSJWR;m:;l:0&test=&ad=1

但這回用 curl 得到的 mid 不太一樣,且 filepathmid 組起來的網址也無法丟到瀏覽器, 但是直接用 curl 是可以下載的,所以猜測 mid 的產生有用到 User-Agent 去做雜湊,於是筆者實驗性用了自己瀏覽器的 User-Agent 丟進 curl

1
2
$ curl "http://video.fc2.com/ginfo.php?mimi=c5e51ed4de1f4e6246b851bef4a210de&upid=20140528bpRKSJWR" -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36'
filepath=http://vip.video54000.fc2.com/up/flv/201405/28/b/20140528bpRKSJWR.flv&mid=023358550acbb0cadcf93f50edcfaf5a&sec=71&oref=1&charger=0&charge_second=&err_code=&isadult=0&count=&adreopen=600&cm=0&payment=0&mb_id=&chk_ns=60_256&title=ブラッシングされたいの?&seek_image=3&play_min=1&play_query=i:0;c:5;f:;o:;p:0;u:20140528bpRKSJWR;m:;l:0&test=&ad=1

賓果,這下 mid 變數已經一樣了(mid=023358550acbb0cadcf93f50edcfaf5a),所以由此更可以確定,mid 的產生完全只有用到,User-Agent 而已,只要確保下載影片時候送出去的請求,其 User-Agent 保持一致就沒問題,至此可先鬆一口氣。

Hacking

回到剛剛化簡的網址:

1
http://video.fc2.com/ginfo.php?mimi=c5e51ed4de1f4e6246b851bef4a210de&upid=20140528bpRKSJWR

upid 是很好產生的,不過 mimi 並沒有在網站原始碼出現過,且筆者也沒有在任何 HTTP 封包上找到線索。猜測剩下一種可能:這段變數是由 Flash 產生的。然後我翻翻,找到這個:

1
2
3
4
5
6
public static function makeMimiLocal(_arg1:String):String{
  var _local2:String = "dEgEGrrGeegfe";
  var _local3:String = "gGddgPfeaf_gzyr";
  var _local4:String = "e_egeDEgggEfe";
  return (MD5(((_arg1 + "_") + _local3)));
}

看來這就是製造變數「咪咪」的配方了,試寫一下 Ruby 版本:

1
2
3
4
5
6
def make_mimi(movie_id) # ex. 20140528bpRKSJWR
  # local2 = 'dEgEGrrGeegfe'
  local3 = 'gGddgPfeaf_gzyr'
  # local4 = 'e_egeDEgggEfe'
  Digest::MD5.hexdigest movie_id + '_' + local3
end

其中有兩個區域變數不知道要幹嘛,順手註解掉了。如果這段程式正確,那麼輸入 20140528bpRKSJWR 應該會得到一個 c5e51ed4de1f4e6246b851bef4a210de 才對:

1
make_mimi '20140528bpRKSJWR' # => c5e51ed4de1f4e6246b851bef4a210de

做了一個下載器:

1
2
3
4
$ ruby mimi.rb 20140528bpRKSJWR
$ ls
20140528bpRKSJWR.flv mimi.rb
$ open 20140528bpRKSJWR.flv

收工,以後可以不用瀏覽器下載這個網站的影片了XD

臉書打卡集氣棒

| Comments

本棒會在指定 FB 粉絲頁或打卡點,其按讚數量與打卡數總和超過指定數量時,放出慶祝特效。

這是當初為了五倍紅寶石說明會做出來的東西,此外也被用在 I’M Waffle 現烤鬆餅,為了可以重複利用,特此放到了 Github Page,並且改版為可透過網址變數去設定頁面內容。

產生器


進階設定:




Github:https://github.com/5xRuby/FB-checkin

變數說明

變數 預設值 說明
obj_id 5xruby 粉絲頁 ID
font_size 0.5 倒數數字大小
auto_fire false 自動放煙火
btn_size 100 啟動煙火按大小
qr_code_size 600 QRCode 圖片大小
max_count 500 讚、打卡最大值
cycle 1000 更新週期

漫畫下載器

| Comments

Github 傳送門

筆者是個漫畫迷,其中最喜歡拜訪的網站莫過於這家,但因為是網頁,在離線狀態就無法看了,加上最近的 Ruby 課程常放網頁爬蟲程式給學生當練習,於是這個 gem 就誕生了。

安裝

1
$ gem install sfacg

使用

下載海賊王 751 話

1
$ sfacg chapter http://comic.sfacg.com/HTML/OnePiece/751/

下載整部海賊王

1
$ sfacg comic http://comic.sfacg.com/HTML/OnePiece/

Swift Optional Chaining in Ruby

| Comments

上次參加了 Ruby Tuesday #29,由 Ruby 圈的 JoJo,Joseph Ku范范范瑋琪的概念),分享 WWDC 參加心得與 Swift 的簡介。

其中 Swift 的問號用法(Optional Chaining)引起了我的好奇:

1
2
3
4
5
if let johnsStreet = john.residence?.address?.street {
  println("John's street name is \(johnsStreet).")
} else {
  println("Unable to retrieve the address.")
}

身為一個 Rubist,看到問號結尾的方法名想必是不陌生的。依照 Ruby 方法命名的慣例,問號結尾的方法只會回傳 truefalse。但在 Swift 就不太一樣了,john.residence?.address?.street 的意思和 john.residence.address.street 一樣,可是萬一 john.residencenil,後者會出錯。

再看一次上面優雅的寫法,只要印出 Unable to retrieve the address.,我們就知道 john.residence?.address?.street 在 chainging 的時候被其中一個回傳值 nil 斷法,可能是 residence,或是 address

Ruby 也可以嗎?

乍看覺得這好像也可以在魔法 Ruby 中實現,於是我開始了我的實驗:

1
2
3
4
5
6
.
├── lib
│   └── taylor_swift.rb
└── spec
    ├── taylor_swift_spec.rb
    └── spec_helper.rb

先寫測試是好習慣,我希望我的 Ruby 以後可以這樣寫:

1
2
3
4
5
6
7
require 'taylor_swift'
name = 'tonytonyjan'
name.length?            # => 11
name.length?.gcd?(1331) # => 11
name.length?.asdf?      # => nil
name.asdf?              # => nil
name.asdf               # => NoMethodError

變成 Rspec 後:

1
2
3
4
5
6
7
8
9
10
require 'taylor_swift'

describe '"tonytonyjan"' do
  before(:all){ @name = 'tonytonyjan' }
  it('.length?')             { expect(@name.length?).to             eql(11) }
  it('.length?.gcd?(1331)')  { expect(@name.length?.gcd?(1331)).to  eql(11) }
  it('.length?.asdf?(1331)') { expect(@name.length?.asdf?(1331)).to be_nil }
  it('.asdf?')               { expect(@name.asdf?).to               be_nil }
  it('.asdf')                { expect{@name.asdf}.to                raise_error(NoMethodError) }
end

接下來就是 taylor_swift.rb

1
2
3
4
5
6
7
8
9
def method_missing name, *args
  name_to_s = name.to_s
  if name_to_s.end_with?('?')
    method = name_to_s.chop
    respond_to?(method) ? send(method, *args) : nil
  else
    super
  end
end

乍看好像可以 work,讓我們測測看:

1
2
3
4
5
$ rspec
.....

Finished in 0.00393 seconds (files took 0.19131 seconds to load)
5 examples, 0 failures

喔喔!不錯,看起來確實可以運作,可以收工了呢XD(Ruby 真的是很好惡搞的語言)

注意

看起來很酷,但是已經違反了 Ruby 設計問號的初衷,正如上述所提,問號結尾的方法名在 Ruby 的功用就是回傳 truefalse,同樣的慣例還有驚嘆號(bang method),用於會產生副作用的方法。

鑑於此若真要應用在實務上,建議不要用 ?,改用像是 ?? 或是其他符號來代替,但 ?? 其實有點醜陋,應該有更漂亮的符號,因為這不是 Ruby 官方的慣例,所以依照個人喜好而定就好。當然最後也可以自己打一個 Gem 給自己用。但若還是堅持希望用 ? 怎麼辦?

學 Swift XD

噗浪機器人製作

| Comments

回聲蟲示範

以下這段程式碼的功能即是在自己河道上只要聽到有人發新噗,立即回應一模一樣的內容給噗主。

1
2
3
4
5
6
7
8
9
10
11
12
13
require 'tjplurk'

api = Tjplurk::API.new CONSUMER_KEY, CONSUMER_SECRET, TOKEN_KEY, TOKEN_SECRET
api.real_time do |plurk|
  if plurk['type'] == 'new_plurk'
    params = {
      plurk_id: plurk['plurk_id'],
      content: plurk['content_raw'],
      qualifier: ':'
    }
    api.request '/APP/Responses/responseAdd', params
  end
end

且聽筆者逐行解釋:

1
require 'tjplurk'

這是一個最近才出現的 Ruby Gem,被實際應用在一隻叫小兜蟲的噗浪機器人上,是 Plurk API 的包裝,也提供指令式的方式使用(稍後會提到),輸入 gem install tjplurk 即可安裝。

Github:https://github.com/tonytonyjan/tjplurk

文件:https://github.com/tonytonyjan/tjplurk/blob/master/README.zh-TW.md

1
api = Tjplurk::API.new CONSUMER_KEY, CONSUMER_SECRET, TOKEN_KEY, TOKEN_SECRET

初始化,後面四個參數看起來嚇人,但也不至太難取得,請到這裡申請噗浪應用,隨即可以取得 consumer key 與 concumer secret。

至於 token key、token secret,可以透過噗浪的「測試工具」或是 tjplurk 內建的指令取得。

1
2
3
4
5
6
params = {
  plurk_id: plurk['plurk_id'],
  content: plurk['content_raw'],
  qualifier: ':'
}
api.request '/APP/Responses/responseAdd', params

鑑於這行比較簡明,先跳來解釋,Tjjplurk::API#request 會送出一個 POST 請求到噗浪,第一個參數是 API 路徑,第二個則是該 API 需要的參數。

可以參考噗浪官方的 API 文件,以此為例 /APP/Responses/responseAdd 需要三個必填的參數:plurk_idcontentqualifier

1
2
3
api.real_time do |plurk|
...
end

這段是噗浪河道實況的 API 包裝,利用 comet 技巧來實現,回傳的東西會長得像這樣:

1
{"new_offset": 27, "data": [...]}

其中 data 裡面放的是「噗」陣列,也就是 Tjplurk::API#real_time 所迭代的內容。有兩種類型,分別是 new_plurknew_response(格式請見文末附錄,因為噗浪並沒有詳細的官方文件)。

之所以會有 if plurk['type'] == 'new_plurk',是為了避免回聲蟲暴走,見到新的回應也回。

指令

1
2
3
4
5
$ tjplurk help
Commands:
  tjplurk api PATH ["FOO=BAR" ...]           # 發送 API 請求
  tjplurk auth CONSUMER_KEY CONSUMER_SECRET  # 互動的方式取得 Access Token
  tjplurk help [COMMAND]                     # 說明

第一步先用 tjplurk auth 取得授權

1
2
3
4
$ tjplurk auth CONSUMER_KEY CONSUMER_SECRET
Authorize URL: http://www.plurk.com/OAuth/authorize?oauth_token=Reqj6s1zowzn
Enter Verification Number: 405603
Key & secret successfully saved to "/Users/tonytonyjan/.tjplurk".

注意這裡有個檔案叫 .tjplurk 被存在家目錄下,裡面只放了 4 筆資料:CONSUMER_KEYCONSUMER_SECRETTOKEN_KEYTOKEN_SECRET。而 Tjplurk::API.new 如果不傳參數,預設也會去找這個檔案。若有特別指定檔案位置,可以設定環境變數 TJPLURK_FILE

1
$ export TJPLURK_FILE=/path/to/file

接下來就可以盡情的使用了:

1
2
$ tjplurk api /APP/Users/me
$ tjplurk api /APP/Timeline/plurkAdd "content=hello world" qualifier=says

這個指令都會回傳 JSON 格式,需要的話也可以 pipe 到別的工具做使用。例如下面的例子是印出漂亮的 JSON:

1
$ tjplurk api /APP/Users/me | ruby -rjson -e 'jj JSON.parse ARGF.read'

附錄

new_plurk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
  "replurkers": [

  ],
  "responses_seen": 0,
  "qualifier": ":",
  "replurkers_count": 0,
  "replurker_id": null,
  "response_count": 0,
  "anonymous": false,
  "replurkable": false,
  "limited_to": "|7910597||5874158|",
  "id": 1216516571,
  "favorite_count": 0,
  "is_unread": 0,
  "lang": "tr_ch",
  "favorers": [

  ],
  "content_raw": "test",
  "user_id": 5874158,
  "plurk_type": 1,
  "replurked": false,
  "favorite": false,
  "no_comments": 2,
  "content": "test",
  "plurk_id": 1216516571,
  "posted": "Sat, 14 Jun 2014 04:21:29 GMT",
  "type": "new_plurk",
  "owner_id": 5874158
}

new_response

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
{
  "plurk_id": 1216516326,
  "response_count": 1,
  "response": {
    "lang": "tr_ch",
    "content_raw": "TEST",
    "user_id": 5874158,
    "qualifier": ":",
    "plurk_id": 1216516326,
    "content": "TEST",
    "id": 5993521307,
    "posted": "Sat, 14 Jun 2014 04:19:52 GMT"
  },
  "user": {
    "5874158": {
      "verified_account": true,
      "default_lang": "tr_ch",
      "display_name": "大兜:職業學生",
      "uid": 5874158,
      "dateformat": 0,
      "nick_name": "tonytonyjan",
      "has_profile_image": 1,
      "date_of_birth": "Thu, 23 Nov 1989 00:01:00 GMT",
      "karma": 124.39,
      "gender": 1,
      "name_color": "2264D6",
      "recruited": 5,
      "id": 5874158,
      "avatar": 82
    }
  },
  "type": "new_response",
  "plurk": {
    "replurkers": [

    ],
    "responses_seen": 0,
    "qualifier": ":",
    "replurkers_count": 0,
    "replurker_id": "",
    "response_count": 1,
    "replurkable": false,
    "limited_to": "|7910597||5874158|",
    "id": 1216516326,
    "favorite_count": 0,
    "is_unread": 0,
    "lang": "tr_ch",
    "favorers": [

    ],
    "content_raw": "TEST",
    "user_id": 5874158,
    "plurk_type": 1,
    "replurked": false,
    "favorite": false,
    "no_comments": 2,
    "content": "TEST",
    "plurk_id": 1216516326,
    "posted": "Sat, 14 Jun 2014 04:19:21 GMT",
    "owner_id": 5874158
  }
}

五倍的祝福,五倍紅寶石

| Comments

http://5xruby.tw

莫名其妙地,第二間公司就這樣開張了。

三年,從 Movimpact(已停止運作)、腦袋有動工作室一路到五倍紅寶石,有趣的是這些我有參與創辦過程的單位,其名字湊巧都是我想的,偶爾我也懷疑到底是我體貼的隊友想讓我開心的,抑或我說不定是個命名的天才?(欸

余憶童稚時

記得大三時為了吃飯,本來可有很多選擇的,諸如餐廳打工、國高中家教或是系上助教。但因為人在新竹,沒車等於斷腿,斷腿又要常常出校門跑餐廳、兼家教其實頗折磨(要嘛找專屬工具人,否則也要買雙好鞋,但當時找人屌短,買鞋人又懶,最後是放棄了)。何況幸福城市夜路不佳,弄個不好說不定本來沒斷的腿,後來就斷了。

從桌面到網站

那時做了第一個關鍵的決定,就是考慮用本行來賺,於是開始試著使用 Java 在 PTT 上面找東西來做,小到作業、遊戲外掛,大至桌面工具程式。只是這年頭外包的東西還是以網站、手機應用居多,桌面應用寥寥無幾,有鑒於筆者拿的是傳統手機,所以把矛頭指到網站開發上,一切看似正確,卻因為 Java 寫網站的開發速度還是太慢,且收入不如預期(是筆者太弱了),這般做罷了。

從 Java 到 PHP

後來有幸透過學長介紹,得到一份 PHP 的案子來做,這也是筆者與 PHP 的第一次邂逅,那時不可思議的花了一週的時間去學,再花一週的時間看 Wordpress 原始碼就上場了,且勉強的在不被學校當掉的情況下撐了一個月,最後終於成功的違約(果然沒有什麼東西是可以速成的)。

於是第一次邂逅變成了最後一次。

從 Java 到 Ruby

至於筆者最後為什麼選擇了 Ruby?其實寫了 Java 快 4 年的時間,曾經陷入其可跨平台、有豐富函示庫與應用的迷湯之中,認為自己可以用 Java 超越任何事物,然後看到一本書就叫「超越 Java」。

如果各位對這本書有印象, 他的書名掛名 Java,實則偷塞 Ruby,筆者就這樣上當了,例如序的開頭長這樣:

Java 已經存在超過十年了,這段時間,它的成就非凡,它徹底改變我們寫軟體的作法和想法。但是 Java 已顯老態,該是時候了,我們得想想未來接班人是誰。

Bruce Tate

這本書很不錯的,作者 Bruce 寫過「輕快 Java」,以前有翻過。我從被這樣的序給吸引住,到最後合上書頁後的第一個念頭:「不妨給 Ruby 一個嘗試吧?」

Ruby 好快,也好快樂

還記得那時筆者從 C 跳到了 Java,從此有了更多喝茶的時間,這幾年開始寫 Ruby,筆者已經有時間種茶葉了。

邪神有云:「天下武功,無堅不破,唯快不破」,但論效能之快大概也沒語言快過 C 與組語了,可是 Ruby 之快不在此面,而在其彈性與簡潔,適合用於 meta programming 和 DSL。動態編程有效的縮短了開發的時間。如果要給 Ruby 一個評價,那我認為 Ruby 大概就是個魔法的語言吧(其實是容易惡搞的意思)!

Ruby 社群

因為同學們學的東西比較硬派,C/C++、Java 和 Python,我雖然也想推廣 Ruby,但在校園中沒有遇到任何一位同好。所以那時經常新竹臺北兩地跑,為的就是可以認識更多相同興趣的人。

果然就在社群之中,交到了很多很棒的朋友,甚至為了要推廣 Ruby 教育,進而與他們一起成立了一家公司,也就是「五倍紅寶石」。

從一開始籌劃、找辦公室場地、師資、合作對象、網站製作等,當我發覺時,公司已成立且說明會下週就要舉辦,一切來得好快,彷彿在做夢一樣。這是頭一次對未來有既興奮又期待的感覺,和當初成立腦袋有動工作室時的心情完全不同。那時只是要開發票而已,但這次是真的有想為這個社會做些什麼。

雖然自己還是有很多不足之處需要學習,希望未來也能有五倍的順利,帶領我們一起度過種種關卡 =)

加油!

報名網址:http://www.accupass.com/go/5xruby
時間:2014/6/5 (星期四) 19:30
地點:TED x Taipei Space (台北市金山南路一段 9 號 4 樓)

你可以接受世界的幾分之幾?

| Comments

「人的心胸有多大」,大概可以用「對世界接受的分量」來衡量吧?

習俗、傳統與道德教育的存在背後多出於好意,但弄個不好可能就變成思想的監獄,難以逃出來。此所以世界如此之大,但有的人只能接受其中的兆分之一甚至更少,並且同時排擠剩下的部分。

這聽起來可笑,但身邊其實處處是例子,如習俗上的無法接受結婚沒有婚禮、無法接受嫁女兒沒有聘金、無法認同小孩進行在家教育;到宗教的反伊斯蘭、排基督;以至性別上的揶揄女裝男、嘲笑第三性等,而同性戀議題與人獸交更是一個經典的例子,族繁不及備載。

然而很多事情並無違背到不侵犯到他人自由的底線,這些人也沒有殺人放火,他們頂多就只是想法與自己的不同罷了。我們真的有必要常常因為世界不照自己的意思走,且時常為此生氣嗎?

其實照著自己想法轉的世界是很無聊的,所有事情都可以預測,且完全不會意外,我們所講的每一句話都會被所有人認同,我們也知道全世界的人的想法應該都跟自己一樣,且自己認為對的永遠就是對的,錯的永遠是錯的,不會聽到一絲反駁之聲。但這樣生活又有何樂趣可言?

有異端的世界才健康啊,正如生態圈要複雜度夠高才會平衡一樣,且異端同時也是相對的,我們認為的異端,反過來他們也認為我們是異端。但若那些討厭的傢伙甚至也都可以反過來接納我們,我們卻還是照樣排擠,如此豈不同時顯得自己心胸狹小嗎?

人都可以有喜好的,做自己也是很開心的一件事,但做自己的同時卻嘲笑做自己的別人就不對了。人各有志不排斥,但自相矛盾不應該。

所以筆者認為,往後當有「我無法接受⋯⋯」的想法時,是否先冷靜一下,想想這事情有誰受到傷害嗎?世界遭到破壞嗎?自己被攻擊嗎?或者只是自己的思維已被國民教育與傳統習俗給綁架罷了?又抑或只是出於一時不理智的刻板印象與情緒?

如果都沒有,那麼讓這個世界多元一點有什麼不好呢?

筆者今日閒聊時提到往後結婚可以接受 Cosplay 取代禮服,可以接受小孩從母姓,希望未來的小孩可選擇在家教育等等,而閒聊對象提到唯一的限制可能是筆者的另外一半不會接受。內心有感
遂成一文。
老實說這種心胸並不容易,筆者並不是一開始就能接受同性戀,以及各種違背習俗的行為與觀念,有過一段掙扎。至於好處,除了平時看事情可能比較不會原地打轉之外,反過來看筆者未來的對象對於決定一些事情時,或許會比其他女性擁有更多的選擇的可能(炸)。

築夢

| Comments

第一站 – 中和

去年有幸得到一個研究所的資格,含淚(喜悅的)離開新竹北上找地方住,第一個就找上中和區一戶八坪的雙人套房,裝潢、傢俱全新,附近有各種賣場、3C 與便利商店,第一眼看到很喜歡一簽就是兩年,且先預付了一年的房租。

屋況不佳

不料幾個月過後發現屋況不太好,除了無對外窗、過於潮濕、會漏水,此外發現左鄰右舍都是情侶,情侶?乍看最後一項似乎沒什麼亮點,不過偏偏這裡的隔音不太好,夜夜笙歌,其實一開始因為可以聽 live 還頗驚奇的,但久了任誰都會覺得難受,且情侶在這裡占多數,會互相袒護(你做一三五,我做二四六),單身的房客根本就是來受罪的(單身錯了嗎?)。

加上半夜大多是我的工作時間,往往出現隔著一面牆,一邊在寫程式,一邊在啪啪啪的情境。打個比方,這就像上班坐在辦公室裏面認真工作,被坐在隔壁的同事啪啪啪干擾一樣,這誰有辦法專心?

第二站 – 出谷遷「橋」

過了六個月,我決定不管違約,就是要搬出去,透過朋友介紹之下找到了現在這間板橋的房子,雖然離市區有點遠,但這次從 8 坪變成了 28 坪,三房一廳二衛一廚一陽,而且租金才多兩千塊,頓時覺得自己之前是被坑的。

雖然這裡傢俱沒有上一站齊全,且房租不含水電、瓦斯與管理費, 但傢俱可以慢慢補,費用也可以負擔,重點是這裡安靜整潔沒人吵,機能完善又近國小(?),附近店家不輸中和、有管理員代收包裹、有社區垃圾場,不用追垃圾車,且之前住的套房帶客人進來一開門就看到床,老實說會亂不好意思的,但這裡有我夢寐以求的大客廳,真的讓人很開心啊!

築夢

這次屋況與坪數讓我打算在這裡居住一陣子,從以前就希望有自己的空間,可自己佈置、升級,剛剛搬進來不到兩週,有種自己終於朝著夢想往邁出了一步的感覺,心情是既興奮又期待,彷彿在玩真人版的「模擬市民」似的。希望今年有機會把所有的傢俱補齊,我得更加努力才行, 加油!

2013 回顧

| Comments

時間 工作 學校 成就
一月 有了自己的筆電,工作效率得到提昇 從交大畢業了 擔任 WebConf 會場志工
二月 成大研究所落榜,怒在成大榜單留隱藏文字 投入了 g0v 的 3du 計畫
三月 與見龍、慕凡前輩互加好友,開始與台灣 Ruby 社群接觸 到台科面試,造成教授困擾 第一次參加 Potluck,煮了拿手雞肉咖哩
四月 參加工研院新訓 第一次 FB 的文章誤打誤撞無論回應、分享或讚數全部破紀錄第一次知道自己的愛情觀可以受到他人讚賞
五月 因為菲律賓把交大某個網站打爆了,我因而得到一份工作XD 北橫自行車兩天一夜破台
六月 開始了咖啡廳工作的習慣 開始在天龍國中和區住下
七月 終於可以不用錯過每一場 Ruby Tuesday 參加了百度黑客松
八月 得知自己上了台科電機 第一次走上街頭,萬人送仲丘
九月 創業了,名叫「腦袋有動工作室」 開始台科研究所生活,修了三門課,不過都待在鋼琴社,沒有找教授
十月 找到了會計師,開始學著怎麼處理發票、計帳、報價單 終於無法同時負荷學業與事業,退掉所有課程,策略改變,決定念四年然後成功退學
十一月 事情越來越多 Yahoo Hack Day 冠軍、第一次上廣播電台:科技 98
十二月 離開工研院 與母親通話,一句「你做得很不錯了!」,淚腺潰堤之餘,2013 宣告破台

2014 願望

這年會碰到我的 25 歲生日,看了一下 20 歲立下得清單(筆者的生涯規劃是五年一個單位):

  • 有持家能力
  • 上研究所
  • 出書
  • 帶全家出國玩
  • 投稿,並且錄用至少一個 conference

眼看剩下一年不到得時間,看來「出書」大概是達不到了,不過筆者倒不小心把 30 歲的目標給解了(創業)XD,出書我看也只能移到 30 歲。除此之外剩下「出國」和「投稿」,這兩點還算有自信。

只好再加把勁了XD

TJStamp 印章產生器

| Comments

因為工作上需要用到某個能夠產生印章的功能,我在台大的學生活動中心花了一個下午完成了這個小工具,可以支援 1 ~ 4 個字的印章。