Location: PHPKode > projects > Nzbirc > nzbirc-1.4/modules/autotv.php
<?php

/**************************************************
 * NZBirc v1
 * Copyright (c) 2006 Harry Bragg
 * tiberious.org
 * Module: autotv
 **************************************************
 *
 * 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_autotv extends Net_SmartIRC_module_base
{

	// default module variable
	var $name = 'autotv';
	var $version = 'v0.6';
	var $description = 'automatic tv downloading';
	
	/**
	 * 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 int checkTime         - When to start checking for a new episode (in hours from 00:00 on the day of airing)
	 * @var int hourlyCheckLength - How long to check for episodes every hour (in days)
	 * @var int dailyCheckLength  - How long to check for episodes every day (in days)
	 * @var int tvrageCheckTime   - How often to check tvrage for new episodes (in hours)
	 * @var array startTime
	 * @var     array hourCheck   - List of times to check for episodes hourly (minutes of the hour) [splits the search evenly between the times]
	 * @var     array dayCheck    - List of times to check for episodes daily (mintues of the hour) [splits the search evenly between the times]
	 * @var     array tvrageCheck - List of times to perform the tvrage check (minutes of the hour) [splits the search evenly between the times]
	 * @var string defaultFlags   - The default flags for tv shows (see module:ed for list of flags)
	 * @var int nextEpisode       - Number of days to check in the future for new episodes
	 * @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 historyLength     - How long to keep episodes in the history
	 * @var int updateShowsCheck  - How many shows to check for when using the update command
	 * @var bool useTvNzb         - Use the tvnzb module to look and download tv episodes
	 * ENDCONFIG
	 */
	var $_config = array(
		'publicCommand' => array( '^autotv', '^!autotv' ),
		'privateCommand' => array( '^@autotv' ),
		'checkTime' => 20,
		'hourlyCheckLength' => 4,
		'dailyCheckLength' => 21,
		'tvrageCheckTime' => 12,
		'startTime' => array(
			'hourCheck' => array( 06, 16, 26, 36, 46, 56 ),
			'dayCheck' => array( 03, 13, 23, 33, 43, 53 ),
			'tvrageCheck' => array( 00, 10, 20, 30, 40, 50 )
			),
		'defaultFlags' => 'any',
		'nextEpisode' => 6,
		'list' => array(
			'compactLimit' => 6
			),
		'historyLength' => 14,
		'updateShowsCheck' => 6,
		'useTvNzb' => false
		);
		
	var $_def = array(
		'regex' => array(
			'flags' => '/(.+)\sf(?:lags?)?:([a-z0-9,.\s\&\(\)\~\|\-\+\/]+)/i',
			'getOptionSplit' => '/^(.+) (\S+)$/i',
			'getTimeSecs' => '/(\d{2}):(\d{2})(a|p)m/i'
			),
		'options' => array(
			'name' => 'Main name of the show, as listed on tvrage.com or newzbin.com',
			'alias' => 'An alias for easier access to the show',
			'alternatives' => 'List of alternative names found on newzbin.com',
			'tvrageID' => 'The id of the show on tvrage',
			'tvrageIDonly' => 'Do not use episode numbers to check for new episodes, use tvrage urls',
			'priority' => 'Where to place the item in the queue when downloaded (none/next/force)',
			'checkTime' => 'When to start checking for a new episode (in hours from 00:00 on the day of airing)',
			'hourlyCheckLength' => 'How long to check for episodes every hour (in days)',
			'dailyCheckLength' => 'How long to check for episodes every day (in days)',
			'flags' => 'List of flags specifying the quality and codec information to download (the first item is most important), see http://www.tiberious.org/wiki/index.php/Nzbirc/v1/flags',
			'airtime' => 'When a show airs (in a standard time format)',
			'airday' => 'Which day the show airs on',
			'airReminder' => 'Display an Airing reminder (When the program airs) [Note: This does __not__ take into account for time zones]'
			),
		'date' => array(
			'history' => array(
				'time' => 'h:ia'
				)
			)			
		);
	
	var $_template = array(
		'showExists' => 'The show {show} [{query}] has already been added, use **{trigger} edit {show}** to change options',
		'showNotExist' => 'No show found with name matching: {query}',
		'showAdded' => 'Added **{show}** to the autodownloader, upcoming episodes: {newEpisodes}',
		'newEpisodes' => '{series}x{episode} - {title} [{airdate}]',
		'showDeleted' => 'Deleted **{show}** from the autodownloader',
		'toManyMatch' => 'Unable to find a single match for {query}, possible shows: {listShow}',
		'updateYesterday' => 'Updating yesterdays shows: {shows}',
		'listEmpty' => 'No items found{search}{from}{to}',
		'listShort' => '{listItemShort}',
		'listItem' => '**{show}**: f:{flags} | {episodeList}',
		'listItemShort' => '**{show}**: {episodeListShort}',
		'episodeListShort' => '[{series}x{episode} {airdate}]',
		'episodeList' => '{series}x{episode} [air:{airdate}{lastCheck}{flagQueueBridge}]',
		'flagQueueBridge' => '{flagQueue}', //change me to ' ({flagQueue})' when using it [see botList]
		//'flagQueue' => '{flag}{nzbid}{queued}{downloaded}',
		'flagQueue' => '{flag}{nzbid}',
		'error' => '**Error:** {errormsg}',
		'avVar' => 'Available variables: {varList}',
		'varDetails' => '{type} **{name}** = {value} - {description}',
		'varSet' => 'Variable __{pwd}__: set to: {newVar}',
		'varAdd' => '{newVar} has been added to variable: __{pwd}__',
		'varDel' => '{oldVar} has been deleted from variable: __{pwd}__',
		'history' => '[**{date}**] {nzbHistory}',
		'nzbHistory' => '({time}) {flag}|{id}: {title}',		
		'help' => '{command} - {description}',
		'helpList' => array(
			'Commands available for autotv: {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'
			),
		'add' => array(
			'command' => '{trigger} add show [f:flags]',
			'description' => 'Add the __show__ to the auto download list, when new episodes for the show air and get posted on newzbin, they are automatically downloaded, __flags__ specifies the quality of tv you wish to download',
			'longDescription' => array(
				'Add the __show__ to the auto download list, when new episodes for the show air and get posted on newzbin, they are automatically downloaded',
				'__flags__, define the quality of files to be downloaded, a list of flags can be found: http://www.tiberious.org/wiki/index.php/Nzbirc/v1/flags',
				'The order of the flags define their importance (with the first being the most important), and the auto downloader will always attempt to dowload the best quality version',
				'for additional show settings, use the edit command'
				)
			),
		'del' => array(
			'command' => '{trigger} del show',
			'description' => 'Delete a __show__ from the auto downloader list',
			'longDescription' => 'Delete a __show__ from the auto downloader list'
			),
		'list' => array(
			'command' => '{trigger} list [show] [date/duration]',
			'description' => 'List information about a __show__, or all shows, or limit the results to a particular date or time period',
			'longDescription' => array(
				'List information about a __show__, is no __show__ is specified, information about all the shows are shown',
				'You can limit the results to a particual date, or period using the __date__/__duration__ suffix',
				'Almost all date formats are accepted, and date difference (eg: 2days) also work. Date periods can be defined by using <date1> to <date2>'
				)
			),
		'edit' => array(
			'command' => '{trigger} edit show [option] [=/+/- value]',
			'description' => 'View or change a __show__s options, if __=__, __+__, or __-__ and a __value__ are specified, the option is modified',
			'longDescription' => array(
				'View or change a __show__s options, if __=__, __+__, or __-__ and a __value__ are specified, the option is modified',
				'This works the same way as the config module'
				)
			),
		'update' => array(
			'command' => '{trigger} update show',
			'description' => 'Perform a manual update on a particular __show__, this will check for new episodes from tvrage.com and newzbin.com',
			'longDescription' => 'Perform a manual update on a particular __show__, this will check for new episodes from tvrage.com and newzbin.com'
			),
		'history' => array(
			'command' => '{trigger} history times',
			'description' => 'Return the nzb\'s downloaded using the auto downloader on the specified __time__',
			'longDescription' => array(
				'Return the nzb\'s downloaded using the auto downloader on the specified __time__',
				'__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/Nzbirc/v1/times for more information'
				)
			)
		);
			
	function _registerCommands()
	{
	 	global $irc;
	 	
		$this->_setHandler( '^add', $this, 'botAdd' );
		$this->_setHandler( '^del', $this, 'botDel' );
		$this->_setHandler( '^list', $this, 'botList' );
		$this->_setHandler( '^update', $this, 'botUpdate' );
		$this->_setHandler( '^edit (.+) (\S+) (=|\+|-)\s?(.+)$', $this, 'botSet' );
		$this->_setHandler( '^edit ([^=\+\-]+)?$', $this, 'botGet' );
		$this->_setHandler( '^history', $this, 'botHistory' );
		
		//help
		$this->_setHandler( '^help', $this, 'botHelp' );
		$this->_setHandler( '^commands', $this, 'botCommands' );
		
		$irc->_modules['store']->addVariable( '_autotvInfo' );
		
		if ( ( ( $irc->config->useWorker == true ) &&
			   ( $irc->isWorker == true ) ) ||
			 ( $irc->config->useWorker == false ) )
		{
			$this->_setupTimers();
		}
		
		// fix old show flags
		$this->_checkShowFlags();
	}
	
	function _customClose()
	{
		global $irc;
		
		if ( is_array( $irc->_autotvTimers ) )
		{
			foreach( $irc->_autotvTimers as $id )
			{
				$irc->unregisterTimeid( $id );
			}
		}
		
		if ( is_array( $irc->_autotvSTimers ) )
		{
			foreach( $irc->_autotvSTimers as $t )
			{
				if ( is_array( $t ) )
				{
					foreach( $t as $s )
					{
						$irc->unregisterTimeid( $s );
					}
				}
			}
		}
	}
	
	
	/*****************************************************
	 * Bot functions
	 *****************************************************/	
	
	function botAdd( &$irc, &$data, $notice )
	{
		// split up the query string
		if ( preg_match( $this->_def['regex']['flags'], $data->subMessage, $flagSplit ) )
		{
			$flags = $flagSplit[2];
			$query = $flagSplit[1];
		}
		else
		{
			$flags = '';
			$query = $data->subMessage;
		}
		
		// check if the show has allready been added
		if ( ( $tvrID = $irc->_modules['tvrage']->findShow( $query ) ) !== false )
		{
		
			$irc->_modules['store']->manualUpdate( '_autotvInfo' );
			
			if ( isset( $irc->_autotvInfo['_'.$tvrID] ) )
			{
				// already exists, lets stop
				$vars = array(
					'show' => $irc->_autotvInfo['_'.$tvrID]['name'],
					'query' => $query,
					'trigger' => $data->trigger
				);					
				$this->parseTemplate( $msg, 'showExists', $vars );
			}
			else
			{
				if ($this->addShow( $query, $flags, $data ) !== false)
				{
					$show = $irc->_autotvInfo['_'.$tvrID];
					$vars = array(
						'show' => $show['name']
					);
					if ( is_array( $show['episodes'] ) )
					{
						foreach( $show['episodes'] as $tvredID => $ep )
						{
							$vars['newEpisodes'][] = array(
								'series' => $ep['series'],
								'episode' => sprintf( '%02d', $ep['episode'] ),
								'title' => $ep['title'],
								'airdate' => $irc->_modules['func']->snicedate( $ep['airdate'] )
								);
						}
					}
									
					$this->parseTemplate( $msg, 'showAdded', $vars );
				}
				else
				{
					$this->parseTemplate( $msg, 'error', 'Adding show '.$query.' failed');
				}
			}
		}
		else
		{
			$this->parseTemplate( $msg, 'showNotExist', array( 'query' => $query ) );
		}
		
		if ( isset( $msg ) )
		{
			$irc->_modules['func']->reply( $irc, $data, $msg, $notice );			
		}
	}
	
	function botDel( &$irc, &$data, $notice )
	{
		$shows = $this->_getShow( $data->subMessage );
		
		if ( count( $shows ) == 1 )
		{
			$name = $irc->_autotvInfo['_'.$shows[0]]['name'];
			// delete show
			unset( $irc->_autotvInfo['_'.$shows[0]] );
			$irc->_modules['store']->manualUpdate( '_autotvInfo', true );
			
			$this->parseTemplate( $msg, 'showDeleted', array( 'show' => $name ) );
		}
		else if ( count( $shows ) > 1 )
		{
			$vars = array(
				'query' => $data->subMessage
				);
			foreach( $shows as $tvrID )
			{
				$vars['listShow'][] = $irc->_autotvInfo['_'.$tvrID]['name'];
			}
			$this->parseTemplate( $msg, 'toManyMatch', $vars );
		}
		else
		{
			$this->parseTemplate( $msg, 'showNotExist', array( 'query' => $query ) );			
		}
		if ( isset( $msg ) )
		{
			$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
		}
	}

	function botList( &$irc, &$data, $notice )
	{
		// check for a time/date, get and strip
		list( $date, $date2, $query ) = $irc->_modules['func']->dateDurationParse( $data->subMessage );
		
		if ( $date > 0 )
			$date = $irc->_modules['func']->dateToDay( $date );
		if ( $date2 > 0 )
			$date2 = $irc->_modules['func']->dateToDay( $date2 );
		
		$list = $this->listShows( $query, $date, $date2 );

		if ( count( $list ) == 0 )
		{
			if ( strlen( $query ) > 0 )
			{
				$vars['search'] = ' for: '.$query;
			}
			if ( $date > 0 )
			{
				$vars['from'] = ' from: {fromDate}';
				$vars['fromDate'] = $irc->_modules['func']->snicedate( $date );
			}
			if ( $date2 > 0 )
			{
				$vars['to'] = ' to: {toDate}';
				$vars['toDate'] = $irc->_modules['func']->snicedate( $date2 );
			}
			$this->parseTemplate( $msg, 'listEmpty', $vars );
		}
		else if ( count( $list ) > $this->_config['list']['compactLimit'] )
		{
			foreach( $list as $tvrID )
			{
				$tmp = $irc->_autotvInfo['_'.$tvrID];
				$tmp['show'] = $tmp['name'];
				if ( is_array( $tmp['episodes'] ) )
				{
					if ( count( $tmp['episodes'] ) == 0 )
					{
						$tmp['episodeListShort'] = 'None';
					}
					foreach( $tmp['episodes'] as $tvrepID => $ep )
					{
						$tEp = $ep;
						$tEp['episode'] = sprintf( '%02d', $tEp['episode'] );
						$tEp['airdate'] = $irc->_modules['func']->snicedur( $tEp['airdate'] );
						
						if ( !$tEp['beenQueued'] )
						{
							$tEp['airdate'] = '__'.$tEp['airdate'].'__';
						}
						$tmp['episodeListShort'][] = $tEp;
					}
				}
				else
				{
					$tmp['episodeListShort'] = 'None';
				}
				
				$vars['listItemShort'][] = $tmp;
			}
			$this->parseTemplate( $msg, 'listShort', $vars );
		}
		else
		{
			foreach( $list as $tvrID )
			{
				$tmp = $irc->_autotvInfo['_'.$tvrID];
				$tmp['show'] = $tmp['name'];
				if ( is_array( $tmp['episodes'] ) )
				{
					if ( count( $tmp['episodes'] ) == 0 )
					{
						$tmp['episodeList'] = 'No Episodes';
					}
					foreach( $tmp['episodes'] as $tvrepID => $ep )
					{
						$tEp = $ep;
						$tEp['episode'] = sprintf( '%02d', $tEp['episode'] );
						$tEp['airdate'] = $irc->_modules['func']->snicedate( $tEp['airdate'] );
						$tEp['lastCheck'] = ( $tEp['lastCheck'] > 0 )? ', chk:'.$irc->_modules['func']->nicedur( $tEp['lastCheck'] ):'';						
						
						if ( !$tEp['beenQueued'] )
						{
							$tEp['airdate'] = '__'.$tEp['airdate'].'__';
						}
						
						foreach( $tEp['flags'] as $flag => $fOpts )
						{							
							if ( isset( $fOpts['nzbid'] ) )
							{
								$tFlag = array(
									'flag' => $fOpts['name'],
									'nzbid' => ':'.$fOpts['nzbid']
									);
								if ( isset( $fOpts['queued'] ) )
								{
									$tFlag['queued'] = ':q'.$irc->_modules['func']->snicedate( $fOpts['queued'] );
								}
								if ( isset( $fOpts['downloaded'] ) )
								{
									$tFlag['downloaded'] = ':d'.$irc->_modules['func']->duration( $fOpts['downloaded'], $fOpts['queued'] );
								}
								$tEp['flagQueue'][] = $tFlag;
								$tEp['flagQueueBridge'] = ' | {flagQueue}';
							}
						}				
						$tmp['episodeList'][] = $tEp;
					}
				}
				else
				{
					$tmp['episodeList'] = 'No Episodes';
				}
				$this->parseTemplate( $msg, 'listItem', $tmp );
			}
		}
		
		if ( isset( $msg ) )
		{
			$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
		}
			
	}
	
	function botUpdate( &$irc, &$data, $notice )
	{
		if ( strlen( $data->subMessage ) == 0 )
		{
			list( $date, $date2, $query ) = $irc->_modules['func']->dateDurationParse( 'yesterday' );
			
			$shows = $this->listShows( $query, $date, $date2 );
			
			$irc->modDebug( 'autotv', sprintf( 'Updating yesterdays shows: %s', implode(',', $shows ) ), __FILE__, __LINE__ );
			
			$vars = array( 'shows' => array() );
			foreach( $shows as $sCheck )
			{
				$vars['shows'][] = $irc->_autotvInfo['_'.$sCheck]['name'];
			}
			
			$this->parseTemplate( $msg, 'updateYesterday', $vars );
			
			foreach ( $shows as $sCheck )
			{
				$this->_checkShow( $sCheck );
				$this->_updateShow( $sCheck );
				$this->_updateShow( $sCheck, true );
				$irc->_modules['store']->manualUpdate( '_autotvInfo', true );
			}
		}
		else
		{
			$shows = $this->_getShow( $data->subMessage );
			
			if ( count( $shows ) <= $this->_config['updateShowsCheck'] )
			{
				foreach ( $shows as $sCheck )
				{
					$this->_checkShow( $sCheck );
					$this->_updateShow( $sCheck );
					$this->_updateShow( $sCheck, true );
					$irc->_modules['store']->manualUpdate( '_autotvInfo', true );
				}
			}
			else if ( count( $shows ) > $this->_config['updateShowsCheck'] )
			{
				$vars = array(
					'query' => $data->subMessage
					);
				foreach( $shows as $tvrID )
				{
					$vars['listShow'][] = $irc->_autotvInfo['_'.$tvrID]['name'];					
				}
				$this->parseTemplate( $msg, 'toManyMatch', $vars );
			}
			else
			{
				$this->parseTemplate( $msg, 'showNotExist', array( 'query' => $data->subMessage ) );		
			}
		}
		if ( isset( $msg ) )
		{
			$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
		}
	}
	
	function botGet( &$irc, &$data, $notice )
	{
		// get variable
		if ( preg_match( $this->_def['regex']['getOptionSplit'], $data->trig[1], $split ) )
		{
			if ( isset( $this->_def['options'][$split[2]] ) )
			{
				$show = $split[1];
				$pos = array( $split[2] );
			}
			else
			{
				$show = $data->trig[1];
				$pos = array();
			}
		}
		else
		{
			$show = $data->trig[1];
			$pos = array();
		}
		
		// check show
		$shows = $this->_getShow( $show );
		
		if ( count( $shows ) == 1 )
		{
			// found a show, hooray
			
			if ( ( $val = $irc->_modules['config']->_gTravArray( $this->_def['options'], $pos ) ) !== 'fakeFalse' )
			{
				if ( is_array( $val ) )
				{
					// list options
					foreach( $val as $id => $item )
					{
						$vars['varList'][] = $id;
					}					
					$this->parseTemplate( $msg, 'avVar', $vars );
				}
				else
				{
					$vars['name'] = $pos[count($pos)-1];
					$rVal = $irc->_autotvInfo['_'.$shows[0]][$vars['name']];
					$vars['description'] = $val;
					// display variable
					if ( $vars['name'] == 'flags' )
					{
						$vars['value'] = implode( ',', $rVal );
						$vars['type'] = 'array';
					}
					else if ( $vars['name'] == 'airtime' )
					{
						$vars['value'] = date( 'h:ia', $rVal );
						$vars['type'] = 'string';
					}
					else if ( is_array( $rVal ) )
					{
						$vars['value'] = 'array( {vals} )';
						$vars['vals'] = $rVal;
						$vars['type'] = 'array';
					}
					else if ( is_bool( $rVal ) )
					{
						$vars['value'] = ( $rVal )? 'true':'false';
						$vars['type'] = 'bool';
					}
					else if ( is_numeric( $rVal ) )
					{
						$vars['type'] = 'int';
						$vars['value'] = $rVal;
					}
					else
					{
						$vars['type'] = 'string';					
						$vars['value'] = $rVal;
					}
					
					$this->parseTemplate( $msg, 'varDetails', $vars );					
				}
			}
			else
			{
				$this->parseTemplate( $msg, 'error', array( 'errormsg' => 'Invalid variable: __{pos}__', 'pos' => implode( '__ > __', $pos ) ) );
			}				
			
		}
		else if ( count( $shows ) > 1 )
		{
			$vars = array(
				'query' => $show
				);
			foreach( $shows as $tvrID )
			{
				$vars['listShow'][] = $irc->_autotvInfo['_'.$tvrID]['name'];					
			}
			$this->parseTemplate( $msg, 'toManyMatch', $vars );
		}
		else
		{
			$this->parseTemplate( $msg, 'showNotExist', array( 'query' => $show ) );			
		}
		
		if ( isset( $msg ) )
		{
			$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
		}		
	}

	function botSet( &$irc, &$data, $notice )
	{
		$show = $data->trig[1];
		$pos = array( $data->trig[2] );
		$setOpt = $data->trig[3];
		$newVal = $data->trig[4];
		
		$pwd = implode( '__ > __', $pos );
				
		// check show
		$shows = $this->_getShow( $show );
		
		if ( count( $shows ) == 1 )
		{
			// found a show, hooray
			$sID = '_'.$shows[0];
			
			if ( ( $val = $irc->_modules['config']->_gTravArray( $this->_def['options'], $pos ) ) !== 'fakeFalse' )
			{
				if ( !is_array( $val ) )
				{
					$name = $pos[count($pos)-1];
					
					$rVal = $irc->_autotvInfo[$sID][$name];
					
					// set variable
					if ( is_array( $rVal ) )
					{
						if ( $setOpt == '=' )
						{
							if ( $name == 'flags' )
							{
								$irc->_autotvInfo[$sID][$name] = explode( ',', $newVal );
	
								$vars = array(
									'pwd' => $pwd,
									'newVar' => $newVal
								);							
								$this->parseTemplate( $msg, 'varSet', $vars );
							}
							else
							{	
								$this->parseTemplate( $msg, 'error', array( 'errormsg' => 'Variable: __{pwd}__ is an array, use the **+** and **-** commands to add or remove items', 'pwd' => $pwd ) );
							}							
						}
						else if ( $setOpt == '+' )
						{
							$irc->_autotvInfo[$sID][$name][] = $newVal;

							$vars = array(
								'pwd' => $pwd,
								'newVar' => $newVal
							);
							$this->parseTemplate( $msg, 'varAdd', $vars );
						}
						elseif ( $setOpt == '-' )
						{
							if ( ( $key = array_search( trim( $newVal ), $rVal ) ) !== false )
							{
								unset( $rVal[$key] );
								$nVal = $irc->_modules['config']->_resortArray( $rVal );
								
								$irc->_autotvInfo[$sID][$name] = $nVal;
								
								$vars = array(
									'pwd' => $pwd,
									'oldVar' => $newVal
								);
								
								$this->parseTemplate( $msg, 'varDel', $vars );	
							}
							else
							{
								$this->parseTemplate( $msg, 'error', array( 'errormsg' => 'Can not delete item: {oldVar}, does not exist in variable: __{pwd}__', 'oldVar' => $newVal, 'pwd' => $pwd ) );
							}						
						}
					}
					else
					{
						$vars = array(
							'pwd' => $pwd,
							'newVar' => $newVal
						);					

						if ( $name == 'airtime' )
						{
							$newVal = strtotime( '1970/01/01 '.$newVal );
							$newVar = date( 'h:ia', $newVal );
						}

						if ( !$fail )
						{
							if ( is_bool( $rVal ) )
							{
								$newVal = ( $newVal == 'true' )? true:false;
							}
							$irc->_autotvInfo[$sID][$name] = $newVal;
	
							$this->parseTemplate( $msg, 'varSet', $vars );
						}
					}
					
					if ( $name == 'flags' )
					{
						$this->_updateFlags( $shows[0] );
					}
				}
				else
				{
					$this->parseTemplate( $msg, 'error', array( 'errormsg' => 'Variable: __{pos}__ is not writeable', 'pos' => implode( '__ > __', $pos ) ) );	
				}
			}
			else
			{
				$this->parseTemplate( $msg, 'error', array( 'errormsg' => 'Invalid variable: __{pos}__', 'pos' => implode( '__ > __', $pos ) ) );
			}				
			
		}
		else if ( count( $shows ) > 1 )
		{
			$vars = array(
				'query' => $show
				);
			foreach( $shows as $tvrID )
			{
				$vars['listShow'][] = $irc->_autotvInfo['_'.$tvrID]['name'];					
			}
			$this->parseTemplate( $msg, 'toManyMatch', $vars );
		}
		else
		{
			$this->parseTemplate( $msg, 'showNotExist', array( 'query' => $show ) );			
		}
		
		if ( isset( $msg ) )
		{
			$irc->_modules['func']->reply( $irc, $data, $msg, $notice );
		}
		$irc->_modules['store']->manualUpdate( '_autotvInfo', true );
	}

	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 botHistory( &$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 );
		
		$nzbs = $this->_getHistory( $date, $date2 );
		
		if ( count( $nzbs ) > 0 ) 
		{
			foreach( $nzbs as $id => $item )
			{
			 	$vars = array(
					'date' => $irc->_modules['func']->snicedate( $id )
				);
			 	
				foreach( $item as $nzb )
				{
				 	$tmp = array(
				 		'time' => date( $this->_def['date']['history']['time'], $nzb['queued'] ),
						'flag' => $nzb['flag'],
				 		'id' => $nzb['id'],
				 		'title' => $nzb['title']
				 	);
					$vars['nzbHistory'][] = $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 );
		}
			
	}
	
	/*****************************************************
	 * General functions
	 *****************************************************/
	
	function addShow( $name, $flags, $data )
	{
		global $irc;
		
		if (($tvrageID = $irc->_modules['tvrage']->findShow( $name )) !== false)
		{
			if (($tvshow = $irc->_modules['tvrage']->getShow( $tvrageID )) !== false)
			{
				$irc->modDebug( 'autotv', 'Added show: '.$tvshow['name'], __FILE__, __LINE__ );
		
				$options = array(
					'name' => $tvshow['name'],
					'alias' => '',
					'alternatives' => array(),
					'tvrageID' => $tvrageID,
					'tvrageIDonly' => false,
					'priority' => 'none',
					'data' => $irc->_modules['func']->getTData( $data ),
					'checkTime' => $this->_config['checkTime'],
					'hourlyCheckLength' => $this->_config['hourlyCheckLength'],
					'dailyCheckLength' => $this->_config['dailyCheckLength'],
					'airtime' => $at,
					'airReminder' => false
					);
				
				if ( strlen( $flags ) == 0 )
				{
					$flags = $this->_config['defaultFlags'];
				}
		
				$fExplode = explode( ',', $flags );
				
				$options['flags'] = $fExplode;
				
				$irc->_autotvInfo['_'.$tvrageID] = $options;
				
				// update
				$this->_checkShow( $tvrageID );
				$irc->_modules['store']->manualUpdate( '_autotvInfo', true );

				return true;
			}
			else
			{
				$irc->modDebug( 'autotv', 'TVrage, getShow failed: '.$tvrageID, __FILE__, __LINE__ );
				return false;
			}
		}
		else
		{
			$irc->modDebug( 'autotv', 'TVrage, findShow failed: '.$name, __FILE__, __LINE__ );
			return false;
		}
		return false;
	}
	
	function _checkShow( $showID )
	{
		global $irc;

		// check current episodes
		$sID = '_'.$showID;

		$tvShow = $irc->_modules['tvrage']->getShow( $showID, true );
		
		$irc->modDebug( 'autotv', 'Updating '.$tvShow['name'].' information from tvrage', __FILE__, __LINE__, SMARTIRC_DEBUG_MODULES );
		
		$nep = $this->_getNextEpisodes( $showID );
		
		if ( is_array( $nep ) )
		{
			foreach( $nep as $epID => $eS )
			{
				if ( ( $tvEp = $irc->_modules['tvrage']->getEpisode( $showID, $epID ) ) !== false )
				{
					$es['series'] = $tvEp['series'];
					$eS['episode'] = $tvEp['sepnum'];
					$eS['title'] = $tvEp['title'];
					$eS['airdate'] = $tvEp['airdate'];
					
					$irc->_autotvInfo[$sID]['episodes'][$epID] = $eS;
					$irc->_modules['store']->manualUpdate( '_autotvInfo', true );
				}
				else
				{
					$irc->modDebug( 'autotv', 'Can not find episode: '. $epID .' for show '.$tvShow['name'].', deleting', __FILE__, __LINE__, SMARTIRC_DEBUG_MODULES );
					unset( $irc->_autotvInfo[$sID]['episodes'][$epID] );
					$irc->_modules['store']->manualUpdate( '_autotvInfo', true );
				}
			}
		}
		
		if ( is_array( $tvShow['Next'] ) )
		{
			if ( ( $eps = $irc->_modules['tvrage']->findEpisodesFromDate( $showID, $tvShow['Next']['date'], $this->_config['nextEpisode'] ) ) === false )
			{
				$eps = array();
			}
		}
		else
		{
			$eps = array();
		}
		if ( ( $oeps = $irc->_modules['tvrage']->findEpisodesFromDate( $showID, $irc->_modules['func']->dateToDay(time() - (3600 * 24 * 2)), $this->_config['nextEpisode'] ) ) === false )
		{
			$oeps = array();
		}
		$eps = array_merge( $eps, $oeps );

		foreach( $eps as $tvRID )
		{
			if ( !isset( $irc->_autotvInfo[$sID]['episodes'][$tvRID] ) )
			{
				$tvEp = $irc->_modules['tvrage']->getEpisode( $showID, $tvRID );
				
				$eS = array(
					'series' => $tvEp['series'],
					'episode' => $tvEp['sepnum'],
					'title' => $tvEp['title'],
					'airdate' => $tvEp['airdate']
				);
				
				foreach( $irc->_autotvInfo[$sID]['flags'] as $flag )
				{
					$eS['flags'][] = array( 
						'name' => $flag,	
						'done' => false
					);
				}
				
				$irc->modDebug( 'autotv', sprintf( 'Added episode: %dx%02d - %s, for show: %s', $eS['series'], $eS['episode'], $eS['title'], $tvShow['name'] ), __FILE__, __LINE__ );
				
				$irc->_autotvInfo[$sID]['episodes'][$tvRID] = $eS;
				$irc->_modules['store']->manualUpdate( '_autotvInfo', true );
			}
		}
	}
	
	function _getNextEpisodes( $showID )
	{
		global $irc;
		
		$irc->_modules['store']->manualUpdate( '_autotvInfo' );
		
		$options = $irc->_autotvInfo['_'.$showID];
		
		if ( !is_array( $options['episodes'] ) )
		{
			return false;
		}
		else
		{
			foreach( $options['episodes'] as $id => $ep )
			{
				if ( count( $ep['flags'] ) == 0 )
				{
					foreach( $irc->_autotvInfo[$sID]['flags'] as $flag )
					{
						$irc->_autotvInfo['_'.$showID]['episodes'][$id]['flags'][] = array( 
							'name' => $flag,
							'done' => false
						);
					}
					$ep = $irc->_autotvInfo['_'.$showID]['episodes'][$id];
				}
				foreach( $ep['flags'] as $flagEp )
				{
					if ( !$flagEp['done'] )
					{
						$out[$id] = $ep;
					}	
				}
			}
		}
		return $out;
	}
	
	function _getShow( $name )
	{
		global $irc;
		
		$out = array();
		$regex = '/.*'.str_replace( ' ', '.*', $name ).'.*/i';
		
		$irc->_modules['store']->manualUpdate( '_autotvInfo' );
		
		if ( is_array( $irc->_autotvInfo ) )
		{
			foreach( $irc->_autotvInfo as $id => $show )
			{
				if ( strlen( $name ) > 0 )
				{
					if ( strtolower( $show['name'] ) == strtolower( $name ) )
					{
						$out = array( $show['tvrageID'] );
						return $out;
					}
					else if ( strtolower( $show['alias'] ) == strtolower( $name ) )
					{
						$out = array( $show['tvrageID'] );
						return $out;
					}
				}
				if ( preg_match( $regex, $show['name'] ) )
				{
					$out[] = $show['tvrageID'];
				}
				else
				{
					if ( is_array( $show['alternatives'] ) )
					{
						foreach( $show['alternatives'] as $altShow )
						{
							if ( preg_match( $regex, $altShow ) )
							{
								$out[] = $show['tvrageID'];
								break;
							}
						}
					}
				}
			}
		}
		return $out;
	}
	
	function listShows( $query = '', $date = 0, $date2 = false )
	{
		global $irc;
		
		$out = array();
		
		$list = $this->_getShow( $query );
		
	 	if ( ( !$date2 ) || ( $date2 <= 0 ) )
	 	{
			if ( $date < 1 )
				$date2 = 17179869184;
			else
				$date2 = $date;
		}
		
		foreach( $list as $tvrID )
		{
			if ( ( $date <= 0  ) &&
				 ( $date2 >= 4294967296 ) )
			{
				$out[] = $tvrID;
				$sort[] = $irc->_autotvInfo['_'.$tvrID]['name'];
			}
			else
			{
				if ( is_array( $irc->_autotvInfo['_'.$tvrID]['episodes'] ) )
				{
					foreach( $irc->_autotvInfo['_'.$tvrID]['episodes'] as $ep )
					{
						if ( ( $ep['airdate'] >= $date ) && ( $ep['airdate'] <= $date2 ) )
						{
							$out[] = $tvrID;
							$sort[] = $irc->_autotvInfo['_'.$tvrID]['name'];
							break 1;
						}
					}
				}
			}
		}
		if ( count( $out ) > 0 )
		{
			$tmp_sort = array_map('strtolower', $sort);
			array_multisort($tmp_sort, SORT_ASC, SORT_STRING, $out);
			unset( $sort, $tmp_sort );
		}
		return $out;
	}
	
	/**
	 * Get the index of a particular flag for a show
	 *
	 * @param array $episode - The episode to search for the flag in
	 * @param string $flagName - The name of the flag 
	 * @return int - The index of the flag
	 * @access private
	 */
	function _getFlagIndex( $episode, $flagName )
	{
		foreach( $episode['flags'] as $k => $val )
		{
			if ( $val['name'] == $flagName )
			{
				return $k;
			}
		}
		return -1;
	}
	
	/**
	 * Update a show
	 *
	 * @param string $showID - Show ID to update
	 * @param boolean $dayCheck - Weather to do the daily check or hourly
	 * @return null
	 * @access private
	 */
	function _updateShow( $showID, $dayCheck = false )
	{
		global $irc;
		
		$sID = '_'.$showID;
				
		if ( isset( $irc->_autotvInfo[$sID] ) )
		{
			// check episodes
			if ( isset( $irc->_autotvInfo[$sID]['episodes'] ) )
			{
				// loop through episodes
				foreach( $irc->_autotvInfo[$sID]['episodes'] as $tvrID => $ep )
				{
					$spF = ( $irc->_autotvInfo[$sID]['tvrageIDonly'] ) ? '^"%s - "':'^"%s - %dx%02d"';
					
					$searchStr = array( sprintf( $spF, $irc->_autotvInfo[$sID]['name'], $ep['series'], $ep['episode'] ) );
					foreach( $irc->_autotvInfo[$sID]['alternatives'] as $alt )
					{
						$searchStr[] = sprintf( $spF, $alt, $ep['series'], $ep['episode'] );
					}
									
					// check if its in the time range
					if ( ( ( $dayCheck ) &&
						   ( ( $ep['airdate'] + $irc->_autotvInfo[$sID]['hourlyCheckLength'] * 86400 <= time() ) &&
						     ( $ep['airdate'] + $irc->_autotvInfo[$sID]['dailyCheckLength'] * 86400 >= time() ) ) ) ||
						 ( ( !$dayCheck ) &&
						   ( ( $ep['airdate'] + $irc->_autotvInfo[$sID]['checkTime'] * 3600 <= time() ) &&
						     ( $ep['airdate'] + $irc->_autotvInfo[$sID]['hourlyCheckLength'] * 86400 >= time() ) ) ) )
					{
						// get a list of flags that have not been downloaded
						$listFlags = array();
						foreach( $irc->_autotvInfo[$sID]['flags'] as $flag )
						{
							if ( ( $fid = $this->_getFlagIndex( $ep, $flag ) ) !== -1 )
							{
								if ( $ep['flags'][$fid]['name'] == $flag )
								{
									if  ( !$ep['flags'][$fid]['done'] )
									{
										$listFlags[] = $flag;
									}
								}
								else
								{
									break;
								}
							}
						}

						if ( count( $listFlags ) > 0 )
						{
							$irc->_autotvInfo[$sID]['episodes'][$tvrID]['lastCheck'] = time();
							
							$irc->modDebug( 'autotv', sprintf( 'Checking: %s - %dx%02d | flags: %s', $irc->_autotvInfo[$sID]['name'], $ep['series'], $ep['episode'], implode( ',', $listFlags ) ), __FILE__, __LINE__, SMARTIRC_DEBUG_MODULES );				
							
							$mod = ( $this->_config['useTvNzb'] )? 'tvnzb':'nzb';
							
							$result = array();
							// loop through the alternatives
							foreach( $searchStr as $sStr )
							{
								if ( $irc->_autotvInfo[$sID]['tvrageIDonly'] )
								{
									$tmp = $irc->_modules['nzb']->idSearch( $sStr, $irc->_autotvInfo[$sID]['tvrageID'], $tvrID, 1, $listFlags );
								}
								else
								{
									$tmp = $irc->_modules[$mod]->search( $sStr, 1, $listFlags );
								}
								$irc->_modules['func']->array_append( $result, $tmp );
							}
							
							// sod it, lets take the first entry
							if ( count( $result ) > 0 )
							{
								$theResult = $result[0];
								
								// use the score to get which flag was successful
								$flagID = count( $listFlags ) - $theResult['score'];
								
								$rFlag = $listFlags[$flagID];
								$fid = $this->_getFlagIndex( $ep, $rFlag );
								
								// unset the lower flags
								for ( $i = $fid; $i < count( $ep['flags'] ); $i++ )
								{
									unset( $irc->_autotvInfo[$sID]['episodes'][$tvrID]['flags'][$i] );
								}
								
								$irc->_autotvInfo[$sID]['episodes'][$tvrID]['flags'][$fid] = array(
									'name' => $rFlag,
									'done' => true,
									'nzbid' => $theResult['report:id'],
									'queued' => time()
								);
								
								$irc->_autotvInfo[$sID]['episodes'][$tvrID]['beenQueued'] = true;
								
								$irc->modDebug( 'autotv', sprintf( 'queued %d:%s, %s', $theResult['report:id'], $theResult['report:title'], $rFlag ), __FILE__, __LINE__ );
								//$irc->_modules['func']->reply( $irc, $irc->_autotvInfo[$sID]['data'], sprintf( 'Fake Download: %d:%s, %s', $theResult['id'], $theResult['title'], $rFlag ) );

								// add to download queue
								// $irc->_modules['nzb']->addID( $theResult['id'], $irc->_autotvInfo[$sID]['data'], $irc->_autotvInfo[$sID]['priority'] );
								$irc->_modules['store']->setVariable( '_nzbWait', array(
										'id' => $theResult['report:id'],
										'data' => $irc->_autotvInfo[$sID]['data'] ),
									$theResult['report:id']
								);
								$irc->_modules['store']->setVariable( '_nzbCache', $theResult, $theResult['report:id'] );
							}
						}
					}
				}
			}
		}
		$irc->_modules['store']->manualUpdate( '_autotvInfo', true );
	}
	
	/**
	 * Update existing episode Flags with new Show Flags 
	 *
	 * @param string $showID - Show's TVRage ID
	 * @return null
	 * @access private
	 */
	function _updateFlags( $showID )
	{
		global $irc;
		$sID = '_'.$showID;
		
		$irc->modDebug( 'autotv', 'Checking flags for showID: '.$sID, __FILE__, __LINE__ );
				
		if ( isset( $irc->_autotvInfo[$sID]['episodes'] ) )
		{
			$flags = $irc->_autotvInfo[$sID]['flags'];
		
			foreach( $irc->_autotvInfo[$sID]['episodes'] as $tvrID => $ep )
			{
				$tFlags = $ep['flags'];
				
				$irc->_autotvInfo[$sID]['episodes'][$tvrID]['flags'] = array();
				
				foreach( $flags as $flag )
				{
					$done = false;
					foreach( $tFlags as $k => $tFV )
					{
						// Backwards compatability code
						if ( !isset( $tFV['name'] ) )
						{
							$tFV['name'] = $k;
						}
						if ( $tFV['name'] == $flag )
						{
							$irc->_autotvInfo[$sID]['episodes'][$tvrID]['flags'][] = $tFV;
							$done = true;
							if ($tFV['done'])
								break(2);
							else
								break;
						}
					}
					if (!$done)
					{
						$irc->_autotvInfo[$sID]['episodes'][$tvrID]['flags'][] = array(
							'name' => $flag,
							'done' => false
						);
					}
				}
			}
		}
	}
	
	/**
	 * Check the shows for old flag type and fix
	 *
	 */
	function _checkShowFlags()
	{
		global $irc;
		
		if ( is_array( $irc->_autotvInfo ) ) 
		{
			foreach( $irc->_autotvInfo as $sID => $show )
			{
				if ( isset( $show['episodes'] ) )
				{
					foreach( $show['episodes'] as $eID => $ep )
					{
						foreach( $ep['flags'] as $k => $flag )
						{
							if ( is_numeric( $k ) )
							{
								return;
							}
							else
							{
								$irc->modDebug( 'autotv', sprintf( 'Fixing tvshow %s to new flag system', $show['name'] ), __FILE__, __LINE__ );
								$this->_updateFlags($show['tvrageID']);
								break(2);
							}
						}
					}	 
				}
			}
		}
		$irc->_modules['store']->manualUpdate('_autotvInfo', true);
	}
	
	/**
	 * 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( '_autotvInfo' );
		
		if ( is_array( $irc->_autotvInfo ) )
		{
			foreach( $irc->_autotvInfo as $tvrID => $show )
			{
				if ( is_array( $show['episodes'] ) )
				{
					foreach( $show['episodes'] as $eTvrID => $ep )
					{
						foreach( $ep['flags'] as $flag => $item )
						{
							if ( $item['done'] == true )
							{
								if ( ( $item['queued'] >= $date ) &&
									 ( $item['queued'] <= $date2 ) )
								{
									if ( isset( $irc->_nzbHistory[$item['nzbid']] ) )
									{
										$out[$item['nzbid']] = $irc->_nzbHistory[$item['nzbid']];
										$out[$item['nzbid']]['flag'] = $item['name'];
									}
									else
									{
										$rep = $irc->_modules['nzb']->getReport( $item['nzbid'] );
										$out[$item['nzbid']] = array(
											'queued' => $item['queued'],
											'id' => $item['nzbid'],
											'title' => $rep['report:title'],
											'flag' => $item['name']
										);
									}
									$downloaded[$item['nzbid']] = $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;
	}
	
	function _checkHistory()
	{
		global $irc;
		
		$irc->_modules['store']->manualUpdate( '_autotvInfo' );

		if ( is_array( $irc->_autotvInfo ) )
		{
			foreach( $irc->_autotvInfo as $tvrID => $show )
			{
				if ( is_array( $show['episodes'] ) )
				{
					foreach( $show['episodes'] as $eTvrID => $ep )
					{
						if ( $ep['airdate'] < time() - ( 3600 * 24 * $this->_config['historyLength'] ) )
						{
							unset( $irc->_autotvInfo[$tvrID]['episodes'][$eTvrID] );
						}
					}
				}
			}
		}
		$irc->_modules['store']->manualUpdate( '_autotvInfo', true );
	}
	
	/*****************************************************
	 * Timers
	 *****************************************************/	
	
	function _setupTimers()
	{
		global $irc;
		
		// hourly check
		foreach( $this->_config['startTime']['hourCheck'] as $i => $cTime )
		{
			$nTime = strtotime( date('Y/m/d H:').$cTime );
			$nTime = $nTime - time();
			if ( $nTime < 5 )
				$nTime += 3600;			
			$irc->_autotvSTimers['hour'][$i] = $irc->registerTimeHandler( $nTime * 1000, $this, '_firstHUS', array( 'id' => $i ) );
			$irc->modDebug( 'autotv', 'Registered inital hour check timer: '.$cTime.', in '.$irc->_modules['func']->duration($nTime), __FILE__, __LINE__ );
		}
		
		// daily check
		foreach( $this->_config['startTime']['dayCheck'] as $i => $cTime )
		{
			// 3am, why not
			$nTime = strtotime( date('Y/m/d').' 03:'.$cTime );
			$nTime = $nTime - time();
			if ( $nTime < 5 )
				$nTime += 86400;			
			$irc->_autotvSTimers['day'][$i] = $irc->registerTimeHandler( $nTime * 1000, $this, '_firstDUS', array( 'id' => $i ) );
			$irc->modDebug( 'autotv', 'Registered inital day check timer: '.$cTime.', in '.$irc->_modules['func']->duration($nTime), __FILE__, __LINE__ );			
		}
	 
		// tvrage check
		foreach( $this->_config['startTime']['tvrageCheck'] as $i => $cTime )
		{
			$nTime = strtotime( date('Y/m/d H:').$cTime );
			$nTime = $nTime - time();
			if ( $nTime < 5 )
				$nTime += 3600;
			$irc->_autotvSTimers['tvrage'][$i] = $irc->registerTimeHandler( $nTime * 1000, $this, '_firstTU', array( 'id' => $i ) );
			$irc->modDebug( 'autotv', 'Registered inital tvrage check timer: '.$cTime.', in '.$irc->_modules['func']->duration($nTime), __FILE__, __LINE__ );
		}
	}
	
	function _firstHUS( &$irc, $vars )
	{
		$id = $vars['id'];
		
		$irc->unregisterTimeid( $irc->_autotvSTimers['hour'][$id] );
		unset( $irc->_autotvSTimers['hour'][id] );
		
		$irc->_autotvTimers[] = $irc->registerTimeHandler( 3600000, $this, '_hourlyUpdateShows', $vars );
		$irc->modDebug( 'autotv', 'Registered regular hour check timer: '.date('i').', in '.$irc->_modules['func']->duration(3600), __FILE__, __LINE__ );
		$this->_hourlyUpdateShows( $irc, $vars );
	}
	
	function _firstDUS( &$irc, $vars )
	{
		$id = $vars['id'];
		
		$irc->unregisterTimeid( $irc->_autotvSTimers['day'][$id] );
		unset( $irc->_autotvSTimers['day'][$id] );
		
		$irc->_autotvTimers[] = $irc->registerTimeHandler( 86400000, $this, '_dailyUpdateShows', $vars );
		$irc->modDebug( 'autotv', 'Registered regular day check timer: '.date('i').', in '.$irc->_modules['func']->duration(86400), __FILE__, __LINE__ );		
		$this->_dailyUpdateShows( $irc, $vars );
	}
	
	function _firstTU( &$irc, $vars )
	{
		$id = $vars['id'];
		
		$irc->unregisterTimeid( $irc->_autotvSTimers['tvrage'][$id] );
		unset( $irc->_autotvSTimers['tvrage'][$id] );

		$irc->_autotvTimers[] = $irc->registerTimeHandler( 3600000 * $this->_config['tvrageCheckTime'], $this, '_tvrageUpdate', $vars );
		$irc->modDebug( 'autotv', 'Registered regular tvrage check timer: '.date('i').', in '.$irc->_modules['func']->duration(3600 * $this->_config['tvrageCheckTime']), __FILE__, __LINE__ );
		$this->_tvrageUpdate( $irc, $vars );
	}
	
	function _hourlyUpdateShows( &$irc, $vars )
	{
		list( $tStart, $tStop ) = $this->_timerSplit( 'hourCheck', $vars['id'] );
		
		$irc->_modules['store']->manualUpdate( '_autotvInfo' );
		
		if ( is_array( $irc->_autotvInfo ) )
		{
			$keys = array_keys( $irc->_autotvInfo );
			for( $i=$tStart; $i < $tStop; $i++ )
			{
				$cShows .= $irc->_autotvInfo[$keys[$i]]['name'].', ';
				$this->_updateShow( $irc->_autotvInfo[$keys[$i]]['tvrageID'] );
			}
			$irc->modDebug( 'autotv', 'Checked shows: '.$cShows.'for new episodes', __FILE__, __LINE__ );
			$this->_checkHistory();
		}
	}
	
	function _dailyUpdateShows( &$irc, $vars )
	{
		list( $tStart, $tStop ) = $this->_timerSplit( 'dayCheck', $vars['id'] );
		
		$irc->_modules['store']->manualUpdate( '_autotvInfo' );

		if ( is_array( $irc->_autotvInfo ) )
		{		
			$keys = array_keys( $irc->_autotvInfo );		
			for( $i=$tStart; $i < $tStop; $i++ )
			{
				$cShows .= $irc->_autotvInfo[$keys[$i]]['name'].', ';
				$this->_updateShow( $irc->_autotvInfo[$keys[$i]]['tvrageID'], true );
			}
			$irc->modDebug( 'autotv', 'Checked shows: '.$cShows.'for new episodes', __FILE__, __LINE__ );
			$this->_checkHistory();
		}
	}
	                         
	function _tvrageUpdate( &$irc, $vars )
	{
		list( $tStart, $tStop ) = $this->_timerSplit( 'tvrageCheck', $vars['id'] );
		
		$irc->_modules['store']->manualUpdate( '_autotvInfo' );

		if ( is_array( $irc->_autotvInfo ) )
		{
			$keys = array_keys( $irc->_autotvInfo );
			for( $i=$tStart; $i < $tStop; $i++ )
			{
				$cShows .= $irc->_autotvInfo[$keys[$i]]['name'].', ';
				$this->_checkShow( $irc->_autotvInfo[$keys[$i]]['tvrageID'] );
			}
			$irc->modDebug( 'autotv', 'Checked tvrage info for: '.$cShows, __FILE__, __LINE__ );		
			$this->_checkHistory();
		}
	}
	
	/**
	 * Get the current entry in the startTime split
	 * 
	 * @param string $name - Variable name in startTime config array
	 * @param int $id - The timer identifier
	 * @return array $tStart, $tStop - The starting and stopping positions of the autotvInfo array
	 */
	function _timerSplit( $name, $id )
	{
		global $irc;
			
		$nSplit = count( $this->_config['startTime'][$name] );

		$tTotal = count( $irc->_autotvInfo );
		$tStart = floor( ( $tTotal / $nSplit ) * $id );
		$tStop = ceil( ( $tTotal / $nSplit ) * ($id + 1) );
		
		return array( $tStart, $tStop );
	}
}

?>
Return current item: Nzbirc