跳到主要內容

Facebook - Establish a app in 5 minutes - Find the Single

要做一個Facebook的應用程式,一點也不難!今天要帶給大家的是:5分鐘做一個facebook AP。第一步是加入開發人員這個應用程式。

加入開發人員應用程式

在上方的搜尋輸入開發人員就能找到應用程式,點擊後會導入如下圖的授權頁面。

在點擊前往應用程式後,你可以看到類似下圖的畫面,差別在於你不會像我這裡有三個應用程式。這個畫面我把它叫做應用程式主控板,你可以看到你建立的應用程式資訊。

新增應用程式

在應用程式主控板上點擊建立新的應用程式,會出現如下圖的Dialog。App Name即應用程式名稱,應用程式名稱空間即應用程式的URL名稱,而Web Hosting則是使用Herocu提供的服務,讓你可以不需要把應用程式放在自己的主機上,它還有許多強大的功能,有興趣可以參考它的介紹。當初我在寫國軍登出倒數計時器時,還沒有這麼好用的東西,只能把寫好的應用程式放在自己家中而已。言歸正傳,今天我們要做的應用程式叫「Find The Single」 - 尋找單身。

在按繼續並輸入驗證碼後,會出現如下圖應用程式主控板。

在點擊編輯應用程式後會進入下面這個頁面。我預計要把應用程式放在Apache Server上,並透過Canvas的方式讓User存取。我需要輸入以下資料:

  • 基本資料: 如果有App Domain就填入Domain,類別選擇你應用程式的類別。Find The Fuck Buddy Single我想是策略性遊戲吧…
  • Website with Facebook Login: 輸入網站的URL即可。
  • Facebook上的App: 輸入網站的URL即可。如果支援Https就輸入Https的URL。

部屬與撰寫程式

Apache Config

設定Artifact的目錄。

<Directory "/var/www/FindTheSingle">
        Order Deny,Allow
        Allow from all
</Directory>

Alias /FindTheSingle /var/www/FindTheSingle
Alias /findTheSingle /var/www/FindTheSingle
Alias /findthesingle /var/www/FindTheSingle

HTML and Javascript

需求

Find The Single顧名思義為尋找單身。我希望能夠找到單身的異性朋友,包含難以言喻(Complicated)與單身(Single),而不詳(Unknown)僅做為參考用。你也許會問: 為什麼難以言喻也要放進來? 我說: 因為機會比單身還大啊! 因此我預計將UI設計為三個區塊,而顯示內容主要以朋友的大頭照為主。這個範例直接透過Facebook Javascript的API即可完成。讓我們先看看預期出現的結果:

骨架

以下程式碼是這個範例的骨架。在<body>內為整個頁面的layout,分成Complicated、Single與Unknown三個區塊,而fb-root區塊為load Facebook Javascript SDK所需要。在Javascript區塊的部分,引用了jquery與我自己整理的fb-util.js。實作內容則直接由SDK範例中複製修改,主要有三個動作:

  1. Load SDK: 將最新的FB Javascript API source file讀取進來。
  2. Init SDK: 必須給定應用程式的App ID,可於應用程式主控板看到。其它參數則是決定是否啟用功能,其中xfbml設定為true代表要去parse頁面中有使用FB的特有語法(XFBML)。
  3. Login: 讓應用程式透過OAuth方式取得Access_token(門牌),以存取在臉書上的資料。這應用程式需要存取的權限包含朋友清單、我的關係與朋友的關係(read_friendlists, user_relationships, and friends_relationships)。在完成授權與登入後,會透過callback的方式呼叫function(response)的內容,一切的實作都是從這開始!

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=BIG5">
<title>Find The Single</title>
<script type="text/javascript" src="js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="js/fb-util.js"></script>
<script type="text/javascript">
	window.fbAsyncInit = function() {
		FB.init( {
			appId : 'App ID', 
			status : true, // check login status
			cookie : true, // enable cookies to allow the server to access the session
			xfbml : true // parse XFBML
		});
 
		FB.login(function(response) {
			if (response.authResponse) {
				// implement here!
			}
		}, {
			scope : 'read_friendlists,user_relationships,friends_relationships'
		});
	};
 
	(function(d) {
		var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
		if (d.getElementById(id)) {
			return;
		}
		js = d.createElement('script');
		js.id = id;
		js.async = true;
		js.src = "//connect.facebook.net/en_US/all.js";
		ref.parentNode.insertBefore(js, ref);
	}(document));
</script>
</head>
<body>
<div id="fb-root"></div>
<h2><img src="images/unstarred.gif" /> Complicated:</h2>
<hr />
<div id='complicated-friend-list'></div>
<h2><img src="images/unstarred.gif" /> Single:</h2>
<hr />
<div id='single-friend-list'></div>
<h2><img src="images/unstarred.gif" /> Unknown:</h2>
<hr />
<div id='unkown-friend-list'></div>
</body>
</html>
要求使用者授權的畫面:

主要實作

程式流程非常簡單。登入後讀取我的性別與朋友列表,接著根據朋友的感情狀態進行分類,最後產生朋友的大頭照塞入對應的layout中。

登入後的動作

再登入後呼叫initFriendsRelationShip() function。
	FB.login(function(response) {
		if (response.authResponse) {
			initFriendsRelationShip();
		}}, {
			scope : 'read_friendlists,user_relationships,friends_relationships'
	});
透過Graph API去查詢我的性別,用以判斷異性朋友。(要找同性的請自行改寫…)
	function initFriendsRelationShip(){
		FB.api('/me', function(response) {
			handelFriendList(response.gender);
		});		
	};
讀取朋友清單,並一個個丟到handleRelationship中處理。FB.Canvas.setAutoResize()是為了在產生整個頁面資料後,用來調整layout長寬的。
	function handelFriendList(myGender) {
		FB.api('/me/friends', function(response) {
			var data = response.data;
			for ( var i = 0 ; i < data.length; i++) {
				handleRelationship(data[i].id, myGender);
			}
			FB.Canvas.setAutoResize();
		});
	};
透過Graph API取得的內容為Json format:

處理朋友清單

根據朋友的id透過Graph API找她的感情狀態來做比對,並skip掉同性朋友。接著根據狀態去呼叫各別的function做處理。
	function handleRelationship(uid, myGender){
		FB.api('/'+uid, function(response) {
			var data = response.relationship_status;
			var friendGender = response.gender;
			if( myGender == friendGender ){
				return;
			}
 
			if(data){
				if( data == 'Single' ||
						data == 'Separated'){
					insertToSingleFriendList(uid);
				} else if( data == 'It\'s complicated' ){
					insertToComplicated(uid);
				}
			} else {
				insertToUnkownFriendList(uid);
			}
		});
	}

產生大頭照

在根據感情狀態呼叫各自的function後,接著會產生根據朋友的uid產生fxbml語法(FacebookUtillity.getUserSqurePicWithLogo)去加入到對應的div中。最後透過API去parse這個語法以顯示出fxbml的內容。大頭照的fxbml語法為fb:profile-pic標籤,在這裡我有做特殊處理,讓它點擊後會開新視窗。

	function insertThePicToDiv(uid, div){
		var fbHtml = FacebookUtillity.getUserSqurePicWithLogo(uid,true);
		$('#'+div).append(fbHtml);
		FacebookUtillity.parseXFBML(div);
	};
 
	function insertToSingleFriendList(uid){
		insertThePicToDiv(uid, 'single-friend-list');
	};
 
	function insertToUnkownFriendList(uid){
		insertThePicToDiv(uid, 'unkown-friend-list');
	};
 
	function insertToComplicated(uid){
		insertThePicToDiv(uid, 'complicated-friend-list');
	};

Summary

做一個Facebook應用程式不難吧?完全不需要Server Side Programming,就能夠完成一個有趣的程式。言歸正傳,看完這篇你可能會存在這些疑問:
  1. OAuth是什麼?
  2. Graph API是什麼?
  3. 難道授權畫面只能透過pop-up的方式嗎?
  4. fxbml語法還有哪些?
  5. 我想透過其它語言實作行嗎?
也許還有許多疑問,在之後的文章會再一一替大家解答。(或許前兩個問題Google比較快啦!)

留言

這個網誌中的熱門文章

Show NIC selection when setting the network command with the device option

 Problem  在answer file中設定網卡名稱後,安裝時會停在以下畫面: 所使用的command參數如下: network --onboot = yes --bootproto =dhcp --ipv6 =auto --device =eth1 Diagnostic Result 這樣的參數,以前試驗過是可以安裝完成的。因此在發生這個問題後,我檢查了它的debug console: 從console得知,eth1可能是沒有連接網路線或者是網路太慢而導致的問題。後來和Ivy再三確認,有問題的是有接網路線的網卡,且問題是發生在activate階段: Solution 我想既然有retry應該就有次數或者timeout限制,因此發現在Anaconda的說明文件中( link ),有提到dhcptimeout這個boot參數。看了一些人的使用範例,應該是可以直接串在isolinux.cfg中,如下: default linux ksdevice = link ip =dhcp ks =cdrom: / ks.cfg dhcptimeout = 90 然而我在RHEL/CentOS 6.7與6.8試驗後都無效。 因此我就拿了顯示的錯誤字串,問問Google大師,想找一下Anaconda source code來看一下。最後找到別人根據Anaconda code修改的版本: link ,關鍵在於setupIfaceStruct函式中的setupIfaceStruct與readNetConfig: setupIfaceStruct: 會在dhcp時設定dhcptimeout。 readNetConfig: 在writeEnabledNetInfo將timeout寫入dhclient config中;在wait_for_iface_activation內會根據timeout做retry。 再來從log與code可以得知,它讀取的檔案是answer file而不是boot command line。因此我接下來的測試,就是在answer file的network command上加入dhcptimeout: network --onboot = yes --bootproto =dhcp --ipv6 =auto --device =eth1 --dhcptimeo

解決RobotFramework從3.1.2升級到3.2.2之後,Choose File突然會整個Hand住的問題

考慮到自動測試環境的維護,我們很久以前就使用java去執行robot framework。前陣子開始處理從3.1.2升級到3.2.2的事情,主要先把明確的runtime語法錯誤與deprecate item處理好,這部分內容可以參考: link 。 直到最近才發現,透過SeleniumLibrary執行Choose File去上傳檔案的動作,會導致測試案例timeout。本篇文章主要分享心路歷程與解決方法,我也送了一條issue給robot framework: link 。 我的環境如下: RobotFramework: 3.2.2 Selenium: 3.141.0 SeleniumLibrary: 3.3.1 Remote Selenium Version: selenium-server-standalone-3.141.59 首先並非所有Choose File的動作都會hang住,有些測試案例是可以執行的,但是上傳一個作業系統ISO檔案一定會發生問題。後來我透過wireshark去比對新舊版本的上傳動作,因為我使用 Remote Selenium ,所以Selenium會先把檔案透過REST API發送到Remote Selenium Server上。從下圖我們可以發現,在3.2.2的最後一個TCP封包,比3.1.2大概少了500個bytes。 於是就開始了我trace code之路。包含SeleniumLibrary產生要送給Remote Selenium Server的request內容,還有HTTP Content-Length的計算,我都確認過沒有問題。 最後發現問題是出在socket API的使用上,就是下圖的這支code: 最後發現可能因為開始使用nio的方式送資料,但沒處理到尚未送完的資料內容,而導致發生問題。加一個loop去做計算就可以解決了。 最後我有把解法提供給robot framework官方,在他們出新的版本之前,我是將改完的_socket.py放在我們自己的Lib底下,好讓我們測試可以正常進行。(shutil.py應該也是為了解某個bug而產生的樣子..)

PostgreSQL - Unattended installation on windows

Introduction 要將別人軟體包裝到自己軟體中,不可或缺的東西就是Unattended installation。以Unattended installation來說,我們可以選擇透過Installer的silent mode安裝,也可以透過把目標軟體做成portable的版本。本篇文章分享這兩種方法,教導大家如何將PostgreSQL透過Unattended installation方式安裝到目標系統成為service。 Note. 本篇以PostgreSQL 10.7為例。 Install with installer Tips 安裝程式或反安裝程式的參數,除了可以直接上官網搜尋Installation User Guide以外,也可以直接使用help參數查詢: postgresql- 10.7 - 2 -windows-x64.exe --help Windows安裝程式主要有EnterpriseDB與BigSQL兩種。BigSQL版本安裝元件是透過網路下載且支援參數不如EnterpriseDB版本多,以我們需求來說,我們傾向於使用EnterpriseDB版本。接下來分享給大家安裝與反安裝方法。 Installation @ echo off set INSTALL_DIR =C:\postgres10 set INSTALLER =postgresql- 10.7 - 2 -windows-x64.exe   rem options for installation set SSMDB_SERVICE =postgresql- 10 set MODE =--unattendedmodeui none --mode unattended   set DB_PASSWD =--superpassword postgres set DB_PORT =--serverport 5432   set SERVICE_NAME =--servicename % SSMDB_SERVICE %   set PREFIX =--prefix "%INSTALL_DIR%" set DATA_DIR =--datadir "%INSTALL_DIR%\data"   set OPTIONS =