Skip to content

Commit

Permalink
add avg ratings and percentage of genre
Browse files Browse the repository at this point in the history
Signed-off-by: Navratan Lal Gupta <[email protected]>
  • Loading branch information
navilg committed Dec 9, 2024
1 parent 6a40d98 commit a39ca63
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 41 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
TRAKT_USER=trakt_user_account
TRAKT_CLIENT_ID=trakt_client_id
TMDB_API_KEY=tmdb_api_key
YEAR=2024
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,5 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

*.json
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@ Generate year in review from Trakt history

## Steps

1. Create `.env` file from `.env.example` file

```bash
cp .env.example .env
```

2. Update trakt user name, trakt client id and year in `.env` file

3. Run below command on full terminal screen

```bash
python generate.py
```

4. Alternatively, You can also pass trakt user name, year and client id in command line argument

```bash
python generate.py user_id 2024 trakt_client_id
```

## Screenshots

![](Screenshot.png)
Binary file modified Screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
101 changes: 61 additions & 40 deletions generate.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import requests
from datetime import datetime
from time import sleep
from collections import Counter
import json
from dotenv import load_dotenv
import os
import sys

from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.layout import Layout
from rich.align import Align


load_dotenv()
if len(sys.argv) != 3:
load_dotenv()
else:
os.environ['TRAKT_USER'] = sys.argv[1]
os.environ['YEAR'] = sys.argv[2]
os.environ['TRAKT_CLIENT_ID'] = sys.argv[3]

# Trakt API configuration
TRAKT_CLIENT_ID = os.getenv('TRAKT_CLIENT_ID')
Expand All @@ -23,9 +29,7 @@
'trakt-api-key': TRAKT_CLIENT_ID
}

# TMDB API configuration
TMDB_API_KEY = os.getenv('TMDB_API_KEY')
TMDB_API_BASE_URL = 'https://api.themoviedb.org/3'
username = os.getenv('TRAKT_USER')

year=os.getenv('YEAR')

Expand All @@ -39,77 +43,89 @@ def fetch_trakt_history(username, start_date, end_date):
response = requests.get(url, headers=TRAKT_HEADERS, params=params)
return response.json()

def get_tmdb_movie_details(tmdb_id):
url = f"{TMDB_API_BASE_URL}/movie/{tmdb_id}"
params = {'api_key': TMDB_API_KEY}
response = requests.get(url, params=params)
def get_movie_details(id):
url = f"{TRAKT_API_BASE_URL}/movies/{id}"
params = {'extended': 'full'}
response = requests.get(url, headers=TRAKT_HEADERS, params=params)
data = response.json()

return data.get('runtime', 0), data.get('genres', [])
return data.get('runtime', 0), data.get('genres', []), data.get('rating', 0)

def get_tmdb_episode_details(show_tmdb_id, season_number, episode_number):
url = f"{TMDB_API_BASE_URL}/tv/{show_tmdb_id}/season/{season_number}/episode/{episode_number}"
params = {'api_key': TMDB_API_KEY}
response = requests.get(url, params=params)
def get_episode_details(show_id, season_number, episode_number):
url = f"{TRAKT_API_BASE_URL}/shows/{show_id}/seasons/{season_number}/episodes/{episode_number}"
params = {'extended': 'full'}
response = requests.get(url, headers=TRAKT_HEADERS, params=params)
data = response.json()

show_details_url = f"{TMDB_API_BASE_URL}/tv/{show_tmdb_id}"
params = {'api_key': TMDB_API_KEY}
show_detail_response = requests.get(show_details_url, params=params)
show_details_url = f"{TRAKT_API_BASE_URL}/shows/{show_id}"
params = {'extended': 'full'}
show_detail_response = requests.get(show_details_url, headers=TRAKT_HEADERS, params=params)
show_detail_data = show_detail_response.json()

return data.get('runtime', 0), show_detail_data.get('genres', [])
return data.get('runtime', 0), show_detail_data.get('genres', []), data.get('rating', 0)

def analyze_history(history):
tv_episodes = 0
tv_minutes = 0
tv_ratings = 0
tv_genres = Counter()
movies = 0
movie_minutes = 0
movie_ratings = 0
movie_genres = Counter()
loop_count = 0

for item in history:
if item['type'] == 'episode':
tv_episodes += 1
show_tmdb_id = item['show'].get('ids', {}).get('tmdb')
show_id = item['show'].get('ids', {}).get('trakt')
season_number = item['episode']['season']
episode_number = item['episode']['number']
if show_tmdb_id:
runtime, genres = get_tmdb_episode_details(show_tmdb_id, season_number, episode_number)
if show_id:
runtime, genres, rating = get_episode_details(show_id, season_number, episode_number)
try:
tv_minutes += runtime
except TypeError:
runtime = 30
genre_list = [item['name'] for item in genres]
tv_minutes += 30
tv_ratings += rating
genre_list = genres
tv_genres.update(genre_list)
elif item['type'] == 'movie':
movies += 1
tmdb_id = item['movie'].get('ids', {}).get('tmdb')
if tmdb_id:
runtime, genres = get_tmdb_movie_details(tmdb_id)
id = item['movie'].get('ids', {}).get('trakt')
if id:
runtime, genres, rating = get_movie_details(id)
try:
movie_minutes += runtime
except TypeError:
runtime = 90
genre_list = [item['name'] for item in genres]
movie_minutes += 90
movie_ratings += rating
genre_list = genres
movie_genres.update(genre_list)
loop_count += 1
if loop_count > 99:
sleep(10) # To make sure API call rate for Trakt is not breached. It waits for 10 seconds every 100th call
loop_count = 0

return {
'tv_episodes': tv_episodes,
'tv_hours': round(tv_minutes / 60, 2),
'top_tv_genres': tv_genres.most_common(5),
'tv_genres_total_count': sum(tv_genres.values()),
'episodes_average_rating': round(tv_ratings/tv_episodes, 1),
'movies': movies,
'movie_hours': round(movie_minutes / 60, 2),
'top_movie_genres': movie_genres.most_common(5)
'top_movie_genres': movie_genres.most_common(5),
'movie_genres_total_count': sum(movie_genres.values()),
'movies_average_rating': round(movie_ratings/movies,1)
}

# Set the date range for 2024
start_date = datetime(int(year), 1, 1)
end_date = datetime(int(year), 12, 31)

# Fetch and analyze the history
username = 'navilg0409'
print('Generating Year in Review for', year+'...')
print('Generating Year in Review for', year+'. It may take few minutes depending on your size of history...')
print("\n")
history = fetch_trakt_history(username, start_date, end_date)
with open("trakt-history-"+year+".json", "w") as file:
Expand All @@ -125,11 +141,13 @@ def analyze_history(history):
"tv_shows": {
"episodes_watched": stats['tv_episodes'],
"hours_watched": stats['tv_hours'],
"average_rating": stats['episodes_average_rating'],
"top_genres": [genre for genre, count in stats['top_tv_genres']]
},
"movies": {
"movies_watched": stats['movies'],
"hours_watched": stats['movie_hours'],
"average_rating": stats['movies_average_rating'],
"top_genres": [genre for genre, count in stats['top_movie_genres']]
}
}
Expand All @@ -150,26 +168,30 @@ def analyze_history(history):
cards_table.add_column(justify="center", ratio=1)
cards_table.add_column(justify="center", ratio=1)
cards_table.add_column(justify="center", ratio=1)
cards_table.add_column(justify="center", ratio=1)
cards_table.add_column(justify="center", ratio=1)

cards_table.add_row(
Panel("Movies Watched\n\n[bold cyan]"+str(stats['movies'])+"[/bold cyan]", border_style="cyan"),
Panel("Movies Hours\n\n[bold green]"+str(stats['movie_hours'])+"[/bold green]", border_style="green"),
Panel("Movies Avg Rating\n\n[bold blue]"+str(stats['movies_average_rating'])+"[/bold blue]", border_style="blue"),
Panel("TV Episodes Watched\n\n[bold cyan]"+str(stats['tv_episodes'])+"[/bold cyan]", border_style="cyan"),
Panel("TV Episodes Hours\n\n[bold green]"+str(stats['tv_hours'])+"[/bold green]", border_style="green"),
Panel("Episodes Avg Rating\n\n[bold blue]"+str(stats['episodes_average_rating'])+"[/bold blue]", border_style="blue")
)


# Function to create genre rows
def create_genre_row(genres, color):
def create_genre_row(top_movie_genres_stat, total_count, color):
genre_row = Table.grid(expand=True)
for genre in genres:
for genre, count in top_movie_genres_stat:
genre_row.add_column(justify="center", ratio=1)
genre_row.add_row(*[Panel(f"[bold {color}]{genre}[/bold {color}]", border_style=color, padding=(0, 2)) for genre in genres])

genre_row.add_row(*[Panel(f"[bold {color}]{genre}\n\n{round(100*count/total_count, 2)}%[/bold {color}]", border_style=color, padding=(0, 2)) for genre, count in top_movie_genres_stat])
return genre_row

# Top 5 Movie Genres Section
movie_genres = ["Action", "Comedy", "Drama", "Sci-Fi", "Thriller"]
movie_genres_row = create_genre_row([genre for genre, count in stats['top_movie_genres']], "bold cyan")
movie_genres_row = create_genre_row(stats['top_movie_genres'], stats['movie_genres_total_count'], "bold cyan")

movie_genres_section = Panel(
movie_genres_row,
Expand All @@ -179,8 +201,7 @@ def create_genre_row(genres, color):
)

# Top 5 TV Show Genres Section
tv_genres = ["Drama", "Fantasy", "Reality", "Mystery", "Animation"]
tv_genres_row = create_genre_row([genre for genre, count in stats['top_tv_genres']], "bold green")
tv_genres_row = create_genre_row(stats['top_tv_genres'], stats['tv_genres_total_count'], "bold green")

tv_genres_section = Panel(
tv_genres_row,
Expand All @@ -195,9 +216,9 @@ def create_genre_row(genres, color):
Layout(heading, size=3),
Layout(cards_table, size=5),
Layout("\n\n", size=2),
Layout(movie_genres_section, size=8),
Layout(movie_genres_section, size=9),
Layout("\n\n", size=2),
Layout(tv_genres_section, size=8),
Layout(tv_genres_section, size=9),
)

# Print Layout
Expand Down

0 comments on commit a39ca63

Please sign in to comment.