node.anitomy.js is a Node.js binding for
Anitomy a C++ library for parsing anime
video filenames.
You can install node.anitomy.js as a dependency of your project using NPM like so, provided you have met the dependencies listed below.
> npm install --save anitomyjs
- Node.JS >= 4.0.0
- CMake >= 3.2
- A C++14 compatible compiler
- GCC >= 5
- Clang >= 3.4 (According to the Clang CXX status page)
- Visual Studio 2017 OR Build Tools for Visual Studio 2017
const anitomy = require('anitomyjs');
const filename = '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv';
const elems = anitomy.parseSync(filename);
console.log(elems.AnimeTitle + ' #' + elems.EpisodeNumber +
' by ' + elems.ReleaseGroup);Would output:
Toradora! #01 by TaigaSubs
Parses the filenames asynchronously.
filenamesmust be either a string, or an array of strings.optionsis optional, if provided it must be an object, as set out here.callbackmust be a function, will be called passing the resulting elements as the first parameter.- If
filenameswas an array, then the passed value will be an array of AnitomyElements, with the same ordering asfilenames. - If
filenameswas a string, then the passed value will be an AnitomyElements.
- If
const filename = '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv';
anitomy.parse(filename, function (elems) {
console.log(elems.AnimeTitle + ' #' + elems.EpisodeNumber +
' by ' + elems.ReleaseGroup);
});Would output:
Toradora! #01 by TaigaSubs
Parses the filenames synchronously.
filenamesmust be either a string, or an array of strings.optionsis optional, if provided it must be an object, as set out here.- Returns:
- If
filenameswas an array, then the returned value will be an array of AnitomyElements, with the same ordering asfilenames. - If
filenameswas a string, then the returned value will be an AnitomyElements.
- If
const filename = '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv';
const elems = anitomy.parseSync(filename);
console.log(elems.AnimeTitle + ' #' + elems.EpisodeNumber +
' by ' + elems.ReleaseGroup);Would output:
Toradora! #01 by TaigaSubs
Parses each of the individual filenames asynchronously, as opposed to parse which parses them all in bulk. As it is asynchronous there is no ordering ensured.
filenamesmust be either a string, or an array of strings.optionsis optional, if provided it must be an object, as set out here.callbackmust be a function, will be called when each filename is parsed, passing the filename and the resulting AnitomyElements as the first and second parameters respectively.
const filenames = [
'[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv',
'[ANBU]_Princess_Lover!_-_01_[2048A39A].mkv',
'[ANBU-Menclave]_Canaan_-_01_[1024x576_H.264_AAC][12F00E89].mkv',
'[ANBU-umai]_Haiyoru!_Nyaru-Ani_[596DD8E6].mkv'
];
anitomy.parseEach(filenames, function (filename, elems) {
console.log(filename + '\n\t=> ' + elems.AnimeTitle + ' #' + elems.EpisodeNumber +
' by ' + elems.ReleaseGroup);
});Would output (though not necessarily in this order):
[ANBU]_Princess_Lover!_-_01_[2048A39A].mkv
=> Princess Lover! #01 by ANBU
[ANBU-Menclave]_Canaan_-_01_[1024x576_H.264_AAC][12F00E89].mkv
=> Canaan #01 by ANBU-Menclave
[ANBU-umai]_Haiyoru!_Nyaru-Ani_[596DD8E6].mkv
=> Haiyoru! Nyaru-Ani #undefined by ANBU-umai
[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv
=> Toradora! #01 by TaigaSubs
Same as parseEach but synchronous, i.e.
calls callback for each parsed filename, then returns. callback is ensured to
be called in the same order as filenames.
filenamesmust be either a string, or an array of strings.optionsis optional, if provided it must be an object, as set out here.callbackmust be a function, will be called when each filename is parsed, passing the filename and the resulting AnitomyElements as the first and second parameters respectively.
const filenames = [
'[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv',
'[ANBU]_Princess_Lover!_-_01_[2048A39A].mkv',
'[ANBU-Menclave]_Canaan_-_01_[1024x576_H.264_AAC][12F00E89].mkv',
'[ANBU-umai]_Haiyoru!_Nyaru-Ani_[596DD8E6].mkv'
];
anitomy.parseEachSync(filenames, function (filename, elems) {
console.log(filename + '\n\t=> ' + elems.AnimeTitle + ' #' + elems.EpisodeNumber +
' by ' + elems.ReleaseGroup);
});
console.log('parseEachSync completed');Would output:
[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv
=> Toradora! #01 by TaigaSubs
[ANBU]_Princess_Lover!_-_01_[2048A39A].mkv
=> Princess Lover! #01 by ANBU
[ANBU-Menclave]_Canaan_-_01_[1024x576_H.264_AAC][12F00E89].mkv
=> Canaan #01 by ANBU-Menclave
[ANBU-umai]_Haiyoru!_Nyaru-Ani_[596DD8E6].mkv
=> Haiyoru! Nyaru-Ani #undefined by ANBU-umai
parseEachSync completed
Options are given in the form of an object, with any or all of the following properties set, if unset they default to these values (Anitomy's defaults):
{
allowedDelimiters: ' _.&+,|',
ignoredStrings: [],
parseEpisodeNumber: true,
parseEpisodeTitle: true,
parseFileExtension: true,
parseReleaseGroup: true
}This object represents the parsed elements of the filename. With a property for each ElementCategory that it has a value for, the properties are immutable. In cases where there are multiple elements in a category the property's value will be an array.
AnitomyElements {
AnimeTitle: 'Toradora!',
AnimeYear: '2008',
AudioTerm: 'FLAC',
EpisodeNumber: '01',
EpisodeTitle: 'Tiger and Dragon',
FileChecksum: '1234ABCD',
FileExtension: 'mkv',
FileName: '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD]',
ReleaseGroup: 'TaigaSubs',
ReleaseVersion: '2',
VideoResolution: '1280x720',
VideoTerm: 'H.264' }Returns true if the AnitomyElements has no category-value pairs.
categoryis optional, if provided must be a string representing an ElementCategory, return value will then be true if the AnitomyElements has no values for that category.
const filename = '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv';
const elems = anitomy.parseSync(filename);
/* -> AnitomyElements {
AnimeTitle: 'Toradora!',
AnimeYear: '2008',
AudioTerm: 'FLAC',
EpisodeNumber: '01',
EpisodeTitle: 'Tiger and Dragon',
FileChecksum: '1234ABCD',
FileExtension: 'mkv',
FileName: '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD]',
ReleaseGroup: 'TaigaSubs',
ReleaseVersion: '2',
VideoResolution: '1280x720',
VideoTerm: 'H.264' } */
const isEmpty = elems.empty();
// -> false
const hasNoVolumeNumber = elems.empty('VolumeNumber');
// -> trueReturns the number of values associated with the category in this AnitomyElements.
categorymust be a string representing an ElementCategory.
const filename = 'Detective Conan - 316-317 [DCTP][2411959B].mkv';
const elems = anitomy.parseSync(filename);
/* -> AnitomyElements {
AnimeTitle: 'Detective Conan',
EpisodeNumber: [ '316', '317' ],
FileChecksum: '2411959B',
FileExtension: 'mkv',
FileName: 'Detective Conan - 316-317 [DCTP][2411959B]',
ReleaseGroup: 'DCTP' } */
const numOfEpNumbers = elems.count('EpisodeNumber');
// -> 2Returns the number of category-value pairs this AnitomyElements has.
const filename = '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD].mkv';
const elems = anitomy.parseSync(filename);
/* -> AnitomyElements {
AnimeTitle: 'Toradora!',
AnimeYear: '2008',
AudioTerm: 'FLAC',
EpisodeNumber: '01',
EpisodeTitle: 'Tiger and Dragon',
FileChecksum: '1234ABCD',
FileExtension: 'mkv',
FileName: '[TaigaSubs]_Toradora!_(2008)_-_01v2_-_Tiger_and_Dragon_[1280x720_H.264_FLAC][1234ABCD]',
ReleaseGroup: 'TaigaSubs',
ReleaseVersion: '2',
VideoResolution: '1280x720',
VideoTerm: 'H.264' } */
const size = elems.size();
// -> 12Returns the first value associated with the category in this AnitomyElements, or an empty string if none.
categorymust be a string representing an ElementCategory.
const filename = 'Detective Conan - 316-317 [DCTP][2411959B].mkv';
const elems = anitomy.parseSync(filename);
/* -> AnitomyElements {
AnimeTitle: 'Detective Conan',
EpisodeNumber: [ '316', '317' ],
FileChecksum: '2411959B',
FileExtension: 'mkv',
FileName: 'Detective Conan - 316-317 [DCTP][2411959B]',
ReleaseGroup: 'DCTP' } */
const firstEpNum = elems.get('EpisodeNumber');
// -> '316'Returns an array of all the values associated with the category in this AnitomyElements, or an empty array if none.
categorymust be a string representing an ElementCategory.
const filename = 'Detective Conan - 316-317 [DCTP][2411959B].mkv';
const elems = anitomy.parseSync(filename);
/* -> AnitomyElements {
AnimeTitle: 'Detective Conan',
EpisodeNumber: [ '316', '317' ],
FileChecksum: '2411959B',
FileExtension: 'mkv',
FileName: 'Detective Conan - 316-317 [DCTP][2411959B]',
ReleaseGroup: 'DCTP' } */
const epNums = elems.getAll('EpisodeNumber');
// -> [ '316', '317' ]The element category names are the same as in anitomy::ElementCategory,
without the anitomy::kElement prefix:
[
'AnimeSeason',
'AnimeSeasonPrefix',
'AnimeTitle',
'AnimeType',
'AnimeYear',
'AudioTerm',
'DeviceCompatibility',
'EpisodeNumber',
'EpisodeNumberAlt',
'EpisodePrefix',
'EpisodeTitle',
'FileChecksum',
'FileExtension',
'FileName',
'Language',
'Other',
'ReleaseGroup',
'ReleaseInformation',
'ReleaseVersion',
'Source',
'Subtitles',
'VideoResolution',
'VideoTerm',
'VolumeNumber',
'VolumePrefix'
]node.anitomy.js is licensed under Mozilla Public License 2.0.
