Merge branch 'Kometa-Team:nightly' into nightly

pull/2043/head
Chris 6 months ago committed by GitHub
commit d109ce4997
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -4,16 +4,23 @@
**/__pycache__ **/__pycache__
/.vscode /.vscode
**/log **/log
README.md *.psd
LICENSE
.gitignore
.dockerignore
.git .git
.github .github
*.psd .idea
config/**/*
config config
Dockerfile config/**/*
docs
json-schema
venv venv
.idea .dockerignore
.gitignore
.readthedocs.yml
.spellcheck.yml
CHANGELOG
Dockerfile
Dockerfile.lxml
LICENSE
mkdocs.yml
README.md
test.py test.py

@ -0,0 +1,330 @@
AAC
accessModes
Addon
Adlib
Amblin
analytics
AniDB
AniDB's
AniList
anilist
AniList's
API
apikey
APIs
apiVersion
AppleTV
ArrAPI
Arrowverse
Atmos
Avenir
BAFTA
BBFC
bearlikelion
Berlinale
Bestest
BING
bing
bitrate
BOING
boolean
BoxOfficeMojo
boxofficemojo
BPjM
BritBox
britbox
bullmoose
burkasaurusrex
bw
Cappella
cd
chazlarson
codec
codecs
collectionless
config
configs
cpp
cpt
CPUs
cron
CronJob
cronjob
crontab
Crunchyroll
customizable
customizations
César
dbader
de
deva
DIIIVOY
diiivoy
diiivoycolor
DIR
dir
DiskStation
dockerfile
dockerfiles
DockerHub
dockerhub
dolby
DreamWorks
dropdown
DTS
DV
Emmys
ENV
env
etree
eventartworks
favorited
fawkes
FFFFFF
Fi
filepath
filetype
FLAC
FlixPatrol
flixpatrol
fontawesome
Fribb
FSK
Galician
generalizable
GitHub
github
githubusercontent
gotify
Grenvilles
GUID
HAMA
hayu
HD
HDR
Hemsworth
homescreen
homescreens
HRA
html
http
https
Hulu
ICheckMovies
ImageMaid
IMAX
IMDb
imdb
IMDb's
IMDbList
img
includer
init
integrations
io
iteratively
Jinja
jkirkcaldy
JohnFawkes
JonnyWong
jpeg
jpg
json
kesleyalfa
Koltom
kometa
Kometa
Kometa's
kometateam
kometautils
Kubernetes
kuesel
Launchd
Letterboxd
LGBTQ
linas
Lingala
linux
LinuxServer
linuxserver
linuxserver's
localhost
Looper
LSIO
lsio
Luxembourgish
LXML
lxml
macOS
mal
MB
mb
MCU
md
mdb
MDBList
mdblist
MediaStinger
mediastinger
mediastingers
MediUX
mediux
meisnate
metacritic
microsoft
mikenobbs
minikube
mnt
monetization
Mossi
MPAA
MyAnimeList
myanimelist
MyAnimeList's
MyCollections
MyOverlays
MyPlaylists
mza
namespace
NAS
natively
nitsua
Nokmål
NOSUCHLIBRARY
notifiarr
Nynorsk
OAuth
oauth
octicons
OMDb
oscar
OSX
ozzy
pathing
PCM
PersistentVolumeClaim
PGID
pgid
pkkid
plex
plex's
plexapi
PlexCollection
PlexPosters
PNG
Pokémon
popularplex
portainer
Powershell
pre
prepend
PUID
puid
QNAP
radarr
Razzie
Razzies
README
Readme
ReadWriteOnce
reciperr
reddit
RedHeadJedi
REMUX
repo
repos
rholder
RogerEvert
Romani
runtime
runtimes
schemas
Sci-Fi
SciFi
ScudLee
SDTV
SemVer
ShawShank
Skywalker
Sohjiro
Sohjiro's
sonarr
SSL
StevenLu
StevenLu's
subprocess
Sundance
SxxEyy
symlinks
Synology
Systemctl
Taglist
Tautulli
Tautulli's
TELESYNC
Templatizing
th
TheMovieDb
themoviedb
ThePosterDB
TheTVDb
TMDb
tmdb
TMDb's
TMDbAPIs
Toastjuh
TODO
tomatometer
trakt
trakt's
transcoded
transcoding
TRaSH
TrueHD
ttf
tutin
tv
TVDb
UI
unionfs
unmanaged
unplayed
unraid
unRAID
URI
URL
url
urls
UserList
userlist
utills
Vecteezy
VENV
venv
visualstudio
vladimir
Wachowski
walkthrough
walkthroughs
watchlist
webhook
webhooks
WEBP
webserver
whitespace
wildcarded
Witherspoon
Wizarding
Wolof
www
xmark
XYZ
yaml
yml
YourName
yourname
Yozora
YozoraXCII
YYYY
zaP
ZeroQI

BIN
.github/bot.png vendored

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 KiB

@ -42,10 +42,10 @@ jobs:
with: with:
webhook_id_token: ${{ secrets.BUILD_WEBHOOK }} webhook_id_token: ${{ secrets.BUILD_WEBHOOK }}
message: <@&1079153184007790652> message: <@&1079153184007790652>
title: "${{ secrets.REPO_NAME }}: **Copyright Update Failed**" title: "${{ vars.REPO_NAME }}: **Copyright Update Failed**"
url: https://github.com/Kometa-Team/${{ secrets.REPO_NAME }}/actions/runs/${{ github.run_id }} url: https://github.com/Kometa-Team/${{ vars.REPO_NAME }}/actions/runs/${{ github.run_id }}
color: 14879811 color: 14879811
username: Kobota username: Kobota
avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/logo.png avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/bot.png
author: GitHub author: GitHub
author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/git.png author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/git.png

@ -56,11 +56,11 @@ jobs:
if: success() if: success()
with: with:
webhook_id_token: ${{ secrets.BUILD_WEBHOOK }} webhook_id_token: ${{ secrets.BUILD_WEBHOOK }}
title: "${{ secrets.REPO_NAME }} ${{ matrix.node.tag }}: **Build Successful**" title: "${{ vars.REPO_NAME }} ${{ matrix.node.tag }}: **Build Successful**"
url: https://github.com/Kometa-Team/${{ secrets.REPO_NAME }}/actions/runs/${{ github.run_id }} url: https://github.com/Kometa-Team/${{ vars.REPO_NAME }}/actions/runs/${{ github.run_id }}
color: 844716 color: 844716
username: Kobota username: Kobota
avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/logo.png avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/bot.png
author: Docker author: Docker
author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/docker.png author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/docker.png
@ -70,11 +70,11 @@ jobs:
with: with:
webhook_id_token: ${{ secrets.BUILD_WEBHOOK }} webhook_id_token: ${{ secrets.BUILD_WEBHOOK }}
message: <@&1079153184007790652> message: <@&1079153184007790652>
title: "${{ secrets.REPO_NAME }} ${{ matrix.node.tag }}: **Build Failed**" title: "${{ vars.REPO_NAME }} ${{ matrix.node.tag }}: **Build Failed**"
url: https://github.com/Kometa-Team/${{ secrets.REPO_NAME }}/actions/runs/${{ github.run_id }} url: https://github.com/Kometa-Team/${{ vars.REPO_NAME }}/actions/runs/${{ github.run_id }}
color: 14879811 color: 14879811
username: Kobota username: Kobota
avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/logo.png avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/bot.png
author: Docker author: Docker
author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/docker.png author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/docker.png
@ -92,6 +92,6 @@ jobs:
message: "<@&954835263731949623> - An update to Kometa has been published and is available to users of the **develop** branch.\n\nWe **strongly** recommend users who previously switched to the `nightly` branch to resolve any previous issues to now switch back to the `develop` branch now." message: "<@&954835263731949623> - An update to Kometa has been published and is available to users of the **develop** branch.\n\nWe **strongly** recommend users who previously switched to the `nightly` branch to resolve any previous issues to now switch back to the `develop` branch now."
commits: "true" commits: "true"
username: Kobota username: Kobota
avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/logo.png avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/bot.png
author: ${{ secrets.REPO_NAME }} Develop Release author: ${{ vars.REPO_NAME }} Develop Release
author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/release.png author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/release.png

@ -52,11 +52,11 @@ jobs:
if: success() if: success()
with: with:
webhook_id_token: ${{ secrets.BUILD_WEBHOOK }} webhook_id_token: ${{ secrets.BUILD_WEBHOOK }}
title: "${{ secrets.REPO_NAME }} ${{ matrix.node.tag }}: **Build Successful**" title: "${{ vars.REPO_NAME }} ${{ matrix.node.tag }}: **Build Successful**"
url: https://github.com/Kometa-Team/${{ secrets.REPO_NAME }}/actions/runs/${{ github.run_id }} url: https://github.com/Kometa-Team/${{ vars.REPO_NAME }}/actions/runs/${{ github.run_id }}
color: 844716 color: 844716
username: Kobota username: Kobota
avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/logo.png avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/bot.png
author: Docker author: Docker
author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/docker.png author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/docker.png
@ -66,10 +66,10 @@ jobs:
with: with:
webhook_id_token: ${{ secrets.BUILD_WEBHOOK }} webhook_id_token: ${{ secrets.BUILD_WEBHOOK }}
message: <@&1079153184007790652> message: <@&1079153184007790652>
title: "${{ secrets.REPO_NAME }} ${{ matrix.node.tag }}: **Build Failed**" title: "${{ vars.REPO_NAME }} ${{ matrix.node.tag }}: **Build Failed**"
url: https://github.com/Kometa-Team/${{ secrets.REPO_NAME }}/actions/runs/${{ github.run_id }} url: https://github.com/Kometa-Team/${{ vars.REPO_NAME }}/actions/runs/${{ github.run_id }}
color: 14879811 color: 14879811
username: Kobota username: Kobota
avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/logo.png avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/bot.png
author: Docker author: Docker
author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/docker.png author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/docker.png

@ -6,8 +6,37 @@ on:
jobs: jobs:
verify-changes:
runs-on: ubuntu-latest
outputs:
build: ${{ steps.list-changes.outputs.build }}
steps:
- name: Check Out Repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changes
id: get-changes
run: echo "files=$(git diff --name-only ${{ github.event.before }} ${{ github.event.after }} | xargs)" >> $GITHUB_OUTPUT
- name: List changed files
id: list-changes
run: |
for file in ${{ steps.get-changes.outputs.files }}; do
if [[ $file == defaults/* ]] || [[ $file == fonts/* ]] || [[ $file == modules/* ]] || [[ $file == kometa.py ]] || [[ $file == requirements.txt ]] || [[ $file == .dockerignore ]] || [[ $file == Dockerfile ]] || [[ $file == Dockerfile.lxml ]] ; then
echo "$file will trigger docker build"
echo "build=true" >> $GITHUB_OUTPUT
else
echo "$file will not trigger docker build"
fi
done
docker: docker:
needs: [verify-changes]
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: needs.verify-changes.outputs.build == 'true'
strategy: strategy:
matrix: matrix:
node: node:
@ -56,11 +85,11 @@ jobs:
if: success() if: success()
with: with:
webhook_id_token: ${{ secrets.BUILD_WEBHOOK }} webhook_id_token: ${{ secrets.BUILD_WEBHOOK }}
title: "${{ secrets.REPO_NAME }} ${{ matrix.node.tag }}: **Build Successful**" title: "${{ vars.REPO_NAME }} ${{ matrix.node.tag }}: **Build Successful**"
url: https://github.com/Kometa-Team/${{ secrets.REPO_NAME }}/actions/runs/${{ github.run_id }} url: https://github.com/Kometa-Team/${{ vars.REPO_NAME }}/actions/runs/${{ github.run_id }}
color: 844716 color: 844716
username: Kobota username: Kobota
avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/logo.png avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/bot.png
author: Docker author: Docker
author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/docker.png author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/docker.png
@ -70,18 +99,18 @@ jobs:
with: with:
webhook_id_token: ${{ secrets.BUILD_WEBHOOK }} webhook_id_token: ${{ secrets.BUILD_WEBHOOK }}
message: <@&1079153184007790652> message: <@&1079153184007790652>
title: "${{ secrets.REPO_NAME }} ${{ matrix.node.tag }}: **Build Failed**" title: "${{ vars.REPO_NAME }} ${{ matrix.node.tag }}: **Build Failed**"
url: https://github.com/Kometa-Team/${{ secrets.REPO_NAME }}/actions/runs/${{ github.run_id }} url: https://github.com/Kometa-Team/${{ vars.REPO_NAME }}/actions/runs/${{ github.run_id }}
color: 14879811 color: 14879811
username: Kobota username: Kobota
avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/logo.png avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/bot.png
author: Docker author: Docker
author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/docker.png author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/docker.png
commit-notification: commit-notification:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ success() }} if: ${{ success() && needs.verify-changes.outputs.build == 'true' }}
needs: [docker] needs: [docker, verify-changes]
steps: steps:
- name: Send Discord Commit Notification - name: Send Discord Commit Notification
@ -92,6 +121,6 @@ jobs:
message: "<@&967002147520675840> - An update to Kometa has now been published and is available to users of the **nightly** branch." message: "<@&967002147520675840> - An update to Kometa has now been published and is available to users of the **nightly** branch."
commits: "true" commits: "true"
username: Kobota username: Kobota
avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/logo.png avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/bot.png
author: ${{ secrets.REPO_NAME }} Nightly Release author: ${{ vars.REPO_NAME }} Nightly Release
author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/release.png author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/.github/release.png

@ -19,6 +19,6 @@ jobs:
title: Release VERSION title: Release VERSION
message: "<@&967002324646113290> - A new version of Kometa has been released and is available to all users.\n\nWe **strongly** recommend users who previously switched to the `nightly` or `develop` branches to resolve any previous issues to now switch back to the `latest` branch now." message: "<@&967002324646113290> - A new version of Kometa has been released and is available to all users.\n\nWe **strongly** recommend users who previously switched to the `nightly` or `develop` branches to resolve any previous issues to now switch back to the `latest` branch now."
username: Kobota username: Kobota
avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/logo.png avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/bot.png
author: Kometa Release author: Kometa Release
author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/release.png author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/develop/.github/release.png

@ -0,0 +1,12 @@
name: Spellcheck Action
on: pull_request
jobs:
spellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: rojopolis/spellcheck-github-actions@0.36.0

@ -1,12 +1,11 @@
name: Tag name: Tag New Version
on: on:
push: push:
branches: [ master ] branches: [ master ]
jobs: jobs:
tag:
tag-new-versions:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@ -15,7 +14,7 @@ jobs:
token: ${{ secrets.PAT }} token: ${{ secrets.PAT }}
fetch-depth: 2 fetch-depth: 2
- uses: salsify/action-detect-and-tag-new-version@v1.0.3 - uses: Kometa-Team/tag-new-version@master
with: with:
version-command: | version-command: |
cat VERSION cat VERSION

@ -8,15 +8,8 @@ on:
jobs: jobs:
docker: docker:
if: ${{ startsWith(github.ref, 'refs/tags/v1') || startsWith(github.ref, 'refs/tags/v2') }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
matrix:
node:
- tag: ""
file: Dockerfile
- tag: lxml-
file: Dockerfile.lxml
steps: steps:
- name: Check Out Repo - name: Check Out Repo
@ -43,15 +36,27 @@ jobs:
id: get_version id: get_version
run: echo "VERSION=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT run: echo "VERSION=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT
- name: Build and Push LXML
id: docker_build_lxml
uses: docker/build-push-action@v5
with:
context: ./
file: ./Dockerfile.lxml
platforms: linux/amd64,linux/arm64,linux/arm/v7
push: true
tags: kometateam/kometa:lxml-${{ steps.get_version.outputs.VERSION }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Build and Push - name: Build and Push
id: docker_build id: docker_build
uses: docker/build-push-action@v5 uses: docker/build-push-action@v5
with: with:
context: ./ context: ./
file: ./${{ matrix.node.file }} file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/arm/v7 platforms: linux/amd64,linux/arm64,linux/arm/v7
push: true push: true
tags: kometateam/kometa:${{ matrix.node.tag }}${{ steps.get_version.outputs.VERSION }} tags: kometateam/kometa:${{ steps.get_version.outputs.VERSION }}
cache-from: type=gha cache-from: type=gha
cache-to: type=gha,mode=max cache-to: type=gha,mode=max
@ -60,11 +65,11 @@ jobs:
if: success() if: success()
with: with:
webhook_id_token: ${{ secrets.BUILD_WEBHOOK }} webhook_id_token: ${{ secrets.BUILD_WEBHOOK }}
title: "${{ secrets.REPO_NAME }} ${{ steps.get_version.outputs.VERSION }}: **Build Successful**" title: "${{ vars.REPO_NAME }} ${{ steps.get_version.outputs.VERSION }}: **Build Successful**"
url: https://github.com/Kometa-Team/${{ secrets.REPO_NAME }}/actions/runs/${{ github.run_id }} url: https://github.com/Kometa-Team/${{ vars.REPO_NAME }}/actions/runs/${{ github.run_id }}
color: 844716 color: 844716
username: Kobota username: Kobota
avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/logo.png avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/bot.png
author: Docker author: Docker
author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/docker.png author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/docker.png
@ -74,29 +79,14 @@ jobs:
with: with:
webhook_id_token: ${{ secrets.BUILD_WEBHOOK }} webhook_id_token: ${{ secrets.BUILD_WEBHOOK }}
message: <@&1079153184007790652> message: <@&1079153184007790652>
title: "${{ secrets.REPO_NAME }} ${{ steps.get_version.outputs.VERSION }}: **Build Failed**" title: "${{ vars.REPO_NAME }} ${{ steps.get_version.outputs.VERSION }}: **Build Failed**"
url: https://github.com/Kometa-Team/${{ secrets.REPO_NAME }}/actions/runs/${{ github.run_id }} url: https://github.com/Kometa-Team/${{ vars.REPO_NAME }}/actions/runs/${{ github.run_id }}
color: 14879811 color: 14879811
username: Kobota username: Kobota
avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/logo.png avatar_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/bot.png
author: Docker author: Docker
author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/docker.png author_icon_url: https://raw.githubusercontent.com/Kometa-Team/Kometa/master/.github/docker.png
commit-notification:
runs-on: ubuntu-latest
if: ${{ success() }}
needs: [docker]
steps:
- name: Check Out Repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get the version
id: get_version
run: echo "VERSION=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT
- name: Checkout Configs Repo - name: Checkout Configs Repo
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:

1
.gitignore vendored

@ -18,6 +18,7 @@ config/overlays/*/
config/overlays/temp.jpeg config/overlays/temp.jpeg
config/overlays/temp.jpg config/overlays/temp.jpg
config/overlays/temp.png config/overlays/temp.png
config/overlays/temp.webp
!config/*.template !config/*.template
build/ build/
develop-eggs/ develop-eggs/

@ -0,0 +1,19 @@
matrix:
- name: Markdown
sources:
- '**/*.md'
- 'CHANGELOG'
aspell:
lang: en
dictionary:
wordlists:
- .github/.wordlist.txt
encoding: utf-8
pipeline:
- pyspelling.filters.markdown:
- pyspelling.filters.html:
comments: false
ignores:
- code
- pre
default_encoding: utf-8

@ -1,26 +1,16 @@
# Plex Meta Manager is now rebranded as Kometa!
# Requirements Update (requirements will need to be reinstalled) # Requirements Update (requirements will need to be reinstalled)
Updated arrapi requirement to 1.4.11
Updated PlexAPI requirement to 4.15.12
Updated setuptools requirement to 69.5.1
Updated tmdbapis requirement to 1.2.14
# Removed Features # Removed Features
# New Features # New Features
Add Page Topics Options to `imdb_search` Checks requirement versions to print a message if one needs to be updated
Add `lxml` Docker Version using an old lxml version that supports more cpus Added the `mass_added_at_update` operation to mass set the Added At field of Movies and Shows.
# Updates # Updates
Let conditional `.not` and `.exists` work with default variables Changed the `overlay_artwork_filetype` Setting to accept `webp_lossy` and `webp_lossless` while the old attribute `webp` will be treated as `webp_lossy`.
# Defaults # Defaults
# Bug Fixes # Bug Fixes
Fixes #1965 `download_url_assets` was causing `url_background` to upload as a poster
Fixes #1969 Ignore validating TPDb links
Various other Minor Fixes Various other Minor Fixes
Closed legacy issues on GitHub

@ -44,12 +44,6 @@ The below YouTube video has been created by one of our community members to show
[![Kometa](https://img.youtube.com/vi/nTfCUtKWTYI/0.jpg)](https://www.youtube.com/watch?v=nTfCUtKWTYI "Kometa") [![Kometa](https://img.youtube.com/vi/nTfCUtKWTYI/0.jpg)](https://www.youtube.com/watch?v=nTfCUtKWTYI "Kometa")
## Demo Video
The below YouTube video has been created by one of our community members to showcase some of the things that Kometa can do for you.
[![Kometa](https://img.youtube.com/vi/nTfCUtKWTYI/0.jpg)](https://www.youtube.com/watch?v=nTfCUtKWTYI "Kometa")
## Example Kometa Libraries ## Example Kometa Libraries
Here are some examples of the things you can achieve using Kometa! Here are some examples of the things you can achieve using Kometa!

@ -1 +1 @@
1.21.1-develop2 2.0.1-develop7

@ -74,6 +74,8 @@ settings:
playlist_report: false playlist_report: false
verify_ssl: true verify_ssl: true
custom_repo: custom_repo:
overlay_artwork_filetype: jpg
overlay_artwork_quality: 75
webhooks: # Can be individually specified per library as well webhooks: # Can be individually specified per library as well
error: error:
version: version:

@ -14,7 +14,7 @@ templates:
streaming: streaming:
optional: optional:
- use_<<key>> - use_<<key>>
- use_<<originals_key>> - use_<<tmdb_key>>
- allowed_libraries - allowed_libraries
- originals_only - originals_only
conditionals: conditionals:
@ -26,27 +26,33 @@ templates:
conditions: conditions:
- originals_only: false - originals_only: false
value: <<limit>> value: <<limit>>
discover_with:
conditions:
- originals_only: false
value: <<key>>
discover_region: discover_region:
conditions: conditions:
- originals_only: false - originals_only: false
value: <<region>> value: <<region>>
final_tmdb_key:
default: <<tmdb_key>>
conditions:
- region: CA
tmdb_key: [9]
value: 119
discover_with:
conditions:
- originals_only: false
value: <<final_tmdb_key>>
allowed_streaming: allowed_streaming:
conditions: conditions:
- originals_only: true - originals_only: true
key: ["103", "1759", "151", "230", "283", "510", "39", "37", "188"] tmdb_key: [103, 1759, 151, 230, 283, 510, 39, 37, 188]
value: False value: False
- region.not: GB - region.not: GB
key: ["103", "151", "39"] tmdb_key: [103, 151, 39]
value: False value: False
- region.not: CA - region.not: CA
key: ["230"] tmdb_key: [230]
value: False value: False
- region: CA - region: CA
key: ["1899", "37"] tmdb_key: [1899, 37]
value: False value: False
default: default:
@ -58,13 +64,13 @@ templates:
sort_by_<<key>>: <<sort_by>> sort_by_<<key>>: <<sort_by>>
run_definition: run_definition:
- <<use_<<key>>>> - <<use_<<key>>>>
- <<use_<<originals_key>>>> - <<use_<<tmdb_key>>>>
- <<allowed_libraries>> - <<allowed_libraries>>
- <<allowed_streaming>> - <<allowed_streaming>>
cache_builders: 1 cache_builders: 1
smart_label: <<sort_by_<<key>>>> smart_label: <<sort_by_<<key>>>>
sync_mode: <<sync_mode_<<key>>>> sync_mode: <<sync_mode_<<key>>>>
mdblist_list: https://mdblist.com/lists/k0meta/<<originals_key>>-<<originals>> mdblist_list: https://mdblist.com/lists/k0meta/<<key>>-<<originals>>
tmdb_discover: tmdb_discover:
limit: <<discover_limit>> limit: <<discover_limit>>
with_watch_providers: <<discover_with>> with_watch_providers: <<discover_with>>
@ -82,24 +88,24 @@ dynamic_collections:
Streaming: Streaming:
type: custom type: custom
data: data:
103: All 4 all4: All 4
350: Apple TV+ appletv: Apple TV+
1759: BET+ bet: BET+
151: BritBox britbox: BritBox
230: Crave crave: Crave
283: Crunchyroll crunchyroll: Crunchyroll
510: discovery+ discovery: discovery+
337: Disney+ disney: Disney+
1899: Max max: Max
223: hayu hayu: hayu
15: Hulu hulu: Hulu
8: Netflix netflix: Netflix
39: NOW now: NOW
531: Paramount+ paramount: Paramount+
387: Peacock peacock: Peacock
9: Prime Video amazon: Prime Video
37: Showtime showtime: Showtime
188: YouTube youtube: YouTube
title_format: <<key_name>> <<library_typeU>>s title_format: <<key_name>> <<library_typeU>>s
template: template:
- streaming - streaming
@ -108,31 +114,31 @@ dynamic_collections:
template_variables: template_variables:
image: image:
default: streaming/<<key_name_encoded>> default: streaming/<<key_name_encoded>>
originals_key: tmdb_key:
103: all4 all4: 103
350: appletv appletv: 350
1759: bet bet: 1759
151: britbox britbox: 151
230: crave crave: 230
283: crunchyroll crunchyroll: 283
510: discovery discovery: 510
337: disney disney: 337
1899: max max: 1899
223: hayu hayu: 223
15: hulu hulu: 15
8: netflix netflix: 8
39: now now: 39
531: paramount paramount: 531
387: peacock peacock: 387
9: amazon amazon: 9
37: showtime showtime: 37
188: youtube youtube: 188
originals_only: originals_only:
default: false default: false
allowed_libraries: allowed_libraries:
223: show hayu: show
510: show discovery: show
283: show crunchyroll: show
translation_key: translation_key:
default: streaming default: streaming
dynamic: dynamic:

@ -23,10 +23,14 @@ templates:
default: default:
limit: 100 limit: 100
limit_season: <<limit>> limit_season: <<limit>>
starting_only_season: <<starting_only>>
optional:
- starting_only
mal_season: mal_season:
season: current season: current
sort_by: score sort_by: score
limit: <<limit_season>> limit: <<limit_season>>
starting_only: <<starting_only_season>>
collections: collections:
MyAnimeList Popular: MyAnimeList Popular:

@ -143,35 +143,58 @@ dynamic_collections:
lgbtq: range(05/31-06/30) lgbtq: range(05/31-06/30)
latinx: range(09/15-10/15) latinx: range(09/15-10/15)
women: range(02/28-03/31) women: range(02/28-03/31)
# check3 # check4
imdb_list: imdb_search:
years: https://www.imdb.com/list/ls066838460/ years:
list.any: ls066838460
limit: 500
valentine: valentine:
- https://www.imdb.com/list/ls000094398/ list.any:
- https://www.imdb.com/list/ls057783436/ - ls000094398
- https://www.imdb.com/list/ls064427905/ - ls057783436
patrick: https://www.imdb.com/list/ls063934595/ - ls064427905
limit: 500
patrick:
list.any: ls063934595
limit: 500
easter: easter:
- https://www.imdb.com/list/ls062665509/ list.any:
- https://www.imdb.com/list/ls051733651/ - ls062665509
mother: https://www.imdb.com/list/ls072551197/ - ls051733651
memorial: https://www.imdb.com/list/ls561621160/ limit: 500
father: https://www.imdb.com/list/ls020471057/ mother:
list.any: ls072551197
limit: 500
memorial:
list.any: ls561621160
limit: 500
father:
list.any: ls020471057
limit: 500
independence: independence:
- https://www.imdb.com/list/ls068664510/ list.any:
- https://www.imdb.com/list/ls080925875/ - ls068664510
labor: https://www.imdb.com/list/ls002014923/ - ls080925875
limit: 500
labor:
list.any: ls002014923
limit: 500
halloween: halloween:
- https://www.imdb.com/list/ls023118929/ list.any:
- https://www.imdb.com/list/ls000099714/ - ls023118929
- ls000099714
limit: 500
veteran: veteran:
- https://www.imdb.com/list/ls565595526/ list.any: ls565595526
limit: 500
thanksgiving: thanksgiving:
- https://www.imdb.com/list/ls000835734/ list.any:
- https://www.imdb.com/list/ls091597850/ - ls000835734
christmas: https://www.imdb.com/list/ls000096828/ - ls091597850
# check4 limit: 500
imdb_search: christmas:
list.any: ls000096828
limit: 500
women: women:
type: movie type: movie
keyword.any: women in film, women's rights, women's suffrage, womens rights, womens suffrage keyword.any: women in film, women's rights, women's suffrage, womens rights, womens suffrage

@ -122,7 +122,7 @@ templates:
rating<<rating_num>>_image_url: rating<<rating_num>>_image_url:
conditions: conditions:
- rating<<rating_num>>_image: anidb - rating<<rating_num>>_image: anidb
value: Anidb value: AniDB
- rating<<rating_num>>_image: imdb - rating<<rating_num>>_image: imdb
value: IMDb value: IMDb
- rating<<rating_num>>_image: letterboxd - rating<<rating_num>>_image: letterboxd

@ -55,11 +55,11 @@ templates:
originals_only: false originals_only: false
optional: optional:
- use_<<key>> - use_<<key>>
- use_<<originals_key>> - use_<<tmdb_key>>
- allowed_libraries - allowed_libraries
run_definition: run_definition:
- <<use_<<key>>>> - <<use_<<key>>>>
- <<use_<<originals_key>>>> - <<use_<<tmdb_key>>>>
- <<allowed_libraries>> - <<allowed_libraries>>
- <<allowed_streaming>> - <<allowed_streaming>>
ignore_blank_results: true ignore_blank_results: true
@ -75,26 +75,32 @@ templates:
discover_with: discover_with:
conditions: conditions:
- originals_only: false - originals_only: false
value: <<key>> value: <<final_tmdb_key>>
discover_region: discover_region:
conditions: conditions:
- originals_only: false - originals_only: false
value: <<region>> value: <<region>>
final_tmdb_key:
default: <<tmdb_key>>
conditions:
- region: CA
tmdb_key: [9]
value: 119
allowed_streaming: allowed_streaming:
conditions: conditions:
- originals_only: true - originals_only: true
key: ["103", "1759", "151", "230", "283", "510", "39", "37", "188"] tmdb_key: [103, 1759, 151, 230, 283, 510, 39, 37, 188]
value: False value: False
- region.not: GB - region.not: GB
key: ["103", "151", "39"] tmdb_key: [103, 151, 39]
value: False value: False
- region.not: CA - region.not: CA
key: ["230"] tmdb_key: [230]
value: False value: False
- region: CA - region: CA
key: ["1899", "37"] tmdb_key: [1899, 37]
value: False value: False
mdblist_list: https://mdblist.com/lists/k0meta/<<originals_key>>-<<originals>> mdblist_list: https://mdblist.com/lists/k0meta/<<key>>-<<originals>>
tmdb_discover: tmdb_discover:
limit: <<discover_limit>> limit: <<discover_limit>>
with_watch_providers: <<discover_with>> with_watch_providers: <<discover_with>>
@ -103,73 +109,73 @@ templates:
overlays: overlays:
Netflix: Netflix:
variables: {key: "8", originals_key: netflix, weight: 160} variables: {key: netflix, tmdb_key: 8, weight: 160}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
Prime: Prime:
variables: {key: "9", originals_key: amazon, weight: 150} variables: {key: amazon, tmdb_key: 9, weight: 150}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
Disney: Disney:
variables: {key: "337", originals_key: disney, weight: 140} variables: {key: disney, tmdb_key: 337, weight: 140}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
Max: Max:
variables: {key: "1899", originals_key: max, weight: 130} variables: {key: max, tmdb_key: 1899, weight: 130}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
Crunchyroll: Crunchyroll:
variables: {key: "283", originals_key: crunchyroll, weight: 120, allowed_libraries: show} variables: {key: crunchyroll, tmdb_key: 283, weight: 120, allowed_libraries: show}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
YouTube: YouTube:
variables: {key: "188", originals_key: youtube, weight: 110} variables: {key: youtube, tmdb_key: 188, weight: 110}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
Hulu: Hulu:
variables: {key: "15", originals_key: hulu, weight: 100} variables: {key: hulu, tmdb_key: 15, weight: 100}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
Paramount: Paramount:
variables: {key: "531", originals_key: paramount, weight: 90} variables: {key: paramount, tmdb_key: 531, weight: 90}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
AppleTV: AppleTV:
variables: {key: "350", originals_key: appletv, weight: 80} variables: {key: appletv, tmdb_key: 350, weight: 80}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
Peacock: Peacock:
variables: {key: "387", originals_key: peacock, weight: 70} variables: {key: peacock, tmdb_key: 387, weight: 70}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
Showtime: Showtime:
variables: {key: "37", originals_key: showtime, weight: 60} variables: {key: showtime, tmdb_key: 37, weight: 60}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
discovery+: discovery+:
variables: {key: "510", originals_key: discovery, weight: 58, allowed_libraries: show} variables: {key: discovery, tmdb_key: 510, weight: 58, allowed_libraries: show}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
Crave: Crave:
variables: {key: "230", originals_key: crave, weight: 55} variables: {key: crave, tmdb_key: 230, weight: 55}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
NOW: NOW:
variables: {key: "39", originals_key: now, weight: 50} variables: {key: now, tmdb_key: 39, weight: 50}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
All 4: All 4:
variables: {key: "103", originals_key: all4, weight: 40} variables: {key: all4, tmdb_key: 103, weight: 40}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
britbox: britbox:
variables: {key: "151", originals_key: britbox, weight: 30} variables: {key: britbox, tmdb_key: 151, weight: 30}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
BET+: BET+:
variables: {key: "1759", originals_key: bet, weight: 20} variables: {key: bet, tmdb_key: 1759, weight: 20}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]
hayu: hayu:
variables: {key: "223", originals_key: hayu, weight: 10, allowed_libraries: show} variables: {key: hayu, tmdb_key: 223, weight: 10, allowed_libraries: show}
template: [name: standard, name: mdb_streaming] template: [name: standard, name: mdb_streaming]

@ -64,6 +64,12 @@ templates:
- file_poster_<<key>>.exists: false - file_poster_<<key>>.exists: false
file_poster.exists: false file_poster.exists: false
value: <<url_poster>> value: <<url_poster>>
final_use:
conditions:
- use_<<key>>.exists: true
value: <<use_<<key>>>>
- use_all: false
value: false
default: default:
collection_section: "00" collection_section: "00"
key: <<mapping_name>> key: <<mapping_name>>
@ -110,6 +116,7 @@ templates:
- delete_collections_named - delete_collections_named
- schedule - schedule
run_definition: run_definition:
- <<final_use>>
- <<use_<<key>>>> - <<use_<<key>>>>
- <<allowed_libraries>> - <<allowed_libraries>>
name_mapping: <<name_mapping>> name_mapping: <<name_mapping>>

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 KiB

@ -298,11 +298,17 @@ The available attributes for each library are as follows:
<div id="reapply-overlays" />Used to reapply overlays from this library only. This will reapply overlays to every item in your library. <div id="reapply-overlays" />Used to reapply overlays from this library only. This will reapply overlays to every item in your library.
Note that this is typically NEVER required. Kometa will automatically update overlays as needed as part of a regular overlay run.
???+ warning "Proceed with Caution" ???+ warning "Proceed with Caution"
When set to `true`, this will reapply all overlays on each run even if there is no need to do so, which will result in When set to `true`, this will reapply all overlays on each run even if there is no need to do so, which will result in
[image bloat](../kometa/scripts/imagemaid.md). [image bloat](../kometa/scripts/imagemaid.md).
If you think you need to use this setting, please think hard about why you have that impression, as you are almost certainly mistaken.
In general use, this setting will only extend runtimes and cause image bloat in the Plex metadata for no good reason.
<hr style="margin: 0px;"> <hr style="margin: 0px;">
**Attribute:** `reapply_overlays` **Attribute:** `reapply_overlays`

@ -1,6 +1,6 @@
# MdbList Attributes # MDBList Attributes
Configuring [MdbList](https://mdblist.com/) is optional but can allow you to mass edit metadata. Configuring [MDBList](https://mdblist.com/) is optional but can allow you to mass edit metadata.
A `mdblist` mapping is in the root of the config file. A `mdblist` mapping is in the root of the config file.
@ -13,12 +13,12 @@ mdblist:
| Attribute | Allowed Values | Default | Required | | Attribute | Allowed Values | Default | Required |
|:-------------------|:--------------------------------------------------------------------------|:--------|:------------------------------------------:| |:-------------------|:--------------------------------------------------------------------------|:--------|:------------------------------------------:|
| `apikey` | MdbList API Key | N/A | :fontawesome-solid-circle-check:{ .green } | | `apikey` | MDBList API Key | N/A | :fontawesome-solid-circle-check:{ .green } |
| `cache_expiration` | Number of days before each cache mapping expires and has to be re-cached. | 60 | :fontawesome-solid-circle-xmark:{ .red } | | `cache_expiration` | Number of days before each cache mapping expires and has to be re-cached. | 60 | :fontawesome-solid-circle-xmark:{ .red } |
???+ tip ???+ tip
The MdbList apikey can be found [here](https://mdblist.com/preferences/). The MDBList apikey can be found [here](https://mdblist.com/preferences/).
The free apikey is limited to 1000 requests per day so if you hit your limit the program should be able to pick up The free apikey is limited to 1000 requests per day so if you hit your limit the program should be able to pick up
where it left off the next day as long as the `cache` [Setting](settings.md#cache) is enabled. where it left off the next day as long as the `cache` [Setting](settings.md#cache) is enabled.

@ -66,7 +66,7 @@ To connect to MyAnimeList.net you must create a MyAnimeList application and supp
You will need to stop that web server while you're doing this in order to grab that localhost URL. You will need to stop that web server while you're doing this in order to grab that localhost URL.
19. Run Kometa and the auth will be completed. 19. Run Kometa and the authentication will be completed.
## Alternative Way of Letting Kometa make the URL ## Alternative Way of Letting Kometa make the URL
@ -127,6 +127,6 @@ the container normally.
## Online Authorization ## Online Authorization
{% {%
include-markdown "./auth.md" include-markdown "./authentication.md"
start="# Trakt and MyAnimeList Authentication" start="# Trakt and MyAnimeList Authentication"
%} %}

@ -158,11 +158,11 @@ You can create individual blocks of operations by using a list under `operations
**Accepted Values:** Source or List of sources to use in that order **Accepted Values:** Source or List of sources to use in that order
<table class="clearTable"> <table class="clearTable">
<tr><td>`mdb`</td><td>Use MdbList for Content Ratings</td></tr> <tr><td>`mdb`</td><td>Use MDBList for Content Ratings</td></tr>
<tr><td>`mdb_commonsense`</td><td>Use Common Sense Rating through MDbList for Content Ratings</td></tr> <tr><td>`mdb_commonsense`</td><td>Use Common Sense Rating through MDBList for Content Ratings</td></tr>
<tr><td>`mdb_commonsense0`</td><td>Use Common Sense Rating with Zero Padding through MDbList for Content Ratings</td></tr> <tr><td>`mdb_commonsense0`</td><td>Use Common Sense Rating with Zero Padding through MDBList for Content Ratings</td></tr>
<tr><td>`mdb_age_rating`</td><td>Use MDbList Age Rating for Content Ratings</td></tr> <tr><td>`mdb_age_rating`</td><td>Use MDBList Age Rating for Content Ratings</td></tr>
<tr><td>`mdb_age_rating0`</td><td>Use MDbList Age Rating with Zero Padding for Content Ratings</td></tr> <tr><td>`mdb_age_rating0`</td><td>Use MDBList Age Rating with Zero Padding for Content Ratings</td></tr>
<tr><td>`omdb`</td><td>Use IMDb through OMDb for Content Ratings</td></tr> <tr><td>`omdb`</td><td>Use IMDb through OMDb for Content Ratings</td></tr>
<tr><td>`mal`</td><td>Use MyAnimeList for Content Ratings</td></tr> <tr><td>`mal`</td><td>Use MyAnimeList for Content Ratings</td></tr>
<tr><td>`lock`</td><td>Lock Content Rating Field</td></tr> <tr><td>`lock`</td><td>Lock Content Rating Field</td></tr>
@ -279,8 +279,8 @@ You can create individual blocks of operations by using a list under `operations
<tr><td>`tmdb`</td><td>Use TMDb Release Date</td></tr> <tr><td>`tmdb`</td><td>Use TMDb Release Date</td></tr>
<tr><td>`tvdb`</td><td>Use TVDb Release Date</td></tr> <tr><td>`tvdb`</td><td>Use TVDb Release Date</td></tr>
<tr><td>`omdb`</td><td>Use IMDb Release Date through OMDb</td></tr> <tr><td>`omdb`</td><td>Use IMDb Release Date through OMDb</td></tr>
<tr><td>`mdb`</td><td>Use MdbList Release Date</td></tr> <tr><td>`mdb`</td><td>Use MDBList Release Date</td></tr>
<tr><td>`mdb_digital`</td><td>Use MdbList Digital Release Date</td></tr> <tr><td>`mdb_digital`</td><td>Use MDBList Digital Release Date</td></tr>
<tr><td>`anidb`</td><td>Use AniDB Release Date</td></tr> <tr><td>`anidb`</td><td>Use AniDB Release Date</td></tr>
<tr><td>`mal`</td><td>Use MyAnimeList Release Date</td></tr> <tr><td>`mal`</td><td>Use MyAnimeList Release Date</td></tr>
<tr><td>`lock`</td><td>Lock Originally Available Field</td></tr> <tr><td>`lock`</td><td>Lock Originally Available Field</td></tr>
@ -302,6 +302,45 @@ You can create individual blocks of operations by using a list under `operations
- 1900-01-01 - 1900-01-01
``` ```
###### Mass Added At Update
??? blank "`mass_added_at_update` - Updates the added at date of every item in the library.<a class="headerlink" href="#mass-added-at-update" title="Permanent link"></a>"
<div id="mass-added-at-update" />Updates every item's added at date in the library to the chosen site's date.
<hr style="margin: 0px;">
**Attribute:** `mass_added_at_update`
**Accepted Values:** Source or List of sources to use in that order
<table class="clearTable">
<tr><td>`tmdb`</td><td>Use TMDb Release Date</td></tr>
<tr><td>`tvdb`</td><td>Use TVDb Release Date</td></tr>
<tr><td>`omdb`</td><td>Use IMDb Release Date through OMDb</td></tr>
<tr><td>`mdb`</td><td>Use MDBList Release Date</td></tr>
<tr><td>`mdb_digital`</td><td>Use MDBList Digital Release Date</td></tr>
<tr><td>`anidb`</td><td>Use AniDB Release Date</td></tr>
<tr><td>`mal`</td><td>Use MyAnimeList Release Date</td></tr>
<tr><td>`lock`</td><td>Lock Added At Field</td></tr>
<tr><td>`unlock`</td><td>Unlock Added At Field</td></tr>
<tr><td>`remove`</td><td>Remove Added At and Lock Field</td></tr>
<tr><td>`reset`</td><td>Remove Added At and Unlock Field</td></tr>
<tr><td colspan="2">Any String in the Format: YYYY-MM-DD for Added At (<code>2022-05-28</code>)</td></tr>
</table>
???+ example "Example"
```yaml
libraries:
TV Shows:
operations:
mass_added_at_update:
- mdb_digital
- mdb
- 1900-01-01
```
###### Mass Rating Update ###### Mass Rating Update
??? blank "`mass_***_rating_update` - Updates the audience/critic/user rating of every item in the library.<a class="headerlink" href="#mass-star-rating-update" title="Permanent link"></a>" ??? blank "`mass_***_rating_update` - Updates the audience/critic/user rating of every item in the library.<a class="headerlink" href="#mass-star-rating-update" title="Permanent link"></a>"
@ -330,17 +369,17 @@ You can create individual blocks of operations by using a list under `operations
<tr><td>`imdb`</td><td>Use IMDb Rating</td></tr> <tr><td>`imdb`</td><td>Use IMDb Rating</td></tr>
<tr><td>`trakt_user`</td><td>Use Trakt User's Personal Rating</td></tr> <tr><td>`trakt_user`</td><td>Use Trakt User's Personal Rating</td></tr>
<tr><td>`omdb`</td><td>Use IMDbRating through OMDb</td></tr> <tr><td>`omdb`</td><td>Use IMDbRating through OMDb</td></tr>
<tr><td>`mdb`</td><td>Use MdbList Score</td></tr> <tr><td>`mdb`</td><td>Use MDBList Score</td></tr>
<tr><td>`mdb_average`</td><td>Use MdbList Average Score</td></tr> <tr><td>`mdb_average`</td><td>Use MDBList Average Score</td></tr>
<tr><td>`mdb_imdb`</td><td>Use IMDb Rating through MDbList</td></tr> <tr><td>`mdb_imdb`</td><td>Use IMDb Rating through MDBList</td></tr>
<tr><td>`mdb_metacritic`</td><td>Use Metacritic Rating through MDbList</td></tr> <tr><td>`mdb_metacritic`</td><td>Use Metacritic Rating through MDBList</td></tr>
<tr><td>`mdb_metacriticuser`</td><td>Use Metacritic User Rating through MDbList</td></tr> <tr><td>`mdb_metacriticuser`</td><td>Use Metacritic User Rating through MDBList</td></tr>
<tr><td>`mdb_trakt`</td><td>Use Trakt Rating through MDbList</td></tr> <tr><td>`mdb_trakt`</td><td>Use Trakt Rating through MDBList</td></tr>
<tr><td>`mdb_tomatoes`</td><td>Use Rotten Tomatoes Rating through MDbList</td></tr> <tr><td>`mdb_tomatoes`</td><td>Use Rotten Tomatoes Rating through MDBList</td></tr>
<tr><td>`mdb_tomatoesaudience`</td><td>Use Rotten Tomatoes Audience Rating through MDbList</td></tr> <tr><td>`mdb_tomatoesaudience`</td><td>Use Rotten Tomatoes Audience Rating through MDBList</td></tr>
<tr><td>`mdb_tmdb`</td><td>Use TMDb Rating through MDbList</td></tr> <tr><td>`mdb_tmdb`</td><td>Use TMDb Rating through MDBList</td></tr>
<tr><td>`mdb_letterboxd`</td><td>Use Letterboxd Rating through MDbList</td></tr> <tr><td>`mdb_letterboxd`</td><td>Use Letterboxd Rating through MDBList</td></tr>
<tr><td>`mdb_myanimelist`</td><td>Use MyAnimeList Rating through MDbList</td></tr> <tr><td>`mdb_myanimelist`</td><td>Use MyAnimeList Rating through MDBList</td></tr>
<tr><td>`anidb_rating`</td><td>Use AniDB Rating</td></tr> <tr><td>`anidb_rating`</td><td>Use AniDB Rating</td></tr>
<tr><td>`anidb_average`</td><td>Use AniDB Average</td></tr> <tr><td>`anidb_average`</td><td>Use AniDB Average</td></tr>
<tr><td>`anidb_score`</td><td>Use AniDB Review Score</td></tr> <tr><td>`anidb_score`</td><td>Use AniDB Review Score</td></tr>

@ -9,7 +9,7 @@ A template Configuration File can be found in the
[GitHub Repo](https://github.com/Kometa-Team/Kometa/blob/master/config/config.yml.template). [GitHub Repo](https://github.com/Kometa-Team/Kometa/blob/master/config/config.yml.template).
This table outlines the third-party services that Kometa can make use of. Each service has specific This table outlines the third-party services that Kometa can make use of. Each service has specific
requirements for setup that can be found by clicking the links within the table. requirements for setup that can be found by clicking the links within the table or in the sidebar.
| Attribute | Required | | Attribute | Required |
|:--------------------------------------------|:----------------------------------------------------------------------| |:--------------------------------------------|:----------------------------------------------------------------------|
@ -19,9 +19,10 @@ requirements for setup that can be found by clicking the links within the table.
| [`webhooks`](webhooks.md) | :fontawesome-solid-circle-xmark:{ .red } | | [`webhooks`](webhooks.md) | :fontawesome-solid-circle-xmark:{ .red } |
| [`plex`](plex.md) | :fontawesome-solid-circle-check:{ .green } Either here or per library | | [`plex`](plex.md) | :fontawesome-solid-circle-check:{ .green } Either here or per library |
| [`tmdb`](tmdb.md) | :fontawesome-solid-circle-check:{ .green } | | [`tmdb`](tmdb.md) | :fontawesome-solid-circle-check:{ .green } |
| [`github`](github.md) | :fontawesome-solid-circle-xmark:{ .red } |
| [`tautulli`](tautulli.md) | :fontawesome-solid-circle-xmark:{ .red } | | [`tautulli`](tautulli.md) | :fontawesome-solid-circle-xmark:{ .red } |
| [`github`](github.md) | :fontawesome-solid-circle-xmark:{ .red } |
| [`omdb`](omdb.md) | :fontawesome-solid-circle-xmark:{ .red } | | [`omdb`](omdb.md) | :fontawesome-solid-circle-xmark:{ .red } |
| [`mdblist`](mdblist.md) | :fontawesome-solid-circle-xmark:{ .red } |
| [`notifiarr`](notifiarr.md) | :fontawesome-solid-circle-xmark:{ .red } | | [`notifiarr`](notifiarr.md) | :fontawesome-solid-circle-xmark:{ .red } |
| [`gotify`](gotify.md) | :fontawesome-solid-circle-xmark:{ .red } | | [`gotify`](gotify.md) | :fontawesome-solid-circle-xmark:{ .red } |
| [`anidb`](anidb.md) | :fontawesome-solid-circle-xmark:{ .red } | | [`anidb`](anidb.md) | :fontawesome-solid-circle-xmark:{ .red } |

@ -6,8 +6,7 @@ search:
## Overview ## Overview
The `settings:` attribute and subsequent settings can be used to command various aspects of the functionality of Plex The `settings:` attribute and subsequent settings can be used to command various aspects of the functionality of Kometa.
Meta Manager.
Examples of these settings include the ability to: Examples of these settings include the ability to:
@ -936,10 +935,34 @@ The available setting attributes which can be set at each level are outlined bel
- metadata - metadata
``` ```
??? blank "`verify_ssl` - Turn SSL Verification on or off.<a class="headerlink" href="#verify-ssl" title="Permanent link"></a>"
<div id="verify-ssl" />Turn SSL Verification on or off.
???+ note
set to false if your log file shows any errors similar to "SSL: CERTIFICATE_VERIFY_FAILED"
<hr style="margin: 0px;">
**Attribute:** `verify_ssl`
**Levels with this Attribute:** Global
**Accepted Values:** `true` or `false`
**Default Value:** `true`
???+ example "Example"
```yaml
settings:
verify_ssl: false
```
??? blank "`custom_repo` - Used to set up the custom `repo` [file block type](files.md#location-types-and-paths).<a class="headerlink" href="#custom-repo" title="Permanent link"></a>" ??? blank "`custom_repo` - Used to set up the custom `repo` [file block type](files.md#location-types-and-paths).<a class="headerlink" href="#custom-repo" title="Permanent link"></a>"
<div id="custom-repo" />Specify where the `repo` attribute's base is when defining `collection_files`, <div id="custom-repo" />Specify where the `repo` attribute's base is when defining `collection_files`, `metadata_files`, `playlist_file` and `overlay_files`.
`metadata_files`, `playlist_file` and `overlay_files`.
???+ note ???+ note
@ -963,29 +986,55 @@ The available setting attributes which can be set at each level are outlined bel
custom_repo: https://github.com/Kometa-Team/Community-Configs/tree/master/meisnate12 custom_repo: https://github.com/Kometa-Team/Community-Configs/tree/master/meisnate12
``` ```
??? blank "`verify_ssl` - Turn SSL Verification on or off.<a class="headerlink" href="#verify-ssl" title="Permanent link"></a>" ??? blank "`overlay_artwork_filetype` - Used to control the filetype used with overlay images.<a class="headerlink" href="#overlay-filetype" title="Permanent link"></a>"
<div id="verify-ssl" />Turn SSL Verification on or off. <div id="overlay-filetype" />Used to control the filetype used with overlay images. This setting will only be applied to images generated after the value is added to your config.
???+ note <hr style="margin: 0px;">
set to false if your log file shows any errors similar to "SSL: CERTIFICATE_VERIFY_FAILED" **Attribute:** `overlay_artwork_filetype`
**Levels with this Attribute:** Global/Library
**Accepted Values:**
<table class="clearTable">
<tr><td>`jpg`</td><td>Use JPG files for saving Overlays</td></tr>
<tr><td>`png`</td><td>Use PNG files for saving Overlays</td></tr>
<tr><td>`webp_lossy`</td><td>Use Lossy WEBP files for saving Overlays</td></tr>
<tr><td>`webp_lossless`</td><td>Use Lossless WEBP files for saving Overlays</td></tr>
</table>
**Default Value:** `jpg`
???+ example "Example"
```yaml
settings:
overlay_artwork_filetype: png
```
??? blank "`overlay_artwork_quality` - Used to control the JPG or Lossy WEBP quality used with overlay images.<a class="headerlink" href="#overlay-quality" title="Permanent link"></a>"
<div id="overlay-quality" />Used to control the JPG or Lossy WEBP quality used with overlay images. This setting
will only be applied to images generated after the value is added to your config.
<hr style="margin: 0px;"> <hr style="margin: 0px;">
**Attribute:** `verify_ssl` **Attribute:** `overlay_artwork_quality`
**Levels with this Attribute:** Global **Levels with this Attribute:** Global/Library
**Accepted Values:** `true` or `false` **Accepted Values:** Any Integer 1-100 [Values over 95 are not recommended and may result in excessive image size,
perhaps too large to be uploaded to Plex.
**Default Value:** `true` **Default Value:** `None` [when no value is provided the standard 75 is used]
???+ example "Example" ???+ example "Example"
```yaml ```yaml
settings: settings:
verify_ssl: false overlay_artwork_quality: 95
``` ```
## Default Values ## Default Values

@ -52,6 +52,6 @@ To connect to Trakt.tv you must create a Trakt application and supply Kometa the
## Online Authorization ## Online Authorization
{% {%
include-markdown "./auth.md" include-markdown "./authentication.md"
start="# Trakt and MyAnimeList Authentication" start="# Trakt and MyAnimeList Authentication"
%} %}

@ -1,6 +1,6 @@
# Award Separator Collections # Award Separator Collections
The `separator_award` Default Collection File is used to create a seperator collection for Awards. The `separator_award` Default Collection File is used to create a separator collection for Awards.
![](../images/awardseparator.png) ![](../images/awardseparator.png)

@ -11,33 +11,27 @@ Supported Library Types: Movie, Show
## Collections Section 030 ## Collections Section 030
!!! important | Collection | Key | Description |
|:---------------------------|:--------------|:-------------------------------------------------------------------------------|
As of Kometa release 1.21, the keys associated with this Defaults file has changed. | `Streaming Collections` | `separator` | [Separator Collection](../separators.md) to denote the Section of Collections. |
| `All 4 Movies/Shows` | `all4` | Collection of Movies/Shows Streaming on All 4. |
If you are setting custom images, you will need to use `<<originals_key>>` | `Apple TV+ Movies/Shows` | `appletv` | Collection of Movies/Shows Streaming on Apple TV+. |
| `BET+ Movies/Shows` | `bet` | Collection of Movies/Shows Streaming on BET+. |
| Collection | Key | `originals_key` | Description | | `BritBox Movies/Shows` | `britbox` | Collection of Movies/Shows Streaming on BritBox. |
|:---------------------------|---------------|:-----------------|:-------------------------------------------------------------------------------| | `Crave Movies/Shows` | `crave` | Collection of Movies/Shows Streaming on Crave. |
| `Streaming Collections` | `separator` | `separator` | [Separator Collection](../separators.md) to denote the Section of Collections. | | `Crunchyroll Shows` | `crunchyroll` | Collection of Shows Streaming on Crunchyroll. |
| `All 4 Movies/Shows` | `103` | `all4` | Collection of Movies/Shows Streaming on All 4. | | `discovery+ Shows` | `discovery` | Collection of Shows Streaming on discovery+. |
| `Apple TV+ Movies/Shows` | `350` | `appletv` | Collection of Movies/Shows Streaming on Apple TV+. | | `Disney+ Movies/Shows` | `disney` | Collection of Movies/Shows Streaming on Disney+. |
| `BET+ Movies/Shows` | `1759` | `bet` | Collection of Movies/Shows Streaming on BET+. | | `Max Movies/Shows` | `max` | Collection of Movies/Shows Streaming on Max. |
| `BritBox Movies/Shows` | `151` | `britbox` | Collection of Movies/Shows Streaming on BritBox. | | `Hayu Shows` | `hayu` | Collection of Shows Streaming on Hulu. |
| `Crave Movies/Shows` | `230` | `crave` | Collection of Movies/Shows Streaming on Crave. | | `Hulu Movies/Shows` | `hulu` | Collection of Movies/Shows Streaming on Hulu. |
| `Crunchyroll Shows` | `283` | `crunchyroll` | Collection of Shows Streaming on Crunchyroll. | | `Netflix Movies/Shows` | `netflix` | Collection of Movies/Shows Streaming on Netflix. |
| `discovery+ Shows` | `510` | `discovery` | Collection of Shows Streaming on discovery+. | | `NOW Movies/Shows` | `now` | Collection of Movies/Shows Streaming on NOW. |
| `Disney+ Movies/Shows` | `337` | `disney` | Collection of Movies/Shows Streaming on Disney+. | | `Paramount+ Movies/Shows` | `paramount` | Collection of Movies/Shows Streaming on Paramount+. |
| `Max Movies/Shows` | `1189` | `max` | Collection of Movies/Shows Streaming on Max. | | `Peacock Movies/Shows` | `peacock` | Collection of Movies/Shows Streaming on Peacock. |
| `Hayu Shows` | `223` | `hayu` | Collection of Shows Streaming on Hulu. | | `Prime Video Movies/Shows` | `amazon` | Collection of Movies/Shows Streaming on Prime Video. |
| `Hulu Movies/Shows` | `15` | `hulu` | Collection of Movies/Shows Streaming on Hulu. | | `Showtime Movies/Shows` | `showtime` | Collection of Movies/Shows Streaming on Showtime. |
| `Netflix Movies/Shows` | `8` | `netflix` | Collection of Movies/Shows Streaming on Netflix. | | `YouTube Movies/Shows` | `youtube` | Collection of Movies/Shows Streaming on YouTube. |
| `NOW Movies/Shows` | `39` | `now` | Collection of Movies/Shows Streaming on NOW. |
| `Paramount+ Movies/Shows` | `531` | `paramount` | Collection of Movies/Shows Streaming on Paramount+. |
| `Peacock Movies/Shows` | `387` | `peacock` | Collection of Movies/Shows Streaming on Peacock. |
| `Prime Video Movies/Shows` | `9` | `amazon` | Collection of Movies/Shows Streaming on Prime Video. |
| `Showtime Movies/Shows` | `37` | `showtime` | Collection of Movies/Shows Streaming on Showtime. |
| `YouTube Movies/Shows` | `188` | `youtube` | Collection of Movies/Shows Streaming on YouTube. |
## Regional Variants ## Regional Variants

@ -53,6 +53,7 @@ work. Any value not specified will use its default value if it has one if not it
| `limit` | **Description:** Changes the Builder Limit for all collections in a Defaults file.<br>**Default:** `100`<br>**Values:** Number greater than 0 | | `limit` | **Description:** Changes the Builder Limit for all collections in a Defaults file.<br>**Default:** `100`<br>**Values:** Number greater than 0 |
| `limit_<<key>>`<sup>1</sup> | **Description:** Changes the Builder Limit of the specified key's collection.<br>**Default:** `limit`<br>**Values:** Number greater than 0 | | `limit_<<key>>`<sup>1</sup> | **Description:** Changes the Builder Limit of the specified key's collection.<br>**Default:** `limit`<br>**Values:** Number greater than 0 |
| `sync_mode` | **Description:** Changes the Sync Mode for all collections in a Defaults file.<br>**Default:** `sync`<br>**Values:**<table class="clearTable"><tr><td>`sync`</td><td>Add and Remove Items based on Builders</td></tr><tr><td>`append`</td><td>Only Add Items based on Builders</td></tr></table> | | `sync_mode` | **Description:** Changes the Sync Mode for all collections in a Defaults file.<br>**Default:** `sync`<br>**Values:**<table class="clearTable"><tr><td>`sync`</td><td>Add and Remove Items based on Builders</td></tr><tr><td>`append`</td><td>Only Add Items based on Builders</td></tr></table> |
| `starting_only` | **Description:** Changes the season collection to only use anime listed under the new section on [MAL Seasons](https://myanimelist.net/anime/season/)<br>**Default:** `False`<br>**Values:** `True` or `False` |
| `sync_mode_<<key>>`<sup>1</sup> | **Description:** Changes the Sync Mode of the specified key's collection.<br>**Default:** `sync_mode`<br>**Values:**<table class="clearTable"><tr><td>`sync`</td><td>Add and Remove Items based on Builders</td></tr><tr><td>`append`</td><td>Only Add Items based on Builders</td></tr></table> | | `sync_mode_<<key>>`<sup>1</sup> | **Description:** Changes the Sync Mode of the specified key's collection.<br>**Default:** `sync_mode`<br>**Values:**<table class="clearTable"><tr><td>`sync`</td><td>Add and Remove Items based on Builders</td></tr><tr><td>`append`</td><td>Only Add Items based on Builders</td></tr></table> |
| `collection_order` | **Description:** Changes the Collection Order for all collections in a Defaults file.<br>**Default:** `custom`<br>**Values:**<table class="clearTable"><tr><td>`release`</td><td>Order Collection by Release Dates</td></tr><tr><td>`alpha`</td><td>Order Collection Alphabetically</td></tr><tr><td>`custom`</td><td>Order Collection Via the Builder Order</td></tr><tr><td>[Any `plex_search` Sort Option](../../files/builders/plex.md#sort-options)</td><td>Order Collection by any `plex_search` Sort Option</td></tr></table> | | `collection_order` | **Description:** Changes the Collection Order for all collections in a Defaults file.<br>**Default:** `custom`<br>**Values:**<table class="clearTable"><tr><td>`release`</td><td>Order Collection by Release Dates</td></tr><tr><td>`alpha`</td><td>Order Collection Alphabetically</td></tr><tr><td>`custom`</td><td>Order Collection Via the Builder Order</td></tr><tr><td>[Any `plex_search` Sort Option](../../files/builders/plex.md#sort-options)</td><td>Order Collection by any `plex_search` Sort Option</td></tr></table> |
| `collection_order_<<key>>`<sup>1</sup> | **Description:** Changes the Collection Order of the specified key's collection.<br>**Default:** `collection_order`<br>**Values:**<table class="clearTable"><tr><td>`release`</td><td>Order Collection by Release Dates</td></tr><tr><td>`alpha`</td><td>Order Collection Alphabetically</td></tr><tr><td>`custom`</td><td>Order Collection Via the Builder Order</td></tr><tr><td>[Any `plex_search` Sort Option](../../files/builders/plex.md#sort-options)</td><td>Order Collection by any `plex_search` Sort Option</td></tr></table> | | `collection_order_<<key>>`<sup>1</sup> | **Description:** Changes the Collection Order of the specified key's collection.<br>**Default:** `collection_order`<br>**Values:**<table class="clearTable"><tr><td>`release`</td><td>Order Collection by Release Dates</td></tr><tr><td>`alpha`</td><td>Order Collection Alphabetically</td></tr><tr><td>`custom`</td><td>Order Collection Via the Builder Order</td></tr><tr><td>[Any `plex_search` Sort Option](../../files/builders/plex.md#sort-options)</td><td>Order Collection by any `plex_search` Sort Option</td></tr></table> |

@ -1,6 +1,6 @@
# Chart Separator Collections # Chart Separator Collections
The `separator_chart` Default Collection File is used to create a seperator collection for Charts. The `separator_chart` Default Collection File is used to create a separator collection for Charts.
![](../images/chartseparator.png) ![](../images/chartseparator.png)

@ -1,7 +1,9 @@
File paths need to be valid in the context where Kometa is running; this is primarily an issue when running in docker, as Kometa inside the container cannot see host paths.
| Variable | Description & Values | | Variable | Description & Values |
|:----------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |:----------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `language` | **Description:** Set the language of Collection Names and Summaries<br>**Default:** `default`<br>**Values:** `default` (English), `fr` (French), or `de` (German) | | `language` | **Description:** Set the language of Collection Names and Summaries<br>**Default:** `default`<br>**Values:** `default` (English), `fr` (French), or `de` (German) |
| `use_all` | **Description:** Turns off all Collections in a Defaults file.<br>**Values:** `false` to turn off the collection |
| `use_<<key>>`<sup>1</sup> | **Description:** Turns off individual Collections in a Defaults file.<br>**Values:** `false` to turn off the collection | | `use_<<key>>`<sup>1</sup> | **Description:** Turns off individual Collections in a Defaults file.<br>**Values:** `false` to turn off the collection |
| `name_<<key>>`<sup>1</sup> | **Description:** Changes the name of the specified key's collection.<br>**Values:** New Collection Name | | `name_<<key>>`<sup>1</sup> | **Description:** Changes the name of the specified key's collection.<br>**Values:** New Collection Name |
| `summary_<<key>>`<sup>1</sup> | **Description:** Changes the summary of the specified key's collection.<br>**Values:** New Collection Summary | | `summary_<<key>>`<sup>1</sup> | **Description:** Changes the summary of the specified key's collection.<br>**Values:** New Collection Summary |

@ -47,7 +47,9 @@
- default: universe # Marvel Cinematic Universe, Wizarding World, etc. - default: universe # Marvel Cinematic Universe, Wizarding World, etc.
remove_overlays: false # Set to true if you want to remove overlays remove_overlays: false # Set to true if you want to remove overlays
reapply_overlays: false # If you are doing a lot of testing and changes like me, keep this to true to always reapply overlays - can cause image bloat reapply_overlays: false # Set to true if you want to force-reapply overlays to everything
# THERE IS RARELY IF EVER A REASON TO DO THIS AS IT WILL EXTEND RUN TIMES ANS CAUSE IMAGE BLOAT
# IF YOU THINK YOU WANT TO DO THIS YOU ARE ALMOST CERTAINLY MISTAKEN
#reset_overlays: tmdb # if you want to reset the poster to default poster from tmdb - can cause image bloat #reset_overlays: tmdb # if you want to reset the poster to default poster from tmdb - can cause image bloat
overlay_files: overlay_files:

@ -17,17 +17,9 @@ Special thanks to Magic815 for the overlay image inspiration and base template.
Please consider [donating](https://github.com/sponsors/meisnate12) towards the project. Please consider [donating](https://github.com/sponsors/meisnate12) towards the project.
## Collection Defaults
See the [Collection Defaults](collections.md) Page for more information on the specifics of the Collection Defaults.
## Overlay Defaults
See the [Overlay Defaults](overlays.md) Page for more information on the specifics of the Overlay Defaults.
## Configurations ## Configurations
To run a default KometCollection or Overlay file you can simply add it to your `collection_files` (For Collection Files) To run a default Kometa Collection or Overlay file you can simply add it to your `collection_files` (For Collection Files)
or `overlay_files` (For Overlay Files) using `default` like so: or `overlay_files` (For Overlay Files) using `default` like so:
```yaml ```yaml
@ -41,16 +33,60 @@ libraries:
- default: ratings - default: ratings
``` ```
## Customizing Configs ## Customizing these defaults
Configs can be customized using the `template_variables` attribute when calling the file.
These template variables can be used to customize individual collections/overlays or the set as a whole.
A given default may have variables that are specific to it, and may also leverage a common set of shared template variables. These lists are shown on each default file's wiki page.
## Customizing individual components
Configs can be customized using the `template_variables` attribute when calling the file. These `template_variables` Each default file uses "keys" to refer to the collections and overlays that it creates, and you can use those keys to modify the behavior of individual collections or overlays created by the file.
will be given to every template call in the file which allows them to affect how that file runs.
For collections, this example disables two keys, which will prevent those collections from being created. It also sets For, example, the IMDB default creates three collections, each with their own "key":
the visibility of one of the keys so that it is visible on the library tab, the server owner's homescreen and shared
user's homescreens (assuming they server owner and/or the shared users have the library pinned to their homescreen)
For overlays, this example changes the ratings overlay to apply to episodes rather than shows. | Collection | Key |
|:--------------------|:----------|
| `IMDb Popular` | `popular` |
| `IMDb Top 250` | `top` |
| `IMDb Lowest Rated` | `lowest` |
You use that key to customize the individual collection or overlay.
This example disables two keys, which will prevent those collections from being created. It also sets
the visibility of one of the keys [`top`] so that it is visible on the library tab, the server owner's homescreen and shared
user's homescreens (assuming the server owner and/or the shared users have the library pinned to their homescreen)
It also changes the resolution overlay to skip applying the overlay to 480p movies.
The template variables in this example happen to be all shared template variables.
```yaml
libraries:
Movies:
collection_files:
- default: imdb
template_variables:
use_popular: false # turn off the 'popular' key
use_lowest: false # turn off the 'lowest' key
visible_library_top: true # set visibilities for the 'top' key
visible_home_top: true
visible_shared_top: true
overlay_files:
- default: resolution
template_variables:
use_480p: false # turn off the '480p' key
```
## Customizing the set as a whole
In addition to the keys, each default can be customized with other template variables that are not key-specific.
This example uses a file-specific variable to change the order of all the IMDB chart collections to alphabetical by title and a shared variable to schedule these IMDB collections to be run only on Wednesdays.
On the `resolution` overlay, it uses a file-specific variable to disable all the "edition" overlays and a shared variable to align the overlay on the right side of the poster.
```yaml ```yaml
libraries: libraries:
@ -63,17 +99,33 @@ libraries:
visible_library_top: true visible_library_top: true
visible_home_top: true visible_home_top: true
visible_shared_top: true visible_shared_top: true
collection_order: alpha # file-specific variable sets sort order
schedule: weekly(wednesday) # shared variable sets schedule
overlay_files: overlay_files:
- default: ratings - default: ribbon
template_variables: template_variables:
builder_level: episode use_480p: false
use_edition: false # file-specific variable hides editions
horizontal_align: right # shared variable sets alignment
``` ```
Each file has a page on the wiki showing the available `template_variables` for each file. For example the default All of the default files are customized in this basic fashion.
`default: ratings` has a page [here](overlays/ratings.md).
**NOTE: this `template_variable` system is specific to the defaults. If and when you start creating your own [collection](../files/collections.md) or [overlay](../files/overlays.md) files, you cannot use this `template_variables` setup unless you specifically write your files to implement it.**
Each of these default files has a page on the wiki showing its keys, available `template_variables`, and default settings. For example, the default overlay `default: resolution` has a page [here](overlays/resolution.md).
The shared template variables can be reviewed here for [Collections](collection_variables.md) and [Overlays](overlay_variables.md). These are also linked from each default file's wiki page. Keep in mind that *most*, but not all default files have access to the shared variables. This will be noted on the individual files' page.
## Collection Defaults
See the [Collection Defaults](collections.md) Page for more information on the specifics of the Collection Defaults.
## Overlay Defaults
See the [Overlay Defaults](overlays.md) Page for more information on the specifics of the Overlay Defaults.
**In addition to the defined `template_variables` almost all default Collection and Overlay files have access to their # Example config using the defaults
respective [Collection](collection_variables.md)/[Overlay](overlay_variables.md) Shared Variables.**
{% {%
include-markdown "./example.md" include-markdown "./example.md"

@ -66,11 +66,11 @@ work. Any value not specified will use its default value if it has one if not it
| Variable | Description & Values | | Variable | Description & Values |
|:--------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |:--------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `tmdb_collection_<<key>>`<sup>1</sup> | **Description:** Adds the TMDb Collection IDs given to the specified key's collection. Overrides the [default tmdb_collection](#tmdb-collection) for that collection if used.<br>**Values:** List of TMDb Collection IDs | | `tmdb_collection_<<key>>`<sup>1</sup> | **Description:** Adds the TMDb Collection IDs given to the specified key's collection. Overrides the [default tmdb_collection](#tmdb-collection) for that collection if used.<br>**Values:** List of TMDb Collection IDs |
| `tmdb_movie_<<key>>`<sup>1</sup> | **Description:** Adds the TMDb Movie IDs given to the specified key's collection. Overrides the [default tmdb_movie](#tmdb-movie) for that collection if used.<br>**Values:** List of TMDb Movie IDs | | | `tmdb_movie_<<key>>`<sup>1</sup> | **Description:** Adds the TMDb Movie IDs given to the specified key's collection. Overrides the [default tmdb_movie](#tmdb-movie) for that collection if used.<br>**Values:** List of TMDb Movie IDs |
| `imdb_list_<<key>>`<sup>1</sup> | **Description:** Adds the Movies in the IMDb List to the specified key's collection. Overrides the [default imdb_list](#imdb-list) for that collection if used.<br>**Values:** List of IMDb List URLs | | | | `imdb_list_<<key>>`<sup>1</sup> | **Description:** Adds the Movies in the IMDb List to the specified key's collection.<br>**Values:** List of IMDb List URLs |
| `imdb_search_<<key>>`<sup>1</sup> | **Description:** Adds the Movies in the IMDb Search to the specified key's collection. Overrides the [default imdb_search](#imdb-search) for that collection if used.<br>**Values:** List of IMDb List URLs | | | | `imdb_search_<<key>>`<sup>1</sup> | **Description:** Adds the Movies in the IMDb Search to the specified key's collection. Overrides the [default imdb_search](#imdb-search) for that collection if used.<br>**Values:** List of IMDb List URLs |
| `trakt_list_<<key>>`<sup>1</sup> | **Description:** Adds the Movies in the Trakt List to the specified key's collection. Overrides the [default trakt_list](#trakt-list) for that collection if used.<br>**Values:** List of Trakt List URLs | | | | | `trakt_list_<<key>>`<sup>1</sup> | **Description:** Adds the Movies in the Trakt List to the specified key's collection. Overrides the [default trakt_list](#trakt-list) for that collection if used.<br>**Values:** List of Trakt List URLs |
| `mdblist_list_<<key>>`<sup>1</sup> | **Description:** Adds the Movies in the MDb List to the specified key's collection. Overrides the [default mdblist_list](#mdblist-list) for that collection if used.<br>**Values:** List of MDbList URLs | | | | | `mdblist_list_<<key>>`<sup>1</sup> | **Description:** Adds the Movies in the MDb List to the specified key's collection. Overrides the [default mdblist_list](#mdblist-list) for that collection if used.<br>**Values:** List of MDBList URLs |
| `emoji` | **Description:** Controls the Emoji Prefix for all Collections. Set to `""` to remove all emojis.<br>**Values:** Any String | | `emoji` | **Description:** Controls the Emoji Prefix for all Collections. Set to `""` to remove all emojis.<br>**Values:** Any String |
| `emoji_<<key>>`<sup>1</sup> | **Description:** Controls the Emoji Prefix for the specified key's collection. Overrides the [default emoji](#emoji) for that collection if used.<br>**Values:** Any String | | `emoji_<<key>>`<sup>1</sup> | **Description:** Controls the Emoji Prefix for the specified key's collection. Overrides the [default emoji](#emoji) for that collection if used.<br>**Values:** Any String |
| `limit` | **Description:** Changes the Builder Limit for all collections in this file.<br>**Values:** Number Greater than 0 | | `limit` | **Description:** Changes the Builder Limit for all collections in this file.<br>**Values:** Number Greater than 0 |
@ -193,25 +193,6 @@ If you want to customize these values, use the methods described above.
%} %}
``` ```
??? example "Default Template Variable `imdb_list` (click to expand) <a class="headerlink" href="#imdb-list" title="Permanent link"></a>"
<div id="imdb-list" />
???+ tip
Pass `imdb_list_<<key>>` to the file as template variables to change this value per collection.
```yaml
{%
include-markdown "../../../defaults/movie/seasonal.yml"
comments=false
preserve-includer-indent=true
dedent=true
start="# check3"
end="# check4"
%}
```
??? example "Default Template Variable `imdb_search` (click to expand) <a class="headerlink" href="#imdb-search" title="Permanent link"></a>" ??? example "Default Template Variable `imdb_search` (click to expand) <a class="headerlink" href="#imdb-search" title="Permanent link"></a>"
<div id="imdb-search" /> <div id="imdb-search" />

@ -1,15 +1,20 @@
When something in this table is noted as expecting a number, typically that number is expressed in pixels, assuming an image 1000x1500 in size.
Color values should be wrapped in quotes in the YAML, as the `#` denotes a comment in YAML and if left unquoted will prevent the value from being seen by Kometa.
File paths need to be valid in the context where Kometa is running; this is primarily an issue when running in docker, as Kometa inside the container cannot see host paths.
| Variable | Description & Values | | Variable | Description & Values |
|:-----------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |:-----------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `font` | **Description:** Choose the font for the Overlay.<br>**Default:** `fonts/Inter-Medium.ttf`<br>**Values:** Path to font file | | `font` | **Description:** Choose the font for the Overlay.<br>**Default:** `fonts/Inter-Medium.ttf`<br>**Values:** Path to font file |
| `font_style` | **Description:** Font style for Variable Fonts.<br>**Values:** Variable Font Style | | `font_style` | **Description:** Font style for Variable Fonts.<br>**Values:** Variable Font Style |
| `font_size` | **Description:** Choose the font size for the Overlay.<br>**Default:** `55`<br>**Values:** Any number greater than 0 | | `font_size` | **Description:** Choose the font size for the Overlay.<br>**Default:** `55`<br>**Values:** Any number greater than 0 [pixels assuming a 1000x1500 image] |
| `font_color` | **Description:** Choose the font color for the Overlay.<br>**Default:** `#FFFFFF`<br>**Values:** Color Hex Code in format `#RGB`, `#RGBA`, `#RRGGBB` or `#RRGGBBAA` | | `font_color` | **Description:** Choose the font color for the Overlay.<br>**Default:** `#FFFFFF`<br>**Values:** Color Hex Code in format `#RGB`, `#RGBA`, `#RRGGBB` or `#RRGGBBAA` |
| `stroke_width` | **Description:** Font Stroke Width for the Overlay.<br>**Values:** Any number greater than 0 | | `stroke_width` | **Description:** Font Stroke Width for the Overlay.<br>**Values:** Any number greater than 0 [pixels assuming a 1000x1500 image] |
| `stroke_color` | **Description:** Font Stroke Color for the Overlay.<br>**Values:** Color Hex Code in format `#RGB`, `#RGBA`, `#RRGGBB` or `#RRGGBBAA` | | `stroke_color` | **Description:** Font Stroke Color for the Overlay.<br>**Values:** Color Hex Code in format `#RGB`, `#RGBA`, `#RRGGBB` or `#RRGGBBAA` |
| `font_<<key>>` | **Description:** Choose the font for this key's Overlay.<br>**Default:** `fonts/Inter-Medium.ttf`<br>**Values:** Path to font file | | `font_<<key>>` | **Description:** Choose the font for this key's Overlay.<br>**Default:** `fonts/Inter-Medium.ttf`<br>**Values:** Path to font file |
| `font_style_<<key>>` | **Description:** Font style for this key's Variable Fonts.<br>**Values:** Variable Font Style | | `font_style_<<key>>` | **Description:** Font style for this key's Variable Fonts.<br>**Values:** Variable Font Style |
| `font_size_<<key>>` | **Description:** Choose the font size for this key's Overlay.<br>**Default:** `55`<br>**Values:** Any number greater than 0 | | `font_size_<<key>>` | **Description:** Choose the font size for this key's Overlay.<br>**Default:** `55`<br>**Values:** Any number greater than 0 [pixels assuming a 1000x1500 image] |
| `font_color_<<key>>` | **Description:** Choose the font color for this key's Overlay.<br>**Default:** `#FFFFFF`<br>**Values:** Color Hex Code in format `#RGB`, `#RGBA`, `#RRGGBB` or `#RRGGBBAA` | | `font_color_<<key>>` | **Description:** Choose the font color for this key's Overlay.<br>**Default:** `#FFFFFF`<br>**Values:** Color Hex Code in format `#RGB`, `#RGBA`, `#RRGGBB` or `#RRGGBBAA` |
| `stroke_width_<<key>>` | **Description:** Font Stroke Width for this key's Overlay.<br>**Values:** Any number greater than 0 | | `stroke_width_<<key>>` | **Description:** Font Stroke Width for this key's Overlay.<br>**Values:** Any number greater than 0 [pixels assuming a 1000x1500 image] |
| `stroke_color_<<key>>` | **Description:** Font Stroke Color for this key's Overlay.<br>**Values:** Color Hex Code in format `#RGB`, `#RGBA`, `#RRGGBB` or `#RRGGBBAA` | | `stroke_color_<<key>>` | **Description:** Font Stroke Color for this key's Overlay.<br>**Values:** Color Hex Code in format `#RGB`, `#RGBA`, `#RRGGBB` or `#RRGGBBAA` |

@ -1,3 +1,33 @@
When something in this table is noted as expecting a number, that number is expressed in pixels, assuming an image 1000x1500 in size. If the number is an `offset`, the value is relative to the corresponding `alignment`. Percentages are also relative to the `alignment`.
For example:
```yaml
libraries:
Movies:
overlay_files:
- default: resolution
template_variables:
horizontal_align: left
horizontal_offset: 247
vertical_align: bottom
vertical_offset: 40%
```
That would place the resolution overlay 247 pixels in from the left edge of the poster, and 40% of the way up from the bottom.
```yaml
libraries:
Movies:
overlay_files:
- default: resolution
template_variables:
back_width: 198
back_height: 47
```
That would set the resolution overlay background to 198 pixels wide by 47 pixels high.
Color values should be wrapped in quotes in the YAML, as the `#` denotes a comment in YAML and if left unquoted will prevent the value from being seen by Kometa.
File paths need to be valid in the context where Kometa is running; this is primarily an issue when running in docker, as Kometa inside the container cannot see host paths.
| Variable | Description & Values | | Variable | Description & Values |
|:---------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |:---------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
@ -10,18 +40,18 @@
| `git_<<key>>`<sup>1</sup> | **Description:** Controls the image associated with this key's Overlay to the git repo.<br>**Values:** Git Path to Overlay Image | | `git_<<key>>`<sup>1</sup> | **Description:** Controls the image associated with this key's Overlay to the git repo.<br>**Values:** Git Path to Overlay Image |
| `repo` | **Description:** Controls the images associated with all the Overlays to a custom repo.<br>**Values:** Repo Path to Overlay Image | | `repo` | **Description:** Controls the images associated with all the Overlays to a custom repo.<br>**Values:** Repo Path to Overlay Image |
| `repo_<<key>>`<sup>1</sup> | **Description:** Controls the image associated with this key's Overlay to a custom repo.<br>**Values:** Repo Path to Overlay Image | | `repo_<<key>>`<sup>1</sup> | **Description:** Controls the image associated with this key's Overlay to a custom repo.<br>**Values:** Repo Path to Overlay Image |
| `horizontal_offset` | **Description:** Controls the Horizontal Offset of this overlay. Can be a %.<br>**Values:** Number 0 or greater or 0%-100% | | `horizontal_offset` | **Description:** Controls the Horizontal Offset of this overlay. Can be a %.<br>**Values:** Number 0 or greater or 0%-100% [pixels assuming a 1000x1500 image] |
| `horizontal_align` | **Description:** Controls the Horizontal Alignment of the overlay.<br>**Values:** `left`, `center`, or `right` | | `horizontal_align` | **Description:** Controls the Horizontal Alignment of the overlay.<br>**Values:** `left`, `center`, or `right` |
| `vertical_offset` | **Description:** Controls the Vertical Offset of this overlay. Can be a %.<br>**Values:** Number 0 or greater or 0%-100% | | `vertical_offset` | **Description:** Controls the Vertical Offset of this overlay. Can be a %.<br>**Values:** Number 0 or greater or 0%-100% [pixels assuming a 1000x1500 image] |
| `vertical_align` | **Description:** Controls the Vertical Alignment of the overlay.<br>**Values:** `top`, `center`, or `bottom` | | `vertical_align` | **Description:** Controls the Vertical Alignment of the overlay.<br>**Values:** `top`, `center`, or `bottom` |
| `back_color` | **Description:** Controls the Backdrop Color for the Text Overlay.<br>**Values:** Color Hex Code in format `#RGB`, `#RGBA`, `#RRGGBB` or `#RRGGBBAA`<br>`AA` is transparency; 00 [transparent] to FF [opaque] | | `back_color` | **Description:** Controls the Backdrop Color for the Text Overlay.<br>**Values:** Color Hex Code in format `#RGB`, `#RGBA`, `#RRGGBB` or `#RRGGBBAA`<br>`AA` is transparency; 00 [transparent] to FF [opaque] |
| `back_width` | **Description:** Controls the Backdrop Width for the Text Overlay. If `back_width` is not specified the Backdrop Sizes to the text<br>**Values:** Any number greater than 0 | | `back_width` | **Description:** Controls the Backdrop Width for the Text Overlay. If `back_width` is not specified the Backdrop Sizes to the text<br>**Values:** Any number greater than 0 [pixels assuming a 1000x1500 image] |
| `back_height` | **Description:** Controls the Backdrop Height for the Text Overlay. If `back_height` is not specified the Backdrop Sizes to the text<br>**Values:** Any number greater than 0 | | `back_height` | **Description:** Controls the Backdrop Height for the Text Overlay. If `back_height` is not specified the Backdrop Sizes to the text<br>**Values:** Any number greater than 0 [pixels assuming a 1000x1500 image] |
| `back_align` | **Description:** Controls the Alignment for the Text Overlay inside the backdrop. If `back_align` is not specified the Backdrop Centers the text.<br>**Values:** `left`, `right`, `center`, `top`, or `bottom` | | `back_align` | **Description:** Controls the Alignment for the Text Overlay inside the backdrop. If `back_align` is not specified the Backdrop Centers the text.<br>**Values:** `left`, `right`, `center`, `top`, or `bottom` |
| `back_padding` | **Description:** Controls the Backdrop Padding for the Text Overlay.<br>**Values:** Any number greater than 0 | | `back_padding` | **Description:** Controls the Backdrop Padding for the Text Overlay.<br>**Values:** Any number greater than 0 [pixels assuming a 1000x1500 image] |
| `back_radius` | **Description:** Controls the Backdrop Radius for the Text Overlay.<br>**Values:** Any number greater than 0 | | `back_radius` | **Description:** Controls the Backdrop Radius for the Text Overlay.<br>**Values:** Any number greater than 0 [pixels assuming a 1000x1500 image] |
| `back_line_color` | **Description:** Controls the Backdrop Line Color for the Text Overlay.<br>**Values:** Color Hex Code in format `#RGB`, `#RGBA`, `#RRGGBB` or `#RRGGBBAA``AA` is transparency; 00 [transparent] to FF [opaque] | | `back_line_color` | **Description:** Controls the Backdrop Line Color for the Text Overlay.<br>**Values:** Color Hex Code in format `#RGB`, `#RGBA`, `#RRGGBB` or `#RRGGBBAA``AA` is transparency; 00 [transparent] to FF [opaque] |
| `back_line_width` | **Description:** Controls the Backdrop Line Width for the Text Overlay.<br>**Values:** Any number greater than 0 | | `back_line_width` | **Description:** Controls the Backdrop Line Width for the Text Overlay.<br>**Values:** Any number greater than 0 [pixels assuming a 1000x1500 image] |
1. Each default overlay has a `key` that when calling to effect a specific collection you must replace `<<key>>` with 1. Each default overlay has a `key` that when calling to effect a specific collection you must replace `<<key>>` with
when calling. when calling.

@ -23,14 +23,14 @@ libraries:
### Example Poster Overlays ### Example Poster Overlays
**Note: These examples use fonts not packaged with Kometa. See [bullmoose20's Configs](https://github.com/Kometa-Team/Community-Configs/tree/master/bullmoose20)**
![](images/movie-overlays1-annotated.png) ![](images/movie-overlays1-annotated.png)
![](images/movie-overlays2-annotated.png) ![](images/movie-overlays2-annotated.png)
<details> <details>
<summary>Click to expand sample config.yml Movies overlays section:</summary> <summary>Click to expand sample config.yml Movies overlays section:</summary>
**Note: This uses fonts not packaged with Kometa. See [bullmoose20's Configs](https://github.com/Kometa-Team/Community-Configs/tree/master/bullmoose20)**
```yaml ```yaml
libraries: libraries:
Movies: Movies:
@ -74,8 +74,6 @@ libraries:
<details> <details>
<summary>Click to expand sample config.yml TV Shows overlays section for the Show Poster:</summary> <summary>Click to expand sample config.yml TV Shows overlays section for the Show Poster:</summary>
**Note: This uses fonts not packaged with Kometa. See [bullmoose20's Configs](https://github.com/Kometa-Team/Community-Configs/tree/master/bullmoose20)**
```yaml ```yaml
libraries: libraries:
TV Shows: TV Shows:
@ -141,8 +139,6 @@ libraries:
<details> <details>
<summary>Click to expand sample config.yml TV Shows overlays section for the Episode Poster:</summary> <summary>Click to expand sample config.yml TV Shows overlays section for the Episode Poster:</summary>
**Note: This uses fonts not packaged with Kometa. See [bullmoose20's Configs](https://github.com/Kometa-Team/Community-Configs/tree/master/bullmoose20)**
```yaml ```yaml
libraries: libraries:
TV Shows: TV Shows:
@ -239,6 +235,10 @@ Each file has a page on the wiki showing the available `template_variables` for
**In addition to the defined `template_variables` almost all default Overlay files have access to the **In addition to the defined `template_variables` almost all default Overlay files have access to the
[Shared Variables](collection_variables.md).** [Shared Variables](collection_variables.md).**
### Custom fonts used in these examples:
See [bullmoose20's Configs](https://github.com/Kometa-Team/Community-Configs/tree/master/bullmoose20)
### Examples ### Examples
{% {%

@ -3,6 +3,8 @@
The `status` Default Overlay File is used to create an overlay on a show detailing its Current Airing Status for all The `status` Default Overlay File is used to create an overlay on a show detailing its Current Airing Status for all
shows in your library. shows in your library.
Show status is sourced from TMDB.
![](images/status.png) ![](images/status.png)
## Requirements & Recommendations ## Requirements & Recommendations

@ -11,33 +11,26 @@ Supported Overlay Level: Movie, Show
## Supported Streaming Services ## Supported Streaming Services
| Streaming Service | Key | Weight |
!!! important |:------------------|:--------------|:-------|
| Netflix | `netflix` | `160` |
As of Kometa release 1.21, the keys associated with this Defaults file has changed. | Prime Video | `amazon` | `150` |
| Disney+ | `disney` | `140` |
If you are setting custom images, you will need to use `<<originals_key>>` | Max | `max` | `130` |
| Crunchyroll | `Crunchyroll` | `120` |
| Streaming Service | Key | `originals_key` | Weight | | YouTube | `youtube` | `110` |
|:------------------|--------|:----------------|:-------| | Hulu | `hulu` | `100` |
| Netflix | `8` | `netflix` | `160` | | Paramount+ | `paramount` | `90` |
| Prime Video | `9` | `amazon` | `150` | | AppleTV | `appletv` | `80` |
| Disney+ | `337` | `disney` | `140` | | Peacock | `peacock` | `70` |
| Max | `1189` | `max` | `130` | | Showtime | `showtime` | `60` |
| Crunchyroll | `283` | `Crunchyroll` | `120` | | discovery+ | `discovery` | `58` |
| YouTube | `188` | `youtube` | `110` | | Crave | `crave` | `55` |
| Hulu | `15` | `hulu` | `100` | | NOW | `now` | `50` |
| Paramount+ | `531` | `paramount` | `90` | | All 4 | `all4` | `40` |
| AppleTV | `350` | `appletv` | `80` | | britbox | `britbox` | `30` |
| Peacock | `387` | `peacock` | `70` | | BET+ | `bet` | `20` |
| Showtime | `37` | `showtime` | `60` | | hayu | `hayu` | `10` |
| discovery+ | `510` | `discovery` | `58` |
| Crave | `230` | `crave` | `55` |
| NOW | `39` | `now` | `50` |
| All 4 | `103` | `all4` | `40` |
| britbox | `151` | `britbox` | `30` |
| BET+ | `1759` | `bet` | `20` |
| hayu | `223` | `hayu` | `10` |
## Regional Variants ## Regional Variants

@ -62,7 +62,7 @@ Radarr/Sonarr.
When `radarr_add_existing`/`sonarr_add_existing` are true the items that exist in the collection/playlist will be added When `radarr_add_existing`/`sonarr_add_existing` are true the items that exist in the collection/playlist will be added
to Radarr/Sonarr. to Radarr/Sonarr.
If your Radarr/Sonarr has different file system mappings from your plex use `radarr_path`/`sonarr_path` along with If your Radarr/Sonarr has different file system mappings from your Plex use `radarr_path`/`sonarr_path` along with
`plex_path` from your [Radarr](../config/radarr.md)/[Sonarr](../config/sonarr.md) global config settings. `plex_path` from your [Radarr](../config/radarr.md)/[Sonarr](../config/sonarr.md) global config settings.
### Radarr Add Settings ### Radarr Add Settings

@ -197,7 +197,7 @@ The `sync_mode: sync` and `collection_order: custom` Setting are recommended sin
| `votes.lte` | Item must have a Number of Votes less than or equal to the given number.<br>**Options:** Any Integer greater than `0`<br>**Example:** `1000` | | `votes.lte` | Item must have a Number of Votes less than or equal to the given number.<br>**Options:** Any Integer greater than `0`<br>**Example:** `1000` |
| `genre` | Item must match all genres given. Can be a comma-separated list.<br>**Options:** `action`, `adventure`, `animation`, `biography`, `comedy`, `documentary`, `drama`, `crime`, `family`, `history`, `news`, `short`, `western`, `sport`, `reality-tv`, `horror`, `fantasy`, `film-noir`, `music`, `romance`, `talk-show`, `thriller`, `war`, `sci-fi`, `musical`, `mystery`, `game-show` | | `genre` | Item must match all genres given. Can be a comma-separated list.<br>**Options:** `action`, `adventure`, `animation`, `biography`, `comedy`, `documentary`, `drama`, `crime`, `family`, `history`, `news`, `short`, `western`, `sport`, `reality-tv`, `horror`, `fantasy`, `film-noir`, `music`, `romance`, `talk-show`, `thriller`, `war`, `sci-fi`, `musical`, `mystery`, `game-show` |
| `genre.any` | Item must match at least one given genre. Can be a comma-separated list.<br>**Options:** `action`, `adventure`, `animation`, `biography`, `comedy`, `documentary`, `drama`, `crime`, `family`, `history`, `news`, `short`, `western`, `sport`, `reality-tv`, `horror`, `fantasy`, `film-noir`, `music`, `romance`, `talk-show`, `thriller`, `war`, `sci-fi`, `musical`, `mystery`, `game-show` | | `genre.any` | Item must match at least one given genre. Can be a comma-separated list.<br>**Options:** `action`, `adventure`, `animation`, `biography`, `comedy`, `documentary`, `drama`, `crime`, `family`, `history`, `news`, `short`, `western`, `sport`, `reality-tv`, `horror`, `fantasy`, `film-noir`, `music`, `romance`, `talk-show`, `thriller`, `war`, `sci-fi`, `musical`, `mystery`, `game-show` |
| `genre.not` | Item must not match any og the given genres. Can be a comma-separated list.<br>**Options:** `action`, `adventure`, `animation`, `biography`, `comedy`, `documentary`, `drama`, `crime`, `family`, `history`, `news`, `short`, `western`, `sport`, `reality-tv`, `horror`, `fantasy`, `film-noir`, `music`, `romance`, `talk-show`, `thriller`, `war`, `sci-fi`, `musical`, `mystery`, `game-show` | | `genre.not` | Item must not match any of the given genres. Can be a comma-separated list.<br>**Options:** `action`, `adventure`, `animation`, `biography`, `comedy`, `documentary`, `drama`, `crime`, `family`, `history`, `news`, `short`, `western`, `sport`, `reality-tv`, `horror`, `fantasy`, `film-noir`, `music`, `romance`, `talk-show`, `thriller`, `war`, `sci-fi`, `musical`, `mystery`, `game-show` |
| `event` | Item must have been nominated for a category at the event given. Can be a comma-separated list.<br>**Options:** `cannes`, `choice`, `spirit`, `sundance`, `bafta`, `oscar`, `emmy`, `golden`, `oscar_picture`, `oscar_director`, `national_film_board_preserved`, `razzie`, or any [IMDb Event ID](https://www.imdb.com/event/all/) (ex. `ev0050888`) | | `event` | Item must have been nominated for a category at the event given. Can be a comma-separated list.<br>**Options:** `cannes`, `choice`, `spirit`, `sundance`, `bafta`, `oscar`, `emmy`, `golden`, `oscar_picture`, `oscar_director`, `national_film_board_preserved`, `razzie`, or any [IMDb Event ID](https://www.imdb.com/event/all/) (ex. `ev0050888`) |
| `event.winning` | Item must have won a category at the event given. Can be a comma-separated list.<br>**Options:** `cannes`, `choice`, `spirit`, `sundance`, `bafta`, `oscar`, `emmy`, `golden`, `oscar_picture`, `oscar_director`, `national_film_board_preserved`, `razzie`, or any [IMDb Event ID](https://www.imdb.com/event/all/) (ex. `ev0050888`) | | `event.winning` | Item must have won a category at the event given. Can be a comma-separated list.<br>**Options:** `cannes`, `choice`, `spirit`, `sundance`, `bafta`, `oscar`, `emmy`, `golden`, `oscar_picture`, `oscar_director`, `national_film_board_preserved`, `razzie`, or any [IMDb Event ID](https://www.imdb.com/event/all/) (ex. `ev0050888`) |
| `imdb_top` | Item must be in the top number of given Movies.<br>**Options:** Any Integer greater than `0` | | `imdb_top` | Item must be in the top number of given Movies.<br>**Options:** Any Integer greater than `0` |

@ -1,16 +1,16 @@
# MdbList Builders # MDBList Builders
You can find items using the features of [MdbList.com](https://mdblist.com/) (MdbList). You can find items using the features of [MDBList.com](https://mdblist.com/) (MDBList).
| Attribute | Description | Works with Movies | Works with Shows | Works with Playlists and Custom Sort | | Attribute | Description | Works with Movies | Works with Shows | Works with Playlists and Custom Sort |
|:--------------------------------|:--------------------------------------------------------------------------|:------------------------------------------:|:------------------------------------------:|:------------------------------------------:| |:--------------------------------|:--------------------------------------------------------------------------|:------------------------------------------:|:------------------------------------------:|:------------------------------------------:|
| [`mdblist_list`](#mdblist-list) | Gets every movie/show in a [MdbList List](https://mdblist.com/toplists/). | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | | [`mdblist_list`](#mdblist-list) | Gets every movie/show in a [MDBList List](https://mdblist.com/toplists/). | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } |
## MdbList List ## MDBList List
Finds every item in a [MdbList List](https://mdblist.com/toplists/). Finds every item in a [MDBList List](https://mdblist.com/toplists/).
The expected input is an MdbList List URL. Multiple values are supported as a list only a comma-separated string will not work. The expected input is an MDBList List URL. Multiple values are supported as a list only a comma-separated string will not work.
The `sync_mode: sync` and `collection_order: custom` Setting are recommended since the lists are continuously updated and in a specific order. The `sync_mode: sync` and `collection_order: custom` Setting are recommended since the lists are continuously updated and in a specific order.
@ -40,9 +40,9 @@ The default `sort_by` when it's not specified is `rank.asc`.
| Option | Description | | Option | Description |
|:----------------------------------------------|:-------------------------------| |:----------------------------------------------|:-------------------------------|
| `rank.asc`<br>`rank.desc` | Sort by MdbList Rank | | `rank.asc`<br>`rank.desc` | Sort by MDBList Rank |
| `score.asc`<br>`score.desc` | Sort by MdbList Score | | `score.asc`<br>`score.desc` | Sort by MDBList Score |
| `score_average.asc`<br>`score_average.desc` | Sort by MdbList Average Score | | `score_average.asc`<br>`score_average.desc` | Sort by MDBList Average Score |
| `released.asc`<br>`released.desc` | Sort by Release Date | | `released.asc`<br>`released.desc` | Sort by Release Date |
| `imdbrating.asc`<br>`imdbrating.desc` | Sort by IMDb Rating | | `imdbrating.asc`<br>`imdbrating.desc` | Sort by IMDb Rating |
| `imdbvotes.asc`<br>`imdbvotes.desc` | Sort by IMDb Votes | | `imdbvotes.asc`<br>`imdbvotes.desc` | Sort by IMDb Votes |

@ -61,15 +61,15 @@ Builders use third-party services to source items to be added to the collection.
!!! builder !!! builder
![MdbList logo](../../../assets/icons/mdblist.png){ align=right } ![MDBList logo](../../../assets/icons/mdblist.png){ align=right }
**[MdbList](../mdblist)** builders grab items based on lists on MdbList.com **[MDBList](../mdblist)** builders grab items based on lists on MDBList.com
[:octicons-home-16: View Builder](../mdblist){ .md-button .md-button--primary } [:octicons-home-16: View Builder](../mdblist){ .md-button .md-button--primary }
??? quicklink "Popular Builders" ??? quicklink "Popular Builders"
- [:octicons-list-ordered-16: MdbList List](../mdblist/#mdblist-list) - Gets every movie/show in a MDbList List. - [:octicons-list-ordered-16: MDBList List](../mdblist/#mdblist-list) - Gets every movie/show in a MDBList List.
!!! builder !!! builder
@ -98,7 +98,7 @@ Builders use third-party services to source items to be added to the collection.
- [:material-television-guide: TVDb Show](../tvdb/#tvdb-show) - Grabs the specified series. - [:material-television-guide: TVDb Show](../tvdb/#tvdb-show) - Grabs the specified series.
- [:material-television-guide: TVDb Movie](../tvdb/#tvdb-movie) - Gets the specified movies. - [:material-television-guide: TVDb Movie](../tvdb/#tvdb-movie) - Gets the specified movies.
- [:material-television-guide: TVDb List](../tvdb/#tvdb-list) - Gets every item in a TVDb List or TVDb Userlist. - [:material-television-guide: TVDb List](../tvdb/#tvdb-list) - Gets every item in a TVDb List or TVDb UserList.
!!! builder !!! builder

@ -9,7 +9,7 @@ You can find items using the features of [Trakt.tv](https://trakt.tv/) (Trakt).
| [`trakt_list`](#trakt-list) | Finds every movie/show in the Trakt List | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | | [`trakt_list`](#trakt-list) | Finds every movie/show in the Trakt List | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } |
| [`trakt_list_details`](#trakt-list) | Finds every movie/show in the Trakt List and updates the collection summary with the list description | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | | [`trakt_list_details`](#trakt-list) | Finds every movie/show in the Trakt List and updates the collection summary with the list description | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } |
| [`trakt_chart`](#trakt-chart) | Finds the movies/shows in the Trakt Chart | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | | [`trakt_chart`](#trakt-chart) | Finds the movies/shows in the Trakt Chart | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } |
| [`trakt_userlist`](#trakt-userlist) | Finds every movie/show in the Trakt Userlist | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | | [`trakt_userlist`](#trakt-userlist) | Finds every movie/show in the Trakt UserList | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } |
| [`trakt_recommendations`](#trakt-recommendations) | Finds the movies/shows in Trakt's Personal Recommendations for your User [Movies](https://trakt.docs.apiary.io/#reference/recommendations/movies/get-movie-recommendations)/[Shows](https://trakt.docs.apiary.io/#reference/recommendations/shows/get-show-recommendations) | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | | [`trakt_recommendations`](#trakt-recommendations) | Finds the movies/shows in Trakt's Personal Recommendations for your User [Movies](https://trakt.docs.apiary.io/#reference/recommendations/movies/get-movie-recommendations)/[Shows](https://trakt.docs.apiary.io/#reference/recommendations/shows/get-show-recommendations) | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } |
| [`trakt_boxoffice`](#trakt-box-office) | Finds the 10 movies in Trakt's Top Box Office [Movies](https://trakt.tv/movies/boxoffice) list | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-xmark:{ .red } | :fontawesome-solid-circle-check:{ .green } | | [`trakt_boxoffice`](#trakt-box-office) | Finds the 10 movies in Trakt's Top Box Office [Movies](https://trakt.tv/movies/boxoffice) list | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-xmark:{ .red } | :fontawesome-solid-circle-check:{ .green } |
@ -128,9 +128,9 @@ collections:
sync_mode: sync sync_mode: sync
``` ```
## Trakt Userlist ## Trakt UserList
Finds every movie/show in the Trakt Userlist. Finds every movie/show in the Trakt UserList.
The `sync_mode: sync` and `collection_order: custom` Setting are recommended since the lists are continuously updated The `sync_mode: sync` and `collection_order: custom` Setting are recommended since the lists are continuously updated
and in a specific order. and in a specific order.

@ -6,8 +6,8 @@ No configuration is required for these builders.
| Attribute | Description | Works with Movies | Works with Shows | Works with Playlists and Custom Sort | | Attribute | Description | Works with Movies | Works with Shows | Works with Playlists and Custom Sort |
|:------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------:|:------------------------------------------:|:------------------------------------------:| |:------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------:|:------------------------------------------:|:------------------------------------------:|
| [`tvdb_list`](#tvdb-list) | Finds every item in a [TVDb List](https://www.thetvdb.com/lists) or [TVDb Userlist](https://www.thetvdb.com/lists/custom) | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | | [`tvdb_list`](#tvdb-list) | Finds every item in a [TVDb List](https://www.thetvdb.com/lists) or [TVDb UserList](https://www.thetvdb.com/lists/custom) | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } |
| [`tvdb_list_details`](#tvdb-list) | Finds every item in a [TVDb List](https://www.thetvdb.com/lists) or [TVDb Userlist](https://www.thetvdb.com/lists/custom) and updates the collection summary and poster with the TVDb list metadata | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | | [`tvdb_list_details`](#tvdb-list) | Finds every item in a [TVDb List](https://www.thetvdb.com/lists) or [TVDb UserList](https://www.thetvdb.com/lists/custom) and updates the collection summary and poster with the TVDb list metadata | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-check:{ .green } |
| [`tvdb_show`](#tvdb-show) | Finds the series specified | :fontawesome-solid-circle-xmark:{ .red } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-xmark:{ .red } | | [`tvdb_show`](#tvdb-show) | Finds the series specified | :fontawesome-solid-circle-xmark:{ .red } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-xmark:{ .red } |
| [`tvdb_show_details`](#tvdb-show) | Finds the series specified and updates the collection with the summary, poster, and background from the TVDb series | :fontawesome-solid-circle-xmark:{ .red } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-xmark:{ .red } | | [`tvdb_show_details`](#tvdb-show) | Finds the series specified and updates the collection with the summary, poster, and background from the TVDb series | :fontawesome-solid-circle-xmark:{ .red } | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-xmark:{ .red } |
| [`tvdb_movie`](#tvdb-movie) | Finds the movie specified | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-xmark:{ .red } | :fontawesome-solid-circle-xmark:{ .red } | | [`tvdb_movie`](#tvdb-movie) | Finds the movie specified | :fontawesome-solid-circle-check:{ .green } | :fontawesome-solid-circle-xmark:{ .red } | :fontawesome-solid-circle-xmark:{ .red } |
@ -15,9 +15,9 @@ No configuration is required for these builders.
## TVDb List ## TVDb List
Finds every item in a [TVDb List](https://www.thetvdb.com/lists) or [TVDb Userlist](https://www.thetvdb.com/lists/custom) Finds every item in a [TVDb List](https://www.thetvdb.com/lists) or [TVDb UserList](https://www.thetvdb.com/lists/custom)
The expected input is a TVDb List URL or TVDb Userlist URL. Multiple values are supported as either a list or a The expected input is a TVDb List URL or TVDb UserList URL. Multiple values are supported as either a list or a
comma-separated string. comma-separated string.
The `sync_mode: sync` and `collection_order: custom` Setting are recommended since the lists are continuously updated The `sync_mode: sync` and `collection_order: custom` Setting are recommended since the lists are continuously updated

Binary file not shown.

Before

Width:  |  Height:  |  Size: 452 KiB

After

Width:  |  Height:  |  Size: 323 KiB

@ -58,20 +58,6 @@ I then call "MyOverlays.yml" in my [Configuration File](../config/overview.md) w
1. This must match the name of a library in your Plex server 1. This must match the name of a library in your Plex server
2. `config` refers to the location that you mapped to `config` when following the Kometa Installation Guides. 2. `config` refers to the location that you mapped to `config` when following the Kometa Installation Guides.
???+ example "config.yml Example Collection File Addition"
Click the :fontawesome-solid-circle-plus: icon to learn more
```yaml
libraries:
Movies: #(1)!
Overlay_files:
- file: config/MyOverlays.yml #(2)!
```
1. This must match the name of a library in your Plex server
2. `config` refers to the location that you mapped to `config` when following the Kometa Installation Guides.
Whenever I execute Kometa and the Movies library is run, MyOverlays.yml will run and my "Direct Play" overlay will appear on all items with a 4K resolution. Whenever I execute Kometa and the Movies library is run, MyOverlays.yml will run and my "Direct Play" overlay will appear on all items with a 4K resolution.
## File Attributes ## File Attributes
@ -333,17 +319,17 @@ Each Special Text Variables has multiple modifiers that can be used to format th
| `imdb_rating` | IMDb Rating | `Movies`, `Shows`, or `Episodes` | | `imdb_rating` | IMDb Rating | `Movies`, `Shows`, or `Episodes` |
| `trakt_user_rating` | Trakt User Rating | `Movies` or `Shows` | | `trakt_user_rating` | Trakt User Rating | `Movies` or `Shows` |
| `omdb_rating` | OMDb Rating | `Movies` or `Shows` | | `omdb_rating` | OMDb Rating | `Movies` or `Shows` |
| `mdb_rating` | MDbList Rating | `Movies` or `Shows` | | `mdb_rating` | MDBList Rating | `Movies` or `Shows` |
| `mdb_average_rating` | MDbList Average Rating | `Movies` or `Shows` | | `mdb_average_rating` | MDBList Average Rating | `Movies` or `Shows` |
| `mdb_imdb_rating` | MDbList IMDb Rating | `Movies` or `Shows` | | `mdb_imdb_rating` | MDBList IMDb Rating | `Movies` or `Shows` |
| `mdb_metacritic_rating` | MDbList Metacritic Rating | `Movies` or `Shows` | | `mdb_metacritic_rating` | MDBList Metacritic Rating | `Movies` or `Shows` |
| `mdb_metacriticuser_rating` | MDbList Metacritic User Rating | `Movies` or `Shows` | | `mdb_metacriticuser_rating` | MDBList Metacritic User Rating | `Movies` or `Shows` |
| `mdb_trakt_rating` | MDbList Trakt Rating | `Movies` or `Shows` | | `mdb_trakt_rating` | MDBList Trakt Rating | `Movies` or `Shows` |
| `mdb_tomatoes_rating` | MDbList Rotten Tomatoes Rating | `Movies` or `Shows` | | `mdb_tomatoes_rating` | MDBList Rotten Tomatoes Rating | `Movies` or `Shows` |
| `mdb_tomatoesaudience_rating` | MDbList Rotten Tomatoes Audience Rating | `Movies` or `Shows` | | `mdb_tomatoesaudience_rating` | MDBList Rotten Tomatoes Audience Rating | `Movies` or `Shows` |
| `mdb_tmdb_rating` | MDbList TMDb Rating | `Movies` or `Shows` | | `mdb_tmdb_rating` | MDBList TMDb Rating | `Movies` or `Shows` |
| `mdb_letterboxd_rating` | MDbList Letterboxd Rating | `Movies` or `Shows` | | `mdb_letterboxd_rating` | MDBList Letterboxd Rating | `Movies` or `Shows` |
| `mdb_myanimelist_rating` | MDbList MyAnimeList Rating | `Movies` or `Shows` | | `mdb_myanimelist_rating` | MDBList MyAnimeList Rating | `Movies` or `Shows` |
| `anidb_rating` | AniDB Rating | `Movies` or `Shows` | | `anidb_rating` | AniDB Rating | `Movies` or `Shows` |
| `anidb_average_rating` | AniDB Average Rating | `Movies` or `Shows` | | `anidb_average_rating` | AniDB Average Rating | `Movies` or `Shows` |
| `anidb_score_rating` | AniDB Score Rating | `Movies` or `Shows` | | `anidb_score_rating` | AniDB Score Rating | `Movies` or `Shows` |

@ -124,8 +124,8 @@ There are multiple types of attributes that can be utilized within a playlist:
### Special Playlist Attributes ### Special Playlist Attributes
| Attribute | Description | Required | | Attribute | Description | Required |
|:------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------:| |:------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------:|
| `libraries` | Determine which libraries the playlist will be built from.<br>**Options:** Comma-separated string or list of library mapping names defined in the `libraries` attribute in the base of your [Configuration File](../overview.md. | :fontawesome-solid-circle-check:{ .green } | | `libraries` | Determine which libraries the playlist will be built from.<br>**Options:** Comma-separated string or list of library mapping names defined in the `libraries` attribute in the base of your [Configuration File](../config/overview.md). | :fontawesome-solid-circle-check:{ .green } |
| `sync_to_users` | Determine which Users have the playlist synced.<br>This will override the global [`playlist_sync_to_users` Setting](../config/settings.md).<br>**Options:** Comma-separated string or list of users, `all` for every user who has server access, or leave blank for just the server owner. | :fontawesome-solid-circle-xmark:{ .red } | | `sync_to_users` | Determine which Users have the playlist synced.<br>This will override the global [`playlist_sync_to_users` Setting](../config/settings.md).<br>**Options:** Comma-separated string or list of users, `all` for every user who has server access, or leave blank for just the server owner. | :fontawesome-solid-circle-xmark:{ .red } |
| `exclude_users` | Determine which Users will be excluded from having the playlist synced.<br>This will override the global [`playlist_excude_users` Setting](../config/settings.md).<br>**Options:** Comma-separated string or list of users, `all` for every user who has server access, or leave blank for just the server owner. | :fontawesome-solid-circle-xmark:{ .red } | | `exclude_users` | Determine which Users will be excluded from having the playlist synced.<br>This will override the global [`playlist_excude_users` Setting](../config/settings.md).<br>**Options:** Comma-separated string or list of users, `all` for every user who has server access, or leave blank for just the server owner. | :fontawesome-solid-circle-xmark:{ .red } |
| `delete_playlist` | Will delete this playlist for the users defined by sync_to_users.<br>**Options:** `true` or `false` | :fontawesome-solid-circle-xmark:{ .red } | | `delete_playlist` | Will delete this playlist for the users defined by sync_to_users.<br>**Options:** `true` or `false` | :fontawesome-solid-circle-xmark:{ .red } |

@ -7,7 +7,7 @@ search:
All the following attributes serve various functions as how the definition functions inside of Kometa. All the following attributes serve various functions as how the definition functions inside of Kometa.
| Attribute | Description & Values | | Attribute | Description & Values |
|:-----------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |:-----------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `name` | **Description:** Used to specify the name of the definition in Plex as different than the mapping name.<br>**Values:** Any String | | `name` | **Description:** Used to specify the name of the definition in Plex as different than the mapping name.<br>**Values:** Any String |
| `limit` | **Description:** Used to specify the max number of items for the definition<br>**Values:** Number greater than 0 | | `limit` | **Description:** Used to specify the max number of items for the definition<br>**Values:** Number greater than 0 |
| `template` | **Description:** Used to specify a template and template variables to use for this definition. See the [Templates Page](templates.md) for more information.<br>**Values:** Dictionary | | `template` | **Description:** Used to specify a template and template variables to use for this definition. See the [Templates Page](templates.md) for more information.<br>**Values:** Dictionary |
@ -58,3 +58,22 @@ An example of using `default_percent` which is used in an external yml file and
filters: filters:
filepath.regex: 'HDR10\+|HDR10P' filepath.regex: 'HDR10\+|HDR10P'
``` ```
An example of using `server_preroll` which is also used in an external yml file and not within config.yml:
```yml
templates:
preroll:
default: # HERE
location: "\\path\\to\\file"
build_collection: false
schedule: <<schedule>>
server_preroll: <<location>>
collections:
base:
template: {name: preroll, location: "\\path\\to\\file", schedule: daily}
date1:
template: {name: preroll, location: "\\path\\to\\file", schedule: range(12/01-12/31)}
date2:
template: {name: preroll, location: "\\path\\to\\file2", schedule: range(01/01-01/31)}
```

@ -47,9 +47,8 @@ In addition, templates also have a few special attributes that they can use:
??? blank "`default` - Sets what template variables default to.<a class="headerlink" href="#default" title="Permanent link"></a>" ??? blank "`default` - Sets what template variables default to.<a class="headerlink" href="#default" title="Permanent link"></a>"
<div id="default" />The `default` attribute allows default values for template variables to be used if they're not <div id="default" />The `default` attribute allows default values for template variables which will be used if they're not
specified in the call. It's value is a dictionary of key value pairs where the key is the template variable and the specified in the call. You need to provide a list of variables and the value that variable should get if not told differently when the template is referenced. See the tooltips below.
value is the default value to set it to when not provided.
**A variable cannot be default if it is a conditional variable.** **A variable cannot be default if it is a conditional variable.**
@ -83,13 +82,13 @@ In addition, templates also have a few special attributes that they can use:
1. This sets the default value of the template variable `my_sync_mode` to `sync`. 1. This sets the default value of the template variable `my_sync_mode` to `sync`.
2. The value for template variable `my_sync_mode` will replace `<<my_sync_mode>>` here. 2. The value for template variable `my_sync_mode` will replace `<<my_sync_mode>>` here.
3. This specifiys that `my_sync_mode` for this definition will be `append`. 3. This specifies that `my_sync_mode` for this definition will be `append`.
4. Since `my_sync_mode` is not passed to this definition the value of `my_sync_mode` will be the default `sync`. 4. Since `my_sync_mode` is not passed to this definition the value of `my_sync_mode` will be the default `sync`.
??? blank "`optional` - List of template variables to be removed when not provided.<a class="headerlink" href="#optional" title="Permanent link"></a>" ??? blank "`optional` - List of template variables to be removed when not provided.<a class="headerlink" href="#optional" title="Permanent link"></a>"
<div id="optional" />The `optional` attribute can specify variables that when not specified on the template call <div id="optional" />The `optional` attribute can specify variables that when not specified on the template call
will cause any attribute using one of those variables to be ignored in the template. It's value is a list of will cause any attribute using one of those variables to be ignored in the template. Its value is a list of
template variables to be considered optional. template variables to be considered optional.
**You can make any template variable optional per collection by setting it to `null`.** **You can make any template variable optional per collection by setting it to `null`.**
@ -126,7 +125,7 @@ In addition, templates also have a few special attributes that they can use:
1. This sets the template variable `my_sync_mode` as an optional variable. 1. This sets the template variable `my_sync_mode` as an optional variable.
2. The value for template variable `my_sync_mode` will replace `<<my_sync_mode>>` here or removed as optional. 2. The value for template variable `my_sync_mode` will replace `<<my_sync_mode>>` here or removed as optional.
3. This specifiys that `my_sync_mode` for this definition will be `append`. 3. This specifies that `my_sync_mode` for this definition will be `append`.
4. Since `my_sync_mode` is not passed to this definition it will ignore the entire `sync_mode` attribute in the 4. Since `my_sync_mode` is not passed to this definition it will ignore the entire `sync_mode` attribute in the
template. template.
@ -145,7 +144,7 @@ In addition, templates also have a few special attributes that they can use:
A condition block consists of one or more key value pairs comparing given template variables to pre supplied static A condition block consists of one or more key value pairs comparing given template variables to pre supplied static
values. values.
The key is the name of the template variable who's value you want to compare. While the value is the staic value or The key is the name of the template variable whose value you want to compare, while the value is the static value or
values to compare aginst. Every condition block must also have the `value` key which will be the value of the values to compare aginst. Every condition block must also have the `value` key which will be the value of the
template variable if all the conditions in that block are met. template variable if all the conditions in that block are met.
@ -231,7 +230,7 @@ In addition, templates also have a few special attributes that they can use:
name: Movies name: Movies
tmdb_id: 86311 tmdb_id: 86311
Iron Man: Iron Man:
template: 1 template:
name: Movies name: Movies
tmdb_id: 131292 tmdb_id: 131292
``` ```

@ -76,14 +76,6 @@ Transform your media library with Kometa and discover its full potential! Connec
</div> </div>
## Demo Video
The below YouTube video has been created by one of our community members to showcase some of the things that Kometa can do for you.
<iframe width="840" height="472" src="https://www.youtube.com/embed/nTfCUtKWTYI?si=PUvELjmqFUu4p9yk" title="Kometa Demo Video" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
## Example Kometa Libraries ## Example Kometa Libraries
Here are some examples of the things you can achieve using Kometa! Here are some examples of the things you can achieve using Kometa!

@ -28,11 +28,11 @@ These are the developers and creators who are an active part of the Kometa commu
| Acknowledgement | Reason | Sponsor the Developer | | Acknowledgement | Reason | Sponsor the Developer |
|:---------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------:| |:---------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------:|
| [chazlarson](https://github.com/chazlarson/) | Creator of [Media-Scripts](https://github.com/chazlarson/Media-Scripts) which offers supporting functionality to users of Kometa | [Click Here](https://www.google.com/search?q=food+shelf+near+me) | | [chazlarson](https://github.com/chazlarson/) | Creator of [Media-Scripts](https://github.com/chazlarson/Media-Scripts) which offers supporting functionality to users of Kometa | [Click Here](https://www.google.com/search?q=food+shelf+near+me) |
| [linas](https://github.com/linaspurinis) | Creator of [MDBlist.com](https://github.com/deva5610/IMDBList2PlexCollection) which makes creating Kometa compatible lists easy | [Click Here](https://www.patreon.com/mdblist/posts) | | [linas](https://github.com/linaspurinis) | Creator of [MDBList.com](https://github.com/deva5610/IMDbList2PlexCollection) which makes creating Kometa compatible lists easy | [Click Here](https://www.patreon.com/mdblist/posts) |
| [nitsua](https://github.com/austinwbest) | Creator of [Notifiarr](https://github.com/Notifiarr) which integrates Kometa with Discord | [Click Here](https://github.com/sponsors/Notifiarr) | | [nitsua](https://github.com/austinwbest) | Creator of [Notifiarr](https://github.com/Notifiarr) which integrates Kometa with Discord | [Click Here](https://github.com/sponsors/Notifiarr) |
| [ZeroQI](https://github.com/ZeroQI) | Creator of [Absolute Series Scanner](https://github.com/ZeroQI/Absolute-Series-Scanner) and the [HTTP Anidb Metadata Agent (HAMA)](https://github.com/ZeroQI/Hama.bundle) | [Click Here](https://github.com/sponsors/ZeroQI) | | [ZeroQI](https://github.com/ZeroQI) | Creator of [Absolute Series Scanner](https://github.com/ZeroQI/Absolute-Series-Scanner) and the [HTTP AniDB Metadata Agent (HAMA)](https://github.com/ZeroQI/Hama.bundle) | [Click Here](https://github.com/sponsors/ZeroQI) |
| [ScudLee](https://github.com/ScudLee) | Creator of [AniDb Anime Lists](https://github.com/Anime-Lists/anime-lists) | :fontawesome-solid-circle-xmark:{ .red } | | [ScudLee](https://github.com/ScudLee) | Creator of [AniDB Anime Lists](https://github.com/Anime-Lists/anime-lists) | :fontawesome-solid-circle-xmark:{ .red } |
| [Fribb](https://github.com/Fribb) | Creator of the [MyAnimelist.net Metadata Agent](https://github.com/Fribb/MyAnimeList.bundle) which makes matching Anime easy for Kometa users | :fontawesome-solid-circle-xmark:{ .red } | | [Fribb](https://github.com/Fribb) | Creator of the [MyAnimeList.net Metadata Agent](https://github.com/Fribb/MyAnimeList.bundle) which makes matching Anime easy for Kometa users | :fontawesome-solid-circle-xmark:{ .red } |
| [Koltom](https://mediux.pro/) | Creator of [Mediux](https://mediux.pro/) | :fontawesome-solid-circle-xmark:{ .red } | | [Koltom](https://mediux.pro/) | Creator of [Mediux](https://mediux.pro/) | :fontawesome-solid-circle-xmark:{ .red } |
<br> <br>
@ -43,8 +43,8 @@ These are the developers and creators who served as inspiration for Kometa.
| Acknowledgement | Reason | Sponsor the Developer | | Acknowledgement | Reason | Sponsor the Developer |
|:--------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------:| |:--------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------:|
| [JonnyWong16](https://github.com/JonnyWong16) | Creator of the [IMDb Top 250](https://gist.github.com/JonnyWong16/f5b9af386ea58e19bf18c09f2681df23) collection script which served as inspiration for IMDBList2PlexCollection (and for [Tautulli](https://github.com/Tautulli/Tautulli)!) | [Click Here](https://github.com/sponsors/JonnyWong16) | | [JonnyWong16](https://github.com/JonnyWong16) | Creator of the [IMDb Top 250](https://gist.github.com/JonnyWong16/f5b9af386ea58e19bf18c09f2681df23) collection script which served as inspiration for IMDbList2PlexCollection (and for [Tautulli](https://github.com/Tautulli/Tautulli)!) | [Click Here](https://github.com/sponsors/JonnyWong16) |
| [deva5610](https://github.com/deva5610) | Creator of [IMDBList2PlexCollection](https://github.com/deva5610/IMDBList2PlexCollection) which prompted vladimir-tutin to write the original Plex Auto Collections | :fontawesome-solid-circle-xmark:{ .red } | | [deva5610](https://github.com/deva5610) | Creator of [IMDbList2PlexCollection](https://github.com/deva5610/IMDbList2PlexCollection) which prompted vladimir-tutin to write the original Plex Auto Collections | :fontawesome-solid-circle-xmark:{ .red } |
| [vladimir-tutin](https://github.com/vladimir-tutin) | Creator of the original [Plex Auto Collections](https://github.com/vladimir-tutin/Plex-Auto-Collections) which is the inspiration for Kometa. | :fontawesome-solid-circle-xmark:{ .red } | | [vladimir-tutin](https://github.com/vladimir-tutin) | Creator of the original [Plex Auto Collections](https://github.com/vladimir-tutin/Plex-Auto-Collections) which is the inspiration for Kometa. | :fontawesome-solid-circle-xmark:{ .red } |
| [mza921](https://github.com/mza921) and [burkasaurusrex](https://github.com/burkasaurusrex) | Maintaining a forked [Plex Auto Collections](https://github.com/mza921/Plex-Auto-Collections) | :fontawesome-solid-circle-xmark:{ .red } | | [mza921](https://github.com/mza921) and [burkasaurusrex](https://github.com/burkasaurusrex) | Maintaining a forked [Plex Auto Collections](https://github.com/mza921/Plex-Auto-Collections) | :fontawesome-solid-circle-xmark:{ .red } |
| [jkirkcaldy](https://github.com/jkirkcaldy) | Creator of [plex-utills](https://github.com/jkirkcaldy/plex-utills) which served as inspiration for Image Overlay | [Click Here](https://opencollective.com/themainframe) | | [jkirkcaldy](https://github.com/jkirkcaldy) | Creator of [plex-utills](https://github.com/jkirkcaldy/plex-utills) which served as inspiration for Image Overlay | [Click Here](https://opencollective.com/themainframe) |

@ -2,7 +2,7 @@
search: search:
boost: 4 boost: 4
--- ---
# FAQ & Knowledgebase # FAQ & Knowledge Base
This page aims to provide knowledge based on combined user experience, and to answer the frequent questions that we are asked in our [Discord Server](https://kometa.wiki/en/latest/discord/). This page aims to provide knowledge based on combined user experience, and to answer the frequent questions that we are asked in our [Discord Server](https://kometa.wiki/en/latest/discord/).
@ -380,7 +380,7 @@ Your Kometa installation may not be located at the paths referenced below. These
There is nothing that Kometa or our support staff can really do to resolve a 500 error. There is nothing that Kometa or our support staff can really do to resolve a 500 error.
## Knowledgebase ## Knowledge Base
This section aims to provide some insight as to articles/information that we feel is important to document as they may pop up infrequently but often enough to require entry here. This section aims to provide some insight as to articles/information that we feel is important to document as they may pop up infrequently but often enough to require entry here.

@ -17,7 +17,7 @@ These guides will walk you through installing Kometa on your system.
## Explanations ## Explanations
The below guides and recipes have been created to assist users with various aspects of Komets and its companion scripts. The below guides and recipes have been created to assist users with various aspects of Kometa's and its companion scripts.
- [Plex Ratings Explained](ratings.md) - [Plex Ratings Explained](ratings.md)
- [Scheduling Kometa Runs Guide](scheduling.md) - [Scheduling Kometa Runs Guide](scheduling.md)
@ -80,10 +80,10 @@ A lot of these guides are stored on Google Drive as using the traditional wiki p
- Stores the Rainier actor posters - Stores the Rainier actor posters
- [People Images Signature (signature)](https://github.com/Kometa-Team/People-Images-signature) - [People Images Signature (signature)](https://github.com/Kometa-Team/People-Images-signature)
- Stores the Signature actor posters - Stores the Signature actor posters
- [People Images DIIVOY (diiivoy)](https://github.com/Kometa-Team/People-Images-diiivoy) - [People Images DIIIVOY (diiivoy)](https://github.com/Kometa-Team/People-Images-diiivoy)
- Stores the DIIVOY actor posters - Stores the DIIIVOY actor posters
- [People Images DIIVOY Color (diiivoycolor)](https://github.com/Kometa-Team/People-Images-diiivoycolor) - [People Images DIIIVOY Color (diiivoycolor)](https://github.com/Kometa-Team/People-Images-diiivoycolor)
- Stores the DIIVOY Color actor posters - Stores the DIIIVOY Color actor posters
- [People Images Transparent (transparent)](https://github.com/Kometa-Team/People-Images-transparent) - [People Images Transparent (transparent)](https://github.com/Kometa-Team/People-Images-transparent)
- Stores the Transparent actor posters - Stores the Transparent actor posters
@ -93,3 +93,13 @@ A lot of these guides are stored on Google Drive as using the traditional wiki p
- Stores the Kometa Unraid Templates - Stores the Kometa Unraid Templates
- [Translations](https://github.com/Kometa-Team/Translations) - [Translations](https://github.com/Kometa-Team/Translations)
- Stores the data for Kometa Translations - Stores the data for Kometa Translations
## Demo Video
This YouTube video has been created by one of our community members to showcase some of the things that Kometa can do for you.
Caveat: it is very long, and the author has their own ideas as to what is "required". For example, this video begins with setting up a third-party script that is not required to use Kometa.
<iframe width="840" height="472" src="https://www.youtube.com/embed/nTfCUtKWTYI?si=PUvELjmqFUu4p9yk" title="Kometa Demo Video" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

@ -55,9 +55,9 @@ Now let's add rating overlays to the poster. We're going to use the minimal conf
* `rating3` is set to be the user rating and it's image (`rating3_image`) is set to IMDb just because we have to pick something. * `rating3` is set to be the user rating and it's image (`rating3_image`) is set to IMDb just because we have to pick something.
* `reapply_overlays` is set to true to ensure that Kometa always updates the overlays as we run things. * `reapply_overlays` is set to true to ensure that Kometa always updates the overlays as we run things. This should NEVER be required in a typical scenario, it's being done here just as belt-and-suspender insurance.
* We do not recommend using `reapply_overlays: true` consistently in a live/production environment, make sure to switch this back to `false` when finished. * `reapply_overlays: true` should NEVER be used in a live/production environment without a very specific reason, make sure to switch this back to `false` when finished.
After Kometa is run on this library, you'll get this result: After Kometa is run on this library, you'll get this result:
@ -103,7 +103,7 @@ You and I both know that the IMDb rating isn't 6.0, but Kometa is just doing wha
* `rating1_image` and `rating2_image` were both changed from `rt_score` and `rt_popcorn` respectively to `imdb` * `rating1_image` and `rating2_image` were both changed from `rt_score` and `rt_popcorn` respectively to `imdb`
* We do not recommend using `reapply_overlays: true` consistently in a live/production environment, make sure to switch this back to `false` when finished. * `reapply_overlays: true` should NEVER be used in a live/production environment without a very specific reason, make sure to switch this back to `false` when finished.
When the above is run you see this result: When the above is run you see this result:
@ -140,7 +140,7 @@ Now let's actually update the ratings and push some numbers into those boxes usi
* `rating1_image` and `rating2_image` were both changed back to `rt_score` and `rt_popcorn` respectively from `imdb` * `rating1_image` and `rating2_image` were both changed back to `rt_score` and `rt_popcorn` respectively from `imdb`
* We do not recommend using `reapply_overlays: true` consistently in a live/production environment, make sure to switch this back to `false` when finished. * `reapply_overlays: true` should NEVER be used in a live/production environment without a very specific reason, make sure to switch this back to `false` when finished.
This will put the actual IMDb rating value, retrieved from IMDb, into the "user" rating field. This will put the actual IMDb rating value, retrieved from IMDb, into the "user" rating field.
@ -178,7 +178,7 @@ Now let's update the critic and audience ratings to some different ratings:
* under `operations` the attribute `mass_critic_rating_update` set to `trakt_user` and `mass_audience_rating_update` set to `tmdb` are added. * under `operations` the attribute `mass_critic_rating_update` set to `trakt_user` and `mass_audience_rating_update` set to `tmdb` are added.
* We do not recommend using `reapply_overlays: true` consistently in a live/production environment, make sure to switch this back to `false` when finished. * `reapply_overlays: true` should NEVER be used in a live/production environment without a very specific reason, make sure to switch this back to `false` when finished.
Running the above will put the Trakt User's personal rating into the critic box and the TMDb rating into the audience box. Note that we haven't changed the rating images yet. Running the above will put the Trakt User's personal rating into the critic box and the TMDb rating into the audience box. Note that we haven't changed the rating images yet.
@ -202,7 +202,7 @@ The log will show Kometa updating those values.
#### Use Trakt Rating #### Use Trakt Rating
Let's change the Trakt rating to that trakt public rating of `85%` instead, which is available via MDbList: Let's change the Trakt rating to that trakt public rating of `85%` instead, which is available via MDBList:
??? example "Updated config (click to expand)" ??? example "Updated config (click to expand)"
@ -227,7 +227,7 @@ Let's change the Trakt rating to that trakt public rating of `85%` instead, whic
* under `operations` the attribute `mass_critic_rating_update` was changed to `mdb_trakt` from `trakt_user`. (This step requires MDBList to be configured) * under `operations` the attribute `mass_critic_rating_update` was changed to `mdb_trakt` from `trakt_user`. (This step requires MDBList to be configured)
* We do not recommend using `reapply_overlays: true` consistently in a live/production environment, make sure to switch this back to `false` when finished. * `reapply_overlays: true` should NEVER be used in a live/production environment without a very specific reason, make sure to switch this back to `false` when finished.
When the above is run you should get: When the above is run you should get:
@ -264,7 +264,7 @@ Now, finally, let's make the poster rating images match the numbers we put in th
* `rating2_image` was changed to `tmdb` from `rt_popcorn` * `rating2_image` was changed to `tmdb` from `rt_popcorn`
* We do not recommend using `reapply_overlays: true` consistently in a live/production environment, make sure to switch this back to `false` when finished. * `reapply_overlays: true` should NEVER be used in a live/production environment without a very specific reason, make sure to switch this back to `false` when finished.
When the above is run you should get: When the above is run you should get:

@ -102,13 +102,13 @@ This message shows that your installation appears to be working correctly.
... ...
``` ```
If that doesn't work, stop here until you fix that. Diagnoing and repairing Docker install problems is out of the scope of this walkthrough. If that doesn't work, stop here until you fix that. Diagnosing and repairing Docker install problems is out of the scope of this walkthrough.
--- ---
#### Important note on Docker images #### Important note on Docker images
This tutorial uses the official image, and you should, too. Don't change `kometateam/kometa` to the `linuxserver.io` image or any other; other images may have [idiosyncracies](images.md) that will prevent this walkthrough from working. The official image *will* behave exactly as documented below. Others very possibly won't. This tutorial uses the official image, and you should, too. Don't change `kometateam/kometa` to the `linuxserver.io` image or any other; other images may have [idiosyncrasies](images.md) that will prevent this walkthrough from working. The official image *will* behave exactly as documented below. Others very possibly won't.
The great thing about Docker is that all the setup you'd have to do to run Kometa is already done inside the docker image. The great thing about Docker is that all the setup you'd have to do to run Kometa is already done inside the docker image.
@ -300,19 +300,19 @@ First, make a copy of the template:
Get a copy of the template to edit [type this into your terminal]: Get a copy of the template to edit [type this into your terminal]:
``` ```
curl -fLvo config/config.yml https://raw.githubusercontent.com/kometateam/kometa/master/config/config.yml.template curl -fLvo config/config.yml https://raw.githubusercontent.com/Kometa-Team/Kometa/master/config/config.yml.template
``` ```
=== ":fontawesome-brands-apple: macOS" === ":fontawesome-brands-apple: macOS"
Get a copy of the template to edit [type this into your terminal]: Get a copy of the template to edit [type this into your terminal]:
``` ```
curl -fLvo config/config.yml https://raw.githubusercontent.com/kometateam/kometa/master/config/config.yml.template curl -fLvo config/config.yml https://raw.githubusercontent.com/Kometa-Team/Kometa/master/config/config.yml.template
``` ```
=== ":fontawesome-brands-windows: Windows" === ":fontawesome-brands-windows: Windows"
Go to [this URL](https://raw.githubusercontent.com/kometateam/kometa/master/config/config.yml.template) using a web browser; choose the "Save" command, then save the file at: Go to [this URL](https://raw.githubusercontent.com/Kometa-Team/Kometa/master/config/config.yml.template) using a web browser; choose the "Save" command, then save the file at:
``` ```
C:\Users\YOURUSERNAME\kometa\config\config.yml C:\Users\YOURUSERNAME\kometa\config\config.yml
``` ```
@ -445,7 +445,7 @@ docker run --rm -it -v "KOMETA_PATH_GOES_HERE:/config:rw" kometateam/kometa:deve
^^^^^^^ ^^^^^^^
``` ```
This may not work if you are not using the official image; for example, it does not work with the lsio image. This may not work if you are not using the official image.
### I want to use the nightly branch ### I want to use the nightly branch
@ -456,7 +456,7 @@ docker run --rm -it -v "KOMETA_PATH_GOES_HERE:/config:rw" kometateam/kometa:nigh
^^^^^^^ ^^^^^^^
``` ```
This may not work if you are not using the official image; for example, it does not work with the lsio image. This may not work if you are not using the official image.
### I want to ensure I am using the master branch ### I want to ensure I am using the master branch
@ -466,6 +466,3 @@ Add the `latest` tag to the image name in your run command [or wherever you spec
docker run --rm -it -v "KOMETA_PATH_GOES_HERE:/config:rw" kometateam/kometa:latest --run docker run --rm -it -v "KOMETA_PATH_GOES_HERE:/config:rw" kometateam/kometa:latest --run
^^^^^^ ^^^^^^
``` ```
This is the only version tag supplied by the lsio image.

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

@ -77,6 +77,7 @@ spec:
name: tv-config name: tv-config
restartPolicy: OnFailure restartPolicy: OnFailure
``` ```
> :warning: If you are using [Longhorn](https://longhorn.io/) as your storage class, you should omit the `spec.jobTemplate.spec.template.spec.securityContext` node to fix file permission errors.
This CronJob also requires This CronJob also requires
@ -286,7 +287,7 @@ the cronjob starts each time. This can be done by including an init container w
### Including the Init Container in the Cron Job ### Including the Init Container in the Cron Job
NOTE the environment value nameed `JINJA_DEST_FILE` is the resulting name of the generated config file. NOTE the environment value named `JINJA_DEST_FILE` is the resulting name of the generated config file.
``` ```
apiVersion: batch/v1 apiVersion: batch/v1

@ -204,7 +204,7 @@ Later on you can move it elsewhere if you want, but for now put it there. This
``` ```
git pull git pull
``` ```
No need to download a new ZIP, uncompress it, etc. No need to download a new ZIP, decompress it, etc.
Also, if you are asked to [or want to] switch to the latest develop or nightly code, you can do so with: Also, if you are asked to [or want to] switch to the latest develop or nightly code, you can do so with:
``` ```
git checkout develop git checkout develop
@ -366,7 +366,7 @@ python -m pip install -r requirements.txt
``` ```
You should see something like this [Ive removed a few lines for space, and the specific versions may have changed since this was captured]: You should see something like this [Ive removed a few lines for space, and the specific versions may have changed since this was captured]:
Studio: 441 and 1807 and 2495 and 1286 and 2503 and 2264
``` ```
Collecting PlexAPI==4.7.0 Collecting PlexAPI==4.7.0
Downloading PlexAPI-4.7.0-py3-none-any.whl (133 kB) Downloading PlexAPI-4.7.0-py3-none-any.whl (133 kB)
@ -634,10 +634,10 @@ deactivate
### I want to use the nightly branch ### I want to use the nightly branch
Follow the instructions for the `develop` branch above, subsituting `nightly` for `develop` Follow the instructions for the `develop` branch above, substituting `nightly` for `develop`
### I want to use the master branch ### I want to use the master branch
Follow the instructions for the `develop` branch above, subsituting `master` for `develop` Follow the instructions for the `develop` branch above, substituting `master` for `develop`
The installation of requirements every time is probably overkill, but it's harmless and ensures that you always get any new versions or new requirements. The installation of requirements every time is probably overkill, but it's harmless and ensures that you always get any new versions or new requirements.

@ -39,7 +39,7 @@ Thats a command youre going to type or paste into your unRAID Kometa `>_Co
**IMPORTANT NOTES:** **IMPORTANT NOTES:**
* If you were not aware, the unRAID app store leverages Docker containers. As such, we are tweaking the existing Docker container walkthrough to make it work on unRAID. This walkthrough is going to be pretty pedantic. Im assuming youre reading it because you have no idea how to get this going on unRAID, so Im proceeding from the assumption that you want to be walked through every little detail. Youre going to deliberately cause errors and then fix them as you go through it. This is to help you understand what exactly is going on behind the scenes so that when you see these sorts of problems in the wild you will have some background to understand whats happening. If I only give you the happy path walkthrough, then when you make a typo later on youll have no idea where that typo might be or why its breaking things. * The unRAID app store leverages Docker containers. As such, we are tweaking the existing Docker container walkthrough to make it work on unRAID. This walkthrough is going to be pretty pedantic. Im assuming youre reading it because you have no idea how to get this going on unRAID, so Im proceeding from the assumption that you want to be walked through every little detail. Youre going to deliberately cause errors and then fix them as you go through it. This is to help you understand what exactly is going on behind the scenes so that when you see these sorts of problems in the wild you will have some background to understand whats happening. If I only give you the happy path walkthrough, then when you make a typo later on youll have no idea where that typo might be or why its breaking things.
* You may want to take an hour to get familiar with Docker fundamentals with the [official tutorial](https://www.docker.com/101-tutorial/). * You may want to take an hour to get familiar with Docker fundamentals with the [official tutorial](https://www.docker.com/101-tutorial/).
@ -58,7 +58,9 @@ To install a container from docker hub, you will need community applications - a
### Installing Kometa in unRAID ### Installing Kometa in unRAID
1. Head to the `Apps` tab of unRAID (Community Applications), and search `kometa` in the upper right search box. There will be a couple of results shown, but you should ignore them ([Why?](images.md)) and use the official image. 1. Head to the `Apps` tab of unRAID (Community Applications), and search `kometa` in the upper left search box. There will be a couple of results shown, but you should ignore them ([Why?](images.md)) and use the official image.
![](images/unraid-options.png)
2. Click the `Install` button on the Template from Sohjiro's Repository Tools. 2. Click the `Install` button on the Template from Sohjiro's Repository Tools.
@ -66,13 +68,15 @@ To install a container from docker hub, you will need community applications - a
4. Set the `Console shell command:` to `Bash` 4. Set the `Console shell command:` to `Bash`
5. Click `Show more settings...` to set any [Environmental Variables](../environmental.md) you wish to use. **For the purposes of this walkthrough, the** `Container Path: /config` **path for the unRAID app is** `/mnt/user/appdata/kometa/config` (_**Note the case is ALL lower case**_). Other than this, set the `KOMETA_TIME` variable to `5:00` under the `Show more settings...` 5. Verify that the `Container Path: /config` path for the unRAID app is `/mnt/user/appdata/Kometa/config`
![](images/unraid-appdata.png)
6. Hit `Apply`, and allow unRAID to download the container. 6. Hit `Apply`, and allow unRAID to download the image and build the container.
#### Important note on Docker images #### Important note on Docker images
This tutorial uses the official image, and you should, too. Don't change `kometateam/kometa` to the `linuxserver.io` image or any other. Other images may have [idiosyncracies](images.md) that will prevent this walkthrough from working. The official image *will* behave exactly as documented below. Others very possibly won't. This tutorial uses the official image, and you should, too. Don't change `kometateam/kometa` to the `linuxserver.io` image or any other. Other images may have [idiosyncrasies](images.md) that will prevent this walkthrough from working. The official image *will* behave exactly as documented below. Others very possibly won't.
The great thing about Docker is that all the setup you'd have to do to run Kometa is already done inside the docker image. The great thing about Docker is that all the setup you'd have to do to run Kometa is already done inside the docker image.
@ -90,15 +94,15 @@ We need to have a file called `config.yml` in the correct directory for Kometa t
[type this into your terminal] [type this into your terminal]
``` ```
mkdir /mnt/user/appdata/kometa/config mkdir /mnt/user/appdata/Kometa/config
touch /mnt/user/appdata/kometa/config/config.yml touch /mnt/user/appdata/Kometa/config/config.yml
``` ```
You can now close the unRAID terminal and start the Kometa container. You can now close the unRAID terminal and start the Kometa container.
**_From this point forward, you can Console `>_Console` into the running container as it will stay running_** **_From this point forward, you can Console `>_Console` into the running container as it will stay running_**
Open a Console by left-clicking on the running Kometcontainer and selecting `>_Console`. This will open up an interactive session within the container to be able to run the commands we want. Open a Console by left-clicking on the running Kometa Container and selecting `>_Console`. This will open up an interactive session within the container to be able to run the commands we want.
### Create a directory to quiet an error later ### Create a directory to quiet an error later
@ -242,7 +246,9 @@ kometateam/kometa:develop
^^^^^^^ ^^^^^^^
``` ```
This may not work if you are not using the official image; for example, it does not work with the lsio image. Enter that here in the template:
![](images/unraid-repo.png)
### I want to use the nightly branch ### I want to use the nightly branch
@ -253,7 +259,9 @@ kometateam/kometa:nightly
^^^^^^^ ^^^^^^^
``` ```
This may not work if you are not using the official image; for example, it does not work with the lsio image. Enter that here in the template:
![](images/unraid-repo.png)
### I want to ensure I am using the master branch ### I want to ensure I am using the master branch
@ -263,6 +271,7 @@ Add the `latest` tag to the image name in your `Repository:` setting for the Kom
kometateam/kometa:latest kometateam/kometa:latest
^^^^^^ ^^^^^^
``` ```
Enter that here in the template:
This is the only version tag supplied by the lsio image. ![](images/unraid-repo.png)

@ -58,7 +58,7 @@ You will ultimately need an entry here for each of the libraries on which you wa
For now, delete the “TV Shows”, “Anime”, and "Music" sections from the config file and change the name of the “Movies” section to “Movies-NOSUCHLIBRARY": For now, delete the “TV Shows”, “Anime”, and "Music" sections from the config file and change the name of the “Movies” section to “Movies-NOSUCHLIBRARY":
The top bit of your config file should now looke like this: The top bit of your config file should now look like this:
```yaml ```yaml
libraries: libraries:
@ -74,5 +74,5 @@ playlist_files:
This is intended to cause an error for illustration that you will then fix. This is intended to cause an error for illustration that you will then fix.
Be very careful with the indentation and ensure it looks exactly like the above; each line indented using two spaces, NOT TABS, with `playlist_files:` all teh way over on the left. Indentation is significant in YAML. Be very careful with the indentation and ensure it looks exactly like the above; each line indented using two spaces, NOT TABS, with `playlist_files:` all the way over on the left. Indentation is significant in YAML.

@ -2,7 +2,7 @@ Kometa provides an extensive collection of "default" collection files.
These files provide a simple way for you to create collections based on franchises or awards or actors, etc. These files provide a simple way for you to create collections based on franchises or awards or actors, etc.
The default config links to two of them, thse two lines in your config file: The default config links to two of them, these two lines in your config file:
```yaml ```yaml
libraries: libraries:

@ -8,8 +8,8 @@ For best results *with this walkthrough*, your test library will contain:
- At least two comedy movies released since 2012. - At least two comedy movies released since 2012.
- At least two movies from the [IMDB top 250](https://www.imdb.com/chart/top/). - At least two movies from the [IMDB top 250](https://www.imdb.com/chart/top/).
- At least two movies from [IMDB's Popular list](https://www.imdb.com/chart/moviemeter). - At least two movies from [IMDb's Popular list](https://www.imdb.com/chart/moviemeter).
- At least two movies from [IMDB's Lowest Rated](https://www.imdb.com/chart/bottom). - At least two movies from [IMDb's Lowest Rated](https://www.imdb.com/chart/bottom).
- A couple different resolutions among the movies. - A couple different resolutions among the movies.
That will ensure there's something to go into each of the example collections that will be created. That will ensure there's something to go into each of the example collections that will be created.

@ -70,21 +70,21 @@ This section aims to explain some commonly seen event messages that are produced
This table details examples of the most commonly-seen `[CRITICAL]` events and what they mean for the user. This table details examples of the most commonly-seen `[CRITICAL]` events and what they mean for the user.
| Type | Short Info | Description | Recommendation | | Type | Short Info | Description | Recommendation |
|:-----------|:----------------------------------------------------|:------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------| |:-----------|:----------------------------------------------------|:---------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------|
| `CRITICAL` | `Failed to Connect to https://api.themoviedb.org/3` | Current step Kometa was on made an API call to TMDb, but it aborted and moved on | Determine if TMDb was offline and not replying to api requests. Try again and see if it fails again or not. | | `CRITICAL` | `Failed to Connect to https://api.themoviedb.org/3` | Current step Kometa was on made an API call to TMDb, but it aborted and moved on | Determine if TMDb was offline and not replying to API requests. Try again and see if it fails again or not. |
#### ERROR #### ERROR
This table details examples of the most commonly-seen `[ERROR]` events and what they mean for the user. This table details examples of the most commonly-seen `[ERROR]` events and what they mean for the user.
| Type | Short Info | Description | Recommendation | | Type | Short Info | Description | Recommendation |
|:--------|:------------------------------------------------------------------|:---------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |:--------|:------------------------------------------------------------------|:------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `ERROR` | `Playlist Error: Library: XYZ not defined` | Plex library XYZ is not found | Ensure that your config file has defined the proper library name as found in Plex | | `ERROR` | `Playlist Error: Library: XYZ not defined` | Plex library XYZ is not found | Ensure that your config file has defined the proper library name as found in Plex |
| `ERROR` | `Plex Error: resolution: No matches found with regex pattern XYZ` | While looking for a pattern in Plex, this one was not found | This may be normal and require 0 actions. However, if you expect that Plex should have returned records, check the pattern to ensure it is working properly | | `ERROR` | `Plex Error: resolution: No matches found with regex pattern XYZ` | While looking for a pattern in Plex, this one was not found | This may be normal and require 0 actions. However, if you expect that Plex should have returned records, check the pattern to ensure it is working properly |
| `ERROR` | `Plex Error: No Items found in Plex` | While using the Kometa builder, no items with that criteria were returned from Plex | This may be normal and require 0 actions. However, if you expect that Plex should have returned records, check the builder to ensure it is working properly | | `ERROR` | `Plex Error: No Items found in Plex` | While using the Kometa builder, no items with that criteria were returned from Plex | This may be normal and require 0 actions. However, if you expect that Plex should have returned records, check the builder to ensure it is working properly |
| `ERROR` | `IMDb Error: Failed to parse URL:` | While using the Kometa builder, url does not exist | This may be normal and require 0 actions. However, if you expect that the URL should have returned records, check the url in your browser to ensure it is working properly | | `ERROR` | `IMDb Error: Failed to parse URL:` | While using the Kometa builder, url does not exist | This may be normal and require 0 actions. However, if you expect that the URL should have returned records, check the url in your browser to ensure it is working properly |
| `ERROR` | `Trakt Error: No TVDb ID found for Nightfall (2022)` | Online sources are missing information | These sorts of errors indicate that the thing can't be cross-referenced between sites.</br>For example, at the time of that error, the Trakt record for "Nightfall (2022)" didn't contain a TVDb ID.</br>This could be because the record just hasn't been updated, or because "Nightfall (2022)" is not listed on TVDb.</br>The fix is for someone [like you, perhaps] to go to the relevant site and fill in the missing data. | | `ERROR` | `Trakt Error: No TVDb ID found for Nightfall (2022)` | Online sources are missing information | These sorts of errors indicate that the thing can't be cross-referenced between sites.</br>For example, at the time of that error, the Trakt record for "Nightfall (2022)" didn't contain a TVDb ID.</br>This could be because the record just hasn't been updated, or because "Nightfall (2022)" is not listed on TVDb.</br>The fix is for someone [like you, perhaps] to go to the relevant site and fill in the missing data. |
| `ERROR` | `MdbList Error: Not Found` | Online sources are missing information | These sorts of errors indicate that the thing can't be cross-referenced between sites. For example, at the time of that error, the MDBlist record was trying to get a rating for a media item and could not find it. | | `ERROR` | `MDBList Error: Not Found` | Online sources are missing information | These sorts of errors indicate that the thing can't be cross-referenced between sites. For example, at the time of that error, the MDBList record was trying to get a rating for a media item and could not find it. |
| `ERROR` | `Plex Error: actor: Mel B not found` | Actor not found and hence unable to create the collection | Report error in #kometa-help channel and see if there is a fix. | | `ERROR` | `Plex Error: actor: Mel B not found` | Actor not found and hence unable to create the collection | Report error in #kometa-help channel and see if there is a fix. |
| `ERROR` | `Input Failed` | A token or password is no longer valid for an online source of information | Review the kometa.log for more information | | `ERROR` | `Input Failed` | A token or password is no longer valid for an online source of information | Review the kometa.log for more information |
| `ERROR` | `Collection Error: trakt_list requires Trakt to be configured` | You are using a builder that has not been configured yet. | Review the kometa.log for more information on what went wrong. Refer to the wiki for details on how to set this up (in this case Trakt) | | `ERROR` | `Collection Error: trakt_list requires Trakt to be configured` | You are using a builder that has not been configured yet. | Review the kometa.log for more information on what went wrong. Refer to the wiki for details on how to set this up (in this case Trakt) |
@ -94,7 +94,7 @@ This table details examples of the most commonly-seen `[ERROR]` events and what
This table details examples of the most commonly-seen `[WARNING]` events and what they mean for the user. This table details examples of the most commonly-seen `[WARNING]` events and what they mean for the user.
| Type | Short Info | Description | Recommendation | | Type | Short Info | Description | Recommendation |
|:----------|:-----------------------------------------------------------------|:-----------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |:----------|:-------------------------------------------------------------------|:----------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `WARNING` | `Convert Warning: No TVDb ID Found for TMDb ID: 15733` | Online sources are missing information | These sorts of errors indicate that the thing can't be cross-referenced between sites.</br>For example, at the time of that error, the TMDb record for "The Two Mrs. Grenvilles" [ID 15733] didn't contain a TVDb ID.</br>This could be because the record just hasn't been updated, or because "The Two Mrs. Grenvilles" is not listed on TVDB.</br>The fix is for someone [like you, perhaps] to go to the relevant site and fill in the missing data. | | `WARNING` | `Convert Warning: No TVDb ID Found for TMDb ID: 15733` | Online sources are missing information | These sorts of errors indicate that the thing can't be cross-referenced between sites.</br>For example, at the time of that error, the TMDb record for "The Two Mrs. Grenvilles" [ID 15733] didn't contain a TVDb ID.</br>This could be because the record just hasn't been updated, or because "The Two Mrs. Grenvilles" is not listed on TVDB.</br>The fix is for someone [like you, perhaps] to go to the relevant site and fill in the missing data. |
| `WARNING` | `Convert Warning: AniDB ID not found for AniList ID: 21400` | Online sources are missing information | These sorts of errors indicate that the thing can't be cross-referenced between sites. The fix is for someone [like you, perhaps] to go to the relevant site and fill in the missing data. | | `WARNING` | `Convert Warning: AniDB ID not found for AniList ID: 21400` | Online sources are missing information | These sorts of errors indicate that the thing can't be cross-referenced between sites. The fix is for someone [like you, perhaps] to go to the relevant site and fill in the missing data. |
| `WARNING` | `Convert Warning: No TVDb ID or IMDb ID found for AniDB ID: 14719` | Online sources are missing information | These sorts of errors indicate that the thing can't be cross-referenced between sites. The fix is for someone [like you, perhaps] to go to the relevant site and fill in the missing data. | | `WARNING` | `Convert Warning: No TVDb ID or IMDb ID found for AniDB ID: 14719` | Online sources are missing information | These sorts of errors indicate that the thing can't be cross-referenced between sites. The fix is for someone [like you, perhaps] to go to the relevant site and fill in the missing data. |
@ -105,7 +105,7 @@ This table details examples of the most commonly-seen `[WARNING]` events and wha
This table details examples of the most commonly-seen `[INFO]` events and what they mean for the user. This table details examples of the most commonly-seen `[INFO]` events and what they mean for the user.
| Type | Short Info | Description | Recommendation | | Type | Short Info | Description | Recommendation |
|:-------|:----------------------------------------------|:--------------------------------------|:------------------------------------------------------------------------------------------------------------------------------| |:-------|:----------------------------------------------|:--------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------|
| `INFO` | `Detail: TMDb_person updated poster to [URL]` | Person image was downloaded from TMDb | May require you to update the people poster image to your style or request it in the style of the Kometa defaults people posters | | `INFO` | `Detail: TMDb_person updated poster to [URL]` | Person image was downloaded from TMDb | May require you to update the people poster image to your style or request it in the style of the Kometa defaults people posters |
### Other Troubleshooting Examples ### Other Troubleshooting Examples

@ -184,25 +184,25 @@ message: 3: YAML # breaks as a : is a special character
"message: 3": YAML # Works as the key string is quoted "message: 3": YAML # Works as the key string is quoted
``` ```
#### Multiline Strings #### Multi-Line Strings
Strings can be interpreted as multiline using the pipe (`|`) character. Strings can be interpreted as multi-line using the pipe (`|`) character.
```yaml ```yaml
message: | message: |
this is this is
a real multiline a real multi-line
message message
``` ```
This would be read as `this is\na real multiline\nmessage` This would be read as `this is\na real multi-line\nmessage`
## Comments ## Comments
YAML file also supports comments, unlike JSON. A comment starts with #. YAML file also supports comments, unlike JSON. A comment starts with #.
```yaml ```yaml
# Strats with a top level Dictionary with keys `libraries` and `settings` # Starts with a top level Dictionary with keys `libraries` and `settings`
libraries: # Value is a Dictionary with keys `Movies` and `TV Shows` libraries: # Value is a Dictionary with keys `Movies` and `TV Shows`
``` ```

@ -4,4 +4,4 @@
See the [Installation Page](../kometa/install/overview.md) for info on how to install Kometa. See the [Installation Page](../kometa/install/overview.md) for info on how to install Kometa.
This guide is assuming you know how to run Kometwith the `--run` run command or the `KOMETA_RUN` environment variable to perform immediate runs This guide is assuming you know how to run Kometa with the `--run` run command or the `KOMETA_RUN` environment variable to perform immediate runs

@ -65,7 +65,7 @@ Now let's use the `sort_title` attribute to reorder these collections slightly
sort_title: "%&'Collection 2" sort_title: "%&'Collection 2"
``` ```
You will often see users using sort titles such as `+++++++_My Collection` or `!010_My Collection` in order to force a specific order of collections. Whilst it may not seem logical at a glance, the ASCII sort order allows a lot of fleixibility for power users to be able to tailor the ordering of collections. You will often see users using sort titles such as `+++++++_My Collection` or `!010_My Collection` in order to force a specific order of collections. Whilst it may not seem logical at a glance, the ASCII sort order allows a lot of flexibility for power users to be able to tailor the ordering of collections.
### Kometa Default Collection Sorting ### Kometa Default Collection Sorting

@ -1,5 +1,23 @@
JSON schemas for Kometa YAML files JSON schemas for Kometa YAML files
How to:
Add this as the first line in your `config.yml`:
```
# yaml-language-server: $schema=https://raw.githubusercontent.com/Kometa-Team/Kometa/nightly/json-schema/config-schema.json
```
[change `nightly` to `develop`, or `master` if you wish]
Then open your config file in an editor that supports the use of JSON schema.
For example, VS Code with the Red Hat YAML extension.
This will give you context-sensitive hints and auto-complete for much of the Kometa `config.yml`
![image](https://github.com/Kometa-Team/Kometa/assets/3865541/62133e59-ed12-4764-a4da-23595824d4da)
![image](https://github.com/Kometa-Team/Kometa/assets/3865541/06fbca9b-f0ad-4c20-8cf0-12d6c259c838)
limitations: limitations:
- template variables not cased for specific default file - template variables not cased for specific default file

@ -895,6 +895,16 @@
"type": "string" "type": "string"
} }
] ]
},
"overlay_artwork_filetype": {
"description": "Used to control the filetype used with overlay images.",
"enum": ["jpg", "png", "webp_lossy", "webp_lossless"]
},
"overlay_artwork_quality": {
"description": "Used to control the JPG or Lossy WEBP quality used with overlay images.",
"type": "integer",
"minimum": 1,
"maximum": 100
} }
}, },
"required": [ "required": [
@ -938,6 +948,31 @@
], ],
"title": "trakt" "title": "trakt"
}, },
"pmm-lib-collection-path": {
"type": "object",
"additionalProperties": false,
"properties": {
"pmm": {
"type": "string",
"enum": ["actor", "anilist","aspect","audio_language","bafta","based","basic","berlinale","cannes","cesar","choice","collectionless","content_rating_au","content_rating_cs","content_rating_de","content_rating_nz","content_rating_mal","content_rating_uk","content_rating_us","continent","country","decade","director","emmy","flixpatrol","franchise","genre","golden","imdb","myanimelist","network","nfr","oscars","other_chart","pca","producer","razzie","region","resolution","sag","seasonal","separator_award","separator_chart","spirit","streaming","studio","subtitle_language","sundance","tautulli","tiff","tmdb","trakt","universe","venice","writer","year"]
},
"schedule": {
"type": "string"
},
"asset_directory": {
"oneOf": [
{ "type": "string"},
{ "type": "array", "uniqueItems": true, "items": {"type": "string" }}
]
},
"template_variables": {
"$ref": "#/definitions/template-variables-collections"
}
},
"required": [
"pmm"
]
},
"lib-collection-path": { "lib-collection-path": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
@ -1243,6 +1278,9 @@
"items": { "items": {
"anyOf": [ "anyOf": [
{ {
"$ref": "#/definitions/pmm-lib-collection-path",
"deprecated": true
}, {
"$ref": "#/definitions/lib-collection-path" "$ref": "#/definitions/lib-collection-path"
}, { }, {
"$ref": "#/definitions/file-path" "$ref": "#/definitions/file-path"
@ -1287,6 +1325,8 @@
"items": { "items": {
"anyOf": [ "anyOf": [
{ {
"$ref": "#/definitions/pmm-lib-collection-path"
}, {
"$ref": "#/definitions/lib-collection-path" "$ref": "#/definitions/lib-collection-path"
}, { }, {
"$ref": "#/definitions/file-path" "$ref": "#/definitions/file-path"
@ -1389,30 +1429,142 @@
"type": "string", "type": "string",
"enum": ["tmdb","tvdb","omdb","mdb","anidb","mal","lock","unlock","remove","reset"] "enum": ["tmdb","tvdb","omdb","mdb","anidb","mal","lock","unlock","remove","reset"]
}, },
"mass_added_at_update": {
"type": "string",
"enum": ["tmdb","tvdb","omdb","mdb","anidb","mal","lock","unlock","remove","reset"]
},
"mass_audience_rating_update": { "mass_audience_rating_update": {
"anyOf": [
{
"type": "number"
},
{
"type": "string", "type": "string",
"enum": ["tmdb","imdb","trakt_user","omdb","mdb","mdb_average","mdb_imdb","mdb_metacritic","mdb_metacriticuser","mdb_trakt","mdb_tomatoes","mdb_tomatoesaudience","mdb_tmdb","mdb_letterboxd","mdb_myanimelist","anidb_rating","anidb_average","anidb_score","mal","lock","unlock","remove","reset"] "enum": ["tmdb","imdb","trakt_user","omdb","mdb","mdb_average","mdb_imdb","mdb_metacritic","mdb_metacriticuser","mdb_trakt","mdb_tomatoes","mdb_tomatoesaudience","mdb_tmdb","mdb_letterboxd","mdb_myanimelist","anidb_rating","anidb_average","anidb_score","mal","lock","unlock","remove","reset"]
}, },
{
"type": "array",
"uniqueItems": true,
"items":
{
"anyOf": [
{"enum": ["tmdb","imdb","trakt_user","omdb","mdb","mdb_average","mdb_imdb","mdb_metacritic","mdb_metacriticuser","mdb_trakt","mdb_tomatoes","mdb_tomatoesaudience","mdb_tmdb","mdb_letterboxd","mdb_myanimelist","anidb_rating","anidb_average","anidb_score","mal","lock","unlock","remove","reset"]},
{"type": "number"}
]
}
}
]
},
"mass_critic_rating_update": { "mass_critic_rating_update": {
"anyOf": [
{
"type": "number"
},
{
"type": "string", "type": "string",
"enum": ["tmdb","imdb","trakt_user","omdb","mdb","mdb_average","mdb_imdb","mdb_metacritic","mdb_metacriticuser","mdb_trakt","mdb_tomatoes","mdb_tomatoesaudience","mdb_tmdb","mdb_letterboxd","mdb_myanimelist","anidb_rating","anidb_average","anidb_score","mal","lock","unlock","remove","reset"] "enum": ["tmdb","imdb","trakt_user","omdb","mdb","mdb_average","mdb_imdb","mdb_metacritic","mdb_metacriticuser","mdb_trakt","mdb_tomatoes","mdb_tomatoesaudience","mdb_tmdb","mdb_letterboxd","mdb_myanimelist","anidb_rating","anidb_average","anidb_score","mal","lock","unlock","remove","reset"]
}, },
{
"type": "array",
"uniqueItems": true,
"items":
{
"anyOf": [
{"enum": ["tmdb","imdb","trakt_user","omdb","mdb","mdb_average","mdb_imdb","mdb_metacritic","mdb_metacriticuser","mdb_trakt","mdb_tomatoes","mdb_tomatoesaudience","mdb_tmdb","mdb_letterboxd","mdb_myanimelist","anidb_rating","anidb_average","anidb_score","mal","lock","unlock","remove","reset"]},
{"type": "number"}
]
}
}
]
},
"mass_user_rating_update": { "mass_user_rating_update": {
"anyOf": [
{
"type": "number"
},
{
"type": "string", "type": "string",
"enum": ["tmdb","imdb","trakt_user","omdb","mdb","mdb_average","mdb_imdb","mdb_metacritic","mdb_metacriticuser","mdb_trakt","mdb_tomatoes","mdb_tomatoesaudience","mdb_tmdb","mdb_letterboxd","mdb_myanimelist","anidb_rating","anidb_average","anidb_score","mal","lock","unlock","remove","reset"] "enum": ["tmdb","imdb","trakt_user","omdb","mdb","mdb_average","mdb_imdb","mdb_metacritic","mdb_metacriticuser","mdb_trakt","mdb_tomatoes","mdb_tomatoesaudience","mdb_tmdb","mdb_letterboxd","mdb_myanimelist","anidb_rating","anidb_average","anidb_score","mal","lock","unlock","remove","reset"]
}, },
{
"type": "array",
"uniqueItems": true,
"items":
{
"anyOf": [
{"enum": ["tmdb","imdb","trakt_user","omdb","mdb","mdb_average","mdb_imdb","mdb_metacritic","mdb_metacriticuser","mdb_trakt","mdb_tomatoes","mdb_tomatoesaudience","mdb_tmdb","mdb_letterboxd","mdb_myanimelist","anidb_rating","anidb_average","anidb_score","mal","lock","unlock","remove","reset"]},
{"type": "number"}
]
}
}
]
},
"mass_episode_audience_rating_update": { "mass_episode_audience_rating_update": {
"anyOf": [
{
"type": "number"
},
{
"type": "string", "type": "string",
"enum": ["tmdb","imdb","lock","remove","reset","unlock"] "enum": ["tmdb","imdb","lock","remove","reset","unlock"]
}, },
{
"type": "array",
"uniqueItems": true,
"items":
{
"anyOf": [
{"enum": ["tmdb","imdb","lock","remove","reset","unlock"]},
{"type": "number"}
]
}
}
]
},
"mass_episode_critic_rating_update": { "mass_episode_critic_rating_update": {
"anyOf": [
{
"type": "number"
},
{
"type": "string", "type": "string",
"enum": ["tmdb","imdb","lock","remove","reset","unlock"] "enum": ["tmdb","imdb","lock","remove","reset","unlock"]
}, },
{
"type": "array",
"uniqueItems": true,
"items":
{
"anyOf": [
{"enum": ["tmdb","imdb","lock","remove","reset","unlock"]},
{"type": "number"}
]
}
}
]
},
"mass_episode_user_rating_update": { "mass_episode_user_rating_update": {
"anyOf": [
{
"type": "number"
},
{
"type": "string", "type": "string",
"enum": ["tmdb","imdb","lock","remove","reset","unlock"] "enum": ["tmdb","imdb","lock","remove","reset","unlock"]
}, },
{
"type": "array",
"uniqueItems": true,
"items":
{
"anyOf": [
{"enum": ["tmdb","imdb","lock","remove","reset","unlock"]},
{"type": "number"}
]
}
}
]
},
"mass_poster_update": { "mass_poster_update": {
"type": "string", "type": "string",
"enum": ["tmdb","plex","lock","unlock"] "enum": ["tmdb","plex","lock","unlock"]
@ -1609,8 +1761,6 @@
"vertical_position": { "type": "string", "enum": ["top","top2","top3","center","center_top","center_bottom","bottom","bottom2","bottom3"] } "vertical_position": { "type": "string", "enum": ["top","top2","top3","center","center_top","center_bottom","bottom","bottom2","bottom3"] }
}, },
"patternProperties": { "patternProperties": {
"^back_color_.*$": { "type": "string", "pattern": "^\\#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$" },
"^font_color_.*$": { "type": "string", "pattern": "^\\#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$" },
"^country_.*$": { "type": "string", "pattern": "^[A-Z]{2}$" }, "^country_.*$": { "type": "string", "pattern": "^[A-Z]{2}$" },
"^file_.*$": { "type": "string" }, "^file_.*$": { "type": "string" },
"^git_.*$": { "type": "string" }, "^git_.*$": { "type": "string" },
@ -1623,7 +1773,25 @@
"^time_window_.*$": { "type": "string", "enum": ["today","yesterday","this_week","last_week","this_month","last_month","this_year","last_year"] }, "^time_window_.*$": { "type": "string", "enum": ["today","yesterday","this_week","last_week","this_month","last_month","this_year","last_year"] },
"^url_.*$": { "type": "string", "format": "uri", "pattern": "^(https?)://" }, "^url_.*$": { "type": "string", "format": "uri", "pattern": "^(https?)://" },
"^use_.*$": { "type": "boolean" }, "^use_.*$": { "type": "boolean" },
"^weight_.*$": { "type": "integer" } "^weight_.*$": { "type": "integer" },
"^font_.*$": { "type": "string" },
"^font_color_.*$": { "type": "string", "pattern": "^\\#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$" },
"^font_size_.*$": { "type": "integer", "exclusiveMinimum": 0 },
"^font_style_.*$": { "type": "string", "enum": ["Any","Italic","Normal","Oblique"] },
"^horizontal_align_.*$": { "type": "string", "enum": ["left","center","right"] },
"^horizontal_offset_.*$": { "type": "integer", "minimum": 0 },
"^vertical_align_.*$": { "type": "string", "enum": ["top","center","bottom"] },
"^vertical_offset_.*$": { "type": "integer", "minimum": 0 },
"^stroke_color_.*$": { "type": "string", "pattern": "^\\#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$" },
"^stroke_width_.*$": { "type": "integer", "exclusiveMinimum": 0 },
"^back_align_.*$": { "type": "string", "enum": ["left","right","center","top","bottom"] },
"^back_color_.*$": { "type": "string", "pattern": "^\\#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$" },
"^back_height_.*$": { "type": "integer", "exclusiveMinimum": 0 },
"^back_line_color_.*$": { "type": "string", "pattern": "^\\#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$" },
"^back_line_width_.*$": { "type": "integer", "exclusiveMinimum": 0 },
"^back_padding_.*$": { "type": "integer", "exclusiveMinimum": 0 },
"^back_radius_.*$": { "type": "integer", "exclusiveMinimum": 0 },
"^back_width_.*$": { "type": "integer", "exclusiveMinimum": 0 }
}, },
"required": [ "required": [
], ],

@ -23,7 +23,7 @@ libraries:
- url: https://foo.bar.com/something.yml - url: https://foo.bar.com/something.yml
- git: bing/bang/boing - git: bing/bang/boing
- repo: bing - repo: bing
- default: cannes - pmm: cannes
- default: choice - default: choice
- default: emmy - default: emmy
- default: spirit - default: spirit
@ -118,6 +118,14 @@ libraries:
asset_directory: config/assets asset_directory: config/assets
operations: operations:
mass_audience_rating_update:
- mdb_average
- imdb
- 2.0
mass_episode_audience_rating_update:
- tmdb
- imdb
- 2.0
split_duplicates: false split_duplicates: false
assets_for_all: false assets_for_all: false
genre_mapper: genre_mapper:
@ -432,6 +440,8 @@ settings:
playlist_report: false playlist_report: false
verify_ssl: true verify_ssl: true
custom_repo: custom_repo:
overlay_artwork_filetype: jpg
overlay_artwork_quality: 72
webhooks: # Can be individually specified per library as well webhooks: # Can be individually specified per library as well
error: error:
version: version:

@ -9,16 +9,35 @@ if sys.version_info[0] != 3 or sys.version_info[1] < 8:
sys.exit(0) sys.exit(0)
try: try:
import plexapi, psutil, requests, schedule import arrapi, lxml, pathvalidate, PIL, plexapi, psutil, dateutil, requests, ruamel.yaml, schedule, setuptools, tmdbapis
from dotenv import load_dotenv from dotenv import load_dotenv, version as dotenv_version
from PIL import ImageFile from PIL import ImageFile
from plexapi import server from plexapi import server
from plexapi.exceptions import NotFound from plexapi.exceptions import NotFound
from plexapi.video import Show, Season from plexapi.video import Show, Season
except (ModuleNotFoundError, ImportError): except (ModuleNotFoundError, ImportError) as ie:
print("Requirements Error: Requirements are not installed") print(f"Requirements Error: Requirements are not installed ({ie})")
sys.exit(0) sys.exit(0)
system_versions = {
"arrapi": arrapi.__version__,
"GitPython": None,
"lxml": lxml.__version__,
"num2words": None,
"pathvalidate": pathvalidate.__version__,
"pillow": PIL.__version__,
"PlexAPI": plexapi.__version__,
"psutil": psutil.__version__,
"python-dotenv": dotenv_version.__version__,
"python-dateutil": dateutil.__version__, # noqa
"requests": requests.__version__,
"retrying": None,
"ruamel.yaml": ruamel.yaml.__version__,
"schedule": None,
"setuptools": setuptools.__version__,
"tmdbapis": tmdbapis.__version__
}
default_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config") default_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config")
load_dotenv(os.path.join(default_dir, ".env")) load_dotenv(os.path.join(default_dir, ".env"))
@ -141,6 +160,7 @@ plex_token = get_env("KOMETA_PLEX_TOKEN", plex_token)
env_secrets = [] env_secrets = []
for env_name, env_data in os.environ.items(): for env_name, env_data in os.environ.items():
if env_data is not None and str(env_data).strip():
if str(env_name).upper().startswith("KOMETA_") and str(env_name).upper() not in static_envs: if str(env_name).upper().startswith("KOMETA_") and str(env_name).upper() not in static_envs:
secret_args[str(env_name).lower()[7:].replace("_", "-")] = env_data secret_args[str(env_name).lower()[7:].replace("_", "-")] = env_data
elif str(env_name).upper().startswith("PMM_") and str(env_name).upper() not in static_envs: elif str(env_name).upper().startswith("PMM_") and str(env_name).upper() not in static_envs:
@ -151,6 +171,8 @@ for _, sv in secret_args.items():
run_arg = run_arg.replace(sv, "(redacted)") run_arg = run_arg.replace(sv, "(redacted)")
try: try:
import git # noqa
system_versions["GitPython"] = git.__version__
from git import Repo, InvalidGitRepositoryError # noqa from git import Repo, InvalidGitRepositoryError # noqa
try: try:
git_branch = Repo(path=".").head.ref.name # noqa git_branch = Repo(path=".").head.ref.name # noqa
@ -236,11 +258,11 @@ def start(attrs):
logger.add_main_handler() logger.add_main_handler()
logger.separator() logger.separator()
logger.info("") logger.info("")
logger.info_center(" __ ___ ______ .___ ___. _______ .___________. ___ ") logger.info_center(" __ ___ ______ ___ ___ _______ __________ ___ ")
logger.info_center("| |/ / / __ \\ | \\/ | | ____|| | / \\ ") logger.info_center("| |/ / / __ \\ | \\/ | | ____|| | / \\ ")
logger.info_center("| ' / | | | | | \\ / | | |__ `---| |----` / ^ \\ ") logger.info_center("| ' / | | | | | \\ / | | |__ `---| |---` / ^ \\ ")
logger.info_center("| < | | | | | |\\/| | | __| | | / /_\\ \\ ") logger.info_center("| < | | | | | |\\/| | | __| | | / /_\\ \\ ")
logger.info_center("| . \\ | `--' | | | | | | |____ | | / _____ \\ ") logger.info_center("| . \\ | `--` | | | | | | |____ | | / _____ \\ ")
logger.info_center("|__|\\__\\ \\______/ |__| |__| |_______| |__| /__/ \\__\\ ") logger.info_center("|__|\\__\\ \\______/ |__| |__| |_______| |__| /__/ \\__\\ ")
logger.info("") logger.info("")
if is_lxml: if is_lxml:
@ -256,18 +278,17 @@ def start(attrs):
new_version = latest_version[0] if latest_version and (version[1] != latest_version[1] or (version[2] and version[2] < latest_version[2])) else None new_version = latest_version[0] if latest_version and (version[1] != latest_version[1] or (version[2] and version[2] < latest_version[2])) else None
if new_version: if new_version:
logger.info(f" Newest Version: {new_version}") logger.info(f" Newest Version: {new_version}")
required_version = None logger.info(f" Platform: {platform.platform()}")
logger.info(f" Memory: {round(psutil.virtual_memory().total / (1024.0 ** 3))} GB")
if not is_docker and not is_linuxserver: if not is_docker and not is_linuxserver:
try: try:
with open(os.path.abspath(os.path.join(os.path.dirname(__file__), "requirements.txt")), "r") as file: with open(os.path.abspath(os.path.join(os.path.dirname(__file__), "requirements.txt")), "r") as file:
required_version = next(ln.strip()[9:] for ln in file.readlines() if ln.strip().startswith("PlexAPI==")) required_versions = {ln.split("==")[0]: ln.split("==")[1].strip() for ln in file.readlines()}
for req_name, sys_ver in system_versions.items():
if sys_ver and sys_ver != required_versions[req_name]:
logger.info(f" {req_name} version: {sys_ver} requires an update to: {required_versions[req_name]}")
except FileNotFoundError: except FileNotFoundError:
logger.error(" File Error: requirements.txt not found") logger.error(" File Error: requirements.txt not found")
logger.info(f" PlexAPI Version: {plexapi.VERSION}")
if required_version is not None and required_version != plexapi.VERSION:
logger.info(f" PlexAPI Requires an Update to Version: {required_version}")
logger.info(f" Platform: {platform.platform()}")
logger.info(f" Memory: {round(psutil.virtual_memory().total / (1024.0 ** 3))} GB")
if "time" in attrs and attrs["time"]: start_type = f"{attrs['time']} " if "time" in attrs and attrs["time"]: start_type = f"{attrs['time']} "
elif run_args["tests"]: start_type = "Test " elif run_args["tests"]: start_type = "Test "
elif "collections" in attrs and attrs["collections"]: start_type = "Collections " elif "collections" in attrs and attrs["collections"]: start_type = "Collections "

@ -58,7 +58,7 @@ plugins:
redirect_maps: redirect_maps:
'discord.md': 'https://kometa.wiki/en/nightly/link/' 'discord.md': 'https://kometa.wiki/en/nightly/link/'
'redact.md': 'https://regex101.com/r/DMo1DQ/latest' 'redact.md': 'https://regex101.com/r/DMo1DQ/latest'
'link.md': 'https://discord.gg/FNqqw5jRSz' 'link.md': 'https://discord.com/invite/kometa-822460010649878528'
'malauth.md': 'https://replit.com/@chazlarson/MALAuth' 'malauth.md': 'https://replit.com/@chazlarson/MALAuth'
'traktauth.md': 'https://replit.com/@chazlarson/TraktAuth' 'traktauth.md': 'https://replit.com/@chazlarson/TraktAuth'
- material-plausible - material-plausible
@ -133,7 +133,7 @@ nav:
- INSTALLATION: - INSTALLATION:
- Installing Kometa: kometa/install/overview.md - Installing Kometa: kometa/install/overview.md
- Docker Images: kometa/install/images.md - Docker Images: kometa/install/images.md
- Walkthroughs: &walkthroughs - Walkthroughs:
- Local (Win/Mac/Linux): kometa/install/local.md - Local (Win/Mac/Linux): kometa/install/local.md
- Docker: kometa/install/docker.md - Docker: kometa/install/docker.md
- unRAID: kometa/install/unraid.md - unRAID: kometa/install/unraid.md
@ -166,28 +166,34 @@ nav:
- CONFIGURATION FILE: - CONFIGURATION FILE:
- Overview: config/overview.md - Overview: config/overview.md
- STRUCTURE: - STRUCTURE:
- LIBRARIES:
- Library Attributes: config/libraries.md - Library Attributes: config/libraries.md
- File Blocks: config/files.md - File Blocks: config/files.md
- Scheduling Parts: config/schedule.md
- Library Operations: config/operations.md - Library Operations: config/operations.md
- PLAYLISTS:
- Playlist Files: config/playlists.md - Playlist Files: config/playlists.md
- SETTINGS:
- Settings: config/settings.md - Settings: config/settings.md
- WEBHOOKS:
- Webhooks: config/webhooks.md - Webhooks: config/webhooks.md
- CONNECTORS: - REQUIRED CONNECTIONS:
- Plex: config/plex.md - Plex: config/plex.md
- TMDb: config/tmdb.md - TMDb: config/tmdb.md
- Trakt: config/trakt.md - OPTIONAL CONNECTIONS:
- Radarr: config/radarr.md
- Sonarr: config/sonarr.md
- Notifiarr: config/notifiarr.md
- Gotify: config/gotify.md
- Tautulli: config/tautulli.md - Tautulli: config/tautulli.md
- Github: config/github.md - Github: config/github.md
- MdbList: config/mdblist.md
- OMDb: config/omdb.md - OMDb: config/omdb.md
- MDBList: config/mdblist.md
- Notifiarr: config/notifiarr.md
- Gotify: config/gotify.md
- AniDB: config/anidb.md - AniDB: config/anidb.md
- Radarr: config/radarr.md
- Sonarr: config/sonarr.md
- Trakt: config/trakt.md
- MyAnimeList: config/myanimelist.md - MyAnimeList: config/myanimelist.md
- Trakt and MyAnimeList Authentication: config/auth.md - Trakt and MyAnimeList Authentication: config/auth.md
- OTHER:
- Scheduling Parts: config/schedule.md
- KOMETA DEFAULTS: - KOMETA DEFAULTS:
- Defaults Usage Guide: defaults/guide.md - Defaults Usage Guide: defaults/guide.md
- Defaults Files: defaults/files.md - Defaults Files: defaults/files.md
@ -321,7 +327,7 @@ nav:
- Tautulli Builders: files/builders/tautulli.md - Tautulli Builders: files/builders/tautulli.md
- Radarr Builders: files/builders/radarr.md - Radarr Builders: files/builders/radarr.md
- Sonarr Builders: files/builders/sonarr.md - Sonarr Builders: files/builders/sonarr.md
- MdbList Builders: files/builders/mdblist.md - MDBList Builders: files/builders/mdblist.md
- Letterboxd Builders: files/builders/letterboxd.md - Letterboxd Builders: files/builders/letterboxd.md
- ICheckMovies Builders: files/builders/icheckmovies.md - ICheckMovies Builders: files/builders/icheckmovies.md
- BoxOfficeMojo Builders: files/builders/mojo.md - BoxOfficeMojo Builders: files/builders/mojo.md

@ -298,7 +298,7 @@ class AniList:
logger.info(f"Processing AniList Relations: ({data}) {name} ({len(anilist_ids)} Anime)") logger.info(f"Processing AniList Relations: ({data}) {name} ({len(anilist_ids)} Anime)")
elif method == "anilist_userlist": elif method == "anilist_userlist":
anilist_ids = self._userlist(data["username"], data["list_name"], data["sort_by"], data["score"]) anilist_ids = self._userlist(data["username"], data["list_name"], data["sort_by"], data["score"])
logger.info(f"Processing AniList Userlist: {data['list_name']} from {data['username']} sorted by {pretty_user[data['sort_by']]}") logger.info(f"Processing AniList UserList: {data['list_name']} from {data['username']} sorted by {pretty_user[data['sort_by']]}")
else: else:
if method == "anilist_popular": if method == "anilist_popular":
data = {"limit": data, "popularity.gt": 3, "sort_by": "popular"} data = {"limit": data, "popularity.gt": 3, "sort_by": "popular"}

@ -370,7 +370,7 @@ class CollectionBuilder:
trans_summary = apply_vars(trans_summary, trans_vars, trans_key, self.limit) trans_summary = apply_vars(trans_summary, trans_vars, trans_key, self.limit)
delete_cols = [] delete_cols = []
if (self.name and self.name != en_name) or (not self.name and en_name != trans_name): if (self.name and self.name != en_name) or (not self.name and trans_name and en_name != trans_name):
delete_cols.append(en_name) delete_cols.append(en_name)
if self.name and self.name != trans_name and en_name != trans_name: if self.name and self.name != trans_name and en_name != trans_name:
delete_cols.append(trans_name) delete_cols.append(trans_name)
@ -390,7 +390,7 @@ class CollectionBuilder:
if not self.name: if not self.name:
self.name = trans_name if trans_name else en_name self.name = trans_name if trans_name else en_name
logger.info(self.name) logger.info(f"Final Name: {self.name}")
if en_summary or trans_summary: if en_summary or trans_summary:
self.summaries["translation"] = trans_summary if trans_summary else en_summary self.summaries["translation"] = trans_summary if trans_summary else en_summary
@ -1965,7 +1965,7 @@ class CollectionBuilder:
self.builders.append((method_name, util.parse(self.Type, method_name, method_data, "bool"))) self.builders.append((method_name, util.parse(self.Type, method_name, method_data, "bool")))
def _mdblist(self, method_name, method_data): def _mdblist(self, method_name, method_data):
for mdb_dict in self.config.Mdblist.validate_mdblist_lists(self.Type, method_data): for mdb_dict in self.config.MDBList.validate_mdblist_lists(self.Type, method_data):
self.builders.append((method_name, mdb_dict)) self.builders.append((method_name, mdb_dict))
def _tautulli(self, method_name, method_data): def _tautulli(self, method_name, method_data):
@ -2214,7 +2214,7 @@ class CollectionBuilder:
elif "mojo" in method: elif "mojo" in method:
ids = self.config.BoxOfficeMojo.get_imdb_ids(method, value) ids = self.config.BoxOfficeMojo.get_imdb_ids(method, value)
elif "mdblist" in method: elif "mdblist" in method:
ids = self.config.Mdblist.get_tmdb_ids(method, value, self.library.is_movie if not self.playlist else None) ids = self.config.MDBList.get_tmdb_ids(method, value, self.library.is_movie if not self.playlist else None)
elif "tmdb" in method: elif "tmdb" in method:
ids = self.config.TMDb.get_tmdb_ids(method, value, self.library.is_movie, self.tmdb_region) ids = self.config.TMDb.get_tmdb_ids(method, value, self.library.is_movie, self.tmdb_region)
elif "trakt" in method: elif "trakt" in method:

@ -22,7 +22,7 @@ from modules.plex import Plex
from modules.radarr import Radarr from modules.radarr import Radarr
from modules.sonarr import Sonarr from modules.sonarr import Sonarr
from modules.reciperr import Reciperr from modules.reciperr import Reciperr
from modules.mdblist import Mdblist from modules.mdblist import MDBList
from modules.tautulli import Tautulli from modules.tautulli import Tautulli
from modules.tmdb import TMDb from modules.tmdb import TMDb
from modules.trakt import Trakt from modules.trakt import Trakt
@ -41,6 +41,12 @@ run_order_options = {
"operations": "Represents Operations Updates" "operations": "Represents Operations Updates"
} }
sync_modes = {"append": "Only Add Items to the Collection or Playlist", "sync": "Add & Remove Items from the Collection or Playlist"} sync_modes = {"append": "Only Add Items to the Collection or Playlist", "sync": "Add & Remove Items from the Collection or Playlist"}
filetype_list = {
"jpg": "Use JPG files for saving Overlays",
"png": "Use PNG files for saving Overlays",
"webp_lossy": "Use Lossy WEBP files for saving Overlays",
"webp_lossless": "Use Lossless WEBP files for saving Overlays"
}
imdb_label_options = { imdb_label_options = {
"remove": "Remove All IMDb Parental Labels", "remove": "Remove All IMDb Parental Labels",
"none": "Add IMDb Parental Labels for None, Mild, Moderate, or Severe", "none": "Add IMDb Parental Labels for None, Mild, Moderate, or Severe",
@ -58,9 +64,9 @@ mass_genre_options = {
} }
mass_content_options = { mass_content_options = {
"lock": "Lock Rating", "unlock": "Unlock Rating", "remove": "Remove and Lock Rating", "reset": "Remove and Unlock Rating", "lock": "Lock Rating", "unlock": "Unlock Rating", "remove": "Remove and Lock Rating", "reset": "Remove and Unlock Rating",
"omdb": "Use IMDb Rating through OMDb", "mdb": "Use MdbList Rating", "omdb": "Use IMDb Rating through OMDb", "mdb": "Use MDBList Rating",
"mdb_commonsense": "Use Commonsense Rating through MDbList", "mdb_commonsense0": "Use Commonsense Rating with Zero Padding through MDbList", "mdb_commonsense": "Use Commonsense Rating through MDBList", "mdb_commonsense0": "Use Commonsense Rating with Zero Padding through MDBList",
"mdb_age_rating": "Use MDbList Age Rating", "mdb_age_rating0": "Use MDbList Age Rating with Zero Padding", "mdb_age_rating": "Use MDBList Age Rating", "mdb_age_rating0": "Use MDBList Age Rating with Zero Padding",
"mal": "Use MyAnimeList Rating" "mal": "Use MyAnimeList Rating"
} }
mass_collection_content_options = { mass_collection_content_options = {
@ -85,7 +91,7 @@ mass_original_title_options = {
} }
mass_available_options = { mass_available_options = {
"lock": "Lock Originally Available", "unlock": "Unlock Originally Available", "remove": "Remove and Lock Originally Available", "reset": "Remove and Unlock Originally Available", "lock": "Lock Originally Available", "unlock": "Unlock Originally Available", "remove": "Remove and Lock Originally Available", "reset": "Remove and Unlock Originally Available",
"tmdb": "Use TMDb Release", "omdb": "Use IMDb Release through OMDb", "mdb": "Use MdbList Release", "mdb_digital": "Use MdbList Digital Release", "tvdb": "Use TVDb Release", "tmdb": "Use TMDb Release", "omdb": "Use IMDb Release through OMDb", "mdb": "Use MDBList Release", "mdb_digital": "Use MDBList Digital Release", "tvdb": "Use TVDb Release",
"anidb": "Use AniDB Release", "mal": "Use MyAnimeList Release" "anidb": "Use AniDB Release", "mal": "Use MyAnimeList Release"
} }
mass_image_options = { mass_image_options = {
@ -104,17 +110,17 @@ mass_rating_options = {
"imdb": "Use IMDb Rating", "imdb": "Use IMDb Rating",
"trakt_user": "Use Trakt User Rating", "trakt_user": "Use Trakt User Rating",
"omdb": "Use IMDb Rating through OMDb", "omdb": "Use IMDb Rating through OMDb",
"mdb": "Use MdbList Score", "mdb": "Use MDBList Score",
"mdb_average": "Use MdbList Average Score", "mdb_average": "Use MDBList Average Score",
"mdb_imdb": "Use IMDb Rating through MDbList", "mdb_imdb": "Use IMDb Rating through MDBList",
"mdb_metacritic": "Use Metacritic Rating through MDbList", "mdb_metacritic": "Use Metacritic Rating through MDBList",
"mdb_metacriticuser": "Use Metacritic User Rating through MDbList", "mdb_metacriticuser": "Use Metacritic User Rating through MDBList",
"mdb_trakt": "Use Trakt Rating through MDbList", "mdb_trakt": "Use Trakt Rating through MDBList",
"mdb_tomatoes": "Use Rotten Tomatoes Rating through MDbList", "mdb_tomatoes": "Use Rotten Tomatoes Rating through MDBList",
"mdb_tomatoesaudience": "Use Rotten Tomatoes Audience Rating through MDbList", "mdb_tomatoesaudience": "Use Rotten Tomatoes Audience Rating through MDBList",
"mdb_tmdb": "Use TMDb Rating through MDbList", "mdb_tmdb": "Use TMDb Rating through MDBList",
"mdb_letterboxd": "Use Letterboxd Rating through MDbList", "mdb_letterboxd": "Use Letterboxd Rating through MDBList",
"mdb_myanimelist": "Use MyAnimeList Rating through MDbList", "mdb_myanimelist": "Use MyAnimeList Rating through MDBList",
"anidb_rating": "Use AniDB Rating", "anidb_rating": "Use AniDB Rating",
"anidb_average": "Use AniDB Average", "anidb_average": "Use AniDB Average",
"anidb_score": "Use AniDB Review Dcore", "anidb_score": "Use AniDB Review Dcore",
@ -129,8 +135,8 @@ library_operations = {
"mass_audience_rating_update": mass_rating_options, "mass_episode_audience_rating_update": mass_episode_rating_options, "mass_audience_rating_update": mass_rating_options, "mass_episode_audience_rating_update": mass_episode_rating_options,
"mass_critic_rating_update": mass_rating_options, "mass_episode_critic_rating_update": mass_episode_rating_options, "mass_critic_rating_update": mass_rating_options, "mass_episode_critic_rating_update": mass_episode_rating_options,
"mass_user_rating_update": mass_rating_options, "mass_episode_user_rating_update": mass_episode_rating_options, "mass_user_rating_update": mass_rating_options, "mass_episode_user_rating_update": mass_episode_rating_options,
"mass_original_title_update": mass_original_title_options, "mass_originally_available_update": mass_available_options, "mass_original_title_update": mass_original_title_options, "mass_imdb_parental_labels": imdb_label_options,
"mass_imdb_parental_labels": imdb_label_options, "mass_originally_available_update": mass_available_options, "mass_added_at_update": mass_available_options,
"mass_collection_mode": "mass_collection_mode", "mass_poster_update": "dict", "mass_background_update": "dict", "mass_collection_mode": "mass_collection_mode", "mass_poster_update": "dict", "mass_background_update": "dict",
"metadata_backup": "dict", "delete_collections": "dict", "genre_mapper": "dict", "content_rating_mapper": "dict", "metadata_backup": "dict", "delete_collections": "dict", "genre_mapper": "dict", "content_rating_mapper": "dict",
} }
@ -340,7 +346,7 @@ class ConfigFile:
if self.secrets: if self.secrets:
check_next(self.data) check_next(self.data)
def check_for_attribute(data, attribute, parent=None, test_list=None, default=None, do_print=True, default_is_none=False, req_default=False, var_type="str", throw=False, save=True, int_min=0): def check_for_attribute(data, attribute, parent=None, test_list=None, translations=None, default=None, do_print=True, default_is_none=False, req_default=False, var_type="str", throw=False, save=True, int_min=0, int_max=None):
endline = "" endline = ""
if parent is not None: if parent is not None:
if data and parent in data: if data and parent in data:
@ -349,6 +355,9 @@ class ConfigFile:
data = None data = None
do_print = False do_print = False
save = False save = False
final_value = data[attribute] if data and attribute in data else None
if translations and final_value in translations:
final_value = translations[final_value]
if self.read_only: if self.read_only:
save = False save = False
text = f"{attribute} attribute" if parent is None else f"{parent} sub-attribute {attribute}" text = f"{attribute} attribute" if parent is None else f"{parent} sub-attribute {attribute}"
@ -362,26 +371,27 @@ class ConfigFile:
else: endline = "" else: endline = ""
yaml.save() yaml.save()
if default_is_none and var_type in ["list", "int_list", "lower_list", "list_path"]: return default if default else [] if default_is_none and var_type in ["list", "int_list", "lower_list", "list_path"]: return default if default else []
elif data[attribute] is None: elif final_value is None:
if default_is_none and var_type in ["list", "int_list", "lower_list", "list_path"]: return default if default else [] if default_is_none and var_type in ["list", "int_list", "lower_list", "list_path"]: return default if default else []
elif default_is_none: return None elif default_is_none: return None
else: message = f"{text} is blank" else: message = f"{text} is blank"
elif var_type == "url": elif var_type == "url":
if data[attribute].endswith(("\\", "/")): return data[attribute][:-1] if final_value.endswith(("\\", "/")): return final_value[:-1]
else: return data[attribute] else: return final_value
elif var_type == "bool": elif var_type == "bool":
if isinstance(data[attribute], bool): return data[attribute] if isinstance(final_value, bool): return final_value
else: message = f"{text} must be either true or false" else: message = f"{text} must be either true or false"
elif var_type == "int": elif var_type == "int":
if isinstance(data[attribute], bool): message = f"{text} must an integer >= {int_min}" if isinstance(final_value, int) and final_value >= int_min and (not int_max or final_value <= int_max):
elif isinstance(data[attribute], int) and data[attribute] >= int_min: return data[attribute] return final_value
else: message = f"{text} must an integer >= {int_min}" else:
message = f"{text} must an integer greater than or equal to {int_min}{f' and less than or equal to {int_max}'}"
elif var_type == "path": elif var_type == "path":
if os.path.exists(os.path.abspath(data[attribute])): return data[attribute] if os.path.exists(os.path.abspath(final_value)): return final_value
else: message = f"Path {os.path.abspath(data[attribute])} does not exist" else: message = f"Path {os.path.abspath(final_value)} does not exist"
elif var_type in ["list", "lower_list", "int_list"]: elif var_type in ["list", "lower_list", "int_list"]:
output_list = [] output_list = []
for output_item in util.get_list(data[attribute], lower=var_type == "lower_list", split=var_type != "list", int_list=var_type == "int_list"): for output_item in util.get_list(final_value, lower=var_type == "lower_list", split=var_type != "list", int_list=var_type == "int_list"):
if output_item not in output_list: if output_item not in output_list:
output_list.append(output_item) output_list.append(output_item)
failed_items = [o for o in output_list if o not in test_list] if test_list else [] failed_items = [o for o in output_list if o not in test_list] if test_list else []
@ -392,7 +402,7 @@ class ConfigFile:
elif var_type == "list_path": elif var_type == "list_path":
temp_list = [] temp_list = []
warning_message = "" warning_message = ""
for p in util.get_list(data[attribute], split=False): for p in util.get_list(final_value, split=False):
if os.path.exists(os.path.abspath(p)): if os.path.exists(os.path.abspath(p)):
temp_list.append(p) temp_list.append(p)
else: else:
@ -403,13 +413,13 @@ class ConfigFile:
logger.warning(warning_message) logger.warning(warning_message)
if len(temp_list) > 0: return temp_list if len(temp_list) > 0: return temp_list
else: message = "No Paths exist" else: message = "No Paths exist"
elif test_list is None or data[attribute] in test_list: return data[attribute] elif test_list is None or final_value in test_list: return final_value
else: message = f"{text}: {data[attribute]} is an invalid input" else: message = f"{text}: {final_value} is an invalid input"
if var_type == "path" and default and os.path.exists(os.path.abspath(default)): if var_type == "path" and default and os.path.exists(os.path.abspath(default)):
return default return default
elif var_type == "path" and default: elif var_type == "path" and default:
if data and attribute in data and data[attribute]: if final_value:
message = f"neither {data[attribute]} or the default path {default} could be found" message = f"neither {final_value} or the default path {default} could be found"
else: else:
message = f"no {text} found and the default path {default} could not be found" message = f"no {text} found and the default path {default} could not be found"
default = None default = None
@ -430,7 +440,7 @@ class ConfigFile:
raise Failed(f"Config Error: {message}") raise Failed(f"Config Error: {message}")
if do_print: if do_print:
logger.warning(f"Config Warning: {message}") logger.warning(f"Config Warning: {message}")
if data and attribute in data and data[attribute] and test_list is not None and data[attribute] not in test_list: if final_value and test_list is not None and final_value not in test_list:
logger.warning(options) logger.warning(options)
return default return default
@ -472,6 +482,8 @@ class ConfigFile:
"playlist_report": check_for_attribute(self.data, "playlist_report", parent="settings", var_type="bool", default=True), "playlist_report": check_for_attribute(self.data, "playlist_report", parent="settings", var_type="bool", default=True),
"verify_ssl": check_for_attribute(self.data, "verify_ssl", parent="settings", var_type="bool", default=True), "verify_ssl": check_for_attribute(self.data, "verify_ssl", parent="settings", var_type="bool", default=True),
"custom_repo": check_for_attribute(self.data, "custom_repo", parent="settings", default_is_none=True), "custom_repo": check_for_attribute(self.data, "custom_repo", parent="settings", default_is_none=True),
"overlay_artwork_filetype": check_for_attribute(self.data, "overlay_artwork_filetype", parent="settings", test_list=filetype_list, translations={"webp": "webp_lossy"}, default="jpg"),
"overlay_artwork_quality": check_for_attribute(self.data, "overlay_artwork_quality", parent="settings", var_type="int", default_is_none=True, int_min=1, int_max=100),
"assets_for_all": check_for_attribute(self.data, "assets_for_all", parent="settings", var_type="bool", default=False, save=False, do_print=False) "assets_for_all": check_for_attribute(self.data, "assets_for_all", parent="settings", var_type="bool", default=False, save=False, do_print=False)
} }
self.custom_repo = None self.custom_repo = None
@ -616,21 +628,21 @@ class ConfigFile:
logger.separator() logger.separator()
self.Mdblist = Mdblist(self) self.MDBList = MDBList(self)
if "mdblist" in self.data: if "mdblist" in self.data:
logger.info("Connecting to Mdblist...") logger.info("Connecting to MDBList...")
try: try:
self.Mdblist.add_key( self.MDBList.add_key(
check_for_attribute(self.data, "apikey", parent="mdblist", throw=True), check_for_attribute(self.data, "apikey", parent="mdblist", throw=True),
check_for_attribute(self.data, "cache_expiration", parent="mdblist", var_type="int", default=60, int_min=1) check_for_attribute(self.data, "cache_expiration", parent="mdblist", var_type="int", default=60, int_min=1)
) )
logger.info("Mdblist Connection Successful") logger.info("MDBList Connection Successful")
except Failed as e: except Failed as e:
if str(e).endswith("is blank"): if str(e).endswith("is blank"):
logger.warning(e) logger.warning(e)
else: else:
logger.error(e) logger.error(e)
logger.info("Mdblist Connection Failed") logger.info("MDBList Connection Failed")
else: else:
logger.info("mdblist attribute not found") logger.info("mdblist attribute not found")
@ -850,6 +862,8 @@ class ConfigFile:
params["ignore_ids"].extend([i for i in self.general["ignore_ids"] if i not in params["ignore_ids"]]) params["ignore_ids"].extend([i for i in self.general["ignore_ids"] if i not in params["ignore_ids"]])
params["ignore_imdb_ids"] = check_for_attribute(lib, "ignore_imdb_ids", parent="settings", var_type="lower_list", default_is_none=True, do_print=False, save=False) params["ignore_imdb_ids"] = check_for_attribute(lib, "ignore_imdb_ids", parent="settings", var_type="lower_list", default_is_none=True, do_print=False, save=False)
params["ignore_imdb_ids"].extend([i for i in self.general["ignore_imdb_ids"] if i not in params["ignore_imdb_ids"]]) params["ignore_imdb_ids"].extend([i for i in self.general["ignore_imdb_ids"] if i not in params["ignore_imdb_ids"]])
params["overlay_artwork_filetype"] = check_for_attribute(lib, "overlay_artwork_filetype", parent="settings", test_list=filetype_list, translations={"webp": "webp_lossy"}, default=self.general["overlay_artwork_filetype"], do_print=False, save=False)
params["overlay_artwork_quality"] = check_for_attribute(lib, "overlay_artwork_quality", parent="settings", var_type="int", default=self.general["overlay_artwork_quality"], default_is_none=True, int_min=1, int_max=100, do_print=False, save=False)
params["changes_webhooks"] = check_for_attribute(lib, "changes", parent="webhooks", var_type="list", default=self.webhooks["changes"], do_print=False, save=False, default_is_none=True) params["changes_webhooks"] = check_for_attribute(lib, "changes", parent="webhooks", var_type="list", default=self.webhooks["changes"], do_print=False, save=False, default_is_none=True)
params["report_path"] = None params["report_path"] = None
if lib and "report_path" in lib and lib["report_path"]: if lib and "report_path" in lib and lib["report_path"]:
@ -903,7 +917,7 @@ class ConfigFile:
final_list.append(str(list_attr)) final_list.append(str(list_attr))
elif op == "mass_genre_update": elif op == "mass_genre_update":
final_list.append(list_attr if isinstance(list_attr, list) else [list_attr]) final_list.append(list_attr if isinstance(list_attr, list) else [list_attr])
elif op == "mass_originally_available_update": elif op in ["mass_originally_available_update", "mass_added_at_update"]:
final_list.append(util.validate_date(list_attr)) final_list.append(util.validate_date(list_attr))
elif op.endswith("rating_update"): elif op.endswith("rating_update"):
final_list.append(util.check_int(list_attr, datatype="float", minimum=0, maximum=10, throw=True)) final_list.append(util.check_int(list_attr, datatype="float", minimum=0, maximum=10, throw=True))
@ -982,8 +996,8 @@ class ConfigFile:
for source in sources: for source in sources:
if source and source == "omdb" and self.OMDb is None: if source and source == "omdb" and self.OMDb is None:
raise Failed(f"{source} without a successful OMDb Connection") raise Failed(f"{source} without a successful OMDb Connection")
if source and str(source).startswith("mdb") and not self.Mdblist.has_key: if source and str(source).startswith("mdb") and not self.MDBList.has_key:
raise Failed(f"{source} without a successful MdbList Connection") raise Failed(f"{source} without a successful MDBList Connection")
if source and str(source).startswith("anidb") and not self.AniDB.is_authorized: if source and str(source).startswith("anidb") and not self.AniDB.is_authorized:
raise Failed(f"{source} without a successful AniDB Connection") raise Failed(f"{source} without a successful AniDB Connection")
if source and str(source).startswith("mal") and self.MyAnimeList is None: if source and str(source).startswith("mal") and self.MyAnimeList is None:

@ -244,10 +244,13 @@ class Convert:
if item_type == "plex": if item_type == "plex":
try: try:
for guid_tag in item.guids: for guid_tag in item.guids:
try:
url_parsed = requests.utils.urlparse(guid_tag.id) url_parsed = requests.utils.urlparse(guid_tag.id)
if url_parsed.scheme == "tvdb": tvdb_id.append(int(url_parsed.netloc)) if url_parsed.scheme == "tvdb": tvdb_id.append(int(url_parsed.netloc))
elif url_parsed.scheme == "imdb": imdb_id.append(url_parsed.netloc) elif url_parsed.scheme == "imdb": imdb_id.append(url_parsed.netloc)
elif url_parsed.scheme == "tmdb": tmdb_id.append(int(url_parsed.netloc)) elif url_parsed.scheme == "tmdb": tmdb_id.append(int(url_parsed.netloc))
except ValueError:
pass
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
library.query(item.refresh) library.query(item.refresh)
logger.stacktrace() logger.stacktrace()

@ -68,7 +68,7 @@ class GitHub:
def config_tags(self): def config_tags(self):
if not self._config_tags: if not self._config_tags:
try: try:
self._config_tags = [r["ref"][11:] for r in self._requests(f"{kometa_base}-Configs/git/refs/tags")] self._config_tags = [r["ref"][11:] for r in self._requests(f"{base_url}/repos/Kometa-Team/Community-Configs/git/refs/tags")]
except TypeError: except TypeError:
pass pass
return self._config_tags return self._config_tags

@ -81,6 +81,8 @@ class Library(ABC):
self.only_filter_missing = params["only_filter_missing"] self.only_filter_missing = params["only_filter_missing"]
self.ignore_ids = params["ignore_ids"] self.ignore_ids = params["ignore_ids"]
self.ignore_imdb_ids = params["ignore_imdb_ids"] self.ignore_imdb_ids = params["ignore_imdb_ids"]
self.overlay_artwork_quality = params["overlay_artwork_quality"]
self.overlay_artwork_filetype = params["overlay_artwork_filetype"]
self.assets_for_all = params["assets_for_all"] self.assets_for_all = params["assets_for_all"]
self.assets_for_all_collections = False self.assets_for_all_collections = False
self.delete_collections = params["delete_collections"] self.delete_collections = params["delete_collections"]
@ -95,6 +97,7 @@ class Library(ABC):
self.mass_content_rating_update = params["mass_content_rating_update"] self.mass_content_rating_update = params["mass_content_rating_update"]
self.mass_original_title_update = params["mass_original_title_update"] self.mass_original_title_update = params["mass_original_title_update"]
self.mass_originally_available_update = params["mass_originally_available_update"] self.mass_originally_available_update = params["mass_originally_available_update"]
self.mass_added_at_update = params["mass_added_at_update"]
self.mass_imdb_parental_labels = params["mass_imdb_parental_labels"] self.mass_imdb_parental_labels = params["mass_imdb_parental_labels"]
self.mass_poster_update = params["mass_poster_update"] self.mass_poster_update = params["mass_poster_update"]
self.mass_background_update = params["mass_background_update"] self.mass_background_update = params["mass_background_update"]
@ -122,7 +125,7 @@ class Library(ABC):
self.items_library_operation = True if self.assets_for_all or self.mass_genre_update or self.remove_title_parentheses \ self.items_library_operation = True if self.assets_for_all or self.mass_genre_update or self.remove_title_parentheses \
or self.mass_audience_rating_update or self.mass_critic_rating_update or self.mass_user_rating_update \ or self.mass_audience_rating_update or self.mass_critic_rating_update or self.mass_user_rating_update \
or self.mass_episode_audience_rating_update or self.mass_episode_critic_rating_update or self.mass_episode_user_rating_update \ or self.mass_episode_audience_rating_update or self.mass_episode_critic_rating_update or self.mass_episode_user_rating_update \
or self.mass_content_rating_update or self.mass_originally_available_update or self.mass_original_title_update\ or self.mass_content_rating_update or self.mass_originally_available_update or self.mass_added_at_update or self.mass_original_title_update\
or self.mass_imdb_parental_labels or self.genre_mapper or self.content_rating_mapper or self.mass_studio_update\ or self.mass_imdb_parental_labels or self.genre_mapper or self.content_rating_mapper or self.mass_studio_update\
or self.radarr_add_all_existing or self.sonarr_add_all_existing or self.mass_poster_update or self.mass_background_update else False or self.radarr_add_all_existing or self.sonarr_add_all_existing or self.mass_poster_update or self.mass_background_update else False
self.library_operation = True if self.items_library_operation or self.delete_collections or self.mass_collection_mode \ self.library_operation = True if self.items_library_operation or self.delete_collections or self.mass_collection_mode \

@ -318,7 +318,7 @@ class MyAnimeList:
logger.info(f"Processing MyAnimeList Suggested: {data} Anime") logger.info(f"Processing MyAnimeList Suggested: {data} Anime")
mal_ids = self._suggestions(data) mal_ids = self._suggestions(data)
elif method == "mal_userlist": elif method == "mal_userlist":
logger.info(f"Processing MyAnimeList Userlist: {data['limit']} Anime from {self._username() if data['username'] == '@me' else data['username']}'s {pretty_names[data['status']]} list sorted by {pretty_names[data['sort_by']]}") logger.info(f"Processing MyAnimeList UserList: {data['limit']} Anime from {self._username() if data['username'] == '@me' else data['username']}'s {pretty_names[data['status']]} list sorted by {pretty_names[data['sort_by']]}")
mal_ids = self._userlist(data["username"], data["status"], data["sort_by"], data["limit"]) mal_ids = self._userlist(data["username"], data["status"], data["sort_by"], data["limit"])
else: else:
raise Failed(f"MyAnimeList Error: Method {method} not supported") raise Failed(f"MyAnimeList Error: Method {method} not supported")

@ -71,7 +71,7 @@ class MDbObj:
self.age_rating = data["age_rating"] self.age_rating = data["age_rating"]
class Mdblist: class MDBList:
def __init__(self, config): def __init__(self, config):
self.config = config self.config = config
self.apikey = None self.apikey = None
@ -110,12 +110,12 @@ class Mdblist:
time.sleep(0.2 if self.supporter else 1) time.sleep(0.2 if self.supporter else 1)
response = self.config.get_json(url, params=final_params) response = self.config.get_json(url, params=final_params)
except JSONDecodeError: except JSONDecodeError:
raise Failed("Mdblist Error: JSON Decoding Failed") raise Failed("MDBList Error: JSON Decoding Failed")
if "response" in response and (response["response"] is False or response["response"] == "False"): if "response" in response and (response["response"] is False or response["response"] == "False"):
if response["error"] in ["API Limit Reached!", "API Rate Limit Reached!"]: if response["error"] in ["API Limit Reached!", "API Rate Limit Reached!"]:
self.limit = True self.limit = True
raise LimitReached(f"MdbList Error: {response['error']}") raise LimitReached(f"MDBList Error: {response['error']}")
raise Failed(f"MdbList Error: {response['error']}") raise Failed(f"MDBList Error: {response['error']}")
return response return response
def get_item(self, imdb_id=None, tmdb_id=None, tvdb_id=None, is_movie=True, ignore_cache=False): def get_item(self, imdb_id=None, tmdb_id=None, tvdb_id=None, is_movie=True, ignore_cache=False):
@ -132,7 +132,7 @@ class Mdblist:
params["m"] = "movie" if is_movie else "show" params["m"] = "movie" if is_movie else "show"
key = f"{'tvm' if is_movie else 'tvs'}{tvdb_id}" key = f"{'tvm' if is_movie else 'tvs'}{tvdb_id}"
else: else:
raise Failed("MdbList Error: Either IMDb ID, TVDb ID, or TMDb ID and TMDb Type Required") raise Failed("MDBList Error: Either IMDb ID, TVDb ID, or TMDb ID and TMDb Type Required")
expired = None expired = None
if self.config.Cache and not ignore_cache: if self.config.Cache and not ignore_cache:
mdb_dict, expired = self.config.Cache.query_mdb(key, self.expiration) mdb_dict, expired = self.config.Cache.query_mdb(key, self.expiration)
@ -198,7 +198,7 @@ class Mdblist:
def get_tmdb_ids(self, method, data, is_movie=None): def get_tmdb_ids(self, method, data, is_movie=None):
if method == "mdblist_list": if method == "mdblist_list":
logger.info(f"Processing Mdblist.com List: {data['url']}") logger.info(f"Processing MDBList.com List: {data['url']}")
logger.info(f"Sort By: {data['sort_by']}") logger.info(f"Sort By: {data['sort_by']}")
sort, direction = data["sort_by"].split(".") sort, direction = data["sort_by"].split(".")
params = {"sort": sort, "sortorder": direction} params = {"sort": sort, "sortorder": direction}
@ -216,14 +216,14 @@ class Mdblist:
if (isinstance(response, dict) and "error" in response) or (isinstance(response, list) and response and "error" in response[0]): if (isinstance(response, dict) and "error" in response) or (isinstance(response, list) and response and "error" in response[0]):
err = response["error"] if isinstance(response, dict) else response[0]["error"] err = response["error"] if isinstance(response, dict) else response[0]["error"]
if err in ["empty", "empty or private list"]: if err in ["empty", "empty or private list"]:
raise Failed(f"Mdblist Error: No Items Returned. Lists can take 24 hours to update so try again later.") raise Failed(f"MDBList Error: No Items Returned. Lists can take 24 hours to update so try again later.")
raise Failed(f"Mdblist Error: Invalid Response {response}") raise Failed(f"MDBList Error: Invalid Response {response}")
results = [] results = []
for item in response: for item in response:
if item["mediatype"] in ["movie", "show"]: if item["mediatype"] in ["movie", "show"]:
results.append((item["id"], "tmdb" if item["mediatype"] == "movie" else "tmdb_show")) results.append((item["id"], "tmdb" if item["mediatype"] == "movie" else "tmdb_show"))
return results return results
except JSONDecodeError: except JSONDecodeError:
raise Failed(f"Mdblist Error: Invalid JSON Response received") raise Failed(f"MDBList Error: Invalid JSON Response received")
else: else:
raise Failed(f"Mdblist Error: Method {method} not supported") raise Failed(f"MDBList Error: Method {method} not supported")

@ -1,5 +1,5 @@
import os, re import os, re
from datetime import datetime from datetime import datetime, timedelta, timezone
from modules import plex, util, anidb from modules import plex, util, anidb
from modules.util import Failed, LimitReached, YAML from modules.util import Failed, LimitReached, YAML
from plexapi.exceptions import NotFound from plexapi.exceptions import NotFound
@ -10,14 +10,15 @@ logger = util.logger
meta_operations = [ meta_operations = [
"mass_audience_rating_update", "mass_user_rating_update", "mass_critic_rating_update", "mass_audience_rating_update", "mass_user_rating_update", "mass_critic_rating_update",
"mass_episode_audience_rating_update", "mass_episode_user_rating_update", "mass_episode_critic_rating_update", "mass_episode_audience_rating_update", "mass_episode_user_rating_update", "mass_episode_critic_rating_update",
"mass_genre_update", "mass_content_rating_update", "mass_originally_available_update", "mass_original_title_update", "mass_genre_update", "mass_content_rating_update", "mass_originally_available_update", "mass_added_at_update",
"mass_poster_update", "mass_background_update", "mass_studio_update" "mass_original_title_update", "mass_poster_update", "mass_background_update", "mass_studio_update"
] ]
name_display = { name_display = {
"audienceRating": "Audience Rating", "audienceRating": "Audience Rating",
"rating": "Critic Rating", "rating": "Critic Rating",
"userRating": "User Rating", "userRating": "User Rating",
"originallyAvailableAt": "Originally Available Date", "originallyAvailableAt": "Originally Available Date",
"addedAt": "Added At Date",
"contentRating": "Content Rating" "contentRating": "Content Rating"
} }
@ -45,6 +46,7 @@ class Operations:
logger.debug(f"Mass Content Rating Update: {self.library.mass_content_rating_update}") logger.debug(f"Mass Content Rating Update: {self.library.mass_content_rating_update}")
logger.debug(f"Mass Original Title Update: {self.library.mass_original_title_update}") logger.debug(f"Mass Original Title Update: {self.library.mass_original_title_update}")
logger.debug(f"Mass Originally Available Update: {self.library.mass_originally_available_update}") logger.debug(f"Mass Originally Available Update: {self.library.mass_originally_available_update}")
logger.debug(f"Mass Added At Update: {self.library.mass_added_at_update}")
logger.debug(f"Mass IMDb Parental Labels: {self.library.mass_imdb_parental_labels}") logger.debug(f"Mass IMDb Parental Labels: {self.library.mass_imdb_parental_labels}")
logger.debug(f"Mass Poster Update: {self.library.mass_poster_update}") logger.debug(f"Mass Poster Update: {self.library.mass_poster_update}")
logger.debug(f"Mass Background Update: {self.library.mass_background_update}") logger.debug(f"Mass Background Update: {self.library.mass_background_update}")
@ -88,7 +90,7 @@ class Operations:
genre_edits = {"add": {}, "remove": {}} genre_edits = {"add": {}, "remove": {}}
content_edits = {} content_edits = {}
studio_edits = {} studio_edits = {}
available_edits = {} date_edits = {"originallyAvailableAt": {}, "addedAt": {}}
remove_edits = {} remove_edits = {}
reset_edits = {} reset_edits = {}
lock_edits = {} lock_edits = {}
@ -229,10 +231,10 @@ class Operations:
nonlocal _mdb_obj nonlocal _mdb_obj
if _mdb_obj is None: if _mdb_obj is None:
_mdb_obj = False _mdb_obj = False
if self.config.Mdblist.limit is False: if self.config.MDBList.limit is False:
if self.library.is_show and tvdb_id: if self.library.is_show and tvdb_id:
try: try:
_mdb_obj = self.config.Mdblist.get_series(tvdb_id) _mdb_obj = self.config.MDBList.get_series(tvdb_id)
except LimitReached as err: except LimitReached as err:
logger.debug(err) logger.debug(err)
except Failed as err: except Failed as err:
@ -242,7 +244,7 @@ class Operations:
raise raise
if self.library.is_movie and tmdb_id: if self.library.is_movie and tmdb_id:
try: try:
_mdb_obj = self.config.Mdblist.get_movie(tmdb_id) _mdb_obj = self.config.MDBList.get_movie(tmdb_id)
except LimitReached as err: except LimitReached as err:
logger.debug(err) logger.debug(err)
except Failed as err: except Failed as err:
@ -252,7 +254,7 @@ class Operations:
raise raise
if imdb_id and not _mdb_obj: if imdb_id and not _mdb_obj:
try: try:
_mdb_obj = self.config.Mdblist.get_imdb(imdb_id) _mdb_obj = self.config.MDBList.get_imdb(imdb_id)
except LimitReached as err: except LimitReached as err:
logger.debug(err) logger.debug(err)
except Failed as err: except Failed as err:
@ -664,62 +666,66 @@ class Operations:
except Failed: except Failed:
continue continue
if self.library.mass_originally_available_update: for attribute, item_attr in [
current_available = item.originallyAvailableAt (self.library.mass_originally_available_update, "originallyAvailableAt"),
if current_available: (self.library.mass_added_at_update, "addedAt")
current_available = current_available.strftime("%Y-%m-%d") ]:
for option in self.library.mass_originally_available_update: if attribute:
current = getattr(item, item_attr)
if current:
current = current.strftime("%Y-%m-%d")
for option in attribute:
if option in ["lock", "remove"]: if option in ["lock", "remove"]:
if option == "remove" and current_available: if option == "remove" and current:
if "originallyAvailableAt" not in remove_edits: if item_attr not in remove_edits:
remove_edits["originallyAvailableAt"] = [] remove_edits[item_attr] = []
remove_edits["originallyAvailableAt"].append(item.ratingKey) remove_edits[item_attr].append(item.ratingKey)
item_edits += "\nRemove Originally Available Date (Batched)" item_edits += f"\nRemove {name_display[item_attr]} (Batched)"
elif "originallyAvailableAt" not in locked_fields: elif item_attr not in locked_fields:
if "originallyAvailableAt" not in lock_edits: if item_attr not in lock_edits:
lock_edits["originallyAvailableAt"] = [] lock_edits[item_attr] = []
lock_edits["originallyAvailableAt"].append(item.ratingKey) lock_edits[item_attr].append(item.ratingKey)
item_edits += "\nLock Originally Available Date (Batched)" item_edits += f"\nLock {name_display[item_attr]} (Batched)"
break break
elif option in ["unlock", "reset"]: elif option in ["unlock", "reset"]:
if option == "reset" and current_available: if option == "reset" and current:
if "originallyAvailableAt" not in reset_edits: if item_attr not in reset_edits:
reset_edits["originallyAvailableAt"] = [] reset_edits[item_attr] = []
reset_edits["originallyAvailableAt"].append(item.ratingKey) reset_edits[item_attr].append(item.ratingKey)
item_edits += "\nReset Originally Available Date (Batched)" item_edits += f"\nReset {name_display[item_attr]} (Batched)"
elif "originallyAvailableAt" in locked_fields: elif item_attr in locked_fields:
if "originallyAvailableAt" not in unlock_edits: if item_attr not in unlock_edits:
unlock_edits["originallyAvailableAt"] = [] unlock_edits[item_attr] = []
unlock_edits["originallyAvailableAt"].append(item.ratingKey) unlock_edits[item_attr].append(item.ratingKey)
item_edits += "\nUnlock Originally Available Date (Batched)" item_edits += f"\nUnlock {name_display[item_attr]} (Batched)"
break break
else: else:
try: try:
if option == "tmdb": if option == "tmdb":
new_available = tmdb_obj().release_date if self.library.is_movie else tmdb_obj().first_air_date # noqa new_date = tmdb_obj().release_date if self.library.is_movie else tmdb_obj().first_air_date # noqa
elif option == "omdb": elif option == "omdb":
new_available = omdb_obj().released # noqa new_date = omdb_obj().released # noqa
elif option == "tvdb": elif option == "tvdb":
new_available = tvdb_obj().release_date # noqa new_date = tvdb_obj().release_date # noqa
elif option == "mdb": elif option == "mdb":
new_available = mdb_obj().released # noqa new_date = mdb_obj().released # noqa
elif option == "mdb_digital": elif option == "mdb_digital":
new_available = mdb_obj().released_digital # noqa new_date = mdb_obj().released_digital # noqa
elif option == "anidb": elif option == "anidb":
new_available = anidb_obj().released # noqa new_date = anidb_obj().released # noqa
elif option == "mal": elif option == "mal":
new_available = mal_obj().aired # noqa new_date = mal_obj().aired # noqa
else: else:
new_available = option new_date = option
if not new_available: if not new_date:
logger.info(f"No {option} Originally Available Date Found") logger.info(f"No {option} {name_display[item_attr]} Found")
raise Failed raise Failed
new_available = new_available.strftime("%Y-%m-%d") new_date = new_date.strftime("%Y-%m-%d")
if current_available != new_available: if current != new_date:
if new_available not in available_edits: if new_date not in date_edits[item_attr]:
available_edits[new_available] = [] date_edits[item_attr][new_date] = []
available_edits[new_available].append(item.ratingKey) date_edits[item_attr][new_date].append(item.ratingKey)
item_edits += f"\nUpdate Originally Available Date (Batched) | {new_available}" item_edits += f"\nUpdate {name_display[item_attr]} (Batched) | {new_date}"
break break
except Failed: except Failed:
continue continue
@ -920,11 +926,27 @@ class Operations:
self.library.Plex.editStudio(new_studio) self.library.Plex.editStudio(new_studio)
self.library.Plex.saveMultiEdits() self.library.Plex.saveMultiEdits()
_size = len(available_edits.items()) _size = len(date_edits["originallyAvailableAt"].items())
for i, (new_available, rating_keys) in enumerate(sorted(available_edits.items()), 1): for i, (new_date, rating_keys) in enumerate(sorted(date_edits["originallyAvailableAt"].items()), 1):
logger.info(get_batch_info(i, _size, "originallyAvailableAt", len(rating_keys), display_value=new_available)) logger.info(get_batch_info(i, _size, "originallyAvailableAt", len(rating_keys), display_value=new_date))
self.library.Plex.batchMultiEdits(self.library.load_list_from_cache(rating_keys)) self.library.Plex.batchMultiEdits(self.library.load_list_from_cache(rating_keys))
self.library.Plex.editOriginallyAvailable(new_available) self.library.Plex.editOriginallyAvailable(new_date)
self.library.Plex.saveMultiEdits()
epoch = datetime(1970, 1, 1)
_size = len(date_edits["addedAt"].items())
for i, (new_date, rating_keys) in enumerate(sorted(date_edits["addedAt"].items()), 1):
logger.info(get_batch_info(i, _size, "addedAt", len(rating_keys), display_value=new_date))
self.library.Plex.batchMultiEdits(self.library.load_list_from_cache(rating_keys))
new_date = datetime.strptime(new_date, "%Y-%m-%d")
logger.trace(new_date)
try:
ts = int(round(new_date.timestamp()))
except (TypeError, OSError):
offset = int(datetime(2000, 1, 1, tzinfo=timezone.utc).timestamp() - datetime(2000, 1, 1).timestamp())
ts = int((new_date - epoch).total_seconds()) - offset
logger.trace(epoch + timedelta(seconds=ts))
self.library.Plex.editAddedAt(ts)
self.library.Plex.saveMultiEdits() self.library.Plex.saveMultiEdits()
_size = len(remove_edits.items()) _size = len(remove_edits.items())

@ -61,7 +61,8 @@ class Overlays:
logger.ghost(f"Restoring: {i}/{len(remove_overlays)} {item_title}") logger.ghost(f"Restoring: {i}/{len(remove_overlays)} {item_title}")
self.remove_overlay(item, item_title, "Overlay", [ self.remove_overlay(item, item_title, "Overlay", [
os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png"), os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png"),
os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg") os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg"),
os.path.join(self.library.overlay_backup, f"{item.ratingKey}.webp")
]) ])
logger.exorcise() logger.exorcise()
else: else:
@ -176,11 +177,15 @@ class Overlays:
os.remove(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png")) os.remove(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png"))
if os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg")): if os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg")):
os.remove(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg")) os.remove(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg"))
if os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.webp")):
os.remove(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.webp"))
elif has_overlay: elif has_overlay:
if os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png")): if os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png")):
has_original = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png") has_original = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.png")
elif os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg")): elif os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg")):
has_original = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg") has_original = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.jpg")
elif os.path.exists(os.path.join(self.library.overlay_backup, f"{item.ratingKey}.webp")):
has_original = os.path.join(self.library.overlay_backup, f"{item.ratingKey}.webp")
if self.library.reset_overlays: if self.library.reset_overlays:
reset_list = self.library.reset_overlays reset_list = self.library.reset_overlays
elif has_original is None and not self.library.reset_overlays: elif has_original is None and not self.library.reset_overlays:
@ -296,10 +301,10 @@ class Overlays:
raise Failed("No Trakt User Rating Found") raise Failed("No Trakt User Rating Found")
elif str(format_var).startswith("mdb"): elif str(format_var).startswith("mdb"):
mdb_item = None mdb_item = None
if self.config.Mdblist.limit is False: if self.config.MDBList.limit is False:
if self.library.is_show and tvdb_id: if self.library.is_show and tvdb_id:
try: try:
mdb_item = self.config.Mdblist.get_series(tvdb_id) mdb_item = self.config.MDBList.get_series(tvdb_id)
except LimitReached as err: except LimitReached as err:
logger.debug(err) logger.debug(err)
except Failed as err: except Failed as err:
@ -309,7 +314,7 @@ class Overlays:
raise raise
if self.library.is_movie and tmdb_id: if self.library.is_movie and tmdb_id:
try: try:
mdb_item = self.config.Mdblist.get_movie(tmdb_id) mdb_item = self.config.MDBList.get_movie(tmdb_id)
except LimitReached as err: except LimitReached as err:
logger.debug(err) logger.debug(err)
except Failed as err: except Failed as err:
@ -319,7 +324,7 @@ class Overlays:
raise raise
if imdb_id and not mdb_item: if imdb_id and not mdb_item:
try: try:
mdb_item = self.config.Mdblist.get_imdb(imdb_id) mdb_item = self.config.MDBList.get_imdb(imdb_id)
except LimitReached as err: except LimitReached as err:
logger.debug(err) logger.debug(err)
except Failed as err: except Failed as err:
@ -507,7 +512,13 @@ class Overlays:
else: else:
overlay_box = current_overlay.get_coordinates((canvas_width, canvas_height), box=current_overlay.image.size, new_cords=cord) overlay_box = current_overlay.get_coordinates((canvas_width, canvas_height), box=current_overlay.image.size, new_cords=cord)
new_poster.paste(current_overlay.image, overlay_box, current_overlay.image) new_poster.paste(current_overlay.image, overlay_box, current_overlay.image)
temp = os.path.join(self.library.overlay_folder, "temp.jpg") ext = "webp" if self.library.overlay_artwork_filetype.startswith("webp") else self.library.overlay_artwork_filetype
temp = os.path.join(self.library.overlay_folder, f"temp.{ext}")
if self.library.overlay_artwork_quality and self.library.overlay_artwork_filetype in ["jpg", "webp_lossy"]:
new_poster.save(temp, exif=exif_tags, quality=self.library.overlay_artwork_quality)
elif self.library.overlay_artwork_filetype == "webp_lossless":
new_poster.save(temp, exif=exif_tags, lossless=True)
else:
new_poster.save(temp, exif=exif_tags) new_poster.save(temp, exif=exif_tags)
self.library.upload_poster(item, temp) self.library.upload_poster(item, temp)
self.library.edit_tags("label", item, add_tags=["Overlay"], do_print=False) self.library.edit_tags("label", item, add_tags=["Overlay"], do_print=False)

@ -1350,7 +1350,7 @@ class Plex(Library):
elif self.show_missing_assets: elif self.show_missing_assets:
logger.warning(f"Asset Warning: No poster or background found in the assets folder '{item_dir}'") logger.warning(f"Asset Warning: No poster or background found in the assets folder '{item_dir}'")
else: else:
logger.warning(f"Asset Warning: {name} has an Overlay and will be updated when overlays are run") logger.info(f"Item: {name} has an Overlay and will be updated when overlays are run")
except Failed as e: except Failed as e:
if self.show_missing_assets: if self.show_missing_assets:
logger.warning(e) logger.warning(e)

@ -29,7 +29,7 @@ class Reciperr:
name = "StevenLu" if method == "stevenlu_popular" else "Reciperr" name = "StevenLu" if method == "stevenlu_popular" else "Reciperr"
logger.info(f"Processing {name} Movies") logger.info(f"Processing {name} Movies")
if method == "reciperr_list": if method == "reciperr_list":
ids = [(i["imdb_id"], "imdb") for i in self._request(data)] ids = [(i["imdb_id"], "imdb") for i in self._request(data) if "imdb_id" in i]
elif method == "stevenlu_popular": elif method == "stevenlu_popular":
ids = [(i["imdb_id"], "imdb") for i in self._request(stevenlu_url, name="StevenLu")] ids = [(i["imdb_id"], "imdb") for i in self._request(stevenlu_url, name="StevenLu")]
else: else:

@ -314,7 +314,7 @@ class Webhooks:
} }
], ],
"username": "Kobota", "username": "Kobota",
"avatar_url": "https://github.com/Kometa-Team/Kometa/raw/master/.github/logo.png" "avatar_url": "https://github.com/Kometa-Team/Kometa/raw/master/.github/bot.png"
} }
if description: if description:
new_json["embeds"][0]["description"] = description new_json["embeds"][0]["description"] = description

@ -1,4 +1,4 @@
arrapi==1.4.11 arrapi==1.4.13
GitPython==3.1.43 GitPython==3.1.43
lxml==5.2.1 lxml==5.2.1
num2words==0.5.13 num2words==0.5.13
@ -13,4 +13,4 @@ retrying==1.3.4
ruamel.yaml==0.18.6 ruamel.yaml==0.18.6
schedule==1.2.1 schedule==1.2.1
setuptools==69.5.1 setuptools==69.5.1
tmdbapis==1.2.14 tmdbapis==1.2.16
Loading…
Cancel
Save