├── .gitignore ├── .travis.yml ├── core.js ├── index.js ├── package.json ├── parts ├── common.js ├── excess.js └── title.js ├── project.sublime-project ├── readme.md └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | project.sublime-workspace 2 | node_modules 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10" 4 | -------------------------------------------------------------------------------- /core.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var EventEmitter = require('events').EventEmitter; 4 | 5 | var Core = function() { 6 | EventEmitter.call(this); 7 | 8 | var parts; 9 | 10 | this.getParts = function() { 11 | return parts; 12 | }; 13 | 14 | this.on('setup', function () { 15 | parts = {}; 16 | }); 17 | 18 | this.on('part', function (part) { 19 | parts[part.name] = part.clean; 20 | }); 21 | }; 22 | 23 | Core.prototype = Object.create(EventEmitter.prototype); 24 | Core.prototype.constructor = EventEmitter; 25 | 26 | Core.prototype.exec = function(name) { 27 | this.emit('setup', { 28 | name: name 29 | }); 30 | this.emit('start'); 31 | this.emit('end'); 32 | 33 | return this.getParts(); 34 | }; 35 | 36 | module.exports = new Core(); 37 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('./parts/common'); 4 | require('./parts/title'); 5 | require('./parts/excess'); 6 | 7 | module.exports = function(name) { 8 | return require('./core').exec(name); 9 | }; 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parse-torrent-name", 3 | "version": "0.5.4", 4 | "description": "Parses torrent name of a movie or TV show.", 5 | "repository": { 6 | "type": "git", 7 | "url": "git://github.com/jzjzjzj/parse-torrent-name.git" 8 | }, 9 | "homepage": "https://github.com/jzjzjzj/parse-torrent-name", 10 | "bugs": { 11 | "url": "https://github.com/jzjzjzj/parse-torrent-name/issues" 12 | }, 13 | "keywords": [ 14 | "torrent", 15 | "parse torrent name" 16 | ], 17 | "devDependencies": { 18 | "tape": "^3.0.1", 19 | "tap-spec": "^1.0.1" 20 | }, 21 | "scripts": { 22 | "test": "tape test.js | tap-spec" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /parts/common.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var core = require('../core'); 4 | 5 | /** 6 | * Pattern should contain either none or two capturing groups. 7 | * In case of two groups - 1st is raw, 2nd is clean. 8 | */ 9 | var patterns = { 10 | season: /([Ss]?([0-9]{1,2}))[Eex]/, 11 | episode: /([Eex]([0-9]{2})(?:[^0-9]|$))/, 12 | year: /([\[\(]?((?:19[0-9]|20[01])[0-9])[\]\)]?)/, 13 | resolution: /(([0-9]{3,4}p))[^M]/, 14 | quality: /(?:PPV\.)?[HP]DTV|(?:HD)?CAM|B[rR]Rip|TS|(?:PPV )?WEB-?DL(?: DVDRip)?|H[dD]Rip|DVDRip|DVDRiP|DVDRIP|CamRip|W[EB]B[rR]ip|[Bb]lu[Rr]ay|DvDScr|hdtv/, 15 | codec: /xvid|x264|h\.?264/i, 16 | audio: /MP3|DD5\.?1|Dual[\- ]Audio|LiNE|DTS|AAC(?:\.?2\.0)?|AC3(?:\.5\.1)?/, 17 | group: /(- ?([^-]+(?:-={[^-]+-?$)?))$/, 18 | region: /R[0-9]/, 19 | extended: /EXTENDED/, 20 | hardcoded: /HC/, 21 | proper: /PROPER/, 22 | repack: /REPACK/, 23 | container: /MKV|AVI/, 24 | widescreen: /WS/, 25 | website: /^(\[ ?([^\]]+?) ?\])/, 26 | language: /rus\.eng/, 27 | garbage: /1400Mb|3rd Nov| ((Rip))/ 28 | }; 29 | var types = { 30 | season: 'integer', 31 | episode: 'integer', 32 | year: 'integer', 33 | extended: 'boolean', 34 | hardcoded: 'boolean', 35 | proper: 'boolean', 36 | repack: 'boolean', 37 | widescreen: 'boolean' 38 | }; 39 | var torrent; 40 | 41 | core.on('setup', function (data) { 42 | torrent = data; 43 | }); 44 | 45 | core.on('start', function() { 46 | var key, match, index, clean, part; 47 | 48 | for(key in patterns) { 49 | if(patterns.hasOwnProperty(key)) { 50 | if(!(match = torrent.name.match(patterns[key]))) { 51 | continue; 52 | } 53 | 54 | index = { 55 | raw: match[1] ? 1 : 0, 56 | clean: match[1] ? 2 : 0 57 | }; 58 | 59 | if(types[key] && types[key] === 'boolean') { 60 | clean = true; 61 | } 62 | else { 63 | clean = match[index.clean]; 64 | 65 | if(types[key] && types[key] === 'integer') { 66 | clean = parseInt(clean, 10); 67 | } 68 | } 69 | 70 | if(key === 'group') { 71 | if(clean.match(patterns.codec) || clean.match(patterns.quality)) { 72 | continue; 73 | } 74 | 75 | if(clean.match(/[^ ]+ [^ ]+ .+/)) { 76 | key = 'episodeName'; 77 | } 78 | } 79 | 80 | part = { 81 | name: key, 82 | match: match, 83 | raw: match[index.raw], 84 | clean: clean 85 | }; 86 | 87 | if(key === 'episode') { 88 | core.emit('map', torrent.name.replace(part.raw, '{episode}')); 89 | } 90 | 91 | core.emit('part', part); 92 | } 93 | } 94 | 95 | core.emit('common'); 96 | }); 97 | 98 | core.on('late', function (part) { 99 | if(part.name === 'group') { 100 | core.emit('part', part); 101 | } 102 | else if(part.name === 'episodeName') { 103 | part.clean = part.clean.replace(/[\._]/g, ' '); 104 | part.clean = part.clean.replace(/_+$/, '').trim(); 105 | core.emit('part', part); 106 | } 107 | }); 108 | -------------------------------------------------------------------------------- /parts/excess.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var core = require('../core'); 4 | 5 | var torrent, raw, groupRaw; 6 | var escapeRegex = function(string) { 7 | return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&'); 8 | }; 9 | 10 | core.on('setup', function (data) { 11 | torrent = data; 12 | raw = torrent.name; 13 | groupRaw = ''; 14 | }); 15 | 16 | core.on('part', function (part) { 17 | if(part.name === 'excess') { 18 | return; 19 | } 20 | else if(part.name === 'group') { 21 | groupRaw = part.raw; 22 | } 23 | 24 | // remove known parts from the excess 25 | raw = raw.replace(part.raw, ''); 26 | }); 27 | 28 | core.on('map', function (map) { 29 | torrent.map = map; 30 | }); 31 | 32 | core.on('end', function () { 33 | var clean, groupPattern, episodeNamePattern; 34 | 35 | // clean up excess 36 | clean = raw.replace(/(^[-\. ]+)|([-\. ]+$)/g, ''); 37 | clean = clean.replace(/[\(\)\/]/g, ' '); 38 | clean = clean.split(/\.\.+| +/).filter(Boolean); 39 | 40 | if(clean.length !== 0) { 41 | groupPattern = escapeRegex(clean[clean.length - 1] + groupRaw) + '$'; 42 | 43 | if(torrent.name.match(new RegExp(groupPattern))) { 44 | core.emit('late', { 45 | name: 'group', 46 | clean: clean.pop() + groupRaw 47 | }); 48 | } 49 | 50 | if(torrent.map && clean[0]) { 51 | episodeNamePattern = '{episode}' + escapeRegex(clean[0].replace(/_+$/, '')); 52 | 53 | if(torrent.map.match(new RegExp(episodeNamePattern))) { 54 | core.emit('late', { 55 | name: 'episodeName', 56 | clean: clean.shift() 57 | }); 58 | } 59 | } 60 | } 61 | 62 | if(clean.length !== 0) { 63 | core.emit('part', { 64 | name: 'excess', 65 | raw: raw, 66 | clean: clean.length === 1 ? clean[0] : clean 67 | }); 68 | } 69 | }); 70 | -------------------------------------------------------------------------------- /parts/title.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var core = require('../core'); 4 | 5 | require('./common'); 6 | 7 | var torrent, start, end, raw; 8 | 9 | core.on('setup', function (data) { 10 | torrent = data; 11 | start = 0; 12 | end = undefined; 13 | raw = undefined; 14 | }); 15 | 16 | core.on('part', function (part) { 17 | if(!part.match) { 18 | return; 19 | } 20 | 21 | if(part.match.index === 0) { 22 | start = part.match[0].length; 23 | 24 | return; 25 | } 26 | 27 | if(!end || part.match.index < end) { 28 | end = part.match.index; 29 | } 30 | }); 31 | 32 | core.on('common', function () { 33 | var raw = end ? torrent.name.substr(start, end - start).split('(')[0] : torrent.name; 34 | var clean = raw; 35 | 36 | // clean up title 37 | clean = raw.replace(/^ -/, ''); 38 | 39 | if(clean.indexOf(' ') === -1 && clean.indexOf('.') !== -1) { 40 | clean = clean.replace(/\./g, ' '); 41 | } 42 | 43 | clean = clean.replace(/_/g, ' '); 44 | clean = clean.replace(/([\(_]|- )$/, '').trim(); 45 | 46 | core.emit('part', { 47 | name: 'title', 48 | raw: raw, 49 | clean: clean 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /project.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "path": ".", 6 | "folder_exclude_patterns": [ 7 | "node_modules" 8 | ], 9 | "file_exclude_patterns": [ 10 | "npm-debug.log" 11 | ] 12 | } 13 | ], 14 | "settings": 15 | { 16 | "tab_size": 2, 17 | "translate_tabs_to_spaces": true, 18 | "default_line_ending": "unix", 19 | "ensure_newline_at_eof_on_save": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # parse-torrent-name [![Build Status](https://travis-ci.org/jzjzjzj/parse-torrent-name.svg?branch=master)](https://travis-ci.org/jzjzjzj/parse-torrent-name) [![Code Climate](https://codeclimate.com/github/jzjzjzj/parse-torrent-name/badges/gpa.svg)](https://codeclimate.com/github/jzjzjzj/parse-torrent-name) 2 | 3 | Parses torrent name of a movie or TV show. 4 | 5 | **Possible parts extracted:** 6 | 7 | - audio 8 | - codec 9 | - container 10 | - episode 11 | - episodeName 12 | - excess 13 | - extended 14 | - garbage 15 | - group 16 | - hardcoded 17 | - language 18 | - proper 19 | - quality 20 | - region 21 | - repack 22 | - resolution 23 | - season 24 | - title 25 | - website 26 | - widescreen 27 | - year 28 | 29 | ## Install: 30 | ```bash 31 | $ npm install parse-torrent-name 32 | ``` 33 | 34 | ## Usage: 35 | ```javascript 36 | var ptn = require('parse-torrent-name'); 37 | 38 | ptn('The.Staying.Alive.S05E02.720p.HDTV.x264-KILLERS[rartv]'); 39 | /* 40 | { season: 5, 41 | episode: 2, 42 | resolution: '720p', 43 | quality: 'HDTV', 44 | codec: 'x264', 45 | group: 'KILLERS[rartv]', 46 | title: 'The Staying Alive' } 47 | */ 48 | 49 | ptn('Captain Russia The Summer Soldier (2014) 1080p BrRip x264 - YIFY'); 50 | /* 51 | { year: 2014, 52 | resolution: '1080p', 53 | quality: 'BrRip', 54 | codec: 'x264', 55 | group: 'YIFY', 56 | title: 'Captain Russia The Summer Soldier' } 57 | */ 58 | 59 | ptn('AL.288-1.2014.HC.HDRip.XViD.AC3-juggs[ETRG]'); 60 | /* 61 | { year: 2014, 62 | quality: 'HDRip', 63 | codec: 'XViD', 64 | audio: 'AC3', 65 | group: 'juggs[ETRG]', 66 | hardcoded: true, 67 | title: 'AL 288-1' } 68 | */ 69 | ``` 70 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var ptn = require('./'); 4 | var tape = require('tape'); 5 | 6 | var torrents = [ 7 | { 8 | name: 'The Walking Dead S05E03 720p HDTV x264-ASAP[ettv]', 9 | title: 'The Walking Dead', 10 | season: 5, 11 | episode: 3, 12 | resolution: '720p', 13 | quality: 'HDTV', 14 | codec: 'x264', 15 | audio: undefined, 16 | group: 'ASAP[ettv]', 17 | extended: undefined, 18 | hardcoded: undefined, 19 | widescreen: undefined, 20 | website: undefined, 21 | excess: undefined 22 | }, 23 | { 24 | name: 'Hercules (2014) 1080p BrRip H264 - YIFY', 25 | title: 'Hercules', 26 | year: 2014, 27 | resolution: '1080p', 28 | quality: 'BrRip', 29 | codec: 'H264', 30 | group: 'YIFY' 31 | }, 32 | { 33 | name: 'Dawn.of.the.Planet.of.the.Apes.2014.HDRip.XViD-EVO', 34 | title: 'Dawn of the Planet of the Apes', 35 | year: 2014, 36 | quality: 'HDRip', 37 | codec: 'XViD', 38 | group: 'EVO' 39 | }, 40 | { 41 | name: 'The Big Bang Theory S08E06 HDTV XviD-LOL [eztv]', 42 | season: 8, 43 | episode: 6, 44 | quality: 'HDTV', 45 | codec: 'XviD', 46 | group: 'LOL [eztv]' 47 | }, 48 | { 49 | name: '22 Jump Street (2014) 720p BrRip x264 - YIFY', 50 | title: '22 Jump Street', 51 | episode: undefined 52 | }, 53 | { 54 | name: 'Hercules.2014.EXTENDED.1080p.WEB-DL.DD5.1.H264-RARBG', 55 | extended: true, 56 | quality: 'WEB-DL', 57 | audio: 'DD5.1', 58 | excess: undefined 59 | }, 60 | { 61 | name: 'Hercules.2014.EXTENDED.HDRip.XViD-juggs[ETRG]', 62 | extended: true, 63 | excess: undefined 64 | }, 65 | { 66 | name: 'Hercules (2014) WEBDL DVDRip XviD-MAX', 67 | quality: 'WEBDL DVDRip', 68 | excess: undefined 69 | }, 70 | { 71 | name: 'WWE Hell in a Cell 2014 PPV WEB-DL x264-WD -={SPARROW}=-', 72 | quality: 'PPV WEB-DL', 73 | group: 'WD -={SPARROW}=-', 74 | excess: undefined 75 | }, 76 | { 77 | name: 'UFC.179.PPV.HDTV.x264-Ebi[rartv]', 78 | title: 'UFC 179', 79 | quality: 'PPV.HDTV' 80 | }, 81 | { 82 | name: 'Marvels Agents of S H I E L D S02E05 HDTV x264-KILLERS [eztv]', 83 | title: 'Marvels Agents of S H I E L D' 84 | }, 85 | { 86 | name: 'X-Men.Days.of.Future.Past.2014.1080p.WEB-DL.DD5.1.H264-RARBG', 87 | title: 'X-Men Days of Future Past' 88 | }, 89 | { 90 | name: 'Guardians Of The Galaxy 2014 R6 720p HDCAM x264-JYK', 91 | region: 'R6', 92 | quality: 'HDCAM' 93 | }, 94 | { 95 | name: 'Marvel\'s.Agents.of.S.H.I.E.L.D.S02E01.Shadows.1080p.WEB-DL.DD5.1', 96 | title: 'Marvel\'s Agents of S H I E L D', 97 | episodeName: 'Shadows', 98 | audio: 'DD5.1', 99 | excess: undefined 100 | }, 101 | { 102 | name: 'Marvels Agents of S.H.I.E.L.D. S02E06 HDTV x264-KILLERS[ettv]', 103 | title: 'Marvels Agents of S.H.I.E.L.D.' 104 | }, 105 | { 106 | name: 'Guardians of the Galaxy (CamRip / 2014)', 107 | excess: undefined 108 | }, 109 | { 110 | name: 'The.Walking.Dead.S05E03.1080p.WEB-DL.DD5.1.H.264-Cyphanix[rartv]', 111 | codec: 'H.264', 112 | year: undefined, 113 | excess: undefined 114 | }, 115 | { 116 | name: 'Brave.2012.R5.DVDRip.XViD.LiNE-UNiQUE', 117 | region: 'R5', 118 | audio: 'LiNE', 119 | excess: undefined 120 | }, 121 | { 122 | name: 'Lets.Be.Cops.2014.BRRip.XViD-juggs[ETRG]', 123 | quality: 'BRRip' 124 | }, 125 | { 126 | name: 'These.Final.Hours.2013.WBBRip XViD', 127 | quality: 'WBBRip' 128 | }, 129 | { 130 | name: 'Downton Abbey 5x06 HDTV x264-FoV [eztv]', 131 | title: 'Downton Abbey', 132 | season: 5, 133 | episode: 6, 134 | excess: undefined 135 | }, 136 | { 137 | name: 'Annabelle.2014.HC.HDRip.XViD.AC3-juggs[ETRG]', 138 | hardcoded: true, 139 | audio: 'AC3', 140 | excess: undefined 141 | }, 142 | { 143 | name: 'Lucy.2014.HC.HDRip.XViD-juggs[ETRG]', 144 | hardcoded: true, 145 | excess: undefined 146 | }, 147 | { 148 | name: 'The Flash 2014 S01E04 HDTV x264-FUM[ettv]', 149 | excess: undefined 150 | }, 151 | { 152 | name: 'South Park S18E05 HDTV x264-KILLERS [eztv]', 153 | excess: undefined 154 | }, 155 | { 156 | name: 'The Flash 2014 S01E03 HDTV x264-LOL[ettv]', 157 | excess: undefined 158 | }, 159 | { 160 | name: 'The Flash 2014 S01E01 HDTV x264-LOL[ettv]', 161 | excess: undefined 162 | }, 163 | { 164 | name: 'Lucy 2014 Dual-Audio WEBRip 1400Mb', 165 | audio: 'Dual-Audio', 166 | garbage: '1400Mb', 167 | group: undefined, 168 | excess: undefined 169 | }, 170 | { 171 | name: 'Teenage Mutant Ninja Turtles (HdRip / 2014)', 172 | title: 'Teenage Mutant Ninja Turtles', 173 | quality: 'HdRip' 174 | }, 175 | { 176 | name: 'Teenage Mutant Ninja Turtles (unknown_release_type / 2014)', 177 | excess: 'unknown_release_type', 178 | proper: undefined 179 | }, 180 | { 181 | name: 'The Simpsons S26E05 HDTV x264 PROPER-LOL [eztv]', 182 | proper: true, 183 | excess: undefined 184 | }, 185 | { 186 | name: '2047 - Sights of Death (2014) 720p BrRip x264 - YIFY', 187 | title: '2047 - Sights of Death', 188 | year: 2014, 189 | excess: undefined, 190 | repack: undefined 191 | }, 192 | { 193 | name: 'Two and a Half Men S12E01 HDTV x264 REPACK-LOL [eztv]', 194 | repack: true, 195 | excess: undefined 196 | }, 197 | { 198 | name: 'Dinosaur 13 2014 WEBrip XviD AC3 MiLLENiUM', 199 | quality: 'WEBrip', 200 | audio: 'AC3', 201 | group: 'MiLLENiUM', 202 | excess: undefined 203 | }, 204 | { 205 | name: 'Teenage.Mutant.Ninja.Turtles.2014.HDRip.XviD.MP3-RARBG', 206 | audio: 'MP3', 207 | excess: undefined 208 | }, 209 | { 210 | name: 'Dawn.Of.The.Planet.of.The.Apes.2014.1080p.WEB-DL.DD51.H264-RARBG', 211 | audio: 'DD51', 212 | excess: undefined 213 | }, 214 | { 215 | name: 'Teenage.Mutant.Ninja.Turtles.2014.720p.HDRip.x264.AC3.5.1-RARBG', 216 | audio: 'AC3.5.1', 217 | excess: undefined 218 | }, 219 | { 220 | name: 'Gotham.S01E05.Viper.WEB-DL.x264.AAC', 221 | episodeName: 'Viper', 222 | audio: 'AAC', 223 | group: undefined, 224 | excess: undefined 225 | }, 226 | { 227 | name: 'Into.The.Storm.2014.1080p.WEB-DL.AAC2.0.H264-RARBG', 228 | audio: 'AAC2.0', 229 | excess: undefined 230 | }, 231 | { 232 | name: 'Lucy 2014 Dual-Audio 720p WEBRip', 233 | audio: 'Dual-Audio', 234 | group: undefined, 235 | excess: undefined 236 | }, 237 | { 238 | name: 'Into The Storm 2014 1080p BRRip x264 DTS-JYK', 239 | audio: 'DTS', 240 | excess: undefined 241 | }, 242 | { 243 | name: 'Sin.City.A.Dame.to.Kill.For.2014.1080p.BluRay.x264-SPARKS', 244 | quality: 'BluRay' 245 | }, 246 | { 247 | name: 'WWE Monday Night Raw 3rd Nov 2014 HDTV x264-Sir Paul', 248 | title: 'WWE Monday Night Raw', 249 | garbage: '3rd Nov' 250 | }, 251 | { 252 | name: 'Jack.And.The.Cuckoo-Clock.Heart.2013.BRRip XViD', 253 | title: 'Jack And The Cuckoo-Clock Heart', 254 | group: undefined, 255 | excess: undefined 256 | }, 257 | { 258 | name: 'WWE Hell in a Cell 2014 HDTV x264 SNHD', 259 | group: 'SNHD', 260 | excess: undefined 261 | }, 262 | { 263 | name: 'Dracula.Untold.2014.TS.XViD.AC3.MrSeeN-SiMPLE', 264 | group: 'MrSeeN-SiMPLE', 265 | excess: undefined 266 | }, 267 | { 268 | name: 'The Missing 1x01 Pilot HDTV x264-FoV [eztv]', 269 | episodeName: 'Pilot', 270 | excess: undefined 271 | }, 272 | { 273 | name: 'Doctor.Who.2005.8x11.Dark.Water.720p.HDTV.x264-FoV[rartv]', 274 | season: 8, 275 | episode: 11, 276 | episodeName: 'Dark Water', 277 | excess: undefined 278 | }, 279 | { 280 | name: 'Gotham.S01E07.Penguins.Umbrella.WEB-DL.x264.AAC', 281 | episodeName: 'Penguins Umbrella', 282 | excess: undefined 283 | }, 284 | { 285 | name: 'One Shot [2014] DVDRip XViD-ViCKY', 286 | title: 'One Shot', 287 | excess: undefined 288 | }, 289 | { 290 | name: 'The Shaukeens 2014 Hindi (1CD) DvDScr x264 AAC...Hon3y', 291 | quality: 'DvDScr', 292 | excess: ['Hindi', '1CD'] 293 | }, 294 | { 295 | name: 'The Shaukeens (2014) 1CD DvDScr Rip x264 [DDR]', 296 | quality: 'DvDScr', 297 | garbage: 'Rip', 298 | group: '[DDR]', 299 | excess: '1CD' 300 | }, 301 | { 302 | name: 'Annabelle.2014.1080p.PROPER.HC.WEBRip.x264.AAC.2.0-RARBG', 303 | audio: 'AAC.2.0', 304 | group: 'RARBG' 305 | }, 306 | { 307 | name: 'Interstellar (2014) CAM ENG x264 AAC-CPG', 308 | quality: 'CAM', 309 | excess: 'ENG' 310 | }, 311 | { 312 | name: 'Guardians of the Galaxy (2014) Dual Audio DVDRip AVI', 313 | audio: 'Dual Audio', 314 | container: 'AVI', 315 | group: undefined, 316 | excess: undefined 317 | }, 318 | { 319 | name: 'Eliza Graves (2014) Dual Audio WEB-DL 720p MKV x264', 320 | container: 'MKV', 321 | excess: undefined 322 | }, 323 | { 324 | name: 'WWE Monday Night Raw 2014 11 10 WS PDTV x264-RKOFAN1990 -={SPARR', 325 | widescreen: true, 326 | quality: 'PDTV', 327 | group: 'RKOFAN1990 -={SPARR', 328 | excess: ['11', '10'] 329 | }, 330 | { 331 | name: 'Sons.of.Anarchy.S01E03', 332 | title: 'Sons of Anarchy', 333 | season: 1, 334 | episode: 3, 335 | group: undefined 336 | }, 337 | { 338 | name: 'doctor_who_2005.8x12.death_in_heaven.720p_hdtv_x264-fov', 339 | title: 'doctor who', 340 | episodeName: 'death in heaven', 341 | quality: 'hdtv', 342 | excess: undefined 343 | }, 344 | { 345 | name: 'breaking.bad.s01e01.720p.bluray.x264-reward', 346 | title: 'breaking bad', 347 | season: 1, 348 | episode: 1, 349 | quality: 'bluray', 350 | excess: undefined 351 | }, 352 | { 353 | name: 'Game of Thrones - 4x03 - Breaker of Chains', 354 | title: 'Game of Thrones', 355 | episodeName: 'Breaker of Chains', 356 | group: undefined 357 | }, 358 | { 359 | name: '[720pMkv.Com]_sons.of.anarchy.s05e10.480p.BluRay.x264-GAnGSteR', 360 | website: '720pMkv.Com', 361 | title: 'sons of anarchy', 362 | season: 5, 363 | episode: 10, 364 | resolution: '480p', 365 | quality: 'BluRay', 366 | codec: 'x264', 367 | group: 'GAnGSteR', 368 | excess: undefined 369 | }, 370 | { 371 | name: '[ www.Speed.cd ] -Sons.of.Anarchy.S07E07.720p.HDTV.X264-DIMENSION', 372 | website: 'www.Speed.cd', 373 | title: 'Sons of Anarchy', 374 | season: 7, 375 | episode: 7, 376 | resolution: '720p', 377 | quality: 'HDTV', 378 | codec: 'X264', 379 | group: 'DIMENSION' 380 | }, 381 | { 382 | name: 'Community.s02e20.rus.eng.720p.Kybik.v.Kybe', 383 | title: 'Community', 384 | season: 2, 385 | episode: 20, 386 | language: 'rus.eng', 387 | resolution: '720p', 388 | group: 'Kybik.v.Kybe', 389 | episodeName: undefined 390 | } 391 | ]; 392 | 393 | torrents.forEach(function(torrent) { 394 | var testName = '"' + torrent.name + '"'; 395 | var parts = ptn(torrent.name); 396 | 397 | tape(testName, function (test) { 398 | var key, testMessage; 399 | 400 | for(key in torrent) { 401 | if(torrent.hasOwnProperty(key)) { 402 | if(key === 'name') { 403 | continue; 404 | } 405 | 406 | testMessage = key + ': ' + JSON.stringify(torrent[key]); 407 | 408 | test[Array.isArray(torrent[key]) ? 'deepEqual' : 'equal']( 409 | parts[key], 410 | torrent[key], 411 | testMessage 412 | ); 413 | } 414 | } 415 | 416 | test.end(); 417 | }); 418 | }); 419 | --------------------------------------------------------------------------------