Mar 19, 2018

New blog on Github pages

I know I haven't written anything for a long time. But I recently decided to start a new blog using Github pages. Take a look if you're interested: https://hencrice.github.io/

Jul 1, 2013

Repost Google Plus Activities to Facebook with a Python app hosted on GAE (Google App Engine)

A few days ago I found Friend+Me, which is a service that periodically fetches your public posts on G+ and reposts them to other social networks. I immediately signed up for their free plan because Facebook's complicated UI has always been painful to use.

However, the free plan offers only 40 reposts/month so I decided to implement my own version and hosted it on GAE. Since it was the first time I tried out any Google's and Facebook's API, it took me hours to search/go through related documents about GAE, Google Plus API, and Graph API from Facebook. Nevertheless, I still managed to code up a working implementation, check out my G+ profile and FB page (i.e. those posts shared via hencrice_gae). Here's how I've done it:


The whole concept of the program was borrowed from Friend+Me's webpage, only that my implementation is a stripped down, personal-use version of what they offer. That is: (Currently) no repost control with hashtags because all I want to do is merely G+ to FB.


System requirement: Python 2.7 (for deploying your app to GAE). That's it!

1. Go to https://code.google.com/apis/consolecreate a project. Select "Services" tab on the left and turn on Google+ API:


2. Go to "API Access" tab and jot down your "API key" under "Simple API Access" section:

3. (Optional but highly recommended for privacy reason. I'll explain in step 6.) Create an app on Facebook:


4. (Optional) After creating your app, now's the time to set it up. In the "Basic" tab, write down your "App ID", "App Secret" and "Namespace", then fill in these info and click "Save Changes":

5. (Optional) Then go to "Permissions" tab and type in "publish_actions" then save changes:


6. [ CAUTION: I highly recommend creating your own FB app with steps above to obtain another unique set of "App ID" and "App Secret" because I have made mine public (which should never be done) here. Put it simply, if you authorize the one I created to post on your timeline, malicious users might use this app to post ANYTHING they want on your timeline! ]

Now it's time to authorize the app on FB so that it can post to your timeline on your behalf. First, obtain your FB id with the following:

   6. (1) Get your FB username

   6. (2) Go to the following for your FB id:
http://graph.facebook.com/FB_username
After that, if you create your own FB app, go to:
https://www.facebook.com/dialog/oauth?client_id=YOUR_FB_APP_ID&redirect_uri=http://apps.facebook.com/YOUR_FB_APP_NAMESPACE&scope=publish_actions
Otherwise, go to:
https://www.facebook.com/dialog/oauth?client_id=467522106672018&redirect_uri=http://apps.facebook.com/publicgptofbwithgae&scope=publish_actions
 to authorize the app I created for you guys. It will ask to access your public info and the right to post on your behalf. Beware of the CAUTION clause at the beginning of step 6 :


You can choose the sharing option for the FB app here:


You'll land on this page, just ignore and close it:


You can modify the sharing option later in your setting:


7. Get your Google+ profile ID to fetch your public activities. It should be in your address bar and contains numerical values only. For example,
https://plus.google.com/u/0/GOOGLE_PROFILE_ID_HERE/posts


8. Create an app on Google App Engine https://appengine.google.com/:


9. Now comes the interesting part: Coding! Go here to download App Engine SDK for Python. In this tutorial, I'll use the third one labeled as "Linux/Other Platforms" cause Linux is AWESOME!


10. Extract the zip file and change directory into the extracted folder, create a new folder "GplusToFBwithGAE" (or whatever you like):


11. Download my code https://github.com/hencrice/GPlusToFBwithGAE and unzip it into the new folder you created in step 9:

12. Let's start with app.yaml. For more detail, check here:


13. Next, cron.yaml. There's no need to modify this file unless you want to change the polling schedule of your program (Note that when I was testing, this setting already consumed ~24 out of 28 front end instance hours, which is the daily quota for a free app on GAE). Check here for more details on the schedule format:


14. Finally, the most critical part of our GAE app, GplusToFBwithGAE.py. Fill in variables values at the top:


If you want to know more about how it really works, here are some related documentation:
14.(1) https://developers.google.com/+/api/latest/activities/list
14.(2) https://developers.google.com/appengine/docs/python/datastore/entities?hl=it#Retrieving_an_Entity
14.(3) https://developers.google.com/+/api/latest/activities
14. (4) https://developers.facebook.com/docs/reference/api/publishing/
14.(5) http://stackoverflow.com/questions/7827696/http-post-curl-in-python
14.(6) https://developers.facebook.com/docs/reference/api/post/
14.(7) https://developers.facebook.com/docs/opengraph/howtos/publishing-with-app-token/

15. Open terminal and change directory to the folder in step 10 (i.e. google_appengine), type in the following command (might need to replace "GplusToFBwithGAE" with yours) to upload and deploy your app to GAE (check this for more detail):
python appcfg.py update GplusToFBwithGAE/


16. Go to https://appengine.google.com/ to check whether your app hosted on GAE is running. Now you can either click on the small link beside "Running" to perform an initial setup, which merely set the last polling time as current time, or you can wait a 2~3 minutes (depends on your schedule in cron.yaml) for cron service to automatically set it up for you:


17. Testing your app by posting something public on G+ and check whether there's a similar repost on FB:


Yeah~ You made it :)

    Oct 13, 2012

    海軍新訓結束啦!

    6/26下午5點結束我在成大最後一次,最後一科:演算法,的期末考試後,就跟老爸和老媽開車北上回家。在家裡睡了一晚,隔天早上就在板橋車站搭接近10點的入伍"慢速"自強號專車往左營前進了。因為海軍的新訓中心只有一個,所以火車沿途又停靠了幾站把其他縣市的一些役男接上來。

    前幾天的生活真的只能用"忙亂+流汗流到快乾了+被罵到臭頭"來形容,因為我們花了好幾天關在悶熱的建築內不停的填資料,然後領了兩大袋的裝備,再加上新訓中心為了防止感冒大規模傳染,所以規定所有兵都要戴著口罩,在這麼悶熱的情況下,每天流汗應該可以用公升來算了:) 至於被罵的部份,排隊,整隊,走路對腳步,吃飯,洗澡,睡覺沒有一個沒被罵的。

    給海軍新兵的一些提示:
    1. 帶個小筆記本進去吧,差不多是可以放在口袋的大小。先把12個朋友的聯絡資訊,含居住地,手機等等查好寫在上面,進去填資料時會用到。
    2. 也帶個口袋大小的小皮包進去吧!洗澡睡覺都帶著,因為很可能被偷,一旦不見,幾乎都是找不回來的。
    3. 自己隨身的行李不要帶太多,而且行李袋越小越好,因為第一天領裝備會抱一個頗大的水兵袋,若你又拿個要拖的行李箱,會超級難移動的。
    4. 有些公所兵役科的人員會亂講,說什麼有照相功能的手機也可以帶,其實只能帶最基本的款式,沒有儲存功能(記憶卡之類的)的那種。
    5. 徵集令之外所附的一張單子上會寫一些要帶的東西,其中有說要帶照片,要記得帶否則還要爸媽或朋友寄去,會很麻煩因為剛開始若沒有手機,只能打公共電話,很多人排隊所以講什麼都很趕。
    6. 剛開始一兩個禮拜會頗有壓力,因為要弄的東西很多,所以做什麼都會很趕時間,之後則會無聊到爆,剛開始先忍忍吧。
    ---------------------------------------------------------------------------------------------------------
    我現在已經下部隊兩個月了,之前寫了這篇忘了po,因為原本想要寫更多真正紀錄我感覺的stuff,但最近實在太忙了~ so就先貢獻給之後要入伍的人吧! See ya~

    Apr 12, 2012

    Sorting integer array in place, in linear time

    Recently when I was learning algorithms, I came up with a pretty handy sorting method that can sort integer array in place, in linear time under the assumption that all the elements in input array are distinct and their values are 1~n(or 0~n-1) where n is the length of input array. So I decided to write a reminder to myself.
    Here's the algorithm:

    1:  gonnaSortIndex=len(array)-1  
    2:  for i=len(array)-1;i>0 {//Note that there's no i-- here
    3:    correctIndex=array[gonnaSortIndex]  
    4:    if correctIndex!=gonnaSortIndex {  
    5:      array[correctIndex],array[gonnaSortIndex]=array[gonnaSortIndex],array[correctIndex] //swapping array[gonnaSortIndex] into its final position and place the swapped out element array[correctIndex] into array[gonnaSortIndex].  
    6:   } else {  
    7:     i--  
    8:     gonnaSortIndex=i  
    9:   }  
    10: }

    This algorithm is clearly in-place, now let's examine what's the possible worst running time~

    Although not 100% sure because I did't really prove it but I think in the worst case, the running time is 2(n-1) where n is the # of elements in array
    Here's the worst case(that I came up with so far):
    Assume we swap all elements into their correct positions while i remains len(array)-1 all the time, so that it will take n-1 times executing if clause on line 4. After that we spend n-1 times executing else clause on line 6 so total running time is: 2*(n-1).
    If there's any mistakes, can someone please point it out cause I'm eager to know whether this actually works in all situation under the assumption above.

    Mar 10, 2012

    "我們經不起一次核災: 政府不回答,也不希望你知道的52件事"讀後感


    這本書是一位旅日作家劉黎兒所寫的。雖然,她並非核能方面的專家,但在日本311核災後,她開始嘗試了解核電,並發現到核電並非一向支持核電的日本政府所歌頌的那樣完美。所以她以一個避難者的身份,對仍然擁核的她的故鄉:台灣,發出深沈的警告。

    民眾和媒體都是健忘的!日本311核災到今天即將屆滿一週年。現在全世界一片歌舞昇平,全都沉醉在Linsanity的魅力中,好像一年前發生的核災已經不復存在了。沒錯!Jeremy Lin的例子的確是很鼓舞人心,但是這個世界難道沒有其他遠遠比NBA球星更重要的事情需要我們來關心嗎?日本政府聲稱發生事情的原子爐溫度已經穩定下來了,但根據書中所引述的專家看法,溫度降下來是因為爐心已經熔出圍阻體外部進入地下了,換句話說,污染已經不只在核電廠內部,而是擴散到福島的土地,地下水,情況可以說是已經到了無法挽救的地步了。

    然而,在整個事件中,最令人吃驚的不僅止於東電在發生事故時的隱瞞,而是在危險曝光後,日本政府的處理方式:簡言之,為了避免相當於日本十年國家預算的醫療,產業賠償以及徒勞無功的除污的費用。即使當地農民表示他們種的作物自己都不敢食用,但因為日本政府公然地違法調高農產品的輻射劑量數十甚至數百倍,使得福島農民所栽種的農作物,以及利用當地落葉等製造的肥料,都仍然無限制地擴散到全日本。而且因為政府無力搬遷所有應避難的居民,所以只好未經修法就調高人體所能忍受的輻射劑量幾十倍,福島當地有能力搬走的居民都已經避難了,剩下的人因為經濟能力等因素無法逃離,只好留在當地繼續呼吸受污染的空氣,食用受污染的農作物和魚肉。許多福島孩子們?」「我將來能不能生小孩?」,被我們視為生命中理所當然的事情,對他們而言變成了奢望。有能力離開當地的家庭的孩子們也不是毫髮無傷,許多地方因為害怕輻射已經開始排斥福島人,即使專家出面呼籲輻射並不會傳染,但福島兒童在其他地區學校被霸凌的案件仍層出不窮,有些餐廳和旅館仍拒絕福島人進入消費。

    有別於傳統媒體時常受到各方勢力的影響,網路世界一直被視為能夠自由抒發意見以及闡述事實的一個重要媒介。然而最近一兩年,美國及國際上的一些法案,如SOPA, ACTA等等,都引發政府權力擴張,以至於侵犯言論,自由及隱私權的疑慮。假使如此的法案通過了,一旦發生如日本核災的狀況,政府公然違法時,傳統媒體因受到壓迫而噤聲,網路自由又不復存在,所有能夠得到真相的媒介都已經喪失了!人民的生命財產,對受到強大壓力下的政府而言,只不過是數字罷了!

    311核災後,世界上絕大多數國家都決定暫緩興建中的核電廠,並且商議運轉中核電廠的退役事宜。反觀台灣,即便該型號反應爐的原設計者早已經向奇異表示該設計有重大瑕疵,台電仍執意興建核四。再加上台電自行變更了幾百處的設計,並使用全世界最為複雜的控制系統,也使得核四的可靠度十分令人存疑!

    台電和台灣政府目前使用的理由,是因為電力不足,所以必須啟用核四。先不論該說法是否為真,請問政府有問過人民,是不是願意犧牲部份時間的電力使用,來避免核四的商轉嗎?沒有!請問台電和政府有對一旦發生事故做好準備嗎?沒有!先不論核電廠週圍的緊急避難圈應該是5公里,50公里還是100公里,緊急避難圈內必備的碘片,我們的里長竟然只有碘藥水,其他就更不用說了。面對可能的災害,我們的準備可以說是趨近於0。難道真的要等到發生核災,全島一起滅亡的時候,才要後悔嗎?

    Feb 25, 2012

    Future


    Forerunner of the path I chose?

    The following is what I wrote but stayed as draft until now at the beginning of the fall semester 2011:

    "
    It's kind of exciting and sad at the same time to see so many new faces in our department, which constantly remind me of the path--the one I chose when I was still a freshman--that seems bumpy all the way down, impossible to penetrate like the muzzy night fog. Nevertheless, I know that the choice will eventually be worth the struggle.

    Recently I read a blog post, in which the author cited a quote:
    "The man who was crazy enough to think he could change the world, was the one who did"
    I'm about to begin my journey, which I have no idea how and when it's gonna end. But still, that won't stop me from striving to be whom I've always wanted to become."

    Now I've traveled a fairly long way down the path, it seems like I'm finally getting close to the crepuscule after this long journey in the night. Let's hope that one day I'll get to see the clear blue sky and together we can make a difference, we can change the world :)