Commit 886c1954 by hanccc

增加视频、表情、图片发送

1 parent 46ac3d11
...@@ -305,6 +305,11 @@ $robot->server->setCustomHandler(function(){ ...@@ -305,6 +305,11 @@ $robot->server->setCustomHandler(function(){
- [ ] 命令行操作信息发送 - [ ] 命令行操作信息发送
- [ ] 抽象消息 - [ ] 抽象消息
- [ ] 图片
- [ ] 视频
- [ ] 文字
- [ ] 语音
- [ ] 表情
- [ ] 群操作 - [ ] 群操作
- [ ] 创建群 - [ ] 创建群
...@@ -322,15 +327,17 @@ $robot->server->setCustomHandler(function(){ ...@@ -322,15 +327,17 @@ $robot->server->setCustomHandler(function(){
- [x] 增加消息集合存储 - [x] 增加消息集合存储
- [ ] 消息发送 - [x] 消息发送
- [x] 发送文字 - [x] 发送文字
- [ ] 发送图片 - [x] 发送图片
- [ ] 发送表情 - [x] 发送表情
- [x] 发送视频
- [ ] 消息存储 - [x] 消息存储
- [x] 语音 - [x] 语音
- [x] 图片 - [x] 图片
- [ ] 视频 - [x] 视频
- [x] 表情
- [ ] 消息处理 - [ ] 消息处理
- [x] 文字 - [x] 文字
......
...@@ -10,24 +10,38 @@ require_once __DIR__ . './../vendor/autoload.php'; ...@@ -10,24 +10,38 @@ require_once __DIR__ . './../vendor/autoload.php';
use Hanson\Robot\Foundation\Robot; use Hanson\Robot\Foundation\Robot;
use Hanson\Robot\Message\Message; use Hanson\Robot\Message\Message;
use Hanson\Robot\Support\Console; use Hanson\Robot\Message\Image;
use Hanson\Robot\Message\Text;
use Hanson\Robot\Message\Emoticon;
use Hanson\Robot\Message\Video;
$path = __DIR__ . '/./../tmp/';
$robot = new Robot([ $robot = new Robot([
'tmp' => __DIR__ . '/./../tmp/', 'tmp' => $path,
'debug' => true
]); ]);
$robot->server->setMessageHandler(function($message){ $robot->server->setMessageHandler(function($message) use ($path){
/** @var $message Message */ /** @var $message Message */
// 发送撤回消息 (排除自己) // 发送撤回消息 (排除自己)
if($message->type === 'Recall' && $message->rawMsg['FromUserName'] !== myself()->username ){ if($message->type === 'Recall' && $message->rawMsg['FromUserName'] !== myself()->username ){
// Message::send($message->content, $message->username); $msg = message()->get($message->msgId);
$message = message()->get($message->msgId); print_r($msg);
$nickname = $message['sender'] ? $message['sender']['NickName'] : account()->getAccount($message['username'])['NickName']; print_r($message->rawMsg);
$content = "{$nickname} 刚撤回了消息 " . $message['type'] === 'Text' ? "\"{$message['content']}\"" : null; $nickname = $msg['sender'] ? $msg['sender']['NickName'] : account()->getAccount($msg['username'])['NickName'];
if($message['type'] === 'Image'){ if($msg['type'] === 'Image'){
\Hanson\Robot\Message\Image::send($message->username, realpath(__DIR__ . "/./../tmp/jpg/{$message->msgId}.jpg")); Text::send($message->username, "{$nickname} 撤回了一张照片");
Image::send($message->username, realpath($path . "jpg/{$message->msgId}.jpg"));
}elseif($msg['type'] === 'Emoticon'){
Text::send($message->username, "{$nickname} 撤回了一个表情");
Emoticon::send($message->username, realpath($path . "gif/{$message->msgId}.gif"));
}elseif($msg['type'] === 'Video' || $msg['type'] === 'VideoCall'){
Text::send($message->username, "{$nickname} 撤回了一个视频");
Video::send($message->username, realpath($path . "mp4/{$message->msgId}.mp4"));
}elseif($msg['type'] === 'Voice'){
Text::send($message->username, "{$nickname} 撤回了一条语音");
}else{ }else{
return $content; Text::send($message->username, "{$nickname} 撤回了一条信息 \"{$msg['content']}\"");
} }
} }
......
...@@ -57,7 +57,7 @@ class Account ...@@ -57,7 +57,7 @@ class Account
$account = $account ? : static::$contact->get($username, null); $account = $account ? : static::$contact->get($username, null);
return $account ? : member()->get($username, null); return $account ? : member()->get($username, []);
} }
} }
\ No newline at end of file \ No newline at end of file
...@@ -43,7 +43,7 @@ class Contact extends Collection ...@@ -43,7 +43,7 @@ class Contact extends Collection
{ {
$contact = $this->get($id); $contact = $this->get($id);
return $contact ?? null; return $contact ?? [];
} }
/** /**
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
namespace Hanson\Robot\Core; namespace Hanson\Robot\Core;
use GuzzleHttp\Client as HttpClient; use GuzzleHttp\Client as HttpClient;
use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Cookie\FileCookieJar;
use Hanson\Robot\Support\Console; use Hanson\Robot\Support\Console;
class Http class Http
...@@ -19,6 +21,13 @@ class Http ...@@ -19,6 +21,13 @@ class Http
protected $client; protected $client;
/** /**
* @var FileCookieJar
*/
private $cookieJar;
private $cookieFile;
/**
* @return Http * @return Http
*/ */
public static function getInstance() public static function getInstance()
...@@ -68,17 +77,25 @@ class Http ...@@ -68,17 +77,25 @@ class Http
public function getClient() public function getClient()
{ {
if (!($this->client instanceof HttpClient)) { if (!($this->client instanceof HttpClient)) {
$this->client = new HttpClient(['cookies' => true]); $this->cookieFile = realpath(server()->config['tmp']) . '/cookie.txt';
$this->cookieJar = new FileCookieJar($this->cookieFile);
$this->client = new HttpClient(['cookies' => $this->cookieJar]);
} }
return $this->client; return $this->client;
} }
/**
* @param $url
* @param string $method
* @param array $options
* @return string
*/
public function request($url, $method = 'GET', $options = []) public function request($url, $method = 'GET', $options = [])
{ {
try{ try{
$response = $this->getClient()->request($method, $url, $options); $response = $this->getClient()->request($method, $url, $options);
$this->cookieJar->save($this->cookieFile);
return $response->getBody()->getContents(); return $response->getBody()->getContents();
}catch (\Exception $e){ }catch (\Exception $e){
Console::log('http链接失败:' . $e->getMessage()); Console::log('http链接失败:' . $e->getMessage());
......
...@@ -239,8 +239,8 @@ class Server ...@@ -239,8 +239,8 @@ class Server
if($result['BaseResponse']['Ret'] != 0){ if($result['BaseResponse']['Ret'] != 0){
// print_r($this->baseRequest); // print_r($this->baseRequest);
Console::log('init URL:'. $url); // Console::log('init URL:'. $url);
// throw new Exception('[ERROR] init fail!'); throw new Exception('[ERROR] init fail!');
} }
} }
......
<?php
/**
* Created by PhpStorm.
* User: HanSon
* Date: 2017/1/10
* Time: 16:51
*/
namespace Hanson\Robot\Message;
use Hanson\Robot\Core\Server;
use Hanson\Robot\Support\Console;
class Emoticon extends Message
{
use UploadAble;
public static function send($username, $file)
{
$response = static::uploadMedia($username, $file);
if(!$response){
Console::log("表情 {$file} 上传失败");
return false;
}
$mediaId = $response['MediaId'];
$url = sprintf(Server::BASE_URI . '/webwxsendemoticon?fun=sys&f=json&pass_ticket=%s' , server()->passTicket);
$data = [
'BaseRequest'=> server()->baseRequest,
'Msg'=> [
'Type'=> 47,
"EmojiFlag"=> 2,
'MediaId'=> $mediaId,
'FromUserName'=> myself()->username,
'ToUserName'=> $username,
'LocalID'=> time() * 1e4,
'ClientMsgId'=> time() * 1e4
]
];
$result = http()->json($url, $data, true);
if($result['BaseResponse']['Ret'] != 0){
Console::log('发送表情失败');
return false;
}
return true;
}
}
\ No newline at end of file \ No newline at end of file
...@@ -22,7 +22,7 @@ class Image extends Message ...@@ -22,7 +22,7 @@ class Image extends Message
$response = static::uploadMedia($username, $file); $response = static::uploadMedia($username, $file);
if(!$response){ if(!$response){
Console::log("文件 {$file} 发送失败"); Console::log("文件 {$file} 上传失败");
return false; return false;
} }
...@@ -42,8 +42,6 @@ class Image extends Message ...@@ -42,8 +42,6 @@ class Image extends Message
]; ];
$result = http()->json($url, $data, true); $result = http()->json($url, $data, true);
print_r($result);
if($result['BaseResponse']['Ret'] != 0){ if($result['BaseResponse']['Ret'] != 0){
Console::log('发送图片失败'); Console::log('发送图片失败');
return false; return false;
......
...@@ -189,15 +189,34 @@ class Message ...@@ -189,15 +189,34 @@ class Message
break; break;
case 43: case 43:
$this->type = 'VideoCall'; $this->type = 'VideoCall';
Console::log('video');
$url = Server::BASE_URI . sprintf('/webwxgetvideo?msgid=%s&skey=%s', $this->rawMsg['MsgId'], server()->skey);
$content = http()->request($url, 'get', [
'headers' => [
'Range' => 'bytes=0-'
]
]);
FileManager::download($this->rawMsg['MsgId'].'.mp4', $content, 'mp4');
break; break;
case 47: // 动画表情 case 47: // 动画表情
$this->type = 'Animation'; $this->type = 'Emoticon';
$this->content = Server::BASE_URI . sprintf('/webwxgetmsgimg?MsgID=%s&skey=%s', $this->rawMsg['MsgId'], server()->skey);
$content = http()->get($this->content);
FileManager::download($this->rawMsg['MsgId'].'.gif', $content, 'gif');
break; break;
case 49: case 49:
$this->type = 'Share'; $this->type = 'Share';
break; break;
case 62: case 62:
$this->type = 'Video'; $this->type = 'Video';
Console::log('video');
$url = Server::BASE_URI . sprintf('/webwxgetvideo?msgid=%s&skey=%s', $this->rawMsg['MsgId'], server()->skey);
$content = http()->request($url, 'get', [
'headers' => [
'Range' => 'bytes=0-'
]
]);
FileManager::download($this->rawMsg['MsgId'].'.mp4', $content, 'mp4');
break; break;
case 51: case 51:
$this->type = 'Init'; $this->type = 'Init';
...@@ -215,8 +234,6 @@ class Message ...@@ -215,8 +234,6 @@ class Message
case 10002: case 10002:
$this->type = 'Recall'; // 撤回 $this->type = 'Recall'; // 撤回
$this->msgId = $msgId = $this->parseMsgId($this->rawMsg['Content']); $this->msgId = $msgId = $this->parseMsgId($this->rawMsg['Content']);
// if($message['type'] === )
break; break;
default: default:
$this->type = 'Unknown'; $this->type = 'Unknown';
......
...@@ -9,11 +9,48 @@ ...@@ -9,11 +9,48 @@
namespace Hanson\Robot\Message; namespace Hanson\Robot\Message;
class Text use Hanson\Robot\Core\Server;
use Hanson\Robot\Support\Console;
class Text extends Message
{ {
public static function make($msg) /**
* 发送消息
*
* @param $word string 消息内容
* @param $username string 目标username
* @return bool
*/
public static function send($username, $word)
{ {
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' => $username,
'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 \ No newline at end of file
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
*/ */
namespace Hanson\Robot\Message; namespace Hanson\Robot\Message;
use Hanson\Robot\Core\Server;
use Hanson\Robot\Support\Console;
/** /**
...@@ -71,15 +73,64 @@ trait UploadAble ...@@ -71,15 +73,64 @@ trait UploadAble
return false; return false;
} }
public static function send($username, $file)
{
$response = static::uploadMedia($username, $file);
if(!$response){
Console::log("文件 {$file} 上传失败");
return false;
}
$mediaId = $response['MediaId'];
$url = sprintf(Server::BASE_URI . '/webwxsendappmsg?fun=async&f=json' , server()->passTicket);
$data = [
'BaseRequest'=> server()->baseRequest,
'Msg'=> [
'Type'=> 6,
'Content' => sprintf("<appmsg appid='wxeb7ec651dd0aefa9' sdkver=''><title>%s</title><des></des><action></action><type>6</type><content></content><url></url><lowurl></lowurl><appattach><totallen>%s</totallen><attachid>%s</attachid><fileext>%s</fileext></appattach><extinfo></extinfo></appmsg>", basename($file), filesize($file), $mediaId, end(explode('.', $file))),
'FromUserName'=> myself()->username,
'ToUserName'=> $username,
'LocalID'=> time() * 1e4,
'ClientMsgId'=> time() * 1e4
]
];
print_r($data);
$result = http()->json($url, $data, true);
if($result['BaseResponse']['Ret'] != 0){
Console::log('发送文件失败');
return false;
}
return true;
}
/**
* 获取媒体类型
*
* @param $file
* @return array
*/
private static function getMediaType($file) private static function getMediaType($file)
{ {
$info = finfo_open(FILEINFO_MIME_TYPE); $info = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($info, $file); $mime = finfo_file($info, $file);
finfo_close($info); finfo_close($info);
return [$mime, explode('/', $mime)[0] === 'image' ? 'pic' : 'doc']; $fileExplode = explode('.', $file);
$fileExtension = end($fileExplode);
return [$mime, $fileExtension === 'jpg' ? 'pic' : $fileExtension === 'mp4' ? 'video' : 'doc'];
} }
/**
* 获取cookie的ticket
*
* @return mixed
*/
private static function getTicket() private static function getTicket()
{ {
$cookies = http()->getClient()->getConfig('cookies')->toArray(); $cookies = http()->getClient()->getConfig('cookies')->toArray();
...@@ -89,6 +140,12 @@ trait UploadAble ...@@ -89,6 +140,12 @@ trait UploadAble
return $cookies[$key]['Value']; return $cookies[$key]['Value'];
} }
/**
* 把请求数组转为multipart模式
*
* @param $data
* @return array
*/
private static function dataToMultipart($data) private static function dataToMultipart($data)
{ {
$result = []; $result = [];
......
<?php
/**
* Created by PhpStorm.
* User: Hanson
* Date: 2017/1/13
* Time: 22:08
*/
namespace Hanson\Robot\Message;
use Hanson\Robot\Core\Server;
use Hanson\Robot\Support\Console;
class Video extends Message
{
use UploadAble;
public static function send($username, $file)
{
$response = static::uploadMedia($username, $file);
if(!$response){
Console::log("视频 {$file} 上传失败");
return false;
}
$mediaId = $response['MediaId'];
$url = sprintf(Server::BASE_URI . '/webwxsendvideomsg?fun=async&f=json&pass_ticket=%s' , server()->passTicket);
$data = [
'BaseRequest'=> server()->baseRequest,
'Msg'=> [
'Type'=> 43,
'MediaId'=> $mediaId,
'FromUserName'=> myself()->username,
'ToUserName'=> $username,
'LocalID'=> time() * 1e4,
'ClientMsgId'=> time() * 1e4
]
];
$result = http()->json($url, $data, true);
if($result['BaseResponse']['Ret'] != 0){
Console::log('发送视频失败');
return false;
}
return true;
}
}
\ No newline at end of file \ No newline at end of file
<?php
/**
* Created by PhpStorm.
* User: Hanson
* Date: 2017/1/13
* Time: 22:08
*/
namespace Hanson\Robot\Message;
class Voice extends Message
{
use UploadAble;
}
\ No newline at end of file \ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!