Skip to content

Commit

Permalink
Add script.service.latestrating plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
pizzamx committed Jan 13, 2025
1 parent 2c68a67 commit fd36238
Show file tree
Hide file tree
Showing 10 changed files with 712 additions and 0 deletions.
8 changes: 8 additions & 0 deletions script.service.latestrating/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007

This program is derived in part from the Kodi TV Show Scraper
(https://github.com/xbmc/metadata.tvshows.themoviedb.org.python)
which is licensed under GPL-3.0.

For the full license text, see https://www.gnu.org/licenses/gpl-3.0.txt
26 changes: 26 additions & 0 deletions script.service.latestrating/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Latest Rating Service for Kodi

A Kodi service add-on that automatically updates movie and TV show ratings in your library.

## Features
- Automatically updates ratings on a configurable schedule
- Supports IMDb and Trakt as rating sources
- Weighted average calculation when multiple sources are enabled
- Configurable date range filters to limit which movies and TV shows get updated
- Built-in log viewer through "Run" function of the add-on (for now you can only see logs in current session)

## Installation
1. Download the zip file
2. In Kodi, go to Settings > Add-ons > Install from zip file
3. Select the downloaded zip file

## Configuration
1. Enable desired rating sources (IMDb and/or Trakt)
2. Set update interval and content filters
3. The service will start automatically

## Credits
Rating fetch functionality and Trakt API key from [Kodi's official TV Show scraper](https://github.com/xbmc/metadata.tvshows.themoviedb.org.python).

## License
GPL-3.0
21 changes: 21 additions & 0 deletions script.service.latestrating/addon.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="script.service.latestrating" name="Latest Rating Service" version="1.0.2" provider-name="pizzamx">
<requires>
<import addon="xbmc.python" version="3.0.0" />
<import addon="xbmc.addon" version="19.0.0"/>
<import addon="script.module.requests" version="2.22.0"/>
</requires>
<extension point="xbmc.python.script" library="default.py">
<provides>executable</provides>
</extension>
<extension point="xbmc.service" library="service.py" start="login">
<provides>service</provides>
</extension>
<extension point="xbmc.addon.metadata">
<summary lang="en_GB">Latest Rating Service</summary>
<description lang="en_GB">Automatically updates ratings for movies and TV shows in your library. Enalbe in settings first after install.</description>
<platform>all</platform>
<license>GPL-3.0</license>
<source>https://github.com/pizzamx/script.service.latestrating</source>
</extension>
</addon>
63 changes: 63 additions & 0 deletions script.service.latestrating/default.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import xbmcaddon
import xbmcgui
import xbmc
import xbmcvfs
import os
from datetime import datetime

ADDON = xbmcaddon.Addon()
ADDON_NAME = ADDON.getAddonInfo('name')

def get_kodi_log_path():
if xbmc.getCondVisibility('system.platform.windows'):
return xbmcvfs.translatePath('special://home/kodi.log')
else:
return xbmcvfs.translatePath('special://home/temp/kodi.log')

def parse_log_file():
log_path = get_kodi_log_path()
if not os.path.exists(log_path):
return ["Log file not found"]

addon_logs = []
try:
with open(log_path, 'r', encoding='utf-8', errors='replace') as f:
for line in f:
if f'[{ADDON_NAME}]' in line and '[UPDATE_RESULT]' in line:
try:
# Format: [Latest Rating Service] [2024-01-06 14:30:01] [UPDATE_RESULT] Movie: The Matrix - Rating: 7.9 → 8.5
# Split by ']' and remove leading '['
parts = [p.strip(' []') for p in line.split(']')]
if len(parts) >= 3:
timestamp = parts[1] # The timestamp part
# Find the message after [UPDATE_RESULT]
for i, part in enumerate(parts):
if 'UPDATE_RESULT' in part:
message = '] '.join(parts[i+1:]).strip()
formatted_line = f"{timestamp} - {message}"
addon_logs.append(formatted_line)
break
except Exception as e:
print(f"Error parsing line: {line}, Error: {str(e)}")
continue
except Exception as e:
return [f"Error reading log file: {str(e)}"]

return list(reversed(addon_logs[-1000:])) # Return last 1000 lines in reverse chronological order

def show_log_viewer():
logs = parse_log_file()
if not logs:
xbmcgui.Dialog().ok(ADDON_NAME, "No rating updates found")
return

# Create a list dialog
dialog = xbmcgui.Dialog()
while True:
# Show the logs in a select dialog
idx = dialog.select("Rating Update History", logs)
if idx == -1: # User pressed back/cancel
break

if __name__ == '__main__':
show_log_viewer()
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Kodi Media Center language file
msgid ""
msgstr ""

msgctxt "#32001"
msgid "View Update Log"
msgstr "View Update Log"
29 changes: 29 additions & 0 deletions script.service.latestrating/resources/lib/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import xbmc
import xbmcaddon
from datetime import datetime

class Logger:
def __init__(self):
self.addon = xbmcaddon.Addon()
self.addon_name = self.addon.getAddonInfo('name')

def log(self, message, level=xbmc.LOGINFO):
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
log_message = f'[{self.addon_name}] [{timestamp}] {message}'
xbmc.log(log_message, level)

def update_result(self, message):
"""Log an update result with a special prefix"""
self.log(f'[UPDATE_RESULT] {message}', xbmc.LOGINFO)

def error(self, message):
self.log(message, xbmc.LOGERROR)

def info(self, message):
self.log(message, xbmc.LOGINFO)

def debug(self, message):
self.log(message, xbmc.LOGDEBUG)

def warning(self, message):
self.log(message, xbmc.LOGWARNING)
33 changes: 33 additions & 0 deletions script.service.latestrating/resources/lib/rate_limiter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from datetime import datetime, timedelta
import xbmc
from collections import deque

class RateLimiter:
def __init__(self, calls_per_second=1):
self.calls_per_second = calls_per_second
self.calls = {} # Dictionary to track calls for different sources

def wait_for_token(self, source):
"""Wait until we can make another API call for the given source"""
if source not in self.calls:
self.calls[source] = deque(maxlen=self.calls_per_second)
self.calls[source].append(datetime.now())
return

# Remove old timestamps
now = datetime.now()
while self.calls[source] and (now - self.calls[source][0]) > timedelta(seconds=1):
self.calls[source].popleft()

# If we've made too many calls in the last second, wait
if len(self.calls[source]) >= self.calls_per_second:
oldest_call = self.calls[source][0]
wait_time = 1 - (now - oldest_call).total_seconds()
if wait_time > 0:
xbmc.sleep(int(wait_time * 1000))

def add_call(self, source):
"""Record that we made an API call"""
if source not in self.calls:
self.calls[source] = deque(maxlen=self.calls_per_second)
self.calls[source].append(datetime.now())
Loading

0 comments on commit fd36238

Please sign in to comment.