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 python3

# <xbar.title>Live Cricket Scores</xbar.title>
# <xbar.version>v2.0</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>https://i.imgur.com/xiQTWZ4.png</xbar.image>
# <xbar.dependencies>python</xbar.dependencies>
# <xbar.abouturl></xbar.abouturl>

# <xbar.var>string(FAVORITE_TEAMS_FILE="/var/tmp/bitbar_cricket.data"): File location for storing your favorite teams' name.</xbar.var>

import os
import sys
import getopt
import http.client
import json
from datetime import datetime
from pathlib import Path


if len(sys.argv) > 1:
    opts, args = getopt.getopt(sys.argv[1:], "i:d:", [])
    FAVORITE_TEAMS_FILE = Path(args[0])
    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()
else:
    FAVORITE_TEAMS_FILE = Path(os.environ.get('FAVORITE_TEAMS_FILE'))

FAVORITE_TEAMS_FILE.parent.mkdir(parents=True, exist_ok=True)

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

# fetch the json feed listing all the matches
CRICINFO_BASE_URL = "https://espncricinfo.com"
CRICINFO_API_BASE_URL = "hs-consumer-api.espncricinfo.com"

conn = http.client.HTTPSConnection(CRICINFO_API_BASE_URL)
conn.request('GET', '/v1/pages/matches/current?lang=en&latest=true')
response = conn.getresponse().read()
summary_data = json.loads(response)

# fetch the url for matches that needs to be shown in the plugin
matches = 0
live_matches = 0
list_links = []
for match in summary_data['matches']:
    team_names = []
    for team in match['teams']:
        if team['team']['name'] not in favorite_teams:
            untracked_teams.append(team['team']['name'])
        team_names.append(team['team']['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
        match_url = f"{CRICINFO_BASE_URL}/series/{match['series']['slug']}-{match['series']['objectId']}/{match['slug']}-{match['objectId']}/live-cricket-score"
        match_api_url = f"/v1/pages/match/home?lang=en&seriesId={match['series']['objectId']}&matchId={match['objectId']}"
        live_match = False
        if match['stage'] == "RUNNING" and match['state'] == "LIVE":
            live_matches += 1
            live_match = True
        list_links.append((match_url, match_api_url, live_match))

if matches:
    print('🏏' + str(matches) + ' | dropdown=false')
    print('---')
    print("%s/%s matches live" % (live_matches, matches))
    print("---")
    for match_url in list_links:
        match_api_url = match_url[1]
        conn = http.client.HTTPSConnection('hs-consumer-api.espncricinfo.com')
        conn.request('GET', match_api_url)
        response = conn.getresponse().read()
        match_data = json.loads(response)

        # get team_data
        teams = {}
        for team_info in match_data['match']['teams']:
            if 'id' in team_info['team']:
                team_id = team_info['team']['id']
            else:
                team_id = "TBA"

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

        if match_data['match']['format'] == "TEST":
            test_match = True
        else:
            test_match = False

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

        else:
            match_started = False

        # get the scores of batsmen at crease
        batsmen = []
        if match_data['content']['supportInfo']['liveSummary']:
            for batsman in match_data['content']['supportInfo']['liveSummary']['batsmen']:
                batsman_name = batsman['player']['name']
                
                batsman_score = f"{batsman['runs']}({batsman['balls']})"
                if batsman['currentType'] == 1:
                    batsman_score += '*'
                batsmen.append(batsman_name + ': ' + batsman_score)

        # get the match status.
        # match_status = match_data['status']
        if test_match:
            if 'actualDays' in match_data['match'] and match_data['match']['actualDays']:
                status_text = f"Day {match_data['match']['actualDays']}:"
            else:
                status_text = 'Day 0:'
        else:
            status_text = ''
        status_text += match_data['match']['statusText']
        if "MATCH_START_HOURS" in status_text:
            start_time = datetime.strptime(match_data['match']['startTime'], "%Y-%m-%dT%H:%M:%S.%fZ")
            current_time = datetime.utcnow()
            time_diff = start_time-current_time
            match_start_hours = time_diff.seconds//3600
            match_start_minutes = (time_diff.seconds//60) % 60
            if match_start_hours:
                match_start_hours = f"{match_start_hours} hours"
            else:
                match_start_hours = ""
            if match_start_minutes:
                if match_start_hours:
                    match_start_hours += " and"
                match_start_minutes = f"{match_start_minutes} minutes"
            else:
                match_start_minutes = ""
            status_text = status_text.replace(
                "{{MATCH_START_HOURS}}", 
                match_start_hours
            ).replace("{{MATCH_START_MINS}}", match_start_minutes)

        # 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.items():
                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['match']['teams']:
                if match_desc:
                    match_desc += " vs "
                if 'name' in team_data['team']:
                    match_desc += team_data['team']['name']
                else:
                    match_desc += "TBA"
            print(match_desc + ' | ' + print_params['team_name'])

        print(status_text + ' | href=' + match_url[0] + 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(f"--{each_team if each_team != '*' else 'TRACK ALL TEAMS'} | "
              f"terminal=false bash=\"{sys.argv[0]}\" param1=\"-d\" "
              f"param2=\"{each_team}\" param3=\"{FAVORITE_TEAMS_FILE.absolute().as_posix()}\" refresh=true")
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(f"--{each_team} | terminal=false bash=\"{sys.argv[0]}\" "
          f"param1=\"-i\" param2=\"{each_team}\" "
          f"param3=\"{FAVORITE_TEAMS_FILE.absolute().as_posix()}\" refresh=true")
if not track_all_teams:
    print(f"--TRACK ALL TEAMS | terminal=false bash=\"{sys.argv[0]}\" "
          f"param1=\"-i\" param2=\"*\" param3=\"{FAVORITE_TEAMS_FILE.absolute().as_posix()}\" refresh=true")