{"id":18258977,"url":"https://github.com/5rahim/tanuki","last_synced_at":"2025-04-08T23:36:42.800Z","repository":{"id":199987496,"uuid":"704730503","full_name":"5rahim/tanuki","owner":"5rahim","description":"Anime video filename parser in Golang, Anitogo Fork.","archived":false,"fork":false,"pushed_at":"2023-11-20T17:58:06.000Z","size":86,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-04-06T06:36:17.802Z","etag":null,"topics":["anime","anime-torrent","anitogo","anitomy","parser"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/5rahim.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-13T23:40:20.000Z","updated_at":"2024-07-10T06:00:25.000Z","dependencies_parsed_at":"2023-11-20T18:46:26.401Z","dependency_job_id":null,"html_url":"https://github.com/5rahim/tanuki","commit_stats":null,"previous_names":["seanime-app/tanuki","5rahim/tanuki"],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5rahim%2Ftanuki","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5rahim%2Ftanuki/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5rahim%2Ftanuki/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/5rahim%2Ftanuki/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/5rahim","download_url":"https://codeload.github.com/5rahim/tanuki/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247947823,"owners_count":21023058,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anime","anime-torrent","anitogo","anitomy","parser"],"created_at":"2024-11-05T10:35:41.574Z","updated_at":"2025-04-08T23:36:42.771Z","avatar_url":"https://github.com/5rahim.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🦝 Tanuki\n\nTanuki is a Golang library for parsing anime video filenames. \n\nIt is a **fork** of [Anitogo](https://github.com/nssteinbrenner/anitogo), which itself is based off of [Anitomy](https://github.com/erengy/anitomy) and [Anitopy](https://github.com/igorcmoura/anitopy).\n\n## Changes\n\nTanuki simply handles more cases while avoiding regression.\n\n### Anitogo\n```txt\n {\n  \"file_name\": \"Byousoku 5 Centimeter [Blu-Ray][1920x1080 H.264][2.0ch AAC][SOFTSUBS]\",\n  \"anime_title\": \"Byousoku\",\n  \"episode_number\": [\"5\"],\n  \"episode_title\": \"Centimeter\",\n  ...\n}\n```\n\n### 🦝 Tanuki\n```txt\n{\n  \"file_name\": \"Byousoku 5 Centimeter [Blu-Ray][1920x1080 H.264][2.0ch AAC][SOFTSUBS]\",\n  \"anime_title\": \"Byousoku 5 Centimeter\",\n  ...\n}\n```\n\n---\n\n### Anitogo\n```txt\n {\n  \"file_name\": \"S01E05 - Episode title.mkv\",\n  \"anime_title\": \"S01E05 - Episode title\",\n  ...\n}\n```\n\n### 🦝 Tanuki\n```txt\n{\n  \"file_name\": \"S01E05 - Episode title.mkv\",\n  \"anime_season\": [\"01\"],\n  \"episode_number\": [\"05\"],\n  \"episode_title\": \"Episode title\",\n  ...\n}\n```\n\n---\n\n### Anitogo\n```txt\n {\n  \"file_name\": \"[Judas] Aharen-san wa Hakarenai - S01E06v2.mkv\",\n  \"anime_title\": \"Aharen-san wa Hakarenai - S01E06v2\",\n  ...\n}\n```\n\n### 🦝 Tanuki\n```txt\n{\n  \"file_name\": \"[Judas] Aharen-san wa Hakarenai - S01E06v2.mkv\",\n  \"anime_title\": \"Aharen-san wa Hakarenai\",\n  \"anime_season\": [\"01\"],\n  \"episode_number\": [\"06\"],\n  ...\n}\n```\n\n---\n\n- Added `anime_part`\n- Better parsing of `anime_title`\n- Updated keywords\n- Fixed:\n  - Incorrect episode detection, e.g, now: `Rozen Maiden 3` != `episode 3`, `Byousoku 5 Centimeter` != `episode 5`\n  - Incorrect versioning detection, e.g, `S01E01v2`, `- 05'` are parsed correctly now\n- Support for:\n  - Higher episode numbers\n  - Absence of title, e.g, `S01E05 - Episode title.mkv`\n  - Season ranges, e.g, `S1-2`, `Seasons 1-2`, `Seasons 1 ~ 2`, etc...\n  - Enclosed keywords, e.g, `Hyouka (2012) [Season 1+OVA] [BD 1080p HEVC OPUS] [Dual-Audio]`\n\n---\n\n## Example\nThe following filename...\n\n    [Trix] Shingeki no Kyojin - S04E29-31 (Part 3) [Multi Subs] (1080p AV1 E-AC3)\"\n\n...is resolved into:\n\n```json\n{\n  \"file_name\": \"[Trix] Shingeki no Kyojin - S04E29-31 (Part 3) [Multi Subs] (1080p AV1 E-AC3)\",\n  \"anime_title\": \"Shingeki no Kyojin\",\n  \"anime_season\": [\"04\"],\n  \"anime_part\": [\"3\"],\n  \"episode_number\": [\"29\", \"31\"],\n  \"release_group\": \"Trix\",\n  \"video_resolution\": \"1080p\",\n  \"video_term\": [\"AV1\"]\n}\n```\n\nThe following example code:\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    \"encoding/json\"\n\n    \"github.com/5rahim/tanuki\"\n)\n\nfunc main() {\n    parsed := tanuki.Parse(\"[Nubles] Space Battleship Yamato 2199 (2012) episode 18 (720p 10 bit AAC)[1F56D642]\", tanuki.DefaultOptions)\n    jsonParsed, err := json.MarshalIndent(parsed, \"\", \"    \")\n    if err != nil {\n        fmt.Println(err)\n    }\n    fmt.Println(string(jsonParsed) + \"\\n\")\n\n    // Accessing the elements directly\n    fmt.Println(\"Anime Title:\", parsed.AnimeTitle)\n    fmt.Println(\"Anime Year:\", parsed.AnimeYear)\n    fmt.Println(\"Episode Number:\", parsed.EpisodeNumber)\n    fmt.Println(\"Release Group:\", parsed.ReleaseGroup)\n    fmt.Println(\"File Checksum:\", parsed.FileChecksum)\n}\n```\n\nWill output:\n\n```go\n{\n    \"anime_title\": \"Space Battleship Yamato 2199\",\n    \"anime_year\": \"2012\",\n    \"audio_term\": [\"AAC\"],\n    \"episode_number\": [\"18\"],\n    \"file_checksum\": \"1F56D642\",\n    \"file_name\": \"[Nubles] Space Battleship Yamato 2199 (2012) episode 18 (720p 10 bit AAC)[1F56D642]\",\n    \"release_group\": \"Nubles\",\n    \"video_resolution\": \"720p\"\n}\n```\n\nThe Parse function returns a pointer to an Elements struct. The full definition of the struct is here:\n\n```go\ntype elements struct {\n    AnimeSeason         []string  `json:\"anime_season,omitempty\"`\n    AnimeSeasonPrefix   []string  `json:\"anime_season_prefix,omitempty\"`\n    AnimePart           []string  `json:\"anime_part,omitempty\"`\n    AnimePartPrefix     []string  `json:\"anime_part_prefix,omitempty\"`\n    AnimeTitle          string    `json:\"anime_title,omitempty\"`\n    AnimeType           []string  `json:\"anime_type,omitempty\"`\n    AnimeYear           string    `json:\"anime_year,omitempty\"`\n    AudioTerm           []string  `json:\"audio_term,omitempty\"`\n    DeviceCompatibility []string  `json:\"device_compatibility,omitempty\"`\n    EpisodeNumber       []string  `json:\"episode_number,omitempty\"`\n    EpisodeNumberAlt    []string  `json:\"episode_number_alt,omitempty\"`\n    EpisodePrefix       []string  `json:\"episode_prefix,omitempty\"`\n    EpisodeTitle        string    `json:\"episode_title,omitempty\"`\n    FileChecksum        string    `json:\"file_checksum,omitempty\"`\n    FileExtension       string    `json:\"file_extension,omitempty\"`\n    FileName            string    `json:\"file_name,omitempty\"`\n    Language            []string  `json:\"language,omitempty\"`\n    Other               []string  `json:\"other,omitempty\"`\n    ReleaseGroup        string    `json:\"release_group,omitempty\"`\n    ReleaseInformation  []string  `json:\"release_information,omitempty\"`\n    ReleaseVersion      []string  `json:\"release_version,omitempty\"`\n    Source              []string  `json:\"source,omitempty\"`\n    Subtitles           []string  `json:\"subtitles,omitempty\"`\n    VideoResolution     string    `json:\"video_resolution,omitempty\"`\n    VideoTerm           []string  `json:\"video_term,omitempty\"`\n    VolumeNumber        []string  `json:\"volume_number,omitempty\"`\n    VolumePrefix        []string  `json:\"volume_prefix,omitempty\"`\n    Unknown             []string  `json:\"unknown,omitempty\"`\n    checkAltNumber      bool\n}\n```\n\nSample results encoded in JSON can be seen in the tests/data.json file.\n\n## Installation\nGet the package:\n\n    go get -u github.com/5rahim/tanuki\n\nThen, import it in your code:\n\n    import \"github.com/5rahim/tanuki\"\n\n## Options\nThe Parse function receives the filename and an Options struct. The default options are as follows:\n\n    var DefaultOptions = Options{\n        AllowedDelimiters:  \" _.\u0026+,|\", // Parse these as delimiters\n        IgnoredStrings:     []string{}, // Ignore these when they are in the filename\n        ParseEpisodeNumber: true, // Parse the episode number and include it in the elements\n        ParseEpisodeTitle:  true, // Parse the episode title and include it in the elements\n        ParseFileExtension: true, // Parse the file extension and include it in the elements\n        ParseReleaseGroup:  true, // Parse the release group and include it in the elements\n    }","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F5rahim%2Ftanuki","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F5rahim%2Ftanuki","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F5rahim%2Ftanuki/lists"}