FLYING

/* TODO: 気の利いた説明を書く */

YouTubeAPIで動画に評価を追加

ClientLogin認証を使ってYoutubeの動画に評価を追加するサンプル。YoutubeAPIで動画をアップロードするPerlのコードはググると簡単に見つけられたが,評価を追加するコードは(少なくとも日本語では)見つからなかったので,これから似たような事をする人のために載せておく。

手順

  1. ClientLoginの認証トークンを取得する
  2. 取得したトークンをヘッダに指定し,追加する評価を表すXMLをPOSTメソッドで送信する
  3. 評価が正常に追加されると,スタータス200と共に現在の評価値を表すXMLが返ってくる

引っかかったところ

POSTでXMLを送信する際に,事前に取得した認証トークンをAuthorizationヘッダに指定する。この書式はAuthSub認証を使う場合は

Authorization: AuthSub token=hogehoge

となるが,ClientLoginを使う場合は

Authorization: GoogleLogin auth=hogehoge

となることに注意する。

また,URLLoaderを使ってXMLを送信すると何故か途中でストリームエラーが発生してうまくいかないので,as3httpclientで公開されているSocketURLLoaderを利用した。他にも,URLLoaderにはGETでリクエストを送ると何故かヘッダが付加されないなどの不具合があるようなので,込み入ったリクエストを送る場合はSocketURLLoaderを利用したほうがよさげ。

コード

評価を追加するためのクラス

package
{
	import flash.events.*;
	import flash.net.*;
	import code.google.as3httpclient.*;
	
	public class RatingTask
	{
		private var videoId:String;
		private var ratingRate:int;
		private var userId:String;
		private var userPassword:String;
		private var authToken:String;
		public var isSuccess:Boolean;
		public var onExecuted:Function;
		
		private const CLIENT_ID:String = "YourClientID";
		private const DEVELOPER_KEY:String = "YourDeveloperKey";
		private const CLIENT_LOGIN_URI:String = "https://www.google.com/youtube/accounts/ClientLogin";
		private const RATING_URI_PREFIX:String = "http://gdata.youtube.com/feeds/api/videos/";
		private const RATING_URI_SUFFIX:String = "/ratings";
		
		// ユーザー情報を与えて初期化
		public function RatingTask(videoId:String, ratingRate:int, userId:String, userPassword:String)
		{
			this.videoId = videoId;
			this.ratingRate = ratingRate;
			this.userId = userId;
			this.userPassword = userPassword;
			this.isSuccess = false;
		}
		
		// ログイン
		public function load():void
		{
			// ログインリクエストを作成
			var loginRequest:URLRequest = new URLRequest(CLIENT_LOGIN_URI);
			loginRequest.method = URLRequestMethod.POST;
			loginRequest.contentType = "application/x-www-form-urlencoded";
			var variables:URLVariables = new URLVariables();
			variables.Email = userId;
			variables.Passwd = userPassword;
			variables.service = "youtube";
			variables.source = "ratingtask";
			loginRequest.data = variables;
			
			// ログイン実行
			var loginLoader:URLLoader = new URLLoader();
			loginLoader.addEventListener(Event.COMPLETE, onAuth);
			loginLoader.addEventListener(IOErrorEvent.IO_ERROR, onError);
			loginLoader.load(loginRequest);
		}
		
		// 評価
		public function onAuth(event:Event):void
		{
			// 認証トークンを取得する
			var loginLoader:URLLoader = URLLoader(event.target);
			var matches:Array = loginLoader.data.match(/Auth=([^\s]*)/);
			if (matches == null || matches.length < 2) {
				onError(new Event("認証トークンの取得に失敗しました"));
				return;
			}
			authToken = matches[1];
			
			// 評価リクエストを作成
			var ratingRequest:URLRequest = new URLRequest(RATING_URI_PREFIX + videoId + RATING_URI_SUFFIX);
			ratingRequest.method = URLRequestMethod.POST;
			ratingRequest.contentType = "application/atom+xml";
			ratingRequest.data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
						+ "<entry xmlns=\"http://www.w3.org/2005/Atom\"\n"
						+ "       xmlns:gd=\"http://schemas.google.com/g/2005\">\n"
						+ "  <gd:rating value=\"" + ratingRate + "\" min=\"1\" max=\"5\"/>\n"
						+ "</entry>\n";
			ratingRequest.requestHeaders = [
				new URLRequestHeader("Content-Length", ratingRequest.data.length),
				new URLRequestHeader("Authorization", "GoogleLogin auth=" + authToken),
				new URLRequestHeader("X-GData-Client", CLIENT_ID),
				new URLRequestHeader("X-GData-Key",  "key=" + DEVELOPER_KEY)
			];
			
			// 評価実行
			var ratingLoader:SocketURLLoader = new SocketURLLoader();
			ratingLoader.addEventListener(Event.COMPLETE, onRating);
			ratingLoader.addEventListener(IOErrorEvent.IO_ERROR, onError);
			ratingLoader.load(ratingRequest);
		}
		
		// 評価後
		public function onRating(event:Event):void
		{
			var loader:SocketURLLoader = SocketURLLoader(event.target);
			var matches:Array = loader.data.match(/<\?xml.[^\?>]*\?>/);
			if (matches == null) {
				onError(new Event("評価の追加に失敗しました"));
				return;
			}
			isSuccess = true;
			if (onExecuted != null) {
				onExecuted();
			}
		}
		
		// エラー処理
		public function onError(event:Event):void
		{
			isSuccess = false;
			if (onExecuted != null) {
				onExecuted();
			}
		}
	}
}

使い方

var videoId:String = "hogehoge";
var ratingRate:int = 5;
var userName:String = "YourName";
var userPassword:String = "YourPassword";
ratingTask = new RatingTask(videoId, ratingRate, userName, userPassword);
ratingTask.onExecuted = function():void{
	if (ratingTask.isSuccess) {
		trace("評価の追加に成功したっぽい");
	} else {
		trace("評価の追加に失敗したっぽい");
	}
};
ratingTask.load();