Commit 0871aa18 by hanccc

大重构

1 parent f92223ed
......@@ -18,6 +18,9 @@
"illuminate/support": "^5.3"
},
"autoload": {
"files": [
"src/Support/helpers.php"
],
"psr-4": {
"Hanson\\Robot\\": "src/"
}
......
......@@ -10,11 +10,11 @@ namespace Hanson\Robot\Collections;
use Hanson\Robot\Core\Server;
use Hanson\Robot\Support\Log;
use Hanson\Robot\Support\Console;
class ContactFactory
{
protected $server;
// protected $server;
const SPECIAL_USERS = ['newsapp', 'fmessage', 'filehelper', 'weibo', 'qqmail',
'fmessage', 'tmessage', 'qmessage', 'qqsync', 'floatbottle',
......@@ -25,18 +25,17 @@ class ContactFactory
'officialaccounts', 'notification_messages', 'wxid_novlwrv3lqwv11',
'gh_22b87fa7cb3c', 'wxitil', 'userexperience_alarm', 'notification_messages'];
public function __construct(Server $server)
public function __construct()
{
$this->server = $server;
$this->getContacts();
}
public function getContacts()
{
$url = sprintf(Server::BASE_URI . '/webwxgetcontact?pass_ticket=%s&skey=%s&r=%s', $this->server->passTicket, $this->server->skey, time());
$url = sprintf(Server::BASE_URI . '/webwxgetcontact?pass_ticket=%s&skey=%s&r=%s', server()->passTicket, server()->skey, time());
$content = $this->server->http->json($url, [
'BaseRequest' => $this->server->baseRequest
$content = http()->json($url, [
'BaseRequest' => server()->baseRequest
], true);
// file_put_contents($this->server->config['tmp'] . 'debug.json', json_encode($content));
......@@ -68,11 +67,11 @@ class ContactFactory
}
$this->getBatchGroupMembers();
file_put_contents($this->server->config['tmp'] . 'account.json', json_encode(Account::getInstance()->all()));
file_put_contents($this->server->config['tmp'] . 'OfficialAccount.json', json_encode(OfficialAccount::getInstance()->all()));
file_put_contents($this->server->config['tmp'] . 'SpecialAccount.json', json_encode(SpecialAccount::getInstance()->all()));
file_put_contents($this->server->config['tmp'] . 'GroupAccount.json', json_encode(GroupAccount::getInstance()->all()));
file_put_contents($this->server->config['tmp'] . 'ContactAccount.json', json_encode(ContactAccount::getInstance()->all()));
file_put_contents(server()->config['tmp'] . 'account.json', json_encode(Account::getInstance()->all()));
file_put_contents(server()->config['tmp'] . 'OfficialAccount.json', json_encode(OfficialAccount::getInstance()->all()));
file_put_contents(server()->config['tmp'] . 'SpecialAccount.json', json_encode(SpecialAccount::getInstance()->all()));
file_put_contents(server()->config['tmp'] . 'GroupAccount.json', json_encode(GroupAccount::getInstance()->all()));
file_put_contents(server()->config['tmp'] . 'ContactAccount.json', json_encode(ContactAccount::getInstance()->all()));
}
/**
......@@ -80,7 +79,7 @@ class ContactFactory
*/
public function getBatchGroupMembers()
{
$url = sprintf(Server::BASE_URI . '/webwxbatchgetcontact?type=ex&r=%s&pass_ticket=%s', time(), $this->server->passTicket);
$url = sprintf(Server::BASE_URI . '/webwxbatchgetcontact?type=ex&r=%s&pass_ticket=%s', time(), server()->passTicket);
$list = [];
GroupAccount::getInstance()->each(function($item, $key) use (&$list){
......@@ -93,8 +92,8 @@ class ContactFactory
// 'List' => $list
// ]));
$content = $this->server->http->json($url, [
'BaseRequest' => $this->server->baseRequest,
$content = http()->json($url, [
'BaseRequest' => server()->baseRequest,
'Count' => GroupAccount::getInstance()->count(),
'List' => $list
], true);
......
......@@ -13,8 +13,23 @@ use GuzzleHttp\Client as HttpClient;
class Http
{
static $instance;
protected $client;
/**
* @return Http
*/
public static function getInstance()
{
if(!static::$instance){
echo 'http is null';
static::$instance = new Http();
}
return static::$instance;
}
public function get($url, array $options = [])
{
$query = $options ? ['query' => $options] : [];
......
......@@ -11,7 +11,7 @@ namespace Hanson\Robot\Core;
use Closure;
use Hanson\Robot\Collections\Account;
use Hanson\Robot\Message\Message;
use Hanson\Robot\Support\Log;
use Hanson\Robot\Support\Console;
class MessageHandler
{
......@@ -23,29 +23,15 @@ class MessageHandler
static $instance = null;
const MESSAGE_MAP = [
2 => 'text', // 新消息
3 => 'unknown', // 未知
4 => 'contactUpdate', // 通讯录更新
6 => 'money', // 可能是红包
7 => 'mobile' // 手机上操作了微信
];
public function __construct(Server $server)
{
$this->server = $server;
}
/**
* get a message handler single instance
*
* @param Server $server
* @return MessageHandler
*/
public static function getInstance($server = null)
public static function getInstance()
{
if(static::$instance === null){
static::$instance = new MessageHandler($server);
static::$instance = new MessageHandler();
}
return static::$instance;
......@@ -81,7 +67,6 @@ class MessageHandler
$this->checkTime($time);
}
// call_user_func_array($this->handler, []);
}
private function handlerMessage($selector)
......@@ -108,14 +93,13 @@ class MessageHandler
}
$random = strval(time() * 1000) . '0' . strval(rand(100, 999));
echo $word;
$result = $this->server->http->post(Server::BASE_URI . '/webwxsendmsg?pass_ticket=' . $this->server->passTicket,
$result = http()->post(Server::BASE_URI . '/webwxsendmsg?pass_ticket=' . server()->passTicket,
json_encode([
'BaseRequest' => $this->server->baseRequest,
'BaseRequest' => server()->baseRequest,
'Msg' => [
'Type' => 1,
'Content' => $word,
'FromUserName' => $this->server->getMyAccount(),
'FromUserName' => myself()->userName,
'ToUserName' => $content->rawMsg['FromUserName'],
'LocalID' => $random,
'ClientMsgId' => $random,
......@@ -124,7 +108,7 @@ class MessageHandler
], JSON_UNESCAPED_UNICODE), true);
if($result['BaseResponse']['Ret'] != 0){
Log::echo('发送消息失败');
Console::log('发送消息失败');
}
}
......@@ -137,16 +121,16 @@ class MessageHandler
{
$url = 'https://' . $this->syncHost . '/cgi-bin/mmwebwx-bin/synccheck?' . http_build_query([
'r' => time(),
'sid' => $this->server->sid,
'uin' => $this->server->uin,
'skey' => $this->server->skey,
'deviceid' => $this->server->deviceId,
'synckey' => $this->server->syncKeyStr,
'sid' => server()->sid,
'uin' => server()->uin,
'skey' => server()->skey,
'deviceid' => server()->deviceId,
'synckey' => server()->syncKeyStr,
'_' => time()
]);
try{
$content = $this->server->http->get($url);
$content = http()->get($url);
preg_match('/window.synccheck=\{retcode:"(\d+)",selector:"(\d+)"\}/', $content, $matches);
......@@ -177,12 +161,12 @@ class MessageHandler
private function sync()
{
$url = sprintf(Server::BASE_URI . '/webwxsync?sid=%s&skey=%s&lang=en_US&pass_ticket=%s', $this->server->sid, $this->server->skey, $this->server->passTicket);
$url = sprintf(Server::BASE_URI . '/webwxsync?sid=%s&skey=%s&lang=en_US&pass_ticket=%s', server()->sid, server()->skey, server()->passTicket);
try{
$result = $this->server->http->json($url, [
'BaseRequest' => $this->server->baseRequest,
'SyncKey' => $this->server->syncKey,
$result = http()->json($url, [
'BaseRequest' => server()->baseRequest,
'SyncKey' => server()->syncKey,
'rr' => ~time()
], true);
......@@ -203,15 +187,15 @@ class MessageHandler
*/
private function generateSyncKey($result)
{
$this->server->syncKey = $result['SyncKey'];
server()->syncKey = $result['SyncKey'];
$syncKey = [];
foreach ($this->server->syncKey['List'] as $item) {
foreach (server()->syncKey['List'] as $item) {
$syncKey[] = $item['Key'] . '_' . $item['Val'];
}
$this->server->syncKeyStr = implode('|', $syncKey);
server()->syncKeyStr = implode('|', $syncKey);
}
/**
......@@ -237,7 +221,7 @@ class MessageHandler
*/
private function debugMessage($retCode, $selector, $sleep = null)
{
Log::echo('[DEBUG] retcode:' . $retCode . ' selector:' . $selector);
Console::log('[DEBUG] retcode:' . $retCode . ' selector:' . $selector);
if($sleep){
sleep($sleep);
......
<?php
/**
* Created by PhpStorm.
* User: Hanson
* Date: 2017/1/3
* Time: 21:54
*/
namespace Hanson\Robot\Core;
class Myself
{
static $instance;
public $nickname;
public $userName;
public $uin;
public $sex;
public static function getInstance()
{
if(!static::$instance){
static::$instance = new Myself();
}
return static::$instance;
}
public function init($user)
{
$this->nickname = $user['NickName'];
$this->userName = $user['UserName'];
$this->sex = $user['Sex'];
$this->uin= $user['Uin'];
}
}
\ No newline at end of file
......@@ -14,13 +14,15 @@ use GuzzleHttp\Client;
use Hanson\Robot\Collections\Account;
use Hanson\Robot\Collections\ContactFactory;
use Hanson\Robot\Collections\GroupAccount;
use Hanson\Robot\Support\Log;
use Hanson\Robot\Support\Console;
use QueryPath\Exception;
use Symfony\Component\DomCrawler\Crawler;
class Server
{
static $instance;
protected $uuid;
protected $redirectUri;
......@@ -39,12 +41,8 @@ class Server
public $syncKey;
static $myAccount;
public $syncKeyStr;
public $http;
public $config;
public $messageHandler;
......@@ -57,23 +55,35 @@ class Server
public function __construct($config = [])
{
$this->http = new Http();
$this->config = $config;
}
/**
* @param array $config
* @return Server
*/
public static function getInstance($config = [])
{
if(!static::$instance){
static::$instance = new Server($config);
}
return static::$instance;
}
/**
* start a wechat trip
*/
public function run()
{
$this->prepare();
$this->init();
Log::echo('[INFO] init success!');
Console::log('[INFO] init success!');
$this->statusNotify();
Log::echo('[INFO] begin to init contacts');
Console::log('[INFO] begin to init contacts');
$this->initContact();
Log::echo('[INFO] init contacts success!');
Console::log('[INFO] init contacts success!');
MessageHandler::getInstance()->listen();
}
......@@ -82,11 +92,11 @@ class Server
{
$this->getUuid();
$this->generateQrCode();
Log::echo('[INFO] please scan qrcode to login');
Console::log('[INFO] please scan qrcode to login');
$this->waitForLogin();
$this->login();
Log::echo('[INFO] login success!');
Console::log('[INFO] login success!');
}
/**
......@@ -96,7 +106,7 @@ class Server
*/
protected function getUuid()
{
$content = $this->http->get('https://login.weixin.qq.com/jslogin', [
$content = http()->get('https://login.weixin.qq.com/jslogin', [
'appid' => 'wx782c26e4c19acffb',
'fun' => 'new',
'lang' => 'zh_CN',
......@@ -143,14 +153,14 @@ class Server
while($retryTime > 0){
$url = sprintf('https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=%s&uuid=%s&_=%s', $tip, $this->uuid, time());
$content = $this->http->get($url);
$content = http()->get($url);
preg_match('/window.code=(\d+);/', $content, $matches);
$code = $matches[1];
switch($code){
case '201':
Log::echo('[INFO] please confirm to login');
Console::log('[INFO] please confirm to login');
$tip = 0;
break;
case '200':
......@@ -158,13 +168,13 @@ class Server
$this->redirectUri = $matches[1] . '&fun=new';
return;
case '408':
Log::echo('[ERROR] login timeout. please try 1 second later.');
Console::log('[ERROR] login timeout. please try 1 second later.');
$tip = 1;
$retryTime -= 1;
sleep(1);
break;
default:
Log::echo("[ERROR] login fail. exception code:$code . please try 1 second later.");
Console::log("[ERROR] login fail. exception code:$code . please try 1 second later.");
$tip = 1;
$retryTime -= 1;
sleep(1);
......@@ -182,7 +192,7 @@ class Server
*/
public function login()
{
$content = $this->http->get($this->redirectUri);
$content = http()->get($this->redirectUri);
$crawler = new Crawler($content);
$this->skey = $crawler->filter('error skey')->text();
......@@ -210,18 +220,19 @@ class Server
{
$url = sprintf(self::BASE_URI . '/webwxinit?r=%i&lang=en_US&pass_ticket=%s', time(), $this->passTicket);
$content = $this->http->json($url, [
$content = http()->json($url, [
'BaseRequest' => $this->baseRequest
]);
$result = json_decode($content, true);
$this->generateSyncKey($result);
static::$myAccount = $result['User'];
myself()->init($result['User']);
$this->initContactList($result['ContactList']);
if($result['BaseResponse']['Ret'] != 0){
// Log::echo('init fail!');
throw new Exception('[ERROR] init fail!');
}
}
......@@ -240,7 +251,7 @@ class Server
protected function initContact()
{
new ContactFactory($this);
new ContactFactory();
}
/**
......@@ -250,11 +261,11 @@ class Server
{
$url = sprintf(self::BASE_URI . '/webwxstatusnotify?lang=zh_CN&pass_ticket=%s', $this->passTicket);
$this->http->json($url, [
http()->json($url, [
'BaseRequest' => $this->baseRequest,
'Code' => 3,
'FromUserName' => static::$myAccount['UserName'],
'ToUserName' => static::$myAccount['UserName'],
'FromUserName' => myself()->userName,
'ToUserName' => myself()->userName,
'ClientMsgId' => time()
]);
}
......@@ -272,23 +283,13 @@ class Server
$this->syncKeyStr = implode('|', $syncKey);
}
public static function isMyself($fromUserName)
{
return $fromUserName === static::$myAccount['UserName'];
}
public function getMyAccount()
{
return static::$myAccount['UserName'];
}
public function setMessageHandler(\Closure $closure)
{
if(!is_callable($closure)){
throw new \Exception('[ERROR] message handler must be a closure!');
}
MessageHandler::getInstance($this)->setMessageHandler($closure);
MessageHandler::getInstance()->setMessageHandler($closure);
}
public function debug($debug = true)
......
......@@ -10,9 +10,15 @@ namespace Hanson\Robot\Foundation;
use Hanson\Robot\Core\Http;
use Hanson\Robot\Core\Server;
use Illuminate\Support\Collection;
use Pimple\Container;
/**
* Class Robot
* @package Hanson\Robot\Foundation
* @property Server $server
*/
class Robot extends Container
{
......
......@@ -14,11 +14,7 @@ class ServerServiceProvider implements ServiceProviderInterface
public function register(Container $pimple)
{
$pimple['server'] = function ($pimple) {
$server = new Server($pimple['config']);
$server->debug($pimple['config']['debug']);
return $server;
return server($pimple['config']);
};
}
}
......@@ -16,6 +16,8 @@ use Hanson\Robot\Collections\OfficialAccount;
use Hanson\Robot\Collections\SpecialAccount;
use Hanson\Robot\Models\Content;
use Hanson\Robot\Models\Sender;
use Hanson\Robot\Support\FileManager;
use Hanson\Robot\Support\Console;
class Message
{
......@@ -64,20 +66,12 @@ class Message
public function make($selector, $msg)
{
$this->rawMsg = $msg;
// $this->sender = new Sender();
// $this->content = new Content();
// $this->setSender();
$this->setFrom();
$this->setTo();
// $this->setContent();
$this->setFromType();
$this->setType();
......@@ -104,7 +98,7 @@ class Message
$this->FromType = 'System';
} elseif ($this->rawMsg['MsgType'] == 37) {
$this->FromType = 'FriendRequest';
} elseif (Server::isMyself($this->rawMsg['FromUserName'])) {
} elseif ($this->rawMsg['FromUserName'] === myself()->userName) {
$this->FromType = 'Self';
} elseif ($this->rawMsg['ToUserName'] === 'filehelper') {
$this->FromType = 'FileHelper';
......@@ -123,9 +117,7 @@ class Message
private function setType()
{
// $msgType = $msg['MsgType'];
$this->rawMsg['Content'] = html_entity_decode($this->rawMsg['Content']);
// $msgId = $msg['MsgId'];
$this->setTypeByFrom();
......@@ -155,23 +147,30 @@ class Message
switch($this->rawMsg['MsgType']){
case 1:
if(Location::isLocation($this->rawMsg['Content'])){
// $this->setLocationMessage();
$this->type = 'Location';
}else{
$this->type = 'Text';
$this->content = $this->rawMsg['Content'];
}
break;
case 3:
$this->type = 'Image';
$this->content = Server::BASE_URI . sprintf('/webwxgetmsgimg?MsgID=%s&skey=%s', $this->rawMsg['MsgId'], server()->skey);
$content = http()->get($this->content);
FileManager::download(server()->config['tmp'] . $this->rawMsg['MsgId'] . '.jpg', $content);
break;
case 34:
$this->type = 'Voice';
$this->content = Server::BASE_URI . sprintf('/webwxgetvoice?msgid=%s&skey=%s', $this->rawMsg['MsgId'], server()->skey);
$content = http()->get($this->content);
FileManager::download(server()->config['tmp'] . $this->rawMsg['MsgId'] . '.mp3', $content);
break;
case 37:
$this->type = 'AddUser';
break;
case 42:
$this->type = 'Recommend';
$this->content = (object)$this->rawMsg['RecommendInfo'];
break;
case 47:
$this->type = 'Animation';
......@@ -227,4 +226,43 @@ class Message
return str_replace('<br/>', '\n', $content);
}
/**
* 发送消息
*
* @param $word string 消息内容
* @param $fromUser string 目标username
* @return bool
*/
public static function send($word, $fromUser)
{
if(!$word && !is_string($word)){
return false;
}
$random = strval(time() * 1000) . '0' . strval(rand(100, 999));
$data = [
'BaseRequest' => server()->baseRequest,
'Msg' => [
'Type' => 1,
'Content' => $word,
'FromUserName' => myself()->userName,
'ToUserName' => $fromUser,
'LocalID' => $random,
'ClientMsgId' => $random,
],
'Scene' => 0
];
$result = http()->post(Server::BASE_URI . '/webwxsendmsg?pass_ticket=' . server()->passTicket,
json_encode($data, JSON_UNESCAPED_UNICODE), true
);
if($result['BaseResponse']['Ret'] != 0){
Console::log('发送消息失败');
return false;
}
return true;
}
}
\ No newline at end of file
......@@ -9,10 +9,10 @@
namespace Hanson\Robot\Support;
class Log
class Console
{
public static function echo($str)
public static function log($str)
{
echo $str . PHP_EOL;
}
......
<?php
/**
* Created by PhpStorm.
* User: Hanson
* Date: 2017/1/2
* Time: 22:21
*/
namespace Hanson\Robot\Support;
class FileManager
{
public static function download($name, $data)
{
file_put_contents($name, $data);
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: Hanson
* Date: 2016/12/29
* Time: 0:10
*/
use Hanson\Robot\Core\Server;
use Hanson\Robot\Core\Myself;
use Hanson\Robot\Core\Http;
if (! function_exists('server')) {
/**
* Get the available container instance.
*
* @param array $config
* @return Server
*/
function server($config = [])
{
return Server::getInstance($config);
}
}
if (! function_exists('myself')) {
/**
* Get the available container instance.
*
* @return Myself
*/
function myself()
{
return Myself::getInstance();
}
}
if (! function_exists('http')) {
/**
* Get the available container instance.
*
* @return Http
*/
function http()
{
return Http::getInstance();
}
}
\ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: HanSon
* Date: 2016/12/7
* Time: 16:33
*/
require_once __DIR__ . './../vendor/autoload.php';
$robot = new \Hanson\Robot\Foundation\Robot([
'tmp' => realpath('./tmp') . '/',
'debug' => true,
]);
$client = new \GuzzleHttp\Client();
$robot->server->setMessageHandler(function($message) use ($client, $robot){
if($message->type === 'Text'){
// print_r($message);
// echo $message->rawMsg['FromUserName'];
\Hanson\Robot\Message\Message::send('hi', $message->rawMsg['FromUserName']);
}
});
$robot->server->run();
......@@ -16,15 +16,16 @@ $robot = new \Hanson\Robot\Foundation\Robot([
$client = new \GuzzleHttp\Client();
$robot->server->setMessageHandler(function($message) use ($client, $robot){
if($message->type === 'Text'){
$url = 'http://www.tuling123.com/openapi/api';
$result = $robot->server->http->post($url, [
'key' => '1dce02aef026258eff69635a06b0ab7d',
'info' => $message->rawMsg['Content']
'info' => $message->content
], true);
print_r($message);
print_r($result);
return $result['text'];
}
});
$robot->server->run();
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!