#!/usr/bin/env python

# This script reads in a scrobbler log file and submits the data
# to last.fm. You need to give it at least the -u (username) and
# -p (password) options. It currently has no configuration file,
# so you should probably just set up a alias to use it:
# # to submit a scrobble file
# alias sblog='./scroblog -u myfmusernme -p mypassword'
#
# To install it - just copy this file and scrobbler.py to the same
# folder. Easy, wasn't it?
#
# By default, it reads the .scrobbler.log file in the current folder
# and doesn't keep any state info, so you have to do it yourself.
# I periodically move the .scrobbler.log file from my Sansa e260
# .rockbox folder to here, run scroblog, and then delete the log file.
#
# The list of options:
#  -u/--username : the last.fm profile name. Required
#  -p/--password : the profile's password. Required
#  -f/--filename : the full path to the scrobbler log file to read. The
#                  default is './.scrobbler.log'
#  -q/--queue    : max number of records to queue up before submitting the
#                  whole bunch. Default is 10. This is so the last.fm
#                  servers don't feel like they are under attack, so don't
#                  make this number too small. Too big and you might lose
#                  some info if there is a problem with the data
#                  ** -q is currently unimplemented, as scrobbler.py does an
#                  ** automatic flush at 5 records. I don't know if that is
#                  ** a good thing or not, so I'll wait
#  -t/--timezone : scroblog currently ignores the timezone field in the
#                  .scrobbler.log file, because my Sansa says it is Unknown,
#                  so I'm not sure what the format is. The timestamp in the
#                  file is localtime, so we need to know what to add or
#                  subtract to this to get UTC (GMT). The default is to
#                  use Python's timezone value, which should work unless
#                  you are running this on a computer that is in a
#                  different timezone than the one you have your MP3 player
#                  set to. It is the number of seconds to add to the
#                  localtime found in the log file in order to get a UTC
#                  timestamp. For instance, for US Eastern Daylight Saving
#                  time, this value is 18000.
#

# Documentation used:
#  scrobbler.py - http://exhuma.wicked.lu/projects/python/scrobbler
#  .scrobbler.log - http://www.audioscrobbler.net/wiki/Portable_Player_Logging
#  audioscrobbler api - http://www.audioscrobbler.net/development/protocol/

import string
import scrobbler
import sys
import getopt
import datetime, time

# Version History
#   1.0  Thursday, January 31 2008 : Released to the wild.
# Jonathan Arnold jdarnold@buddydog.org
#  http://freebsd.amazingdev.com - My openSUSE blog (no, really)
#  http://www.linuxbraindump.org - A Linux blog I write for
#  http://trifle.vox.com - my personal blog
#   1.1 Thursday, February 14 2008
#       - Fix some more encoding bugs
#       - removed the -q option
#
# scroblog is released to the public domain. It doesn't guarantee
# to do anything correctly but if it doesn't work, or if you have any
# ideas for features or code changes, please drop me a line.
#
scroblog_version = "1.1"

def usage() :
    print "Usage: ", sys.argv[0], " -u/--username name -p/--password pwd [-f/--filename scrobler_log_filename(.scrobbler.log) -q/--queue num_records_to_queue_before_send(40) -t/--timeoffset secs_to_utc ]"

username = ''
password = ''

scrobbler_log_name = './.scrobbler.log' # name of portable player scrobble file
flush_count = 10      # how many records to queue up before sending to last.fm
utcoff = time.timezone # offset to add to get to UTC for each timestamp

try :
    (opts,args) = getopt.getopt(sys.argv[1:],"u:p:f:q:t:",
                                ('username=','password=','filename=', 'queue=','timeoffset='))

    for opt in opts:
        if opt[0] == '-u' or opt[0] == '--username':
            username = opt[1]
        elif opt[0] == '-p' or opt[0] == '--password':
            password = opt[1]
        elif opt[0] == '-f' or opt[0] == '--filename':
            scrobbler_log_name = opt[1]
        elif opt[0] == '-q' or opt[0] == '--queue':
            flush_count = int(opt[1])
        elif opt[0] == '-t' or opt[0] == '--timeoffset':
            utcoff = int(opt[1])

    if username == '' or password == '':
        print "Missing username/password"
        usage()
        exit(1)

    scrobbler_log = open(scrobbler_log_name)

    scrobbler.login( username, password )

    rec_count = 0
    scrob_count = 0
    
    for aline in scrobbler_log:
        if aline[0] != '#':
            # turn the line into a unicode line, as there may be weird characters in it
            line = unicode(aline,'utf8')

            # fields in the scrobbler log file are separated by tabs. There
            # should be 6 of them:
            # 0 - artist name
            # 1 - album name (optional)
            # 2 - track name
            # 3 - track position on album (optional)
            # 4 - song duration in seconds
            # 5 - rating (L if listened at least 50% or S if skipped)
            # 6- unix timestamp when song started playing
            #
            fields = string.split(line,'\t')

            # L means it was listened to
            if fields[5] == 'L':
                print "Scrobbling '%s' ('%s') by '%s'" % (unicode(fields[2]).encode('ascii','replace'),
                                                          unicode(fields[1]).encode('ascii','replace'),
                                                          unicode(fields[0]).encode('ascii','replace'))

                # add in utc offset, as the time field is in localtime
                utctime = int(fields[6]) + utcoff

                # Now add it to the pending queue
                scrobbler.submit( fields[0], fields[2], utctime, 'P', '', fields[4],
                                  fields[1], fields[3] )

                scrob_count = scrob_count + 1

                rec_count = rec_count + 1
#
# Remove this as scrobbler does it's own flush
#
#                if rec_count > flush_count:
                    # send the info to last.fm every so often so as not to flood it
#                    scrobbler.flush()
#                    rec_count = 0

    scrobbler_log.close()

    if rec_count > 0:
        # and one last flush
        scrobbler.flush()
        print "Sent %d records to last.fm/user/%s" % (scrob_count, username)

except getopt.GetoptError, e:
    print "Bad parameter: ", e.msg
    usage()
    
except Exception,e:
    print "Fatal Error found: ", e.message
    
