Twitter, Twitter, Twitter

Update!! Yahoo did the same dick move of cockblocking Flash. :/ To remedy this the URLRequest on line 80 had to be changed. If your project used to work but doesn’t anymore; Try this. If this is your first time here; Ignore this message.

Ad infinitum, ad nauseum.
So, I saw that I’m still getting some traffic to this post where I suggested a solution to the Twitter crossdomain.xml problem.

The Yahoo pipes solution still works fine, but my code is a godawful mess and I decided I’d have to fix it up a bit. The methodology is essentially the same. We’ll be using this yahoo pipe, but it’s neatly blackboxed so that you just need to know your Twitter ID to use this class.


The last iteration of this class returned the tweets as an Array of Strings. This time I decided to return them as Objects containing the different versions of the tweet :

  • raw: The raw tweet. No filtering for URLs, no trimming the username.
  • chopped: As above, but “yourusername: ” is removed.
  • linked: Same as raw, but with all URLs tagged.
  • choppedAndLinked: … you get it.

I’m only partly convinced that this is a wise way to go about it, but I’m thinking of expanding this out to include a “Tweet” class, and if I go that way it’ll be fortuitous to have been treating the information as objects already.

Note that in order to get this to work you’ll need both the TwitterPipe class and the URLValidator class I’ve discussed here earlier. I’ve gathered both in this handy zip for you along with a short example on usage. If you’re the kind that wants to read some code before committing to clicking on a link and opening a document, well here you go:

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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package com.ctrloptcmd.twitter {  

      /**
       *      TwitterPipe.as
       *
       *      @langversion: ActionScript 3.0
       *      @playerversion: Flash 10.0
       *
      *      @author: Martin Jacobsen
      *      @since: 22-03-2009
      *  
      *      @description : Cleaned up version of the previous "TweetPipeLoad"
      *      class which was written by a younger, more foolish and not quite as
      *      pretty version of myself. I'm not saying this class is by any means
      *      a stroke of genius, but by jove it certainly is an improvement on
      *      the dreadful mess of the old one.
      *  
      *      This new and improved version has far less unused "mass imports", less
      *      incomprehensible variables and actually uses E4X for what it's worth
      *      rather than clumsily climbing through XMLNode hierarchies AS2 style.
      *  
      *      Also; This class utilizes the URLValidator class for parsing through
      *      tweets for URLs rather than relying on string-parsing mumbo jumbo and
      *      misunderstood implementation of black magic regular expressions to try
      *      and figure out whether there are any URLs present. Just trust me on this;
      *      It's better.
      *  
      *      Note that this version returns a Vector with objects rather than just strings.
      *      I found that returning objects and accessing the different versions of the
      *      string representations seemed somehow easier to use. It also makes it easy to
      *      later expand upon with a "Tweet" class if that should prove interesting at
      *      any time.
      *  
      *      The class uses Vectors because it seems to be all the rage these
      *       days among the optimization literati. If you don't like Flash Player
      *      10, feel free to swap them for Arrays, as I don't think there's anything
      *      else in here that necessitates FP10.
      *  
      */



      import flash.net.URLLoader;
      import flash.net.URLRequest;
      import flash.net.URLVariables;

      import flash.events.Event;
      import flash.events.EventDispatcher;
      import flash.events.IOErrorEvent;

      import com.ctrloptcmd.string.URLValidator;

   public class TwitterPipe extends EventDispatcher {

         private var request          : URLRequest;
         private var variables      : URLVariables;
         private var loader          : URLLoader;

         private var txml             : XML;
         private var urlvalidator   : URLValidator;

         private var ignoreReplies    : Boolean;
         private var userID          : String;

         public var tweets            : Vector.<object>;

         public static const FAILWHALE : String = "failwhale";
         public static const FREEBIRD : String = "freebird";


      public function TwitterPipe (_userID : String, _ignoreReplies : Boolean = true) {

            ignoreReplies   = _ignoreReplies;
            userID          = _userID;

            variables          = new URLVariables();
            variables._render = "rss";
            variables.twitter = userID;

            request = new URLRequest("http://pipes.yahooapis.com/pipes/pipe.run?_id=4b85031723ba7785e277add01b0169c5&_render=rss&twitter="+userID);
            request.data = variables;

            loader = new URLLoader();
            loader.addEventListener(Event.COMPLETE, onLoadComplete);
            loader.addEventListener(IOErrorEvent.IO_ERROR, onLoadIOError);
            loader.load(request);

      }


      private function onLoadComplete(e:Event) : void {
         if (loader.data) {
            tweets = new Vector.</object><object>();
            urlvalidator = new URLValidator();
            txml = new XML(loader.data);
               for each (var xTweet:XML in txml..item..description.text()) {
                  var sTweet : String = xTweet.toString();
                  var tweet : Object = {};
                     tweet.raw = sTweet;
                     tweet.chopped = sTweet.substr(sTweet.indexOf(":") + 2);
                     tweet.linked = urlvalidator.tag(sTweet);
                     tweet.choppedAndLinked = urlvalidator.tag(sTweet.substr(sTweet.indexOf(":") + 2));

                     if(sTweet.indexOf("@") > -1)
                        tweet.friendly = true;
                     else
                        tweet.friendly = false;

                     if(!ignoreReplies)
                        tweets.push(tweet);
                     else if (ignoreReplies && !tweet.friendly)
                        tweets.push(tweet);
            }
               this.dispatchEvent(new Event(FREEBIRD));
         }
      }  

      public function getTweets(): Vector.</object><object>  {
         return tweets;
      }

      private function onLoadIOError(ioe : IOErrorEvent) : void {
               this.dispatchEvent(new Event(FAILWHALE));
      }


      }

}

So there you go. Minor functionality improvements but infinitely more readable and well-structured.

Possibly related posts:

  1. Getting Flash and Twitter to play nice. Attention! This code was written by a far less awesome...
  2. ActionScript 3 URL validator class Fairly robust AS3 utility class for evaluating, parsing and tagging...
  3. Up Up Down Down Left Right Left Right B A While showering last night (this is usually when ideas and...
  4. Tracing to Firebug in AS3 I realize that I’m late to the party with this,...
  5. Capture key sequences in ActionScript 3. AKA The Konami Comeback. Lately the internet has had a wave of sites using...

25 Comments

  1. Chad
    Posted April 5, 2009 at 18:59 | Link

    Hi, I’m trying to get my twitter feed to display on my new portfolio site that i’m building, but have no idea how to use this code. i’m kinda new to AS3. Could you tell me the steps to get this to work in flash? i’m completely lost. I’ve tried a few things, but I just get errors. thanks.

  2. Martin
    Posted April 5, 2009 at 21:36 | Link

    Well. You will need some ActionScript skills to make use of this, but let me break it down for you.

    1. Import the class:

    1
    import com.ctrloptcmd.twtter.TwitterPipe

    2. Instantiate the TwitterPipe:

    1
    var twitterPipe : TwitterPipe = new TwitterPipe(YOUR_USER_ID);

    3. Listen for the “complete” event:

    1
    twitterPipe.addEventListener(TwitterPipe.FREEBIRD, tweetsLoaded);

    4. Create the “tweetsLoaded” function and get the tweets:

    1
    2
    3
    function tweetsLoaded(e:Event) : void {
    myTwitterVector = twitterPipe.getTweets();
    }

    This’ll give you a vector with all the tweets as objects. You can now access your tweets through these objects with the keys “raw”, “incognito” and “choppedAndLinked”. If you are planning on publishing for Flash Player 9 you will have to change all the Vectors to Arrays. That is, change:

    1
    Vector.<Object>

    to

    1
    Array

    wherever you see it throughout the code.

  3. Will
    Posted May 14, 2009 at 13:50 | Link

    Hi Martin, first of all thanks for the great resource, it’s really difficult to find a good solution for twitter/as3 integration.

    I have a question regards targeting flash player 9 though…

    I can get it all to work when published for fp10, but I really need to get it to work in fp9. I therefore followed your instructions and swapped out all the “Vector.” with “Array”, however when I try publishing, I get the error “1086: Syntax error: expecting semicolon before lessthan.

  4. Will
    Posted May 14, 2009 at 14:36 | Link

    My bad! feel a bit stupid now… I just replaced everything from “Vector” to the “>” with Array and it works fine. Thanks!

  5. Martin
    Posted May 14, 2009 at 16:02 | Link

    Glad to hear you got it working :)

  6. Will
    Posted May 14, 2009 at 17:13 | Link

    Ok, I’m sorry about this… looks like I got ahead of myself again. 3rd time lucky I hope.

    Everything was working fine locally, then I uploaded to my server and the tweets are not loading. On closer inspection, safari tells me that there is one error in opening the page

    “http://pipes.yahoo.com/crossdomain.xml is not found”

    Do you know how this can be resolved? I guess it’s not a crossdomain issue on my server?
    thanks again

  7. Martin
    Posted May 15, 2009 at 12:48 | Link

    Gah… It seems Yahoo made the same move as Twitter did originally; Namely blocking access from Flash.

    At least they let us get to the data via a different URL. Change line 80 in the script as I have updated it above and it should work.

    The new line should read:

    1
    request = new URLRequest("http://pipes.yahooapis.com/pipes/pipe.run?_id=4b85031723ba7785e277add01b0169c5&_render=rss&twitter="+userID);
  8. Will
    Posted May 15, 2009 at 14:49 | Link

    You are a LEGEND. I can’t thank you enough for this – I’ve been tearing my hair out for days trying to figure out how to get twitter into my current project and this has been a lifesaver.

    The ONE thing that i’m sure is simple to fix is the fact that the twitter feed in my app is now actually yours, and not the ID that I put into my AS. Is it something to do with the default ID setting in the yahoo pipe?

    I tried making a copy of your yahoo pipe, entering my ID as the default, then linking to this in the TwitterPipe class, but somehow the beginning of each of my tweets is now cut off. It works perfectly with your original pipe (but with your tweets). Weird! I’m SO close, but not quite there yet…

  9. Martin
    Posted May 15, 2009 at 16:39 | Link

    No, no apparently that’s my fault.

    At the moment I haven’t got the time to properly figure out why, but see if it helps if you just delete the lines

    1
    2
    variables._render = "rss";
    variables.twitter = userID;

    from TwitterPipe.as

    Seems I’m going to have to clean up this a bit but that worked for me. Oh, and you have to make sure the line

    1
    pipe = new TwitterPipe("YOUR_TW_ID");

    actually has your twitter ID rather than mine.

    Bah. I’ll sit down and clean this thing up again one of these days. What’s with all the hate on Flash anyways!

  10. Will
    Posted May 15, 2009 at 18:16 | Link

    THANK YOU!! I had been staring at the code far too long to work out that I simply had to get rid of those lines. Works like a beauty.

    I think I might be able to stop pestering you now! Thanks again for all the help.

  11. Martin
    Posted May 15, 2009 at 19:19 | Link

    It’s no trouble man. Thanks for pointing out the problems rather than just moving along.

    Your site is looking to be pretty awesome. :)

  12. Will
    Posted May 16, 2009 at 01:24 | Link

    Thanks! In case you were wondering, here is the twitter feed in action. http://www.cooperativestudios.com. (the client hasn’t really started posting yet so there’s not too much to see atm)

    The site is just about finished, the twitter integration was the final touch…

  13. Tom
    Posted May 18, 2009 at 17:58 | Link

    Hi,

    This may sound a bit stupid, but how do I implement this? I’m new to AS3 so still getting used to having the code externally. Up until now I’ve spent today trying to use another set of code that has an mc in a swf which is referenced by an external .ac file, but that wouldn’t work due to crossdomain issues. For this do I just have to create a dynamic text box, label it correctly and point it to the Main.ac file too?

    Thanks, and sorry if this is a really stupid question..

  14. Martin
    Posted May 19, 2009 at 08:57 | Link

    What this code does is retrieve an d parse the tweets and then store them in a Vector (or an Array).

    That means that the Tweets doesn’t have any visual representation automatically. You would have to fetch the values of the Vector to populate your TextField, like so:

    1
    2
    3
    4
    5
    6
    var pipe : TwitterPipe = new TwitterPipe("200523");
          pipe.addEventListener(TwitterPipe.FREEBIRD, doStuff);

    function doStuff(e:Event) : void {
    myTextField.text = pipe.getTweets()[1];
    }

    Have a look at the sample code in the .zip downloadable.

  15. danya
    Posted July 16, 2009 at 21:45 | Link

    Thank you thank you thank you.

    I successfully integrated a twitterfeed into my client’s AS3 Flash site. Sigh of relief.

  16. Martin
    Posted July 18, 2009 at 12:10 | Link

    Happy to be of assistance.

    Just remember that either Yahoo or Twitter could theoretically pull the plug on this solution at any time, so you might want to include a disclaimer in your contract. I wouldn’t worry too much though. Yahoo still hasn’t gotten around to taking down geocities. :)

  17. Todd
    Posted July 23, 2009 at 01:40 | Link

    Hi Martin- Thanks for the source on this. Is there anyway you’d consider throwing together a sample display fla for this? I am admittedly more of a designer-developer than pure developer, but have decent AS skills (or so I thought)… even after going through your source, and looking through the comment strings, I am at a total loss for what to do next after:

    import Main

    …adding what you suggest in comment 14 give me a bunch of errors (1046, 1180, 1120) referencing TwitterPipe

    Even if I could see a line of script that just traces the Vector object or Array, that would be huge. Thanks man!!

  18. Martin
    Posted July 23, 2009 at 21:14 | Link

    @Todd You’re not supposed to import the Main.as, just define it as the document class of your .fla.

    The Main.as included is just a usage example and doesn’t really do much except trace out Tweets.

    Give it a whirl. Let me know if you need some more help and I’ll try to do what I can.

  19. Martin
    Posted July 23, 2009 at 21:24 | Link

    Oh why not. Here‘s a simple example that’ll cycle through tweets in a TextField on stage when you click.

  20. Dan
    Posted September 18, 2009 at 21:34 | Link

    Hey Martin,
    Just wanted to say a big “Thanks!” for this class. It’s been very helpful. I had another solution running on my site, but it began working very strangely due to Twitter’s crossdomain restrictions. For now, this solution seems to be working just dandy.

    I converted it into a working FP9 version (using Arrays, like you suggested), and I also extended it a bit to add a couple more values to the tweet object (publish date, and status URL).

    I noticed one other issue. You mentioned “chopped” as a return formatting type. But it appears that it’s named “incognito” instead of “chopped”. Small issue, but it might confuse some peeps out there…

    Anyways like I said, THANK YOU for getting me rolling in the right direction.

    Here’s what the loop looks like now:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    for each (var xTweet:XML in txml..item) {
       var sDate  : String = xTweet.pubDate.text().toString();
       var sLink  : String = xTweet.link.text().toString();
       var sTweet  :      String = xTweet.description.text().toString();
       var tweet : Object = {};
       tweet.raw = sTweet;
       tweet.incognito = sTweet.substr(sTweet.indexOf(":") + 2);
       tweet.linked = urlvalidator.tag(sTweet);
       tweet.choppedAndLinked = urlvalidator.tag(sTweet.substr(sTweet.indexOf(":") + 2));
       tweet.pubDate = sDate;
       tweet.statusLink = sLink;
                 
       if(sTweet.indexOf("@") &gt; -1)
         tweet.friendly = true;
       else
         tweet.friendly = false;
                 
       if(!ignoreReplies)
         tweets.push(tweet);
       else if (ignoreReplies &amp;&amp; !tweet.friendly)
         tweets.push(tweet);
       }
  21. Martin
    Posted September 22, 2009 at 11:10 | Link

    @Dan Ah. Seems I let some legacy code sneak it’s way back in there.

    Thanks for pointing that out for me. :) I corrected in the code above.

  22. Anthony
    Posted October 12, 2009 at 20:15 | Link

    Awesome work…I can get it working locally, but I’ve been unable to get it up and running, once I upload to the server.

  23. vicky
    Posted February 18, 2010 at 13:36 | Link

    Haiii…thanks for the class you share….
    very awesome work…..
    but…one question….
    how long did the twitter update the feed

    on my web site it takes hours to get the newest twitter update,,,, any suggestion

    big thanks,
    vicky

  24. Martin
    Posted February 18, 2010 at 14:51 | Link

    That sounds strange. It updates in a few seconds here.

  25. James
    Posted June 10, 2010 at 20:00 | Link

    Thanks a lot for your work – it is great. I would not have had a clue how to do it!

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*