Adding Last Fm Plays from textfile 0.1

Download and get help for different MediaMonkey Addons.

Moderators: Peke, Gurus

m0nkiii
Posts: 15
Joined: Mon Feb 26, 2007 1:48 pm
Location: Swiiiiden

Adding Last Fm Plays from textfile 0.1

Post by m0nkiii » Fri Mar 02, 2007 1:57 pm

Warning! This is my first script so take a backup of your database. Use at your own risk! ;)

Got the idea from this thread: http://www.mediamonkey.com/forum/viewto ... highlight=

And got some help from this thread:
http://www.mediamonkey.com/forum/viewto ... dfakeplays

I'm new at this but I thought it would be fun to make a script so I did :)
The code might not be the best written but it works for me.

I thought about doing a script that could read the xml-files from this site and add all weeks plays:
http://www.audioscrobbler.net/data/webservices/
But this one was easier for the first script :P

Code: Select all

'Place in .ini:
'[AddingLastFM]
'FileName=AddingLastFM.vbs
'ProcName=AddingLastFM
'Order=29
'DisplayName=&Adding Last FM plays
'Description=Adding plays from Last FM
'Language=VBScript
'ScriptType=0

Sub AddingLastFM

	Set objFilesystem = CreateObject("Scripting.FileSystemObject")
	' The path to your textfile
	Set objMyFile = objFilesystem.GetFile("D:\Program Files\MediaMonkey\Scripts\songs.txt")
	Set objTextStream = objMyFile.OpenAsTextStream(1)

	' define vars
	Dim Plays, Track, Artist
	
	Dim list, itm, i
	Dim tmpId, tmpPlayed
	Dim strOut
	Dim intPlayCountDiff
	Dim strDummyDate
	Dim qryStats
	Dim mes
					
	' get the list of selected tracks
	Set list = SDB.CurrentSongList
	
	' loop through the textfile
	Do While Not objTextStream.AtEndOfStream
		
		Plays = objTextStream.readline
		Track = objTextStream.readline
		Artist = objTextStream.readline

		' loop through the list
		For i=0 To list.count-1
		  Set itm = list.Item(i)
		  tmpId = itm.ID
		  
		  If itm.artistName = Artist Then
			If itm.title = Track Then		  
				If Plays > 0 Then
					
					' add fake plays
					For x=0 To Plays-1
					    strDummyDate = Now
						strSQL = "INSERT into Played (IdSong, PlayDate) values (" & itm.ID & ",'" & strDummyDate & "')"
						SDB.Database.ExecSQL(strSQL)
					next
										
					strSQL = "select Count(Played.IdSong) AS CountOfPlays from Played where Played.IdSong = " & itm.ID
					Set qryStats = SDB.Database.OpenSQL(strSQL)

					' find out how many plays of this track there have been
					countofplays = qryStats.StringByName("CountOfPlays")
					
					' increase PlayCounter
					SDB.Database.ExecSQL("UPDATE Songs INNER JOIN Artists ON Songs.IDArtist = Artists.ID SET Songs.PlayCounter = "& countofplays &" WHERE Songs.SongTitle = '"& replace(Track,"'","''") &"' AND Artists.Artist = '"&  replace(Artist,"'","''") &"' ")
					
					mes = mes & "||" & itm.title &" - "& itm.artistName & "  (" & countofplays & ") ||"
					
				End If
			End If
		  End If
		Next
	loop
	
	Call SDB.MessageBox(mes,mtInformation,Array(mbOk))
	
	objTextStream.Close
	
End Sub
It goes through the textfile and the songs in your current songlist.
The textfile should look like this to work:

Code: Select all

164
Call Me When You're Sober
Evanescence
82
The Diary of Jane
Breaking Benjamin
81
Anywhere
Evanescence
78
Hard Rock Hallelujah
Lordi
77
Broken (Acoustic)
Seether
77
Bones
The Killers
72
The Diary Of Jane (Acoustic Version)
Breaking Benjamin
Problems I haven't fixed:
- If you have two songs with the same title and artist it will increase both playcounts.

Mthrsuperior
Posts: 178
Joined: Sun Dec 03, 2006 3:40 pm
Location: Victoria BC

Post by Mthrsuperior » Fri Mar 02, 2007 3:32 pm

wow!

sorry if I'm hijacking here BUT:
My dream is to be able to ditch my iPod firmware and use http://www.rockbox.org/ on my iPod.
What keeps me from doing this is that Rockbox doesn't keep a play count database that MM can read and this is important to me as all my playlists are dependant on play counts and last played dates.
Rockbox does however make a txt file of songs played for uploading to last.fm.

I'm looking at this script (and I know nothing about scripting) and I wonder:
Is it possible to have a script that reads this Rockbox txt file and updates MM playcounts and last played dates?
Image

Jugdish
Posts: 13
Joined: Tue Feb 27, 2007 12:19 pm

Post by Jugdish » Fri Mar 02, 2007 6:11 pm

Well sadly I do not know much about VBScript, but I do know Perl :-P
So here's a Perl script I made that will parse through all the weekly charts for a last.fm user using the web services, adding up all the playcounts and then outputting them to a "songs.txt" file in the same format that your script uses, so that your script can be run on the file. Just give your last.fm username as the first parameter to the script.
Hopefully someone may find this useful.

Code: Select all

use XML::DOM;
use strict;

my $chartlisturl = 'http://ws.audioscrobbler.com/1.0/user/<username>/weeklychartlist.xml';
my $weeklycharturl = 'http://ws.audioscrobbler.com/1.0/user/<username>/weeklytrackchart.xml?from=<start>&to=<end>';
my %trackplays;

my $username = $ARGV[0] || die "Please supply your last.fm username as an argument.";
my $parser = new XML::DOM::Parser;

my $url = $chartlisturl;
$url =~ s/<username>/$username/g;
my $chartlistdoc;
eval { $chartlistdoc = $parser->parsefile($url); };
die "Could not retrieve page $url" unless $chartlistdoc;
sleep 1;

die "Could not find root node <weeklychartlist>" unless (my $rootlist = $chartlistdoc->getElementsByTagName("weeklychartlist",0))->getLength;
my $chartlist = $rootlist->item(0)->getElementsByTagName("chart",0);
print "Found a total of ".$chartlist->getLength." weeks to parse.\n";
for (my $i = 0; $i < $chartlist->getLength; $i++) {
  print "Parsing week ".($i+1)." of ".$chartlist->getLength."...";
  my $start = $chartlist->item($i)->getAttribute("from") || die "ERROR: Could not find 'from' attribute in <chart> node.";
  my $end = $chartlist->item($i)->getAttribute("to") || die "ERROR: Could not find 'to' attribute in <chart> node.";
  
  $url = $weeklycharturl;
  $url =~ s/<username>/$username/g;
  $url =~ s/<start>/$start/g;
  $url =~ s/<end>/$end/g;
  my $weeklychartdoc;
  eval { $weeklychartdoc = $parser->parsefile($url); };
  die "Could not retrieve page $url" unless $weeklychartdoc;
  sleep 1;

  die "Could not find root tag <weeklytrackchart>" unless ($rootlist = $weeklychartdoc->getElementsByTagName("weeklytrackchart",0))->getLength;
  my $tracklist = $rootlist->item(0)->getElementsByTagName("track",0);
  my $totalplays = 0;
  for (my $j = 0; $j < $tracklist->getLength; $j++) {
    die "Could not find <artist> tag" unless (my $artistlist = $tracklist->item($j)->getElementsByTagName("artist",0))->getLength;
    die "Could not find <name> tag" unless (my $songlist = $tracklist->item($j)->getElementsByTagName("name",0))->getLength;
    die "Could not find <playcount> tag" unless (my $playcountlist = $tracklist->item($j)->getElementsByTagName("playcount",0))->getLength;

    die "Could not get text from <artist> tag"
      unless $artistlist->item(0)->hasChildNodes && (my $artisttext = $artistlist->item(0)->getFirstChild)->getNodeType == TEXT_NODE;
    die "Could not get text from <name> tag"
      unless $songlist->item(0)->hasChildNodes && (my $songtext = $songlist->item(0)->getFirstChild)->getNodeType == TEXT_NODE;
    die "Could not get text from <playcount> tag"
      unless $playcountlist->item(0)->hasChildNodes && (my $playcounttext = $playcountlist->item(0)->getFirstChild)->getNodeType == TEXT_NODE;

    my $artist = $artisttext->getData;
    my $song = $songtext->getData;
    my $playcount = $playcounttext->getData;

    if (exists $trackplays{$artist}) {
      $trackplays{$artist}{$song} += $playcount;
    } else {
      $trackplays{$artist} = { $song => $playcount };
    }
    $totalplays += $playcount;
  }
  print "got $totalplays plays\n";
}

# print out hash
open(OUTFILE,'>songs.txt') || die "Could not open songs.txt";
my @artists = sort(keys %trackplays);
for my $artist (@artists) {
  my @songs = sort(keys %{$trackplays{$artist}});
  for my $song (@songs) {
    print OUTFILE "$trackplays{$artist}{$song}\n$song\n$artist\n";
  }
}

Mthrsuperior
Posts: 178
Joined: Sun Dec 03, 2006 3:40 pm
Location: Victoria BC

Post by Mthrsuperior » Fri Mar 02, 2007 6:41 pm

Jugdish wrote:Just give your last.fm username as the first parameter to the script.
I'm at work right now but boy am I ever excited about this :D
I hope it works.

Um, for us Luddites: where is "the first parameter to the script"?
Does this mean I replace everywere it says "username" with my actual username or do I just need to do it on the first line??
Image

Jugdish
Posts: 13
Joined: Tue Feb 27, 2007 12:19 pm

Post by Jugdish » Fri Mar 02, 2007 6:51 pm

Mthrsuperior wrote:where is "the first parameter to the script"?
When you call the script from the command line, you need to give your username as the first argument. For example, suppose you saved the script into a file called "lastfmplaycounts.pl", then you would enter this at the command line:

Code: Select all

perl lastfmplaycounts.pl MyLastFMUsername
Note that you must have a Perl interpreter installed on your computer to do this. If you're using Windows, you can download one here.

m0nkiii
Posts: 15
Joined: Mon Feb 26, 2007 1:48 pm
Location: Swiiiiden

Post by m0nkiii » Fri Mar 02, 2007 6:52 pm

Mthrsuperior wrote:
Jugdish wrote:Just give your last.fm username as the first parameter to the script.
I'm at work right now but boy am I ever excited about this :D
I hope it works.

Um, for us Luddites: where is "the first parameter to the script"?
Does this mean I replace everywere it says "username" with my actual username or do I just need to do it on the first line??
Perl... nice :)

If I understand it right you don't run it through MM.
You have to have Perl installed and run it in the console or something.
Like this : perl lastfmscript username

Edit: grr I was a bit late, but right :)

Mthrsuperior
Posts: 178
Joined: Sun Dec 03, 2006 3:40 pm
Location: Victoria BC

Post by Mthrsuperior » Fri Mar 02, 2007 8:50 pm

Thanks (for both scripts)

I understand now.
I'll play around tomorrow after I shake off the work week tonight.
:lol:
Image

urlwolf
Posts: 179
Joined: Sun Mar 05, 2006 6:58 am

Post by urlwolf » Wed Feb 06, 2008 11:37 am

This is a great idea.
I always wanted to have playcounts synchronous with last.fm (I have >50.000 playcounts there!).

Unfortunately looking at the feeds, it looks like it's impossible to retrieve the entire playcount history for an user, only the last week.

Is that the case?
Has anyone retrieved the entire list?

Thanks
Image

urlwolf
Posts: 179
Joined: Sun Mar 05, 2006 6:58 am

Post by urlwolf » Wed Feb 06, 2008 11:44 am

Here's a possible hack:

Grab playcounts into itunes, then import counts from itunes to MM (I think I saw that offered somewhere, maybe when installing MM3?).

This perl script will update your itunes db with last.fm counts.

http://bios.alterlinks.fr/index.php?opt ... &Itemid=63
Image

Spazz
Posts: 243
Joined: Tue Jan 11, 2005 9:49 pm

Post by Spazz » Wed Feb 06, 2008 3:18 pm

Unfortunatly that script only somewhat works for me, it only sees 119 playcounts from last.fm :(

edit:: script bug looks like, I grabbed the previous version and it looks to be working just fine, apparently it was only grabbing the very first week of plays and that was it.

This could take awhile @ well over 50,000 plays.

I can't wait to see how autorateaccurate deals with this information :)
Image

m0nkiii (not logged in)

Post by m0nkiii (not logged in) » Wed Feb 06, 2008 4:23 pm

This row in the perl-script takes all weeks you have scrobbled:
my $chartlisturl = 'http://ws.audioscrobbler.com/1.0/user/< ... rtlist.xml';

This row takes a week at a time:
my $weeklycharturl = 'http://ws.audioscrobbler.com/1.0/user/< ... t>&to=<end>';

I think the limit per week is 500 artists. So some tracks may not be included.
But it works to get almost all playcounts.

Spazz
Posts: 243
Joined: Tue Jan 11, 2005 9:49 pm

Post by Spazz » Wed Feb 06, 2008 5:34 pm

Hmmm.. it finds all my tracks on last.fm but won't write to the library, annoying.
Image

Spazz
Posts: 243
Joined: Tue Jan 11, 2005 9:49 pm

Post by Spazz » Thu Feb 07, 2008 2:54 am

Alright, I used the perl script posted here to make the text file but I get an error whenever I try to use it. I am selecting a series of songs and then activating the script through the tools menu. I get this error.

"There was a problem querying the database:
Error executing SQL " UPDATE Songs INNER JOIN Artists ON Songs.IDArtist =Artists.ID Set Songs.PLaycounter = 5 WHERE Songs.Songtitle = '...but home is nowhere' AND Artists.Artist = 'AFI'
" : near "INNER" : syntax error (1, 1)"

If I have nothing selected and I activate the script, I get a blank information box with a blank button to press which does nothing. :(

Any ideas on what's causing this?

::edit:: A second error pops up directly after the first referring to line 62, column 15
Image

Spazz
Posts: 243
Joined: Tue Jan 11, 2005 9:49 pm

Post by Spazz » Sun Feb 10, 2008 5:19 pm

No idea what's wrong? :(
Image

m0nkiii
Posts: 15
Joined: Mon Feb 26, 2007 1:48 pm
Location: Swiiiiden

Post by m0nkiii » Sun Mar 16, 2008 6:59 am

Spazz wrote:Alright, I used the perl script posted here to make the text file but I get an error whenever I try to use it. I am selecting a series of songs and then activating the script through the tools menu. I get this error.

"There was a problem querying the database:
Error executing SQL " UPDATE Songs INNER JOIN Artists ON Songs.IDArtist =Artists.ID Set Songs.PLaycounter = 5 WHERE Songs.Songtitle = '...but home is nowhere' AND Artists.Artist = 'AFI'
" : near "INNER" : syntax error (1, 1)"

If I have nothing selected and I activate the script, I get a blank information box with a blank button to press which does nothing. :(

Any ideas on what's causing this?

::edit:: A second error pops up directly after the first referring to line 62, column 15
Maybe the song: Songs.Songtitle = '...but home is nowhere' AND Artists.Artist = 'AFI' doesn't exist in your database, not exactly those letters ?
It's not the perlscript that's the problem ? You get the correct txt-file from it ?

Post Reply