Search the Community
Showing results for tags 'socket_recv'.
-
I've posted below the entire bot's source code, with edited values for passwords and such. My bot for IRC works great, doesn't disconnect for the most part... but after 1-3 days, the bot hangs without any data being received or sent. If for example, I reset/disable my NIC card locally, the bot detects it and keeps trying to re-connect(detects fine...). I went as far as adding all raw data received to a TXT file, but even then... nothing seems abnormal. I suspect that the server is closing the connection, for whatever reason after a certain amount of time, and sends no message to my bot, so my bot stays connected and is waiting for data on the following line (line 337) $flag = @socket_recv($this->socket, $buffer, 4096, 0); I check for things like the buffer being empty or the flag being empty, I've been struggling with this error for a while... any help would be most grateful. I also tried using MSG_DONTWAIT as follows: $flag = @socket_recv($this->socket, $buffer, 4096, MSG_DONTWAIT); But with this method, I was unable to obtain any data correctly... just prints nothing for flags or the buffer... maybe i just don't know what this does or understand how it works? If I could get MSG_DONTWAIT working correctly, I could check the time between the last data and reconnect the bot this way... Thanks in advance /* * JTV Chat bot by Gawdsed * * @author Mathieu "Gawdsed" Graham (mathieugraham@gmail.com) and unofficially Ferdinand E. Silva (six519@phpugph.com) * @version Version 0.25 Alpha * * Special thanks to Ferdinand E. Silva for his starter code to connect to the IRC server, his code was great help as a starting point. * I've edited this starter code heavily though, including parsing text with correct triggers and editing the login process. * More is in stock and I will keep this program updated. */ <?php class PHPIRC { /************************************* /////////////EDIT BELOW/////////////// *************************************/ //server and channel connection info private $IrcServer = "avilo.jtvirc.com"; private $IrcPort = 6667; private $IrcNick = "avilomodbot"; private $IrcPass = "fake123"; private $IrcRoom = "avilo"; //database connection if you have one, set usedatabase to false if you dont private $useDatabase = false; private $DB_HOST = "123.123.123.123"; private $DB_USER = "asdasdasda"; private $DB_NAME = "asd"; private $DB_PASS = "fake123"; //timezone since PHP can't grab the local time for whatever reason... Just change it to your timezone number... central -6 for example private $timezone = "-7"; //by minutes... interval between announcement messages... recommended(20-30) private $announcementInterval = 30; //Decide if the bot should announce itself when logging in. private $announceSelf = false; //Show ping/pong? private $showPingPong = false; /************************************* ////////////STOP EDITING////////////// *************************************/ //standard variables and objects private $socket; private $isConnected = false; private $isAuthenticated = false; private $nextmessage = ""; //stores ops in array from information sent from server private $ops = []; //used for triggers for messages sent private $fileCanned = []; private $fileReply = []; private $fileNews = []; //constructor public function __construct() { $this->main(); } //main loop private function main() { date_default_timezone_set('Etc/GMT' . $this->timezone); //infinit loop while(1==1) { if(!$this->getDbInfo()) { echo $this->timestamp() . "Database not loaded, using local files\n"; } $this->loadFiles(); $this->connect(); //connect to irc server sleep(5); echo $this->timestamp() . "Attempting to reconnect...\n"; } } //send out message if time from now and set is greater private function checkminutes() { $date1 = new DateTime($this->timestampTostring()); if($this->nextmessage == "") { $this->nextmessage = new DateTime($this->timestampTostring()); $this->nextmessage->add(new DateInterval("PT" . $this->announcementInterval . "M")); $date2 = $this->nextmessage; } else { $date2 = $this->nextmessage; } $interval = $date1->diff($date2, false); //echo $this->timestampTostring(); $minutes = $interval->i; $hours = $interval->h; $days = $interval->d; $months = $interval->m; $minutescount = $minutes + ($hours*60) + ($days*24*60) + ($months*24*60*31); if (($minutescount <= 0 && count($this->fileNews) != 0) || (($date1 > $date2) && count($this->fileNews))) { for($i = 0;$i<=count($this->fileNews)-2;$i++) { $this->sendMessage("PRIVMSG #" . $this->IrcRoom . " :" . $this->fileNews[$i] . "\r\n"); sleep(1); //adding the amount requested by user till next broadcast $this->nextmessage = new DateTime($this->timestampTostring()); $this->nextmessage->add(new DateInterval("PT" . $this->announcementInterval . "M")); //echo to console echo $this->timestamp() . $this->IrcNick . ": " . $this->fileNews[$i] . "\n"; } //get mods as well, why not? $this->sendMessage("PRIVMSG " . $this->IrcRoom . " :/mods\r\n"); } } //returns the time since there is no tostring for dates... private function timestampTostring() { return date('Y-m-d H:i:s'); } //return string of a timestamp private function timestamp() { $date = date_create(); return "(" . $date->format( 'h:i:s' ) . ")"; } //loads files to arrays for easier access private function loadFiles() { $this->fileCanned = explode("\r\n", $this->readFile("1")); $this->fileReply = explode("\r\n", $this->readFile("2")); $this->fileNews = explode("\r\n", $this->readFile("3")); } //connects to db, overwrites files if needed private function getDbInfo() { if(!$this->useDatabase) { $this->createFile("1"); $this->createFile("2"); $this->createFile("3"); return false; } $db = new mysqli($this->DB_HOST, $this->DB_USER, $this->DB_PASS, $this->DB_NAME); if (mysqli_connect_errno()) { echo $this->timestamp() . "Connect failed: ", mysqli_connect_error() . "\n"; return false; } //get canned trigger and reply from table (name) and put into files $query = "SELECT * FROM ". $this->IrcRoom . " WHERE isnews = 0"; $result = $db->query($query); if($result === true) { $rowCount = $result->num_rows; } else { $rowCount = 0; } if($rowCount != 0) { $this->recreateFile("1"); $this->recreateFile("2"); while($row = mysqli_fetch_row($result)) { $this->appendFile($row[1],"1"); $this->appendFile($row[2],"2"); } } else { $this->createFile("1"); $this->createFile("2"); } //get news and put into file (name)news $query = "SELECT * FROM ". $this->IrcRoom . " WHERE isnews = 1"; $result = $db->query($query); if($result === true) { $rowCount = $result->num_rows; } else { $rowCount = 0; } if($rowCount != 0) { $this->recreateFile("3"); while($row = mysqli_fetch_row($result)) { $this->appendFile($row[2],"3"); } } else { $this->createFile("3"); } return true; } //reads a file private function readFile($number) { $data = ""; $fileName = $this->IrcRoom . $number; if(file_exists($fileName) && (filesize($fileName) != 0)) { $handle = fopen($fileName, 'r'); $data = fread($handle,filesize($fileName)); fclose($handle); } return $data; } //adds to a file private function appendFile($data,$number) { $fileName = $this->IrcRoom . $number; $fh = fopen($fileName, "a"); fwrite($fh, "" . $data . "\r\n"); fclose($fh); } //recreates files if they exist private function recreateFile($number) { $fileName = $this->IrcRoom . $number; if(file_exists($fileName)) { unlink($fileName); } $handle = fopen($fileName, 'w') or die('Cannot open file: ' . $fileName); fclose($handle); } //creates a file private function createFile($number) { $fileName = $this->IrcRoom . $number; if(file_exists($fileName)) { } else { $handle = fopen($fileName, 'w') or die('Cannot open file: ' . $fileName); fclose($handle); } } //gets user input private function getUserInput($msg) { $endInput = false; while(!$endInput) { echo "\n" . $msg . ": "; $handle = fopen ("php://stdin","r"); $line = fgets($handle); if(trim($line) != "") { $endInput = true; return trim($line); } fclose($handle); } } //connects to IRC server private function connect() { $this->socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP); if(@socket_connect($this->socket, $this->IrcServer,$this->IrcPort)) { $this->isConnected = true; $this->receiveMessages(); }else { echo $this->timestamp() . "Cannot Connect To Server. \n"; echo $this->timestamp() . socket_strerror(socket_last_error($this->socket)) . "\n"; } } //main parsing loop for all incoming server messages private function receiveMessages() { if($this->isConnected) { $flag = 1; $buffer = ""; $this->sendMessage("PASS " . $this->IrcPass . "\r\n" . "USER " . $this->IrcNick . " 0 * :" . $this->IrcNick . "\r\n" . "NICK " . $this->IrcNick . "\r\n"); echo $this->timestamp() . "Connecting to " . $this->IrcServer . " on port " . $this->IrcPort . " as user " . $this->IrcNick . "\n"; $this->sendMessage("JOIN #" . $this->IrcRoom . "\r\n"); echo $this->timestamp() . "Joining channel " . $this->IrcRoom . "\n"; $this->isAuthenticated=true; $this->sendMessage("JTVCLIENT \r\n"); $this->sendMessage("PRIVMSG " . $this->IrcRoom . " :/mods\r\n"); if($this->announceSelf) { $this->sendMessage("PRIVMSG #" . $this->IrcRoom . " :Bot initializing... please wait 10 seconds before sending commands. \r\n"); echo $this->timestamp() . $this->IrcNick . ": " . "Bot initializing... please wait up to 10 seconds before sending commands.\n"; } echo $this->timestamp() . "Connected successfully to server, waiting for text...\n"; while($this->isConnected) { $this->checkminutes(); $flag = @socket_recv($this->socket, $buffer, 4096, 0); if($buffer == "" || $flag === 0) { $this->isConnected = false; $this->isAuthenticated = false; echo $this->timestamp() . "\n********Client Disconnected********\n"; } //$this->appendFile("error: " . socket_strerror(socket_last_error($this->socket)),"debug"); $pieces = explode("\r\n", $buffer); //$this->appendFile($this->timestamp() . "\n****new***** " . $buffer . " *****end*****","debug"); for($i = 0; $i < count($pieces);$i++) { //message handle //echo "\n***BUFFER***:\n" . $pieces[$i] . "\n***ENDBUFFER***\n"; if(preg_match("/Checking Ident/",$pieces[$i]) && !$this->isAuthenticated) { $this->sendMessage("PASS " . $this->IrcPass . "\r\n" . "USER " . $this->IrcNick . " 0 * :" . $this->IrcNick . "\r\n" . "NICK " . $this->IrcNick . "\r\n"); } if(preg_match("/Nickname is already in use/",$pieces[$i]) && !$this->isAuthenticated) { $this->IrcNick=$this->asdgetUserInput("Please Enter New Irc Nick"); $this->sendMessage("PASS " . $this->IrcPass . "\r\n" . "USER " . $this->IrcNick . " 0 * :" . $this->IrcNick . "\r\n" . "NICK " . $this->IrcNick . "\r\n"); } if(preg_match("/Erroneous Nickname/",$pieces[$i]) && !$this->isAuthenticated) { $this->IrcNick=$this->getUserInput("Please Enter New Irc Nick"); $this->sendMessage("PASS " . $this->IrcPass . "\r\n" . "USER " . $this->IrcNick . " 0 * :" . $this->IrcNick . "\r\n" . "NICK " . $this->IrcNick . "\r\n"); } if(preg_match("/This nickname is registered/",$pieces[$i]) && !$this->isAuthenticated) { $this->IrcNick=$this->getUserInput("Please Enter New Irc Nick"); $this->sendMessage("PASS " . $this->IrcPass . "\r\n" . "USER " . $this->IrcNick . " 0 * :" . $this->IrcNick . "\r\n" . "NICK " . $this->IrcNick . "\r\n"); } if(preg_match("/End of \/MOTD command/",$pieces[$i]) && !$this->isAuthenticated) { $this->isAuthenticated=true; $this->sendMessage("JOIN #" . $this->IrcRoom . "\r\n"); } if(preg_match("/PING/",$pieces[$i])) { $this->sendMessage("PONG tmi.twitch.tv :TIMEOUTCHECK\r\n"); //$this->appendFile( $this->timestamp() . "PONG tmi.twitch.tv :TIMEOUTCHECK\r\n","debug"); if($this->showPingPong) { echo $this->timestamp() . "ping pong\n"; } } if(preg_match("/PART/", $pieces[$i])) { $tmpStr = preg_split("/:/", $pieces[$i]); $tmpStr = preg_split("/!/", $tmpStr[1]); $name = $tmpStr[0]; //nick of the sender $message = explode(" ", $pieces[$i]); echo $this->timestamp() . $message[1] . ": " . $name . "\n"; } if(preg_match("/JOIN/", $pieces[$i])) { $tmpStr = preg_split("/:/", $pieces[$i]); if(isset($tmpStr[1])) { $tmpStr = preg_split("/!/", $tmpStr[1]); $name = $tmpStr[0]; //nick of the sender $message = explode(" ", $pieces[$i]); echo $this->timestamp() . $message[1] . ": " . $name . "\n"; } else { echo $this->timestamp() . "Exception caught: " . $pieces[$i] . "\n"; } } if(preg_match("/PRIVMSG/", $pieces[$i])) { //echo $pieces[$i] . "(prvimsg)\n"; //parse and display channel messages $messagetogether = ""; $k = 2; $tmpStr = preg_split("/:/", $pieces[$i]); $tmpStr = preg_split("/!/", $tmpStr[1]); $name = $tmpStr[0]; //nick of the sender if(strpos($name," ") !== false) { $nametemp = explode(" ", $name); $name = $nametemp[0]; } $message = explode(":", $pieces[$i]); //message received //sometimes formatting changes a bit... lets make sure we only get the first item, aka the name. if($name == "jtv") { if(strpos($pieces[$i],":The moderators of this room are:") !== false) { $this->ops = []; $message[3] = str_replace(' ', '', $message[3]); $opsinfo = explode(",", $message[3]); for($t = 0;$t<count($opsinfo);$t++) { array_push($this->ops, $opsinfo[$t]); } echo $this->timestamp() . "Obtained " . count($opsinfo) . " mods from JTV" ."\n"; } }else if(isset($message[2])) { while(isset($message[$k])) { if($k == 2) { $messagetogether .= $message[$k]; $k+=1; } else { $messagetogether .= ":" . $message[$k]; $k+=1; } } //check to see if user is a mod or not $ismod = false; for($x = 0;$x<count($this->ops)-1;$x++) { if($name == $this->ops[$x]) { $ismod = true; } } if($ismod) { echo $this->timestamp() . "@" . $name . ": " . $messagetogether . "\n"; } else { echo $this->timestamp() . $name . ": " . $messagetogether . "\n"; } $this->trigger($name,$messagetogether); } else { echo $this->timestamp() . "Received message but parsed wrong... \n"; echo $pieces[$i] . "\n"; } } if(preg_match("/MODE/",$pieces[$i])) { //add mods to an array list, using /mods instead /* $tmpStr = preg_split("/ /", $pieces[$i]); if($tmpStr[3] == "+o") { array_push($this->ops, $tmpStr[4]); $this->ops = array_unique($this->ops); //echo "adding " . $tmpStr[4] . " as ops\n"; } elseif($tmpStr[3] == "-o") { $index = array_search($tmpStr[4],$this->ops); if($index !== false){ unset($this->ops[$index]); $this->ops = array_values($this->ops); } }*/ } } } echo $this->timestamp() . "Not connected anymore\n"; } } //triggers for messages that people send, check for mod, then ! and the keyword, reply if found, exit once found. private function trigger($nick, $msg) { for($i = 0;$i<count($this->ops)-1;$i++) { if($nick == $this->ops[$i]) { if(isset($this->fileCanned[0])) { for($e=0;$e<=count($this->fileCanned)-1;$e++) { $temp = explode(" ", $this->fileCanned[$e]); for($k=0;$k<=count($temp)-1;$k++) { if($msg == "!" . $temp[$k]) { echo $this->timestamp() . $this->IrcNick . ": " . $this->fileReply[$e] . "\n"; $this->sendMessage("PRIVMSG #" . $this->IrcRoom . " :" . $this->fileReply[$e] . "\r\n"); usleep(1500000); return; } } } } if($msg == "!?") { $messagestring = "Possible commands:"; for($e=0;$e<=count($this->fileCanned)-1;$e++) { $temp = explode(" ", $this->fileCanned[$e]); for($k=0;$k<=count($temp)-1;$k++) { $messagestring .= " " . $temp[$k]; } } $this->sendMessage("PRIVMSG #" . $this->IrcRoom . " :" . $messagestring . " sync " . "reload" . "\r\n"); echo $this->timestamp() . $this->IrcNick . ": " . $messagestring . "sync" . " reload" . "\n"; return; } if($msg == "!sync" || $msg == "!reload") { if($this->useDatabase) { $this->sendMessage("PRIVMSG #" . $this->IrcRoom . " :" . "sync comand received, syncing from database!" . "\r\n"); echo $this->timestamp() . $this->IrcNick . ": " . "sync comand received, syncing from database!" . "\n"; } else { $this->sendMessage("PRIVMSG #" . $this->IrcRoom . " :" . "Reload comand received, rebooting and re-loading files! (database sync not enabled)" . "\r\n"); echo $this->timestamp() . $this->IrcNick . ": " . "Reload comand received, rebooting and re-loading files! (database sync not enabled)" . "\n"; } $this->isConnected = false; return; } } } } //sends a message to the server private function sendMessage($msg) { socket_write($this->socket,$msg,strlen($msg)); } } //run PHPIRC $run = new PHPIRC(); ?>
- 2 replies
-
- irc
- disconnect
-
(and 1 more)
Tagged with: