├── files ├── .env ├── single_composes │ ├── autobrr.yml │ ├── plex.yml │ ├── jellyfin.yml │ ├── qbittorrent.yml │ ├── shoko-server.yml │ └── vpn-qbittorrent.yml ├── compose-plex-novpn.yml ├── compose-jellyfin-novpn.yml ├── compose-plex-vpn.yml ├── compose-jellyfin-vpn.yml └── scripts │ └── renamer.lua └── README.md /files/.env: -------------------------------------------------------------------------------- 1 | PGID=1000 2 | PUID=1000 3 | TZ=Europe/Rome 4 | DOCKERSTORAGEDIR=~/storage 5 | COMPOSE_PROJECT_NAME=selfhosted-anime -------------------------------------------------------------------------------- /files/single_composes/autobrr.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | autobrr: 5 | container_name: autobrr 6 | image: ghcr.io/autobrr/autobrr:latest 7 | environment: 8 | PGID: ${PGID} 9 | PUID: ${PUID} 10 | TZ: ${TZ} 11 | restart: unless-stopped 12 | networks: 13 | - downloadNetwork 14 | volumes: 15 | - autobrr:/config 16 | ports: 17 | - 7474:7474 18 | 19 | volumes: 20 | autobrr: 21 | external: true 22 | name: autobrr-volume 23 | 24 | networks: 25 | downloadNetwork: 26 | driver: bridge 27 | external: true 28 | -------------------------------------------------------------------------------- /files/single_composes/plex.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | plex: 5 | image: lscr.io/linuxserver/plex:latest 6 | container_name: plex 7 | environment: 8 | PGID: ${PGID} 9 | PUID: ${PUID} 10 | TZ: ${TZ} 11 | VERSION: docker 12 | networks: 13 | - plexNetwork 14 | volumes: 15 | - plex:/config 16 | - ${DOCKERSTORAGEDIR}:/storage 17 | ports: 18 | - 32400:32400 19 | restart: unless-stopped 20 | 21 | volumes: 22 | plex: 23 | external: true 24 | name: plex-volume 25 | 26 | networks: 27 | plexNetwork: 28 | driver: bridge 29 | external: true 30 | -------------------------------------------------------------------------------- /files/single_composes/jellyfin.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | jellyfin: 5 | container_name: jellyfin 6 | image: lscr.io/linuxserver/jellyfin:latest 7 | environment: 8 | PGID: ${PGID} 9 | PUID: ${PUID} 10 | TZ: ${TZ} 11 | restart: unless-stopped 12 | networks: 13 | - jellyNetwork 14 | volumes: 15 | - jellyfin:/config 16 | - ${DOCKERSTORAGEDIR}/medialibrary:/data 17 | ports: 18 | - 8096:8096 19 | 20 | volumes: 21 | jellyfin: 22 | external: true 23 | name: jellyfin-volume 24 | 25 | networks: 26 | jellyNetwork: 27 | driver: bridge 28 | external: true 29 | -------------------------------------------------------------------------------- /files/single_composes/qbittorrent.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | qbittorrent: 5 | image: lscr.io/linuxserver/qbittorrent:latest 6 | container_name: qbittorrent 7 | environment: 8 | PGID: ${PGID} 9 | PUID: ${PUID} 10 | TZ: ${TZ} 11 | restart: unless-stopped 12 | networks: 13 | - downloadNetwork 14 | volumes: 15 | - qbittorrent:/config 16 | - ${DOCKERSTORAGEDIR}:/storage 17 | ports: 18 | - 8080:8080 19 | 20 | volumes: 21 | qbittorrent: 22 | external: true 23 | name: qbittorrent-volume 24 | 25 | networks: 26 | downloadNetwork: 27 | driver: bridge 28 | external: true 29 | -------------------------------------------------------------------------------- /files/single_composes/shoko-server.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | shoko_server: 5 | shm_size: 256m 6 | container_name: shokoserver 7 | image: shokoanime/server:daily # I personally use the 'daily' tag, but it is unstable so use the 'latest' tag if you want. 8 | environment: 9 | PGID: ${PGID} 10 | PUID: ${PUID} 11 | TZ: ${TZ} 12 | restart: unless-stopped 13 | networks: 14 | - jellyNetwork 15 | - plexNetwork 16 | volumes: 17 | - shoko:/home/shoko/.shoko 18 | - ${DOCKERSTORAGEDIR}:/mnt 19 | ports: 20 | - 8111:8111 21 | 22 | volumes: 23 | shoko: 24 | external: true 25 | name: shoko-volume 26 | 27 | networks: 28 | jellyNetwork: 29 | driver: bridge 30 | external: true 31 | plexNetwork: 32 | driver: bridge 33 | external: true 34 | -------------------------------------------------------------------------------- /files/single_composes/vpn-qbittorrent.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | # qBittorrentvpn - https://github.com/binhex/arch-qbittorrentvpn 5 | # compose thanks to https://gist.github.com/TRaSH-/68cd26deb5e6269e5eb8114f93b429ab 6 | qbittorrentvpn: 7 | privileged: true 8 | cap_add: 9 | - NET_ADMIN 10 | container_name: qbittorrentvpn 11 | image: binhex/arch-qbittorrentvpn:latest 12 | environment: 13 | PGID: ${PGID} 14 | PUID: ${PUID} 15 | TZ: ${TZ} 16 | UMASK: 022 17 | DEBUG: false 18 | VPN_ENABLED: yes 19 | VPN_CLIENT: openvpn 20 | VPN_USER: "" 21 | VPN_PASS: "" 22 | VPN_PROV: custom 23 | STRICT_PORT_FORWARD: no 24 | LAN_NETWORK: 192.168.1.0/24 25 | NAME_SERVERS: 84.200.69.80,37.235.1.174,1.1.1.1,37.235.1.177,84.200.70.40,1.0.0.1 26 | WEBUI_PORT: 8080 27 | restart: unless-stopped 28 | networks: 29 | - downloadNetwork 30 | volumes: 31 | - /etc/localtime:/etc/localtime:ro 32 | - qbittorrentvpn:/config 33 | - ${DOCKERSTORAGEDIR}:/storage 34 | ports: 35 | - 8080:8080/tcp 36 | 37 | volumes: 38 | qbittorrentvpn: 39 | external: true 40 | name: qbittorrentvpn-volume 41 | 42 | networks: 43 | downloadNetwork: 44 | driver: bridge 45 | external: true 46 | -------------------------------------------------------------------------------- /files/compose-plex-novpn.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | x-default-conf: &default_conf 4 | restart: unless-stopped 5 | networks: 6 | - downloadNetwork 7 | 8 | x-default-conf-plex: &default_conf_plex 9 | restart: unless-stopped 10 | networks: 11 | - plexNetwork 12 | 13 | x-environment: &environment 14 | PGID: ${PGID} 15 | PUID: ${PUID} 16 | TZ: ${TZ} 17 | 18 | services: 19 | qbittorrent: 20 | image: lscr.io/linuxserver/qbittorrent:latest 21 | container_name: qbittorrent 22 | environment: 23 | <<: *environment 24 | <<: *default_conf 25 | volumes: 26 | - qbittorrent:/config 27 | - ${DOCKERSTORAGEDIR}:/storage 28 | ports: 29 | - 8080:8080 30 | 31 | autobrr: 32 | container_name: autobrr 33 | image: ghcr.io/autobrr/autobrr:latest 34 | environment: 35 | <<: *environment 36 | <<: *default_conf 37 | volumes: 38 | - autobrr:/config 39 | ports: 40 | - 7474:7474 41 | 42 | shoko_server: 43 | shm_size: 256m 44 | container_name: shokoserver 45 | image: shokoanime/server:daily # I personally use the 'daily' tag, but it is unstable so use the 'latest' tag if you want. 46 | environment: 47 | <<: *environment 48 | <<: *default_conf_plex 49 | volumes: 50 | - shoko:/home/shoko/.shoko 51 | - ${DOCKERSTORAGEDIR}:/mnt 52 | ports: 53 | - 8111:8111 54 | 55 | plex: 56 | image: lscr.io/linuxserver/plex:latest 57 | container_name: plex 58 | environment: 59 | <<: *environment 60 | <<: *default_conf_plex 61 | volumes: 62 | - plex:/config 63 | - ${DOCKERSTORAGEDIR}:/storage 64 | ports: 65 | - 32400:32400 66 | 67 | volumes: 68 | plex: 69 | external: true 70 | name: plex-volume 71 | autobrr: 72 | external: true 73 | name: autobrr-volume 74 | qbittorrent: 75 | external: true 76 | name: qbittorrent-volume 77 | shoko: 78 | external: true 79 | name: shoko-volume 80 | 81 | networks: 82 | downloadNetwork: 83 | driver: bridge 84 | external: true 85 | plexNetwork: 86 | driver: bridge 87 | external: true 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to the selfhosted-anime guide! 2 | 3 | This project uses **Docker** for its infrastructure and **Ubuntu Linux** as its operating system, so anything else is out of my scope (_unless contributed_). This will give you a **stable and reliable** solution to manage your anime movies and tv-shows while having **proper metadata**. 4 | 5 | ### NOTE (01/20/2024): This guide doesn't include every container you might need, you could add Bazarr for subtitles for example, I'll just show you the basics and maybe update it in the future. 6 | 7 | - **I will NOT be using Sonarr and Radarr... but why?** 8 | - Two simple reasons, really: Sonarr/Radarr's integration with **TheTVDB** and the fact that you **can't change** it as a metadata source. 9 | - I like them as products, I use them daily, but with anime, TheTVDB doesn't offer as much as AniDB does. It may work for some shows, but some are going to be divided in "seasons" instead of aknowledging each "season" of said anime as its own being (Ex. Sailor Moon, Pokémon). 10 | 11 | ### If you don't like this decision and you're not okay to download some stuff manually, that's fine. Otherwise, happy reading! 12 | 13 | Along the way I'll explain how I did things **_my way_**, of course a lot of stuff can be changed and improved, that's up to you. 14 | 15 | The containers that will be used are the following: 16 | 17 | - qBittorrent (qBittorrentVPN as alternative) 18 | - Autobrr 19 | - Shoko-Server 20 | - Jellyfin (Plex as alternative) 21 | 22 | ## Important considerations 23 | 24 | - Shoko-server **REQUIRES** you to install **Shoko Desktop** to set up some important features, currently it's a **Windows only** application that requires a GUI. (you can install it on a different machine and on Linux, but more on it later) 25 | 26 | - You will have **some** automated downloads with Autobrr, but _it's not like the \*arrs_. 27 | 28 | - This guide will make **HEAVY** use of how TRaSH Guides sets up [hardlinks](https://trash-guides.info/), you should really give it a read **beforehand**. 29 | 30 |
31 | 32 | To dive in, read the [wiki](https://github.com/shyonae/selfhosted-anime/wiki). 33 | -------------------------------------------------------------------------------- /files/compose-jellyfin-novpn.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | x-default-conf: &default_conf 4 | restart: unless-stopped 5 | networks: 6 | - downloadNetwork 7 | 8 | x-default-conf-jelly: &default_conf_jelly 9 | restart: unless-stopped 10 | networks: 11 | - jellyNetwork 12 | 13 | x-environment: &environment 14 | PGID: ${PGID} 15 | PUID: ${PUID} 16 | TZ: ${TZ} 17 | 18 | services: 19 | qbittorrent: 20 | image: lscr.io/linuxserver/qbittorrent:latest 21 | container_name: qbittorrent 22 | environment: 23 | <<: *environment 24 | <<: *default_conf 25 | volumes: 26 | - qbittorrent:/config 27 | - ${DOCKERSTORAGEDIR}:/storage 28 | ports: 29 | - 8080:8080 30 | 31 | autobrr: 32 | container_name: autobrr 33 | image: ghcr.io/autobrr/autobrr:latest 34 | environment: 35 | <<: *environment 36 | <<: *default_conf 37 | volumes: 38 | - autobrr:/config 39 | ports: 40 | - 7474:7474 41 | 42 | shoko_server: 43 | shm_size: 256m 44 | container_name: shokoserver 45 | image: shokoanime/server:daily # I personally use the 'daily' tag, but it is unstable so use the 'latest' tag if you want. 46 | environment: 47 | <<: *environment 48 | <<: *default_conf_jelly 49 | volumes: 50 | - shoko:/home/shoko/.shoko 51 | - ${DOCKERSTORAGEDIR}:/mnt 52 | ports: 53 | - 8111:8111 54 | 55 | jellyfin: 56 | container_name: jellyfin 57 | image: lscr.io/linuxserver/jellyfin:latest 58 | environment: 59 | <<: *environment 60 | <<: *default_conf_jelly 61 | volumes: 62 | - jellyfin:/config 63 | - ${DOCKERSTORAGEDIR}/medialibrary:/data 64 | ports: 65 | - 8096:8096 66 | 67 | volumes: 68 | jellyfin: 69 | external: true 70 | name: jellyfin-volume 71 | autobrr: 72 | external: true 73 | name: autobrr-volume 74 | qbittorrent: 75 | external: true 76 | name: qbittorrent-volume 77 | shoko: 78 | external: true 79 | name: shoko-volume 80 | 81 | networks: 82 | downloadNetwork: 83 | driver: bridge 84 | external: true 85 | jellyNetwork: 86 | driver: bridge 87 | external: true 88 | -------------------------------------------------------------------------------- /files/compose-plex-vpn.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | x-default-conf: &default_conf 4 | restart: unless-stopped 5 | networks: 6 | - downloadNetwork 7 | 8 | x-default-conf-plex: &default_conf_plex 9 | restart: unless-stopped 10 | networks: 11 | - plexNetwork 12 | 13 | x-environment: &environment 14 | PGID: ${PGID} 15 | PUID: ${PUID} 16 | TZ: ${TZ} 17 | 18 | services: 19 | qbittorrentvpn: 20 | privileged: true 21 | cap_add: 22 | - NET_ADMIN 23 | container_name: qbittorrentvpn 24 | image: binhex/arch-qbittorrentvpn:latest 25 | environment: 26 | PGID: ${PGID} 27 | PUID: ${PUID} 28 | TZ: ${TZ} 29 | UMASK: 022 30 | DEBUG: false 31 | VPN_ENABLED: yes 32 | VPN_CLIENT: openvpn 33 | VPN_USER: "" 34 | VPN_PASS: "" 35 | VPN_PROV: custom 36 | STRICT_PORT_FORWARD: no 37 | LAN_NETWORK: 192.168.1.0/24 38 | NAME_SERVERS: 84.200.69.80,37.235.1.174,1.1.1.1,37.235.1.177,84.200.70.40,1.0.0.1 39 | WEBUI_PORT: 8080 40 | restart: unless-stopped 41 | networks: 42 | - downloadNetwork 43 | volumes: 44 | - /etc/localtime:/etc/localtime:ro 45 | - qbittorrentvpn:/config 46 | - ${DOCKERSTORAGEDIR}:/storage 47 | ports: 48 | - 8080:8080/tcp 49 | 50 | autobrr: 51 | container_name: autobrr 52 | image: ghcr.io/autobrr/autobrr:latest 53 | environment: 54 | <<: *environment 55 | <<: *default_conf 56 | volumes: 57 | - autobrr:/config 58 | ports: 59 | - 7474:7474 60 | 61 | shoko_server: 62 | shm_size: 256m 63 | container_name: shokoserver 64 | image: shokoanime/server:daily # I personally use the 'daily' tag, but it is unstable so use the 'latest' tag if you want. 65 | environment: 66 | <<: *environment 67 | <<: *default_conf_plex 68 | volumes: 69 | - shoko:/home/shoko/.shoko 70 | - ${DOCKERSTORAGEDIR}:/mnt 71 | ports: 72 | - 8111:8111 73 | 74 | plex: 75 | image: lscr.io/linuxserver/plex:latest 76 | container_name: plex 77 | environment: 78 | <<: *environment 79 | <<: *default_conf_plex 80 | volumes: 81 | - plex:/config 82 | - ${DOCKERSTORAGEDIR}:/storage 83 | ports: 84 | - 32400:32400 85 | 86 | volumes: 87 | plex: 88 | external: true 89 | name: plex-volume 90 | autobrr: 91 | external: true 92 | name: autobrr-volume 93 | qbittorrentvpn: 94 | external: true 95 | name: qbittorrentvpn-volume 96 | shoko: 97 | external: true 98 | name: shoko-volume 99 | 100 | networks: 101 | downloadNetwork: 102 | driver: bridge 103 | external: true 104 | plexNetwork: 105 | driver: bridge 106 | external: true 107 | -------------------------------------------------------------------------------- /files/compose-jellyfin-vpn.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | x-default-conf: &default_conf 4 | restart: unless-stopped 5 | networks: 6 | - downloadNetwork 7 | 8 | x-default-conf-jelly: &default_conf_jelly 9 | restart: unless-stopped 10 | networks: 11 | - jellyNetwork 12 | 13 | x-environment: &environment 14 | PGID: ${PGID} 15 | PUID: ${PUID} 16 | TZ: ${TZ} 17 | 18 | services: 19 | qbittorrentvpn: 20 | privileged: true 21 | cap_add: 22 | - NET_ADMIN 23 | container_name: qbittorrentvpn 24 | image: binhex/arch-qbittorrentvpn:latest 25 | environment: 26 | PGID: ${PGID} 27 | PUID: ${PUID} 28 | TZ: ${TZ} 29 | UMASK: 022 30 | DEBUG: false 31 | VPN_ENABLED: yes 32 | VPN_CLIENT: openvpn 33 | VPN_USER: "" 34 | VPN_PASS: "" 35 | VPN_PROV: custom 36 | STRICT_PORT_FORWARD: no 37 | LAN_NETWORK: 192.168.1.0/24 38 | NAME_SERVERS: 84.200.69.80,37.235.1.174,1.1.1.1,37.235.1.177,84.200.70.40,1.0.0.1 39 | WEBUI_PORT: 8080 40 | restart: unless-stopped 41 | networks: 42 | - downloadNetwork 43 | volumes: 44 | - /etc/localtime:/etc/localtime:ro 45 | - qbittorrentvpn:/config 46 | - ${DOCKERSTORAGEDIR}:/storage 47 | ports: 48 | - 8080:8080/tcp 49 | 50 | autobrr: 51 | container_name: autobrr 52 | image: ghcr.io/autobrr/autobrr:latest 53 | environment: 54 | <<: *environment 55 | <<: *default_conf 56 | volumes: 57 | - autobrr:/config 58 | ports: 59 | - 7474:7474 60 | 61 | shoko_server: 62 | shm_size: 256m 63 | container_name: shokoserver 64 | image: shokoanime/server:daily # I personally use the 'daily' tag, but it is unstable so use the 'latest' tag if you want. 65 | environment: 66 | <<: *environment 67 | <<: *default_conf_jelly 68 | volumes: 69 | - shoko:/home/shoko/.shoko 70 | - ${DOCKERSTORAGEDIR}:/mnt 71 | ports: 72 | - 8111:8111 73 | 74 | jellyfin: 75 | container_name: jellyfin 76 | image: lscr.io/linuxserver/jellyfin:latest 77 | environment: 78 | <<: *environment 79 | <<: *default_conf_jelly 80 | volumes: 81 | - jellyfin:/config 82 | - ${DOCKERSTORAGEDIR}/medialibrary:/data 83 | ports: 84 | - 8096:8096 85 | 86 | volumes: 87 | jellyfin: 88 | external: true 89 | name: jellyfin-volume 90 | autobrr: 91 | external: true 92 | name: autobrr-volume 93 | qbittorrentvpn: 94 | external: true 95 | name: qbittorrentvpn-volume 96 | shoko: 97 | external: true 98 | name: shoko-volume 99 | 100 | networks: 101 | downloadNetwork: 102 | driver: bridge 103 | external: true 104 | jellyNetwork: 105 | driver: bridge 106 | external: true 107 | -------------------------------------------------------------------------------- /files/scripts/renamer.lua: -------------------------------------------------------------------------------- 1 | remove_illegal_chars = false 2 | replace_illegal_chars = true 3 | 4 | local maxnamelen = 35 5 | local animelanguage = Language.English 6 | local episodelanguage = Language.English 7 | local spacechar = " " 8 | 9 | local group = "" 10 | if (file.anidb and file.anidb.releasegroup) then 11 | group = "[" .. (file.anidb.releasegroup.shortname or file.anidb.releasegroup.name) .. "]" 12 | end 13 | local animename = anime:getname(animelanguage) or anime.preferredname 14 | 15 | -- CUSTOM CONDITION HERE -- 16 | if anime.type == AnimeType.Movie then 17 | destination = "Anime Movies" -- MODIFY ACCORDING TO DESTINATION FOLDER 18 | else 19 | destination = "Anime Shows" -- MODIFY ACCORDING TO DESTINATION FOLDER 20 | end 21 | 22 | local episodename = "" 23 | local engepname = episode:getname(Language.English) or "" 24 | local episodenumber = "" 25 | -- If the episode is not a complete movie then add an episode number 26 | if anime.type ~= AnimeType.Movie or not engepname:find("^Complete Movie") then 27 | local fileversion = "" 28 | if (file.anidb and file.anidb.version > 1) then 29 | fileversion = "v" .. file.anidb.version 30 | end 31 | -- Padding is determined from the number of episodes of the same type in the anime (#tostring() gives the number of digits required, e.g. 10 eps -> 2 digits) 32 | -- Padding is at least 2 digits 33 | local epnumpadding = math.max(#tostring(anime.episodecounts[episode.type]), 2) 34 | episodenumber = episode_numbers(epnumpadding) .. fileversion 35 | 36 | -- If this file is associated with a single episode and the episode doesn't have a generic name, then add the episode name 37 | if #episodes == 1 and not engepname:find("^Episode") and not engepname:find("^OVA") then 38 | episodename = episode:getname(episodelanguage) or "" 39 | end 40 | end 41 | 42 | local res = file.media.video.res or "" 43 | local codec = file.media.video.codec or "" 44 | local bitdepth = "" 45 | if (file.media.video.bitdepth and file.media.video.bitdepth ~= 8) then 46 | bitdepth = file.media.video.bitdepth .. "bit" 47 | end 48 | 49 | local dublangs = from(file.media.audio):select("language"):distinct() 50 | local sublangs = from(file.media.sublanguages):distinct() 51 | local source = "" 52 | local centag = "" 53 | if (file.anidb) then 54 | source = file.anidb.source 55 | -- Censorship is only relevent if the anime is age restricted 56 | if (anime.restricted) then 57 | if (file.anidb.censored) then 58 | centag = "[CEN]" 59 | else 60 | centag = "[UNCEN]" 61 | end 62 | end 63 | -- Dub and sub languages from anidb are usually more accurate 64 | -- But will return a single unknown language if there is none, needs to be fixed in Shoko 65 | dublangs = from(file.anidb.media.dublanguages):distinct() 66 | sublangs = from(file.anidb.media.sublanguages):distinct() 67 | end 68 | 69 | local langtag = "" 70 | local nonnativedublangs = dublangs:except({ Language.Japanese, Language.Chinese, Language.Korean, Language.Unknown }) 71 | if (nonnativedublangs:count() == 1 and dublangs:count() == 2) then 72 | langtag = "[DUAL-AUDIO]" 73 | elseif (dublangs:count() > 2) then 74 | langtag = "[MULTI-AUDIO]" 75 | elseif (nonnativedublangs:count() > 0) then 76 | langtag = "[DUB]" 77 | end 78 | 79 | 80 | local crchash = "" 81 | -- CRC can be null if disabled in Shoko settings, so need to check it 82 | if (file.hashes.crc) then 83 | crchash = "[" .. file.hashes.crc .. "]" 84 | end 85 | 86 | local fileinfo = "(" .. table.concat({ res, codec, bitdepth, source }, " "):cleanspaces(spacechar) .. ")" 87 | 88 | local namelist = { 89 | group, 90 | animename:truncate(maxnamelen), 91 | episodenumber, 92 | episodename:truncate(maxnamelen), 93 | fileinfo, 94 | langtag, 95 | centag, 96 | crchash, 97 | } 98 | 99 | filename = table.concat(namelist, " "):cleanspaces(spacechar) 100 | subfolder = { animename } --------------------------------------------------------------------------------