<?php
/**************************************************
* nzbv2irc v1
* Copyright (c) 2006 Harry Bragg
* tiberious.org
* Module: nzbv2
**************************************************
*
* Full GPL License: <http://www.gnu.org/licenses/gpl.txt>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
class Net_SmartIRC_module_nzbv2 extends Net_SmartIRC_module_base
{
// default module variable
var $name = 'nzbv2';
var $version = 'v0.1';
var $description = 'interfaces with newzbin.com';
/**
* Newzbin Module - Please note the commands are regex's www.regular-expressions.info for a very good reference.
*
* STARTCONFIG
* @var array publicCommand - Lists the commands that trigger this module, and return publicly
* @var array privateCommand - Lists the commands that trigger this module privatly (notice you)
* @var bool nbLogin - Login to newzbin.com or not
* @var array login
* @var string username - Newzbin.com username
* @var string password - Newzbin.com password
* @var array download
* @var bool useHella - use Hellanzbv2 to download nzbv2 files (provides fewer details about errors, req: hellanzbv2)
* @var string nzbv2Path - path to store all the nzbv2 files
* @var bool nickPreface - Add a (nickname) at the beginning of each nzbv2 file for ident later
* @var int history - Number of days to keep a history of nzbv2's that have been downloded
* @var bool useDnzbv2 - use v3's Direct nzbv2 download method
* @var string language - if you only want results from a particular language, specify it here
* @var int searchResults - How many results you want to return from a search result
* @var bool deepSearch - Performs a deep search of the results (and provies extra information, ie: size, filename, tv info)
* @var int reportCache - The number of days to keep reports info before re-requesting it
* @var double cacheChange - Probability of using the cache instead of re-querying (between 0 and 1, 0.9 = 90%)
* ENDCONFIG
*/
var $_config = array(
'publicCommand' => array( '^nv2', '^!nv2' ),
'privateCommand' => array( '^@nv2' ),
'nbLogin' => false,
'login' => array(
'username' => 'username',
'password' => 'password' ),
'download' => array(
'useHella' => false,
'nzbv2Path' => '/path/to/nzb/',
'nickPreface' => true,
'history' => 14,
'useDnzbv2' => false ),
'language' => 'English',
'searchResults' => 4,
'deepSearch' => true,
'reportCache' => 1.1,
'cacheChance' => 0.95
);
/**
* newzbin.com definition listing
*/
var $_def = array(
'url' => array(
'search' => 'http://v3.newzbin.com/search/query/?fpn=p&q=%s&category=-1&searchaction=Go&feed=csv&u_post_results_amt=200',
'report' => 'http://v2.newzbin.com/browse/post/%d/',
'download' => 'http://v2.newzbin.com/database/post/edit/?ps_id=%d',
'login' => 'http://v2.newzbin.com/account/login/'
),
'regex' => array(
'search' => array(
/**
* 1 => date
* 2 => id
* 3 => title
* 4 => url
*/
'result' => '/^"(.*)","(\d+)","(.*)",".*","(.*)",".*"$/im',
'specific' => '/^"(.*)","(\d+)","(.*%s.*)",".*","(.*)",".*"$/im',
'urlmatch' => '/^"(.*)","(\d+)","(.*)",".*","(%s)",".*"$/im',
'queryExpansion' => '/^(.*?)\{([^\}]+)\}(.*)$/i',
'numberSearch' => '/(?:(\d+)-(\d+)|([^-,]+))/',
'flags' => '/(.+)\sf(?:lags?)?:([a-z0-9,.\s]+)/i',
'tvrage' => 'http:\/\/www\.tvrage\.com\/%s\/episodes\/%s.*?'
),
'report' => array(
'size' => array(
'regex' => '/<td class="leftBorder">Total Size:<\/td>\s+<td>([0-9,.]+) MB<\/td>/i',
'vals' => array( 1 => 'size' ) ),
'filename' => array(
'regex' => array(
'/<td>[0-9,.]+MB<\/td>\s+<td>.+"(.+)".+<\/td>/i',
'/<td>[0-9,.]+MB<\/td>\s+<td>.+\-\s(.+)(?!\-)<\/td>/i' ),
'vals' => array( 1 => 'filename' ) ),
'title' => array(
'regex' => '/<td>Title:<\/td>\s+<td colspan="3">\s+(?:<img title="([^"]+)" alt="[^"]+"\s+src="[^"]+" \/>)?\s+(.+)\s+<\/td>/i',
'vals' => array( 1 => 'language', 2 => 'title' ) ),
'url' => array(
'regex' => '/<td>URL:<\/td>\s+<td colspan="3"><a href="(.+?)">.+?<\/a><\/td>/i',
'vals' => array( 1 => 'url' ) ),
'files' => array(
'regex' => '/<td class="leftBorder">Total Files:<\/td>\s+<td>([0-9]+) files<\/td>/i',
'vals' => array( 1 => 'files' ) ),
'status' => array(
'regex' => '/<tr class="odd">\s+<td>Status:<\/td>\s+<td>(.+)<\/td>\s+<td>Completion:<\/td>\s+<td>(.+)<\/td>/i',
'vals' => array( 1 => 'status', 2 => 'completion' ) ),
'nfo' => array(
'regex' => '/<td>NFO:<\/td>\s+<td colspan="5">\s+\[<a href="\/nfo\/view\/.+?">View<\/a>\]\s+(.+)\s+<\/td>/i',
'vals' => array( 1 => 'nfo' ) ),
'age' => array(
'regex' => '/\((\S+) ago, (\S+) lag\)<\/td>/i',
'vals' => array( 1 => 'age', 2 => 'lag' ) ),
'category' => array(
'regex' => '/<a href="[^"]+">([^<]+)<\/a> ::\s+<a href="[^"]+">([^<]+)<\/a>/i',
'vals' => array( 1 => 'category', 2 => 'subcategory' ) ),
'post' => array(
'regex' => '/<td>[0-9,.]+MB<\/td>\s+<td>(.+?)<\/td>/i',
'vals' => array( 1 => 'post' )
)
),
'reportInfo' => array(
'specificFilename' => '/<td>[0-9,.]+MB<\/td>\s+<td>.*%s.*<\/td>/i',
'isReport' => '/The specified post does not exist/i',
'hasFiles' => '/No files attached\./i'
),
'add' => array(
'next' => '/^next$/i',
'force' => '/^force"/i',
'split' => '/(\+|\!|\^)(\d{7,9})/i',
'url' => '/(http:\/\/)?[a-z0-9_\-.\/]+\/([a-z0-9_\-.\/]+)/i' ),
'loggedIn' => '/<div class="section">\s+<h3>Login<\/h3>\s+<form method="post" action="\/account\/login\/">/i',
'download' => array(
'Dnzbv2wait' => '/Try Later, wait (\d+) seconds for counter to reset/i' )
),
'date' => array(
'history' => array(
'time' => 'h:ia'
)
),
'replace' => array(
'fileToTitle' => array(
'from' => array( '_' ),
'to' => array( ' ' )
),
'titleToFile' => array(
'from' => array(' ', '..', '.', '?', ':', '#', '<', '>', '/', '\\', '|', '*', '\'', '"', '&' ),
'to' => array( '_' )
)
)
);
/**
* Template system
*/
var $_template = array(
'search' => '({nzbv2id}) {completed}{language}{title} | {category} {extraInfo}[{age}{size}] {file}',
'extraInfo' => '{res} {format} ',
'report' => array(
'({nzbv2id}) {category}:{subcategory}, {language}{status}{completed}{title} ({size}, {files} files) [posted: {age} ago, {lag} lag] {extraInfo}',
'post info: {post}, url: {url}' ),
'addSucc' => 'Queued: [{addQueued}]',
'addQueued' => '{id}:{title}',
'addError' => 'Error: [{addQueued}]',
'history' => '[**{date}**] {nzbv2History}',
'nzbv2History' => '({time}) {id}: {title}',
'error' => 'Error: {errormsg}',
'commandList' => 'List of commands available for nzbv2 | type {trigger} help command, for more information on each command',
'help' => '{command} - {description}',
'helpList' => array(
'Commands available for nzbv2: {helpCommands}',
'Type: {trigger} {subTrigger} command, for more information on each command'
)
);
var $_help = array(
'help' => array(
'command' => '{trigger} help [command]',
'description' => 'Display the available commands, if a __command__ is specified, then extra information is provided',
'longDescription' => 'Display the available commands, if a __command__ is specified, then extra information is provided'
),
'commands' => array(
'command' => '{trigger} commands',
'description' => 'List the available commands with their descriptions',
'longDescription' => 'List the available commands with their descriptions'
),
'forceadd' => 'add',
'nextadd' => 'add',
'enqueue' => 'add',
'forceenqueue' => 'add',
'nextenqueue' => 'add',
'add' => array(
'command' => '{trigger} [force/next]add query [f:flags]',
'description' => 'Download nzbv2 files based on the __query__, which can be one or more nzbv2id\'s, or a search query',
'longDescription' => array(
'Download nzbv2 files based on the __query__, which can be a nzbv2id, or a search query',
'The search query can include **variables**, for example: {{01,02,09-20}}, will add 01, 02, 09, 10, ... 20',
'This also works with words {{cat,mouse,dog}} will add cat, mouse and dog seperatly. Multiple **variables** can be defined in a single query',
'Flags, define the quality of files to be downloaded (mainly for tv, but works for films too), more information can be found with {trigger} help search',
'REQ: Hellanzbv2, If force or next are placed before the add part, the nzbv2\'s downloaded will be placed in the approprate places in the queue',
'Alternative command: + (see {trigger} help +)'
)
),
'!' => '+',
'^' => '+',
'-' => '+',
'+' => array(
'command' => '{trigger} +/!/^/-nzbv2id [+/!/^/-nzbv2id2 [...]]',
'description' => 'the same as {trigger} add/del, but it will only accept nzbv2ID\'s from newzbin.com, **+** adds, **!** adds and forces, **^** adds and places next in the queue, **-** deletes, (**!**,**^** and **-** depends on Hellanzbv2)',
'longDescription' => array(
'the same as {trigger} add/del, but it will only accept nzbv2ID\'s from newzbin.com',
'**+** adds, **!** adds and then forces the nzbv2, **^** adds and places next it in the queue, **-** deletes from the queue'
)
),
'search' => array(
'command' => '{trigger} search query [f:flags]',
'description' => 'Searches newzbin based on the query, if __flags__ are specified, the results are based on their flags',
'longDescription' => array(
'Searches newzbin based on the query, if __flags__ are specified, the results are based on their flags',
'Current flags are: 1080p, 720p, hr, h.264, xvid, divx, svcd, wmv, normal. **hr** means halfres (1080p/2 = 540p)',
'The order of the flags, specifies their priority, placing them earlier makes them more important, for example:',
'f:720p,hr,xvid - means if 720p can be found it will download that, otherwise hr, then xvid',
'These flags are based on the filenames of the reports',
'see: http://www.tiberious.org/wiki/index.php/nzbv2irc/v1/flags for an uptodate list of flags'
)
),
'report' => 'info',
'post' => 'info',
'info' => array(
'command' => '{trigger} info/report/post nzbv2id [nzbv2id2 [nzbv2id3 ...]]',
'description' => 'Obtain information about a newzbin report, from its ID',
'longDescription' => 'Obtain information about a newzbin report, from its ID'
),
'history' => array(
'command' => '{trigger} history date/duration',
'description' => 'Return the nzbv2\'s downloaded on the specified __date__, or __duration__',
'longDescription' => array(
'Return the nzbv2\'s downloaded on the specified __date__, or __duration__',
'__date__ can be in almost any date format: today, next wednesday, 10/11/06, 15th Jan 06, etc',
'__duration__ is in the format: Xw Yd',
'date periods can be specified using **-** or **to**, these will list items between 2 absolute dates/durations, i.e.: {trigger} history -4d to yesterday',
'the joining word **for** can also be used for relative periods, i.e.: {trigger} history 15 dec 06 for 3d',
'see http://www.tiberious.org/wiki/index.php/nzbv2irc/v1/times for more information'
)
)
);
/**
* Store temporary errors
*/
var $_error;
function _registerCommands()
{
global $irc;
$this->_setHandler( '^search', $this, 'doSearch' );
$this->_setHandler( '^(info|report|post)', $this, 'doInfo' );
$this->_setHandler( '^(add|enqueue)', $this, 'add' );
$this->_setHandler( '/\+(\d{7,9})/i', $this, 'addSplit' );
if ( $irc->isLoadedModule( 'hella' ) )
{
$this->_setHandler( '^(force|next)(add|enqueue)', $this, 'add' );
$this->_setHandler( '/(\^|\!|\-)(\d{7,9})/i', $this, 'addSplit' );
}
$this->_setHandler( '^history', $this, 'history' );
//help
$this->_setHandler( '^help', $this, 'botHelp' );
$this->_setHandler( '^commands', $this, 'botCommands' );
$irc->_modules['store']->addVariable( '_nzbv2Cache' );
$irc->_modules['store']->addVariable( '_nzbv2Cookie' );
$irc->_modules['store']->addVariable( '_nzbv2History' );
$irc->_modules['store']->addVariable( '_nzbv2Wait' );
$irc->_modules['store']->addVariable( '_nzbv2Queued' );
$irc->_modules['store']->addVariable( '_nzbv2QError' );
///$irc->_nzbv2TimerID = $irc->registerTimeHandler( 30000, $this, 'checknzbv2' );
}
function _customClose()
{
global $irc;
//$irc->unregisterTimeid( $irc->_nzbv2TimerID );
}
/*****************************************************
* Bot functions
*****************************************************/
function doSearch( &$irc, &$data, $notice )
{
// check to see if flags are specified
if ( preg_match( $this->_def['regex']['search']['flags'], $data->subMessage, $match ) )
{
$flags = explode(',', $match[2]);
$query = $match[1];
}
else
{
$query = $data->subMessage;
$flags = array();
}
$results = $this->search( $query, $this->_config['searchResults'], $flags );
if ( count( $results ) == 0 )
{
$irc->_modules['func']->reply( $irc, $data, 'No results found for: '.$data->subMessage, $notice );
}
foreach( $results as $res )
{
// check res for result
if ( isset( $res['id'] ) ) {
// filter result into string and output
$vars = array(
'nzbv2id' => $res['id'],
'category' => $res['category'],
'age' => trim( $irc->_modules['func']->dduration( time() - $res['reported'] ) ),
'title' => $res['title'] );
if ( isset( $res['report'] ) )
{
$vars['completed'] = ( $res['report']['completion'] != 'COMPLETED')? $res['report']['completion'].', ':'';
$vars['language'] = ( $res['report']['language'] )? '__'.$res['report']['language'].'__ ':'';
$vars['size'] = ', size: '.$irc->_modules['func']->humanSize( $res['report']['size'], 2);
$vars['file'] = ' file: '.$res['report']['filename'];
$vars['category'] = $res['report']['category'];
if ( ( $vars['category'] == 'TV' ) || ( $vars['category'] == 'Movies' ) )
{
if ( isset( $res['report']['res'] ) )
{
$vars['extraInfo'][] = array(
'res' => $res['report']['res'],
'format' => $res['report']['format']
);
}
else
{
$vars['extraInfo'][] = array(
'res' => $res['report']['resolution'],
'format' => $res['report']['video format']
);
}
}
}
$this->parseTemplate( $msg, 'search', $vars );
}
unset( $out, $vars );
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
}
function doInfo( &$irc, &$data, $notice )
{
$subMex = explode( ' ', $data->subMessage );
foreach( $subMex as $nzbv2ID )
{
if ( is_numeric( $nzbv2ID ) )
{
if ( ( $rep = $this->getReport( $nzbv2ID ) ) !== false )
{
$rep['status'] = ( $rep['status'] != 'NORMAL')? $rep['status'].', ':'';
$rep['completed'] = ( $rep['completion'] != 'COMPLETED')? $rep['completion'].', ':'';
$rep['language'] = ( !empty( $rep['language'] ) )? $rep['language'].', ':'';
$rep['size'] = $irc->_modules['func']->humanSize( $rep['size'], 2 );
if ( ( $rep['category'] == 'TV' ) || ( $rep['category'] == 'Movies' ) )
{
if ( isset( $res['report']['res'] ) )
{
$vars['extraInfo'][] = array(
'res' => $res['report']['res'],
'format' => $res['report']['format']
);
}
else
{
$vars['extraInfo'][] = array(
'res' => $res['report']['resolution'],
'format' => $res['report']['video format']
);
}
}
$this->parseTemplate( $msg, 'report', $rep );
unset( $out, $rep );
}
else
{
$irc->_modules['func']->reply( $irc, $data, 'Report: '.$nzbv2ID.' does not exist', $notice );
}
}
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
}
function add( &$irc, &$data, $notice )
{
$data->notice = $notice;
$hellaMod = false;
if ( count( $data->trig ) > 2 )
{
// hella moving stuffs
if ( preg_match( $this->_def['regex']['add']['next'], $data->trig[1] ) )
{
$hellaMod = 'next';
}
else if ( preg_match( $this->_def['regex']['add']['force'], $data->trig[1] ) )
{
$hellaMod = 'force';
}
}
$data->hellaMod = $hellaMod;
$subMessageex = explode( ' ', $data->subMessage );
if ( ( !is_numeric( $subMessageex[0] ) ) || ( strlen($subMessageex[0]) < 5 ) )
{
// check to see if flags are specified
if ( preg_match( $this->_def['regex']['search']['flags'], $data->subMessage, $match ) )
{
$flags = explode(',', $match[2]);
$query = $match[1];
}
else
{
$query = $data->subMessage;
$flags = array();
}
// check if it is a url
if ( preg_match( $this->_def['regex']['add']['url'], $data->subMessage ) )
{
$results[] = array(
'id' => '117114108'.rand(10000,99999),
'url' => $data->subMessage
);
}
else
{
$results = $this->search( $query, 1, $flags );
if ( count( $results ) == 0 )
{
$irc->_modules['func']->reply( $irc, $data, 'No results found for: '.$data->subMessage, $notice );
}
}
}
else
{
foreach( $subMessageex as $id )
{
$results[] = array( 'id' => $id );
}
}
if ( ( $irc->config->useWorker == true ) &&
( $irc->isWorker == false ) )
{
foreach( $results as $res )
{
if ( isset( $res['id'] ) )
{
$irc->_nzbv2Wait[$res['id']] = $res;
$irc->_nzbv2Wait[$res['id']]['data'] = $irc->_modules['func']->getTData( $data );
}
}
$irc->_modules['store']->manualUpdate( '_nzbv2Wait', true );
return;
}
foreach( $results as $res )
{
if ( substr( $res['id'], 0, 9 ) == '117114108' )
{
if ( ( $title = $this->_addUrl( $res['id'], $res['url'] ) ) !== false )
{
$succ[] = array(
'id' => $res['id'],
'title' => $title );
}
else
{
$errors[] = array(
'id' => $res['id'],
'title' => $this->_error );
}
}
else if ( isset( $res['id'] ) )
{
if ( ( $title = $this->_addID( $res['id'], $data, $hellaMod ) ) !== false )
{
$succ[] = array(
'id' => $res['id'],
'title' => $title );
}
else
{
if ( !preg_match( $this->_def['regex']['download']['Dnzbv2wait'], $this->_error ) )
{
$errors[] = array(
'id' => $res['id'],
'title' => $this->_error );
}
else
{
$wait[] = $res['id'];
}
}
}
}
$vars['seperator'] = ', ';
if ( is_array( $succ ) )
{
$vars['addQueued'] = $succ;
$this->parseTemplate( $msg, 'addSucc', $vars );
}
if ( isset( $wait ) )
{
$errors[] = array(
'id' => implode( ',', $wait ),
'title' => 'Waiting for Newzbin\'s 5nzbv2s/minute limit to timeout' );
}
if ( is_array( $errors ) )
{
$vars['addQueued'] = $errors;
$this->parseTemplate( $msg, 'addError', $vars );
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
}
function addSplit( &$irc, &$data, $notice )
{
$data->notice = $notice;
if ( preg_match_all( $this->_def['regex']['add']['split'], $data->strippedMessage, $ids ) > 0 )
{
for( $i = 0; $i < count( $ids[0] ); $i++ )
{
// delete
if ( $ids[1][$i] == '-' )
{
if ( $irc->_modules['hella']->del( $tmp, $ids[2][$i] ) )
{
$succ[] = array(
'id' => $ids[2][$i],
'title' => $tmp[0] );
}
else
{
$errors[] = array(
'id' => $ids[2][$i],
'title' => $tmp[0] );
}
}
else
{
$hellaMod = ( $ids[1][$i] == '!' )? 'force':
( ( $ids[1][$i] == '^' )? 'next':false );
$data->hellaMod = $hellaMod;
if ( ( $irc->config->useWorker == true ) &&
( $irc->isWorker == false ) )
{
$irc->_nzbv2Wait[$ids[2][$i]] = array(
'id' => $ids[2][$i],
'data' => $data );
}
else
{
if ( ( $title = $this->_addID( $ids[2][$i], $data, $hellaMod ) ) !== false )
{
$succ[] = array(
'id' => $ids[2][$i],
'title' => $title );
}
else
{
if ( !preg_match( $this->_def['regex']['download']['Dnzbv2Wait'], $this->_error ) )
{
$errors[] = array(
'id' => $ids[2][$i],
'title' => $this->_error );
}
else
{
$wait[] = $ids[2][$i];
}
}
}
}
}
}
if ( ( $irc->config->useWorker == true ) &&
( $irc->isWorker == false ) )
{
$irc->_modules['store']->manualUpdate( '_nzbv2Wait' );
}
$vars['seperator'] = ', ';
if ( is_array( $succ ) )
{
$vars['addQueued'] = $succ;
$this->parseTemplate( $msg, 'addSucc', $vars );
}
if ( isset( $wait ) )
{
$errors[] = array(
'id' => implode( ',', $wait ),
'title' => 'Waiting for Newzbin\'s 5nzbv2s/minute limit to timeout' );
}
if ( is_array( $errors ) )
{
$vars['addQueued'] = $errors;
$this->parseTemplate( $msg, 'addError', $vars );
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
}
function history( &$irc, &$data, $notice )
{
list( $date, $date2 ) = $irc->_modules['func']->dateDurationParse( $data->subMessage );
$date = $irc->_modules['func']->dateToDay( $date );
if ( $date2 >= 0 )
$date2 = $irc->_modules['func']->dateToDay( $date2 );
$nzbv2s = $this->_getHistory( $date, $date2 );
if ( count( $nzbv2s ) > 0 )
{
foreach( $nzbv2s as $id => $item )
{
$vars = array(
'date' => $irc->_modules['func']->snicedate( $id )
);
foreach( $item as $nzbv2 )
{
$tmp = array(
'time' => date( $this->_def['date']['history']['time'], $nzbv2['queued'] ),
'id' => $nzbv2['id'],
'title' => $nzbv2['title']
);
$vars['nzbv2History'][] = $tmp;
}
$this->parseTemplate( $msg, 'history', $vars );
}
}
else
{
$msg[] = 'No results found for the times specified';
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
}
function botHelp( &$irc, &$data, $notice )
{
if ( strlen( $data->subMessage ) > 0 )
{
if ( isset( $this->_help[$data->subMessage] ) )
{
$this->parseHelp( $msg, $data->subMessage, array( 'trigger' => $data->trigger ) );
}
else
{
//$this->parseTemplate( $msg, 'error', array( 'errormsg' => sprintf( 'Unknown command: %s', $data->subMessage ) ) );
}
}
else
{
foreach ( $this->_help as $id => $helpItem )
{
$vars['helpCommands'][] = $id;
}
$vars['trigger'] = $data->trigger;
$vars['subTrigger'] = $data->trig[0];
$this->parseTemplate( $msg, 'helpList', $vars );
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $data, $msg, true );
}
}
function botCommands( &$irc, &$data, $notice )
{
$vars['trigger'] = $data->trigger;
$this->parseTemplate( $msg, 'commandList', $vars );
foreach( $this->_help as $id => $helpItem )
{
if ( is_array( $helpItem ) )
{
$helpItem['trigger'] = $data->trigger;
$this->parseTemplate( $msg, 'help', $helpItem );
}
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $data, $msg, true );
}
}
/*****************************************************
* Main functions
*****************************************************/
/**
* Add a newzbinID, with a specified modifier
*
* @param int $id - Newzbin.com ID
* @param string $nick - Nickname of the person who added the nzbv2
* @param string $modifier - modifiy the item in the queue afterwards (Default: false)
* @return bool/string - string containing nzbv2 report title, or false if failed
* @access private
*/
function _addID( $id, &$data, $modifier = false )
{
global $irc;
$irc->modDebug( 'nzbv2', 'adding nzbv2ID: '. $id .' to download queue', __FILE__, __LINE__, SMARTIRC_DEBUG_MODULES );
// check to see if report exists
if ( ( $rep = $this->getReport( $id ) ) !== false )
{
if ( ( $this->_config['download']['useHella'] ) && ( $irc->isLoadedModule( 'hella' ) ) )
{
// do hellahella stuff here
if ( $irc->_modules['hella']->_send( 'enqueuenewzbin', array( $id ) ) !== false )
{
$irc->_modules['store']->setVariable( '_nzbv2History',
array(
'id' => $id,
'queued' => time(),
'data' => $irc->_modules['func']->getTData( $data ),
'title' => $rep['title'] ),
$id
);
if ( $modifier )
{
if ( isset( $ta[$modifier] ) )
{
$ta = array( 'last' => -2, 'next' => -1, 'force' => 0 );
$irc->_modules['hella']->moveItem( $id, $ta[$modifier], $irc->_modules['func']->getTData( $data ) );
}
}
// remove any old episodes in the history
$this->_checkHistory();
return $rep['title'];
}
else
{
$this->_error = $irc->_modules['hella']->_error;
return false;
}
}
else
{
$filetitle = trim( str_replace( array( ' ','..','.','?',':','#','<','>','/','\\','|','*','\'','"','&' ), '_', html_entity_decode( $rep['title'] ) ), '_' );
$filename = $this->_config['download']['nzbv2Path'] . sprintf( 'msgid_%d_%s%s.nzbv2', $id, (( $this->_config['download']['nickPreface'] )? '('.$data->nick.')_':'' ), $filetitle );
if ( ( $err = $this->_downloadnzbv2( $id, $filename, $data ) ) === true )
{
$irc->_modules['store']->setVariable( '_nzbv2History',
array(
'id' => $id,
'queued' => time(),
'data' => $irc->_modules['func']->getTData( $data ),
'title' => $rep['title'] ),
$id
);
if ( ( $modifier ) && ( $irc->isLoadedModule( 'hella' ) ) )
{
if ( isset( $ta[$modifier] ) )
{
$ta = array( 'last' => -2, 'next' => -1, 'force' => 0 );
$irc->_modules['hella']->moveItem( $id, $ta[$modifier], $irc->_modules['func']->getTData( $data ) );
}
}
// remove any old episodes in the history
$this->_checkHistory();
return $rep['title'];
}
else
{
$this->_error = $err;
return false;
}
}
}
else
{
$this->_error = 'Report ID: '. $id .', does not exist';
return false;
}
}
function _addUrl( $id, $url, $modifer = false )
{
global $irc;
if ( preg_match( $this->_def['regex']['add']['url'], $url, $match ) )
{
$file = $match[1];
if ( ( $err = $this->_downloadURL( $url, $file ) ) === true )
{
$rep['title'] = trim( str_replace( $this->_def['replace']['fileToTitle']['from'], $this->_def['replace']['fileToTile']['to'], $file ) );
// add the item to history
$irc->_nzbv2History[$id] = array(
'id' => $id,
'url' => $url,
'queued' => time(),
'data' => $irc->_modules['func']->getTData( $data ),
'title' => $rep['title'] );
if ( ( $modifier ) && ( $irc->isLoadedModule( 'hella' ) ) )
{
if ( isset( $ta[$modifier] ) )
{
$ta = array( 'last' => -2, 'next' => -1, 'force' => 0 );
$irc->_modules['hella']->moveItem( $id, $ta[$modifier], $irc->_modules['func']->getTData( $data ) );
}
}
// remove any old episodes in the history
$this->_checkHistory();
return $rep['title'];
}
else
{
$this->_error = $err;
return false;
}
}
}
/*****************************************************
* History
*
* The history is only stored for 2 weeks
* (or the number of days you speicified in the config)
*****************************************************/
/**
* Get the history from a day, or region of days
*
* @var int $date - First date
* @var int $date2 - Second date | Default: false
* @return array - Information related to
* @access private
*/
function _getHistory( $date, $date2 = false )
{
global $irc;
if ( ( !$date2 ) || ( $date2 < 0 ) )
{
// date2 = 1 day after date
$date2 = $date + 3600 * 24;
}
else
{
// make date2 + 1 day
$date2 = $date2 + (3600 * 24) - 1;
}
$irc->_modules['store']->manualUpdate( '_nzbv2History' );
if ( is_array( $irc->_nzbv2History ) )
{
foreach( $irc->_nzbv2History as $id => $item )
{
if ( ( $item['queued'] >= $date ) &&
( $item['queued'] <= $date2 ) )
{
$out[$id] = $item;
$downloaded[$id] = $item['queued'];
}
}
if ( count( $out ) > 0 )
{
// all nicely ordered
array_multisort( $downloaded, SORT_ASC, $out );
foreach( $out as $item )
{
$ret[$irc->_modules['func']->dateToDay( $item['queued'] )][] = $item;
}
}
}
return $ret;
}
/**
* Check the nzbv2 history, for old reports
*
* @return void
*/
function _checkHistory()
{
global $irc;
foreach( $irc->_nzbv2History as $id => $history )
{
if ( $history['queued'] < ( time() - ( $this->_config['download']['history'] * 3600 * 24 ) ) )
{
unset( $irc->_nzbv2History[$id] );
}
}
$irc->_modules['store']->manualUpdate( '_nzbv2History' );
}
/*****************************************************
* Search
*****************************************************/
/**
* Search for some nzbv2 posts
*
* @param string $query - Query to search for
* @param int $results - Number of results to return, 0 = all
* @param array $flags = List of flags to conform to, default: empty, i.e. first result
* @returns array - All the results in an array
* @access public
*/
function search( $query, $results, $flags = array() )
{
global $irc;
$res = array();
// check to see if the query contains a variable
if ( preg_match( $this->_def['regex']['search']['queryExpansion'], $query, $varMatch ) )
{
// see if there is a second variable in the query
if ( preg_match( $this->_def['regex']['search']['queryExpansion'], $varMatch[3] ) )
{
// get all the numbers in the first variable
$nums = $this->_getSearchNumbers( $varMatch[2] );
foreach( $nums as $num )
{
$tmp = $this->search( sprintf( '%s%s%s', $varMatch[1], $num, $varMatch[3] ), 1, $flags );
$irc->_modules['func']->array_append( $res, $tmp );
}
return $res;
}
else
{ // have to do this, otherwise there would be too many searches on newzbin.com
$url = sprintf( $this->_def['url']['search'], urlencode( $varMatch[1].' '.$varMatch[3] ) );
$page = $this->_getUrl( $url );
// search through the variable
$nums = $this->_getSearchNumbers( $varMatch[2] );
foreach( $nums as $num )
{
$regex = sprintf( $this->_def['regex']['search']['specific'], str_replace( array( ' ', '"' ), array( '.*', '' ), preg_quote( sprintf( '%s%s%s', $varMatch[1], $num, $varMatch[3] ), '/' ) ) );
//$regex = sprintf( $this->_def['regex']['search']['specific'], str_replace( array( ' ', '"' ), array( '.*', '' ), sprintf( '%s%s%s', $varMatch[1], $num, $varMatch[3] ) ) );
preg_match_all( $regex, $page, $matches );
$tmp = $this->_flagFilter( $matches, 1, $flags );
if ( is_array( $tmp ) ) {
$res[] = $tmp[0];
}
}
return $res;
}
} else {
$url = sprintf( $this->_def['url']['search'], urlencode( $query ) );
}
// do the search
$page = $this->_getUrl( $url );
// split the result up
preg_match_all( $this->_def['regex']['search']['result'], $page, $matches );
$res = $this->_flagFilter( $matches, $results, $flags );
return $res;
}
/**
* Search for some nzbv2 posts
*
* @param string $query - newzbin.com search query
* @param string $showID - TVrage show ID
* @param string $epID - TVrage episode ID
* @param int $results - Number of results to return, 0 = all
* @param array $flags - List of flags to conform to, default: empty, i.e. first result
* @returns array - All the results in an array
* @access public
*/
function idSearch( $query, $showID, $epID, $results, $flags = array() )
{
global $irc;
$res = array();
$url = sprintf( $this->_def['url']['search'], urlencode( $query ) );
// do the search
$page = $this->_getUrl( $url );
$regex = sprintf( $this->_def['regex']['search']['urlmatch'], sprintf( $this->_def['regex']['search']['tvrage'], $showID, $epID ) );
// split the result up
preg_match_all( $regex, $page, $matches );
$res = $this->_flagFilter( $matches, $results, $flags );
return $res;
}
/**
* Filter result by flags
*
* @param array $results - Search results
* @param int $numRes - Number of results to return
* @param array $flags - Flags
* @param bool $sort - Sort the list based on flags
* @return array - Only the relevant results are kept
* @access private
*/
function _flagFilter( $results, $numRes, $flags, $sort = true )
{
$res = array();
$score = array();
$age = array();
for ( $r = 0; $r < count($results[0]); $r++ )
{
/**
* 1 => date
* 2 => id
* 3 => title
* 4 => url
*/
preg_match( '/^(\w+), (\d+) (\w+) (\d+) (\d+):(\d+):(\d+)/i', $results[1][$r], $tMatch );
$time = strtotime( sprintf( '%d %s %d %d:%d:%d', $tMatch[2], $tMatch[3], $tMatch[4], $tMatch[5], $tMatch[6], $tMatch[7] ) );
$result = array(
'title' => $this->stringDecode( $results[3][$r] ),
'id' => $results[2][$r],
'url' => $results[4][$r],
'reported' => $time );
if ( count( $flags ) > 0 )
{
$tot = 0;
$result['report'] = $this->getReport( $result['id'] );
$result['category'] = $result['report']['category'];
// check langauge [if config blank: any, if result blank: english, otherwise exact match]
if ( ( empty( $this->_config['language'] ) ) ||
( empty( $result['report']['language'] ) ) ||
( $this->_config['language'] == $result['report']['language'] ) ) {
for( $i=0; $i < count($flags); $i++ ) {
if ( $result['report']['attributes'][$flags[$i]] == true ) {
$tot += count($flags) - $i;
}
}
if ( $tot > 0 ) {
$result['score'] = $tot;
$res[] = $result;
}
}
} else {
if ( $r < $numRes )
{
if ( $this->_config['deepSearch'] )
$result['report'] = $this->getReport( $result['id'] );
$result['score'] = 0;
$res[] = $result;
}
}
}
if ( ( $sort ) && ( count( $flags ) > 0 ) )
{
foreach( $res as $key => $row )
{
$score[$key] = $row['score'];
$age[$key] = intval( $row['age'] );
}
array_multisort( $age, SORT_ASC, $score, SORT_DESC, $res );
$res = array_slice( $res, 0, $numRes );
}
return $res;
}
/**
* Gets the numbers inside a {01-05,06} variale
*
* @param string $variable - List of numbers
* @returns array - Of all the numbers
* @access private
*/
function _getSearchNumbers( $variable ) {
$res = array();
if ( preg_match_all( $this->_def['regex']['search']['numberSearch'], $variable, $matches ) )
{
for( $i = 0; $i < count( $matches[0] ); $i++ )
{
if ( !empty( $matches[3][$i] ) ) {
$res[] = $matches[3][$i];
}
else
{
$len = strlen( $matches[1][$i] );
for ( $j = $matches[1][$i]; $j <= $matches[2][$i]; $j++ ) {
$res[] = sprintf( '%0'.$len.'d', $j);
}
}
}
}
return $res;
}
/*****************************************************
* Report
*****************************************************/
/**
* Get details of a newzbin.com report
*
* @param int $id - Report ID
* @return array - Information related to the report
* @access public
*/
function getReport( $id ) {
global $irc;
$res = array(
'nzbv2id' => $id
);
$irc->_modules['store']->manualUpdate( '_nzbv2Cache' );
// check cache
if ( isset( $irc->_nzbv2Cache[$id] ) ) {
// found cache
if ( ( $irc->_nzbv2Cache[$id]['searched'] > time() - ( $this->_config['reportCache'] * 3600 * 24 ) ) &&
( mt_rand(1, 100) <= (100 * $this->_config['cacheChance']) ) )
{
$irc->modDebug( 'nzbv2', 'report ID: '.$id.', using cache', __FILE__, __LINE__ );
return $irc->_nzbv2Cache[$id];
}
}
$url = sprintf( $this->_def['url']['report'], $id );
$page = $this->_getUrl( $url );
//$res['page'] = $page;
// check if it is a report
if ( preg_match( $this->_def['regex']['reportInfo']['isReport'], $page ) )
{
$irc->modDebug( 'nzbv2', 'Report ID: '. $id .' is not a valid report', __FILE__, __LINE__ );
return false;
}
foreach( $this->_def['regex']['report'] as $id => $regID )
{
if ( is_array( $regID ) )
{
if ( is_array( $regID['regex'] ) ) {
foreach( $regID['regex'] as $regex ) {
if ( preg_match( $regex, $page, $match ) ) {
for( $i=1; $i < count($match); $i++ ) {
$res[$regID['vals'][$i]] = $this->stringDecode( $match[$i] );
}
break;
}
}
} else {
if ( preg_match( $regID['regex'], $page, $match ) ) {
for( $i=1; $i < count($match); $i++ ) {
$res[$regID['vals'][$i]] = $this->stringDecode( $match[$i] );
}
}
}
}
}
$map = array(
'Format' => 'video format',
'Res' => 'resolution',
'Source' => 'video source',
'Audio' => 'audio Format' );
foreach( $irc->_modules['ed']->_def['attributes'] as $attr => $aArr )
{
foreach( $aArr as $id => $regex ) {
if ( substr( $regex, 0, 1 ) == '!' )
{
if ( !preg_match( sprintf( $this->_def['regex']['reportInfo']['specificFilename'], substr( $regex, 2, -2 ) ), $page ) ) {
$res['attributes'][strtolower($id)] = true;
if ( ( ( isset( $res[$map[$attr]] ) ) && ( !in_array( $id, $res[$map[$attr]] ) ) ) ||
( !isset( $res[$map[$attr]] ) ) )
{
$res[$map[$attr]][] = $id;
}
}
}
else
{
if ( preg_match( sprintf( $this->_def['regex']['reportInfo']['specificFilename'], substr( $regex, 1, -2 ) ), $page ) ) {
$res['attributes'][strtolower($id)] = true;
if ( ( ( isset( $res[$map[$attr]] ) ) && ( !in_array( $id, $res[$map[$attr]] ) ) ) ||
( !isset( $res[$map[$attr]] ) ) )
{
$res[$map[$attr]][] = $id;
}
}
}
}
}
$res['searched'] = time();
$irc->_nzbv2Cache[$res['nzbv2id']] = &$res;
$this->_checkReports();
return $res;
}
function _checkReports()
{
global $irc;
foreach( $irc->_nzbv2Cache as $id => $nzbv2 )
{
if ( $nzbv2['searched'] < ( time() - ( $this->_config['reportCache'] * 3600 * 24 ) ) )
{
unset( $irc->_nzbv2Cache[$id] );
}
}
$irc->_modules['store']->manualUpdate( '_nzbv2Cache', true );
}
/*****************************************************
* Worker Thread Stuffs
*****************************************************/
function checknzbv2( &$irc, $vars )
{
// check wait variable
if ( ( $irc->isWorker == true ) ||
( ( $irc->config->useWorker == false ) &&
( $irc->isWorker == false ) ) )
{
$irc->_modules['store']->manualUpdate( array( '_nzbv2Wait', '_nzbv2Queued', '_nzbv2QError' ) );
if ( ( isset( $irc->_nzbv2Wait ) ) && ( count( $irc->_nzbv2Wait ) > 0 ) )
{
list( $succ, $errors ) = $this->addIds( $irc->_nzbv2Wait );
foreach( $succ as $s1 )
{
$irc->_nzbv2Queued[] = $s1;
foreach( $s1 as $sInfo )
{
unset( $irc->_nzbv2Wait[$sInfo['id']] );
}
}
foreach( $errors as $e1 )
{
$irc->_nzbv2QError[] = $e1;
foreach( $e1 as $eInfo )
{
if ( stristr( $eInfo['id'], ',' ) )
{
$nIds = explode( ',', $eInfo );
foreach( $nIds as $anID )
{
unset( $irc->_nzbv2Wait[$anID] );
}
}
else
{
unset( $irc->_nzbv2Wait[$eInfo['id']] );
}
}
}
// update variables
$irc->_modules['store']->manualUpdate( array( '_nzbv2Wait', '_nzbv2Queued', '_nzbv2QError' ), true );
}
}
if ( ( $irc->config->useWorker == true ) &&
( $irc->isWorker == false ) )
{
$irc->_modules['store']->manualUpdate( array( '_nzbv2Queued', '_nzbv2QError' ) );
if ( ( isset( $irc->_nzbv2Queued ) ) && ( count( $irc->_nzbv2Queued ) > 0 ) )
{
foreach( $irc->_nzbv2Queued as $succ )
{
if ( is_array( $succ ) )
{
$vars['addQueued'] = $succ;
$this->parseTemplate( $msg, 'addSucc', $vars );
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $succ[0]['data'], $msg, $succ[0]['data']->notice );
unset( $msg );
}
unset( $vars );
}
$irc->_nzbv2Queued = array();
$irc->_modules['store']->manualUpdate( '_nzbv2Queued', true );
}
if ( ( isset( $irc->_nzbv2QError ) ) &&
( is_array( $irc->_nzbv2QError ) ) &&
( count( $irc->_nzbv2QError ) > 0 ) )
{
foreach( $irc->_nzbv2QError as $errors )
{
if ( is_array( $errors ) )
{
$vars['addQueued'] = $errors;
$this->parseTemplate( $msg, 'addError', $vars );
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $errors[0]['data'], $msg, $errors[0]['data']->notice );
unset( $msg );
}
unset( $vars );
}
$irc->_nzbv2QError = array();
$irc->_modules['store']->manualUpdate( '_nzbv2QError', true );
}
}
}
/**
* Add a bunch of ids to download
*
* @var array ids - Array of ids/urls to add
* @return array - Successful and Failed enties
*/
function addIds( $ids )
{
global $irc;
$dArray = array();
$succ = array();
$errors = array();
foreach( $ids as $tmp => $res )
{
if ( !isset( $res['id'] ) )
{
unset( $irc->_nzbv2Wait[$tmp] );
$irc->_modules['store']->manualUpdate( '_nzbv2Wait', true );
continue;
}
if ( substr( $res['id'], 0, 9 ) == '117114108' )
{
if ( ( $title = $this->_addUrl( $res['id'], $res['url'] ) ) !== false )
{
$succ[$this->_findDMatch( $dArray, $res['data'] )][] = array(
'id' => $res['id'],
'data' => $res['data'],
'title' => $title );
}
else
{
$errors[$this->_findDMatch( $dArray, $res['data'] )][] = array(
'id' => $res['id'],
'data' => $res['data'],
'title' => $this->_error );
}
}
else if ( isset( $res['id'] ) )
{
if ( ( $title = $this->_addID( $res['id'], $res['data'], $res['data']->hellaMod ) ) !== false )
{
$succ[$this->_findDMatch( $dArray, $res['data'] )][] = array(
'id' => $res['id'],
'data' => $res['data'],
'title' => $title );
}
else
{
if ( !preg_match( $this->_def['regex']['download']['Dnzbv2wait'], $this->_error ) )
{
$errors[$this->_findDMatch( $dArray, $res['data'] )][] = array(
'id' => $res['id'],
'data' => $res['data'],
'title' => $this->_error );
}
else
{
$wait[$this->_findDMatch( $dArray, $res['data'] )][] = $res['id'];
}
}
}
}
if ( isset( $wait ) )
{
foreach( $wait as $dID => $arr )
{
$errors[$dID][] = array(
'id' => implode( ',', $arr ),
'title' => 'Waiting for Newzbin\'s 5nzbv2s/minute limit to timeout' );
}
}
return array( $succ, $errors );
}
function _findDMatch( &$dArray, $data )
{
if ( ( is_array( $dArray ) ) && ( is_array( $data ) ) )
{
foreach( $dArray as $id => $dInfo )
{
if ( ( $dInfo['type'] == $data['type'] ) &&
( ( ( ( $dInfo['type'] == SMARTIRC_TYPE_QUERY ) ||
( $dInfo['type'] == SMARTIRC_TYPE_NOTICE ) ) &&
( $dInfo['nick'] == $data['nick'] ) ) ||
( $dInfo['type'] == SMARTIRC_TYPE_CHANNEL ) ) &&
( $dInfo['channel'] == $data['channel'] ) &&
( $dInfo['notice'] == $data['notice'] ) )
{
return $id;
}
$tD = $id+1;
}
$dArray[$tD]['data'] = $data;
return $tD;
}
}
/*****************************************************
* Newzbin.com login functions
*****************************************************/
function _getWeb( $url )
{
global $irc;
$req = new HTTP_Request( );
$req->setMethod(HTTP_REQUEST_METHOD_GET);
if ( isset( $irc->config->proxy ) )
{
if ( strlen($irc->config->proxy['host']) > 0 )
{
if ( strlen($irc->config->proxy['username']) > 0)
{
$req->setProxy($irc->config->proxy['host'],
$irc->config->proxy['port'],
$irc->config->proxy['username'],
$irc->config->proxy['password']);
}
else
{
$req->setProxy($irc->config->proxy['host'],
$irc->config->proxy['port']);
}
}
}
$req->setURL( $url, array( 'timeout' => '30', 'readTimeout' => 30, 'allowRedirects' => true ) );
$irc->modDebug( 'nzbv2', 'request sent for: '.$url, __FILE__, __LINE__ );
$request = $req->sendRequest();
if (PEAR::isError($request)) {
$irc->modDebug( 'nzbv2', 'failed to get '.$url.', error: '.$request->getMessage(), __FILE__, __LINE__ );
unset( $req, $request );
} else {
$body = $req->getResponseBody();
unset( $req, $request );
return $body;
}
}
/**
* Get a url from newzbin.com
*
* @param string $url - URL to get
* @return string - Page retrived
* @access private
*/
function _getUrl( $url )
{
global $irc;
$req = new HTTP_Request( );
$req->setMethod(HTTP_REQUEST_METHOD_GET);
if ( isset( $irc->config->proxy ) )
{
if ( strlen($irc->config->proxy['host']) > 0 )
{
if ( strlen($irc->config->proxy['username']) > 0)
{
$req->setProxy($irc->config->proxy['host'],
$irc->config->proxy['port'],
$irc->config->proxy['username'],
$irc->config->proxy['password']);
}
else
{
$req->setProxy($irc->config->proxy['host'],
$irc->config->proxy['port']);
}
}
}
$req->setURL( $url, array( 'timeout' => '30', 'readTimeout' => 30, 'allowRedirects' => true ) );
// check login info
if ( $this->_config['nbLogin'] == true ) {
$irc->_modules['store']->manualUpdate('_nzbv2Cookie');
if ( empty( $irc->_nzbv2Cookie ) ) {
$irc->modDebug( 'nzbv2', 'cookie does not exist', __FILE__, __LINE__ );
$this->_login();
}
$req->addCookie( 'PHPSESSID', $irc->_nzbv2Cookie['value'] );
}
$request = $req->sendRequest();
$irc->modDebug( 'nzbv2', 'request sent for: '.$url, __FILE__, __LINE__ );
if (PEAR::isError($request)) {
$irc->modDebug( 'nzbv2', 'failed to get '.$url.', error: '.$request->getMessage(), __FILE__, __LINE__ );
unset( $req, $request );
return false;
} else {
$body = $req->getResponseBody();
unset( $req, $request );
if ( ( $this->_config['nbLogin'] == true ) && ( !$this->_loggedIn( $body ) ) ) {
if ( $this->_login() ) {
$irc->modDebug( 'nzbv2', 'cookie timed out, re-logging in', __FILE__, __LINE__ );
return $this->_getUrl( $url );
}
}
return $body;
}
}
/**
* Download a nzbv2 from a random url
*
* @param string $url - URL
* @param string $file - filename to save
*/
function _downloadURL( $url, $file )
{
global $irc;
$fp = @fopen( $file, 'w' );
if (!$fp) return 'unable to open file: '.$file;
$req = new HTTP_Request( );
$req->setMethod(HTTP_REQUEST_METHOD_GET);
if ( isset( $irc->config->proxy ) )
{
if ( strlen($irc->config->proxy['host']) > 0 )
{
if ( strlen($irc->config->proxy['username']) > 0)
{
$req->setProxy($irc->config->proxy['host'],
$irc->config->proxy['port'],
$irc->config->proxy['username'],
$irc->config->proxy['password']);
}
else
{
$req->setProxy($irc->config->proxy['host'],
$irc->config->proxy['port']);
}
}
}
$req->setURL( $url,
array( 'timeout' => '60', 'readTimeout' => 120, 'allowRedirects' => true ) );
ini_set( 'memory_limit', '50M' );
$request = $req->sendRequest();
$irc->modDebug( 'nzbv2', 'request sent for: '.$url, __FILE__, __LINE__ );
if (PEAR::isError($request))
{
$irc->modDebug( 'nzbv2', 'failed to get '.$url.', error: '.$request->getMessage(), __FILE__, __LINE__, SMARTIRC_DEBUG_MODULES );
fclose( $fp );
ini_set( 'memory_limit', '8M' );
$msg = $request->getMessage();
unset( $req, $request );
return chr(2).'Error:'.chr(2).' '.$msg;
}
else
{
$body = $req->getResponseBody();
unset( $req, $request );
fwrite( $fp, $body );
fclose( $fp );
ini_set( 'memory_limit', '8M' );
return true;
}
}
/**
* Download a nzbv2 from newzbin.com
*
* @param int $id - Newzbin.com ID
* @param string $file - file to save the nzbv2 to
*/
function _downloadnzbv2( $id, $file, &$data )
{
global $irc;
if ( $this->_config['nbLogin'] )
{
if ( $this->_config['download']['useDnzbv2'] )
{
return $this->_downloadDnzbv2( $id, $file, $data );
}
$page = $this->_getUrl( sprintf( $this->_def['url']['report'], $id ) );
// existance check
if ( preg_match( $this->_def['regex']['reportInfo']['isReport'], $nbpage ) ) {
return 'Report does not exist';
} else if ( preg_match( $this->_def['regex']['reportInfo']['hasFiles'], $nbpage ) ) {
return 'Report has no files';
}
preg_match_all( '/type="checkbox" name="(\d+)" checked="checked" \/>/i', $page, $checkboxes );
$post = array( 'msgidlist' => 'Get Message-IDs' );
foreach( $checkboxes[1] as $value ) {
$post[$value] = 'on';
}
if ( count( $post ) == 1 ) {
return 'No files found';
}
if ( empty( $irc->_nzbv2Cookie ) ) {
$irc->modDebug( 'nzbv2', 'cookie does not exist', __FILE__, __LINE__, SMARTIRC_DEBUG_MODULES );
$this->_login();
}
$req = new HTTP_Request( );
$req->setMethod(HTTP_REQUEST_METHOD_POST);
if ( isset( $irc->config->proxy ) )
{
if ( strlen($irc->config->proxy['host']) > 0 )
{
if ( strlen($irc->config->proxy['username']) > 0)
{
$req->setProxy($irc->config->proxy['host'],
$irc->config->proxy['port'],
$irc->config->proxy['username'],
$irc->config->proxy['password']);
}
else
{
$req->setProxy($irc->config->proxy['host'],
$irc->config->proxy['port']);
}
}
}
$url = sprintf( $this->_def['url']['download'], $id );
$req->setURL( $url,
array( 'timeout' => '60', 'readTimeout' => 120, 'allowRedirects' => true ) );
$req->addHeader( 'referer', sprintf( $this->_def['url']['report'], $id ) );
$req->addHeader( 'Content-type', 'application/x-www-form-urlencoded' );
$req->addCookie( 'PHPSESSID', $irc->_nzbv2Cookie['value'] );
foreach( $post as $key => $value )
{
$req->addPostData( $key, $value );
}
ini_set( 'memory_limit', ($irc->config->memoryAllocation * 4).'M' );
$request = $req->sendRequest();
$irc->modDebug( 'nzbv2', 'request sent for: '.$url, __FILE__, __LINE__ );
if (PEAR::isError($request))
{
$irc->modDebug( 'nzbv2', 'failed to get '.$url.', error: '.$request->getMessage(), __FILE__, __LINE__, SMARTIRC_DEBUG_MODULES );
ini_set( 'memory_limit', $irc->config->memoryAllocation.'M' );
$msg = $request->getMessage();
unset( $req, $request );
return chr(2).'Error:'.chr(2).' '.$msg;
}
else
{
$body = $req->getResponseBody();
unset( $req, $request );
$fp = @fopen( $file, 'w' );
if (!$fp) {
$irc->modDebug( 'nzbv2', 'unable to open file: '.$file, __FILE__, __LINE__, SMARTIRC_DEBUG_MODULES );
return 'unable to open file: '.$file;
}
fwrite( $fp, $body );
fclose( $fp );
ini_set( 'memory_limit', $irc->config->memoryAllocation.'M' );
return true;
}
}
else
{
return chr(2).'Config:'.chr(2).' \'nbLogin\' needs to be set in the configuration file';
}
}
function flushDnzbv2( &$irc )
{
$irc->_nzbv2Dnzbv2Wait = false;
$irc->unregisterTimeid( $irc->_nzbv2Dnzbv2WaitID );
foreach( $irc->_nzbv2Dnzbv2Queue as $item )
{
if ( ( $title = $this->_addID( $item['id'], $item['data'], $item['data']->hellaMod ) ) !== false )
{
$succ[] = array(
'id' => $item['id'],
'title' => $title );
unset( $irc->_nzbv2Dnzbv2Queue[$item['id']] );
}
else
{
if ( !preg_match( $this->_def['regex']['download']['Dnzbv2wait'], $this->_error ) )
{
$errors[] = array(
'id' => $item['id'],
'title' => $this->_error );
}
else
{
$wait[] = $item['id'];
}
}
}
$vars['seperator'] = ', ';
if ( is_array( $succ ) )
{
$vars['addQueued'] = $succ;
$this->parseTemplate( $msg, 'addSucc', $vars );
}
if ( isset( $wait ) )
{
/*
$errors[] = array(
'id' => implode( ',', $wait ),
'title' => 'Waiting for Newzbin\'s 5nzbv2s/minute limit to timeout' );
*/
}
if ( is_array( $errors ) )
{
$vars['addQueued'] = $errors;
$this->parseTemplate( $msg, 'addError', $vars );
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $item['data'], $msg, $item['data']->notice );
}
}
function _downloadDnzbv2( $id, $file, &$data )
{
global $irc;
if ( $irc->_nzbv2Dnzbv2Wait == true )
{
$tdata = (object)array(
'nick' => $data->nick,
'channel' => $data->channel,
'type' => $data->type,
'notice' => $notice,
'hellaMod' => $data->hellaMod );
$irc->_nzbv2Dnzbv2Queue[$id] = array(
'id' => $id,
'file' => $file,
'data' => $tdata );
return 'Try Later, wait 60 seconds for counter to reset';
}
$req = new HTTP_Request();
$req->setMethod(HTTP_REQUEST_METHOD_POST);
if ( isset( $irc->config->proxy ) )
{
if ( strlen($irc->config->proxy['host']) > 0 )
{
if ( strlen($irc->config->proxy['username']) > 0)
{
$req->setProxy($irc->config->proxy['host'],
$irc->config->proxy['port'],
$irc->config->proxy['username'],
$irc->config->proxy['password']);
}
else
{
$req->setProxy($irc->config->proxy['host'],
$irc->config->proxy['port']);
}
}
}
$req->setURL('http://v3.newzbin.com/dnzbv2/', array( 'timeout' => 60, 'readTimeout' => 120 ) );
$req->addPostData( 'username', $this->_config['login']['username'] );
$req->addPostData( 'password', $this->_config['login']['password'] );
$req->addPostData( 'reportid', $id );
$irc->modDebug( 'nzbv2', 'DNZD request sent for id: '.$id, __FILE__, __LINE__ );
ini_set( 'memory_limit', ($irc->config->memoryAllocation * 4).'M' );
$reqest = $req->sendRequest();
// check for errors
if ( $req->getResponseCode() != '200' )
{
$rCode = $req->getResponseHeader('X-Dnzbv2-RCode');
fclose( $fp );
switch ( $rCode )
{
case 400:
// bad request (invalid report id)
{
$irc->modDebug( 'nzbv2', 'Error: 400, Invalid Report ID: '.$id, __FILE__, __LINE__ );
ini_set( 'memory_limit', $irc->config->memoryAllocation.'M' );
unset( $req, $request );
return chr(2).'Error:'.chr(2).' Invalid Report ID: '.$id;
}
case 401:
// unauthorized, check u/p
{
$irc->modDebug( 'nzbv2', 'Error: 401, Incorrect user details, please check your login details', __FILE__, __LINE__ );
ini_set( 'memory_limit', $irc->config->memoryAllocation.'M' );
unset( $req, $request );
return chr(2).'Error:'.chr(2).' Incorrect login details, please check them';
}
case 402:
// premium account required
{
$irc->modDebug( 'nzbv2', 'Error: 402, Premium accoun Required', __FILE__, __LINE__ );
ini_set( 'memory_limit', $irc->config->memoryAllocation.'M' );
unset( $req, $request );
return chr(2).'Error:'.chr(2).' A Premium account is required to download nzbv2\'s';
}
case 404:
// not found, report doesnt exist
{
$irc->modDebug( 'nzbv2', 'Error: 404, The report does not exist', __FILE__, __LINE__ );
ini_set( 'memory_limit', $irc->config->memoryAllocation.'M' );
unset( $req, $request );
return chr(2).'Error:'.chr(2).' The report ID: '.$id.', does not exist';
}
case 450:
// try again later
{
$rMsg = $req->getResponseHeader( 'X-Dnzbv2-RText' );
preg_match( $this->_def['regex']['download']['Dnzbv2wait'], $rMsg, $time );
$irc->modDebug( 'nzbv2', 'Error: 450, '.$rMsg, __FILE__, __LINE__ );
$irc->_nzbv2Dnzbv2Wait = true;
$irc->_nzbv2Dnzbv2WaitID = $irc->registerTimehandler( ($time[1] + 2) * 1000, $this, 'flushDnzbv2' );
$tdata = (object)array(
'nick' => $data->nick,
'channel' => $data->channel,
'type' => $data->type,
'notice' => $notice,
'hellaMod' => $data->hellaMod );
$irc->_nzbv2Dnzbv2Queue[$id] = array(
'id' => $id,
'file' => $file,
'data' => $tdata );
ini_set( 'memory_limit', $irc->config->memoryAllocation.'M' );
unset( $req, $request );
return $rMsg;
}
case 500:
// newzbin is broken
case 503:
// newzbin is really broken
$irc->modDebug( 'nzbv2', 'Newzbin.com is borked', __FILE__, __LINE__ );
ini_set( 'memory_limit', $irc->config->memoryAllocation.'M' );
unset( $req, $request );
return chr(2).'Error:'.chr(2).' newzbin.com is broken, please try again later';
}
}
if (PEAR::isError($request))
{
$irc->modDebug( 'nzbv2', 'failed to get id: '.$id.', error: '.$request->getMessage(), __FILE__, __LINE__ );
ini_set( 'memory_limit', $irc->config->memoryAllocation.'M' );
$msg = $request->getMessage();
unset( $req, $request );
return chr(2).'Error:'.chr(2).' '.$msg;
}
else
{
$body = $req->getResponseBody();
unset( $req, $request );
$fp = @fopen( $file, 'w' );
if (!$fp) {
$irc->modDebug( 'nzbv2', 'unable to open file: '.$file, __FILE__, __LINE__ );
return 'unable to open file: '.$file;
}
fwrite( $fp, $body );
fclose( $fp );
ini_set( 'memory_limit', $irc->config->memoryAllocation.'M' );
return true;
}
}
/**
* Login to newzbin.com
*
* @return bool - True if logged in, else false
* @access private
*/
function _login() {
global $irc;
$req = new HTTP_Request( );
$req->setMethod(HTTP_REQUEST_METHOD_POST);
if ( isset( $irc->config->proxy ) )
{
if ( strlen($irc->config->proxy['host']) > 0 )
{
if ( strlen($irc->config->proxy['username']) > 0)
{
$req->setProxy($irc->config->proxy['host'],
$irc->config->proxy['port'],
$irc->config->proxy['username'],
$irc->config->proxy['password']);
}
else
{
$req->setProxy($irc->config->proxy['host'],
$irc->config->proxy['port']);
}
}
}
$req->setURL( $this->_def['url']['login'], array( 'timeout' => 30, 'readTimeout' => 30 ) );
$req->addPostData( 'username', $this->_config['login']['username'] );
$req->addPostData( 'password', $this->_config['login']['password'] );
$request = $req->sendRequest();
$irc->modDebug( 'nzbv2', 'logging into newzbin.com', __FILE__, __LINE__ );
if (PEAR::isError($request)) {
$irc->modDebug( 'nzbv2', 'failed to login, error: '.$request->getMessage(), __FILE__, __LINE__ );
unset( $req, $request );
} else {
if ( $this->_loggedIn( $req->getResponseBody() ) ) {
$cks = $req->getResponseCookies();
foreach( $cks as $cookie ) {
if ( $cookie['name'] == 'PHPSESSID' ) {
$irc->_modules['store']->setVariable( '_nzbv2Cookie', $cookie );
$irc->modDebug( 'nzbv2', 'got cookie:'.$irc->_nzbv2Cookie['value'], __FILE__, __LINE__ );
}
}
$irc->modDebug( 'nzbv2', 'login successful', __FILE__, __LINE__ );
unset( $req, $request );
return true;
} else {
$irc->modDebug( 'nzbv2', 'login Failed', __FILE__, __LINE__ );
unset( $req, $request );
return false;
}
}
}
/**
* Check to see if logged in
*
* @param string $data - Webpage data
* @return bool
* @access private
*/
function _loggedIn( $data )
{
if ( preg_match( $this->_def['regex']['loggedIn'], $data ) )
return false;
else
return true;
}
}
?>