Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import mc
- import tracker
- import urllib
- import random
- import base64
- import datetime as dt
- import time
- import simplejson as json
- import re
- import monthdelta as md
- from xml.dom.minidom import parse, parseString
- import jobmanager
- import md5
- import threading
- class MLB(object):
- __module__ = __name__
- __doc__ = '\n Default values\n '
- def __init__(self):
- self.status_error = -2
- self.status_valid = 1
- self.status_invalid = 0
- self.status_missing = -1
- self.send_to_server = True
- self.send_to_history = True
- self.pitches = {'PO': ['Pitchout',
- 'Pitchout'],
- 'AB': ['Automatic Ball',
- 'Automatic Ball'],
- 'AS': ['Automatic Strike',
- 'Automatic Strike'],
- 'CH': ['Changeup',
- 'Changeup'],
- 'CU': ['Curveball',
- 'Curveball'],
- 'FA': ['Fastball',
- 'Fastball'],
- 'FT': ['Two-seam FB',
- 'Fastball (2-seam)'],
- 'FF': ['Four-seam FB',
- 'Fastball (4-seam)'],
- 'FC': ['Cutter',
- 'Fastball (Cut)'],
- 'FS': ['Splitter',
- 'Fastball (Split-finger)'],
- 'FO': ['Forkball',
- 'Forkball'],
- 'GY': ['Gyroball',
- 'Gyroball'],
- 'IN': ['Intentional Ball',
- 'Intentional Ball'],
- 'KC': ['Knuckle Curve',
- 'Knuckle Curve'],
- 'KN': ['Knuckleball',
- 'Knuckleball'],
- 'NP': ['No Pitch',
- 'No Pitch'],
- 'SC': ['Screwball',
- 'Screwball'],
- 'SI': ['Sinker',
- 'Sinker'],
- 'SL': ['Slider',
- 'Slider'],
- 'UN': ['Unknown',
- 'Unknown']}
- self.event_filter = ['Hit By Pitch',
- 'Double',
- 'Home Run',
- 'Single',
- 'Triple',
- 'Batter Interference',
- 'Catcher Interference',
- 'Error',
- 'Fan interference',
- 'Field Error',
- 'Fielder Interference',
- 'Runner Interference',
- 'Double Play',
- 'Grounded Into DP',
- 'Sac Bunt',
- 'Sac Fly',
- 'Sac Fly DP',
- 'Triple Play',
- 'Ejection',
- 'Player Injured',
- 'Pickoff 1B',
- 'Pickoff 2B ',
- 'Pickoff 3B',
- 'Pickoff Error 1B',
- 'Pickoff Error 2B',
- 'Pickoff Error 3B',
- 'Run',
- 'Balk',
- 'Caught Stealing 2B',
- 'Caught Stealing 3B',
- 'Caught Stealing Home',
- 'Caught Stealing DP',
- 'Passed Ball',
- 'Picked off stealing 2B',
- 'Picked off stealing 3B',
- 'Picked off stealing home',
- 'Stolen Base 2B',
- 'Stolen Base 3B',
- 'Stolen Base Home',
- 'Wild Pitch',
- 'Strikeout - DP',
- 'Strikeout - TP',
- 'Sacrifice Bunt DP',
- 'In play, run(s)']
- self.mr_url = 'https://mlb-ws.mlb.com/pubajaxws/bamrest/MediaService2_0/op-findUserVerifiedEvent/v-2.3?%s'
- self.boxee_server = 'http://dir.boxee.tv/apps'
- self.url_base = (self.boxee_server + '/mlb/mlb.php?func=%s&%s')
- self.data_uri = 'http://gdx.mlb.com/components/game/mlb'
- self.realtime_uri = 'http://lwsa.mlb.com/tfs/tfs?file=components/game/mlb'
- self.message_uri = 'http://dir.boxee.tv/apps/mlb/messages.xml'
- self.time_uri = 'http://dir.boxee.tv/apps/mlb/mlbTime.php'
- self.myTracker = tracker.Tracker()
- try:
- self.device_id = mc.GetDeviceId()
- except:
- self.device_id = None
- def request(self, data):
- try:
- self.info('request', 'processing post request to boxee.tv')
- if ((not data) or (str(type(data)) != "<type 'dict'>")):
- return self.raiseError(log='request', error='data passed is not usable. contact support@boxee.tv')
- try:
- params = urllib.urlencode(data)
- except:
- return self.raiseError(log='request', error='data passed is not usable. contact support@boxee.tv')
- http = mc.Http()
- result = http.Post('http://dir.boxee.tv/apps/mlb/mlb.php', params)
- code = http.GetHttpResponseCode()
- http.Reset()
- if ((code != 200) and self.debug('request', ('post returned response code ' + str(code)))):
- pass
- if (result or self.debug('request', 'post return zero bytes')):
- pass
- if ((code == 200) and result):
- self.info('request', 'post was successful')
- response = {'data': result,
- 'code': code}
- return response
- except Exception, e:
- return self.raiseError(log='request', error=e)
- def callService(self, func, values = {}, authenticated = True, content = False):
- try:
- self.info('callservice', ('calling the boxee_mlb service w/%s, authentication/%s' % (func,
- str(authenticated).lower())))
- params = {}
- http_service = mc.Http()
- if authenticated:
- app = mc.GetApp()
- cf = app.GetLocalConfig()
- params['nsfp'] = cf.GetValue('fprt')
- params['nsid'] = cf.GetValue('ipid')
- if values:
- for i in values:
- params[i] = values[i]
- url_base = self.underscore((self.url_base % (func,
- urllib.urlencode(params))))
- query_result = http_service.Get(url_base)
- if (content == 'json'):
- query_result = re.sub('//.*?\n|/\\*.*?\\*/', '', query_result, re.S)
- query_result = json.loads(query_result)
- return query_result
- except Exception, e:
- return self.raiseError(log='callservice', error=e)
- def underscore(self, string):
- return string.replace('_', '%5F')
- def ordinal(self, n):
- if 10 < n < 14:
- return (u'%sth' % n)
- if ((n % 10) == 1):
- return (u'%sst' % n)
- if ((n % 10) == 2):
- return (u'%snd' % n)
- if ((n % 10) == 3):
- return (u'%srd' % n)
- return ('%sth' % n)
- def gameIdToEventURI(self, game_id, realtime = False):
- game_id = game_id.replace('-', '_')
- underscored = game_id.replace('/', '_')
- split = game_id.split('/')
- if realtime:
- return (self.realtime_uri + ('/year_%s/month_%s/day_%s/gid_%s/' % (split[0],
- split[1],
- split[2],
- underscored)))
- return (self.data_uri + ('/year_%s/month_%s/day_%s/gid_%s/' % (split[0],
- split[1],
- split[2],
- underscored)))
- def info(self, func, msg):
- mc.LogInfo(((('@mlb.tv (' + func) + ') ') + str(msg)))
- def debug(self, func, msg):
- mc.LogDebug(((('@mlb.tv (' + func) + ') ') + str(msg)))
- def error(self, func, msg):
- mc.LogError(((('@mlb.tv (' + func) + ') ') + str(msg)))
- def raiseError(self, message = False, log = False, error = False):
- mc.HideDialogWait()
- if (log and error):
- mc.LogError(((('@mlb.tv (' + log) + ') ') + str(error)))
- if message:
- response = message
- else:
- response = 'An error has occurred. Details have been saved in your log. Please notify Boxee support.'
- mc.ShowDialogOk('MLB.TV', response)
- return False
- def getJson(self, url = False, data = False):
- try:
- if url:
- data = mc.Http().Get(url)
- data = re.sub('//.*?\n|/\\*.*?\\*/', '', data, re.S)
- data = json.loads(data)
- return data
- except Exception, e:
- return self.raiseError(log='getjson', error=e)
- def digitsToTimecode(self, digits):
- return ((((digits[0:2] + ':') + digits[2:4]) + ':') + digits[4:6])
- def getCurrentMLBTime(self):
- self.debug('time', 'Getting MLB time...')
- xml = mc.Http().Get(self.time_uri)
- if xml:
- dom = parseString(xml)
- if dom.getElementsByTagName('time'):
- value = dom.getElementsByTagName('time')[0].firstChild.data
- return time.strptime(value, '%d %b %Y %H:%M:%S')
- else:
- self.debug('time', 'Could not retrieve MLB time.')
- return False
- def authenticate(self):
- try:
- content = mc.Http().Get('http://app.boxee.tv/api/get_application_data?id=mlb')
- if content:
- return self.status_error
- else:
- auth_dom = parseString(content)
- email = auth_dom.getElementsByTagName('email')[0].firstChild.data
- account = auth_dom.getElementsByTagName('rand_account')[0].firstChild.data
- post_data = self.request({'func': '_login',
- 'email': email,
- 'pass': account})
- if ((not post_data) or (post_data['data'] == '0')):
- Exception('post request return false')
- cf = mc.GetApp().GetLocalConfig()
- response = self.getJson(data=post_data['data'])
- response = response.get('identity')
- code = str(response.get('code'))
- if ((code != '1') and self.info('authenticate.code', code)):
- cf.Reset('fprt')
- cf.Reset('ipid')
- cf.Reset('username')
- cf.Reset('password')
- self.info('login', 'stored/entered credentials invalid')
- return self.status_invalid
- mc.HideDialogWait()
- except Exception, e:
- self.updateArchiveSpoiler()
- return self.status_invalid
- def isLoggedIn(self):
- cf = mc.GetApp().GetLocalConfig()
- if (cf.GetValue('fprt') and cf.GetValue('ipid')):
- return True
- def getCredentials(self):
- try:
- cf = mc.GetApp().GetLocalConfig()
- if (cf.GetValue('username') and cf.GetValue('password')):
- return {'user': cf.GetValue('username'),
- 'pass': cf.GetValue('password')}
- except Exception, e:
- return self.raiseError(log='getCredentials', error=e)
- def launchWithItem(self, args):
- try:
- item = mc.ListItem(mc.ListItem.MEDIA_VIDEO_OTHER)
- item.SetLabel(args['title'][0])
- item.SetDescription(args['description'][0])
- item.SetThumbnail(args['thumbnail'][0])
- item.SetProperty('alt-label', args['alt-label'][0])
- item.SetProperty('event-id', args['event-id'][0])
- item.SetProperty('content-id', args['content-id'][0])
- item.SetProperty('bx-ourl', args['bx-ourl'][0])
- item.SetProperty('audio-stream', args['audio-stream'][0])
- item.SetProperty('media-state', args['media-state'][0])
- self.playItem(mlbList=0, playFromListItem=item)
- except Exception, e:
- return self.raiseError('Unable to play requested stream. If this continues please contact support@boxee.tv', 'launchWithItem', e)
- def init(self, args = False):
- try:
- self.info('init', 'mlb launched, checking authentication')
- auth = self.authenticate()
- if (auth == self.status_valid):
- self.authenticated = True
- if (args and self.launchWithItem(args)):
- pass
- else:
- if ((auth == self.status_missing) or (auth == self.status_invalid)):
- self.authenticated = False
- mc.ShowDialogOk('MLB.TV', 'Got MLB.tv? Go to boxee.tv/services to link your account. [CR]No MLB.tv? Sign up at mlb.com/boxee and get a free game a day through April!')
- return False
- except Exception, e:
- return self.raiseError(False, True)
- def populateTodayScreen(self):
- try:
- w = mc.GetWindow(14000)
- w.GetList(120).SetFocusedItem(0)
- w.GetControl(120).SetFocus()
- w.GetList(120).SetFocusedItem(0)
- dt = self.getMonth(0)
- w.GetLabel(101).SetLabel(dt.strftime('%B %d, %Y'))
- games = self.getGames()
- if (games and w.GetList(120).SetItems(games)):
- pass
- except Exception, e:
- if (('AppException' in str(e)) and self.info('populateTodayScreen', e)):
- return False
- def setUpCalendar(self):
- try:
- mc.GetWindow(14001).GetList(121).SetFocus()
- self.setMonth(0, False)
- except Exception, e:
- return self.raiseError(log='setUpCalendar', error=e)
- def standings(self, league):
- try:
- mc.ShowDialogWait()
- if (league == 'national'):
- league = 0
- elif (league == 'american'):
- league = 1
- data = self.getJson('http://mlb.mlb.com/lookup/json/named.standings_all_league_repeater.bam?sit_code=%27h0%27&league_id=104&league_id=103&season=2010')
- data = data.get('standings_all_league_repeater').get('standings_all')[league]
- stand = data.get('queryResults').get('row')
- east = mc.ListItems()
- west = mc.ListItems()
- central = mc.ListItems()
- for team in stand:
- item = mc.ListItem(mc.ListItem.MEDIA_UNKNOWN)
- item.SetLabel(str(team.get('team_short')))
- item.SetThumbnail(('http://mlb.mlb.com/images/logos/200x200/200x200_%s.png' % str(team.get('team_abbrev'))))
- item.SetProperty('games-back', str(team.get('gb')))
- item.SetProperty('wild-card', str(team.get('wild_card')))
- item.SetProperty('elim-wildcard', str(team.get('elim_wildcard')))
- details = (((((((((((((((('Steak (' + team.get('streak')) + '), Home (') + team.get('home')) + '), Away (') + team.get('away')) + '), Vs Division (') + team.get('vs_division')) + '), Last Ten (') + team.get('last_ten')) + ')[CR]Winning Percentage (') + team.get('pct')) + '%), Wildcard (') + team.get('wild_card')) + '), Elimination Wildcard (') + team.get('elim_wildcard')) + ')')
- item.SetDescription(str(details))
- division = str(team.get('division'))
- if (('East' in division) and east.append(item)):
- pass
- mc.GetActiveWindow().GetList(3002).SetItems(west)
- mc.GetActiveWindow().GetList(3003).SetItems(central)
- mc.GetActiveWindow().GetList(3004).SetItems(east)
- mc.HideDialogWait()
- except Exception, e:
- return self.raiseError(message='There was a problem accessing standings. Please try again later.', log='league', error=e)
- def getGames(self, year = False, month = False, day = False):
- try:
- mc.ShowDialogWait()
- if self.isLoggedIn():
- params = {}
- if (year and (month and day)):
- params['year'] = year
- params['month'] = month
- params['day'] = day
- try:
- games = self.callService('today', params, content='json').get('games')
- except:
- try:
- games = self.callService('today', params, content='json').get('games')
- except:
- return self.raiseError('Unable to fetch games list. Please try again later.', 'getgames', 'unable to fetch game list.')
- list = mc.ListItems()
- for game in games:
- item = mc.ListItem(mc.ListItem.MEDIA_VIDEO_OTHER)
- item.SetLabel(str(game.get('title')))
- item.SetThumbnail(str(game.get('thumbnail')))
- item.SetDescription(str(game.get('description')))
- custom = game.get('custom:items')
- for value in custom:
- item.SetProperty(str(value), str(custom.get(str(value))))
- images = game.get('image:items')
- for (key, value,) in enumerate(images):
- item.SetImage(key, str(value))
- media_string = ''
- audio_string = ''
- media = game.get('media:items')
- if bool(media.get('has_video')):
- video = media.get('video')
- for stream in video:
- if media_string:
- media_string = (media_string + '||')
- media_string = (((((media_string + str(stream.get('title'))) + '|') + str(stream.get('contentid'))) + '|') + str(stream.get('eventid')))
- if (media_string and item.SetProperty('media-string', media_string)):
- pass
- if bool(media.get('has_audio')):
- audio = media.get('audio')
- for stream in audio:
- if audio_string:
- audio_string = (audio_string + '||')
- audio_string = (((((audio_string + str(stream.get('title'))) + '|') + str(stream.get('contentid'))) + '|') + str(stream.get('eventid')))
- if (audio_string and item.SetProperty('audio-string', audio_string)):
- pass
- list.append(item)
- mc.HideDialogWait()
- return list
- mc.HideDialogWait()
- except Exception, e:
- return self.raiseError('Unable to fetch game list! Please wait and try again. If problem persists contact support@boxee.tv!', 'getgames', e)
- def getMonth(self, month = 0, formatted = False):
- try:
- date = (dt.date.today() + md.monthdelta(month))
- if formatted:
- return date
- else:
- return date.strftime('%B %Y')
- except Exception, e:
- self.raiseError(log='getmonth', error=e)
- return dt.date.today()
- def setMonth(self, active, setList = True):
- try:
- window = mc.GetActiveWindow()
- cf = mc.GetApp().GetLocalConfig()
- cf.SetValue('calendar', str(active))
- if setList:
- month = self.getMonth(active, False)
- if (active == 0):
- url = month.strftime('rss://dir.boxee.tv/apps/mlb/feed/%Y/%m')
- else:
- url = 'rss://dir.boxee.tv/apps/mlb/feed/calendar'
- mc.GetActiveWindow().GetList(121).SetContentURL(url)
- window.GetLabel(102).SetLabel((('[UPPERCASE]' + self.getMonth(active, True)) + '[/UPPERCASE]'))
- window.GetLabel(103).SetLabel((('[UPPERCASE]' + self.getMonth((active + 1), True)) + '[/UPPERCASE]'))
- window.GetLabel(101).SetLabel((('[UPPERCASE]' + self.getMonth((active - 1), True)) + '[/UPPERCASE]'))
- except Exception, e:
- return self.raiseError(log='nextmonth', error=e)
- def nextMonth(self):
- try:
- cf = mc.GetApp().GetLocalConfig()
- if cf.GetValue('calendar'):
- active = 0
- else:
- active = int(cf.GetValue('calendar'))
- self.setMonth((active + 1))
- except Exception, e:
- return self.raiseError(log='nextmonth', error=e)
- def prevMonth(self):
- try:
- cf = mc.GetApp().GetLocalConfig()
- if cf.GetValue('calendar'):
- active = 0
- else:
- active = int(cf.GetValue('calendar'))
- self.setMonth((active - 1))
- except Exception, e:
- return self.raiseError(log='prevmonth', error=e)
- def mediaServiceResponseCodes(self, id = -9999):
- if (id == -1000):
- return 'The requested media is not currently available.'
- elif (id == -2000):
- return 'invalid app account/partner'
- elif (id == -2500):
- return 'system error determining blackouts'
- elif (id == -3500):
- return 'too many active sessions/devices, this account is temporarily locked.'
- elif (id == -4000):
- return 'general system error'
- elif (id == -9999):
- return 'an unknown error'
- elif (id != -3000):
- return 'an unknown error'
- elif (id == -3000):
- return 'authentication key expired. please log in again to refresh.'
- def queryMediaService(self, media_request, isAudio = False):
- try:
- http = mc.Http()
- cf = mc.GetApp().GetLocalConfig()
- rand_number = str(random.randint(10000, 100000000))
- if http.Get((('http://mlbglobal08.112.2o7.net/b/ss/mlbglobal08/1/H.19--NS/' + rand_number) + '?ch=Media&pageName=BOXEE%20Request&c1=BOXEE')):
- http.Reset()
- media_service = http.Get(media_request)
- try:
- media_service_dom = parseString(media_service)
- except Exception, e:
- self.raiseError(log='querymediaservice', error=e)
- status_code = ''
- if (media_service and ('status-code' in media_service)):
- status_code = int(media_service_dom.getElementsByTagName('status-code')[0].firstChild.data)
- if ('notAuthorizedStatus' in media_service):
- return {'playlist_url': -2,
- 'media_state': ''}
- if (('<url>' in media_service) and media_service_dom.getElementsByTagName('url')[0].firstChild):
- base_encoded_string = media_service_dom.getElementsByTagName('url')[0].firstChild.data
- media_state = ''
- if ('<state>' in media_service):
- media_state = media_service_dom.getElementsByTagName('state')[0].firstChild.data
- content_id = ''
- if ('<content-id>' in media_service):
- content_id = media_service_dom.getElementsByTagName('content-id')[0].firstChild.data
- event_id = ''
- if ('<event-id>' in media_service):
- event_id = media_service_dom.getElementsByTagName('event-id')[0].firstChild.data
- if ('domain-attribute' in media_service):
- domain_attributes = {}
- for element in media_service_dom.getElementsByTagName('domain-attribute'):
- domain_attributes[element.attributes['name'].value] = element.firstChild.data
- game_id = domain_attributes['game_id']
- startDate = '0'
- innings_index = ''
- if (('innings-index' in media_service) and media_service_dom.getElementsByTagName('innings-index')[0].firstChild):
- innings_index = media_service_dom.getElementsByTagName('innings-index')[0].firstChild.data
- self.info('innings_index', innings_index)
- if innings_index.startswith('http'):
- innings_xml = mc.Http().Get(str(innings_index))
- if innings_xml:
- startDate = '0'
- else:
- innings_dom = parseString(innings_xml)
- if ('start_timecode' in innings_xml):
- startDate = innings_dom.getElementsByTagName('game')[0].attributes['start_timecode'].value
- else:
- startDate = '0'
- if ('<session-key>' in media_service):
- old_session = cf.GetValue('sessionid')
- for element in media_service_dom.getElementsByTagName('session-key'):
- session_key = element.firstChild.data
- cf.SetValue('sessionid', str(session_key))
- if ((not isAudio) and ((not base_encoded_string.startswith('http://')) and (not base_encoded_string.startswith('rtmp://')))):
- request_params = base64.b64decode(base_encoded_string).split('|')
- (stream_url, stream_fingerprint, stream_params,) = request_params
- rand_number = str(random.randint(10000, 100000000))
- bx_ourl = ('http://mlb.mlb.com/media/player/entry.jsp?calendar_event_id=%s&source=boxeeRef' % event_id)
- tracking_url = (((('http://mlbglobal08.112.2o7.net/b/ss/mlbglobal08/1/G.5--NS/' + rand_number) + '?ch=Media&pageName=BOXEE%20Media%20Return&c25=') + content_id) + '%7CHTTP%5FCLOUD%5FWIRED&c27=Media%20Player&c43=BOXEE')
- params = {'stream-fingerprint': stream_fingerprint,
- 'tracking-url': tracking_url,
- 'startDate': startDate,
- 'stream-params': stream_params}
- playlist_url = ('playlist://%s?%s' % (urllib.quote_plus(stream_url),
- urllib.urlencode(params)))
- data = {'playlist_url': playlist_url,
- 'media_state': media_state,
- 'game_id': str(game_id),
- 'innings_index': str(innings_index)}
- return data
- except Exception, e:
- self.raiseError(log='querymediaservice', error=e)
- self.log.exception('Error from querymedia service:')
- return {'playlist_url': False,
- 'media_state': ''}
- def parseAudioStreams(self, item):
- try:
- play_audio = False
- audio_string = item.GetProperty('audio-string')
- audio_items = audio_string.split('||')
- if (len(audio_items) == 0):
- return self.raiseError('Unable to located proper audio items. This may be an error, please contact support@boxee.tv. We apologize for the inconvenience.', 'playitem', 'problem locating audio streams, audio-string property is empty or malformed')
- elif (len(audio_items) == 1):
- stream_1 = audio_items[0]
- stream_1 = stream_1.split('|')
- play_audio = stream_1
- elif (len(audio_items) > 1):
- stream_1 = audio_items[0]
- stream_2 = audio_items[1]
- stream_1 = stream_1.split('|')
- stream_2 = stream_2.split('|')
- confirm = mc.ShowDialogConfirm('MLB.TV', 'Please select the audio stream you wish to listen to...', stream_1[0], stream_2[0])
- if confirm:
- play_audio = stream_1
- else:
- play_audio = stream_2
- if (play_audio or self.raiseError()):
- return False
- return play_audio
- except Exception, e:
- return self.raiseError(log='parseaudiostreams', error=e)
- def promptQuality(self):
- try:
- cf = mc.GetApp().GetLocalConfig()
- q_ask = bool(cf.GetValue('ask_quality'))
- q_high = bool(cf.GetValue('high_quality'))
- q_default = bool(cf.GetValue('default_quality'))
- if ((not q_ask) and ((not q_high) and (not q_default))):
- q_ask = True
- cf.SetValue('ask_quality', '1')
- if q_ask:
- q_message = 'Please select your video quality (manage this and other options in the settings tab):'
- quality = mc.ShowDialogConfirm('MLB.TV', q_message, 'Normal', 'High')
- quality = int(quality)
- elif q_high:
- quality = 1
- else:
- quality = 0
- return str(quality)
- except Exception, e:
- return raiseError(log='promptquality', error=e)
- def playItem(self, mlbList, forceAudioCheck = False, playFromListItem = False):
- if mc.ShowDialogWait():
- play_audio = False
- if playFromListItem:
- window = mc.GetActiveWindow()
- list = window.GetList(mlbList)
- index = list.GetFocusedItem()
- item = list.GetItem(index)
- else:
- item = playFromListItem
- session_id = 'null'
- cf = mc.GetApp().GetLocalConfig()
- if cf.GetValue('sessionid'):
- session_id = cf.GetValue('sessionid')
- if self.isLoggedIn():
- return self.raiseError('You must first log in before you can watch this game.')
- video_request_type = 'HTTP_CLOUD_WIRED'
- audio_request_type = 'AUDIO_SHOUTCAST_32K'
- audio_set_shout_protocol = False
- simulate_blackout = False
- simulate_not_authorized = False
- params = {'subject': 'LIVE_EVENT_COVERAGE',
- 'playbackScenario': video_request_type,
- 'eventId': item.GetProperty('event-id'),
- 'contentId': item.GetProperty('content-id'),
- 'sessionKey': session_id,
- 'fingerprint': cf.GetValue('fprt'),
- 'identityPointId': cf.GetValue('ipid'),
- 'platform': 'BOXEE'}
- web_url = ('http://mlb.mlb.com/media/player/entry.jsp?calendar_event_id=%s&source=boxeeRef' % item.GetProperty('event-id'))
- media_request = self.underscore((self.mr_url % urllib.urlencode(params)))
- if simulate_blackout:
- playlist_url = -1
- elif simulate_not_authorized:
- playlist_url = -2
- else:
- media_data = self.queryMediaService(media_request)
- playlist_url = media_data['playlist_url']
- update_media_state = media_data['media_state']
- if (bool(update_media_state) and (str(update_media_state).lower() != item.GetProperty('media-state').lower())):
- self.info('playitem', ('updating media_state (%s)' % update_media_state.lower()))
- item.SetProperty('media-state', update_media_state.lower())
- if (playlist_url == -3000):
- check_auth = self.authenticate()
- if (check_auth == self.status_valid):
- media_data = self.queryMediaService(media_request)
- playlist_url = media_data['playlist_url']
- update_media_state = media_data['media_state']
- if (bool(update_media_state) and (str(update_media_state).lower() != item.GetProperty('media-state').lower())):
- self.info('playitem', ('updating media_state (%s)' % update_media_state.lower()))
- item.SetProperty('media-state', update_media_state.lower())
- else:
- self.raiseError('Unable to validate your account. Please make sure your mlb.tv account is linked with Boxee! See boxee.tv/services.', 'playitem', 'lost users login credentials')
- mc.HideDialogWait()
- return False
- if ((playlist_url == -1) and ((not item.GetProperty('audio-string')) and (item.GetProperty('media-state') != 'media_on'))):
- return self.raiseError('No available audio streams found for this game. We apologize for the inconvenience.')
- confirm = mc.ShowDialogConfirm('MLB.TV', 'Video is not currently available for this game. Would you like to listen to the live audio broadcast?', 'No', 'Yes')
- if confirm:
- play_audio = self.parseAudioStreams(item)
- if play_audio:
- return False
- params = {'subject': 'LIVE_EVENT_COVERAGE',
- 'playbackScenario': audio_request_type,
- 'eventId': item.GetProperty('event-id'),
- 'contentId': play_audio[1],
- 'sessionKey': session_id,
- 'fingerprint': cf.GetValue('fprt'),
- 'identityPointId': cf.GetValue('ipid'),
- 'platform': 'BOXEE'}
- del params['platform']
- media_request = self.underscore((self.mr_url % urllib.urlencode(params)))
- media_data = self.queryMediaService(media_request)
- playlist_url = media_data['playlist_url']
- update_media_state = media_data['media_state']
- if (bool(update_media_state) and (str(update_media_state).lower() != item.GetProperty('media-state').lower())):
- self.info('playitem', ('updating media_state (%s)' % update_media_state.lower()))
- item.SetProperty('media-state', update_media_state.lower())
- else:
- mc.HideDialogWait()
- return False
- if ((playlist_url == -2) and mc.GetActiveWindow().ClearStateStack()):
- return self.raiseError('You must own MLB.TV to watch live baseball. Please go to mlb.com/boxee to sign up.')
- if play_audio:
- content_type = 'audio/mpeg'
- stream_type = mc.ListItem.MEDIA_AUDIO_OTHER
- playlist_url = playlist_url.replace('http://', 'shout://')
- live = 0
- else:
- live = 0
- playlist_url = (playlist_url + ('&quality=%s' % self.promptQuality()))
- if (item.GetProperty('media-state') == 'media_on'):
- confirm = mc.ShowDialogConfirm('MLB.TV', 'Would you like to watch this game from the start or jump into the live broadcast?', 'Start', 'Live')
- live = int(confirm)
- item.SetProperty('IsLiveStream', str(live))
- playlist_url = ((playlist_url + '&live=') + str(live))
- content_type = 'application/vnd.apple.mpegurl'
- stream_type = mc.ListItem.MEDIA_VIDEO_OTHER
- alt_label = item.GetProperty('alt-label')
- title = alt_label.replace('#', '').replace('@mlbtv', '')
- title = (title.replace(' v ', ' @ ') + ' on MLB.TV')
- playlist_url = ((playlist_url + '&bx-ourl=') + urllib.quote_plus(web_url))
- ext = mc.ListItem(stream_type)
- ext.SetTitle(alt_label)
- ext.SetLabel(title)
- ext.SetDescription(item.GetDescription(), False)
- ext.SetContentType(content_type)
- ext.SetThumbnail(item.GetThumbnail())
- ext.SetProviderSource('MLB.TV')
- params = {'title': title,
- 'alt-label': alt_label,
- 'event-id': item.GetProperty('event-id'),
- 'content-id': item.GetProperty('content-id'),
- 'description': item.GetDescription(),
- 'bx-ourl': web_url,
- 'thumbnail': item.GetThumbnail(),
- 'audio-stream': play_audio,
- 'media-state': item.GetProperty('media-state')}
- if play_audio:
- params['audio-string'] = item.GetProperty('audio-string')
- rand_number = str(random.randint(10000, 100000000))
- tracking_url = (((((('http://mlbglobal08.112.2o7.net/b/ss/mlbglobal08/1/G.5--NS/' + rand_number) + '?ch=Media&pageName=BOXEE%20Media%20Return&c25=') + str(play_audio[2])) + '%7C') + self.underscore(audio_request_type)) + '&c27=Media%20Player&c43=BOXEE')
- notify = mc.Http().Get(tracking_url)
- del notify
- ext.SetPath(('app://mlb/launch?%s' % urllib.urlencode(params)))
- new_item = mc.ListItem(stream_type)
- new_item.SetLabel(title)
- new_item.SetTitle(alt_label)
- new_item.SetDescription(item.GetDescription(), False)
- new_item.SetPath(str(playlist_url))
- new_item.SetProviderSource('MLB.TV')
- new_item.SetContentType(content_type)
- if (media_data['game_id'] and new_item.SetProperty('game_id', media_data['game_id'])):
- pass
- new_item.SetProperty('live', str(live))
- new_item.SetThumbnail(item.GetThumbnail())
- if (play_audio and new_item.SetAddToHistory(False)):
- new_item.SetReportToServer(False)
- new_item.SetExternalItem(ext)
- mc.GetActiveWindow().ClearStateStack()
- myJobManager = MLBJobManager(media_data['game_id'])
- try:
- track_label = self.generateTrackerGameString(item)
- if (track_label and self.myTracker.trackEvent('Video', 'Play', track_label)):
- pass
- except:
- self.myTracker.trackEvent('Video', 'Play', title)
- myJobManager.addJob(MessageChecker(media_data['game_id']))
- myJobManager.start()
- mc.HideDialogWait()
- mc.GetPlayer().Play(new_item)
- def generateTrackerGameString(self, item):
- try:
- desc = item.GetDescription()
- event = item.GetProperty('event-id')
- desc = desc.split('[CR]')[0]
- event = event.split('-')[-3:]
- title = desc.replace(')', ((' ' + '-'.join(event)) + ')'))
- self.info('generateTrackerGameString', title)
- return title
- except:
- return False
- def playList(self, mlbList):
- try:
- cf = mc.GetApp().GetLocalConfig()
- list = mc.GetActiveWindow().GetList(mlbList)
- item = list.GetItem(list.GetFocusedItem())
- if (self.isLoggedIn() or mc.ShowDialogNotification('You must first log in before you can watch this game.', 'mlb-icon.png')):
- pass
- except Exception, e:
- self.error('playlist', e)
- mc.ShowDialogNotification('Sorry, we are currently unable to play this game.', 'mlb-icon.png')
- return False
- def updateArchiveSpoiler(self):
- try:
- mc.ShowDialogWait()
- if self.isLoggedIn():
- response = self.callService('showhide')
- if ((response == 'T') and mc.GetApp().GetLocalConfig().SetValue('hide_scores', 'true')):
- pass
- else:
- mc.GetApp().GetLocalConfig().Reset('hide_scores')
- mc.HideDialogWait()
- except Exception, e:
- mc.GetApp().GetLocalConfig().Reset('hide_scores')
- return self.raiseError(log='updatearchivespoiler', error=e)
- def saveArchiveSpoiler(self, value):
- try:
- mc.ShowDialogWait()
- if self.isLoggedIn():
- response = self.callService('showhidesave', {'value': value})
- if ((response == '1') and mc.ShowDialogNotification('Score spoiler settings saved successfully!', 'mlb-icon.png')):
- pass
- else:
- mc.ShowDialogNotification('You must be logged in to modify settings.', 'mlb-icon.png')
- mc.HideDialogWait()
- except Exception, e:
- return self.raiseError(log='savearchivespoiler', error=e)
- def favoriteTeams(self):
- try:
- mc.ShowDialogWait()
- data = self.getJson('http://mlb.mlb.com/lookup/json/named.team_all.bam?sport_code=%27mlb%27&active_sw=%27Y%27&all_star_sw=%27N%27')
- data = data.get('team_all').get('queryResults').get('row')
- teamList = mc.ListItems()
- for team in data:
- item = mc.ListItem(mc.ListItem.MEDIA_UNKNOWN)
- item.SetLabel(str(team.get('name_display_full')))
- item.SetThumbnail(('http://mlb.mlb.com/images/logos/200x200/200x200_%s.png' % str(team.get('name_abbrev'))))
- item.SetProperty('team-id', str(team.get('team_id')))
- item.SetProperty('team-abbrev', str(team.get('team_abbrev')))
- teamList.append(item)
- favList = []
- for (index, team,) in enumerate(teamList):
- if ((team.GetProperty('team-id') in favList) and teamList.SetSelected(index, True)):
- pass
- mc.HideDialogWait()
- return teamList
- except Exception, e:
- self.raiseError(log='favoriteteams', error=e)
- def selectFavorite(self, listId):
- try:
- found = False
- list = mc.GetWindow(14010).GetList(listId)
- itemNumber = list.GetFocusedItem()
- item = list.GetItem(itemNumber)
- selectedItems = list.GetSelected()
- for team in selectedItems:
- if (team.GetProperty('team-id') == item.GetProperty('team-id')):
- found = True
- list.SetSelected(itemNumber, False)
- if (found or list.SetSelected(itemNumber, True)):
- pass
- except Exception, e:
- return self.raiseError(log='selectfavorite', error=e)
- def saveFavorites(self):
- try:
- mc.ShowDialogWait()
- favs = []
- for div in range(200, 206):
- items = mc.GetWindow(14010).GetList(div).GetSelected()
- for team in items:
- favs.append(team.GetProperty('team-id'))
- favs = ';'.join(favs)
- response = self.callService('setfavorites', {'teamids': favs})
- if ((response == '1') and mc.ShowDialogNotification('Your favorite teams have been saved successfully.', 'mlb-icon.png')):
- pass
- mc.HideDialogWait()
- except Exception, e:
- mc.GetActiveWindow().PopState()
- return self.raiseError(log='savefavorites', error=e)
- def loadFavorites(self):
- try:
- mc.ShowDialogWait()
- if self.isLoggedIn():
- response = self.callService('teams')
- data = json.loads(response)
- data = data.get('teams')
- division = {'200': mc.ListItems(),
- '201': mc.ListItems(),
- '202': mc.ListItems(),
- '203': mc.ListItems(),
- '204': mc.ListItems(),
- '205': mc.ListItems()}
- for team in data:
- item = mc.ListItem(mc.ListItem.MEDIA_UNKNOWN)
- item.SetLabel(str(team.get('title')))
- item.SetThumbnail(str(team.get('thumb')))
- item.SetProperty('team-id', str(team.get('team-id')))
- item.SetProperty('team-abbrev', str(team.get('team-abbrev')))
- item.SetProperty('team-leauge', str(team.get('team-leauge')))
- item.SetProperty('team-division', str(team.get('team-division')))
- item.SetProperty('team-fav', str(team.get('team-fav')))
- div = str(team.get('team-division'))
- division[div].append(item)
- for div in division:
- mc.GetWindow(14010).GetList(int(div)).SetItems(division[div])
- list = mc.GetWindow(14010).GetList(int(div))
- for (i, v,) in enumerate(list.GetItems()):
- if ((v.GetProperty('team-fav') == '1') and list.SetSelected(i, True)):
- pass
- else:
- return self.raiseError('You must be logged in to access your favorite teams!')
- mc.HideDialogWait()
- except Exception, e:
- import xbmc
- xbmc.executebuiltin('Dialog.Close(14010)')
- return self.raiseError('An error occured while accessing your favorite team settings. Are you logged in?', log='loadfavorites', error=e)
- def getPlayers(self, game_id):
- '\n Get players for game\n '
- players_uri = (self.gameIdToEventURI(game_id) + 'players.xml')
- xml = mc.Http().Get(players_uri)
- if (xml or self.debug('playersdata', ('Could not retrieve players xml here - %s' % players_uri))):
- return False
- def parsePlayers(self, xml):
- '\n Parse players from gdx xml\n '
- players = {}
- dom = parseString(xml)
- for player in dom.getElementsByTagName('player'):
- dict = {}
- dict['teamname'] = player.parentNode.attributes['name'].value
- dict['teamcode'] = player.parentNode.attributes['id'].value
- dict['teamtype'] = player.parentNode.attributes['type'].value
- for i in range(player.attributes.length):
- attribute = player.attributes.item(i)
- dict[attribute.name] = attribute.value
- players[dict['id']] = dict
- return players
- def getGameMarkers(self, media_data):
- if ((mc.App().GetLocalConfig().GetValue('chapters') == 'atbats') or (mc.App().GetLocalConfig().GetValue('chapters') == 'interesting')):
- if media_data['game_id']:
- self.players = self.getPlayers(media_data['game_id'])
- if (mc.App().GetLocalConfig().GetValue('chapters') == 'interesting'):
- events = self.getEvents(media_data['game_id'], self.players, True)
- else:
- events = self.getEvents(media_data['game_id'], self.players)
- if events:
- return self.setEvents(events)
- else:
- self.debug('chapters', 'Could not get game_id from media service request.')
- return False
- def setInnings(self, innings):
- '\n Set innings for listitem\n '
- chapters = []
- for inning in innings:
- chapters.append({'name': inning['inning'],
- 'startTime': inning['start'],
- 'duration': 0})
- try:
- chapters = self.formatChapters(chapters)
- except Exception, e:
- self.debug('innings', 'Encountered error formatting innings data.')
- self.raiseError(log='innings', error=e)
- return False
- return chapters
- def getInnings(self, innings_index):
- '\n Retrieve innings for innings_index\n '
- xml = mc.Http().Get(innings_index)
- if (xml or self.debug('innings', ('Could not retrieve innings_index xml here - %s' % innings_index))):
- return False
- def parseInnings(self, xml):
- '\n Parse innings index xml\n '
- innings = []
- self.debug('innings', 'Creating DOM...')
- dom = parseString(xml)
- for inning in dom.firstChild.childNodes:
- self.debug('innings', 'Finding inning...')
- dict = {}
- self.debug('innings', 'Getting inning names...')
- if (inning.attributes['top'].value == 'true'):
- dict['inning'] = ('Top ' + self.ordinal(int(inning.attributes['inning_number'].value)))
- else:
- dict['inning'] = ('Bottom ' + self.ordinal(int(inning.attributes['inning_number'].value)))
- self.debug('innings', 'Setting start and end times...')
- time = inning.firstChild
- try:
- dict['start'] = time.attributes['start'].value
- except:
- dict['start'] = 0
- try:
- dict['stop'] = time.attributes['end'].value
- except:
- dict['stop'] = 0
- self.debug('innings', 'Adding to innings...')
- innings.append(dict)
- return innings
- def setEvents(self, events):
- '\n Set Events chapters for listitem\n '
- chapters = []
- for event in events:
- startTime = self.digitsToTimecode(str(event['start_tfs']))
- if ((mc.GetApp().GetLocalConfig().GetValue('hide_scores') == 'true') and chapters.append({'name': ((((event['inning'] + ' ') + event['boxname']) + ' / ') + event['pitcher_boxname']),
- 'startTime': startTime,
- 'duration': 0})):
- pass
- try:
- chapters = self.formatChapters(chapters)
- except Exception, e:
- self.debug('events', 'Encountered error formatting events data.')
- self.raiseError(log='events', error=e)
- return False
- return chapters
- def getEvents(self, game_id, players = None, interesting = False):
- '\n Retrieve events for game_id\n '
- event_uri = (self.gameIdToEventURI(game_id) + 'game_events.xml')
- xml = mc.Http().Get(event_uri)
- if (xml or self.debug('events', ('Could not retrieve events xml here - %s' % event_uri))):
- return False
- def parseInterestingEvents(self, events):
- new_data = []
- for event in events:
- if ((event['event'] in self.event_filter) and new_data.append(event)):
- pass
- return new_data
- def parseEvents(self, xml):
- '\n Parse innings index xml\n '
- events = []
- dom = parseString(xml)
- for event in dom.getElementsByTagName('atbat'):
- dict = {}
- dict['inning'] = ((event.parentNode.tagName.capitalize() + ' ') + self.ordinal(int(event.parentNode.parentNode.attributes['num'].value)))
- for i in range(event.attributes.length):
- attribute = event.attributes.item(i)
- dict[attribute.name] = attribute.value
- events.append(dict)
- return events
- def formatChapters(self, chapters):
- '\n Accept chapters list of dictionaries and output into XML for Boxee client.\n '
- xml = '<?xml version="1.0" encoding="UTF-8" ?><chapters>'
- for chapter in chapters:
- xml = (((((((xml + '<chapter name="') + str(chapter['name'])) + '" startTime="') + str(chapter['startTime'])) + '" duration="') + str(chapter['duration'])) + '" />')
- xml = (xml + '</chapters>')
- return xml
- def getPitch(self, game_id):
- '\n Get latest pitch\n '
- event_uri = (self.gameIdToEventURI(game_id) + 'plays.xml')
- xml = mc.Http().Get(event_uri)
- if (xml or self.debug('pitch', ('Could not retrieve pitch xml here - %s' % event_uri))):
- pass
- def parsePitch(self, xml):
- '\n Parse pitch from plays.xml\n '
- pitches = []
- dom = parseString(xml)
- if dom.getElementsByTagName('p'):
- for pitch in dom.getElementsByTagName('p'):
- dict = {}
- dict['pitcher'] = dom.getElementsByTagName('pitcher')[0].attributes['boxname'].value
- if pitch.hasAttribute('nasty'):
- dict['schema'] = 'detailed'
- else:
- dict['schema'] = 'small'
- for i in range(pitch.attributes.length):
- attribute = pitch.attributes.item(i)
- dict[attribute.name] = attribute.value
- if pitch.hasAttribute('des'):
- dict['des'] = dict['des'].split(',')[0]
- pitches.append(dict)
- if pitches:
- return pitches.pop()
- else:
- self.debug('pitches', 'No pitches found.')
- return False
- def processMessages(self):
- '\n Process all the messages\n '
- self.debug('messages', 'Processing messages...')
- try:
- self.debug('messages', 'Getting messages...')
- messages = self.getMessages()
- except Exception, e:
- self.error('messages', 'Error getting messages.')
- return False
- if (messages and self.debug('messages', 'Messages found - processing')):
- for message in messages:
- if ((not self.messageAlreadyDisplayed(message)) and self.messageWithinWindow(message)):
- try:
- self.debug('messages', ('Displaying message: %s' % message['message']))
- self.displayMessage(message)
- except Exception, e:
- self.error('messages', 'Error displaying messages.')
- return False
- def getMessages(self):
- '\n Get message from message_uri\n '
- xml = mc.Http().Get(self.message_uri)
- if (xml or self.debug('messages', ('Could not retrieve message xml here - %s' % event_uri))):
- pass
- def displayMessage(self, message):
- hash = md5.md5(str(message)).hexdigest()
- mc.GetApp().GetLocalConfig().SetValue(hash, 'true')
- if ((message['type'] == 'ok') and self.debug('messages', 'Displaying OK dialog')):
- return mc.ShowDialogOk(str(message['source']), str(message['message']))
- def messageAlreadyDisplayed(self, message):
- self.debug('messages', 'Checking if message has already been displayed.')
- hash = md5.md5(str(message)).hexdigest()
- if (mc.GetApp().GetLocalConfig().GetValue(hash) and self.debug('messages', 'Message has already been displayed.')):
- return True
- def messageWithinWindow(self, message):
- self.debug('messages', 'Checking if time is in current message window.')
- now = self.getCurrentMLBTime()
- self.debug('messages', ('Current MLB time is: %s.' % str(now)))
- startTime = time.strptime(message['startDatetime'], '%d %b %Y %H:%M')
- endTime = time.strptime(message['endDatetime'], '%d %b %Y %H:%M')
- if ((now >= startTime) and (now <= endTime)):
- self.debug('messages', 'Message is in window.')
- return True
- def parseMessages(self, xml):
- self.debug('messages', 'Parsing messages.')
- dom = parseString(xml)
- if dom.getElementsByTagName('message'):
- messageList = []
- for message in dom.getElementsByTagName('message'):
- dict = {}
- for i in range(message.attributes.length):
- attribute = message.attributes.item(i)
- dict[attribute.name] = attribute.value
- dict['message'] = message.firstChild.data
- messageList.append(dict)
- return messageList
- else:
- return False
- class MLBJobManager(jobmanager.BoxeeJobManager):
- __module__ = __name__
- def __init__(self, game_id):
- self.game_id = game_id
- self.mlb = MLB()
- self.videoFail = 0
- jobmanager.BoxeeJobManager.__init__(self, 5)
- self.log(('Setting game_id as: %s' % self.game_id))
- def check(self):
- if (self.videoFail >= 3):
- return self.stop()
- if (mc.GetPlayer().IsPlaying() or self.log('Video not playing - incrementing counter.')):
- self.videoFail = (self.videoFail + 1)
- return
- class MLBJob(jobmanager.BoxeeJob):
- __module__ = __name__
- def __init__(self, name, game_id, interval = 10):
- self.name = name
- self.mlb = MLB()
- self.game_id = game_id
- self.hash =
- self.log(('Setting game ID to: %s' % self.game_id))
- self.players = self.mlb.getPlayers(self.game_id)
- jobmanager.BoxeeJob.__init__(self, name, interval)
- def xmlChanged(self, xml):
- self.log('Checking if xml has changed.')
- new_hash = md5.md5(str(xml)).hexdigest()
- if ((new_hash == self.hash) and self.log('Xml has not changed.')):
- return False
- def getInHMS(self, seconds):
- (m, s,) = divmod(seconds, 60)
- (h, m,) = divmod(m, 60)
- return ('%d%02d%02d' % (h,
- m,
- s))
- class PitchChecker(MLBJob):
- __module__ = __name__
- def __init__(self, game_id):
- self.firstRun = True
- self.game_id = game_id
- self.timecodeRetry = 0
- self.setting = mc.GetApp().GetLocalConfig().GetValue('pitches')
- self.timer = threading.Event()
- self.lastPitch =
- MLBJob.__init__(self, 'PitchChecker', self.game_id, 0)
- def process(self):
- xml = self.getXml()
- if (self.firstRun or xml):
- pitch = self.mlb.parsePitch(xml)
- if (pitch and (pitch['id'] != self.lastPitch)):
- if self.log('Received pitch - building message.'):
- if (pitch['schema'] == 'detailed'):
- pitch['string_type'] = self.mlb.pitches[pitch['pitch_type']][1]
- if (self.setting == 'km/h'):
- kmh = str((int(pitch['start_speed'].split('.')[0].strip()) * 1.609344))
- pitch_message = str(('%s: %s - %s km/h' % (pitch['des'],
- pitch['string_type'],
- str(int(kmh.split('.')[0].strip())))))
- elif (self.setting == 'nasty'):
- pitch_message = str(('%s: %s - %s%%' % (pitch['des'],
- pitch['string_type'],
- pitch['nasty'])))
- else:
- pitch_message = str(('%s: %s - %s mph' % (pitch['des'],
- pitch['string_type'],
- str(int(pitch['start_speed'].split('.')[0].strip())))))
- else:
- pitch_message = str(('%s' % pitch['des']))
- self.log(('Sending pitch to client: %s' % pitch_message))
- mc.ShowDialogNotification(pitch_message, 'mlb-icon.png')
- self.lastPitch = pitch['id']
- self.log('Message sent.')
- def getXml(self):
- if mc.GetPlayer().IsPlaying():
- rawtime = mc.GetPlayer().GetTime()
- if ((rawtime == -1) and self.log('Did not get timecode from client! ')):
- self.timecodeRetry = (self.timecodeRetry + 1)
- if ((self.timecodeRetry <= 3) and self.timer.wait(1)):
- return self.getXml()
- timecode = self.getInHMS(rawtime)
- timecode = str((int(timecode) + 3))
- timecode = str(int((5 * round((float(int(timecode)) / 5)))))
- self.log(('Timecode is %s' % timecode))
- else:
- return False
- event_uri = ((self.mlb.gameIdToEventURI(self.game_id, True) + 'plays.xml&timecode=') + timecode)
- self.log(('Fetching URI %s' % event_uri))
- xml = mc.Http().Get(event_uri)
- if (xml or self.log(('Could not retrieve innings xml here - %s' % self.innings_index))):
- return False
- def debugXml(self, xml):
- self.log('Debug info for plays data:')
- dom = parseString(xml)
- boxscore = {}
- for i in range(dom.getElementsByTagName('game')[0].attributes.length):
- attribute = dom.getElementsByTagName('game')[0].attributes.item(i)
- try:
- boxscore[attribute.name] = boxscore[attribute.value]
- except:
- raise Exception
- self.log(('Box: %s %s. Count: %s balls, %s strikes, %s outs.' % (boxscore['inning'],
- boxscore['top_inning'],
- boxscore['b'],
- boxscore['s'],
- boxscore['o'])))
- for player in dom.getElementsByTagName('players')[0].childNodes:
- dict = {}
- if self.players:
- for player in self.players:
- dict['boxname'] = self.players[player['pid']]['boxname']
- for i in range(player.attributes.length):
- attribute = player.attributes.item(i)
- dict[attribute.name] = attribute.value
- self.log(('Data for %s: %s' % (player.tagName,
- dict)))
- return self.log('End debug info for plays data.')
- class InningsChecker(MLBJob):
- __module__ = __name__
- def __init__(self, game_id, innings_index):
- self.innings_index = innings_index
- MLBJob.__init__(self, 'InningsChecker', game_id, 120)
- def process(self):
- xml = self.getXml()
- if (xml and self.log('Received new xml to process.')):
- self.log('Parsing xml...')
- data = self.mlb.parseInnings(xml)
- self.log('Formatting chapters...')
- chapters = self.mlb.setInnings(data)
- self.log('Sending chapters to client...')
- return mc.GetApp().SendMessage('mlb:chapters', chapters)
- def getXml(self):
- xml = mc.Http().Get(self.innings_index)
- if (xml or self.log(('Could not retrieve innings xml here - %s' % self.innings_index))):
- return False
- class EventChecker(MLBJob):
- __module__ = __name__
- def __init__(self, game_id):
- MLBJob.__init__(self, 'EventsChecker', game_id, 60)
- def process(self):
- xml = self.getXml()
- if (xml and self.log('Received new xml to process.')):
- self.log('Parsing xml...')
- data = self.mlb.parseEvents(xml)
- if ((mc.App().GetLocalConfig().GetValue('chapters') == 'interesting') and self.log('Getting only big plays')):
- data = self.mlb.parseInterestingEvents(data)
- if (self.players and self.log('Matching up player box names to player ids...')):
- for event in data:
- event['boxname'] = self.players[event['batter']]['boxname']
- if (data and self.log('Formatting into chapters...')):
- chapters = self.mlb.setEvents(data)
- self.log('Updating client with new events.')
- return mc.GetApp().SendMessage('mlb:chapters', chapters)
- return False
- def getXml(self):
- event_uri = (self.mlb.gameIdToEventURI(self.game_id) + 'game_events.xml')
- xml = mc.Http().Get(event_uri)
- if (xml or self.log(('Could not retrieve events xml here - %s' % event_uri))):
- return False
- class MessageChecker(MLBJob):
- __module__ = __name__
- def __init__(self, game_id):
- MLBJob.__init__(self, 'MessageChecker', game_id, 900)
- def process(self):
- self.log('Processing messages...')
- self.mlb.processMessages()
- self.log('Done processing messages.')
Add Comment
Please, Sign In to add comment