Getting Flash and Twitter to play nice.

by Martin on 18/04/2008

Attention!

This code was written by a far less awesome version of me and using it is strongly discouraged. You should go here and use that code instead. Do it. You’ll thank me.


I’m an avid user of Twitter. I’m also a Flash developer so it figures I had created a Twitter badge in Flash to display on my old blog. I even had a tutorial on how to do it. The thing is; Twitter all of a sudden decided to close off their feeds to Flash. By changing their crossdomain.xml 1 the pretty much messed up any Flash apps out there talking to Twitter. A tad frustrating, but oh well.

This just means we’ll have to be a bit more creative when we create Twitter stuff. To get the Actionscript and the clever solution for the cross domain issue, read on.

So. Firstly we’ll have to get around the cross domain issue. Well, luckily I stumbled over a solution. Yahoo Pipes is a pretty awesome mashup tool which allows you to mess around with the feeds from different sources. Specifically this ‘pipe’ is relevant to our problem. You’ll need your twitter ID which is the last string of numbers if you click on the RSS-icon at your twitter homepage. Plug it in at the pipe and snatch the URL for the feed.

We’re ready to write some Actionscript. Here goes nothing.

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package {

import flash.display.Sprite;
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.text.*;
import flash.events.Event;

public class TweetPipeLoad extends Sprite {

    var twitURL:URLRequest;
    var twitLoader:URLLoader;
    var tx:XML;
  var regExp:RegExp;
  var processed:Array;

  public function TweetPipeLoad (userId:String){

  /*Long ass url to the yahoo pipe
 * processed twitter feed.*/

 twitURL = new URLRequest("http://pipes.yahooapis.com/pipes/pipe.run?_id=4b85031723ba7785e277add01b0169c5&_render=rss&twitter="+userId);
    twitLoader = new URLLoader(twitURL);
    twitLoader.addEventListener(Event.COMPLETE, onComplete);
   /*Let's create an Array for the
   *  tweets after they're loaded. */

    processed = new Array();

     /*Reg exp: Regular expressions. Black magic.
     *  This particular one checks for URLs in the string
     *  so we can make them clickable.*/

        regExp = new RegExp( /(ftp|http|https)://(w+:{0,1}w*@)?(S+)(:[0-9]+)?(/|/([w#!:.?+=&%@!-/]))?/);

  }

private function onComplete(e:Event) : void {
    /*This function is called when the Pipe URL is done loading
    * hence the name 'onComplete'. Lets check that it contains
    * valid data and store the information in a XML object. */

if(twitLoader.data){
   tx = new XML(twitLoader.data);

/*Next: Check for the occurrence of '@' in the tweet. If so
* we'll assume the tweet is in response to someone else,
* in which case we don't want it on our badge. I don't, anyway.
* If the string doesn't contain any @s we push it to the array.*/


for (var i:int = 5; i<tx.children()[0].children().length(); i++){
      var curTweet:String = tx.children()[0].children()[i].children()[2];
      if (curTweet.indexOf("@") <= -1 && !regExp.test(curTweet)){
        processed.push(curTweet);
   } else

   /*We also check for URLs using the RegExp from earlier.
   *  If we find a url in the string we wrap it in <a> tags
   *  to make it clickable. At the end we push the string to the array.*/


   if(curTweet.indexOf("@") <= -1 && regExp.test(curTweet)){
    var urlstr:Array = regExp.exec(curTweet);
    var justUrl:String = curTweet.substr(urlstr.index,urlstr.toString().length);
    var linkedUrl:String = "<a href='" + justUrl + "'>" + justUrl + "</a>";
    var newTweet:String = curTweet.replace(justUrl,linkedUrl);
    curTweet = newTweet;
    processed.push(newTweet);

      }

    }
  }
  /*Dispatch an event to let listeners know
  * that the tweets have been loaded and processed.*/

  this.dispatchEvent(new Event("TweetComplete",true,false));

}

  /*The getTweets() - method should be called only
  * after the "TweetComplete" event is dispatched.
  * It takes one optional argument. If you want the
  * tweets to appear without the leading "username: "
  * you can fill out your username and it will
  * automagically be removed from the string.*/


public function getTweets(userDecap:String = null) : Array {
  if(userDecap != null){
  for (var i:int = 0; i< processed.length; i++){
    processed[i] = processed[i].substring(userDecap.length + 2);
  }
  return processed;
  } else {
  return processed;
  }
  }

  }
}

This can almost certainly be improved upon, but it works quite well. Let’s have a look at the usage, which is fairly simple.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import net.parallaxdenigrate.TweetPipeLoad;

var tpl:TweetPipeLoad;
var processed:Array;
/*set up a new instance and pass the Twitter user id*/

tpl = new TweetPipeLoad("200523");
/*Listen for the event dispatched when the
  Tweets are loaded*/

tpl.addEventListener("TweetComplete", onTweetComplete);

function onTweetComplete(e:Event):void {
  /*Fire the getTweets() method and pass your
  username as an argument.*/

    processed = tpl.getTweets("martinj");
    for each (var item:String in processed){
      trace(item)
    }
}

There. That’s all there is to it.
Example files here.

  1. Lots of good info about crossdomain policy files here. It’s dated but still valid.

There are 20 comments in this article:

  1. 26/08/2008Sam says:

    This is a fantastic solution. I love it. Got it working after some fiddling…. I was wondering if there is a way to get the time stamp on entries?

    Thanks

  2. 26/08/2008Sam says:

    Great I’ll try that. Thanks indeed.

    On a different note, do you have frequent errors with the yahoo pipe…? At the moment the link (http://pipes.yahoo.com/pipes/pipe.info?_id=4b85031723ba7785e277add01b0169c5) you demonstrated above goes to an error page…

    “Sorry, Unable to process request at this time — error 999.”

    Am I missing something, or does this just happen?

  3. 26/08/2008Martin says:

    I think most of the problems are because of the Twitter fail whale, but I can’t say for sure.

  4. 26/08/2008Martin says:

    Sure thing.
    If you add a trace statement on line 41 so it reads:

    1
    2
    3
    4
    if(twitLoader.data){
       tx = new XML(twitLoader.data);
       trace(tx)
    ...

    You’ll see the full XML loaded from the Yahoo Pipe. Then just parse the timestamp and send it over to your main class to display.

  5. 23/02/2009William says:

    Hey mate,

    love this tutorial! Thanks a heap.

    I have one small problem, the timestamp is not in the right timezone, as I live in Australia I’m actually 10 hours ahead.

    With a bit of googling it appears I can’t do anything with the twitter backend and most websites showed php solutions.

    Any ideas on your code on how to change the date? My actionscript (3 especially), is pretty intermediate.

    Thanks for taking the time to read this comment.

    Cheers William

  6. 5/03/2009Martin says:

    Hi.
    I suppose there are a few ways you could go about this. One would be to mess around a bit with the actual
    Yahoo Pipe
    that’s being used as a buffer. That link will take you straight to the source.

    An easier way perhaps if you’re comfy with ActionScript is to simply add/subtract your offset to the timestamp in the RSS feed. Just get the time and cast it to

    1
    uints

    and then do something along these lines:

    1
    2
    3
    4
    5
    6
          var currentTime:Date = new Date();
        var utcHours:Number = currentTime.getUTCHours();
        var aussieHours:Number = currentTime.getUTCHours() + 9;

        XTrace.log("UTC: " + utcHours);
        XTrace.log("Australia: " + aussieHours);

    Sorry I can’t come up with a working example right now, but I’m sure you’ll figure it out.

  7. 22/03/2009Monkey says:

    Hi

    The regular expression just throws an error in FDT as the // in the string comments out the second half of the code on that line – any ideas?

    Nice work by the way!

  8. 22/03/2009Martin says:

    Hey. Thank you.
    I do indeed have a suggestion. To be honest the regex in this code is crap. (In fact the entire class could do with some refactoring, so check back in a little and I’ll have it fixed up).

    Recently I was getting fed up with the problems I kept having with validating URLs, so I sat down and wrote this class which I’m pretty sure you’ll find both better and easier to use.

  9. 8/07/2009Steven H says:

    Fabulous solution…ideal if you just need to read the tweets…thanks for sharing!! If you need to post tweets, i guess it would still need a PHP proxy.

  10. 8/07/2009Steven H says:

    btw, if you’re having regexp problems just remove until you have time to sort out properly :

    regExp = new RegExp()

  11. 11/02/2011heliogabal says:

    You could fix it wit php oneliner:

    1
    2
    3
    <?
    echo(file_get_contents('http://www.x.com/feed.xml'));
    ?>

    and that’s whole “php gateway file”

  12. 25/02/2011Loading Twitter Feeds Into Flash (Through PHP) says:

    [...] seemingly devious scheme of cock blockery. So ha! There are a number of ways out there. Like THIS ONE, that uses Yahoo Pipes — plugging your twitter ID into a pipe and pulling in the URL for the [...]

  13. 19/04/2011Jay says:

    Hey Martin,

    Thanks for the tutorial. Its great. I tried putting my own id instead of yours and this is the error I am getting…

    RangeError: Error #1125: The index 0 is out of range 0.
    at Main/cycleThrough()

    Any ideas, what it could be? Thanks in advance.

    Jay

  14. 19/04/2011Martin says:

    That sounds like you’re trying to cycle back beyond the first tweet or back beyond that last tweet in the feed.

    If you give me a working code example I might come up with a more interesting answer.

  15. 19/04/2011Jay says:

    Hey Martin,

    Thanks for replying back. Oh Gosh! only thing I actually changed was your id to my own…

    pipe = new TwitterPipe(“172773388″);

    And when I click on “Click” it gives me the error I posted earlier.

    RangeError: Error #1125: The index 0 is out of range 0.
    at Main/cycleThrough()

    Also I noticed, when you had your ID on their as a sample. I clicked through your tweets and at some point, I got this error….

    RangeError: Error #1125: The index 5 is out of range 5.
    at Main/cycleThrough()

  16. 19/04/2011Martin says:

    Jay: First of all. You shouldn’t be using this code. You should use the improved version that is linked to at the top of the post.

    Try that first, and if that doesn’t do it for you; Shoot me a mail. I won’t be able to hang on for much longer tonight, but I’ll try to answer you snappish.

  17. 19/04/2011Jay says:

    I am using the new code that you linked on up on top. For some odd reason, it doesn’t work if I use any ID.

    same error.

  18. 19/04/2011Jay says:

    oops, I meant I have used the new code that you have linked on your other page. handy.zip file

  19. 20/04/2011Martin says:

    Jay: The example code is exactly that. An example. You get that error when there are no recent tweets in the feed. I just checked the code with my own twitter feed and it read back a couple of tweets and then gave me the same error you get.

    I’m sorry, but error handling isn’t included in this very bare-bones example.

  20. 20/04/2011Jay says:

    Hey Martin,

    No problem! Thanks for the tutorial though! Atleast I learned something today.

    Hopefully, I’ll figure it out

    Thanks,
    Jay

Write a comment: