247 lines
8.9 KiB
PHP
247 lines
8.9 KiB
PHP
<?php
|
|
/**
|
|
* Parse Torrent Name (PTN)
|
|
*
|
|
* PHP port of parse-torrent-name written in Python.
|
|
*
|
|
* Javascript version by jzjzjzj
|
|
* https://github.com/jzjzjzj/parse-torrent-name
|
|
*
|
|
* Python version by divijbindlish
|
|
* https://github.com/divijbindlish/parse-torrent-name
|
|
*
|
|
* Copyright (c) 2014 - 2018, British Columbia Institute of Technology
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*
|
|
* @package PTN
|
|
* @author Drew Smith
|
|
* @copyright copyright (c) 2018, Nihilarr (https://www.nihilarr.com)
|
|
* @license http://opensource.org/licenses/MIT MIT License
|
|
* @link https://gitlab.com/nihilarr/parse-torrent-name
|
|
* @version 0.0.1
|
|
*/
|
|
|
|
namespace App\Base\Util;
|
|
|
|
class PTN {
|
|
|
|
public $torrent;
|
|
public $excess_raw;
|
|
public $group_raw;
|
|
public $start;
|
|
public $end;
|
|
public $title_raw;
|
|
public $parts;
|
|
|
|
public $patterns = array(
|
|
array('season' => '(s?([0-9]{1,3}))[ex]'),
|
|
array('episode' => '([ex]([0-9]{1,3})(?:[^0-9]|$))'),
|
|
array('year' => '([\[\(]?((?:19[0-9]|20[01])[0-9])[\]\)]?)'),
|
|
array('resolution' => '([0-9]{3,4}p)'),
|
|
array('quality' => '((?:PPV\.)?[HP]DTV|(?:HD)?CAM|B[DR]Rip|(?:HD-?)?TS|(?:PPV )?WEB-?DL(?: DVDRip)?|HDRip|DVDRip|DVDRIP|CamRip|W[EB]BRip|BluRay|DvDScr|hdtv|telesync)'),
|
|
array('codec' => '(xvid|[hx]\.?26[45])'),
|
|
array('audio' => '(MP3|DD5\.?1|Dual[\- ]Audio|LiNE|DTS|AAC[.-]LC|AAC(?:\.?2\.0)?|AC3(?:\.5\.1)?)'),
|
|
array('group' => '(- ?([^-]+(?:-={[^-]+-?$)?))$'),
|
|
array('region' => 'R[0-9]'),
|
|
array('extended' => '(EXTENDED(:?.CUT)?)'),
|
|
array('hardcoded' => 'HC'),
|
|
array('proper' => 'PROPER'),
|
|
array('repack' => 'REPACK'),
|
|
array('container' => '(MKV|AVI|MP4)'),
|
|
array('widescreen' => 'WS'),
|
|
array('website' => '^(\[ ?([^\]]+?) ?\])'),
|
|
array('language' => '(rus\.eng|ita\.eng)'),
|
|
array('sbs' => '(?:Half-)?SBS'),
|
|
array('unrated' => 'UNRATED'),
|
|
array('size' => '(\d+(?:\.\d+)?(?:GB|MB))'),
|
|
array('3d' => '3D')
|
|
);
|
|
|
|
public $types = array(
|
|
'season' => 'integer',
|
|
'episode' => 'integer',
|
|
'year' => 'integer',
|
|
'extended' => 'boolean',
|
|
'hardcoded' => 'boolean',
|
|
'proper' => 'boolean',
|
|
'repack' => 'boolean',
|
|
'widescreen' => 'boolean',
|
|
'unrated' => 'boolean',
|
|
'3d' => 'boolean'
|
|
);
|
|
|
|
public function __construct() {}
|
|
|
|
public function parse($name) {
|
|
$this->parts = array();
|
|
$this->torrent = array('name' => $name);
|
|
$this->excess_raw = $name;
|
|
$this->group_raw = '';
|
|
$this->start = 0;
|
|
$this->end = null;
|
|
$this->title_raw = null;
|
|
|
|
foreach($this->patterns as $patterns_single) {
|
|
foreach($patterns_single as $key => $pattern) {
|
|
if(!in_array($key, array('season', 'episode', 'website'))) {
|
|
$pattern = "\b{$pattern}\b";
|
|
}
|
|
|
|
$clean_name = str_replace('_', ' ', $this->torrent['name']);
|
|
if(preg_match("/{$pattern}/i", $clean_name, $match) == 0) break;
|
|
|
|
$index = array();
|
|
if(is_array($match)) {
|
|
array_shift($match);
|
|
}
|
|
if(sizeof($match) == 0) break;
|
|
if(sizeof($match) > 1) {
|
|
$index['raw'] = 0;
|
|
$index['clean'] = 1;
|
|
}
|
|
else {
|
|
$index['raw'] = 0;
|
|
$index['clean'] = 0;
|
|
}
|
|
|
|
if(isset($this->types[$key]) && $this->types[$key] == 'boolean') {
|
|
$clean = true;
|
|
}
|
|
else {
|
|
$clean = $match[$index['clean']];
|
|
if(isset($this->types[$key]) && $this->types[$key] == 'integer') {
|
|
$clean = (int)$clean;
|
|
}
|
|
}
|
|
|
|
if($key == 'group') {
|
|
if((isset($this->patterns[5][1]) && preg_match_all("/{$this->patterns[5][1]}/i", $clean)) ||
|
|
(isset($this->patterns[4][1]) && preg_match_all("/{$this->patterns[4][1]}/", $clean))) {
|
|
break;
|
|
}
|
|
if(preg_match('/[^ ]+ [^ ]+ .+/', $clean)) {
|
|
$key = 'episodeName';
|
|
}
|
|
}
|
|
if($key == 'episode') {
|
|
$sub_pattern = $this->escape_regex($match[$index['raw']]);
|
|
$this->torrent['map'] = preg_replace("/{$sub_pattern}/", '{episode}', $this->torrent['name']);
|
|
}
|
|
|
|
$this->part($key, $match, $match[$index['raw']], $clean);
|
|
}
|
|
}
|
|
|
|
$raw = $this->torrent['name'];
|
|
if(!is_null($this->end)) {
|
|
$raw = explode('(', substr($raw, $this->start, $this->end - $this->start));
|
|
$raw = $raw[0];
|
|
}
|
|
|
|
$clean = preg_replace("/^ -/", '', $raw);
|
|
if(strpos($clean, ' ') === false && strpos($clean, '.') !== false) {
|
|
$clean = str_replace('.', ' ', $clean);
|
|
}
|
|
$clean = str_replace('_', ' ', $clean);
|
|
$clean = trim(preg_replace("/([\[\(_]|- )$/", '', $clean));
|
|
|
|
$this->part('title', array(), $raw, $clean);
|
|
|
|
$clean = preg_replace("/(^[-\. ()]+)|([-\. ]+$)/", '', $this->excess_raw);
|
|
$clean = preg_replace("/[\(\)\/]/", ' ', $clean);
|
|
$match = preg_split("/\.\.+| +/", $clean);
|
|
if(sizeof($match) > 0 && is_array($match[0])) {
|
|
$match = $match[0];
|
|
}
|
|
|
|
$clean = $match;
|
|
$clean = array_filter($clean, function($var) {
|
|
return $var != '-' ? true : false;
|
|
});
|
|
$clean = array_filter($clean, function($var) {
|
|
return trim($var, '-');
|
|
});
|
|
$clean = array_values($clean);
|
|
|
|
if(sizeof($clean) > 0) {
|
|
$group_pattern = $clean[sizeof($clean) - 1] . $this->group_raw;
|
|
if(strpos($this->torrent['name'], $group_pattern) == strlen($this->torrent['name']) - strlen($group_pattern)) {
|
|
$this->late('group', array_pop($clean) . $this->group_raw);
|
|
}
|
|
|
|
if(isset($this->torrent['map']) && sizeof($clean) > 0) {
|
|
$episode_name_pattern = '{episode}' . preg_replace("/_+$/", '', $clean[0]);
|
|
|
|
if(strpos($this->torrent['map'], $episode_name_pattern) != -1) {
|
|
$this->late('episodeName', array_shift($clean));
|
|
}
|
|
}
|
|
}
|
|
|
|
if(sizeof($clean) != 0) {
|
|
if(sizeof($clean) == 1) {
|
|
$clean = $clean[0];
|
|
}
|
|
$this->part('excess', array(), $this->excess_raw, $clean);
|
|
}
|
|
return $this->parts;
|
|
}
|
|
|
|
private function escape_regex($subject) {
|
|
return preg_replace("/[\-\[\]{}()*+?.,\\\^$|#\s]/", "\\\\$&", $subject);
|
|
}
|
|
|
|
private function part($name, $match, $raw, $clean) {
|
|
# The main core instructuions
|
|
$this->parts[$name] = $clean;
|
|
|
|
if(sizeof($match) > 0) {
|
|
# The instructions for extracting title
|
|
$index = strpos($this->torrent['name'], $match[0]);
|
|
if($index == 0) {
|
|
$this->start = strlen($match[0]);
|
|
}
|
|
elseif(is_null($this->end) || $index < $this->end) {
|
|
$this->end = $index;
|
|
}
|
|
}
|
|
if($name != 'excess') {
|
|
if($name == 'group') {
|
|
$this->group_raw = $raw;
|
|
}
|
|
|
|
if(!is_null($raw)) {
|
|
$this->excess_raw = str_replace($raw, '', $this->excess_raw);
|
|
}
|
|
}
|
|
}
|
|
|
|
private function late($name, $clean) {
|
|
if($name == 'group') {
|
|
$this->part($name, array(), null, $clean);
|
|
}
|
|
elseif($name == 'episodeName') {
|
|
$clean = preg_replace("/[\._]/", ' ', $clean);
|
|
$clean = preg_replace("/_+$/", '', $clean);
|
|
$this->part($name, array(), null, trim($clean));
|
|
}
|
|
}
|
|
}
|