PHP实现MSN机器人

PHP实现MSN机器人

« 大家好!

什么是 blogroll? »

PHP实现MSN机器人

上周研究了一下MSN协议,实现了一个小的MSN机器人,可以通过和它对话,可以查看它的好友名单,让它加好友,和给好友发送MSN消息。

代码:

<?php

/**

 * MSN机器人PHP实现

 *   ukalpa@yahoo.com.cn

 * http://www.wangshui.com

 *   2007-12-14

 * 参考: ”官方”协议文档 http://msnpiki.msnfanatic.com/index.php/MSN_Protocol_Version_13  

   MSN例子   http://www.hypothetic.org/docs/msn/switchboard/example_session.php 

   MSN中文协议分析             http://xiongcb.mentor100.com/2007/11/21/msn-messenger-%e5%8d%8f%e8%ae%ae%e5%88%86%e6%9e%90%e4%b8%80/

   代码参考  http://flumpcakes.co.uk/php/msn-messenger

 * Example:

   // ————————————————————————————

   // 此程序执行中,你可以以好友身份与机器人通讯,

   // 可以 /list : 列出机器人所有好友

   //  /user add x@x.com : 让机器人加某人为好友

   //  /message x@x.com hello : 让机器人向 x@x.com 发送 hello 的信息 [x@x.com必须是机器人好友]

    ob_implicit_flush();

    $user = ‘xxx@sports.sohu.com’;

    $pass = ‘xxxxxxxx’;

    if(!defined(”STDIN”)) define(”STDIN”, fopen(’php://stdin’,'r’)) ;

    if(!defined(”STDOUT”)) define(”STDIN”, fopen(’php://stdout’,'r’)) ;

    for(;;)

    {

     $msg = new Msn($user, $pass);

     $msg->putSYN();

     $msg->putCHG();

     while (!feof($msg->fp))

     {

      if ($data = $msg->_get())

       if($code = substr($data, 0, 3))

        if (method_exists($msg, ‘get’.$code)) $msg->{’get’.$code}($data);

        else $msg->getUnknow($data);

     }

     // 接收

     unset($msg);

     exit;

    }

   // ———————————————————————————–

 */

define(’DEBUG’, 1);      // 调试模式

define(’WEBPAGE’, 0);     // 1: WEB页面打开, 0: 命令行中打开

/**

 * MSN LANG

 * ERROR CODE reference : http://msnpiki.msnfanatic.com/index.php/Reference:Error_List#200s

 * Commands reference : http://msnpiki.msnfanatic.com/index.php/Reference:Commands

 */

$MSN_CODE = array(

‘1′   => ‘unknow error’,

‘200′ => ‘Invalid Syntax’,

‘201′ => ‘Invalid parameter’,

‘205′ => ‘Invalid principal’,

‘206′ => ‘Domain name missing’,

‘207′ => ‘Already logged in’,

‘208′ => ‘Invalid principal’,

‘209′ => ‘Nickname change illegal’,

‘210′ => ‘Principal list full’,

‘213′ => ‘Invalid rename request?’,

‘215′ => ‘Principal already on list’,

‘216′ => ‘Principal not on list’,

‘217′ => ‘Principal not online’,

‘218′ => ‘Already in mode’,

‘219′ => ‘Principal is in the opposite list’,

‘223′ => ‘Too many groups’,

‘224′ => ‘Invalid group’,

‘225′ => ‘Principal not in group’,

‘227′ => ‘Group not empty’,

‘228′ => ‘Group with same name already exists’,

‘229′ => ‘Group name too long’,

‘230′ => ‘Cannot remove group zero’,

‘231′ => ‘Invalid group’,

‘240′ => ‘Empty domain’,

‘280′ => ‘Switchboard failed’,

‘281′ => ‘Transfer to switchboard failed’,

‘282′ => ‘P2P Error?’,

‘300′ => ‘Required field missing’,

‘302′ => ‘Not logged in’,

‘402′ => ‘Error accessing contact list’,

‘403′ => ‘Error accessing contact list’,

‘420′ => ‘Invalid Account Permissions’,

‘500′ => ‘Internal server error’,

‘501′ => ‘Database server error’,

‘502′ => ‘Command disabled’,

‘510′ => ‘File operation failed’,

‘511′ => ‘Banned’,

‘520′ => ‘Memory allocation failed’,

‘540′ => ‘Challenge response failed’,

‘600′ => ‘Server is busy’,

‘601′ => ‘Server is unavailable’,

‘602′ => ‘Peer nameserver is down’,

‘603′ => ‘Database connection failed’,

‘604′ => ‘Server is going down’,

‘605′ => ‘Server unavailable’,

‘700′ => ‘Could not create connection’,

‘710′ => ‘Bad CVR parameters sent’,

‘711′ => ‘Write is blocking’,

‘712′ => ‘Session is overloaded’,

‘713′ => ‘Calling too rapidly’,

‘714′ => ‘Too many sessions’,

‘715′ => ‘Not expected’,

‘717′ => ‘Bad friend file’,

‘731′ => ‘Not expected’,

‘800′ => ‘Changing too rapidly’,

‘910′ => ‘Server too busy’,

‘911′ => ‘Server is busy’,

‘912′ => ‘Server too busy’,

‘913′ => ‘Not allowed when hidden’,

‘914′ => ‘Server unavailable’,

‘915′ => ‘Server unavailable’,

‘916′ => ‘Server unavailable’,

‘917′ => ‘Authentication failed’,

‘918′ => ‘Server too busy’,

‘919′ => ‘Server too busy’,

‘920′ => ‘Not accepting new principals’,

‘921′ => ‘Server too busy’,

‘922′ => ‘Server too busy’,

‘923′ => ‘Kids/’ Passport without parental consent’,

‘924′ => ‘Passport account not yet verified’,

‘928′ => ‘Bad ticket’,

‘931′ => ‘Account not on this server’,

);

// HAS REPEATED .

$MSN_COMMAND = array(

// Logon/Dispatch server

‘VER’ => ‘Protocol version’,

‘CVR’ => ‘Sends version information’,

‘USR’ => ‘Authentication command’,

‘XFR’ => ‘Redirection to Notification server’,

// Notification Server

// Contact list/Settings/Initial syncronisation commands

‘BLP’ => ‘Initial settings download’,

‘BPR’ => ‘Initial settings download’,

‘GTC’ => ‘Initial contact list/setting download’,

‘ILN’ => ‘Initial contact persence notification’,

‘LSG’ => ‘Initial contact list download - Groups’,

‘LST’ => ‘Initial contact list download - Contacts’,

‘MSG’ => ‘Initial profile download’,

‘PRP’ => ‘Initial settings download - Mobile settings and display name’,

// Standard send/receive commands

‘ADL’ => ‘Add users to your contact lists’,

‘ADC’ => ‘Add users to your contact lists (deprecated as of MSNP13)’,

‘ADD’ => ‘Add users to your conatct lists (deprecated as of MSNP11)’,

‘ADG’ => ‘Create groups’,

‘CHG’ => ‘Change client`s online status’,

‘GCF’ => ‘Unknown’,

‘OUT’ => ‘Gracefully logout’,

‘PNG’ => ‘Client ping’,

‘QNG’ => ‘Server response to PNG’,

‘QRY’ => ‘Response to CHL by client’,

‘SBS’ => ‘Unknow’,

‘SYN’ => ‘Begin synchronization/download contact list’,

‘REA’ => ‘Change display name’,

‘REG’ => ‘Rename groups’,

‘REM’ => ‘Rename contacts’,

‘RMG’ => ‘Remove groups’,

‘XFR’ => ‘Open new chat session on switchboard server’,

‘UBX’ => ‘Inform you with a user PSM/Media’,

// Asynchronous commands

‘CHL’ => ‘Client challenge (see MSNP8:Challenges)’,

‘FLN’ => ‘Principal signed off’,

‘NLN’ => ‘Principal changed presence/signed on’,

‘RNG’ => ‘Client invited to chat session’,

// Switchboard

‘ANS’ => ‘Log in to switchboard chat session using invitation’,

‘IRO’ => ‘Defines which principals are in the current chat session’,

‘USR’ => ‘Log in to switchboard chat session after requesting session from NS’,

‘CAL’ => ‘Invite a user to a chat session’,

‘JOL’ => ‘Response to CAL, when user connected successfully’,

‘MSG’ => ‘Used to send and receive messages in the chat session’,

‘BYE’ => ‘Contact has left conversation’,

‘OUT’ => ‘Gracefully leave switchboard chat session’,

);

if (WEBPAGE)

{

 ?>

    <style type=”text/css” media=”screen” title=”default”>

 body {

  font: 76%/1.4 tahoma, verdana, arial, helvetica, sans-serif;

 }

 .r {

  color: red;

 }

 .g {

  color: green;

 }

    </style>

 <?php

}

class Msn

{

 var $admin_password = ‘ukalpa@yahoo.com.cn’;

 /**

  * $passport => array(

      ’passport’ =>

      ’status’ =>

      ’group’  =>

      ’identify’ =>

     );

  */

 var $member   = array();      // members

 var $msn_status  = array();

 var $debug   = DEBUG;

 var $server   = ’messenger.hotmail.com’;

 var $port   = 1863;

 var $fp    = null; 

 var $passport  = ”;

 var $password  = ”;

 var $history  = array();       // store put/get history

 var $connected  = false;

 var $font_fn  = ’Arial’;

 var $font_co  = ’333333′;

 var $font_ef  = ”;

 var $nexus = ’https://nexus.passport.com/rdr/pprdr.asp’; //tweener

 var $ssh_login = ’login.live.com/login2.srf’;

 

 // curl is used for the secure login, if you don’t have

 // the php_curl library installed, you can use a curl binary

 // instead. $use_curl needs to be set to 1 to enable this.

 // set $curl to the path where curl is installed.

 // curl can be downloaded here: http://curl.haxx.se/download.html

 var $curl_bin = 0;

 var $curl = ’/usr/local/bin/curl’; // linux

 //var $curl = ’c:/curl.exe’;  // windows

 // __construct

 function Msn($passport = ”, $password = ”)

 {

  if ($passport && $password)

  {

   $this->_login($passport, $password);

  }

 }

 // ——————- operation function ——————————————————-

 function putADC($email)

 {

  $this->_put(”ADC $this->trID FL N=$email F=$email/r/n”);

  $this->_put(”ADD $this->trID AL $email $email/r/n”);

 }

 function getADC($data)

 {

  // <<< ADC 50 FL N=name@domain.tld F=name@domain.tld C=b54cae02-dc8a-447c-8407-f38595ccaba0/r/n

  @list($code,,,$email,,$cid) = $data;

  // @list($code,,,$email,,$cid) = $data;

  if (substr($cid, 0,2) == ‘C=’) $this->setMember($email);

 }

 function putREM($email)

 {

  $this->_put(”REM $this->trID AL $email/r/n”);

  $this->_put(”REM $this->trID FL $email/r/n”);

 }

 function getADD($data)

 {

  // ADD 0 RL 0 bj_yq@hotmail.com bj_yq@hotmail.com

  // <<<< ADD 0 RL 0 hillsilenthill@hotmail.com Shawn

  // <<<< ADD 0 RL 0 fenghuangjie@hotmail.com 鍑ゅ嚢鍔?

  //@list($code,$sid,,$id,$email,$email) = $data;

  // $this->_put(”ADD $sid AL $email $email/r/n”);

  @list($code, , , ,$email, $email1) = $data;

  $this->putADC($email);

 }

 // 获得用户列表

 // LST ukalpa@yahoo.com.cn ukalpa@yahoo.com.cn 11 0

 function getLST($data)

 {

  @list($code,$passport,$nickname,$list, $group) = $data;

  $this->setMember($passport, array(’passport’ => $passport, ‘nickname’ => $nickname) );

 }

 // synchversion : The last cached synchronization version number, the client should send 0 if none exists

 function putSYN($synchversion = 0)

 {

  $this->_put(”SYN $this->trID $synchversion/r/n”);

 }

 function getSYN($data)

 {

  if ($this->debug) $this->show_msg(__METHOD__, $data);

 }

 // 更新上线状态

 // 上线

 function getNLN($data)

 {

  list($code, $status, $passport, $nickname, $xml) = explode(’ ‘, $data);

  if ($this->debug) $this->show_msg(__METHOD__, $passport . ‘ set his msn status: ‘. $status);

  $this->member[$passport][’status’] = $status;

  if ($nickname) $this->member[$passport][’nickname’] = $nickname;

 }

 // 离线

 function getFLN($data)

 {

 }

 // 获得用户列表

 function getILN($data)

 {

  list($code,, $status, $passport, $nickname, $xml) = explode(’ ‘, $data);

  if ($this->debug) $this->show_msg(__METHOD__, $passport . ‘ set his msn status: ‘. $status);

  $this->member[$passport][’status’] = $status;

  if ($nickname) $this->member[$passport][’nickname’] = $nickname;

 }

 // 接受用户通话请求

 function getRNG($data)

 {

  list(, $sid, $server, , $as, $source_email, $name) = explode(’ ‘, $data);

  list($ip, $port) = explode(’:', $server);

  $session_start_time = time();

  if ($sb = @fsockopen($server, $port, $errno, $errstr, 5))

  {

   $this->_put(”ANS $this->trID $this->passport $as $sid/r/n”, $sb);

   $data = $this->_get(4096, $sb);

   /*

   $cur_num Count of the current rooster enumerated

   $tot  Count of the total number of roosters in switchboard

   $email  Passport account-name of the currently enumerated rooster.

   $name  URL encoded MSN friendly-name of the currently enumerated rooster

   */

   @list($iro, , $cur_num, $tot, , $name) = explode(’ ‘, $data); // 只是接收请求的列表

   if ($iro != ‘IRO’)

   {

    // 错误信息

    echo “** IRO BAD data : “. $data .” **/n”;

    return false;

   }

   // recieve names/list of others connected

   for ($i=1; $i<$tot; $i++)

   {

    if (!$data = $this->_get(4096, $sb))

    {

     echo “** TOT BAD data : “. $data .” **/n”;

     return false;

    }

   }

   @list($ans) = explode(’ ‘, $this->_get(4096, $sb));

   if ($ans != ‘ANS’) return false;

   // 验证完毕, 继续接收消息

   $message = null;

   $msglen = null;

   $t_flg = true;

   stream_set_timeout($sb, 1);

   while ($t_flg && !feof($sb))

   {

    $data = ($msglen) ? $this->_get($msglen, $sb) : $this->_get(4096, $sb);

    switch (substr($data, 0, 3))

    {

     default:

      $message.= $data;

      if (strlen($message) >= $msglen && !empty($msglen))

      {

       $mesg = explode(”/n”, trim($message));

       $last = end($mesg);

       if (!strstr($message, ‘TypingUser’))

       {

        $t_flg = false;

        // this isn’t a notification that the user is typing a message

        // return $last;

       }

       $msglen = null;

       $message = null;

      }

      if ($session_start_time + 10 < time())

      {

       // looks like we’ve been idle for a while

       echo ‘IM timed out’;

       $this->_put(”OUT/r/n”, $sb);

       fclose($sb);

       return null;

      }

     break;

     case ‘MSG’:

      list(,,, $msglen) = explode (’ ‘, $data);

     break;

     case ‘BYE’:

      return null;

     break;

    }

   }

   // 接收完毕, 继续处理

   // 处理用户命令

   $msg = $last;

   if ($msg[0] == ‘/’) // 回复

   {

    // 处理消息

    $this->doexec($msg, $source_email, $sb);

   }

   else // 普通对话, 直接回复

   {

    $msg  = ‘your content is : ‘ . $msg . ‘ system time: ‘. date(’Y-m-d H:i:s’);

    $this->sendMsg( $source_email, $msg, $sb);

    //$conv->sendMsg($this->fp, $this->passport, $email, $msg);

    //$this->show_msg(__METHOD__, $this->passport . ‘ talk to ‘. $email .’ : ‘. $msg);

   }

   

   $this->_put(”OUT/r/n”, $sb);

   fclose($sb);

  }

 }

 // 验证状态的一部分

 function getCHL($data)

 {

  $this->putQRY($data);

 }

 // 发送QRY消息, 数据来源CHL

 function putQRY($data)

 {

  $this->connected = false;

  $bits = explode (’ ‘, trim($data));

  $return = md5($bits[2].’Q1P7W2E4J9R8U3S5′);

  $this->_put(”QRY $this->trID msmsgs@msnmsgr.com 32/r/n$return”);

 }

 // 获得QRY反馈

 function getQRY($data)

 {

  $this->connected = true;

 }

 // 获得建立连接请求

 // XFR 7 SB 207.46.27.80:1863 CKI 431823257.2645138.222151136

 function getXFR($data)

 {

  list($xfr, $mak, $sb, $server,, $as) = explode(’ ‘, $data);

  if ($sb == ‘SB’) // 对话新连接

  {

   list($server, $port) = explode(’:', $server);

   if ($sb_c = fsockopen($server, $port, $errno, $errstr, 50))

   {

    $x = 0;

    $data = “USR “. ($x++) .” $this->passport “. trim($as) .”/r/n”;

    $this->_put($data, $sb_c); // 分配服务器

    $this->_get(4096, $sb_c); //  响应分配服务器

    $data = “CAL “. ($x++) .” “. $this->msg_arr[$mak][’email’] .”/r/n”; // 呼叫用户

    $this->_put($data, $sb_c);

    $data = $this->_get(4096, $sb_c); //  响应呼叫用户

    if (strstr($data, ‘CAL’))

    {

     $data = $this->_get(4096, $sb_c); //  响应呼叫用户

     // 判断,应该是 JOI, 表示成功相应

     // ….

    }

    else if ($this->admin_password != $this->msg_arr[$mak][’email’]) // 管理员不给自己发消息

    {

     // 错误,无法发送消息给用户

     $msg = ‘发送消息到[’. $this->msg_arr[$mak][’email’]  . ‘]失败, 原因: ‘. $data;

     $this->sendMsg($this->admin_password, $msg);

     return false;

     // error

    }

    $message = “MIME-Version: 1.0/r/nContent-Type: text/plain; charset=UTF-8/r/nX-MMS-IM-Format: FN=Arial; EF=I; CO=0; CS=0; PF=22/r/n/r/n”. $this->msg_arr[$mak][’msg’];

    $message = “MSG 20 N “.strlen($message).”/r/n$message”;

    $this->_put($message, $sb_c);

    $this->_put(”OUT/r/n”, $sb_c);

    @fclose($sb_c);

    return true;

   }

   else

   {

    echo ‘create error’;

   }

  }

  echo ’successs: ‘;

  echo $data;exit;

 }

 // 改变用户在线状态

 // $status : NLN, BSY, BRB, AWY, IDL, PHN, LUN, HDN

 function putCHG($status = ‘NLN’)

 {

  $this->_put(”CHG $this->trID $status/r/n”);

 }

 function getUnknow($data = ”)

 {

  $this->show_msg(__METHOD__, $data);

 }

 function show_msg($func, $data, $type = ‘r’)

 {

  if (WEBPAGE) echo “<div class=/”g/”>[func:”. $func .”]: $data</div>”;

  else fputs(STDOUT, $func . ‘: ‘ . $data.chr(10));

 }

 // 主动发送命令, 异步

 var $msg_arr = array();

 function sendMsg($email, $msg, $sb = null)

 {

  if (@is_resource($sb)) // 现成的连接

  {

   $message = “MIME-Version: 1.0/r/nContent-Type: text/plain; charset=UTF-8/r/nX-MMS-IM-Format: FN=$this->font_fn; EF=$this->font_ef; CO=$this->font_co; CS=0; PF=22/r/n/r/n$msg”;

   $message = “MSG 20 N “.strlen($message).”/r/n$message”;

   // switchboard session already open

   $this->_put($message, $sb);

   return true;

  }

  else  // 建立一个连接

  {

   $this->msg_arr[$this->trID] = array(’email’ => $email, ‘msg’ => $msg);

   $this->_put(”XFR $this->trID SB/r/n”);

  }

 }

 // ——————- control function ——————————————————-

 // 处理MSN发送请求的命令

 // $email : 发送请求的MSN

 // $sb : MSN人工的消息连接

 function doexec($msg, $source_email, $sb = null)

 {

  $msg = strtolower($msg); // 所有小写

  // 新主动发一个对话

  $this->show_msg(__METHOD__, ‘Oris : ‘. $msg);

  if ( ($msg[0] == ‘/’)) // system order

  {

   if ($p = strpos($msg, ‘ ‘)) 

   {

    $order = substr($msg, 1, $p - 1);

    $data = substr($msg, $p + 1);

   }

   else $order = substr($msg, 1);

   $data = substr($msg, strpos($msg, ‘ ‘) + 1);

   if (method_exists($this, ‘exec’. $order))

   {

    $msg = $this->{’exec’. $order}($data);

   }

   else

   {

    // 错误,无法发送消息给用户

    $msg = ‘无法识别您的请求[’. $order .’], /message (email) (msg) /list’;

   }

   // 发送反馈结果给发送请求的EMAIL

   $this->sendMsg($source_email, $msg, $sb);

   /*

   switch($order)

   {

    case ‘message’:

     $email = substr($data, 0, strpos($data, ‘ ‘));

     $message = substr($data, strpos($data, ‘ ‘) + 1);

     $this->sendMsg($email, $message);

     break;

    default:

     echo ‘unknow error: |’.$order .’|’.chr(10);

   }

   */

  }

  else

  {

   $this->show_msg(__METHOD__, ‘Oris faield’ );

  }

 }

 // 处理/message信息

 // @retu 发送某个消息成功

 function execMessage($data)

 {

  $email = substr($data, 0, strpos($data, ‘ ‘));

  $message = substr($data, strpos($data, ‘ ‘) + 1);

  $this->sendMsg($email, $message);

  return ‘Has send Msg[’. $message . ‘] to Msn[’. $email . ‘] ! ‘ . chr(10);

 }

 // 处理状态信息

 function execStatus($data)

 {

  if (strpos($data, ‘ ‘))

  {

   $act = substr($data, 0, strpos($data, ‘ ‘));

   $status = substr($data, strpos($data, ‘ ‘) + 1);

   /*

   switch($act)

   {

    case ‘now’:

   }

   */

  }

  else

  {

   $act = $data;

   $str = ‘没有具体状态 (NLN, BSY, BRB, AWY, IDL, PHN, LUN, HDN)’ ;

  }

 

  return $str;

 }

 // 处理成员信息

 function execUser($data)

 {

  if (strpos($data, ‘ ‘))

  {

   $act = substr($data, 0, strpos($data, ‘ ‘));

   $user = substr($data, strpos($data, ‘ ‘) + 1);

  }

  else $act = $data;

 

  switch($act)

  {

   case ‘list’:

     $str = $this->execList();

    break;

   case ‘del’:

     if ($user) $this->putREM($user);

     else $str = ‘limit $user’;

    break;

   case ‘add’: 

     if ($user) $this->putADC($user);

     else $str = ‘limit $user’;

    break;

   // case ‘deluser’:

   //  $this->put();

   // break;

  }

  return $str;

 }

 // 获得成员列表

 function execList()

 {

  // 获得用户列表

  $str = ‘User List: ‘ .chr(10);

  foreach($this->member as $msn => $member)

  {

   $str .= $member[’nickname’]. ‘(’. $member[’status’] .’)’ . chr(10);

  }

  return $str;

 }

 // 设置用户信息

 function setMember($passport, $arr = array())

 {

  if ($passport)

  {

   $this->member[$passport][’passport’] = $passport;

   foreach($arr as $k => $v)

   {

    $this->member[$passport][$k] = $v;

   }

  }

 }

 // ——————- private function ——————————————————-

 // put

 function _put($data, $fp = null)

 {

  if ($this->debug) 

  {

   if (WEBPAGE) echo “<div class=/”g/”>>>> $data</div>”;

   else fputs(STDOUT, ‘>>>> ‘ . $data.chr(10));

  }

  if (!$fp) $fp = &$this->fp;

  fwrite($fp, $data);

  $this->history[$this->trID] = $data;

  $this->trID++;

 }

 // get

 function _get($offset = 4096, $fp = null)

 {

  if (!$fp) $fp = &$this->fp;

  if ($data = @fgets($fp, $offset)) 

  {

   if ($this->debug) 

   {

    if (WEBPAGE) echo “<div class=/”r/”><<< $data</div>/n”;

    else fputs(STDOUT, ‘<<<< ‘ . $data.chr(10));

    

   }

   return $data;

  }

  else return false;

 }

 // 显示错误

 function _get_error($code)

 {

  global $MSN_CODE;

  if (array_key_exists($code, $MSN_CODE)) $code = 1;

  return $MSN_CODE[$code];

 }

 // auth user

 // referee: http://msnpiki.msnfanatic.com/index.php/Tweener

 function _ssl_auth($auth_string)

 {

  if ($this->curl_bin)

  {

   exec(”$this->curl -m 60 -LkI $this->nexus”, $header);

   $header = implode($header, null);

  }

  else

  {

   $ch = curl_init($this->nexus);

   curl_setopt($ch, CURLOPT_HEADER, 1);

   curl_setopt($ch, CURLOPT_NOBODY, 1);

   curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

   curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

   // curl_setopt($ch, CURLOPT_TIMEOUT, 2);

   $header = curl_exec($ch);

   curl_close($ch);

  }

  preg_match (’/DALogin=(.*?),/’, $header, $out);

  if (isset($out[1])) $slogin = $out[1];

  else return false;

  if ($this->curl_bin)

  {

   $header1 = ‘”Authorization: Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,sign-in=’.$this->passport.’,pwd=’.$this->password.’,’.$auth_string.’”‘;

   exec(”$this->curl -m 60 -LkI -H $header1 https://$slogin“, $auth_string);

   $header = null;

   foreach ($auth_string as $key => $value)

   {

    if (strstr($value, ‘Unauthorized’))

    {

     echo ‘Unauthorised’;

     return false;

    }

    elseif (strstr($value, ‘Authentication-Info’))

    {

     $header = $value;

    }

   }

  }

  else

  {

   $ch = curl_init(’https://’.$slogin);

   curl_setopt($ch, CURLOPT_HTTPHEADER, array(

       ’Authorization: Passport1.4 OrgVerb=GET,OrgURL=http%3A%2F%2Fmessenger%2Emsn%2Ecom,sign-in=’.$this->passport.’,pwd=’.$this->password.’,’.$auth_string,

       ’Host: login.passport.com’

       ));

   curl_setopt($ch, CURLOPT_HEADER, 1);

   curl_setopt($ch, CURLOPT_NOBODY, 1);

   curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

   curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

   // curl_setopt($ch, CURLOPT_TIMEOUT, 2);

   $header = curl_exec($ch);

   curl_close($ch);

  }

  preg_match (”/from-PP=’(.*?)’/”, $header, $out);

  return (isset($out[1])) ? $out[1] : false;

 }

 

 // passport _login

 // return true:succ, false:failed

 function _login($passport, $password)

 {

  $this->trID = 1;

  if ($this->fp = @fsockopen($this->server, $this->port, $errno, $errstr, 2))

  {

   $this->_put(”VER $this->trID MSNP9 CVR0/r/n”);

   while (! feof($this->fp))

   {

    $data = $this->_get();

    switch ($code = substr($data, 0, 3))

    {

     default:

      echo $this->_get_error($code);

      return false;

     break;

     case ‘VER’:

      $this->_put(”CVR $this->trID 0×0409 win 4.10 i386 MSNMSGR 7.0.0816 MSMSGS $passport/r/n”);

     break;

     case ‘CVR’:

      $this->_put(”USR $this->trID TWN I $passport/r/n”);

     break;

     case ‘XFR’:

      list(, , , $ip)  = explode (’ ‘, $data);

      list($ip, $port) = explode (’:', $ip);

      if ($this->fp = @fsockopen($ip, $port, $errno, $errstr, 2))

      {

       $this->trID = 1;

       $this->_put(”VER $this->trID MSNP9 CVR0/r/n”);

      }

      else

      {

       echo ‘Unable to connect to msn server (transfer)’;

       return false;

      }

     break;

     case ‘USR’:

      if (isset($this->authed))

      {

       return true;

      }

      else

      {

       $this->passport = $passport;

       $this->password = urlencode($password);

       list(,,,, $code) = explode(’ ‘, trim($data));

       if ($auth = $this->_ssl_auth($code))

       {

        $this->_put(”USR $this->trID TWN S $auth/r/n”);

        $this->authed = 1;

       }

       else

       {

        echo ‘auth failed’;

        return false;

       }

      }

     break;

    }

   }

  }

  else

  {

   echo ‘Unable to connect to msn server’;

   return false;

  }

 }

}

环境要求 PHP >= 7.0 PHP fileinfo 拓展 储存文件需要用到 PHP gd 拓展 控制台显示二维码 PHP posix 拓展 控制台显示二维码(linux) PHP 系统命令 拓展 执行clear命令 PHP SimpleXML 拓展 解析XML 安装 请确保已经会使用composer! 运行微信账号的语言设置务必设置为简体中文!!否则可能出现未知的错误! 1、git git clone https://github.com/HanSon/vbot.git cd vbot composer install 2、composer composer require hanson/vbot 运行 正常运行 php example/index.phpsession运行 php example/index.php --session yoursession 关于session : 带session运行会自动寻找设定session指定的cookies,如不存在则新建一个文件夹位于 /tmp/session 中,当下次修改代码时再执行就会免扫码自动登录。 如果不设置,vbot会自动设置一个6位的字符的session值,下次登录也可以直接设定此值进行面扫码登录。 PS:运行后二维码将保存于设置的缓存目录,命名为qr.png,控制台也会显示二维码,扫描即可(linux用户请确保已经打开ANSI COLOR) 警告!执行前请先查看index.php的代码,注释掉你认为不需要的代码,避免对其他人好友造成困扰 请在terminal运行!请在terminal运行!请在terminal运行! 目录结构 vbot demo (vbot 当前在运行的代码,也欢迎大家提供自己的一些实战例子) example (较为初级的实例) src (源码) tmp (假设缓存目录设置在此) session hanson (设定值 php index.php --session hanson) 523eb1 (随机值) users 23534234345 (微信账号的UIN值) file (文件) gif (表情) jpg (图片) mp3 (语音) mp4 (视频) contact.json (联系人 debug模式下存在) group.json (群组 debug模式下存在) member.json (所有群的所有成员 debug模式下存在) official.json (公众号 debug模式下存在) special.json (特殊账号 debug模式下存在) message.json (消息) 体验 扫码后,验证输入“echo”即可自动加为好友并且拉入vbot群。 vbot并非24小时执行,有时会因为开发调试等原因暂停功能。如果碰巧遇到关闭情况,可加Q群 492548647 了解开放时间。执行后发送“拉我”即可自动邀请进群。
<?php namespace BotMan\BotMan; use React\Socket\Server; use BotMan\BotMan\Http\Curl; use React\EventLoop\LoopInterface; use BotMan\BotMan\Cache\ArrayCache; use BotMan\BotMan\Drivers\DriverManager; use BotMan\BotMan\Interfaces\CacheInterface; use Symfony\Component\HttpFoundation\Request; use BotMan\BotMan\Interfaces\StorageInterface; use BotMan\BotMan\Storages\Drivers\FileStorage; class BotManFactory {     private static $extensions = [];     /**      * @param $methodName      * @param $callable      */     public static function extend($methodName, $callable)     {         self::$extensions[$methodName] = $callable;     }聊天机器人(chatterbot)是一个用来模拟人类对话或聊天的程序。“Eliza”和 “Parry”是早期非常著名的聊天机器人。它试图建立这样的程序:至少暂时性地让一个真正的人类认为他们正在和另一个人聊天。Chatterbots已应用于在线互动游戏Tinymuds。一个单独的玩家可以在等待其他“真实”的玩家时与一个chatterbot进行互动。目前至少有一个公司正在制造一种产品,这种产品让你建立一个chatterbot以便用来掌握相关市场或关于你网站的其它问题。不难想象两个chatterbots互相交谈甚至互相交换关于自身的信息,如此一来,他们的对话将会变得更为复杂。(看看人工智能就会知道这个想法如果实现了会引起怎样的惊慌)。当然,他们可以使用更多普通的聊天缩略词
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值