<?php
/**************************************************
* NZBirc v1
* Copyright (c) 2006 Harry Bragg
* tiberious.org
* Module: hella
**************************************************
*
* 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_hella extends Net_SmartIRC_module_base
{
// default module variable
var $name = 'hella';
var $version = 'v0.2';
var $description = 'interfaces with hellanzb';
/**
* HellaNZB module
*
* 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 array xmlrpc
* @var string hostname - HellaNZB XML-RPC hostname
* @var int port - HellaNZB XML-RPC port
* @var string password - HellaNZB XML-RPC password
* @var array list
* @var int compactLimit - Number of results in a list, to use the compact view method (many results on one line)
* @var int positionRange - When listing a particular position, this defines how many items to list around the item you are looking for
* @var int moveTimerMax - Number of minutes to attempt to move an item in the queue (for when force/next adding)
* ENDCONFIG
*/
var $_config = array(
'publicCommand' => array( '^hella', '^!hella' ),
'privateCommand' => array( '^@hella' ),
'xmlrpc' => array(
'hostname' => 'hostname',
'port' => 8760,
'password' => 'password' ),
'list' => array(
'compactLimit' => 6,
'positionRange' => 3
),
'moveTimerMax' => 20
);
var $_template = array(
'status' => array(
'Hellanzb {version}: up {uptime} | downloaded {total_dl_nzbs} nzbs, {total_dl_files} files ({total_dl_mb}) - {status} [{queued_mb}, ETA: {eta} ({percent_complete}%)]',
'Downloading: {downloading}, Processing: {processing}, Queued: {queuedItems}'
),
'downloading' => '[{id}:{msgid}] {nzbName}',
'processing' => '[{id}:{msgid}] {nzbName}',
'queuedItems' => '{total} ({size}{time})',
'listShort' => '{listItemShort}',
'listItem' => '({queuePos}) [{id}:{msgid}] {nzbName}{listItemInfo}',
'listItemShort' => '({queuePos}) [{id}:{msgid}] {nzbName}',
'listItemInfo' => ' ({user}{queued}{size}{category}{age})',
'listEmpty' => 'No items found in the queue {search}',
'paused' => 'Download paused for {pauseLength}',
'unpaused' => 'Downloads have been resumed',
'force' => 'Report: {downloading} forced to the front of the queue',
'next' => 'Report: {downloading} moved to next in the queue',
'last' => 'Report: {downloading} moved to last in the queue',
'move' => 'Report: {downloading} moved to position: {position}',
'newrate' => 'Maxrate set to: {maxrate} kb/s',
'currentrate' => 'Current maxrate: {maxrate} kb/s',
'error' => '**Error:** {errormsg}',
'commandList' => 'List of commands available for HellaNZB | type {trigger} help command, for more information on each command',
'help' => '{command} - {description}',
'helpList' => array(
'Commands available for HellaNZB: {helpCommands}',
'Type: {trigger} {subTrigger} command, for more information on each command'
),
'cancel' => 'Current download canceled',
'clear' => 'Queue list cleared',
'del' => 'Item: {listItem} deleted from the queue',
'rateAdd' => 'Added a rate schedule entry at: {time} setting rate: {rate} kb/s',
'rateList' => 'Current schedule rate changes: {rateListTime}',
'rateListTime' => '{time}: {rate} kb/s',
'rateDel' => 'Deleted the rate schedule entry at: {time}'
);
var $_def = array(
'regex' => array(
'listFlags' => array(
'pos' => '/p(?:os)?:(\d+)/i',
'user' => '/u(?:ser)?:(\w+)/i',
'limit' => '/l(?:imit)?:(\d+)/i',
'top' => '/((^(top|front|start)$)|(p(?:os)?:(top|front|start)))/i',
'end' => '/((^(end|last|back)$)|(p(?:os)?:(end|last|back)))/i',
'id' => '/i(?:d)?:(\d+)/i'
),
'itemAge' => '/(-?\d+)\s?(s|m|h|d|w)/i',
'moveID' => '/(.+)\s(\d+)$/i',
'rateAdd' => '/^(\d+) (.+)$/',
)
);
var $_help = array(
'status' => array(
'command' => '{trigger} status',
'description' => 'Get the current status of hellanzb',
'longDescription' => 'Get the current status of hellanzb'
),
'list' => array(
'command' => '{trigger} list [query] [p:position] [u:user] [l:limit] [i:id]',
'description' => 'list items in the current list, __query__ can be hellanzb\'s ID, NewzBin\'s ID, or part of the name',
'longDescription' => array(
'list items in the current list, __query__ can be hellanzb\'s ID, NewzBin\'s ID, part of the name, or match a particular keyword',
'keywords: **top**,**front**,**start** relate to the beginning of the queue, **end**,**last**,**back** relate to the end of the queue',
'p/pos:__position__ - list items around the __position__',
'u/user:__user__ - List the items the __user__ has queued',
'l/limit:__limit__ - Change the number of results returned to __limit__',
'i/id:__id__ - List the item with the hellanzb __id__'
)
),
'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'
),
'pause' => array(
'command' => '{trigger} pause [duration]',
'description' => 'Pause the downloads, if a __duration__ is specified (in format Xh Ym etc) then it will unpaused after that time, Default: 1 hour',
'longDescription' => 'Pause the downloads, if a __duration__ is specified (in format Xh Ym etc) then it will unpaused after that time, Default: 1 hour'
),
'continue' => 'unpause',
'resume' => 'unpause',
'unpause' => array(
'command' => '{trigger} unpause/continue/resume',
'description' => 'Resume downloading',
'longDescription' => 'Resume downloading'
),
'force' => array(
'command' => '{trigger} force query',
'description' => 'Forces an item in the queue, and immediatly downloads the item. __query__ can be a set of hellanzb IDs or newzbin IDs, or part of the name of an item',
'longDescription' => 'Forces an item in the queue, and immediatly downloads the item. __query__ can be a set of hellanzb IDs or newzbin IDs, or part of the name of an item'
),
'front' => 'next',
'next' => array(
'command' => '{trigger} next/front query',
'description' => 'Moves an item in the queue, to the front in the queue. __query__ can be a set of hellanzb IDs or newzbin IDs, or part of the name of an item',
'longDescription' => 'Moves an item in the queue, to the front in the queue. __query__ can be a set of hellanzb IDs or newzbin IDs, or part of the name of an item'
),
'end' => 'last',
'last' => array(
'command' => '{trigger} last/end query',
'description' => 'Moves an item in the queue, to the back of the queue. __query__ can be a set of hellanzb IDs or newzbin IDs, or part of the name of an item',
'longDescription' => 'Moves an item in the queue, to the back of the queue. __query__ can be a set of hellanzb IDs or newzbin IDs, or part of the name of an item'
),
'move' => array(
'command' => '{trigger} move query position',
'description' => 'Moves the item defined in __query__ to __position__ in the queue. __query__ can be a set of hellanzb IDs or newzbin IDs, or part of the name of an item',
'longDescription' => 'Moves the item defined in __query__ to __position__ in the queue. __query__ can be a set of hellanzb IDs or newzbin IDs, or part of the name of an item'
),
'maxrate' => 'rate',
'rate' => array(
'command' => '{trigger} rate/maxrate [newrate]',
'description' => 'Set the maximum rate of hellanzb in kb/s. A value of 0 means unlimited. For rate scheduling use {trigger} help rate add/list/del',
'longDescription' => 'Set the maximum rate of hellanzb in kb/s. A value of 0 means unlimited. For rate scheduling use {trigger} help rate add/list/del'
),
'maxrate add' => 'rate add',
'rate add' => array(
'command' => '{trigger} rate add speed time',
'description' => 'Add a new entry into the rate scheduler, these will automatically alter the __speed__ hellanzb downloads at, at different times of the day, __time__ is in stardard time formats (ie: 09:00pm)',
'longDescription' => 'Add a new entry into the rate scheduler, these will automatically alter the __speed__ hellanzb downloads at, at different times of the day, __time__ is in stardard time formats (ie: 09:00pm)'
),
'maxrate list' => 'rate list',
'rate list' => array(
'command' => '{trigger} rate list',
'description' => 'List the current rate scheduler entries',
'longDescription' => 'List the current rate scheduler entries'
),
'maxrate delete' => 'rate del',
'rate delete' => 'rate del',
'maxrate del' => 'rate del',
'rate del' => array(
'command' => '{trigger} rate del time',
'description' => 'Delete an entry from the rate scheduler, that matches __time__',
'longDescription' => 'Delete an entry from the rate scheduler, that matches __time__'
),
'cancel' => array(
'command' => '{trigger} cancel',
'description' => 'Cancel the current nzb being downloaded',
'longDescription' => 'Cancel the current nzb being downloaded'
)
);
/**
* Error store
*/
var $_error;
function _registerCommands()
{
global $irc;
$this->_setHandler( '^status', $this, 'botStatus' );
$this->_setHandler( '^list', $this, 'botList' );
$this->_setHandler( '^pause', $this, 'botPause' );
$this->_setHandler( '^(unpause|continue|resume)', $this, 'botUnPause' );
$this->_setHandler( '^(force|next|front|last|end|move) ', $this, 'botMove' );
$this->_setHandler( '^(max)?rate( (\d+))?$', $this, 'botRate' );
$this->_setHandler( '^(max)?rate add', $this, 'botRateAdd' );
$this->_setHandler( '^(max)?rate list', $this, 'botRateList' );
$this->_setHandler( '^(max)?rate del(ete)?', $this, 'botRateDel' );
$this->_setHandler( '^clear', $this, 'botClear' );
$this->_setHandler( '^cancel', $this, 'botCancel' );
$this->_setHandler( '^del(ete)?', $this, 'botDel' );
$this->_setHandler( '^help', $this, 'botHelp' );
$this->_setHandler( '^commands', $this, 'botCommands' );
// connect to xmlrpc server
$this->_connect();
if ( !$irc->isWorker ) {
$irc->_modules['store']->addVariable( '_hellaRate' );
$irc->_hellaSSTimer = $irc->registerTimehandler( 2000, $this, '_setupSetupTimers' );
}
}
function _customClose()
{
global $irc;
$this->_unsetRateTimers();
$irc->_modules['store']->manualUpdate( '_hellaRate', true );
}
/*****************************************************
* Bot functions
*****************************************************/
function botStatus( &$irc, &$data, $notice )
{
if ( ( $hella = $this->_send( 'status' ) ) !== false )
{
$vars = array(
'version' => $hella['version'],
'uptime' => $hella['uptime'],
'total_dl_nzbs' => number_format( $hella['total_dl_nzbs'] ),
'total_dl_files' => number_format( $hella['total_dl_files'] ),
'total_dl_mb' => $irc->_modules['func']->humanSize( $hella['total_dl_mb'], 2 ),
'queued_mb' => $irc->_modules['func']->humanSize( $hella['queued_mb'], 2 ),
'eta' => $irc->_modules['func']->duration( $hella['eta'], true ),
'percent_complete' => $hella['percent_complete'] );
if ( count( $hella['queued'] > 0 ) )
{
$qmb = $this->getQueueSize( $hella['queued'] );
if ( $hella['rate'] > 0 )
{
$qtime = $qmb * 1024 / ( $hella['rate'] + 0.0001 );
$stime = ', '.substr( $irc->_modules['func']->duration( $qtime ), 0, -1 );
}
else
{
$stime = '';
}
$vars['queuedItems'][] = array(
'total' => count( $hella['queued'] ),
'size' => $irc->_modules['func']->humanSize( $qmb, 2 ),
'time' => $stime
);
}
else
{
$vars['queuedItems'] = 'None';
}
// status
$vars['status'] = ( $hella['is_paused'] == 1 )? 'Paused':
( ( $hella['rate'] == 0 )? 'Idle':
round( $hella['rate'], 1 ).( ( $hella['maxrate'] > 0 )? '/'.$hella['maxrate']:'').' **kb/s**' );
if ( count( $hella['currently_downloading'] ) == 0 )
$vars['downloading'] = 'None';
else
{
for( $i=0; $i < count( $hella['currently_downloading'] ); $i++ )
{
$hella['currently_downloading'][$i]['nzbName'] = trim( str_replace( '_', ' ', $hella['currently_downloading'][$i]['nzbName'] ) );
}
$vars['downloading'] = $hella['currently_downloading'];
}
if ( count( $hella['currently_processing'] ) == 0 )
$vars['processing'] = 'None';
else
{
for( $i=0; $i < count( $hella['currently_processing'] ); $i++ )
{
$hella['currently_processing'][$i]['nzbName'] = trim( str_replace( '_', ' ', $hella['currently_processing'][$i]['nzbName'] ) );
}
$vars['processing'] = $hella['currently_processing'];
}
$this->parseTemplate( $msg, 'status', $vars );
if ( isset( $msg ) )
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
else
{
$msg[] = $this->_error;
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
}
function botList( &$irc, &$data, $notice )
{
if ( ( $list = $this->listSearch( $data->subMessage ) ) !== false )
{
if ( count( $list ) == 0 )
{
$this->parseTemplate( $msg, 'listEmpty', array( 'search' => $data->subMessage ) );
}
else if ( count( $list ) > $this->_config['list']['compactLimit'] )
{
$tmp['listItemShort'] = $list;
$this->parseTemplate( $msg, 'listShort', $tmp );
}
else
{
foreach( $list as $item )
{
$this->parseTemplate( $msg, 'listItem', $item );
}
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
}
else
{
$msg[] = $this->_error;
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
}
function botPause( &$irc, &$data, $notice )
{
if ( $this->_send( 'pause' ) !== false )
{
if ( strlen( $data->subMessage ) > 1 )
{
$num = array( 'w' => 604800, 'd' => 86400, 'h' => 3600, 'm' => 60, 's' => 1 );
if ( preg_match_all( $this->_def['regex']['itemAge'], $data->subMessage, $matches ) )
{
for( $i=0; $i < count($matches[0]); $i++ ) {
$time += $matches[1][$i] * $num[$matches[2][$i]];
}
}
}
if ( $time < 60 )
{
$time = 3600;
}
if ( isset( $irc->_hellaPauseID ) )
{
$irc->unregisterTimeid( $irc->_hellaPauseID );
}
$irc->_hellaPauseID = $irc->registerTimehandler( ($time) * 1000, $this, 'unpause' );
$vars['pauseLength'] = $irc->_modules['func']->duration( $time );
$this->parseTemplate( $msg, 'paused', $vars );
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
}
function botUnPause( &$irc, &$data, $notice )
{
if ( $this->_send( 'continue' ) !== false )
{
if ( isset( $irc->_hellaPauseID ) )
{
$irc->unregisterTimeid( $irc->_hellaPauseID );
unset( $irc->_hellaPauseID );
}
$this->parseTemplate( $msg, 'unpaused', array() );
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
}
function botMove( &$irc, &$data, $notice )
{
switch ( $data->trig[1] )
{
case 'force':
case 'next':
case 'last':
case 'front':
case 'end':
{
$smEx = explode( ' ', $data->subMessage );
if ( isset( $smEx[0] ) && preg_match( '/^(\d+)$/', $smEx[0] ) )
{
foreach( $smEx as $sNum )
{
$searchList[] = $sNum;
}
}
else
{
$searchList[] = $data->subMessage;
}
foreach( $searchList as $search )
{
// check to see if it exists
if ( ( $list = $this->listSearch( $search ) ) !== false )
{
if ( count( $list ) == 1 )
{
$ta = array( 'last' => -2, 'next' => -1, 'force' => 0, 'end' => -2, 'front' => -1 );
$this->moveItem( $list[0]['msgid'], $ta[$data->trig[1]], $irc->_modules['func']->getTData( $data ) );
}
else if ( count( $list ) == 0 )
{
$this->parseTemplate( $msg, 'error', array( 'errormsg' => 'No Results found in the queue for query: {query}', 'query' => $search ) );
}
else
{
$this->parseTemplate( $msg, 'error', array( 'errormsg' => 'Too many Results found in the queue for query: {query}', 'query' => $search ) );
}
}
else
{
$this->parseTemplate( $msg, 'error', array( 'errormsg' => $this->_error ) );
}
}
break;
}
case 'move':
{
if ( preg_match( $this->_def['regex']['moveID'], $data->subMessage, $match ) )
{
$smEx = explode( ' ', $match[2] );
if ( isset( $smEx[0] ) && preg_match( '/^(\d+)$/', $smEx[0] ) )
{
foreach( $smEx as $sNum )
{
$searchList[] = $sNum;
}
}
else
{
$searchList[] = $match[2];
}
foreach( $searchList as $search )
{
// check to see if it exists
if ( ( $list = $this->listSearch( $search ) ) !== false )
{
if ( count( $list ) == 1 )
{
$this->moveItem( $list[0]['msgid'], $match[2], $irc->_modules['func']->getTData( $data ) );
}
else if ( count( $list ) == 0 )
{
$this->parseTemplate( $msg, 'error', array( 'errormsg' => 'No Results found in the queue for query: {query}', 'query' => $search ) );
}
else
{
$this->parseTemplate( $msg, 'error', array( 'errormsg' => 'Too many Results found in the queue for query: {query}', 'query' => $search ) );
}
}
else
{
$this->parseTemplate( $msg, 'error', array( 'errormsg' => $this->_error ) );
}
}
}
else
{
$this->parseTemplate( $msg, 'error', array( 'errormsg' => 'Query: {query} did not match the correct format', 'query' => $data->subMessage ) );
}
break;
}
}
if ( isset( $msg ) )
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
function botRate( &$irc, &$data, $notice )
{
if ( strlen( $data->trig[2] ) > 0 )
{
if ( is_numeric( $data->trig[2] ) )
{
if ( ( $hella = $this->_send( 'maxrate', array( $data->trig[2] ) ) ) !== false )
{
$this->parseTemplate( $msg, 'newrate', array( 'maxrate' => $data->trig[2] ) );
}
else
{
$this->parseTemplate( $msg, 'error', array( 'errormsg' => $this->_error ) );
}
}
else
{
$this->parseTemplate( $msg, 'error', array( 'errormsg' => sprintf( 'New rate: %s, is not a number', $data->subMessage ) ) );
}
}
else
{
if ( ( $hella = $this->_send( 'maxrate' ) ) !== false )
{
$this->parseTemplate( $msg, 'currentrate', array( 'maxrate' => $hella ) );
}
else
{
$this->parseTemplate( $msg, 'error', array( 'errormsg' => $this->_error ) );
}
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
}
function botRateAdd( &$irc, &$data, $notice )
{
if ( preg_match( $this->_def['regex']['rateAdd'], $data->subMessage, $match ) )
{
// check the time works
$time = strtotime( '1970/01/01 '.$match[2] );
if ( $time > -1 )
{
$tFor = date( 'h:ia', $time );
$irc->_hellaRate[] = array(
'time' => $tFor,
'rate' => $match[1],
'data' => $irc->_modules['func']->getTData( $data ) );
$this->_unsetRateTimers();
$this->_setupRateTimers();
$this->parseTemplate( $msg, 'rateAdd', array( 'time' => $tFor, 'rate' => $match[1] ) );
}
else
{
$this->parseTemplate( $msg, 'error', array( 'errormsg' => 'Time is in an invalid format, could not understand: {time}', 'time' => $match[2] ) );
}
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
}
function botRateList( &$irc, &$data, $notice )
{
if ( isset( $irc->_hellaRate ) )
{
foreach( $irc->_hellaRate as $id => $rate )
{
if ( $rate['rate'] == 0 )
$rate['rate'] = 'Unlimited';
$vars['rateListTime'][] = $rate;
}
$this->parseTemplate( $msg, 'rateList', $vars );
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
}
function botRateDel( &$irc, &$data, $notice )
{
if ( isset( $irc->_hellaRate ) )
{
$cTime = date( 'h:ia', strtotime( '1970/01/01 '.$data->subMessage ) );
foreach( $irc->_hellaRate as $id => $rate )
{
if ( $rate['time'] == $cTime )
{
$this->_unsetRateTimers();
unset( $irc->_hellaRate[$id] );
$this->_setupRateTimers();
$this->parseTemplate( $msg, 'rateDel', array( 'time' => $cTime ) );
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
return;
}
}
$this->parseTemplate( $msg, 'error', array( 'errormsg' => 'No rate schedule entry matches time: {time}', 'time' => $cTime ) );
$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
}
}
function botDel( &$irc, &$data, $notice )
{
if ( strlen( $data->subMessage ) > 0 )
{
$sMex = explode( ' ', $data->subMessage );
if ( is_numeric( $sMex[0] ) )
{
foreach( $sMex as $item )
{
$this->del( $msg, $item );
}
}
else
{
$this->del( $msg, $data->subMessage );
}
}
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 );
}
}
function botCancel( &$irc, &$data, $notice )
{
if ( ( $hella = $this->_send( 'cancel' ) ) !== false )
{
$this->parseTemplate( $msg, 'cancel', false );
}
else
{
$this->parseTemplate( $msg, 'error', array( 'errormsg' => $this->_error ) );
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $data, $msg, true );
}
}
function botClear( &$irc, &$data, $notice )
{
if ( ( $hella = $this->_send( 'clear' ) ) !== false )
{
$this->parseTemplate( $msg, 'clear', false );
}
else
{
$this->parseTemplate( $msg, 'error', array( 'errormsg' => $this->_error ) );
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $data, $msg, true );
}
}
/*****************************************************
* Bot Internal Functions
*****************************************************/
function del( &$msg, $query )
{
if ( ( $list = $this->listSearch( $query ) ) !== false )
{
if ( count( $list ) == 0 )
{
$this->parseTemplate( $msg, 'listEmpty', array( 'search' => $query ) );
return false;
}
else if ( count( $list ) == 1 )
{
if ( $this->_send( 'dequeue', array( $list[0]['id'] ) ) )
{
$this->_template['listItem'] = '({queuePos}) [{id}:{msgid}] {nzbName}';
$this->parseTemplate( $msg, 'del', array( 'listItem' => $list ) );
}
return true;
}
else
{
$this->_template['listItem'] = '({queuePos}) [{id}:{msgid}] {nzbName}';
$tmp['listItem'] = $list;
$tmp['search'] = $query;
$this->_template['listShort'] = 'Too many matches found for: {search}: {listItem}';
$this->parseTemplate( $msg, 'listShort', $tmp );
return false;
}
}
}
function unpause( &$irc )
{
if ( $this->_send( 'continue' ) !== false )
{
$irc->unregisterTimeid( $irc->_hellaPauseID );
unset( $irc->_hellaPauseID );
}
}
/**
* Search through the list
*
* @var string $search - Search phrase
* @return list of items
* @access public
*/
function listSearch( $search )
{
global $irc;
$vars = array();
$num = array( 'w' => 604800, 'd' => 86400, 'h' => 3600, 'm' => 60, 's' => 1 );
if ( strlen( $search ) > 1 )
{
foreach( $this->_def['regex']['listFlags'] as $name => $regex )
{
if ( is_array( $regex ) )
{
foreach( $regex as $reg )
{
if ( preg_match( $reg, $search, $match ) )
{
$flag[$name] = $match;
$search = str_replace( $match[0], '', $search );
break;
}
}
}
else
{
if ( preg_match( $regex, $search, $match ) )
{
$flag[$name] = $match;
$search = str_replace( $match[0], '', $search );
}
}
}
}
if ( ( $hella = $this->_send( 'status' ) ) !== false )
{
$limit = ( isset( $flag['limit'] ) )? $flag['limit'][1]:$this->_config['list']['positionRange'];
if ( isset( $flag['top'] ) )
{
$start = 0;
}
else if ( isset( $flag['end'] ) )
{
$start = count( $hella['queued'] ) - $this->_config['list']['positionRange'];
$start = ( $start > 0 )? $start:0;
}
else if ( isset( $flag['pos'] ) )
{
$start = $flag['pos'][1] - 1 - floor( $this->_config['list']['positionRange'] / 2 );
if ( $start + $this->_config['list']['positionRange'] > count( $hella['queued'] ) )
$start = count( $hella['queued'] ) - $this->_config['list']['positionRange'];
$start = ( $start > 0 )? $start:0;
}
else
{
$start = 0;
$limit = ( isset( $flag['limit'] ) )? $flag['limit'][1]:9999;
}
for( $i = $start; $i < count( $hella['queued'] ); $i++ )
{
if ( $i - $start < $limit )
{
$succ = true;
$item = $hella['queued'][$i];
$item['queuePos'] = $i+1;
$item['nzbName'] = trim( str_replace( '_', ' ', $item['nzbName'] ) );
if ( preg_match( '/^\([^\)]+\) (.+)/i', $item['nzbName'], $m ) )
{
$item['nzbName'] = $m[1];
}
if ( $item['msgid'] > 0 )
{
if ( isset( $irc->_nzbHistory[$item['msgid']] ) )
{
$iHistory = $irc->_nzbHistory[$item['msgid']];
}
}
// check for user
if ( ( isset( $flag['user'] ) ) && ( isset( $iHistory ) ) )
{
if ( $flag['user'][1] != $iHistory['data']->nick )
{
$succ = false;
}
}
if ( isset( $iHistory ) )
{
if ( $item['msgid'] > 0 )
{
$iHistory['report'] = $irc->_modules['nzb']->getReport( $item['msgid'] );
$age = $irc->_modules['func']->duration( time() - $iHistory['report']['report:reported'] );
$item['listItemInfo'][] = array(
'user' => $iHistory['data']->nick.', ',
'category' => ', '.$iHistory['report']['report:category'],
'queued' => $irc->_modules['func']->nicedate( $iHistory['queued'] ).', ',
'size' => $irc->_modules['func']->humanSize( $iHistory['report']['report:size']['_content'] ),
'age' => ', '.trim( $age )
);
}
}
else if ( $item['msgid'] > 0 )
{
if ( ( $iHistory = $irc->_modules['nzb']->getReport( $item['msgid'] ) ) !== false )
{
$age = $irc->_modules['func']->duration( time() - $iHistory['report:reported'] );
$item['listItemInfo'][] = array(
'category' => ', '.$iHistory['report:category'],
'size' => $irc->_modules['func']->humanSize( $iHistory['report:size']['_content'] ),
'age' => ', '.trim( $age )
);
}
}
else
{
$item['listItemInfo'][] = array(
'size' => $item['total_mb'] );
}
if ( strlen( $search ) > 1 )
{
if ( is_numeric( $search ) )
{
if ( $search == $item['id'] || $search == $item['msgid'] )
{
$vars = array( $item );
return $vars;
}
}
if (substr($search, 0, 1) == '/') {
$regex = '.*'.str_replace(' ', '.*', $search ).'.*';
} else {
$regex = '/.*'.str_replace(' ', '.*', $search ).'.*/i';
}
if ( !preg_match( $regex, $item['nzbName'] ) )
{
$succ = false;
}
}
if ( $succ )
{
$vars[] = $item;
}
unset( $succ, $item, $iHistory, $age, $time, $matches );
}
}
return $vars;
}
else
{
return false;
}
}
function getQueueSize( $queue = false )
{
global $irc;
$tsize = 0;
if ( $queue === false )
{
if ( ( $hella = $this->_send( 'status' ) ) !== false )
{
$queue = $hella['queued'];
}
}
foreach( $queue as $item )
{
if ( isset( $item['total_mb'] ) )
{
$tsize += str_replace( ',', '', $item['total_mb'] );
}
else
{
$rep = $irc->_modules['nzb']->getReport( $item['msgid'] );
$tsize += ( $rep['report:size']['_content'] / (1024*1024) ); // convert from byte to mb
}
}
return $tsize;
}
/*****************************************************
* Queue moving malarky
*****************************************************/
function moveItem( $id, $pos, $tdata )
{
global $irc;
$irc->modDebug( 'hella', 'Attempting to move item: '.$id.' position: '.$pos, __FILE__, __LINE__ );
// cant find the item, start a timer (for 30 secs to check if it is in the list)
$item = array(
'timerID' => $irc->registerTimeHandler( 30000, $this, 'moveTimer' ),
'id' => $id,
'pos' => $pos,
'data' => $tdata,
'time' => time()
);
$irc->_hellaMoveID[$id] = $item;
$this->moveTimer( $irc );
}
function moveTimer( &$irc )
{
$mList = array( 'last', 'next', 'force' );
foreach( $irc->_hellaMoveID as $id => $item )
{
$list = $this->listSearch( $id );
if ( count( $list ) == 1 )
{
$litem = $list[0];
// if pos = 0 force, -1 next, -2 last
if ( $item['pos'] <= 0 )
{
if ( $this->_send( $mList[$item['pos']+2], array( $litem['id'] ) ) !== false )
{
unset( $irc->_hellaMoveID[$id] );
$irc->unregisterTimeid( $item['timerID'] );
$irc->modDebug( 'hella', 'Moved item: '.$id.' to position: '.$mList[$item['pos']+2], __FILE__, __LINE__ );
if ( $irc->isWorker == false )
{
$vars['downloading'][] = array(
'id' => $litem['id'],
'msgid' => $litem['msgid'],
'nzbName' => $litem['nzbName'] );
$this->parseTemplate( $msg, $mList[$item['pos']+2], $vars );
$irc->_modules['func']->reply( $irc, $item['data'], $msg, $item['data']->notice );
}
}
else
{
$irc->modDebug( 'hella', $this->_error, __FILE__, __LINE__ );
}
}
else
{
if ( $this->_send( 'move', array( $item['id'], $item['pos'] ) ) !== false )
{
unset( $irc->_hellaMoveID[$id] );
$irc->unregisterTimeid( $item['timerID'] );
$irc->modDebug( 'hella', 'Moved item: '.$id.' to position: '.$item['pos'].' in queue', __FILE__, __LINE__ );
if ( $irc->isWorker == false )
{
$vars['downloading'][] = array(
'id' => $litem['id'],
'msgid' => $litem['msgid'],
'nzbName' => $litem['nzbName'] );
$vars['position'] = $item['pos'];
$this->parseTemplate( $msg, 'move', $vars );
$irc->_modules['func']->reply( $irc, $item['data'], $msg, $item['data']->notice );
}
}
}
}
if ( $item['time'] + $this->_config['moveTimerMax'] * 3600 < time() )
{
$irc->unregisterTimeid( $item['timerID'] );
unset( $irc->_hellaMoveID[$id] );
}
}
}
/*****************************************************
* Hellanzb Communcation functions
*****************************************************/
function _connect()
{
global $irc;
$irc->_hellaCli = new XML_RPC_Client( '/', $this->_config['xmlrpc']['hostname'], $this->_config['xmlrpc']['port'] );
$irc->_hellaCli->setCredentials( 'hellanzb', $this->_config['xmlrpc']['password'] );
$irc->modDebug( 'hella', sprintf( 'Connected to XML-RPC on '.$this->_config['xmlrpc']['hostname'] ), __FILE__, __LINE__ );
}
/**
* Send a Message
*
* @var string $msg - Message to send
* @var array $params - Values to send
* @var bool $xml - the $params var is allready set as XML_RPC values
* @return response
* @access private
*/
function _send( $msg, $params = false, $xml = false )
{
global $irc;
if ( $params !== false )
{
if ( !$xml )
{
foreach( $params as $prm )
{
$opm[] = XML_RPC_encode( $prm );
}
}
else
{
$opm = $params;
}
$xmlmsg = new XML_RPC_Message( $msg, $opm );
}
else
{
$xmlmsg = new XML_RPC_Message( $msg );
}
$resp = $irc->_hellaCli->send( $xmlmsg );
// check communication error
if ( !$resp )
{
$this->_error = sprintf( 'XML-RPC Communcation Error: [%d] %s', $irc->_hellaCli->errno, $irc->_hellaCli->errstr );
$irc->modDebug( 'hella', $this->_error, __FILE__, __LINE__ );
return false;
}
if ( $resp->faultCode() )
{
$xmlmsg->createPayload();
$this->_error = sprintf( 'Problem with data (%s) sent: [%d] %s', $xmlmsg->payload, $resp->faultCode(), $resp->faultString() );
$irc->modDebug( 'hella', $this->_error, __FILE__, __LINE__ );
return false;
}
else
{
$val = $resp->value();
/*
$tmp = var_export( $val, true );
$fp = fopen( 'hellatmp.txt', 'w' );
fwrite( $fp, $tmp );
fclose( $fp );
*/
return XML_RPC_decode( $val );
}
}
/*****************************************************
* Hellanzb Communcation functions
*****************************************************/
function _setupSetupTimers( &$irc )
{
$irc->unregisterTimeid( $irc->_hellaSSTimer );
unset( $irc->_hellaSSTimer );
$irc->_modules['store']->manualUpdate( '_hellaRate' );
if ( isset( $irc->_hellaRate ) )
{
foreach( $irc->_hellaRate as $id => $rate )
{
unset( $irc->_hellaRate[$id]['timer'], $irc->_hellaRate[$id]['initTimer'] );
}
}
$this->_setupRateTimers();
}
function _setupRateTimers()
{
global $irc;
$irc->_modules['store']->manualUpdate( '_hellaRate' );
if ( isset( $irc->_hellaRate ) )
{
foreach( $irc->_hellaRate as $id => $rate )
{
$nTime = strtotime( date('Y/m/d ').$rate['time'] );
$nTime = $nTime - time();
if ( $nTime < 5 )
$nTime += 86400;
$irc->_hellaRate[$id]['initTimer'] = $irc->registerTimeHandler( $nTime * 1000, $this, '_hellaInitialRate', array( 'id' => $id ) );
$irc->modDebug( 'hella', 'Registered initial rate time handler: '.$rate['time'].', in '.$irc->_modules['func']->duration($nTime).' rate: '.$rate['rate'], __FILE__, __LINE__ );
}
$irc->_modules['store']->manualUpdate( '_hellaRate', true );
}
}
function _unsetRateTimers()
{
global $irc;
$irc->_modules['store']->manualUpdate( '_hellaRate' );
if ( isset( $irc->_hellaRate ) )
{
foreach( $irc->_hellaRate as $id => $rate )
{
if ( isset( $rate['initTimer'] ) )
{
$irc->unregisterTimeid( $rate['initTimer'] );
$irc->modDebug( 'hella', 'Unregistered initial time handler for: '.$rate['time'].', rate: '.$rate['rate'], __FILE__, __LINE__ );
unset( $irc->_hellaRate[$id]['initTimer'] );
}
if ( isset( $rate['timer'] ) )
{
$irc->unregisterTimeid( $rate['timer'] );
$irc->modDebug( 'hella', 'Unregistered regular time handler for: '.$rate['time'].', rate: '.$rate['rate'], __FILE__, __LINE__ );
unset( $irc->_hellaRate[$id]['timer'] );
}
}
$irc->_modules['store']->manualUpdate( '_hellaRate', true );
}
}
function _hellaInitialRate( &$irc, $vars )
{
$rID = $vars['id'];
$irc->_modules['store']->manualUpdate( '_hellaRate' );
$irc->unregisterTimeid( $irc->_hellaRate[$rID]['initTimer'] );
unset( $irc->_hellaRate[$rID]['initTimer'] );
$irc->_hellaRate[$rID]['timer'] = $irc->registerTimeHandler( 86400000, $this, '_hellaRateTrigger', $vars ); // 1 day in ms
$irc->modDebug( 'hella', 'Registered regular rate schedule for time : '.$irc->_hellaRate[$rID]['time'].', rate: '.$irc->_hellaRate[$rID]['rate'], __FILE__, __LINE__ );
$irc->_modules['store']->manualUpdate( '_hellaRate', true );
$this->_hellaRateTrigger( $irc, $vars );
}
function _hellaRateTrigger( &$irc, $vars )
{
$rID = $vars['id'];
if ( $this->_send( 'maxrate', array( $irc->_hellaRate[$rID]['rate'] ) ) !== false )
{
$irc->modDebug( 'hella', 'Rate scheduler triggered, set rate to: '.$irc->_hellaRate[$rID]['rate'].' kb/s at '.$irc->_hellaRate[$rID]['time'], __FILE__, __LINE__ );
$this->parseTemplate( $msg, 'newrate', array( 'maxrate' => $irc->_hellaRate[$rID]['rate'] ) );
}
else
{
$this->parseTemplate( $msg, 'error', array( 'errormsg' => $this->_error ) );
}
if ( isset( $msg ) )
{
$irc->_modules['func']->reply( $irc, $irc->_hellaRate[$rID]['data'], $msg, $irc->_hellaRate[$rID]['data']->notice );
}
}
/**
* Get the current entry in the startTime split
*
* @param string $name - Variable name in startTime config array
* @param bool $posOnly - Only return the position
* @return array $tStart, $tStop - The starting and stopping positions of the autotvInfo array
*/
function _timerSplit( )
{
global $irc;
$cMin = strtotime( '1970/01/01 '.date('H:i:s') );
foreach( $irc->_hellaRate as $id => $rate )
{
$cTime = strtotime( '1970/01/01 '.$rate['time'] );
if ( ( $cMin >= $cTime ) &&
( $cMin < $cTime + 120 ) )
{
return $id;
}
}
return false;
}
}