~alias1 trailing | ~alias2 trailing | ~alias3 trailing (stdout of left pipes to shellarg of right) ??? # TODO: OPTION TO REDIRECT PRIVMSG OUTPUT FROM SCRIPTS TO A BUCKET # TODO: /WAIT COMMAND THAT ALLOWS INDIVIDUAL SCRIPTS TO BE HALTED TILL A CERTAIN COMMAND IS RECEIVED BY THE BOT (SIMILAR USAGE TO BUCKET_GET) # TODO: QUIT COMMANDS FOR SCRIPTS (SIMILAR TO INIT & STARTUP) - USEFUL FOR SHUTTING DOWN DATA SERVERS # TODO: ADD FLAG TO HAVE EXEC IGNORE ITSELF # TODO: ADD && OPERATOR FOR STRINGING COMMANDS TOGETHER. OUTPUT FROM EACH COMMAND SHOULD BE ON SEPARATE LINES require_once("irc_lib.php"); set_time_limit(0); # script needs to run for indefinite time (overrides setting in php.ini) ini_set("display_errors","on"); ini_set("error_reporting",E_ALL); date_default_timezone_set("UTC"); define("START_TIME",microtime(True)); # used for %%start%% template if (isset($argv[1])==False) { # default installation-specific settings define("DEFAULT_NICK","x"); define("USER_NAME","x"); define("FULL_NAME","exec.bot"); define("PASSWORD_FILE","../pwd/exec"); define("BUCKETS_FILE","../data/buckets"); define("IGNORE_FILE","../data/ignore"); define("EXEC_FILE","exec.txt"); define("INIT_CHAN_LIST","#crutchy,#debug"); # comma delimited define("IRC_HOST_CONNECT","chat.soylentnews.org"); define("IRC_HOST","irc.sylnt.us"); define("IRC_PORT","6697"); define("OPERATOR_ACCOUNT","crutchy"); define("OPERATOR_HOSTNAME","709-27-2-01.cust.aussiebb.net"); define("DEBUG_CHAN","#debug"); define("NICKSERV_IDENTIFY_PROMPT","You have 60 seconds to identify to your nickname before it is changed."); define("ADMIN_ACCOUNTS","chromas,juggs,martyb,cmn32480"); define("MYSQL_LOG","1"); define("NICKSERV_IDENTIFY","1"); define("IFACE_ENABLE","0"); define("SSL_PEER_NAME","*.soylentnews.org"); define("SSL_CA_FILE","/etc/ssl/certs/ca-certificates.crt"); #define("SSL_CA_FILE","/home/jared/git/data/soylentnews.crt"); # cafile must contain both peer cert (https://staff.soylentnews.org/~bob/wildcard.crt) and then CA cert (http://sylnt.us/SoylentNewsCA.crt) in single bundled file in order of peer, then CA } elseif (file_exists($argv[1])==True) { $settings=file_get_contents($argv[1]); $settings=explode("\n",$settings); for ($i=0;$i2) { continue; } define($keyval[0],$keyval[1]); } } else { die("INVALID COMMAND LINE ARGUMENT\n"); } if (MYSQL_LOG=="1") { require_once("scripts/lib_mysql.php"); } define("EXEC_OUTPUT_BUFFER_FILE","../data/exec_iface"); define("EXEC_DELIM","|"); define("EXEC_DIRECTIVE_DELIM"," "); define("EXEC_INCLUDE","include"); define("EXEC_INIT","init"); define("EXEC_STARTUP","startup"); define("EXEC_HELP","help"); define("FILE_DIRECTIVE_DELIM",":"); define("FILE_DIRECTIVE_EXEC","exec"); define("FILE_DIRECTIVE_INIT","init"); define("FILE_DIRECTIVE_STARTUP","startup"); define("FILE_DIRECTIVE_HELP","help"); define("MAX_MSG_LENGTH",458); define("IGNORE_TIME",20); # seconds (alias abuse control) define("DELTA_TOLERANCE",1.5); # seconds (alias abuse control) define("TEMPLATE_DELIM","%%"); # stdout bot directives define("DIRECTIVE_QUIT","<>"); # internally used buckets define("BUCKET_IGNORE_NEXT","<>"); define("BUCKET_USERS","<>"); define("BUCKET_EVENT_HANDLERS","<>"); define("BUCKET_CONNECTION_ESTABLISHED","<>"); define("BUCKET_SELF_TRIGGER_EVENTS_FLAG","<>"); define("BUCKET_EXEC_LIST","<>"); define("BUCKET_BOT_NICK","<>"); define("BUCKET_ADMIN_ACCOUNTS_LIST","<>"); define("BUCKET_OPERATOR_ACCOUNT","<>"); define("BUCKET_OPERATOR_HOSTNAME","<>"); define("BUCKET_MEMORY_USAGE","<>"); define("BUCKET_OUTPUT_CONTROL","<>"); define("BUCKET_SHUTDOWN","<>"); define("BUCKET_PROCESS_TEMPLATE_PREFIX","process_template_"); define("BUCKET_ALIAS_ELEMENT_PREFIX","alias_element_"); $internal_bucket_indexes=array( BUCKET_IGNORE_NEXT, BUCKET_USERS, BUCKET_EVENT_HANDLERS, BUCKET_CONNECTION_ESTABLISHED, #BUCKET_SELF_TRIGGER_EVENTS_FLAG, BUCKET_EXEC_LIST, BUCKET_BOT_NICK, BUCKET_PROCESS_TEMPLATE_PREFIX, BUCKET_ALIAS_ELEMENT_PREFIX); # reserved aliases define("ALIAS_ALL","*"); define("ALIAS_INIT",""); define("ALIAS_STARTUP",""); define("ALIAS_QUIT",""); # commands intercepted from stdout # TODO: ADD COMMANDS TO DYNAMICALLY ADD/REMOVE BUCKET LOCKS TO AN ALIAS DEFINITION define("CMD_BUCKET_GET","BUCKET_GET"); define("CMD_BUCKET_SET","BUCKET_SET"); define("CMD_BUCKET_UNSET","BUCKET_UNSET"); define("CMD_BUCKET_APPEND","BUCKET_APPEND"); define("CMD_BUCKET_LIST","BUCKET_LIST"); define("CMD_INTERNAL","INTERNAL"); define("CMD_PAUSE","BOT_IRC_PAUSE"); define("CMD_UNPAUSE","BOT_IRC_UNPAUSE"); define("CMD_INIT","INIT"); define("CMD_STARTUP","STARTUP"); define("CMD_DELETE_HANDLER","DELETE_HANDLER"); define("PREFIX_DELIM","/"); define("PREFIX_IRC",PREFIX_DELIM."IRC"); define("PREFIX_EXEC_ADD",PREFIX_DELIM."EXEC-ADD"); define("PREFIX_EXEC_DEL",PREFIX_DELIM."EXEC-DEL"); define("PREFIX_EXEC_SAVE",PREFIX_DELIM."EXEC-SAVE"); define("PREFIX_PRIVMSG",PREFIX_DELIM."PRIVMSG"); define("PREFIX_BUCKET_GET",PREFIX_DELIM.CMD_BUCKET_GET); define("PREFIX_BUCKET_SET",PREFIX_DELIM.CMD_BUCKET_SET); define("PREFIX_BUCKET_UNSET",PREFIX_DELIM.CMD_BUCKET_UNSET); define("PREFIX_BUCKET_APPEND",PREFIX_DELIM.CMD_BUCKET_APPEND); define("PREFIX_BUCKET_LIST",PREFIX_DELIM.CMD_BUCKET_LIST); define("PREFIX_INTERNAL",PREFIX_DELIM.CMD_INTERNAL); define("PREFIX_PAUSE",PREFIX_DELIM.CMD_PAUSE); define("PREFIX_UNPAUSE",PREFIX_DELIM.CMD_UNPAUSE); define("PREFIX_DELETE_HANDLER",PREFIX_DELIM.CMD_DELETE_HANDLER); define("PREFIX_READER_EXEC_LIST",PREFIX_DELIM."READER_EXEC_LIST"); define("PREFIX_READER_BUCKETS",PREFIX_DELIM."READER_BUCKETS"); define("PREFIX_READER_HANDLES",PREFIX_DELIM."READER_HANDLES"); # internal aliases (can also use in exec file with alias locking, but that would be just weird) define("ALIAS_INTERNAL_RESTART","~restart-internal"); define("ALIAS_ADMIN_ALIAS_MACRO","~alias-macro"); define("ALIAS_ADMIN_QUIT","~quit"); define("ALIAS_ADMIN_NICK","~nick"); define("ALIAS_ADMIN_PS","~ps"); define("ALIAS_ADMIN_KILL","~kill"); define("ALIAS_ADMIN_KILLALL","~killall"); define("ALIAS_ADMIN_RESTART","~restart"); define("ALIAS_ADMIN_REHASH","~rehash"); define("ALIAS_ADMIN_DEST_OVERRIDE","~dest-override"); define("ALIAS_ADMIN_DEST_CLEAR","~dest-clear"); define("ALIAS_ADMIN_IGNORE","~ignore"); define("ALIAS_ADMIN_UNIGNORE","~unignore"); define("ALIAS_ADMIN_LIST_IGNORE","~ignore-list"); define("ALIAS_ADMIN_BUCKETS_DUMP","~buckets-dump"); # dump buckets to terminal define("ALIAS_ADMIN_BUCKETS_SAVE","~buckets-save"); # save buckets to file define("ALIAS_ADMIN_BUCKETS_LOAD","~buckets-load"); # load buckets from file define("ALIAS_ADMIN_BUCKETS_FLUSH","~buckets-flush"); # re-initialize buckets define("ALIAS_ADMIN_BUCKETS_LIST","~buckets-list"); # output list of set bucket indexes to the terminal define("ALIAS_ADMIN_EXEC_CONFLICTS","~exec-conflicts"); define("ALIAS_ADMIN_EXEC_LIST","~exec-list"); define("ALIAS_ADMIN_EXEC_TIMERS","~exec-timers"); define("ALIAS_ADMIN_EXEC_ERRORS","~exec-errors"); define("ALIAS_LOCK","~lock"); define("ALIAS_UNLOCK","~unlock"); define("ALIAS_LIST","~list"); define("ALIAS_LIST_AUTH","~list-auth"); # exec file shell command templates (replaced by the bot with actual values before executing) define("TEMPLATE_TRAILING","trailing"); define("TEMPLATE_NICK","nick"); define("TEMPLATE_DESTINATION","dest"); define("TEMPLATE_START","start"); define("TEMPLATE_ALIAS","alias"); define("TEMPLATE_DATA","data"); define("TEMPLATE_ITEMS","items"); define("TEMPLATE_CMD","cmd"); define("TEMPLATE_PARAMS","params"); define("TEMPLATE_TIMESTAMP","timestamp"); define("TEMPLATE_SERVER","server"); define("TEMPLATE_USER","user"); define("TEMPLATE_HOSTNAME","hostname"); define("TEMPLATE_PREFIX","prefix"); define("THROTTLE_LOCKOUT_TIME",10); # sec define("ANTI_FLOOD_DELAY",0.7); # sec define("RAWMSG_TIME_COUNT",5); # messages to send without any delays $admin_accounts=explode(",",ADMIN_ACCOUNTS); $alias_locks=array(); # optionally stores an alias for each nick, which then treats every privmsg by that nick as being prefixed by the set alias $handles=array(); # stores executed process information $time_deltas=array(); # keeps track of how often nicks call an alias (used for alias abuse control) $buckets=array(); # common place for scripts to store stuff (index cannot contain spaces, bucket content must be a string) $dest_overrides=array(); # optionally stores a destination for each nick, which treats every privmsg by that nick as having the set destination $bucket_locks=array(); # any bucket index put here by execution of an alias with bucket locks in its definition line cannot be read or written by other scripts: index=>array(pid1,pid2,etc) $admin_data=""; $admin_is_sock=""; $irc_pause=False; $throttle_time=False; # set when "throttled" is detected in a message from the server $rawmsg_times=array(); # aliases that may only be executed by the bot operator account $operator_aliases=array( ALIAS_ADMIN_ALIAS_MACRO); $admin_aliases=array( ALIAS_ADMIN_QUIT, ALIAS_ADMIN_NICK, ALIAS_ADMIN_RESTART, ALIAS_ADMIN_PS, ALIAS_ADMIN_KILL, ALIAS_ADMIN_KILLALL, ALIAS_ADMIN_REHASH, ALIAS_ADMIN_DEST_OVERRIDE, ALIAS_ADMIN_DEST_CLEAR, ALIAS_ADMIN_BUCKETS_DUMP, ALIAS_ADMIN_BUCKETS_SAVE, ALIAS_ADMIN_BUCKETS_LOAD, ALIAS_ADMIN_BUCKETS_FLUSH, ALIAS_ADMIN_BUCKETS_LIST, ALIAS_ADMIN_IGNORE, ALIAS_ADMIN_UNIGNORE, ALIAS_ADMIN_LIST_IGNORE, ALIAS_ADMIN_EXEC_CONFLICTS, ALIAS_ADMIN_EXEC_LIST, ALIAS_ADMIN_EXEC_TIMERS, ALIAS_ADMIN_EXEC_ERRORS); $reserved_aliases=array( ALIAS_ALL, ALIAS_INIT, ALIAS_STARTUP, ALIAS_QUIT); $silent_timeout_commands=array( CMD_INTERNAL, CMD_BUCKET_GET, CMD_BUCKET_SET, CMD_BUCKET_UNSET, CMD_BUCKET_APPEND, CMD_BUCKET_LIST, CMD_PAUSE, CMD_UNPAUSE); $valid_data_cmd=get_valid_data_cmd(); $init=array(); $startup=array(); $help=array(); initialize_buckets(); $exec_errors=array(); # stores exec load errors $exec_list=exec_load(); if ($exec_list===False) { term_echo("error loading exec file"); return; } $ignore_list=array(); if (file_exists(IGNORE_FILE)==True) { $ignore_data=file_get_contents(IGNORE_FILE); if ($ignore_data!==False) { $ignore_list=explode("\n",$ignore_data); } } delete_empty_elements($ignore_list); $direct_stdin=fopen("php://stdin","r"); stream_set_blocking($direct_stdin,0); if (file_exists(EXEC_OUTPUT_BUFFER_FILE)==True) { unlink(EXEC_OUTPUT_BUFFER_FILE); } if (IFACE_ENABLE==="1") { if (posix_mkfifo(EXEC_OUTPUT_BUFFER_FILE,0700)==False) { term_echo("error creating output buffer file"); return; } $out_buffer=fopen(EXEC_OUTPUT_BUFFER_FILE,"a+"); if ($out_buffer===False) { term_echo("error opening output buffer file for writing"); return; } stream_set_blocking($out_buffer,0); } init(); $socket=initialize_socket(); initialize_irc_connection(); # main program loop while (True) { for ($i=0;$i \033[31m$msg\033[0m\n"; } ##################################################################################################### function privmsg($destination,$nick,$msg) { global $dest_overrides; if ($destination=="") { term_echo("PRIVMSG: DESTINATION NOT SPECIFIED: nick=\"$nick\", msg=\"$msg\""); return; } if ($msg=="") { term_echo("PRIVMSG: NO TEXT TO SEND: nick=\"$nick\", destination=\"$destination\""); return; } $msg=substr($msg,0,MAX_MSG_LENGTH); if (isset($dest_overrides[$nick][$destination])==True) { $data=":".get_bot_nick()." PRIVMSG ".$dest_overrides[$nick][$destination]." :$msg"; rawmsg($data); } else { if (substr($destination,0,1)=="#") { $data=":".get_bot_nick()." PRIVMSG $destination :$msg"; rawmsg($data); } else { $data=":".get_bot_nick()." PRIVMSG $nick :$msg"; rawmsg($data); } } } ##################################################################################################### function rawmsg($msg,$obfuscate=False) { global $socket; global $throttle_time; global $rawmsg_times; if ($throttle_time!==False) { $delta=microtime(True)-$throttle_time; if ($delta>THROTTLE_LOCKOUT_TIME) { $throttle_time=False; } else { term_echo("*** REFUSED OUTGOING MESSAGE DUE TO SERVER THROTTLING: $msg"); return; } } $n=count($rawmsg_times); if ($n>0) { $last=$rawmsg_times[$n-1]; $dt=microtime(True)-$last; if ($dt>THROTTLE_LOCKOUT_TIME) { $rawmsg_times=array(); } else { if ($n>=RAWMSG_TIME_COUNT) { usleep(ANTI_FLOOD_DELAY*1e6); } } } fwrite($socket,$msg."\n"); $rawmsg_times[]=microtime(True); while (count($rawmsg_times)>RAWMSG_TIME_COUNT) { array_shift($rawmsg_times); } if ($obfuscate==False) { handle_data($msg."\n",True,False,True); } else { term_echo("RAWMSG: (obfuscated)"); } } ##################################################################################################### ?>