An exercise in correlation - playing MySpace music via iTunes

7 February, 2008 – 8:00 pm

[UPDATE] Mr Gecko, has since implemented this logic and sorted out downloading woes (for u US folk) in a nifty little OSX app here

In between contracts, I have been practicing the art of correlation by scraping data from public web sites. The legality of this is perhaps a little unclear so I’ve aimed not to infringe on copyrights by not storing the content, but just changing the way in which content is displayed from a live site. One such example was to open up MySpace songs via iTunes, rather than using the flash player MySpace provide. This required a fair analysis of web server to client traffic, in order to piece together the necessary conversation required to achieve all this via Perl …
itunes-myspace

My tools of choice were Firefox with the LiveHTTP Headers plugin to see what’s happening between the browser and server, tcpdump to catch those harder to find pieces of information, sometimes critical in determining how to correlate necessary data, and Perl to faciliate the automation, namely using the WWW::Mechanize module.

So for an exercise in correlation, I chose to play content from MySpace. Basically what I wanted to do was figure out how to create my own standalone player in order to play MySpace music via iTunes …

I’ve come up with the following script, which takes into account the dynamic nature of MySpace content (as well as all the necessary tokens and so forth) in order to play back content … This has been crafted for a Mac OSX platform. You will need to install the necessary modules via cpan for your own installation in order for it to work.

An example of the script running is shown below:

Download video …


#!/usr/bin/perl -w
use WWW::Mechanize;    
use Getopt::Long;
use Time::HiRes qw(gettimeofday tv_interval);
use Mac::iTunes;
 
GetOptions(
  "username:s"     =>\$opts{username},
  "download:s"     =>\$opts{download},
  "songname:s"     =>\$opts{songname},
  "debug!"         =>\$opts{debug}
);
 
{
    # suppress all stderr warnings
    local $SIG{__WARN__}=sub{};
 
    # make stdout hot
    $| = 1;
      
    # get opts
    my $url          = "http://www.myspace.com/".$opts{username}  ||
    "http://www.myspace.com/djkraftykuts";
    my $download    = $opts{download} || "/tmp";
    my $songname    = $opts{songname};
    my $debug       = $opts{debug};
    
    # init new mech
    my $mech        = WWW::Mechanize->new(cookie_jar => {});
    $mech->agent_alias( 'Linux Mozilla' );
    
    print "\nInitializing :\n------------–\n";
    # get band id
    $result = &getParse($url);
    $bandid = ($result =~ /DisplayFriendId":(.+?),/g) ? $1 : undef;
    print "\t\tBand ID      :\t$bandid\n" if $bandid;
    
    # enum standalone player
    $url    = "http://collect.myspace.com/music/popup.cfm".
    "?num=0&time=undefined&fid=$bandid&uid=1";
    $result = &getParse($url);
    $url    = ($result =~ /EMBED src="(.+?)"/g) ? $1 : undef;
    print "\t\tPlayer       :\tFound\n" if $url;
    
    # launch standalone player
    $result = &get($url);
    print "\t\tPlayer       :\tLaunched\n" if($result->is_success);
    
    # cross domain
    $url = "http://mediaservices.myspace.com/crossdomain.xml";
    $result = &get($url);
    print "\t\tXDomain      :\tReceived\n" if($result->is_success);
 
    # css
    $url = "http://collect.myspace.com/music/player.css";
    $result = &get($url);
    print "\t\tCSS          :\tReceived\n" if($result->is_success);
 
    # xml
    $url = "http://mediaservices.myspace.com/services/media/".
    "musicplayerxml.ashx?b=$bandid";
    $result = &getParse($url);
    print $result if $debug;
    my $n=0;
    $result =~ s/<song bsid/\n<song bsid/g;
    while ($result =~ m/<song(.+?)\/>\n/g) {                            
        $xml      = $1;                                                                        
        $bsid     = ($xml =~ /bsid="(.+?)"/g)     ? $1 : undef;
        $title    = ($xml =~ /title="(.+?)"/g)    ? $1 : undef;
        $songid   = ($xml =~ /songid="(.+?)"/g)   ? $1 : undef;
        $plays    = ($xml =~ /plays="(.+?)"/g)    ? $1 : undef;
        $songurl  = ($xml =~ /url="(.+?)"/g)      ? $1 : undef;
        $durl     = ($xml =~ /durl="(.+?)"/g)     ? $1 : undef;
        $token    = ($xml =~ /token="(.+?)"/g)    ? $1 : undef;
        $i        = ($songurl =~ /i=(.+)/g)       ? $1 : undef;
        
        $songs{$n} = {
            'bsid'      => $bsid,
            'title'     => $title,
            'songid'    => $songid,
            'plays'     => $plays,
            'songurl'   => $songurl,
            'durl'      => $durl,
            'token'     => $token,
            'i'         => $i
            };
        $n++;    
    }
    print "\t\tXML          :\tParsed\n";
    
    
    # connecting to content
    print "Connecting  :\n------------–\n";
    for(0..$n-1){
        print "\t\tSong         :\t".$songs{$_}{'title'}."\n";
        print "\t\tPlays        :\t".$songs{$_}{'plays'}."\n";
        &getSong($_);
    }
    
    undef $mech;
 
    # subs
    sub getSong {
        # start script timer
        &startTimer();
        
        # mediahitcounter
        $url = "http://mediaservices.myspace.com/services/media/".
        "mediahitcounter.ashx?i=".$songs{$_[0]}{'i'};
        $result = &get($url);
        print "\t\tCounters     :\tUpdated\n" if($result->is_success);
        
        # token
        $url = "http://mediaservices.myspace.com/services/media/token.ashx".
        "?b=$bandid&s=".$songs{$_[0]}{'songid'}."&f=0";
        $result = &get($url);
        print "\t\tTokens       :\tReceived\n" if($result->is_success);
 
        # beacon
        $c = int(rand(99999999));
        $url = "http://lads.myspace.com/music/start_beacon.txt?c=$c";
        $result = &get($url);
        print "\t\tBeacon       :\tUpdated\n" if($result->is_success);
        
        # play song
        if($download) {
            print "\t\tPlaying song :\t";
            $url = $songs{$_[0]}{'durl'}."?bandid=$bandid".
            "&songid=".$songs{$_[0]}{'songid'}.
            "&token=".$songs{$_[0]}{'token'};
            
            print $url if $debug;
            my $controller = Mac::iTunes->controller;
            $controller->open_url( $url );
            
            # use keyboard to control playback
            print "Press 's' to skip song or 'q' to quit ";
            system "stty cbreak < /dev/tty > /dev/tty 2>&1";
            while (($key=getc) ) {
              last if $key eq "s";
              $controller->quit if $key eq "q";
              print "\r\t\tExiting    :\t Complete".
              "                        \n\n" if $key eq "q";
              exit if $key eq "q";
            };
            
            # optional download
            #my $result  = $mech->get( $url, ':content_file' =>
            #"$download/".$songs{$_[0]}{'title'}.".mp3" );
            #die "\tERROR!\n\tGET failed on $url \n"
            #unless $result->is_success;
        }
        
        # end script timer
        &endTimer();
        print "\r\t\tPlaying song :\t[$elapsed secs] elapsed time".
        "                \n\n" if($result->is_success);
        
    }
 
    sub get {
        my $url     = $_[0];
        my $result  = $mech->get( $url );
      warn "\tERROR!\n\tGET failed on $url \n ".$result->content.
      " \n\n" unless $result->is_success;
        return $result;
    }
 
    sub getParse {
        my $url     = $_[0];
        my $result  = $mech->get( $url );
      die "\tERROR!\n\tGET failed on $url \n" unless $result->is_success;
        $result     = $mech->content;
        $result     =~ s/\n//g;
        return $result;
    }
 
    sub startTimer {
        $timer = [gettimeofday];
    }
 
    sub endTimer {
        $elapsed = tv_interval ($timer);
        $elapsed = sprintf("%.4s", $elapsed);
    }
 
};

Share it: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Netscape
  • Reddit
  • Slashdot
  • Technorati
  • YahooMyWeb
  1. 6 Responses to “An exercise in correlation - playing MySpace music via iTunes”

  2. Hello I am needing to ask you some questions about your script because I am making a myspace music downloader for mac os x. If you can contact me at GRMrGecko@gmail.com.

    Thanks,
    Mr. Gecko

    By Mr. Gecko on May 8, 2008

  3. Jump on googletalk and I’d be happy to walk u through the code.

    By Tim on May 8, 2008

  4. If you can send a request to my talk account I will be on
    Account=GRMrGecko@gmail.com

    By Mr. Gecko on May 8, 2008

  5. Oh that is what you meant on the side bar it has

    Chat with Tim Koopmans
    Offline

    ok when you come online I will go and chat with you.

    By Mr. Gecko on May 9, 2008

  6. I’m sorry to bother you, but I really can not find any other to help me on this question:

    I want to build up a video website and want to keep my streaming URL be safty, I know there is a way to use Dynamic URL of media e.g.:
    rtsp://x.x.x.x/VODtest/Backseat_Driver_01_1Mb.wmv?userid=guest&token=0639ad457b8

    But I don’t know where the token comes, can Microsoft windows media server support it? or is there any plugin software on windows media server can provide this dynamic url way?

    By liu on Jul 3, 2008

  7. Sorry forget to give you my mail:
    lyx@konceptusa.com

    ————————————————
    I’m sorry to bother you, but I really can not find any other to help me on this question:

    I want to build up a video website and want to keep my streaming URL be safty, I know there is a way to use Dynamic URL of media e.g.:
    rtsp://x.x.x.x/VODtest/Backseat_Driver_01_1Mb.wmv?userid=guest&token=0639ad457b8

    But I don’t know where the token comes, can Microsoft windows media server support it? or is there any plugin software on windows media server can provide this dynamic url way?

    By liu on Jul 3, 2008

Post a Comment

*
To prove that you're not a bot, enter this code
Anti-Spam Image