Templates in go-upper
Templates mit go-upper
go-upper kann nach jedem Upload automatisch Templates füllen (BBCode, Intelligen‑XML, eigene Textdateien usw.). Hier erfährst du, wie du sie aktivierst, welche Dateien als Beispiel dienen und welche Variablen verfügbar sind.
1) Template-Modul aktivieren
In config/upper.config.yml den Block template anpassen:
template:
enabled: true # Templates generieren?
templates:
default:
- '/pfad/zu/config/templates/bbcode/bbcode_movie_boerse07_hidecx.html'
- '/pfad/zu/config/templates/intelligen/murat/movies.xml'
movie: [] # optional: eigene Liste nur für Movies
game: [] # optional: eigene Liste nur für Games
ebook: [] # optional: eigene Liste nur für EBooks
software: [] # optional: eigene Liste nur für Software/Apps
tv: [] # optional: eigene Liste nur für TV
music: [] # optional: eigene Liste nur für Music
xxx: [] # optional: eigene Liste nur für XXX
saveTo: '/pfad/zum/result/' # optional: Zielordner für fertige Templates
contenttypes: # ordnet Scan-Pfade einem Typ zu
- type: "movie"
path: "/pfad/zur/go-upper-installation/backup/"
So wählt go-upper die Templates:
defaultläuft immer.- Zusätzlich der Typen-Block (
movie,game,ebook,software,tv,music,xxx), falls der Inhaltstyp erkannt wird (übercontenttypesoder XRel). - Wenn
saveToleer ist, nutzt go-upper den Ergebnisordner ausresult/. Bei aktivemresult.json.seperatedlandet jedes Template im eigenen Unterordner des Releases.
2) Beispiel-Templates nutzen
Im Repo findest du fertige Beispiele:
- BBCode:
config/templates/bbcode/…(z. B.bbcode_movie_boerse07_hidecx.html) - Intelligen XML:
config/templates/intelligen/…(z. B.intelligen/murat/movies.xml)
Du kannst diese Pfade direkt in template.templates eintragen oder als Vorlage für eigene Dateien kopieren.
3) Template-Verwaltung in der Upper-UI
Die Upper-UI hat links den Bereich Templates. Beim Start importiert die UI alle lesbaren Dateien aus template.templates einmalig in die SQLite-Datenbank. Bei mehreren verwalteten Upper-Instanzen wird der Import je Instanz ausgefuehrt; relative Template-Pfade werden dabei relativ zur jeweiligen upper.config.yml aufgeloest. Verwendet die UI selbst dieselbe upper.config.yml wie eine registrierte Instanz, wird diese Config nur fuer die Instanz importiert und nicht zusaetzlich als Global. Leere Template-Listen bleiben leer.
In der UI kannst du Templates:
- nach Titel, Typen (
movie,tv,game,ebook,software,music,xxxoderAlle) und Format (xml,html,bbcode,plaintext) verwalten, - mit Syntax-Highlighting bearbeiten und speichern,
- neu anlegen,
- als Datei exportieren,
- importierte Templates per Sync erneut aus der Quelldatei laden und den gespeicherten UI-Inhalt ueberschreiben,
- aus der Templates-UI entfernen, ohne die Originaldatei aus der Importquelle zu entfernen,
- mit einer importierten Upload-JSON als Vorschau rendern.
Der normale Import ist idempotent: Bereits importierte Config-Dateien werden pro Instanz nicht erneut überschrieben. Der Sync-Button erscheint bei Templates mit Status importiert; er liest die gespeicherte Quelldatei erneut ein, aktualisiert Format/Typen aus der aktuellen Config, sofern vorhanden, und ueberschreibt den DB-Inhalt. Entfernst du ein importiertes Template aus der UI, wird nur der gespeicherte UI-Datensatz gelöscht; die Originaldatei bleibt erhalten und kann über Import wieder neu eingelesen werden.
Wird ein UI-Template auf der Upload-Edit-Seite fuer ein XenForo- oder uCMS-Publishing-Ziel ausgewaehlt, rendert die Publishing-Warteschlange den gespeicherten UI-Inhalt mit der Config der Upload-Instanz. Bei einer neuen UI-Publishing-Auswahl wird ein zum Inhaltstyp und zur Instanz passendes gespeichertes UI-Template vorausgewaehlt, wenn template im Mapping leer oder nicht lesbar ist. Ein lesbarer Mapping-Pfad bleibt als bewusst gesetzte Vorauswahl erhalten. Fuer ein reines UI-Setup darf template leer bleiben; der CLI-Publishing-Ablauf verwendet dagegen weiterhin den Mapping-Template-Pfad.
Unter Text ersetzen (Replace) kannst du finale Plain-Text-Ersetzungen verwalten, die erst nach dem Rendern eines Templates laufen. Dadurch werden zuerst alle Template-Variablen wie {{ .Name }} eingefuegt und danach der fertige Text ersetzt, zum Beispiel de,en zu Deutsch,Englisch. Ein Replace mit aktivem Global gilt fuer alle Upper-Instanzen. Ohne Global gilt er nur fuer die aktuell ausgewaehlte Instanz; auf Alle / Global muss deshalb Global aktiv sein. Die Regeln sind case-sensitive, verwenden keine Regex und laufen nach aufsteigender Reihenfolge.
Die Target-Auswahl auf der Upload-Edit-Seite wird bei noch nicht gespeicherten Zielen aus Release-Titel und Inhaltstyp vorausgewaehlt. Dafuer gelten dieselben match-, exclude-, priority- und fallback-Regeln wie beim CLI-Publishing; eine bereits manuell gespeicherte Zielwahl bleibt erhalten.
4) Alle verfügbaren Template-Variablen
Alle Variablen in der Reihenfolge der JSON-Struktur (Quelle: config/templates/TEMPLATE-VARIABLES.txt):
Top-Level (UploadItem)
{{ .ID }}– interne Queue-ID (UUID){{ .Name }}– Release-Titel{{ .OriginalName }}– ursprünglicher Ordnername{{ .SourceDir }}– Quellpfad{{ .WorkDir }}– Workdir{{ .TargetDir }}– Zielpfad (falls gesetzt){{ .ToUpload }}– Liste der Upload-Dateien{{ .ToUploadStream }}– Liste der Stream-Upload-Dateien{{ .Links }}– Map: Hoster → Direktlinks{{ .CryptedLinks }}– Map: Hoster → Crypter-Link{{ .CryptedLinksBackup }}– Map nach Crypter-Service → Hosterlinks{{ .CryptedLinksStream }}– Map: Streamhoster → Crypter-Link{{ .CryptedLinksStreamBackup }}– Backup für Streamhoster{{ .CryptedLinksStatus }}– Map: Hoster → Status-ID{{ .Size }}– Größe in Bytes{{ .SizeHuman }},{{ .SizeHumanI }},{{ .SizeHumanReal }},{{ .SizeHumanRealI }}– Größen in SI/IEC{{ .NFOPath }}– Pfad zur NFO (falls vorhanden)
General
{{ .General.Release }}– Release-Name{{ .General.Name }}– bereinigter Name (z. B. „Avatar“){{ .General.Year }}– Jahr{{ .General.Size }},{{ .General.SizeI }},{{ .General.SizeReal }},{{ .General.SizeRealI }}– Größen wie oben{{ .General.Type }}– erkannter Typ (movie, tv, game, ebook, software, music, xxx){{ .General.Plot }}– Beschreibung{{ .General.Genre }}– Genre (kommagetrennt){{ .General.Cover }}– Cover-URL{{ .General.IMDBID }}– IMDB-ID{{ .General.IMDBLink }}– IMDB-Link
ExternalInfo – XRel
{{ .ExternalInfo.XRel.XRelID }}{{ .ExternalInfo.XRel.Release }}{{ .ExternalInfo.XRel.ReleaseLink }}{{ .ExternalInfo.XRel.NFOLink }}{{ .ExternalInfo.XRel.Group }}{{ .ExternalInfo.XRel.Type }}{{ .ExternalInfo.XRel.Title }}{{ .ExternalInfo.XRel.MediaLink }}{{ .ExternalInfo.XRel.Uris }}{{ .ExternalInfo.XRel.ExtInfo.Cover }}{{ .ExternalInfo.XRel.ExtInfo.Plot }}{{ .ExternalInfo.XRel.ExtInfo.IMDBID }}{{ .ExternalInfo.XRel.ExtInfo.IMDBLink }}{{ .ExternalInfo.XRel.ExtInfo.Genre }}{{ .ExternalInfo.XRel.ExtInfo.VideoType }}{{ .ExternalInfo.XRel.ExtInfo.AudioType }}{{ .ExternalInfo.XRel.ExtInfo.ExtInfoRaw }}
Beispielansicht der XRel-Daten im Ergebnis-JSON:

ExternalInfo – PreDB
{{ .ExternalInfo.PreDB.ID }}{{ .ExternalInfo.PreDB.Pretime }}{{ .ExternalInfo.PreDB.Release }}{{ .ExternalInfo.PreDB.Section }}{{ .ExternalInfo.PreDB.Files }}{{ .ExternalInfo.PreDB.SizeMB }}{{ .ExternalInfo.PreDB.Status }}–0ok,1nuked,2unnuked,3delpre,4undelpre{{ .ExternalInfo.PreDB.Reason }}{{ .ExternalInfo.PreDB.Group }}{{ .ExternalInfo.PreDB.Genre }}{{ .ExternalInfo.PreDB.ReleaseLink }}{{ .ExternalInfo.PreDB.NFOLink }}{{ .ExternalInfo.PreDB.NFOImage }}
ExternalInfo – IMDB
{{ .ExternalInfo.IMDB.ID }}{{ .ExternalInfo.IMDB.Title }}{{ .ExternalInfo.IMDB.Plot }}{{ .ExternalInfo.IMDB.Rating }}{{ .ExternalInfo.IMDB.RatingCount }}{{ .ExternalInfo.IMDB.Year }}{{ .ExternalInfo.IMDB.CoverURLs.Small }}{{ .ExternalInfo.IMDB.CoverURLs.Medium }}{{ .ExternalInfo.IMDB.CoverURLs.Big }}
ExternalInfo – TMDB
{{ .ExternalInfo.TMDB.ID }}{{ .ExternalInfo.TMDB.Title }}{{ .ExternalInfo.TMDB.OriginalTitle }}{{ .ExternalInfo.TMDB.Plot }}{{ .ExternalInfo.TMDB.Rating }}{{ .ExternalInfo.TMDB.RatingCount }}{{ .ExternalInfo.TMDB.RunTime }}{{ .ExternalInfo.TMDB.IMDBID }}{{ .ExternalInfo.TMDB.PosterPath }}{{ .ExternalInfo.TMDB.BackdropPath }}{{ .ExternalInfo.TMDB.CoverURLs.Small }}{{ .ExternalInfo.TMDB.CoverURLs.Medium }}{{ .ExternalInfo.TMDB.CoverURLs.Big }}{{ .ExternalInfo.TMDB.Trailer.Name }}{{ .ExternalInfo.TMDB.Trailer.WatchURL }}{{ .ExternalInfo.TMDB.AdditionalLanguages }}– Map: Sprache → lokalisierte TMDB‑Details (nur wenncontentgrabber.tmdb.languagemehrere Codes wie"DE,EN"enthält)
Beispiel: zweite Sprache (EN) im Template nutzen:
{{- with (index .ExternalInfo.TMDB.AdditionalLanguages "EN") }}
EN Titel: {{ .Title }}
EN Plot: {{ .Plot }}
{{- end}}
ExternalInfo – Steam
{{ .ExternalInfo.Steam.ID }}{{ .ExternalInfo.Steam.Name }}{{ .ExternalInfo.Steam.Image }}{{ .ExternalInfo.Steam.Genres }}{{ .ExternalInfo.Steam.Developers }}{{ .ExternalInfo.Steam.Publishers }}{{ .ExternalInfo.Steam.SupportedLanguageSubtitle }}{{ .ExternalInfo.Steam.SupportedLanguageAudio }}{{ .ExternalInfo.Steam.ReleaseDate }}{{ .ExternalInfo.Steam.ShortDescription }}{{ .ExternalInfo.Steam.AdditionalLanguages }}– Map: Sprache → lokalisierte Steam‑Details (nur wenncontentgrabber.steam.languagemehrere Codes wie"DE,EN"enthält)
Beispiel: zweite Sprache (EN) im Template nutzen:
{{- with (index .ExternalInfo.Steam.AdditionalLanguages "EN") }}
EN Titel: {{ .Name }}
EN Beschreibung: {{ .ShortDescription }}
{{- end}}
Beispielansicht der Steam-Daten im Ergebnis-JSON:

ExternalInfo – YouTube
{{ .ExternalInfo.Youtube.Title }}{{ .ExternalInfo.Youtube.Channel }}{{ .ExternalInfo.Youtube.PublishedAt }}{{ .ExternalInfo.Youtube.Score }}{{ .ExternalInfo.Youtube.WatchURL }}{{ .ExternalInfo.Youtube.EmbedURL }}
Emule
{{ .Emule.File }}{{ .Emule.HashLink }}{{ .Emule.Size }}
MediaInfo / FFProbe
{{ .MediaInfo.FFProbe.FFProbeFirstVideoSteam }}{{ .MediaInfo.FFProbe.FFProbeFirstAudioStream }}{{ .MediaInfo.FFProbe.FFProbeRAWData }}{{ .MediaInfo.MediaInfo.MediaInfoFirstVideoSteam }}{{ .MediaInfo.MediaInfo.MediaInfoFirstAudioStream }}{{ .MediaInfo.MediaInfo.MediaInfoRAWData }}{{ .MediaInfo.MediaInfo.MediaInfoData }}{{ .MediaInfo.MediaInfo.MediaInfoData.RAWString }}{{ .MediaInfo.MediaInfo.HumanValues.VideoRuntime }}{{ .MediaInfo.MediaInfo.HumanValues.VideoFormat }}{{ .MediaInfo.MediaInfo.HumanValues.VideoCodec }}{{ .MediaInfo.MediaInfo.HumanValues.VideoWidth }}{{ .MediaInfo.MediaInfo.HumanValues.VideoHeight }}{{ .MediaInfo.MediaInfo.HumanValues.VideoBitrate }}{{ .MediaInfo.MediaInfo.HumanValues.AudioLanguages }}{{ .MediaInfo.MediaInfo.HumanValues.AudioLanguagesLocalized }}– deutsche Sprachbezeichnungen, z. B.Deutsch, Englisch{{ .MediaInfo.MediaInfo.HumanValues.AudioFormat }}{{ .MediaInfo.MediaInfo.HumanValues.AudioBitrate }}{{ .MediaInfo.MediaInfo.HumanValues.AudioChannel }}{{ .MediaInfo.MediaInfo.HumanValues.SubtitleLanguages }}
MovieThumbnail
{{ .MovieThumbnail.ThumbnailPath }}{{ .MovieThumbnail.ThumbnailLink }}{{ .MovieThumbnail.InfoTXT }}
NFO / Crypter / Cover (top-level)
{{ .NFO }}– kompletter NFO-Inhalt{{ .Crypter }}– aktiver Crypter-Name{{ .Cover }}– Cover-URL (Fallback auf.General.Cover)
4) Praktische Beispiele
BBCode-Template (Boerse):
template:
enabled: true
templates:
default:
- '/pfad/zur/go-upper-installation/config/templates/bbcode/bbcode_movie_boerse07_hidecx.html'
saveTo: '/pfad/zur/go-upper-installation/result/'
Intelligen-Template:
template:
enabled: true
templates:
movie:
- '/pfad/zur/go-upper-installation/config/templates/intelligen/murat/movies.xml'
saveTo: '/pfad/zur/go-upper-installation/result/'
contenttypes:
- type: "movie"
path: "/pfad/zur/go-upper-installation/backup/"
Variablen nutzen (Mini-Ausschnitt):
[B]Titel:[/B] {{ .Name }}
[B]Größe:[/B] {{ .SizeHuman }}
[B]Hoster:[/B]
{{- range $hoster, $link := .CryptedLinks }}
- {{ $hoster }} → {{ $link }}
{{- end}}
Tipp: Immer mit if/with prüfen, ob Werte existieren, damit die Template-Ausgabe nicht abbricht:
{{- if .ExternalInfo.Youtube.WatchURL }}
Trailer: [url={{ .ExternalInfo.Youtube.WatchURL }}]{{ .ExternalInfo.Youtube.Title }}[/url]
{{- end}}