Live Cricket Scores

Show live scores of cricket matches happening around the world using Cricinfo api.

Image preview of Live Cricket Scores plugin.

live_cricket.2m.py

Edit
Open on GitHub
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# <xbar.title>Live Cricket Scores</xbar.title>
# <xbar.version>v1.3</xbar.version>
# <xbar.author>Anup Sam Abraham</xbar.author>
# <xbar.author.github>anupsabraham</xbar.author.github>
# <xbar.desc>Show live scores of cricket matches happening around the world using Cricinfo api. </xbar.desc>
# <xbar.image>http://i.imgur.com/xiQTWZ4.png</xbar.image>
# <xbar.dependencies>python</xbar.dependencies>
# <xbar.abouturl></xbar.abouturl>

import os
import sys
import getopt
import re
import urllib2
import json
from datetime import datetime
from time import tzname


FAVORITE_TEAMS_FILE = "/var/tmp/bitbar_cricket.data"

if len(sys.argv) > 1:
    opts, args = getopt.getopt(sys.argv[1:], "i:d:", [])
    for opt, arg in opts:
        if opt == "-i":
            # this is for inserting the team name into our file
            with open(FAVORITE_TEAMS_FILE, "a") as f:
                f.write(arg+"\n")

        elif opt == "-d":
            # this option is for deleting a team name from the file
            if os.path.exists(FAVORITE_TEAMS_FILE):
                with open(FAVORITE_TEAMS_FILE, "r") as f:
                    current_teamnames = [x.strip() for x in f.readlines()]
                    if arg in current_teamnames:
                        current_teamnames.remove(arg)
                with open(FAVORITE_TEAMS_FILE, "w") as f:
                    f.writelines([x+"\n" for x in current_teamnames])
    exit()

if os.path.exists(FAVORITE_TEAMS_FILE):
    with open(FAVORITE_TEAMS_FILE, "r") as f:
        favorite_teams = [x.strip() for x in f.readlines()]
else:
    # create an empty file if it doesn't exist
    open(FAVORITE_TEAMS_FILE, "a").close()
    favorite_teams = []

untracked_teams = []
if "*" in favorite_teams:
    track_all_teams = True
else:
    track_all_teams = False

TIME_DELTA = datetime.utcnow() - datetime.now()  # for converting gmt to local time

# fetch the json feed listing all the matches
cricinfo_base_url = "http://api.espncricinfo.com"
summary_url = cricinfo_base_url + '/netstorage/summary.json'
summary_response = urllib2.urlopen(summary_url)
summary_data = json.load(summary_response)

# fetch the url for matches that needs to be shown in the plugin
matches = 0
live_matches = 0
list_links = []
for match_number, match in summary_data['matches'].iteritems():
    if match['team1_name'] not in favorite_teams:
        untracked_teams.append(match['team1_name'])
    if match['team2_name'] not in favorite_teams:
        untracked_teams.append(match['team2_name'])
    team_names = [match['team1_name'], match['team2_name']]
    if track_all_teams or (set(favorite_teams) & set(team_names)):
        # At least one team in the favorite team list is playing
        matches += 1
        if match['live_match'] == "Y":
            live_matches += 1
        list_links.append(cricinfo_base_url + match['url'])

if matches:
    print '🏏' + str(matches) + ' | dropdown=false'
    print '---'
    print "%s/%s matches live" % (live_matches, matches)
    print "---"
    for match_html_url in list_links:
        match_url = match_html_url.split('.html')[0] + '.json'
        match_data_response = urllib2.urlopen(match_url)
        match_data = json.load(match_data_response)

        # get team_data
        teams = {}
        for loop_counter, team_info in enumerate(match_data['team']):
            if 'team_id' in team_info:
                team_id = team_info['team_id']
            else:
                team_id = "TBA" + str(loop_counter)

            if 'team_short_name' in team_info:
                team_short_name = team_info['team_short_name']
            else:
                team_short_name = "TBA"
            teams[team_id] = {
                'name': team_short_name,
                'score': ''
            }

        if match_data['match']['international_class_card'] == "Test":
            test_match = True
        elif match_data['match']['general_class_card'] == "First-class":
            test_match = True
        else:
            test_match = False

        # get innings data
        remaining_balls = None
        required_runrate = None
        if match_data['innings']:
            match_started = True
            for innings in match_data['innings']:
                if teams[innings['batting_team_id']]['score']:
                    # if its a test match and this is the second innings
                    # of the team add '&'' before adding the score
                    teams[innings['batting_team_id']]['score'] += ' & '
                innings_score = innings['runs'] + '/' + innings['wickets'] + ' (' + \
                                    innings['overs'] + ' ov)'
                if innings['live_current'] == '1':
                    innings_score += '*'
                teams[innings['batting_team_id']]['score'] += innings_score
                if innings['live_current'] == '1':
                    batting_team = teams[innings['batting_team_id']]['name']
                    lead = innings['lead']
                    # my guess is that the below two lines should throw error
                    # for test matches. Lets see
                    if not test_match:
                        remaining_balls = match_data['live']['innings']['remaining_balls']
                        required_runrate = match_data['live']['innings']['required_run_rate']
                    break
        else:
            match_started = False

        # get the scores of batsmen at crease
        batsmen = []
        for batsman in match_data['live']['batting']:
            # get batsman name from team info
            # That's right. The live batsman name is not in this
            # dictionary. Have to go through each players of each team
            # in the match_data to fetch the batsman's name
            batsman_name = ''
            for team in match_data['team']:
                if team['team_id'] == batsman['team_id']:
                    if 'player' in team:
                        for player in team['player']:
                            if player['player_id'] == batsman['player_id']:
                                batsman_name = player['card_long']
                                break
                    elif 'squad' in team:
                        for player in team['squad']:
                            if player['player_id'] == batsman['player_id']:
                                batsman_name = player['card_long']
                                break
                    break
            batsman_score = batsman['runs'] + '(' + batsman['balls_faced'] + ')'
            if batsman['live_current_name'] == 'striker':
                batsman_score += '*'
            batsmen.append(batsman_name + ': ' + batsman_score)

        # get the match status.
        match_status = match_data['live']['status']
        if test_match:
            if 'actual_days' in match_data['match']:
                status_text = 'Day ' + match_data['match']['actual_days'] + ': '
            else:
                status_text = 'Day 0: '
        else:
            status_text = ''
        if 'scheduled' in match_status.lower():
            # match hasn't started yet. Show the start time of the match in local time
            gmt = match_data['match']['start_datetime_gmt']
            local_datetime = datetime.strptime(gmt, '%Y-%m-%d %H:%M:%S') - TIME_DELTA
            local_time_string = local_datetime.strftime('%I:%M %p')
            status_text +=  'Starting at: ' + local_time_string + " (" + tzname[0] + ")"
        elif 'elected to' in match_status.lower():
            # first innings started. show who won the toss
            if match_data['match']['toss_choice_team_id'] != "0":
                toss_winner = match_data['match']['toss_choice_team_id']
            else:
                toss_winner = match_data['match']['toss_winner_team_id']
            status_text += teams[toss_winner]['name'] + ' elected to ' + match_data['match']['toss_decision_name'] + ' first'
        elif 'trail by' in match_status.lower() or 'lead by' in match_status.lower():
            # batting team is either trailing or leading which means it is
            # either 2nd or 3rd innings of a test match
            if int(lead) >= 0:
                status_text += batting_team + " lead by " + lead + " runs"
            else:
                status_text += batting_team + " trail by " + str(abs(int(lead))) + " runs"
        elif 'require another' in match_status.lower():
            # last innings of the match
            status_text += batting_team + " need " + str(abs(int(lead)) + 1) + " runs to win"
            if remaining_balls and required_runrate:
                status_text += " from " + remaining_balls + " balls(RRR: " + required_runrate + ")"
        elif 'won by' in match_status.lower():
            # match is over. show who won the match
            winner = teams[match_data['match']['winner_team_id']]['name']
            win_status = re.match("^.*(won by (an innings and )?\d* (runs?|wickets?))( \(.*\))?", match_status)
            status_text += winner + " " + win_status.group(1)
            if match_data['match']['rain_rule'] == '1':
                # It can be confusing if the score doesn't look complete
                # and the match result is decided using something like D/L method
                status_text += ' (D/L)'
            # I also wanted to show the Man of the Match info. But can't find it anywhere in the json
        else:
            status_text += match_status

        # print teams and score
        print_params = {
            'team_name': " size=14 ",
            'status_text': " color=blue ",
            'batsman_score': " size=12 "
        }
        if match_started:
            for team_id, each_team in teams.iteritems():
                if each_team['score']:
                    print each_team['name'] + ': ' + each_team['score'] + ' |' + print_params['team_name']
                else:
                    print each_team['name'] + ': Yet to bat |' + print_params['team_name']
        else:
            match_desc = ""
            for team_data in match_data['team']:
                if match_desc:
                    match_desc += " vs "
                if 'team_name' in team_data:
                    match_desc += team_data['team_name']
                else:
                    match_desc += "TBA"
            print match_desc + ' | ' +print_params['team_name']

        print status_text + ' | href=' + match_html_url + print_params['status_text']
        for batsman in batsmen:
            print batsman + ' |' + print_params['batsman_score']
        print '---'
else:
    # no matches are live
    print '🏏'
    print '---'
    print 'No matches live'
    print "---"

print "Favorite Teams | color=green"
print "--Click on any to remove from favorites"
print "-----"
if favorite_teams:
    for each_team in favorite_teams:
        print "--%s | terminal=false bash=\"%s\" param1=\"-d\" param2=\"%s\" refresh=true" % (
            each_team if each_team != "*" else "TRACK ALL TEAMS",
            sys.argv[0],
            each_team
        )
else:
    print "--You don't have any favorite teams set"

print "Other Teams | color=red"
print "--Click on any to add to favorites"
print "-----"
for each_team in untracked_teams:
    print "--%s | terminal=false bash=\"%s\" param1=\"-i\" param2=\"%s\" refresh=true" % (each_team, sys.argv[0], each_team)
if not track_all_teams:
    print "--TRACK ALL TEAMS | terminal=false bash=\"%s\" param1=\"-i\" param2=\"*\" refresh=true" % sys.argv[0]