ActionScriptからTwitterAPIを使いたい時にGoogle App Engineをプロキシにすれば簡単

ActionScriptからTwitterAPI使う時は、クロスドメイン対応の為に、phpでプロキシ作ったりするらしいけど、
BlazeDSとTwitter4jでプロキシ作るのも良いんじゃないかな。


S3BlazeDS使えばGoogle App Engineでも動くし、
BlazeDS使えばRemote呼び出しできるのでTwitter4jの使いやすさをActionScriptでも実現できる。

んで、テキトーに作った。

とりあえずTL取得だけですが、
ポップアップ等つかってOAuth認証してもらえば何でもできるんじゃないかと


こいつをBlazeDに登録して使います。
TwitterAPI.java

public class TwitterAPI {
        //TL取得
	public List<Status> getUserTimeline(String screenName)
			throws TwitterException {
		Twitter twitter = new TwitterFactory().getInstance();
		List<Status> rs = twitter.getUserTimeline(screenName);
		return rs;
	}	
}


Twitter4jのクラスを変換できるように変換クラスを作成します。
(デフォルトコンストラクタが無いクラスは作る必要あり)
とりあえずめんどくさいのでStatusのtextプロパティのみ対応。他のプロパティやクラスも同じ要領で作ればOK。
StatusProxy.java

public class StatusProxy extends BeanProxy {

	private static final long serialVersionUID = 1L;

	@Override
	public Object createInstance(String className) {
		return new StatusStub();
	}

	@Override
	public Object getValue(Object instance, String propertyName) {
		Status i = (Status) instance;
		if (propertyName.equals("text")) {
			return i.getText();
		}

		throw new IllegalArgumentException("Illegal propertyName. "
				+ propertyName);
	}

	@Override
	public void setValue(Object instance, String propertyName, Object value) {
		StatusStub s = (StatusStub) instance;
		if (propertyName.equals("text")) {
			s.text = (String) value;
		} else {
			throw new IllegalArgumentException("Illegal propertyName. "
					+ propertyName);
		}
	}

	@Override
	public Object instanceComplete(Object instance) {
		return instance;
	}

	@Override
	public List<String> getPropertyNames(Object instance) {
		return Arrays.asList("text");
	}

	class StatusStub implements Status {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;
		String text;

		@Override
		public String getText() {
			return text;
		}

		@Override
		public RateLimitStatus getRateLimitStatus() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public Annotations getAnnotations() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public String[] getContributors() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public Date getCreatedAt() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public GeoLocation getGeoLocation() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public HashtagEntity[] getHashtagEntities() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public String[] getHashtags() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public long getId() {
			// TODO Auto-generated method stub
			return 0;
		}

		@Override
		public String getInReplyToScreenName() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public long getInReplyToStatusId() {
			// TODO Auto-generated method stub
			return 0;
		}

		@Override
		public int getInReplyToUserId() {
			// TODO Auto-generated method stub
			return 0;
		}

		@Override
		public Place getPlace() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public long getRetweetCount() {
			// TODO Auto-generated method stub
			return 0;
		}

		@Override
		public Status getRetweetedStatus() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public String getSource() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public URLEntity[] getURLEntities() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public URL[] getURLs() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public User getUser() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public UserMentionEntity[] getUserMentionEntities() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public User[] getUserMentions() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public boolean isFavorited() {
			// TODO Auto-generated method stub
			return false;
		}

		@Override
		public boolean isRetweet() {
			// TODO Auto-generated method stub
			return false;
		}

		@Override
		public boolean isRetweetedByMe() {
			// TODO Auto-generated method stub
			return false;
		}

		@Override
		public boolean isTruncated() {
			// TODO Auto-generated method stub
			return false;
		}

		@Override
		public int compareTo(Status o) {
			// TODO Auto-generated method stub
			return 0;
		}
	}
}


変換クラスを登録するBootStrapサービス
service-config.xmlで設定する。
SerializerBootstrapService.java

public class SerializerBootstrapService extends AbstractBootstrapService {

	@Override
	public void initialize(String id, ConfigMap properties) {
	}

	@Override
	public void start() {
		PropertyProxyRegistry.getRegistry().register(Status.class,
				new StatusProxy());
                
	}

	@Override
	public void stop() {
		PropertyProxyRegistry.getRegistry().clear();
	}

}


Flex
TL取得のサンプル

	<fx:Declarations>
		<s:RemoteObject id="twitteAPI" showBusyCursor="true" destination="TwitterAPIService"/>
		<s:ArrayCollection id="tweets">
		</s:ArrayCollection>
	</fx:Declarations>
	
	<fx:Script>
		<![CDATA[
			import mx.collections.ArrayCollection;
			import mx.collections.ArrayList;
			import mx.controls.Alert;
			import mx.rpc.AsyncResponder;
			import mx.rpc.AsyncToken;
			import mx.rpc.events.FaultEvent;
			import mx.rpc.events.ResultEvent;
			
			private function getUserTimeline(userName:String):void{
				var token:AsyncToken = twitteAPI.getUserTimeline(userName);
				token.addResponder(
					new AsyncResponder(
						function(re:ResultEvent, obj:Object=null):void{
							tweets = re.result as ArrayCollection;
							tweets.addAll(tweets);
						},
						function(ee:FaultEvent, obj:Object=null):void{
							Alert.show(ee.message.body.toString());
							trace(ee);
						}
					)
				);

			}
			
		]]>
	</fx:Script>
	
	<s:TextInput id="f_userName" text="kissrobber"/>
	<s:Button label="get" click="getUserTimeline(f_userName.text)"/>
	
	<s:List dataProvider="{tweets}" labelField="text">
	</s:List>
	


Statusクラス

package as_twitterapi_proxy.io
{
	[RemoteClass(alias="twitter4j.StatusJSONImpl")]
	public class Status
	{
		public var createdAt:Date;
		public var id:Number;
		public var text:String;
		public var source:String;
		public var truncated:Boolean:
		public var inReplyToStatusId:Number;
		public var inReplyToUserId:int;
		public var inReplyToScreenName:String;
		public var getLocation:Object;
		public var favorited:Boolean;
		public var user:Object;
		public var retweet:Boolean;
		public var retweetedStatus;Status;
		
		public function Status()
		{
		}
				
	}
}