Updated kodi settings on Lenovo

This commit is contained in:
2026-03-22 22:28:43 +01:00
parent 725dfa7157
commit 32b5a81da6
10925 changed files with 575678 additions and 5511 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

View File

@@ -0,0 +1,328 @@
# Metadata Editor language file
# Addon Name: Metadata Editor
# Addon id: script.metadata.editor
# Addon Provider: sualfred
# Translators:
# sualfred <su4lfred@gmail.com>, 2020
msgid ""
msgstr ""
"Project-Id-Version: Metadata Editor\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2019-11-07 08:05+0000\n"
"Last-Translator: sualfred <su4lfred@gmail.com>, 2020\n"
"Language-Team: German (Germany) (https://www.transifex.com/sualfred/teams/80018/de_DE/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: de_DE\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: /addon.xml
msgctxt "#32000"
msgid "Metadata Editor"
msgstr "Metadata Editor"
#: /resources/lib/dialog.py
msgctxt "#32001"
msgid "User rating"
msgstr "Eigene Bewertung"
#: /resources/lib/dialog_videogenres.py
msgctxt "#32002"
msgid "Available entries"
msgstr "Verfügbare Einträge"
#: /addon.xml
msgctxt "#32003"
msgid "Add/remove available tags"
msgstr "Verfügbare Tags hinzufügen/entfernen"
#: /addon.xml
msgctxt "#32004"
msgid "Add/remove available genres"
msgstr "Verfügbare Genre hinzufügen/entfernen"
#: /resources/lib/utils.py
msgctxt "#32005"
msgid "Add new item"
msgstr "Neuen Eintrag hinzufügen"
#: /resources/lib/utils.py
msgctxt "#32006"
msgid "Edit current list as string"
msgstr "Bearbeite aktuelle Liste als String"
#: /resources/lib/utils.py
msgctxt "#32007"
msgid "Select from available items"
msgstr "Aus verfügbaren Elementen wählen"
#: /context.py
msgctxt "#32008"
msgid "Remove watchlist tag"
msgstr "Entferne Watchlist Tag"
#: /context.py
msgctxt "#32009"
msgid "Add watchlist tag"
msgstr "Setze Watchlist Tag"
#: /context.py
msgctxt "#32010"
msgid "Open editor"
msgstr "Öffne Editor"
#: /resources/lib/utils.py
msgctxt "#32011"
msgid "Enter floating number"
msgstr "Gebe Kommazahl ein"
#: /resources/lib/utils.py
msgctxt "#32012"
msgid "Select source"
msgstr "Wähle Quelle"
#: /resources/lib/utils.py
msgctxt "#32013"
msgid "Available sources"
msgstr "Verfügbare Quellen"
#: /resources/lib/utils.py
msgctxt "#32014"
msgid "Default source"
msgstr "Standard-Quelle"
#: /resources/lib/utils.py
msgctxt "#32015"
msgid "Select default source"
msgstr "Wähle Standard-Quelle"
#: /resources/lib/utils.py
msgctxt "#32016"
msgid "Edit ratings and votes"
msgstr "Bearbeite Bewertungen und Abstimmungen"
#: /resources/lib/utils.py
msgctxt "#32017"
msgid "Add source"
msgstr "Füge Quelle hinzu"
#: /resources/lib/utils.py
msgctxt "#32018"
msgid "Only values between 1.0 and 10.0 are allowed."
msgstr "Nur Werte zwischen 1.0 und 10.0 sind erlaubt."
#: /resources/lib/utils.py
msgctxt "#32019"
msgid "Attention"
msgstr "Achtung"
#: /resources/lib/utils.py
msgctxt "#32020"
msgid "Set as default?"
msgstr "Als Standard setzen?"
#: /resources/settings.xml
msgctxt "#32021"
msgid "Enable .nfo updating for movies, TV shows and music videos"
msgstr "Aktiviere .nfo Aktualisierung für Filme, Serien und Musikvideos"
#: /resources/lib/editor.py
msgctxt "#32022"
msgid "value unkown (missing Kodi feature)"
msgstr "Wert unbekannt (Kodi Feature fehlt)"
#: /resources/lib/editor.py
msgctxt "#32023"
msgid "Record label"
msgstr "Record Label"
#: /resources/settings.xml
msgctxt "#32025"
msgid "Preferred language"
msgstr "Bevorzugte Sprachregion"
#: /resources/settings.xml
msgctxt "#32026"
msgid "Scraper settings"
msgstr "Scraper Einstellungen"
#: /resources/lib/rating_updater.py
msgctxt "#32024"
msgid "Heavy server load. Please wait."
msgstr "Hohe Serverlast. Bitte warten."
#: /resources/settings.xml
msgctxt "#32027"
msgid "TV show library is based on informations of"
msgstr "Serien-Datenbank basiert auf Informationen von"
#: /resources/settings.xml
msgctxt "#32029"
msgid "Enable JSON logging"
msgstr "Aktiviere JSON Logging"
#: /resources/settings.xml
msgctxt "#32030"
msgid "Rating updater"
msgstr "Bewertungs-Updater"
#: /resources/settings.xml
msgctxt "#32028"
msgid "Run updating process in the background"
msgstr "Führe die Aktualisierung im Hintergrund aus"
#: /resources/settings.xml
msgctxt "#32031"
msgid "Your personal OMDb API key (www.omdbapi.com)"
msgstr "Dein persönlicher OMDb API Schlüssel (www.omdbapi.com)"
#: /resources/settings.xml
msgctxt "#32032"
msgid "Search by title/year if IMDb ID is missing (not recommended)"
msgstr "Suche anhand Titel/Jahr falls IMDb ID fehlt (nicht empfohlen)"
#: /default.py
msgctxt "#32035"
msgid ""
"No OMDb API key is configured, which is required to update IMDb, Rotten "
"Tomatoes and Metacritic ratings. Please visit www.omdbapi.com and create "
"your own API key.[CR][CR]Note: The free key is limited to 1000 calls a day. "
"Please suggest to become a patreon of OMDb to increase the limit to "
"100.000.[CR][CR]Do you want to proceed updating The Movie DB ratings? This "
"only works if you have a TMDb ID stored."
msgstr ""
"Kein OMDb API Schlüssel ist konfiguriert, welcher benötigt wird um IMDb, "
"Rotten Tomatoes und Metacritic Bewertungen zu aktualisieren. Bitte besuche "
"www.omdbapi.com und erstelle einen eigenen API Schlüssel.[CR][CR]Hinweis: "
"Der kostenfreie Schlüssel ist auf 1000 Anfragen pro Tag limitiert. Bitte "
"ziehe in Betracht ein Patreon von OMDb zu werden, um das tägliche Limit auf "
"100.000 zu erhöhen.[CR][CR]Willst du fortfahren und nur The Movie DB "
"Bewertungen aktualisieren? Dies funktioniert nur, falls eine TMDb ID in der "
"Datenbank vorhanden ist."
#: /default.py
msgctxt "#32036"
msgid "Update TV show ratings"
msgstr "Aktualisiere Serienbewertungen"
#: /resources/lib/rating_updater.py
msgctxt "#32033"
msgid ""
"OMDB API limit reached. Please consider to become a Patreon to increase your"
" daily call limitation. Proceed by only using The Movie DB?"
msgstr ""
"OMDb API Limit erreicht. Bitte erwäge ein Patreon zu werden um das tägliche "
"Limit zu erhöhen. Nur mit TMDb fortfahren?"
#: /resources/settings.xml
msgctxt "#32034"
msgid "Create .nfo file if missing"
msgstr "Erstelle .nfo Datei, falls diese fehlt"
#: /default.py
msgctxt "#32037"
msgid "Update movie ratings"
msgstr "Aktualisiere Filmbewertungen"
#: /default.py
msgctxt "#32038"
msgid "Update all ratings"
msgstr "Aktualisiere alle Bewertungen"
#: /context.py
msgctxt "#32039"
msgid "Update ratings"
msgstr "Aktualisiere Bewertungen"
#: /resources/lib/editor.py
msgctxt "#32040"
msgid "Edit data for"
msgstr "Bearbeite Daten für"
#: /resources/lib/rating_updater.py
msgctxt "#32042"
msgid "Canceled"
msgstr "Abgebrochen"
#: /resources/settings.xml
msgctxt "#32043"
msgid "MPAA region"
msgstr "MPAA Region"
#: /resources/settings.xml
msgctxt "#32041"
msgid "Update premiered/year if database value is different"
msgstr "Aktualisiere Premiere/Jahr, falls Datenbankwert nicht korrekt ist"
#: /resources/settings.xml
msgctxt "#32044"
msgid "Skip updating of MPAA"
msgstr "MPAA nicht aktualisieren"
#: /default.py
msgctxt "#32045"
msgid "Update episode ratings"
msgstr "Aktualisiere Episodenbewertungen"
#: /resources/lib/editor.py
msgctxt "#32047"
msgid "No default source defined"
msgstr "Keine Standard-Quelle definiert"
#: /resources/lib/rating_updater.py
msgctxt "#32048"
msgid "No items found"
msgstr "Keine Einträge gefunden"
#: /context.py
msgctxt "#32046"
msgid "Update .nfo"
msgstr "Aktualisiere .nfo"
#: /default.py
msgctxt "#32049"
msgid "Incomplete arguments or content type not supported"
msgstr "Unvollständiger Aufruf oder Inhaltstyp werden nicht unterstützt"
#: /default.py
msgctxt "#32050"
msgid "Do you want to cancel the update?"
msgstr "Update abbrechen?"
#: /default.py
msgctxt "#32051"
msgid "Content"
msgstr "Inhalt"
#: /resources/settings.xml
msgctxt "#32052"
msgid "Fallback to US MPAA if configured country has no certification stored"
msgstr ""
"Nutze US MPAA als Fallback, falls keine Zertifizierung der konfigurierten "
"Region gefunden wird"
#: /resources/settings.xml
msgctxt "#32053"
msgid "Don't store \"NR\" (Not rated) MPAA rating"
msgstr "\"NR\" (nicht bewertet) MPAA-Bewertung nicht speichern"
#: /service.py
msgctxt "#32054"
msgid "Do you want to rate the following item?"
msgstr "Möchtest du das folgende Video bewerten?"
#: /resources/settings.xml
msgctxt "#32055"
msgid "Automatically update changed watched states to .nfo"
msgstr "Geänderten Watched Status automatisch in .nfo aktualisieren"
#: /resources/settings.xml
msgctxt "#32056"
msgid "Rate your media if playback has ended"
msgstr "Bewerte Medien nach vollständiger Wiedergabe"
#: /resources/settings.xml
msgctxt "#32057"
msgid "Write watched flag and playcount to .nfo"
msgstr "Schreibe Watched Status und Abspielzähler in .nfo"

View File

@@ -0,0 +1,305 @@
# Metadata Editor language file
# Addon Name: Metadata Editor
# Addon id: script.metadata.editor
# Addon Provider: sualfred
msgid ""
msgstr ""
"Project-Id-Version: Metadata Editor\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: en_GB\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: /addon.xml
msgctxt "#32000"
msgid "Metadata Editor"
msgstr ""
#: /resources/lib/dialog.py
msgctxt "#32001"
msgid "User rating"
msgstr ""
#: /resources/lib/dialog_videogenres.py
msgctxt "#32002"
msgid "Available entries"
msgstr ""
#: /addon.xml
msgctxt "#32003"
msgid "Add/remove available tags"
msgstr ""
#: /addon.xml
msgctxt "#32004"
msgid "Add/remove available genres"
msgstr ""
#: /resources/lib/utils.py
msgctxt "#32005"
msgid "Add new item"
msgstr ""
#: /resources/lib/utils.py
msgctxt "#32006"
msgid "Edit current list as string"
msgstr ""
#: /resources/lib/utils.py
msgctxt "#32007"
msgid "Select from available items"
msgstr ""
#: /context.py
msgctxt "#32008"
msgid "Remove watchlist tag"
msgstr ""
#: /context.py
msgctxt "#32009"
msgid "Add watchlist tag"
msgstr ""
#: /context.py
msgctxt "#32010"
msgid "Open editor"
msgstr ""
#: /resources/lib/utils.py
msgctxt "#32011"
msgid "Enter floating number"
msgstr ""
#: /resources/lib/utils.py
msgctxt "#32012"
msgid "Select source"
msgstr ""
#: /resources/lib/utils.py
msgctxt "#32013"
msgid "Available sources"
msgstr ""
#: /resources/lib/utils.py
msgctxt "#32014"
msgid "Default source"
msgstr ""
#: /resources/lib/utils.py
msgctxt "#32015"
msgid "Select default source"
msgstr ""
#: /resources/lib/utils.py
msgctxt "#32016"
msgid "Edit ratings and votes"
msgstr ""
#: /resources/lib/utils.py
msgctxt "#32017"
msgid "Add source"
msgstr ""
#: /resources/lib/utils.py
msgctxt "#32018"
msgid "Only values between 1.0 and 10.0 are allowed."
msgstr ""
#: /resources/lib/utils.py
msgctxt "#32019"
msgid "Attention"
msgstr ""
#: /resources/lib/utils.py
msgctxt "#32020"
msgid "Set as default?"
msgstr ""
#: /resources/settings.xml
msgctxt "#32021"
msgid "Enable .nfo updating for movies, TV shows and music videos"
msgstr ""
#: /resources/lib/editor.py
msgctxt "#32022"
msgid "value unkown (missing Kodi feature)"
msgstr ""
#: /resources/lib/editor.py
msgctxt "#32023"
msgid "Record label"
msgstr ""
#: /resources/settings.xml
msgctxt "#32025"
msgid "Preferred language"
msgstr ""
#: /resources/settings.xml
msgctxt "#32026"
msgid "Scraper settings"
msgstr ""
#: /resources/lib/rating_updater.py
msgctxt "#32024"
msgid "Heavy server load. Please wait."
msgstr ""
#: /resources/settings.xml
msgctxt "#32027"
msgid "TV show library is based on informations of"
msgstr ""
#: /resources/settings.xml
msgctxt "#32029"
msgid "Enable JSON logging"
msgstr ""
#: /resources/settings.xml
msgctxt "#32030"
msgid "Rating updater"
msgstr ""
#: /resources/settings.xml
msgctxt "#32028"
msgid "Run updating process in the background"
msgstr ""
#: /resources/settings.xml
msgctxt "#32031"
msgid "Your personal OMDb API key (www.omdbapi.com)"
msgstr ""
#: /resources/settings.xml
msgctxt "#32032"
msgid "Search by title/year if IMDb ID is missing (not recommended)"
msgstr ""
#: /default.py
msgctxt "#32035"
msgid "No OMDb API key is configured, which is required to update IMDb, Rotten Tomatoes and Metacritic ratings. Please visit www.omdbapi.com and create your own API key.[CR][CR]Note: The free key is limited to 1000 calls a day. Please suggest to become a patreon of OMDb to increase the limit to 100.000.[CR][CR]Do you want to proceed updating The Movie DB ratings? This only works if you have a TMDb ID stored."
msgstr ""
#: /default.py
msgctxt "#32036"
msgid "Update TV show ratings"
msgstr ""
#: /resources/lib/rating_updater.py
msgctxt "#32033"
msgid "OMDB API limit reached. Please consider to become a Patreon to increase your daily call limitation. Proceed by only using The Movie DB?"
msgstr ""
#: /resources/settings.xml
msgctxt "#32034"
msgid "Create .nfo file if missing"
msgstr ""
#: /default.py
msgctxt "#32037"
msgid "Update movie ratings"
msgstr ""
#: /default.py
msgctxt "#32038"
msgid "Update all ratings"
msgstr ""
#: /context.py
msgctxt "#32039"
msgid "Update ratings"
msgstr ""
#: /resources/lib/editor.py
msgctxt "#32040"
msgid "Edit data for"
msgstr ""
#: /resources/lib/rating_updater.py
msgctxt "#32042"
msgid "Canceled"
msgstr ""
#: /resources/settings.xml
msgctxt "#32043"
msgid "MPAA region"
msgstr ""
#: /resources/settings.xml
msgctxt "#32041"
msgid "Update premiered/year if database value is different"
msgstr ""
#: /resources/settings.xml
msgctxt "#32044"
msgid "Skip updating of MPAA"
msgstr ""
#: /default.py
msgctxt "#32045"
msgid "Update episode ratings"
msgstr ""
#: /resources/lib/editor.py
msgctxt "#32047"
msgid "No default source defined"
msgstr ""
#: /resources/lib/rating_updater.py
msgctxt "#32048"
msgid "No items found"
msgstr ""
#: /context.py
msgctxt "#32046"
msgid "Update .nfo"
msgstr ""
#: /default.py
msgctxt "#32049"
msgid "Incomplete arguments or content type not supported"
msgstr ""
#: /default.py
msgctxt "#32050"
msgid "Do you want to cancel the update?"
msgstr ""
#: /default.py
msgctxt "#32051"
msgid "Content"
msgstr ""
#: /resources/settings.xml
msgctxt "#32052"
msgid "Fallback to US MPAA if configured country has no certification stored"
msgstr ""
#: /resources/settings.xml
msgctxt "#32053"
msgid "Don't store \"NR\" (Not rated) MPAA rating"
msgstr ""
#: /service.py
msgctxt "#32054"
msgid "Do you want to rate the following item?"
msgstr ""
#: /resources/settings.xml
msgctxt "#32055"
msgid "Automatically update changed watched states to .nfo"
msgstr ""
#: /resources/settings.xml
msgctxt "#32056"
msgid "Rate your media if playback has ended"
msgstr ""
#: /resources/settings.xml
msgctxt "#32057"
msgid "Write watched flag and playcount to .nfo"
msgstr ""

View File

@@ -0,0 +1,331 @@
# Metadata Editor language file
# Addon Name: Metadata Editor
# Addon id: script.metadata.editor
# Addon Provider: sualfred
# Translators:
# Bartolome Soriano <bsoriano@gmail.com>, 2019
# Rafa Oliveros <roliverosc@gmail.com>, 2020
#
msgid ""
msgstr ""
"Project-Id-Version: Metadata Editor\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2019-11-07 08:05+0000\n"
"Last-Translator: Rafa Oliveros <roliverosc@gmail.com>, 2020\n"
"Language-Team: Spanish (Spain) (https://www.transifex.com/sualfred/teams/80018/es_ES/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: es_ES\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: /addon.xml
msgctxt "#32000"
msgid "Metadata Editor"
msgstr "Editor de Metadatos"
#: /resources/lib/dialog.py
msgctxt "#32001"
msgid "User rating"
msgstr "Valoración de usuario"
#: /resources/lib/dialog_videogenres.py
msgctxt "#32002"
msgid "Available entries"
msgstr "Entradas disponibles"
#: /addon.xml
msgctxt "#32003"
msgid "Add/remove available tags"
msgstr "Añadir/Eliminar etiquetas disponibles"
#: /addon.xml
msgctxt "#32004"
msgid "Add/remove available genres"
msgstr "Añadir/Eliminar géneros disponibles"
#: /resources/lib/utils.py
msgctxt "#32005"
msgid "Add new item"
msgstr "Añadir nuevo elemento"
#: /resources/lib/utils.py
msgctxt "#32006"
msgid "Edit current list as string"
msgstr "Editar lista actual como cadena"
#: /resources/lib/utils.py
msgctxt "#32007"
msgid "Select from available items"
msgstr "Seleccionar de elementos disponibles"
#: /context.py
msgctxt "#32008"
msgid "Remove watchlist tag"
msgstr "Eliminar de lista de seguimiento"
#: /context.py
msgctxt "#32009"
msgid "Add watchlist tag"
msgstr "Añadir a lista de seguimiento"
#: /context.py
msgctxt "#32010"
msgid "Open editor"
msgstr "Abrir editor"
#: /resources/lib/utils.py
msgctxt "#32011"
msgid "Enter floating number"
msgstr "Introduzca número de coma flotante"
#: /resources/lib/utils.py
msgctxt "#32012"
msgid "Select source"
msgstr "Seleccionar fuente"
#: /resources/lib/utils.py
msgctxt "#32013"
msgid "Available sources"
msgstr "Fuentes disponibles"
#: /resources/lib/utils.py
msgctxt "#32014"
msgid "Default source"
msgstr "Fuente predeterminada"
#: /resources/lib/utils.py
msgctxt "#32015"
msgid "Select default source"
msgstr "Seleccionar fuente predeterminada"
#: /resources/lib/utils.py
msgctxt "#32016"
msgid "Edit ratings and votes"
msgstr "Editar valoración y votos"
#: /resources/lib/utils.py
msgctxt "#32017"
msgid "Add source"
msgstr "Añadir fuente"
#: /resources/lib/utils.py
msgctxt "#32018"
msgid "Only values between 1.0 and 10.0 are allowed."
msgstr "Solo se permiten valores entre 1.0 y 10.0."
#: /resources/lib/utils.py
msgctxt "#32019"
msgid "Attention"
msgstr "Atención"
#: /resources/lib/utils.py
msgctxt "#32020"
msgid "Set as default?"
msgstr "¿Establecer como predeterminado?"
#: /resources/settings.xml
msgctxt "#32021"
msgid "Enable .nfo updating for movies, TV shows and music videos"
msgstr "Activar actualización de .nfo para películas, series TV y videoclips"
#: /resources/lib/editor.py
msgctxt "#32022"
msgid "value unkown (missing Kodi feature)"
msgstr "valor desconocido (falta la función de Kodi)"
#: /resources/lib/editor.py
msgctxt "#32023"
msgid "Record label"
msgstr "Estudio de grabación"
#: /resources/settings.xml
msgctxt "#32025"
msgid "Preferred language"
msgstr "Idioma preferido"
#: /resources/settings.xml
msgctxt "#32026"
msgid "Scraper settings"
msgstr "Ajustes scraper"
#: /resources/lib/rating_updater.py
msgctxt "#32024"
msgid "Heavy server load. Please wait."
msgstr "Carga de servidor intensa. Por favor espere."
#: /resources/settings.xml
msgctxt "#32027"
msgid "TV show library is based on informations of"
msgstr "La biblioteca de serie TV se basa en información de"
#: /resources/settings.xml
msgctxt "#32029"
msgid "Enable JSON logging"
msgstr "Activar registro JSON"
#: /resources/settings.xml
msgctxt "#32030"
msgid "Rating updater"
msgstr "Actualizador de valoraciones"
#: /resources/settings.xml
msgctxt "#32028"
msgid "Run updating process in the background"
msgstr "Ejecutar el proceso de actualización en segundo plano"
#: /resources/settings.xml
msgctxt "#32031"
msgid "Your personal OMDb API key (www.omdbapi.com)"
msgstr "Su clave API personal en OMDb (www.omdbapi.com)"
#: /resources/settings.xml
msgctxt "#32032"
msgid "Search by title/year if IMDb ID is missing (not recommended)"
msgstr "Buscar por título/año si falta la ID IMDb (no recomendado)"
#: /default.py
msgctxt "#32035"
msgid ""
"No OMDb API key is configured, which is required to update IMDb, Rotten "
"Tomatoes and Metacritic ratings. Please visit www.omdbapi.com and create "
"your own API key.[CR][CR]Note: The free key is limited to 1000 calls a day. "
"Please suggest to become a patreon of OMDb to increase the limit to "
"100.000.[CR][CR]Do you want to proceed updating The Movie DB ratings? This "
"only works if you have a TMDb ID stored."
msgstr ""
"No ha configurado la clave API de OMDb, esta es requerida para actualizar "
"valoraciones desde IMDb, Rotten Tomatoes y Metacritic. Por favor visite "
"www.omdbapi.com y cree su propia clave API.[CR][CR]Nota: La clave API "
"gratuita está limitada a 1000 solicitudes diarias. Considere convertirse en "
"donante de OMDb para aumentar este límite a 100.000.[CR][CR]¿Quiere proceder"
" a actualizar las valoraciones desde The Movie DB? Esto solo funcionara si "
"tiene una ID de TMDb almacenada."
#: /default.py
msgctxt "#32036"
msgid "Update TV show ratings"
msgstr "Actualizar valoraciones de Series TV"
#: /resources/lib/rating_updater.py
msgctxt "#32033"
msgid ""
"OMDB API limit reached. Please consider to become a Patreon to increase your"
" daily call limitation. Proceed by only using The Movie DB?"
msgstr ""
"Limite de API OMDB alcanzado. Por favor, considere convertirse en donante "
"para aumentar su limite de solicitudes diarias. ¿Proceder usando solo The "
"Movie DB?"
#: /resources/settings.xml
msgctxt "#32034"
msgid "Create .nfo file if missing"
msgstr "Crear archivo .nfo si está pendiente"
#: /default.py
msgctxt "#32037"
msgid "Update movie ratings"
msgstr "Actualizar valoraciones de películas"
#: /default.py
msgctxt "#32038"
msgid "Update all ratings"
msgstr "Actualizar todas las valoraciones"
#: /context.py
msgctxt "#32039"
msgid "Update ratings"
msgstr "Actualizar valoraciones"
#: /resources/lib/editor.py
msgctxt "#32040"
msgid "Edit data for"
msgstr "Editar datos para"
#: /resources/lib/rating_updater.py
msgctxt "#32042"
msgid "Canceled"
msgstr "Cancelado"
#: /resources/settings.xml
msgctxt "#32043"
msgid "MPAA region"
msgstr "Región MPAA"
#: /resources/settings.xml
msgctxt "#32041"
msgid "Update premiered/year if database value is different"
msgstr ""
"Actualizar premiered/año si los valores de la base de datos son diferentes."
#: /resources/settings.xml
msgctxt "#32044"
msgid "Skip updating of MPAA"
msgstr "Omitir actualización de MPAA"
#: /default.py
msgctxt "#32045"
msgid "Update episode ratings"
msgstr "Actualizar valoraciones de episodios"
#: /resources/lib/editor.py
msgctxt "#32047"
msgid "No default source defined"
msgstr "No hay una fuente predeterminada definida"
#: /resources/lib/rating_updater.py
msgctxt "#32048"
msgid "No items found"
msgstr "No se encontraron elementos"
#: /context.py
msgctxt "#32046"
msgid "Update .nfo"
msgstr "Actualizar .nfo"
#: /default.py
msgctxt "#32049"
msgid "Incomplete arguments or content type not supported"
msgstr "Argumentos incompletos o tipo de contenido no soportado"
#: /default.py
msgctxt "#32050"
msgid "Do you want to cancel the update?"
msgstr "¿Desea cancelar la actualización?"
#: /default.py
msgctxt "#32051"
msgid "Content"
msgstr "Contenido"
#: /resources/settings.xml
msgctxt "#32052"
msgid "Fallback to US MPAA if configured country has no certification stored"
msgstr ""
"Recurrir a MPAA de EE. UU. Si el país configurado no tiene ninguna "
"certificación almacenada"
#: /resources/settings.xml
msgctxt "#32053"
msgid "Don't store \"NR\" (Not rated) MPAA rating"
msgstr "No almacenar \"NR\" (Not rated) valoración MPAA"
#: /service.py
msgctxt "#32054"
msgid "Do you want to rate the following item?"
msgstr "¿Quiere valorar el siguiente elemento?"
#: /resources/settings.xml
msgctxt "#32055"
msgid "Automatically update changed watched states to .nfo"
msgstr "Actualizar automáticamente los estados de vistos modificados a .nfo"
#: /resources/settings.xml
msgctxt "#32056"
msgid "Rate your media if playback has ended"
msgstr "Calificar sus medios si la reproducción ha finalizado"
#: /resources/settings.xml
msgctxt "#32057"
msgid "Write watched flag and playcount to .nfo"
msgstr "Escribir etiqueta de visto y recuento de reproducciones en .nfo"

View File

@@ -0,0 +1,274 @@
# Metadata Editor language file
# Addon Name: Metadata Editor
# Addon id: script.metadata.editor
# Addon Provider: sualfred
# Translators:
# Andrea Matesi <andreamatesi@gmail.com>, 2019
#
msgid ""
msgstr ""
"Project-Id-Version: Metadata Editor\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2019-11-07 08:05+0000\n"
"Last-Translator: Andrea Matesi <andreamatesi@gmail.com>, 2019\n"
"Language-Team: Italian (Italy) (https://www.transifex.com/sualfred/teams/80018/it_IT/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: it_IT\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: /addon.xml
msgctxt "#32000"
msgid "Metadata Editor"
msgstr "Editor Metadati"
#: /resources/lib/dialog.py
msgctxt "#32001"
msgid "User rating"
msgstr "Valutazione utente"
#: /resources/lib/dialog_videogenres.py
msgctxt "#32002"
msgid "Available entries"
msgstr "Voci disponibili"
#: /addon.xml
msgctxt "#32003"
msgid "Add/remove available tags"
msgstr "Aggiungi/rimuovi tag disponibili"
#: /addon.xml
msgctxt "#32004"
msgid "Add/remove available genres"
msgstr "Aggiungi/rimuovi generi disponibili"
#: /resources/lib/utils.py
msgctxt "#32005"
msgid "Add new item"
msgstr "Aggiungi nuovo oggetto"
#: /resources/lib/utils.py
msgctxt "#32006"
msgid "Edit current list as string"
msgstr "Modifica lista attuale come stringa"
#: /resources/lib/utils.py
msgctxt "#32007"
msgid "Select from available items"
msgstr "Seleziona dagli oggetti disponibili"
#: /context.py
msgctxt "#32008"
msgid "Remove watchlist tag"
msgstr "Rimuovi tag da vedere"
#: /context.py
msgctxt "#32009"
msgid "Add watchlist tag"
msgstr "Aggiungi tag da vedere"
#: /context.py
msgctxt "#32010"
msgid "Open editor"
msgstr "Apri editor"
#: /resources/lib/utils.py
msgctxt "#32011"
msgid "Enter floating number"
msgstr "Inserisci numero decimale"
#: /resources/lib/utils.py
msgctxt "#32012"
msgid "Select source"
msgstr "Seleziona sorgente"
#: /resources/lib/utils.py
msgctxt "#32013"
msgid "Available sources"
msgstr "Sorgenti disponibili"
#: /resources/lib/utils.py
msgctxt "#32014"
msgid "Default source"
msgstr "Sorgente predefinita"
#: /resources/lib/utils.py
msgctxt "#32015"
msgid "Select default source"
msgstr "Seleziona sorgente predefinita"
#: /resources/lib/utils.py
msgctxt "#32016"
msgid "Edit ratings and votes"
msgstr "Modifica voti e valutazioni"
#: /resources/lib/utils.py
msgctxt "#32017"
msgid "Add source"
msgstr "Aggiungi sorgente"
#: /resources/lib/utils.py
msgctxt "#32018"
msgid "Only values between 1.0 and 10.0 are allowed."
msgstr "Solo i valori compresi tra 1.0 e 10.0 sono consentiti"
#: /resources/lib/utils.py
msgctxt "#32019"
msgid "Attention"
msgstr "Attenzione"
#: /resources/lib/utils.py
msgctxt "#32020"
msgid "Set as default?"
msgstr "Imposta come predefinito?"
#: /resources/settings.xml
msgctxt "#32021"
msgid "Enable .nfo updating for movies, TV shows and music videos"
msgstr "Attiva aggiornamento .nfo per film, serie TV e video musicali"
#: /resources/lib/editor.py
msgctxt "#32022"
msgid "value unkown (missing Kodi feature)"
msgstr "valore sconosciuto (funzionalità Kodi mancante)"
#: /resources/lib/editor.py
msgctxt "#32023"
msgid "Record label"
msgstr "Casa discografica"
#: /default.py
msgctxt "#32024"
msgid "Please use the context menu on a library item to run this script."
msgstr ""
"Si prega di usare il menu contestuale su un oggetto libreria per eseguire "
"questo script"
#: /resources/settings.xml
msgctxt "#32025"
msgid "Preferred TMDb language"
msgstr "Lingua TMDb preferita"
#: /resources/settings.xml
msgctxt "#32026"
msgid "TV show scraper related settings"
msgstr "Impostazioni relative a scraper Serie TV "
#: /resources/settings.xml
msgctxt "#32027"
msgid "Library is based on informations of"
msgstr "Libreria basata su informazioni relative a "
#: /resources/settings.xml
msgctxt "#32029"
msgid "Enable JSON logging"
msgstr "Attiva logging JSON"
#: /resources/settings.xml
msgctxt "#32030"
msgid "Rating updater"
msgstr "Updater valutazioni"
#: /resources/settings.xml
msgctxt "#32028"
msgid "Run updating process in the background"
msgstr "Esegui processo di aggiornamento nel sottofondo"
#: /resources/settings.xml
msgctxt "#32031"
msgid "Your personal OMDb API key (www.omdbapi.com)"
msgstr "Chiave personale OMDb API (www.obdbapi.com)"
#: /resources/settings.xml
msgctxt "#32032"
msgid "Search OMDb with title/year if IMDb is missing"
msgstr "Ricerca OMDB in base al titolo/anno se IMDb non esiste"
#: /resources/lib/rating_updater.py
msgctxt "#32033"
msgid "Updating movie ratings"
msgstr "Aggiornamento valutazioni film"
#: /resources/lib/rating_updater.py
msgctxt "#32034"
msgid "Updating TV show ratings"
msgstr "Aggiornamento valutazioni Serie TV"
#: /default.py
msgctxt "#32035"
msgid ""
"No OMDb API key is configured, which is required to update IMDb, Rotten "
"Tomatoes and Metacritic ratings. Please visit www.omdbapi.com and create "
"your own API key.[CR][CR]Note: The free key is limited to 1000 calls a day. "
"Please suggest to become a patreon of OMDb to increase the limit to "
"100.000.[CR][CR]Do you want to proceed updating The Movie DB ratings? This "
"only works if you have a TMDb ID stored."
msgstr ""
"Nessuna chiave OMDb API configurata, ciò è richiesto per aggiornare "
"valutazioni IMDb, Rotten Tomatoes e Metacritic. Si prega di visitare "
"www.omdbapi.com per generare la propria chiave API.[CR][CR]Nota: chiave "
"gratuita limitata a 1000 aggiornamenti al giorno. Al fine di incrementare il"
" limite a 100,000, si raccomanda diventare patreon di OMDB.[CR][CR] Desideri"
" procedere con l'aggiornamento delle valutazioni The Movie DB? Funzione "
"disponibile solo se hai un ID TMDb salvato."
#: /default.py
msgctxt "#32036"
msgid "Update TV show ratings"
msgstr "Aggiorna valutazioni Serie TV"
#: /default.py
msgctxt "#32037"
msgid "Update movie ratings"
msgstr "Aggiorna valutazioni film"
#: /default.py
msgctxt "#32038"
msgid "Update all ratings"
msgstr "Aggiorna tutte le valutazioni"
#: /context.py
msgctxt "#32039"
msgid "Update ratings"
msgstr "Aggiorna valutazioni"
#: /resources/lib/editor.py
msgctxt "#32040"
msgid "Edit data for"
msgstr "Modifica dati per"
#: /default.py
msgctxt "#32041"
msgid "Cancel updating"
msgstr "Annulla aggiornamento"
#: /resources/lib/rating_updater.py
msgctxt "#32042"
msgid "Canceled"
msgstr "Annullato"
#: /resources/settings.xml
msgctxt "#32043"
msgid "MPAA region"
msgstr "Regione MPAA"
#: /resources/settings.xml
msgctxt "#32044"
msgid "Skip updating of MPAA"
msgstr "Salta aggiornamento MPAA"
#: /default.py
msgctxt "#32045"
msgid "Update episode ratings"
msgstr "Aggiorna valutazione episodi"
#: /resources/lib/rating_updater.py
msgctxt "#32046"
msgid "Updating episode ratings"
msgstr "Aggiornamento valutazione episodi"
#: /resources/lib/editor.py
msgctxt "#32047"
msgid "No default source defined"
msgstr "Nessuna sorgente definita"

View File

@@ -0,0 +1,328 @@
# Metadata Editor language file
# Addon Name: Metadata Editor
# Addon id: script.metadata.editor
# Addon Provider: sualfred
# Translators:
# David Claes <d3claes@gmail.com>, 2020
#
msgid ""
msgstr ""
"Project-Id-Version: Metadata Editor\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2019-11-07 08:05+0000\n"
"Last-Translator: David Claes <d3claes@gmail.com>, 2020\n"
"Language-Team: Dutch (Netherlands) (https://www.transifex.com/sualfred/teams/80018/nl_NL/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: nl_NL\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: /addon.xml
msgctxt "#32000"
msgid "Metadata Editor"
msgstr "Metadata Editor"
#: /resources/lib/dialog.py
msgctxt "#32001"
msgid "User rating"
msgstr "Gebruikersbeoordeling"
#: /resources/lib/dialog_videogenres.py
msgctxt "#32002"
msgid "Available entries"
msgstr "Beschikbare vermeldingen"
#: /addon.xml
msgctxt "#32003"
msgid "Add/remove available tags"
msgstr "Beschikbare labels toevoegen/verwijderen"
#: /addon.xml
msgctxt "#32004"
msgid "Add/remove available genres"
msgstr "Beschikbare genres toevoegen/verwijderen"
#: /resources/lib/utils.py
msgctxt "#32005"
msgid "Add new item"
msgstr "Nieuw item toevoegen"
#: /resources/lib/utils.py
msgctxt "#32006"
msgid "Edit current list as string"
msgstr "Huidige lijst als string bewerken"
#: /resources/lib/utils.py
msgctxt "#32007"
msgid "Select from available items"
msgstr "Kiezen uit beschikbare items"
#: /context.py
msgctxt "#32008"
msgid "Remove watchlist tag"
msgstr "Kijklijst label verwijderen"
#: /context.py
msgctxt "#32009"
msgid "Add watchlist tag"
msgstr "Kijklijst label toevoegen"
#: /context.py
msgctxt "#32010"
msgid "Open editor"
msgstr "Editor openen"
#: /resources/lib/utils.py
msgctxt "#32011"
msgid "Enter floating number"
msgstr "Kommagetal invoeren"
#: /resources/lib/utils.py
msgctxt "#32012"
msgid "Select source"
msgstr "Bron kiezen"
#: /resources/lib/utils.py
msgctxt "#32013"
msgid "Available sources"
msgstr "Beschikbare bronnen"
#: /resources/lib/utils.py
msgctxt "#32014"
msgid "Default source"
msgstr "Standaardbron"
#: /resources/lib/utils.py
msgctxt "#32015"
msgid "Select default source"
msgstr "Standaardbron kiezen"
#: /resources/lib/utils.py
msgctxt "#32016"
msgid "Edit ratings and votes"
msgstr "Beoordelingen en stemmen bewerken"
#: /resources/lib/utils.py
msgctxt "#32017"
msgid "Add source"
msgstr "Bron toevoegen"
#: /resources/lib/utils.py
msgctxt "#32018"
msgid "Only values between 1.0 and 10.0 are allowed."
msgstr "Enkel waarden tussen 1.0 en 10.0 zijn toegelaten."
#: /resources/lib/utils.py
msgctxt "#32019"
msgid "Attention"
msgstr "Opgelet"
#: /resources/lib/utils.py
msgctxt "#32020"
msgid "Set as default?"
msgstr "Als standaard instellen?"
#: /resources/settings.xml
msgctxt "#32021"
msgid "Enable .nfo updating for movies, TV shows and music videos"
msgstr ".nfo-updates voor films, tv-shows en muziekvideo's inschakelen"
#: /resources/lib/editor.py
msgctxt "#32022"
msgid "value unkown (missing Kodi feature)"
msgstr "onbekende waarde (ontbrekende Kodi-functie)"
#: /resources/lib/editor.py
msgctxt "#32023"
msgid "Record label"
msgstr "Opnamelabel"
#: /resources/settings.xml
msgctxt "#32025"
msgid "Preferred language"
msgstr "Voorkeurstaal"
#: /resources/settings.xml
msgctxt "#32026"
msgid "Scraper settings"
msgstr "Schraperinstellingen"
#: /resources/lib/rating_updater.py
msgctxt "#32024"
msgid "Heavy server load. Please wait."
msgstr "Zware serverbelasting. Even geduld a.u.b."
#: /resources/settings.xml
msgctxt "#32027"
msgid "TV show library is based on informations of"
msgstr "Bibliotheek TV-series is gebaseerd op informatie van"
#: /resources/settings.xml
msgctxt "#32029"
msgid "Enable JSON logging"
msgstr "JSON-logboekregistratie inschakelen"
#: /resources/settings.xml
msgctxt "#32030"
msgid "Rating updater"
msgstr "Beoordelingsupdater"
#: /resources/settings.xml
msgctxt "#32028"
msgid "Run updating process in the background"
msgstr "Het updateproces op de achtergrond uitvoeren"
#: /resources/settings.xml
msgctxt "#32031"
msgid "Your personal OMDb API key (www.omdbapi.com)"
msgstr "Uw persoonlijke OMDb API key (www.omdbapi.com)"
#: /resources/settings.xml
msgctxt "#32032"
msgid "Search by title/year if IMDb ID is missing (not recommended)"
msgstr "Zoeken op titel/jaar als IMDb ID ontbreekt (niet aanbevolen)"
#: /default.py
msgctxt "#32035"
msgid ""
"No OMDb API key is configured, which is required to update IMDb, Rotten "
"Tomatoes and Metacritic ratings. Please visit www.omdbapi.com and create "
"your own API key.[CR][CR]Note: The free key is limited to 1000 calls a day. "
"Please suggest to become a patreon of OMDb to increase the limit to "
"100.000.[CR][CR]Do you want to proceed updating The Movie DB ratings? This "
"only works if you have a TMDb ID stored."
msgstr ""
"Er is geen OMDb API-sleutel geconfigureerd, die nodig is om IMDb, Rotten "
"Tomatoes en Metacritic-beoordelingen bij te werken. Ga naar www.omdbapi.com "
"en maak uw eigen API-sleutel aan.[CR][CR]Opmerking: de gratis sleutel is "
"beperkt tot 1000 oproepen per dag. Overweeg om een patreon van OMDb te "
"worden om de limiet naar 100.000 te verhogen.[CR][CR] Wilt u doorgaan met "
"het bijwerken van The Movie DB-beoordelingen? Dit werkt alleen als u een "
"TMDb-ID hebt opgeslagen."
#: /default.py
msgctxt "#32036"
msgid "Update TV show ratings"
msgstr "Beoordelingen van TV-series bijwerken"
#: /resources/lib/rating_updater.py
msgctxt "#32033"
msgid ""
"OMDB API limit reached. Please consider to become a Patreon to increase your"
" daily call limitation. Proceed by only using The Movie DB?"
msgstr ""
"OMDB API-limiet bereikt. Overweeg a.u.b. om een Patreon te worden om uw "
"dagelijkse aanroepbeperking te verhogen. Enkel verdergaan met The Movie DB?"
#: /resources/settings.xml
msgctxt "#32034"
msgid "Create .nfo file if missing"
msgstr ".nfo bestand aanmaken als het ontbreekt"
#: /default.py
msgctxt "#32037"
msgid "Update movie ratings"
msgstr "Beoordelingen van films bijwerken"
#: /default.py
msgctxt "#32038"
msgid "Update all ratings"
msgstr "Alle beoordelingen bijwerken"
#: /context.py
msgctxt "#32039"
msgid "Update ratings"
msgstr "Beoordelingen bijwerken"
#: /resources/lib/editor.py
msgctxt "#32040"
msgid "Edit data for"
msgstr "Data bewerken voor"
#: /resources/lib/rating_updater.py
msgctxt "#32042"
msgid "Canceled"
msgstr "Geannuleerd"
#: /resources/settings.xml
msgctxt "#32043"
msgid "MPAA region"
msgstr "MPAA regio"
#: /resources/settings.xml
msgctxt "#32041"
msgid "Update premiered/year if database value is different"
msgstr "Première/jaar bijwerken als de databasewaarde anders is"
#: /resources/settings.xml
msgctxt "#32044"
msgid "Skip updating of MPAA"
msgstr "Bijwerken van MPAA overslaan"
#: /default.py
msgctxt "#32045"
msgid "Update episode ratings"
msgstr "Beoordelingen van afleveringen bijwerken"
#: /resources/lib/editor.py
msgctxt "#32047"
msgid "No default source defined"
msgstr "Geen standaardbron gedefinieerd"
#: /resources/lib/rating_updater.py
msgctxt "#32048"
msgid "No items found"
msgstr "Geen items gevonden"
#: /context.py
msgctxt "#32046"
msgid "Update .nfo"
msgstr ".nfo bijwerken"
#: /default.py
msgctxt "#32049"
msgid "Incomplete arguments or content type not supported"
msgstr "Onvolledige argumenten of inhoudstype niet ondersteund"
#: /default.py
msgctxt "#32050"
msgid "Do you want to cancel the update?"
msgstr "Wilt u de bijwerking annuleren?"
#: /default.py
msgctxt "#32051"
msgid "Content"
msgstr "Inhoud"
#: /resources/settings.xml
msgctxt "#32052"
msgid "Fallback to US MPAA if configured country has no certification stored"
msgstr ""
"Terugvallen op US MPAA als ingesteld land geen certificering heeft "
"opgeslagen"
#: /resources/settings.xml
msgctxt "#32053"
msgid "Don't store \"NR\" (Not rated) MPAA rating"
msgstr "MPAA NR-beoordeling niet opslaan (NR = No rating = geen beoordeling)"
#: /service.py
msgctxt "#32054"
msgid "Do you want to rate the following item?"
msgstr "Wilt u het volgende item beoordelen?"
#: /resources/settings.xml
msgctxt "#32055"
msgid "Automatically update changed watched states to .nfo"
msgstr "Automatische bijwerking wijzigde kijkstatus naar .nfo"
#: /resources/settings.xml
msgctxt "#32056"
msgid "Rate your media if playback has ended"
msgstr "Beoordeel uw media als het afspelen beëindigd is"
#: /resources/settings.xml
msgctxt "#32057"
msgid "Write watched flag and playcount to .nfo"
msgstr "Kijkstatus (bekeken) en kijkteller wegschrijven naar .nfo"

View File

@@ -0,0 +1,146 @@
# Metadata Editor language file
# Addon Name: Metadata Editor
# Addon id: script.metadata.editor
# Addon Provider: sualfred
# Translators:
# Edjalmo Bf <edjalmo.bf@hotmail.com>, 2019
#
msgid ""
msgstr ""
"Project-Id-Version: Metadata Editor\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2019-11-07 08:05+0000\n"
"Last-Translator: Edjalmo Bf <edjalmo.bf@hotmail.com>, 2019\n"
"Language-Team: Portuguese (Brazil) (https://www.transifex.com/sualfred/teams/80018/pt_BR/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pt_BR\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: /addon.xml
msgctxt "#32000"
msgid "Metadata Editor"
msgstr "Editor de Metadados"
#: /resources/lib/dialog.py
msgctxt "#32001"
msgid "User rating"
msgstr "Avaliação do usuário"
#: /resources/lib/dialog_videogenres.py
msgctxt "#32002"
msgid "Available entries"
msgstr "Entradas disponíveis"
#: /addon.xml
msgctxt "#32003"
msgid "Add/remove available tags"
msgstr "Add/remover tags disponíveis"
#: /addon.xml
msgctxt "#32004"
msgid "Add/remove available genres"
msgstr "Add/remover gêneros disponíveis"
#: /resources/lib/utils.py
msgctxt "#32005"
msgid "Add new item"
msgstr "Add novo item"
#: /resources/lib/utils.py
msgctxt "#32006"
msgid "Modify current list"
msgstr "Modificar lista atual"
#: /resources/lib/utils.py
msgctxt "#32007"
msgid "Select from available items"
msgstr "Selecionar de itens disponíveis"
#: /context.py
msgctxt "#32008"
msgid "Remove favourite tag"
msgstr "Remover tag favorita"
#: /context.py
msgctxt "#32009"
msgid "Add favourite tag"
msgstr "Add tag favorita"
#: /context.py
msgctxt "#32010"
msgid "Open editor"
msgstr "Editor livre"
#: /resources/lib/utils.py
msgctxt "#32011"
msgid "Enter floating number"
msgstr "Digite um número real"
#: /resources/lib/utils.py
msgctxt "#32012"
msgid "Select source"
msgstr "Selecionar caminho"
#: /resources/lib/utils.py
msgctxt "#32013"
msgid "Available sources"
msgstr "Caminhos disponíveis"
#: /resources/lib/utils.py
msgctxt "#32014"
msgid "Default source"
msgstr "Caminho padrão"
#: /resources/lib/utils.py
msgctxt "#32015"
msgid "Select default source"
msgstr "Selecionar caminho padrão"
#: /resources/lib/utils.py
msgctxt "#32016"
msgid "Edit ratings and votes"
msgstr "Editar notas e votos"
#: /resources/lib/utils.py
msgctxt "#32017"
msgid "Add source"
msgstr "Add caminho"
#: /resources/lib/utils.py
msgctxt "#32018"
msgid "Only values between 1.0 and 10.0 are allowed."
msgstr "Somente valores entre 1.0 e 10.0 são permitidos."
#: /resources/lib/utils.py
msgctxt "#32019"
msgid "Attention"
msgstr "Atenção"
#: /resources/lib/utils.py
msgctxt "#32020"
msgid "Set as default?"
msgstr "Definir como padrão?"
#: /resources/settings.xml
msgctxt "#32021"
msgid "Enable .nfo updating for movies, TV shows and music videos"
msgstr "Ativar atualização de .nfo para filmes, seriados e videoclipes"
#: /resources/lib/editor.py
msgctxt "#32022"
msgid "value unkown (missing Kodi feature)"
msgstr "valor desconhecidos (faltando recurso do Kodi)"
#: /resources/lib/editor.py
msgctxt "#32023"
msgid "Record label"
msgstr "Gravadora"
#: /default.py
msgctxt "#32024"
msgid "Please use the context menu on a library item to run this script."
msgstr ""
"Por favor, use o menu de contexto em um item da biblioteca para executar "
"este script."

View File

@@ -0,0 +1,274 @@
# Metadata Editor language file
# Addon Name: Metadata Editor
# Addon id: script.metadata.editor
# Addon Provider: sualfred
# Translators:
# Эдуард Приутеса <eduardpriutesa@gmail.com>, 2019
#
msgid ""
msgstr ""
"Project-Id-Version: Metadata Editor\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2019-11-07 08:05+0000\n"
"Last-Translator: Эдуард Приутеса <eduardpriutesa@gmail.com>, 2019\n"
"Language-Team: Russian (Russia) (https://www.transifex.com/sualfred/teams/80018/ru_RU/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ru_RU\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
#: /addon.xml
msgctxt "#32000"
msgid "Metadata Editor"
msgstr "Редактор метаданных"
#: /resources/lib/dialog.py
msgctxt "#32001"
msgid "User rating"
msgstr "Рейтинг пользователей"
#: /resources/lib/dialog_videogenres.py
msgctxt "#32002"
msgid "Available entries"
msgstr "Доступные записи"
#: /addon.xml
msgctxt "#32003"
msgid "Add/remove available tags"
msgstr "Добавить / удалить доступные теги"
#: /addon.xml
msgctxt "#32004"
msgid "Add/remove available genres"
msgstr "Добавить / удалить доступные жанры"
#: /resources/lib/utils.py
msgctxt "#32005"
msgid "Add new item"
msgstr "Добавление нового элемента"
#: /resources/lib/utils.py
msgctxt "#32006"
msgid "Edit current list as string"
msgstr "Изменить текущий список как строку"
#: /resources/lib/utils.py
msgctxt "#32007"
msgid "Select from available items"
msgstr "Выберите из доступных предметов"
#: /context.py
msgctxt "#32008"
msgid "Remove watchlist tag"
msgstr "Удалить тег списка наблюдения"
#: /context.py
msgctxt "#32009"
msgid "Add watchlist tag"
msgstr "Добавить тег наблюдения"
#: /context.py
msgctxt "#32010"
msgid "Open editor"
msgstr "Открыть редактор"
#: /resources/lib/utils.py
msgctxt "#32011"
msgid "Enter floating number"
msgstr "Введите плавающее число"
#: /resources/lib/utils.py
msgctxt "#32012"
msgid "Select source"
msgstr "Выберите источник"
#: /resources/lib/utils.py
msgctxt "#32013"
msgid "Available sources"
msgstr "Доступные источники"
#: /resources/lib/utils.py
msgctxt "#32014"
msgid "Default source"
msgstr "Источник по умолчанию"
#: /resources/lib/utils.py
msgctxt "#32015"
msgid "Select default source"
msgstr "Выберите источник по умолчанию"
#: /resources/lib/utils.py
msgctxt "#32016"
msgid "Edit ratings and votes"
msgstr "Редактировать рейтинги и голоса"
#: /resources/lib/utils.py
msgctxt "#32017"
msgid "Add source"
msgstr "Добавить источник"
#: /resources/lib/utils.py
msgctxt "#32018"
msgid "Only values between 1.0 and 10.0 are allowed."
msgstr "Допустимы только значения от 1,0 до 10,0."
#: /resources/lib/utils.py
msgctxt "#32019"
msgid "Attention"
msgstr "Внимание!"
#: /resources/lib/utils.py
msgctxt "#32020"
msgid "Set as default?"
msgstr "Установить по умолчанию?"
#: /resources/settings.xml
msgctxt "#32021"
msgid "Enable .nfo updating for movies, TV shows and music videos"
msgstr "Включить обновление .nfo для фильмов, сериалов и музыкальных клипов"
#: /resources/lib/editor.py
msgctxt "#32022"
msgid "value unkown (missing Kodi feature)"
msgstr "Значение неизвестно (отсутствует функция Kodi)"
#: /resources/lib/editor.py
msgctxt "#32023"
msgid "Record label"
msgstr "Запись метки"
#: /default.py
msgctxt "#32024"
msgid "Please use the context menu on a library item to run this script."
msgstr ""
"Пожалуйста, используйте контекстное меню элемента библиотеки, чтобы "
"запустить этот скрипт."
#: /resources/settings.xml
msgctxt "#32025"
msgid "Preferred TMDb language"
msgstr "Предпочитаемый язык TMDb"
#: /resources/settings.xml
msgctxt "#32026"
msgid "TV show scraper related settings"
msgstr "Настройки скрепера для сериалов"
#: /resources/settings.xml
msgctxt "#32027"
msgid "Library is based on informations of"
msgstr "Библиотека основана на информации"
#: /resources/settings.xml
msgctxt "#32029"
msgid "Enable JSON logging"
msgstr "Включить ведение журнала JSON"
#: /resources/settings.xml
msgctxt "#32030"
msgid "Rating updater"
msgstr "Обновление рейтинга"
#: /resources/settings.xml
msgctxt "#32028"
msgid "Run updating process in the background"
msgstr "Запустите процесс обновления в фоновом режиме"
#: /resources/settings.xml
msgctxt "#32031"
msgid "Your personal OMDb API key (www.omdbapi.com)"
msgstr "Ваш личный ключ API OMDb (www.omdbapi.com)"
#: /resources/settings.xml
msgctxt "#32032"
msgid "Search OMDb with title/year if IMDb is missing"
msgstr "Поиск OMDb с названием / годом, если IMDb отсутствует"
#: /resources/lib/rating_updater.py
msgctxt "#32033"
msgid "Updating movie ratings"
msgstr "Обновление рейтингов фильмов"
#: /resources/lib/rating_updater.py
msgctxt "#32034"
msgid "Updating TV show ratings"
msgstr "Обновление рейтингов сериалов"
#: /default.py
msgctxt "#32035"
msgid ""
"No OMDb API key is configured, which is required to update IMDb, Rotten "
"Tomatoes and Metacritic ratings. Please visit www.omdbapi.com and create "
"your own API key.[CR][CR]Note: The free key is limited to 1000 calls a day. "
"Please suggest to become a patreon of OMDb to increase the limit to "
"100.000.[CR][CR]Do you want to proceed updating The Movie DB ratings? This "
"only works if you have a TMDb ID stored."
msgstr ""
"Не настроен ключ API OMDb, который необходим для обновления рейтингов IMDb, "
"Rotten Tomatoes и Metacritic . Пожалуйста, посетите www.omdbapi.com и "
"создайте свой собственный ключ API. [CR] [CR] Примечание: бесплатный ключ "
"ограничен 1000 звонками в день. Пожалуйста, предложите стать партнёром OMDb,"
" чтобы увеличить лимит до 100.000. [CR] [CR] Хотите продолжить обновление "
"рейтинга The Movie DB? Это работает, только если у вас есть идентификатор "
"TMDb."
#: /default.py
msgctxt "#32036"
msgid "Update TV show ratings"
msgstr "Обновление рейтингов сериалов"
#: /default.py
msgctxt "#32037"
msgid "Update movie ratings"
msgstr "Обновить рейтинги фильмов"
#: /default.py
msgctxt "#32038"
msgid "Update all ratings"
msgstr "Обновить все рейтинги"
#: /context.py
msgctxt "#32039"
msgid "Update ratings"
msgstr "Обновить рейтинги"
#: /resources/lib/editor.py
msgctxt "#32040"
msgid "Edit data for"
msgstr "Изменить данные для"
#: /default.py
msgctxt "#32041"
msgid "Cancel updating"
msgstr "Отменить обновление"
#: /resources/lib/rating_updater.py
msgctxt "#32042"
msgid "Canceled"
msgstr "Отменен"
#: /resources/settings.xml
msgctxt "#32043"
msgid "MPAA region"
msgstr "MPAA регион"
#: /resources/settings.xml
msgctxt "#32044"
msgid "Skip updating of MPAA"
msgstr "Пропустить обновление MPAA"
#: /default.py
msgctxt "#32045"
msgid "Update episode ratings"
msgstr "Обновление рейтингов эпизодов"
#: /resources/lib/rating_updater.py
msgctxt "#32046"
msgid "Updating episode ratings"
msgstr "Обновление рейтингов эпизодов"
#: /resources/lib/editor.py
msgctxt "#32047"
msgid "No default source defined"
msgstr "Источник по умолчанию не определен"

View File

@@ -0,0 +1,329 @@
# Metadata Editor language file
# Addon Name: Metadata Editor
# Addon id: script.metadata.editor
# Addon Provider: sualfred
# Translators:
# Snn 1452 <snn1452@gmail.com>, 2020
#
msgid ""
msgstr ""
"Project-Id-Version: Metadata Editor\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: 2019-11-07 08:05+0000\n"
"Last-Translator: Snn 1452 <snn1452@gmail.com>, 2020\n"
"Language-Team: Turkish (Turkey) (https://www.transifex.com/sualfred/teams/80018/tr_TR/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: tr_TR\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: /addon.xml
msgctxt "#32000"
msgid "Metadata Editor"
msgstr "Metaveri Düzenleyici"
#: /resources/lib/dialog.py
msgctxt "#32001"
msgid "User rating"
msgstr "Kullanıcı derecelendirmesi"
#: /resources/lib/dialog_videogenres.py
msgctxt "#32002"
msgid "Available entries"
msgstr "Mevcut girişler"
#: /addon.xml
msgctxt "#32003"
msgid "Add/remove available tags"
msgstr "Mevcut etiketleri ekle/kaldır"
#: /addon.xml
msgctxt "#32004"
msgid "Add/remove available genres"
msgstr "Mevcut türleri ekle/kaldır"
#: /resources/lib/utils.py
msgctxt "#32005"
msgid "Add new item"
msgstr "Yeni öğe ekle"
#: /resources/lib/utils.py
msgctxt "#32006"
msgid "Edit current list as string"
msgstr "Geçerli listeyi dize olarak düzenle"
#: /resources/lib/utils.py
msgctxt "#32007"
msgid "Select from available items"
msgstr "Mevcut öğelerden seç"
#: /context.py
msgctxt "#32008"
msgid "Remove watchlist tag"
msgstr "İzleme listesi etiketini kaldır"
#: /context.py
msgctxt "#32009"
msgid "Add watchlist tag"
msgstr "İzleme listesi etiketi ekle"
#: /context.py
msgctxt "#32010"
msgid "Open editor"
msgstr "Düzenleyiciyi aç"
#: /resources/lib/utils.py
msgctxt "#32011"
msgid "Enter floating number"
msgstr "Yüzen numarayı girin"
#: /resources/lib/utils.py
msgctxt "#32012"
msgid "Select source"
msgstr "Kaynak Seç"
#: /resources/lib/utils.py
msgctxt "#32013"
msgid "Available sources"
msgstr "Mevcut kaynaklar"
#: /resources/lib/utils.py
msgctxt "#32014"
msgid "Default source"
msgstr "Varsayılan kaynak"
#: /resources/lib/utils.py
msgctxt "#32015"
msgid "Select default source"
msgstr "Varsayılan kaynağı seç"
#: /resources/lib/utils.py
msgctxt "#32016"
msgid "Edit ratings and votes"
msgstr "Derecelendirmeleri ve oyları düzenle"
#: /resources/lib/utils.py
msgctxt "#32017"
msgid "Add source"
msgstr "Kaynak ekle"
#: /resources/lib/utils.py
msgctxt "#32018"
msgid "Only values between 1.0 and 10.0 are allowed."
msgstr "Yalnızca 1.0 ile 10.0 arasındaki değerlere izin verilir."
#: /resources/lib/utils.py
msgctxt "#32019"
msgid "Attention"
msgstr "Dikkat"
#: /resources/lib/utils.py
msgctxt "#32020"
msgid "Set as default?"
msgstr "Varsayılan olarak ayarla?"
#: /resources/settings.xml
msgctxt "#32021"
msgid "Enable .nfo updating for movies, TV shows and music videos"
msgstr ""
"Filmler, TV programları ve müzik videoları için .nfo güncellemesini "
"etkinleştir"
#: /resources/lib/editor.py
msgctxt "#32022"
msgid "value unkown (missing Kodi feature)"
msgstr "bilinmeyen değer (eksik Kodi özelliği)"
#: /resources/lib/editor.py
msgctxt "#32023"
msgid "Record label"
msgstr "Kayıt etiketi"
#: /resources/settings.xml
msgctxt "#32025"
msgid "Preferred language"
msgstr "Tercih edilen dil"
#: /resources/settings.xml
msgctxt "#32026"
msgid "Scraper settings"
msgstr "Scraper ayarları"
#: /resources/lib/rating_updater.py
msgctxt "#32024"
msgid "Heavy server load. Please wait."
msgstr "Ağır sunucu yükü. Lütfen bekleyin."
#: /resources/settings.xml
msgctxt "#32027"
msgid "TV show library is based on informations of"
msgstr "TV programları kitaplığı bilgilerine dayanmaktadır:"
#: /resources/settings.xml
msgctxt "#32029"
msgid "Enable JSON logging"
msgstr "JSON günlüğünü etkinleştir"
#: /resources/settings.xml
msgctxt "#32030"
msgid "Rating updater"
msgstr "Derecelendirme güncelleyici"
#: /resources/settings.xml
msgctxt "#32028"
msgid "Run updating process in the background"
msgstr "Güncelleme işlemini arka planda çalıştır"
#: /resources/settings.xml
msgctxt "#32031"
msgid "Your personal OMDb API key (www.omdbapi.com)"
msgstr "Kişisel OMDb API anahtarınız (www.omdbapi.com)"
#: /resources/settings.xml
msgctxt "#32032"
msgid "Search by title/year if IMDb ID is missing (not recommended)"
msgstr "IMDb kimliği eksikse başlığa/yıla göre ara (önerilmez)"
#: /default.py
msgctxt "#32035"
msgid ""
"No OMDb API key is configured, which is required to update IMDb, Rotten "
"Tomatoes and Metacritic ratings. Please visit www.omdbapi.com and create "
"your own API key.[CR][CR]Note: The free key is limited to 1000 calls a day. "
"Please suggest to become a patreon of OMDb to increase the limit to "
"100.000.[CR][CR]Do you want to proceed updating The Movie DB ratings? This "
"only works if you have a TMDb ID stored."
msgstr ""
"IMDb, Çürük Domates ve Metakritik derecelendirmelerini güncellemek için "
"gerekli olan hiçbir OMDb API anahtarı yapılandırılmadı. Lütfen "
"www.omdbapi.com adresini ziyaret edin ve kendi API anahtarınızı "
"oluşturun.[CR][CR]Not: Ücretsiz anahtar günde 1000 çağrı ile sınırlıdır. "
"Lütfen limiti 100.000'e çıkarmak için OMDb'de patron olun.[CR][CR]The Movie "
"DB derecelendirmelerini güncellemeye devam etmek ister misiniz? Bu yalnızca "
"kayıtlı bir TMDb kimliğiniz varsa çalışır."
#: /default.py
msgctxt "#32036"
msgid "Update TV show ratings"
msgstr "TV programı derecelendirmelerini güncelle"
#: /resources/lib/rating_updater.py
msgctxt "#32033"
msgid ""
"OMDB API limit reached. Please consider to become a Patreon to increase your"
" daily call limitation. Proceed by only using The Movie DB?"
msgstr ""
"OMDB API sınırına ulaşıldı. Günlük arama sınırınızı artırmak için lütfen bir"
" Patreon olmayı düşünün. Yalnızca The Movie DB kullanarak devam edilsin mi?"
#: /resources/settings.xml
msgctxt "#32034"
msgid "Create .nfo file if missing"
msgstr "Eksikse .nfo dosyası oluştur"
#: /default.py
msgctxt "#32037"
msgid "Update movie ratings"
msgstr "Film derecelendirmelerini güncelle"
#: /default.py
msgctxt "#32038"
msgid "Update all ratings"
msgstr "Tüm derecelendirmeleri güncelle"
#: /context.py
msgctxt "#32039"
msgid "Update ratings"
msgstr "Derecelendirmeleri güncelle"
#: /resources/lib/editor.py
msgctxt "#32040"
msgid "Edit data for"
msgstr "Verilerini düzenle:"
#: /resources/lib/rating_updater.py
msgctxt "#32042"
msgid "Canceled"
msgstr "İptal edildi"
#: /resources/settings.xml
msgctxt "#32043"
msgid "MPAA region"
msgstr "MPAA bölgesi"
#: /resources/settings.xml
msgctxt "#32041"
msgid "Update premiered/year if database value is different"
msgstr "Veritabanı değeri farklıysa gösterim/yıl değerini güncelle"
#: /resources/settings.xml
msgctxt "#32044"
msgid "Skip updating of MPAA"
msgstr "MPAA'nın güncellenmesini atla"
#: /default.py
msgctxt "#32045"
msgid "Update episode ratings"
msgstr "Bölüm derecelendirmelerini güncelle"
#: /resources/lib/editor.py
msgctxt "#32047"
msgid "No default source defined"
msgstr "Tanımlanmış varsayılan kaynak yok"
#: /resources/lib/rating_updater.py
msgctxt "#32048"
msgid "No items found"
msgstr "Hiç öğe bulunamadı"
#: /context.py
msgctxt "#32046"
msgid "Update .nfo"
msgstr ".nfo güncelle"
#: /default.py
msgctxt "#32049"
msgid "Incomplete arguments or content type not supported"
msgstr "Eksik argümanlar veya içerik türü desteklenmiyor"
#: /default.py
msgctxt "#32050"
msgid "Do you want to cancel the update?"
msgstr "Güncellemeyi iptal etmek istiyor musunuz?"
#: /default.py
msgctxt "#32051"
msgid "Content"
msgstr "İçerik"
#: /resources/settings.xml
msgctxt "#32052"
msgid "Fallback to US MPAA if configured country has no certification stored"
msgstr ""
"Yapılandırılmış ülkenin kayıtlı sertifikası yoksa ABD MPAA'ya geri dön"
#: /resources/settings.xml
msgctxt "#32053"
msgid "Don't store \"NR\" (Not rated) MPAA rating"
msgstr "\"NR\" (Derecelendirilmedi) MPAA derecelendirmesini saklama"
#: /service.py
msgctxt "#32054"
msgid "Do you want to rate the following item?"
msgstr "Takip edilen öğeyi derecelendirmek istiyor musunuz?"
#: /resources/settings.xml
msgctxt "#32055"
msgid "Automatically update changed watched states to .nfo"
msgstr "İzlenme durumları değiştiğinde .nfo'yu otomatik güncelle"
#: /resources/settings.xml
msgctxt "#32056"
msgid "Rate your media if playback has ended"
msgstr "Oynatma sona erdiğinde medyanızı derecelendirin"
#: /resources/settings.xml
msgctxt "#32057"
msgid "Write watched flag and playcount to .nfo"
msgstr "İzlenen durumunu ve çalma sayısını .nfo'ya yaz"

View File

@@ -0,0 +1,153 @@
#!/usr/bin/python
# coding: utf-8
########################
from resources.lib.helper import *
from resources.lib.json_map import *
########################
class Database(object):
def __init__(self,dbid=None,dbtype=None,append=''):
self.dbid = dbid
self.append = append
self.data = {}
if dbtype:
if dbtype in ['movie', 'tvshow', 'season', 'episode', 'musicvideo']:
library = 'Video'
self.data['nfo'] = True
elif dbtype in ['set']:
library = 'Video'
self.data['nfo'] = False
else:
library = 'Audio'
self.data['nfo'] = False
self.set_details = '%sLibrary.Set%sDetails' % (library, dbtype.replace('set', 'movieset'))
self.param = '%sid' % dbtype
def result(self):
return self.data
def write(self,key,value):
if not isinstance(key, list):
key = [key]
value = [value]
for k in key:
json_call(self.set_details,
params={'%s' % k: value[key.index(k)], self.param: int(self.dbid)},
debug=LOG_JSON
)
def movies(self):
self._items('video', 'movie')
def movie(self):
self._item('video', 'movie')
def sets(self):
self._items('video', 'set')
def set(self):
self._item('video', 'set')
def tvshows(self):
self._items('video', 'tvshow')
def tvshow(self):
self._item('video', 'tvshow')
if self.data['tvshow'] and 'episodes' in self.append:
tvshowid = self.data['tvshow'][0].get('tvshowid')
self._items('video', 'episode', {'tvshowid': int(tvshowid)})
def episode(self):
self._item('video', 'episode')
def episodes(self):
self._items('video', 'episode')
def musicvideo(self):
self._item('video', 'musicvideo')
def musicvideos(self):
self._items('video', 'musicvideo')
def artist(self):
self._item('audio', 'artist')
def artists(self):
self._items('audio', 'artist')
def album(self):
self._item('audio', 'album')
def albums(self):
self._items('audio', 'album')
def song(self):
self._item('audio', 'song')
def songs(self):
self._items('audio', 'song')
def genre(self):
movie = []
tvshow = []
musicvideo = []
music = []
video = []
audio = []
# video db
for i in ['movie', 'tvshow', 'musicvideo']:
genres = json_call('VideoLibrary.GetGenres',
properties=['title'],
params={'type': i}
)
genres = genres.get('result', {}).get('genres', [])
for genre in genres:
eval(i).append(genre.get('label'))
# audio db
genres = json_call('AudioLibrary.GetGenres',
properties=['title']
)
genres = genres.get('result', {}).get('genres', [])
for genre in genres:
music.append(genre.get('label'))
self.data['moviegenres'] = movie
self.data['tvshowgenres'] = tvshow
self.data['musicvideogenres'] = musicvideo
self.data['musicgenres'] = music
self.data['videogenres'] = list(set(movie + tvshow + musicvideo))
self.data['audiogenres'] = list(set(music + musicvideo))
def tags(self):
tags = json_call('VideoLibrary.GetTags',
properties=['title']
)
self.data['tags'] = tags.get('result', {}).get('tags', [])
def _item(self,library,dbtype):
item = json_call('%sLibrary.Get%sDetails' % (library, dbtype.replace('set', 'movieset')),
properties=JSON_MAP.get('%s_properties' % dbtype),
params={'%sid' % dbtype: int(self.dbid)}
)
self.data[dbtype] = [item.get('result', {}).get('%sdetails' % dbtype)]
def _items(self,library,dbtype,params=None,query_filter=None):
items = json_call('%sLibrary.Get%ss' % (library, dbtype.replace('set', 'movieset')),
properties=JSON_MAP.get('%ss_properties' % dbtype),
params=params,
query_filter=query_filter
)
self.data[dbtype] = items.get('result', {}).get('%ss' % dbtype, [])

View File

@@ -0,0 +1,338 @@
#!/usr/bin/python
# coding: utf-8
########################
from resources.lib.helper import *
from resources.lib.json_map import *
from resources.lib.functions import *
from resources.lib.database import *
from resources.lib.nfo_updater import *
########################
class EditDialog(object):
def __init__(self,dbid,dbtype):
winprop('SelectDialogPreselect', clear=True)
self.dbid = dbid
self.dbtype = dbtype
self.db = Database(dbid=self.dbid, dbtype=self.dbtype)
self.nfo_support = self.db.result().get('nfo')
self.status = None
self.get_details()
def get_details(self):
getattr(self.db, self.dbtype)()
self.details = self.db.result().get(self.dbtype)[0]
self.file = self.details.get('file') if self.nfo_support else False
def editor(self):
self.modeselect = []
self.keylist = []
self.presetlist = []
self.typelist = []
self.optionlist = []
self.generate_list()
self.dialog()
def set(self,key,type):
preset = self.details.get(key)
if isinstance(preset, list):
preset = get_joined_items(preset)
elif isinstance(preset, float):
preset = str(get_rounded_value(preset))
elif isinstance(preset, int):
preset = str(preset)
self._handle_dbitem(value_type=type,
key=key,
preset=preset
)
self.get_details()
self.quit()
def quit(self):
if self.file:
if self.status:
self.details['status'] = self.status
update_nfo(file=self.file,
dbtype=self.dbtype,
dbid=self.dbid,
details=self.details
)
reload_widgets()
def dialog(self):
preselect = winprop('SelectDialogPreselect')
if not preselect:
preselect = -1
if self.details.get('title'):
headline = ADDON.getLocalizedString(32040) + ' "' + self.details.get('title') + '"'
elif self.details.get('artist'):
headline = ADDON.getLocalizedString(32040) + ' "' + self.details.get('artist') + '"'
else:
headline = ADDON.getLocalizedString(32000)
self.editdialog = DIALOG.select(headline, self.modeselect, preselect=int(preselect), useDetails=True)
# Dialog closed -> write changes to nfo and exit
if self.editdialog == -1:
winprop('SelectDialogPreselect', clear=True)
self.quit()
else:
# Edit value based on the type
winprop('SelectDialogPreselect', str(self.editdialog))
self._handle_dbitem(value_type=self.typelist[self.editdialog],
key=self.keylist[self.editdialog],
preset=self.presetlist[self.editdialog],
option=self.optionlist[self.editdialog]
)
# Refetch updated data and return to entry_point to populate the changes in the dialog
self.get_details()
self.editor()
def generate_list(self):
details = self.details
uniqueid = details.get('uniqueid', {})
ratings = details.get('ratings')
votes = details.get('votes', 0)
if not votes or votes == -1:
votes = 0
# Fallback rule. Create own ratings dict if it's missing in the database.
if not ratings:
ratings = {'default': {'default': True,
'rating': details.get('rating', 0.0),
'votes': details.get('votes', 0)}
}
ratings_default = None
for item in ratings:
if ratings[item].get('default'):
ratings_value = str(get_rounded_value(ratings[item].get('rating', 0.0)))
votes_value = str(ratings[item].get('votes', '0'))
ratings_default = ratings_value + ' / ' + votes_value + ' (' + xbmc.getLocalizedString(21870) + ': ' + item + ')'
break
if not ratings_default and len(ratings) > 0:
ratings_default = ADDON.getLocalizedString(32047)
if self.dbtype == 'movie':
self._create_list(xbmc.getLocalizedString(369), 'title', value=details.get('title'), type='string')
self._create_list(xbmc.getLocalizedString(20376), 'originaltitle', value=details.get('originaltitle'), type='string')
self._create_list(xbmc.getLocalizedString(171), 'sorttitle', value=details.get('sorttitle'), type='string')
self._create_list(xbmc.getLocalizedString(345) + ' / ' + xbmc.getLocalizedString(172), 'premiered', value=details.get('premiered'), type='date')
self._create_list(xbmc.getLocalizedString(515), 'genre', value=get_joined_items(details.get('genre')), type='array')
self._create_list(xbmc.getLocalizedString(202), 'tagline', value=details.get('tagline'), type='string')
self._create_list(xbmc.getLocalizedString(207), 'plot', value=details.get('plot'), type='string')
self._create_list(xbmc.getLocalizedString(203), 'plotoutline', value=details.get('plotoutline'), type='string')
self._create_list(xbmc.getLocalizedString(20457), 'set', value=details.get('set'), type='movieset')
self._create_list(xbmc.getLocalizedString(563) + ' / ' + xbmc.getLocalizedString(205), 'ratings', value=ratings_default, type='ratings', option=ratings)
self._create_list(ADDON.getLocalizedString(32001), 'userrating', value=str(details.get('userrating')), type='userrating')
self._create_list(xbmc.getLocalizedString(20074), 'mpaa', value=details.get('mpaa'), type='string')
self._create_list(xbmc.getLocalizedString(20339), 'director', value=get_joined_items(details.get('director')), type='array')
self._create_list(xbmc.getLocalizedString(20417), 'writer', value=get_joined_items(details.get('writer')), type='array')
self._create_list(xbmc.getLocalizedString(21875), 'country', value=get_joined_items(details.get('country')), type='array')
self._create_list(xbmc.getLocalizedString(572), 'studio', value=get_joined_items(details.get('studio')), type='array')
self._create_list(xbmc.getLocalizedString(20459), 'tag', value=get_joined_items(details.get('tag')), type='array')
self._create_list(xbmc.getLocalizedString(20410), 'trailer', value=details.get('trailer'), type='string')
self._create_list('IMDb ID', 'uniqueid', value=uniqueid.get('imdb'), type='uniqueid', option={'type': 'imdb', 'uniqueids': uniqueid})
self._create_list('TMDb ID', 'uniqueid', value=uniqueid.get('tmdb'), type='uniqueid', option={'type': 'tmdb', 'uniqueids': uniqueid})
self._create_list(xbmc.getLocalizedString(13409), 'top250', value=str(details.get('top250')), type='integer')
self._create_list(xbmc.getLocalizedString(570), 'dateadded', value=details.get('dateadded'), type='datetime')
self._create_list(xbmc.getLocalizedString(568), 'lastplayed', value=details.get('lastplayed'), type='datetime')
self._create_list(xbmc.getLocalizedString(567), 'playcount', value=str(details.get('playcount', 0)), type='integer')
elif self.dbtype == 'tvshow':
if KODI_VERSION < 19:
status = ADDON.getLocalizedString(32022)
else:
status = details.get('status', '')
self._create_list(xbmc.getLocalizedString(369), 'title', value=details.get('title'), type='string')
self._create_list(xbmc.getLocalizedString(20376),'originaltitle', value=details.get('originaltitle'), type='string')
self._create_list(xbmc.getLocalizedString(171), 'sorttitle', value=details.get('sorttitle'), type='string')
self._create_list(xbmc.getLocalizedString(345) + ' / ' + xbmc.getLocalizedString(172), 'premiered', value=details.get('premiered'), type='date')
self._create_list(xbmc.getLocalizedString(515), 'genre', value=get_joined_items(details.get('genre')), type='array')
self._create_list(xbmc.getLocalizedString(207), 'plot', value=details.get('plot'), type='string')
self._create_list(xbmc.getLocalizedString(563) + ' / ' + xbmc.getLocalizedString(205), 'ratings', value=ratings_default, type='ratings', option=ratings)
self._create_list(ADDON.getLocalizedString(32001), 'userrating', value=str(details.get('userrating')), type='userrating')
self._create_list(xbmc.getLocalizedString(20074), 'mpaa', value=details.get('mpaa'), type='string')
self._create_list(xbmc.getLocalizedString(572), 'studio', value=get_joined_items(details.get('studio')), type='array')
self._create_list(xbmc.getLocalizedString(20459), 'tag', value=get_joined_items(details.get('tag')), type='array')
self._create_list(xbmc.getLocalizedString(126), 'status', value=status, type='status')
self._create_list('IMDb ID', 'uniqueid', value=uniqueid.get('imdb'), type='uniqueid', option={'type': 'imdb', 'uniqueids': uniqueid, 'episodeguide': details.get('episodeguide')})
self._create_list('TMDb ID', 'uniqueid', value=uniqueid.get('tmdb'), type='uniqueid', option={'type': 'tmdb', 'uniqueids': uniqueid, 'episodeguide': details.get('episodeguide')})
self._create_list('TVDb ID', 'uniqueid', value=uniqueid.get('tvdb'), type='uniqueid', option={'type': 'tvdb', 'uniqueids': uniqueid, 'episodeguide': details.get('episodeguide')})
self._create_list('aniDB ID', 'uniqueid', value=uniqueid.get('anidb'), type='uniqueid', option={'type': 'anidb', 'uniqueids': uniqueid, 'episodeguide': details.get('episodeguide')})
elif self.dbtype == 'episode':
self._create_list(xbmc.getLocalizedString(369), 'title', value=details.get('title'), type='string')
self._create_list(xbmc.getLocalizedString(20376), 'originaltitle', value=details.get('originaltitle'), type='string')
self._create_list(xbmc.getLocalizedString(20416), 'firstaired', value=details.get('firstaired'), type='date')
self._create_list(xbmc.getLocalizedString(207), 'plot', value=details.get('plot'), type='string')
self._create_list(xbmc.getLocalizedString(563) + ' / ' + xbmc.getLocalizedString(205), 'ratings', value=ratings_default, type='ratings', option=ratings)
self._create_list(ADDON.getLocalizedString(32001), 'userrating', value=str(details.get('userrating')), type='userrating')
self._create_list(xbmc.getLocalizedString(20339), 'director', value=get_joined_items(details.get('director')), type='array')
self._create_list(xbmc.getLocalizedString(20417), 'writer', value=get_joined_items(details.get('writer')), type='array')
self._create_list('IMDb ID', 'uniqueid', value=uniqueid.get('imdb'), type='uniqueid', option={'type': 'imdb', 'uniqueids': uniqueid})
self._create_list('TMDb ID', 'uniqueid', value=uniqueid.get('tmdb'), type='uniqueid', option={'type': 'tmdb', 'uniqueids': uniqueid})
self._create_list('TVDb ID', 'uniqueid', value=uniqueid.get('tvdb'), type='uniqueid', option={'type': 'tvdb', 'uniqueids': uniqueid})
self._create_list('aniDB ID', 'uniqueid', value=uniqueid.get('anidb'), type='uniqueid', option={'type': 'anidb', 'uniqueids': uniqueid})
self._create_list(xbmc.getLocalizedString(570), 'dateadded', value=details.get('dateadded'), type='datetime')
self._create_list(xbmc.getLocalizedString(568), 'lastplayed', value=details.get('lastplayed'), type='datetime')
self._create_list(xbmc.getLocalizedString(567), 'playcount', value=str(details.get('playcount', 0)), type='integer')
elif self.dbtype == 'set':
self._create_list(xbmc.getLocalizedString(369), 'title', value=details.get('title'), type='string')
self._create_list(xbmc.getLocalizedString(207), 'plot', value=details.get('plot'), type='string')
elif self.dbtype == 'musicvideo':
self._create_list(xbmc.getLocalizedString(369), 'title', value=details.get('title'), type='string')
self._create_list(xbmc.getLocalizedString(557), 'artist', value=get_joined_items(details.get('artist')), type='array')
self._create_list(xbmc.getLocalizedString(558), 'album', value=details.get('album'), type='string')
self._create_list(xbmc.getLocalizedString(345) + ' / ' + xbmc.getLocalizedString(172), 'premiered', value=details.get('premiered'), type='date')
self._create_list(xbmc.getLocalizedString(554), 'track', value=str(details.get('track')), type='integer')
self._create_list(xbmc.getLocalizedString(207), 'plot', value=details.get('plot'), type='string')
self._create_list(xbmc.getLocalizedString(515), 'genre', value=get_joined_items(details.get('genre')), type='array')
self._create_list(xbmc.getLocalizedString(20339), 'director', value=get_joined_items(details.get('director')), type='array')
self._create_list(xbmc.getLocalizedString(572), 'studio', value=get_joined_items(details.get('studio')), type='array')
# self._create_list(xbmc.getLocalizedString(563), 'rating', value=str(get_rounded_value(details.get('rating'))), type='integer') broken in kodi? cannot be set
self._create_list(ADDON.getLocalizedString(32001), 'userrating', value=str(details.get('userrating')), type='userrating')
self._create_list(xbmc.getLocalizedString(20459), 'tag', value=get_joined_items(details.get('tag')), type='array')
self._create_list(xbmc.getLocalizedString(570), 'dateadded', value=details.get('dateadded'), type='datetime')
self._create_list(xbmc.getLocalizedString(568), 'lastplayed', value=details.get('lastplayed'), type='datetime')
self._create_list(xbmc.getLocalizedString(567), 'playcount', value=str(details.get('playcount', 0)), type='integer')
elif self.dbtype == 'artist':
self._create_list(xbmc.getLocalizedString(515), 'genre', value=get_joined_items(details.get('genre')), type='array')
self._create_list(xbmc.getLocalizedString(21821), 'description', value=details.get('description'), type='string')
self._create_list(xbmc.getLocalizedString(39026), 'disambiguation', value=details.get('disambiguation'), type='string')
self._create_list(xbmc.getLocalizedString(736), 'style', value=get_joined_items(details.get('style')), type='array')
self._create_list(xbmc.getLocalizedString(175), 'mood', value=get_joined_items(details.get('mood')), type='array')
self._create_list(xbmc.getLocalizedString(21892), 'instrument', value=get_joined_items(details.get('instrument')), type='array')
self._create_list(xbmc.getLocalizedString(21893), 'born', value=details.get('born'), type='string')
self._create_list(xbmc.getLocalizedString(21897), 'died', value=details.get('died'), type='string')
self._create_list(xbmc.getLocalizedString(21894), 'formed', value=details.get('formed'), type='string')
self._create_list(xbmc.getLocalizedString(21896), 'disbanded', value=details.get('disbanded'), type='string')
self._create_list(xbmc.getLocalizedString(21898), 'yearsactive', value=get_joined_items(details.get('yearsactive')), type='array')
elif self.dbtype == 'album':
self._create_list(ADDON.getLocalizedString(32023), 'albumlabel', value=details.get('albumlabel'), type='string')
self._create_list(xbmc.getLocalizedString(21821), 'description', value=details.get('description'), type='string')
self._create_list(xbmc.getLocalizedString(345), 'year', value=str(details.get('year')), type='integer')
self._create_list(xbmc.getLocalizedString(467), 'type', value=details.get('type'), type='string')
self._create_list(xbmc.getLocalizedString(515), 'genre', value=get_joined_items(details.get('genre')), type='array')
self._create_list(xbmc.getLocalizedString(15111), 'theme', value=get_joined_items(details.get('theme')), type='array')
self._create_list(xbmc.getLocalizedString(175), 'mood', value=get_joined_items(details.get('mood')), type='array')
self._create_list(xbmc.getLocalizedString(736), 'style', value=get_joined_items(details.get('style')), type='array')
self._create_list(xbmc.getLocalizedString(563), 'rating', value=str(get_rounded_value(details.get('rating'))), type='float')
self._create_list(xbmc.getLocalizedString(205), 'votes', value=str(votes), type='integer')
self._create_list(ADDON.getLocalizedString(32001), 'userrating', value=str(details.get('userrating')), type='userrating')
elif self.dbtype == 'song':
self._create_list(xbmc.getLocalizedString(563), 'rating', value=str(get_rounded_value(details.get('rating'))), type='float')
#self._create_list(xbmc.getLocalizedString(205), 'votes', value=str(details.get('votes')), type='integer') not available in methods.json? DaveBlake will fix it.
self._create_list(ADDON.getLocalizedString(32001), 'userrating', value=str(details.get('userrating')), type='userrating')
self._create_list(xbmc.getLocalizedString(568), 'lastplayed', value=details.get('lastplayed'), type='datetime')
self._create_list(xbmc.getLocalizedString(567), 'playcount', value=str(details.get('playcount', 0)), type='integer')
def _create_list(self,label,key,type,value,option=None):
if type in ['uniqueid', 'status', 'movieset']:
icon = 'string'
elif type == ('userrating'):
icon = 'integer'
elif type.startswith('date'):
icon = 'date'
elif type.startswith('rating'):
icon = 'float'
else:
icon = type
li_item = xbmcgui.ListItem(label=label, label2='n/a' if not value else value)
li_item.setArt({'icon': 'special://home/addons/script.metadata.editor/resources/media/icon_%s.png' % icon})
self.modeselect.append(li_item)
self.keylist.append(key)
self.typelist.append(type)
self.optionlist.append(option)
self.presetlist.append('' if not value else value)
def _handle_dbitem(self,key,value_type,preset=None,option=None):
if preset:
preset = preset.replace('n/a','')
if value_type == 'array':
value = set_array(self.dbtype, key, preset)
elif value_type == 'select':
value = modify_array(self.dbtype, key, preset)
elif value_type == 'string':
value = set_string(preset)
elif value_type == 'integer':
value = set_integer(preset)
elif value_type == 'float':
value = set_float(preset)
elif value_type == 'date':
value = set_date(preset)
elif value_type == 'datetime':
preset = preset.split(' ') if preset else ['', '']
date = set_date(preset[0])
time = set_time(preset[1][:-3])
value = date + ' ' + time + ':00'
elif value_type == 'userrating':
value = set_integer_range(preset, 11)
elif value_type == 'ratings':
value = set_ratings(option)
elif value_type == 'status':
value = set_status(preset)
self.status = value
elif value_type == 'watchlist':
value = toggle_tag(preset)
elif value_type == 'movieset':
value = set_movieset(preset)
elif value_type == ('uniqueid'):
returned_value = set_string(preset)
returned_value_json = returned_value if returned_value else None
returned_value_str = returned_value if returned_value else ''
uniqueid_key = option.get('type')
uniqueids = option.get('uniqueids')
value = {uniqueid_key: returned_value_json}
# build nfo info
updated_dict = {}
for item in uniqueids:
if item == uniqueid_key:
updated_dict[item] = returned_value_json
else:
updated_dict[item] = uniqueids.get(item)
if uniqueid_key not in updated_dict:
updated_dict[uniqueid_key] = returned_value_str
nfo_value = [updated_dict, option.get('episodeguide')]
self.db.write(key=key, value=value)

View File

@@ -0,0 +1,321 @@
#!/usr/bin/python
# coding: utf-8
########################
from resources.lib.helper import *
from resources.lib.database import *
########################
def set_ratings(ratings):
providerlist = []
for item in ratings:
providerlist.append(str(item))
preselect = -1
for item in providerlist:
if ratings[item].get('default'):
preselect = providerlist.index(item)
menu = DIALOG.select(xbmc.getLocalizedString(424), [ADDON.getLocalizedString(32015), ADDON.getLocalizedString(32016), ADDON.getLocalizedString(32017)])
if menu == 0: # set default provider
providerdefault = DIALOG.select(ADDON.getLocalizedString(32014), providerlist, preselect=preselect)
if providerdefault >= 0:
name = providerlist[providerdefault]
for item in ratings:
default = True if item == name else False
ratings[item] = {'default': default,
'rating': ratings[item].get('rating'),
'votes': ratings[item].get('votes')}
elif menu == 1: # edit votes/rating
providerratings = DIALOG.select(ADDON.getLocalizedString(32012), providerlist, preselect=preselect)
if providerratings >= 0:
name = providerlist[providerratings]
cur_rating = round(ratings[name].get('rating', 0.0), 1)
cur_votes = ratings[name].get('votes', 0)
rating = set_float(cur_rating)
votes = set_integer(cur_votes)
if not rating:
rating = 0.0
if not votes:
votes = 0
ratings[name] = {'default': ratings[name].get('default'),
'rating': rating,
'votes': votes}
elif menu == 2: # add new rating provider
supportedlist = ['imdb', 'themoviedb', 'tomatometerallcritics', 'tomatometeravgcritics', 'tomatometerallaudience', 'tomatometeravgaudience', 'metacritic']
for item in supportedlist:
if item in providerlist:
supportedlist.remove(item)
newprovider = DIALOG.select(ADDON.getLocalizedString(32013), supportedlist)
if newprovider >= 0:
name = supportedlist[newprovider]
rating = set_float(heading='Enter rating (floating number - min 0.1 / max 10.0)')
if not rating or float(rating) > 10:
DIALOG.ok(xbmc.getLocalizedString(257), ADDON.getLocalizedString(32018))
else:
votes = set_integer()
if not votes:
votes = 0
if not DIALOG.yesno(ADDON.getLocalizedString(32019), ADDON.getLocalizedString(32020)):
default = False
else:
default = True
for item in ratings:
ratings[item] = {'default': False,
'rating': ratings[item].get('rating'),
'votes': ratings[item].get('votes')}
ratings[name] = {'default': default,
'rating': rating,
'votes': votes}
return ratings
def set_movieset(preset):
db = Database()
db.sets()
sets = db.result().get('set', [])
selectlist = []
for item in sets:
selectlist.append(item.get('title'))
selectlist.sort()
selectlist.insert(0, xbmc.getLocalizedString(231))
selectlist.insert(1, ADDON.getLocalizedString(32005))
preselect = selectlist.index(preset) if preset in selectlist else -1
selectdialog = DIALOG.select(xbmc.getLocalizedString(20466), selectlist, preselect=preselect)
if selectdialog == 0:
return ''
elif selectdialog == 1:
value = set_string()
return value
elif selectdialog > 1:
return selectlist[selectdialog]
return preset
def set_array(dbtype,key,preset):
actionlist = [ADDON.getLocalizedString(32005), ADDON.getLocalizedString(32007), ADDON.getLocalizedString(32006)]
array_action = DIALOG.select(xbmc.getLocalizedString(14241), actionlist)
array_list = get_list_items(preset)
if array_action == 0:
keyboard = xbmc.Keyboard()
keyboard.doModal()
if keyboard.isConfirmed():
new_item = keyboard.getText()
if new_item not in array_list:
array_list.append(new_item)
return remove_empty(array_list)
elif array_action == 1:
array = modify_array(dbtype, key, array_list)
return array
elif array_action == 2:
keyboard = xbmc.Keyboard(preset)
keyboard.doModal()
if keyboard.isConfirmed():
array = keyboard.getText()
else:
array = preset
return get_list_items(array)
else:
return array_list
def modify_array(dbtype,key,values):
modified = []
all_values = []
if not isinstance(values, list):
values = get_list_items(values)
if key in ['genre', 'tags']:
db = Database()
getattr(db, key)()
result = db.result()
if key == 'genre':
if dbtype in ['musicvideo', 'artist', 'album']:
for genre in result.get('audiogenres'):
all_values.append(genre)
else:
for genre in result.get('videogenres'):
all_values.append(genre)
elif key == 'tags':
for tag in result.get('tags'):
if tag not in values:
all_values.append(tag)
all_values = list(set(values + all_values))
all_values.sort()
values.sort()
# open common array dialog if all_values are empty
if not all_values:
notification(ADDON.getLocalizedString(32000), ADDON.getLocalizedString(32048))
value = set_array(dbtype, key, '')
return value
preselectlist = []
for item in values:
preselectlist.append(all_values.index(item))
selectdialog = DIALOG.multiselect(ADDON.getLocalizedString(32002), all_values, preselect=preselectlist)
if selectdialog == -1 or selectdialog is None:
return values
for index in selectdialog:
modified.append(all_values[index])
return modified
def set_integer(preset=''):
preset = str(preset)
if preset == '0':
preset = ''
value = xbmcgui.Dialog().numeric(0, xbmc.getLocalizedString(16028), preset)
if not value:
return None
return int(value)
def set_float(preset='',heading=ADDON.getLocalizedString(32011)):
try:
preset = float(preset)
preset = round(preset,1)
except Exception:
preset = ''
keyboard = xbmc.Keyboard(str(preset))
keyboard.setHeading(heading)
keyboard.doModal()
if keyboard.isConfirmed():
try:
value = float(keyboard.getText())
value = round(value,1)
return value
except Exception:
set_float(preset)
return preset
def set_date(preset):
try:
conv = time.strptime(preset,'%Y-%m-%d')
conv = time.strftime('%d/%m/%Y', conv)
except Exception:
conv = '01/01/1900'
value = xbmcgui.Dialog().numeric(1, xbmc.getLocalizedString(16028), conv)
if value:
value = value.replace(' ','0')
value = time.strptime(value,'%d/%m/%Y')
value = time.strftime('%Y-%m-%d',value)
return value
return preset
def set_time(preset):
value = xbmcgui.Dialog().numeric(2, xbmc.getLocalizedString(16028), preset)
if value:
return value
return preset
def set_string(preset=''):
value = preset.replace('\n', '[CR]')
keyboard = xbmc.Keyboard(value)
keyboard.doModal()
if keyboard.isConfirmed():
value = keyboard.getText()
return value.replace('[CR]', '\n')
def set_integer_range(preset, maximum):
preset = int(preset) if preset else 0
rangelist = []
for i in range(0, maximum):
rangelist.append(str(i))
value = DIALOG.select(xbmc.getLocalizedString(424), rangelist, preselect=preset)
if value >= 0:
return value
return preset
def set_status(preset):
statuslist = ['Returning series', 'In production', 'Planned', 'Cancelled', 'Ended']
if preset == ADDON.getLocalizedString(32022):
preset = ''
value = DIALOG.select(xbmc.getLocalizedString(126), statuslist)
if value >= 0:
return statuslist[value]
return preset
def toggle_tag(preset):
tag = 'Watchlist'
tags = get_list_items(preset)
if tag in tags:
tags.remove(tag)
else:
tags.append(tag)
return tags

View File

@@ -0,0 +1,250 @@
#!/usr/bin/python
# coding: utf-8
########################
import sys
import xbmc
import xbmcaddon
import xbmcgui
import xbmcvfs
import xbmcplugin
import json
import time
import datetime
import os
import hashlib
import xml.etree.ElementTree as ET
import requests
import urllib.request as urllib
from urllib.parse import urlencode
from contextlib import contextmanager
########################
ADDON = xbmcaddon.Addon()
ADDON_ID = ADDON.getAddonInfo('id')
ADDON_DATA_PATH = os.path.join(xbmcvfs.translatePath("special://profile/addon_data/%s" % ADDON_ID))
NOTICE = xbmc.LOGINFO
WARNING = xbmc.LOGWARNING
DEBUG = xbmc.LOGDEBUG
ERROR = xbmc.LOGERROR
LOG_JSON = ADDON.getSettingBool('json_log')
KODI_VERSION = int(xbmc.getInfoLabel('System.BuildVersion')[:2])
DIALOG = xbmcgui.Dialog()
########################
def log(txt,loglevel=DEBUG,json=False,force=False):
if loglevel in [DEBUG, WARNING, ERROR] or force:
if force:
loglevel = NOTICE
if json:
txt = json_prettyprint(txt)
message = u'[ %s ] %s' % (ADDON_ID,txt)
xbmc.log(msg=message, level=loglevel)
def unicode_string(string):
string = u'%s' % string
return string
def remove_quotes(label):
if not label:
return ''
if label.startswith("'") and label.endswith("'") and len(label) > 2:
label = label[1:-1]
if label.startswith('"') and label.endswith('"') and len(label) > 2:
label = label[1:-1]
elif label.startswith('&quot;') and label.endswith('&quot;'):
label = label[6:-6]
return label
def get_joined_items(item):
if len(item) > 0 and item is not None:
item = '; '.join(item)
item = item + ';'
else:
item = ''
return item
def get_list_items(string):
return remove_empty(string.replace('; ',';').split(';'))
def get_key_item(items,key):
try:
return items.get(key)
except Exception:
return
def get_rounded_value(value):
try:
if not isinstance(value, str) and not isinstance(value, float):
value = str(value)
if not isinstance(value, float):
value = float(value)
return round(value,1)
except Exception:
return
def remove_empty(array):
cleaned_array = []
for item in array:
if not item or item in ['', ';']:
continue
cleaned_array.append(item)
return cleaned_array
def execute(cmd):
xbmc.executebuiltin(cmd)
def condition(condition):
return xbmc.getCondVisibility(condition)
def winprop(key, value=None, clear=False, window_id=10000):
window = xbmcgui.Window(window_id)
if clear:
window.clearProperty(key.replace('.json', '').replace('.bool', '').replace('.str', ''))
elif value is not None:
if key.endswith('.json'):
key = key.replace('.json', '')
value = json.dumps(value)
elif key.endswith('.bool'):
key = key.replace('.bool', '')
value = 'true' if value else 'false'
elif key.endswith('.str'):
key = key.replace('.str', '')
value = str(value)
window.setProperty(key, value)
else:
result = window.getProperty(key.replace('.json', '').replace('.bool', '').replace('.str', ''))
if result:
if key.endswith('.json'):
result = json.loads(result)
elif key.endswith('.bool'):
result = result in ('true', '1')
elif key.endswith('.str'):
result = eval(result)
return result
def json_call(method,properties=None,sort=None,query_filter=None,limit=None,params=None,item=None,options=None,limits=None,debug=False):
json_string = {'jsonrpc': '2.0', 'id': 1, 'method': method, 'params': {}}
if properties is not None:
json_string['params']['properties'] = properties
if limit is not None:
json_string['params']['limits'] = {'start': 0, 'end': int(limit)}
if sort is not None:
json_string['params']['sort'] = sort
if query_filter is not None:
json_string['params']['filter'] = query_filter
if options is not None:
json_string['params']['options'] = options
if limits is not None:
json_string['params']['limits'] = limits
if item is not None:
json_string['params']['item'] = item
if params is not None:
json_string['params'].update(params)
jsonrpc_call = json.dumps(json_string)
result = xbmc.executeJSONRPC(jsonrpc_call)
result = json.loads(result)
if debug:
log('--> JSON CALL: ' + json_prettyprint(json_string), force=True)
log('--> JSON RESULT: ' + json_prettyprint(result), force=True)
return result
def json_prettyprint(string):
return json.dumps(string, sort_keys=True, indent=4, separators=(',', ': '))
def xml_prettyprint(root,level=0):
i = '\n' + level * ' '
if len(root):
if not root.text or not root.text.strip():
root.text = i + ' '
if not root.tail or not root.tail.strip():
root.tail = i
for root in root:
xml_prettyprint(root, level+1)
if not root.tail or not root.tail.strip():
root.tail = i
else:
if level and (not root.tail or not root.tail.strip()):
root.tail = i
def notification(header=ADDON.getLocalizedString(32000),message=''):
DIALOG.notification(header, message, icon='special://home/addons/script.metadata.editor/resources/icon.png')
def reload_widgets():
# Notifies script.embuary.helper to reload widgets
execute('NotifyAll(%s,Finished)' % ADDON_ID)
@contextmanager
def busy_dialog(force=False):
if force:
execute('ActivateWindow(busydialognocancel)')
elif not winprop('UpdatingRatings.bool'):
# NFO writing usually only takes < 1s. Just show BusyDialog if it takes longer for whatever reason.
execute('AlarmClock(BusyAlarmDelay,ActivateWindow(busydialognocancel),00:02,silent)')
try:
yield
finally:
execute('CancelAlarm(BusyAlarmDelay,silent)')
execute('Dialog.Close(busydialognocancel)')

View File

@@ -0,0 +1,267 @@
#!/usr/bin/python
JSON_MAP = {
'movie_properties': [
'title',
'originaltitle',
'sorttitle',
'votes',
'playcount',
'year',
'genre',
'studio',
'country',
'tagline',
'tag',
'plot',
'runtime',
'premiered',
'file',
'plotoutline',
'lastplayed',
'trailer',
'rating',
'ratings',
'userrating',
'resume',
'art',
'mpaa',
'director',
'writer',
'cast',
'set',
'setid',
'top250',
'dateadded',
'imdbnumber',
'uniqueid'
],
'movies_properties': [
'title',
'year'
],
'set_properties': [
'title',
'plot'
],
'sets_properties': [
'title'
],
'episode_properties': [
'title',
'playcount',
'season',
'episode',
'showtitle',
'originaltitle',
'plot',
'votes',
'file',
'rating',
'ratings',
'userrating',
'resume',
'tvshowid',
'firstaired',
'art',
'runtime',
'director',
'writer',
'cast',
'dateadded',
'lastplayed',
'uniqueid'
],
'episodes_properties': [
'title',
'showtitle'
],
'season_properties': [
'season',
'episode',
'art',
'userrating',
'watchedepisodes',
'showtitle',
'playcount',
'tvshowid'
],
'seasons_properties': [
'season',
'showtitle',
'tvshowid'
],
'tvshow_properties': [
'title',
'studio',
'year',
'plot',
'cast',
'rating',
'ratings',
'userrating',
'votes',
'file',
'genre',
'episode',
'season',
'runtime',
'mpaa',
'premiered',
'playcount',
'lastplayed',
'sorttitle',
'originaltitle',
'episodeguide',
'art',
'tag',
'dateadded',
'watchedepisodes',
'imdbnumber',
'uniqueid'
],
'tvshows_properties': [
'title',
'year'
],
'musicvideo_properties': [
'title',
'playcount',
'runtime',
'director',
'studio',
'year',
'plot',
'album',
'artist',
'genre',
'track',
'lastplayed',
'fanart',
'thumbnail',
'file',
'resume',
'dateadded',
'tag',
'art',
'rating',
'userrating',
'premiered'
],
'musicvideos_properties': [
'title',
'year'
],
'artist_properties': [
'instrument',
'style',
'mood',
'born',
'formed',
'description',
'genre',
'died',
'disbanded',
'yearsactive',
'musicbrainzartistid',
'fanart',
'thumbnail',
'compilationartist',
'dateadded',
'roles',
'songgenres',
'isalbumartist',
'disambiguation'
],
'artists_properties': [
'dateadded'
],
'album_properties': [
'title',
'description',
'artist',
'genre',
'theme',
'mood',
'style',
'type',
'albumlabel',
'rating',
'votes',
'userrating',
'year',
'musicbrainzalbumid',
'musicbrainzalbumartistid',
'fanart',
'thumbnail',
'playcount',
'artistid',
'displayartist',
'compilation',
'releasetype',
'dateadded'
],
'albums_properties': [
'title',
'year'
],
'song_properties': [
'title',
'artist',
'albumartist',
'genre',
'year',
'rating',
'album',
'track',
'duration',
'comment',
'lyrics',
'musicbrainztrackid',
'musicbrainzartistid',
'musicbrainzalbumid',
'musicbrainzalbumartistid',
'playcount',
'fanart',
'thumbnail',
'file',
'albumid',
'lastplayed',
'disc',
'genreid',
'artistid',
'displayartist',
'albumartistid',
'albumreleasetype',
'dateadded',
'votes',
'userrating',
'mood',
'contributors',
'displaycomposer',
'displayconductor',
'displayorchestra',
'displaylyricist'
],
'songs_properties': [
'title',
'artist'
]
}

View File

@@ -0,0 +1,337 @@
#!/usr/bin/python
# coding: utf-8
########################
from resources.lib.helper import *
from resources.lib.database import *
########################
def update_nfo(dbtype,dbid,details=None,file=None, forced=False):
if not forced and not ADDON.getSettingBool('nfo_updating'):
winprop('updatenfo', clear=True)
return
if not details:
db = Database(dbid, dbtype)
getattr(db, dbtype)()
details = db.result().get(dbtype)[0]
if not details:
log('NFO updater: No item details found or provided --> ID: %s Type: %s' % (dbid, dbtype), ERROR)
return
if not file:
file = details.get('file')
if not file:
log('NFO updater: No item path available --> ID: %s Type: %s' % (dbid, dbtype), ERROR)
return
if dbtype == 'tvshow':
path = os.path.join(file,'tvshow.nfo')
else:
path = file.replace(os.path.splitext(file)[1], '.nfo')
UpdateNFO(file=path,
dbtype=dbtype,
dbid=dbid,
details=details)
# support for additional movie.nfo
if dbtype == 'movie':
path = file.replace(os.path.basename(file), 'movie.nfo')
if xbmcvfs.exists(path):
UpdateNFO(file=path,
dbtype=dbtype,
dbid=dbid,
details=details)
class UpdateNFO():
def __init__(self,file,dbtype,dbid,details):
self.targetfile = file
self.dbtype = dbtype
self.dbid = dbid
self.details = details
self.root = None
self.sortlist = []
self.run()
def run(self):
with busy_dialog():
try:
if xbmcvfs.exists(self.targetfile):
self.root = self.read_file()
self.existing_nfo = True
elif ADDON.getSettingBool('create_nfo'):
self.root = ET.Element(self.dbtype.replace('episode', 'episodedetails'))
self.existing_nfo = False
else:
raise Exception('File not found')
self.handle_details()
self.write_file()
success = True
except Exception as error:
log('Cannot process .nfo file: %s --> %s' % (self.targetfile, error), ERROR)
success = False
if winprop('updatenfo.bool'):
msg = xbmc.getLocalizedString(20177) if success else xbmc.getLocalizedString(257)
notification(ADDON.getLocalizedString(32046), msg)
winprop('updatenfo', clear=True)
def read_file(self):
file = xbmcvfs.File(self.targetfile)
content = file.read()
file.close()
if content:
tree = ET.ElementTree(ET.fromstring(content))
root = tree.getroot()
return root
def write_file(self):
# sort nfo
if self.existing_nfo:
index = 0
for key in self.sortlist:
for elem in self.root.findall(key):
self.root.remove(elem)
self.root.insert(index, elem)
index += 1
xml_prettyprint(self.root)
content = ET.tostring(self.root, encoding='UTF8', method='xml').decode()
with xbmcvfs.File(self.targetfile, 'w') as f:
result = f.write(content)
def handle_details(self):
li = [{'key': 'title', 'value': self.details.get('title')},
{'key': 'originaltitle', 'value': self.details.get('originaltitle')},
{'key': 'showtitle', 'value': self.details.get('showtitle')},
{'key': 'sorttitle', 'value': self.details.get('sorttitle')},
{'key': 'userrating', 'value': self.details.get('userrating')},
{'key': 'outline', 'value': self.details.get('plotoutline')},
{'key': 'plot', 'value': self.details.get('plot')},
{'key': 'tagline', 'value': self.details.get('tagline')},
{'key': 'mpaa', 'value': self.details.get('mpaa')},
{'key': 'premiered', 'value': self.details.get('premiered')},
{'key': 'releasedate', 'value': self.details.get('releasedate')}, #emby
{'key': 'year', 'value': self.details.get('premiered', '')[:4]}, #emby
{'key': 'country', 'value': self.details.get('country')},
{'key': 'studio', 'value': self.details.get('studio')},
{'key': 'director', 'value': self.details.get('director')},
{'key': 'credits', 'value': self.details.get('writer')},
{'key': 'writer', 'value': self.details.get('writer')}, #emby
{'key': 'tag', 'value': self.details.get('tag')},
{'key': 'isuserfavorite', 'value': 'true' if 'Favorite movies' in self.details.get('tag', []) or 'Favorite tvshows' in self.details.get('tag', []) else 'false'}, #emby
{'key': 'genre', 'value': self.details.get('genre')},
{'key': 'top250', 'value': self.details.get('top250')},
{'key': 'ratings', 'value': self.details.get('ratings')},
{'key': 'uniqueid', 'value': self.details.get('uniqueid')},
{'key': 'status', 'value': self.details.get('status')},
{'key': 'aired', 'value': self.details.get('firstaired')},
{'key': 'dateadded', 'value': self.details.get('dateadded')}
]
if ADDON.getSettingBool('write_watched_stated'):
li.append({'key': 'playcount', 'value': self.details.get('playcount')})
li.append({'key': 'watched', 'value': 'true' if self.details.get('playcount', 0) > 0 else 'false'}) #emby
li.append({'key': 'lastplayed', 'value': self.details.get('lastplayed')})
for item in li:
key = item.get('key')
value = item.get('value')
self.sortlist.append(key)
if key == 'ratings':
self.handle_ratings(value)
elif key == 'uniqueid':
self.handle_uniqueid(value, self.details.get('episodeguide', ''))
else:
self.handle_elem(key, value)
def handle_elem(self,key,value):
if key != 'status' or (key == 'status' and value): # Keep status value. Required for leia because status isn't returned thru json.
for elem in self.root.findall(key):
self.root.remove(elem)
if isinstance(value, list):
for i in value:
if i:
elem = ET.SubElement(self.root, key)
elem.text = unicode_string(i)
elif value:
elem = ET.SubElement(self.root, key)
elem.text = unicode_string(value)
def handle_ratings(self,value):
for elem in self.root.findall('ratings'):
self.root.remove(elem)
elem = ET.SubElement(self.root, 'ratings')
for item in value:
rating = float(value[item].get('rating', 0.0))
rating = str(round(rating, 1))
votes = str(value[item].get('votes', 0))
subelem = ET.SubElement(elem, 'rating')
subelem.set('name', item)
subelem.set('max', '10')
if value[item].get('default'):
subelem.set('default', 'true')
# Emby <votes>, <rating>
for key in ['rating', 'votes']:
for defaultelem in self.root.findall(key):
self.root.remove(defaultelem)
defaultelem = ET.SubElement(self.root, key)
defaultelem.text = eval(key)
self.sortlist.append(key)
else:
subelem.set('default', 'false')
rating_elem = ET.SubElement(subelem, 'value')
rating_elem.text = rating
votes_elem = ET.SubElement(subelem, 'votes')
votes_elem.text = votes
# Emby <criticrating> Rotten ratings
if item == 'tomatometerallcritics':
normalized_rating = int(float(rating) * 10)
if normalized_rating > 100:
normalized_rating = ''
for emby_elem in self.root.findall('criticrating'):
self.root.remove(emby_elem)
emby_rotten = ET.SubElement(self.root, 'criticrating')
emby_rotten.text = str(normalized_rating)
self.sortlist.append('criticrating')
def handle_uniqueid(self,uniqueids,episodeguide):
# find default uniqueid
default = ''
if 'tvdb' in episodeguide:
default = 'tvdb'
elif 'tmdb' in episodeguide:
default = 'tmdb'
else:
for elem in self.root.findall('uniqueid'):
if elem.get('default'):
default = elem.get('type')
break
# set fallback default uniqueid
if not default:
if self.dbtype == 'movie':
if uniqueids.get('tmdb'):
default = 'tmdb'
elif uniqueids.get('imdb'):
default = 'imdb'
elif self.dbtype == 'tvshow':
scraper_default = ADDON.getSetting('tv_scraper_base')
if (scraper_default == 'TVDb' and uniqueids.get('tvdb')):
default = 'tvdb'
elif scraper_default == 'TMDb' and uniqueids.get('tmdb'):
default = 'tmdb'
# <uniqueid> fields
for elem in self.root.findall('uniqueid'):
self.root.remove(elem)
for item in uniqueids:
value = uniqueids.get(item, '')
if value:
elem = ET.SubElement(self.root, 'uniqueid')
elem.set('type', item)
elem.text = value
if default == item:
elem.set('default', 'true')
if self.dbtype == 'tvshow':
self._set_episodeguide(item, value)
self.sortlist.append(item)
# Emby <imdbid>, <tmdbid>, etc.
emby_uniqueids = {}
for item in uniqueids:
if item == 'imdb':
emby_uniqueids['imdbid'] = uniqueids.get(item)
emby_uniqueids['imdb_id'] = uniqueids.get(item) # emby is using a underscore for tvshows Oo
elif item == 'tmdbcollection':
emby_uniqueids['collectionnumber'] = uniqueids.get(item)
elif item.lower() in ['zap2it', 'tvrage', 'tvdb', 'tmdb']:
emby_uniqueids['%sid' % item] = uniqueids.get(item)
for item in emby_uniqueids:
for elem in self.root.findall(item):
self.root.remove(elem)
value = emby_uniqueids.get(item)
if value:
elem = ET.SubElement(self.root, item)
elem.text = value
self.sortlist.append(item)
def _set_episodeguide(self,type,value):
post = False
cache = ''
if type == 'tvdb':
post = 'yes'
cache = 'auth.json'
url = 'https://api.thetvdb.com/login?{"apikey":"439DFEBA9D3059C6","id":%s}|Content-Type=application/json' % str(value)
json_value = '<episodeguide><url post="%s" cache="%s"><url>%s</url></episodeguide>' % (post, cache, url)
elif type == 'tmdb':
language = ADDON.getSetting('tmdb_language')
cache = 'tmdb-%s-%s.json' % (str(value), language)
url = 'http://api.themoviedb.org/3/tv/%s?api_key=6a5be4999abf74eba1f9a8311294c267&amp;language=%s' % (str(value), language)
json_value = '<episodeguide><url cache="%s"><url>%s</url></episodeguide>' % (cache, url)
else:
url = ''
json_value = '<episodeguide><url cache=""><url></url></episodeguide>'
for elem in self.root.findall('episodeguide'):
self.root.remove(elem)
episodeguide_elem = ET.SubElement(self.root, 'episodeguide')
url_elem = ET.SubElement(episodeguide_elem, 'url')
if post:
url_elem.set('post', post)
url_elem.set('cache', cache)
url_elem.text = url
self.sortlist.append('episodeguide')
json_call('VideoLibrary.SetTVShowDetails',
params={'episodeguide': json_value, 'tvshowid': int(self.dbid)},
debug=LOG_JSON
)

View File

@@ -0,0 +1,601 @@
#!/usr/bin/python
# coding: utf-8
########################
from __future__ import division
from resources.lib.helper import *
from resources.lib.functions import *
from resources.lib.database import *
from resources.lib.nfo_updater import *
########################
RUN_IN_BACKGROUND = ADDON.getSettingBool('update_background')
BUSYDIALOG = False if RUN_IN_BACKGROUND else True
OMDB_FALLBACK = ADDON.getSettingBool('omdb_fallback_search')
OMDB_API = ADDON.getSetting('omdb_api_key')
COUNTRY_CODE = ADDON.getSetting('country_code')
SKIP_MPAA = ADDON.getSettingBool('mpaa_skip')
SKIP_NOT_RATED = ADDON.getSettingBool('mpaa_skip_nr')
MPAA_FALLBACK = ADDON.getSettingBool('mpaa_fallback')
TMDB_LANGUAGE = ADDON.getSetting('tmdb_language')
RATING_DEBUG = ADDON.getSetting('debug_rating_updater')
########################
def update_ratings(dbid=None,dbtype=None,content=None):
# no omdb API key message
if not OMDB_API:
if not DIALOG.yesno(xbmc.getLocalizedString(14117), ADDON.getLocalizedString(32035)):
return
winprop('UpdatingRatings.bool', True)
msg_text = xbmc.getLocalizedString(19256)
# get database ids
if isinstance(dbtype, str):
dbtype = dbtype.split('+')
with busy_dialog(force=BUSYDIALOG):
db = Database(dbid=dbid, append=['episodes'])
for i in dbtype:
getattr(db, i)()
result = db.result()
# calc total items to process
total_items = 0
for i in result:
if result.get(i):
total_items = total_items + len(result[i])
if total_items > 1:
# show progress if 1< will be processed
progressdialog = ProgressDialog(total_items)
for i in result:
if i == 'movie':
cat = xbmc.getLocalizedString(20338)
elif i == 'tvshow':
cat = xbmc.getLocalizedString(20364)
elif i == 'episode':
cat = xbmc.getLocalizedString(20359)
for item in result[i]:
if progressdialog.canceled():
break
if item.get('showtitle') and item.get('label'):
label = item.get('showtitle') + ' - ' + item.get('label')
else:
label = item.get('title')
if item.get('year'):
label = label + ' (' + str(item.get('year')) + ')'
progressdialog.update(cat, label)
UpdateRating({'dbid': item.get('%sid' % i),
'type': i})
#xbmc.sleep(50)
if progressdialog.canceled():
msg_text = ADDON.getLocalizedString(32042)
break
progressdialog.close()
elif total_items == 1:
# process single item
for i in result:
UpdateRating({'dbid': result[i][0].get('%sid' % i),
'type': i})
else:
# error message
msg_text = ADDON.getLocalizedString(32048)
winprop('UpdatingRatings', clear=True)
notification(ADDON.getLocalizedString(32030), msg_text)
class ProgressDialog(object):
def __init__(self,total_items):
if RUN_IN_BACKGROUND:
self.progressdialog = xbmcgui.DialogProgressBG()
else:
self.progressdialog = xbmcgui.DialogProgress()
self.progressdialog.create('Updating', '')
self.total_items = total_items
self.processed_items = 0
self.progress = 0
def canceled(self):
if RUN_IN_BACKGROUND:
return True if winprop('CancelRatingUpdater.bool') else False
else:
return True if self.progressdialog.iscanceled() or winprop('CancelRatingUpdater.bool') else False
def update(self,cat,label):
self.processed_items += 1
progress = int(100 / self.total_items * self.processed_items)
processed = str(self.processed_items) + ' / ' + str(self.total_items)
if RUN_IN_BACKGROUND:
self.progressdialog.update(progress, processed, cat + ':' + label)
else:
self.progressdialog.update(progress, cat + ':[CR]' + label + '[CR]' + processed)
def close(self):
self.progressdialog.close()
self.progressdialog = None
winprop('CancelRatingUpdater', clear=True)
class UpdateRating(object):
def __init__(self,params):
self.dbid = params.get('dbid')
self.dbtype = params.get('type')
self.tmdb_type = 'movie' if self.dbtype == 'movie' else 'tv'
self.tmdb_tv_status = None
self.tmdb_mpaa = None
self.tmdb_mpaa_fallback = None
self.tmdb_rating = None
self.imdb_rating = None
self.omdb_limit = False
self.update_uniqueid = False
self.episodeguide = None
# collect db data
self.db = Database(dbid=self.dbid, dbtype=self.dbtype)
self.get_details()
self.uniqueid = self.details.get('uniqueid', {})
self.ratings = self.details.get('ratings', {})
self.file = self.details.get('file')
self.year = self.details.get('year')
self.premiered = self.details.get('premiered') or self.details.get('firstaired')
self.title = self.details.get('title')
self.original_title = self.details.get('originaltitle') or self.title
self.tags = self.details.get('tag')
if any(string in self.details.get('episodeguide', '') for string in ['tvdb', 'tmdb']):
self.episodeguide = self.details.get('episodeguide')
else:
self.episodeguide = None
if self.uniqueid:
self.run()
def get_details(self):
getattr(self.db, self.dbtype)()
self.details = self.db.result().get(self.dbtype)[0]
def run(self):
log('Run rating updater - %s: %s - ID: %s' % (self.dbtype, self.title, str(self.dbid)), force=RATING_DEBUG)
self.imdb = self.uniqueid.get('imdb')
self.tmdb = self.uniqueid.get('tmdb')
self.tvdb = self.uniqueid.get('tvdb')
# don't proceed for episodes if no IMDb is available
if self.dbtype == 'episode' and not self.imdb:
log('Episode with no IMDb. Skip.', force=RATING_DEBUG)
return
# get the default used rating
self.default_rating = None
for rating in self.ratings:
if self.ratings[rating].get('default'):
self.default_rating = rating
break
if self.dbtype != 'episode':
# get TMDb ID (if not available) by using the ID of IMDb or TVDb
if not self.tmdb and self.imdb:
log('No TMDb. Try to get by IMDb ID %s' % self.imdb, force=RATING_DEBUG)
self.get_tmdb_externalid(self.imdb)
elif not self.tmdb and self.tvdb:
log('No TMDb. Try to get by TVDb ID %s' % str(self.tvdb), force=RATING_DEBUG)
self.get_tmdb_externalid(self.tvdb)
# get TMDb rating and IMDb number if not available
if self.tmdb:
log('Fetch data by TMDb ID %s' % str(self.tmdb), force=RATING_DEBUG)
self.get_tmdb()
# get Rotten, Metacritic and IMDb ratings of OMDb
if not self.omdb_limit:
log('Fetch OMDb data', force=RATING_DEBUG)
self.get_omdb()
# if no TMDb ID was known before but OMDb return the IMDb ID -> try to get TMDb data again
if self.dbtype != 'episode' and not self.tmdb and self.imdb:
log('Try to get TMDb ID by returned IMDb ID %s of OMDb' % self.imdb, force=RATING_DEBUG)
self.get_tmdb_externalid(self.imdb)
if self.tmdb:
log('Fetch data by TMDb ID %s' % str(self.tmdb), force=RATING_DEBUG)
self.get_tmdb()
# emby <ratings> and <votes>
if 'default' in self.ratings:
self.emby_ratings()
# update db + nfo
log('Updating info', force=RATING_DEBUG)
self.update_info()
def emby_ratings(self):
# Emby For Kodi is storing the rating as 'default'
if self.imdb_rating:
self._update_ratings_dict(key='default',
rating=float(self.imdb_rating),
votes=int(self.imdb_votes)
)
elif self.tmdb_rating:
self._update_ratings_dict(key='default',
rating=float(self.tmdb_rating),
votes=int(self.tmdb_votes)
)
def get_tmdb(self):
result = self._tmdb(action=self.tmdb_type,
call=str(self.tmdb),
params={'append_to_response': 'release_dates,content_ratings,external_ids'}
)
if not result:
return
self.tmdb_rating = result.get('vote_average')
self.tmdb_votes = result.get('vote_count')
if not self.original_title:
self.original_title = result.get('original_title') or resultresult.get('original_name')
# update original title if missing
if self.original_title:
self._set_value('originaltitle', self.original_title)
if self.tmdb_type == 'tv':
premiered = result.get('first_air_date')
self.tmdb_tv_status = result.get('status')
# update TV status as well
if self.tmdb_tv_status:
self._set_value('status', self.tmdb_tv_status)
else:
premiered = result.get('release_date')
# update the year if not correct
if premiered and self.premiered != premiered:
self.year = premiered[:4]
if ADDON.getSettingBool('update_premiered') or not self.premiered:
self._set_value('premiered', premiered)
if self.tmdb_rating:
self._update_ratings_dict(key='themoviedb',
rating=self.tmdb_rating,
votes=self.tmdb_votes
)
# set MPAA based on setting
if not SKIP_MPAA:
if self.tmdb_type == 'movie':
release_dates = result['release_dates']['results']
for country in release_dates:
if country.get('iso_3166_1') == COUNTRY_CODE:
for item in country['release_dates']:
if item.get('certification'):
self.tmdb_mpaa = item.get('certification')
break
break
elif country.get('iso_3166_1') == 'US':
for item in country['release_dates']:
if item.get('certification'):
self.tmdb_mpaa_fallback = item.get('certification')
break
if self.tmdb_type == 'tv':
content_ratings = result['content_ratings']['results']
for country in content_ratings:
if country.get('iso_3166_1') == COUNTRY_CODE:
self.tmdb_mpaa = country.get('rating')
break
elif country.get('iso_3166_1') == 'US':
self.tmdb_mpaa_fallback = country.get('rating')
if SKIP_NOT_RATED:
if self.tmdb_mpaa == 'NR':
self.tmdb_mpaa = None
if self.tmdb_mpaa_fallback == 'NR':
self.tmdb_mpaa_fallback = None
if self.tmdb_mpaa:
if COUNTRY_CODE == 'DE':
self.tmdb_mpaa = 'FSK ' + self.tmdb_mpaa
self._set_value('mpaa', self.tmdb_mpaa)
elif self.tmdb_mpaa_fallback and MPAA_FALLBACK:
self._set_value('mpaa', self.tmdb_mpaa_fallback)
else:
self._set_value('mpaa', '')
# set IMDb ID if not available in the library
if not self.imdb:
if self.tmdb_type == 'movie':
self.imdb = result.get('imdb_id')
elif self.tmdb_type == 'tv':
self.imdb = result['external_ids'].get('imdb_id')
if self.imdb:
self._update_uniqueid_dict('imdb', self.imdb)
# add TVDb ID to uniqueid if missing
if not self.tvdb and self.tmdb_type == 'tv':
self.tvdb = result['external_ids'].get('tvdb_id')
if self.tvdb:
self._update_uniqueid_dict('tvdb', self.tvdb)
def get_tmdb_externalid(self,external_id):
result = self._tmdb(action='find',
call=str(external_id),
params={'external_source': 'imdb_id' if external_id.startswith('tt') else 'tvdb_id'}
)
if self.dbtype == 'movie' and result.get('movie_results'):
self.tmdb = result['movie_results'][0].get('id')
elif self.dbtype == 'tvshow' and result.get('tv_results'):
self.tmdb = result['tv_results'][0].get('id')
if self.tmdb:
self._update_uniqueid_dict('tmdb', self.tmdb)
def get_omdb(self):
omdb = self._omdb()
if not omdb:
return
tree = ET.ElementTree(ET.fromstring(omdb))
root = tree.getroot()
for child in root:
# imdb ratings
self.imdb_rating = child.get('imdbRating', '').replace('N/A', '')
self.imdb_votes = child.get('imdbVotes', '0').replace('N/A', '0').replace(',', '')
if self.imdb_rating:
self._update_ratings_dict(key='imdb',
rating=float(self.imdb_rating),
votes=int(self.imdb_votes)
)
# regular rotten rating
tomatometerallcritics = child.get('tomatoMeter', '').replace('N/A', '')
tomatometerallcritics_avg = child.get('tomatoRating', '').replace('N/A', '')
tomatometerallcritics_votes = child.get('tomatoReviews', '0').replace('N/A', '0').replace(',', '')
if tomatometerallcritics:
self._update_ratings_dict(key='tomatometerallcritics',
rating=int(tomatometerallcritics) / 10,
votes=int(tomatometerallcritics_votes))
if tomatometerallcritics_avg:
self._update_ratings_dict(key='tomatometeravgcritics',
rating=float(tomatometerallcritics_avg),
votes=int(tomatometerallcritics_votes))
# user rotten rating
tomatometerallaudience = child.get('tomatoUserMeter', '').replace('N/A', '')
tomatometerallaudience_avg = child.get('tomatoUserRating', '').replace('N/A', '')
tomatometerallaudience_votes = child.get('tomatoUserReviews', '0').replace('N/A', '0').replace(',', '')
if tomatometerallaudience:
self._update_ratings_dict(key='tomatometerallaudience',
rating=int(tomatometerallaudience) / 10,
votes=int(tomatometerallaudience_votes))
if tomatometerallaudience_avg:
self._update_ratings_dict(key='tomatometeravgaudience',
rating=float(tomatometerallaudience_avg),
votes=int(tomatometerallaudience_votes))
# metacritic
metacritic = child.get('metascore', '').replace('N/A', '')
if metacritic:
metacritic = int(metacritic) / 10
self._update_ratings_dict(key='metacritic',
rating=metacritic,
votes=0)
# set imdb if not set before
if not self.imdb and child.get('imdbID') and child.get('imdbID') != 'N/A':
self.imdb = child.get('imdbID')
self._update_uniqueid_dict('imdb', child.get('imdbID'))
break
def update_info(self):
# set at least one default rating if none is set in the library
if not self.default_rating and self.ratings:
for item in ['imdb', 'themoviedb', 'tomatometerallcritics', 'tomatometeravgcritics', 'metacritic']:
if item in self.ratings:
self.default_rating = item
break
# unkown rating source is stored -> use the first one
if not self.default_rating:
for item in self.ratings:
self.default_rating = item
break
# update to library
self._set_value(key='ratings', value=self.ratings)
if self.update_uniqueid:
self._set_value(key='uniqueid', value=self.uniqueid)
# episode guide verification
if self.episodeguide:
if 'thetvdb' in self.episodeguide and 'tvdb' not in self.uniqueid:
self.episodeguide = None
elif 'themoviedb' in self.episodeguide and 'tmdb' not in self.uniqueid:
self.episodeguide = None
if self.dbtype == 'tvshow' and not self.episodeguide:
if 'tvdb' in self.uniqueid:
value = self.uniqueid.get('tvdb')
url = 'https://api.thetvdb.com/login?{"apikey":"439DFEBA9D3059C6","id":%s}|Content-Type=application/json' % str(value)
json_value = '<episodeguide><url post="yes" cache="auth.json"><url>%s</url></episodeguide>' % url
elif 'tmdb' in self.uniqueid:
value = self.uniqueid.get('tmdb')
cache = 'tmdb-%s-%s.json' % (str(value), TMDB_LANGUAGE)
url = 'http://api.themoviedb.org/3/tv/%s?api_key=6a5be4999abf74eba1f9a8311294c267&amp;language=%s' % (str(value), TMDB_LANGUAGE)
json_value = '<episodeguide><url cache="%s"><url>%s</url></episodeguide>' % (cache, url)
else:
json_value = '<episodeguide><url cache=""><url></url></episodeguide>'
self.episodeguide = json_value
self._set_value('episodeguide', json_value)
# nfo updating
if self.file:
# get updated data
self.get_details()
# TV status cannot be fetched in Leia
if self.tmdb_tv_status and not self.details.get('status'):
self.details['status'] = self.tmdb_tv_status
update_nfo(file=self.file,
dbtype=self.dbtype,
dbid=self.dbid,
details=self.details
)
def _update_ratings_dict(self,key,rating,votes):
self.ratings[key] = {'default': True if key == self.default_rating else False,
'rating': rating,
'votes': votes}
def _update_uniqueid_dict(self,key,value):
self.uniqueid[key] = str(value)
self.update_uniqueid = True
def _set_value(self,key,value):
self.db.write(key=key, value=value)
def _omdb(self):
if not OMDB_API:
log('No OMDb API key configured. Skip.', force=RATING_DEBUG)
return
if self.imdb:
url = 'http://www.omdbapi.com/?apikey=%s&i=%s&plot=short&r=xml&tomatoes=true' % (OMDB_API, self.imdb)
elif OMDB_FALLBACK and self.dbtype != 'episode' and self.original_title and self.year:
# urllib has issues with some asian letters
try:
title = urllib.quote(self.original_title)
except KeyError:
return
url = 'http://www.omdbapi.com/?apikey=%s&t=%s&year=%s&plot=short&r=xml&tomatoes=true' % (OMDB_API, title, self.year)
else:
return
error_msg = 'OMDb error for "%s (%s)" IMDBd "%s". Error --> ' % (self.original_title, self.year, self.imdb)
for i in range(1,4): # loop if heavy server load
log('OMDb call try %s/3' % str(i), force=RATING_DEBUG)
try:
request = requests.get(url, timeout=5)
if not str(request.status_code).startswith('5'):
break
elif i == 1:
notification('OMDb', ADDON.getLocalizedString(32024))
except Exception:
if i < 3:
xbmc.sleep(500)
else:
log(error_msg + '408', WARNING)
return
if request.status_code == 401:
log('OMDb error --> API limit reached', WARNING)
if DIALOG.yesno(xbmc.getLocalizedString(257), ADDON.getLocalizedString(32033)):
log('OMDb limit reached and disabled for next calls', force=RATING_DEBUG)
self.omdb_limit = True
else:
log('OMDb limit reached and rating updater canceled', force=RATING_DEBUG)
winprop('CancelRatingUpdater.bool', True)
return
elif not request.ok:
log(error_msg + str(request.status_code), WARNING)
return
result = request.text
if not result or '<root response="False">' in result:
log(error_msg + 'Result = ' + str(result), WARNING)
return
return result
def _tmdb(self,action,call=None,get=None,params=None):
result = {}
args = {}
args['api_key'] = 'fc168650632c6597038cf7072a7c20da'
if params:
args.update(params)
call = '/' + str(call) if call else ''
get = '/' + get if get else ''
url = 'https://api.themoviedb.org/3/' + action + call + get
url = '{0}?{1}'.format(url, urlencode(args))
for i in range(1,4): # loop if heavy server load
log('TMDb call try %s/3' % str(i), force=RATING_DEBUG)
try:
request = requests.get(url, timeout=5)
if not str(request.status_code).startswith('5'):
break
elif i == 1:
notification('TMDb', ADDON.getLocalizedString(32024))
except Exception:
if i < 3:
xbmc.sleep(500)
else:
log('TMDb connection error', force=RATING_DEBUG)
return result
if request.ok:
result = request.json()
else:
log('TMDb returned nothing', force=RATING_DEBUG)
return result

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<settings>
<category label="128">
<setting label="$LOCALIZE[128]" type="lsep"/>
<setting label="$ADDON[script.metadata.editor 32021]" type="bool" id="nfo_updating" default="true"/>
<setting label="$ADDON[script.metadata.editor 32034]" type="bool" id="create_nfo" default="true" enable="eq(-1,true)" />
<setting label="$ADDON[script.metadata.editor 32057]" type="bool" id="write_watched_stated" default="true" enable="eq(-2,true)" />
<setting label="$ADDON[script.metadata.editor 32055]" type="bool" id="playback_update_playcount" default="true" enable="eq(-3,true) + eq(-1,true)" />
<setting label="$ADDON[script.metadata.editor 32056]" type="bool" id="playback_user_rating" default="false" />
<setting label="$ADDON[script.metadata.editor 32029]" type="bool" id="json_log" default="false"/>
<setting label="$ADDON[script.metadata.editor 32026]" type="lsep"/>
<setting label="$ADDON[script.metadata.editor 32027]" type="select" values="TVDb|TMDb" id="tv_scraper_base" default="TVDb"/>
<setting label="$ADDON[script.metadata.editor 32025]" type="select" values="bg|cs|da|de|ee|el|en|es|fa|fa-ir|fi|fr|fr-ca|he|hr|hu|it|ja|ko|nl|no|pl|pt|pt-br|ru|sl|sr|sv|tr|zh-cn|zh-tw" id="tmdb_language" default="en"/>
<setting label="$ADDON[script.metadata.editor 32043]" type="select" values="AU|BG|BR|CA|DE|DK|ES|FI|FR|GB|HU|IN|IT|KR|LT|MY|NL|NO|NZ|PH|PT|RU|SE|SK|TH|US" id="country_code" default="US"/>
<setting label="$ADDON[script.metadata.editor 32044]" type="bool" id="mpaa_skip" default="false"/>
<setting label="$ADDON[script.metadata.editor 32052]" type="bool" id="mpaa_fallback" default="true" enable="eq(-1,false) + !eq(-2,US)" />
<setting label="$ADDON[script.metadata.editor 32053]" type="bool" id="mpaa_skip_nr" default="false" enable="eq(-2,false) + !eq(-3,US)" />
<setting label="$ADDON[script.metadata.editor 32032]" type="bool" id="omdb_fallback_search" default="true"/>
<setting label="$ADDON[script.metadata.editor 32041]" type="bool" id="update_premiered" default="true"/>
<setting label="$ADDON[script.metadata.editor 32030]" type="lsep"/>
<setting label="$ADDON[script.metadata.editor 32031]" type="text" id="omdb_api_key"/>
<setting label="$ADDON[script.metadata.editor 32028]" type="bool" id="update_background" default="false"/>
<setting label="$LOCALIZE[20191]" type="bool" id="debug_rating_updater" default="false"/>
</category>
</settings>