1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the slince/smartqq package. |
5
|
|
|
* |
6
|
|
|
* (c) Slince <[email protected]> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Slince\SmartQQ; |
13
|
|
|
|
14
|
|
|
|
15
|
|
|
use GuzzleHttp\Exception\ConnectException; |
16
|
|
|
use Slince\EventDispatcher\DispatcherInterface; |
17
|
|
|
use Slince\EventDispatcher\Event; |
18
|
|
|
use Slince\SmartQQ\Exception\InvalidArgumentException; |
19
|
|
|
use Slince\SmartQQ\Exception\ResponseException; |
20
|
|
|
use Slince\SmartQQ\Exception\RuntimeException; |
21
|
|
|
|
22
|
|
|
class MessageHandler |
23
|
|
|
{ |
24
|
|
|
/** |
25
|
|
|
* 事件名,当收到消息时触发. |
26
|
|
|
* |
27
|
|
|
* @var string |
28
|
|
|
*/ |
29
|
|
|
const EVENT_MESSAGE = 'message'; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @var Client |
33
|
|
|
*/ |
34
|
|
|
protected $client; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* @var DispatcherInterface |
38
|
|
|
*/ |
39
|
|
|
protected $eventDispatcher; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* 可以被忽略的状态码. |
43
|
|
|
* |
44
|
|
|
* @var array |
45
|
|
|
*/ |
46
|
|
|
protected static $ignoredCodes = [ |
47
|
|
|
0, 100003, 100100, 100012 |
48
|
|
|
]; |
49
|
|
|
|
50
|
|
|
public function __construct(Client $client) |
51
|
|
|
{ |
52
|
|
|
$this->client = $client; |
53
|
|
|
$this->eventDispatcher = $client->getEventDispatcher(); |
54
|
|
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* 绑定消息处理回调 |
58
|
|
|
* |
59
|
|
|
* ```php |
60
|
|
|
* $handler->onMessage(function(Slince\SmartQQ\Message\Response\Message $message){ |
61
|
|
|
* //... |
62
|
|
|
* }); |
63
|
|
|
* ``` |
64
|
|
|
* |
65
|
|
|
* @param callable $handler |
66
|
|
|
*/ |
67
|
|
|
public function onMessage($handler) |
68
|
|
|
{ |
69
|
|
|
if (!is_callable($handler)) { |
70
|
|
|
throw new InvalidArgumentException('Message handler should be callable.'); |
71
|
|
|
} |
72
|
|
|
$this->eventDispatcher->addListener(static::EVENT_MESSAGE, function(Event $event) use ($handler){ |
73
|
|
|
$handler($event->getArgument('message')); |
74
|
|
|
}); |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* 开始监听客户端消息 |
79
|
|
|
*/ |
80
|
|
|
public function listen() |
81
|
|
|
{ |
82
|
|
|
while (true) { |
83
|
|
|
try { |
84
|
|
|
$messages = $this->client->pollMessages(); |
85
|
|
|
if ($messages) { |
|
|
|
|
86
|
|
|
foreach ($messages as $message) { |
87
|
|
|
// 收到消息时触发事件 |
88
|
|
|
$event = new Event(static::EVENT_MESSAGE, null, [ |
89
|
|
|
'message' => $message |
90
|
|
|
]); |
91
|
|
|
$this->eventDispatcher->dispatch($event); |
92
|
|
|
} |
93
|
|
|
} else { |
94
|
|
|
//延缓2秒 |
95
|
|
|
usleep(2000000); |
96
|
|
|
} |
97
|
|
|
} catch (ResponseException $exception) { |
98
|
|
|
if (in_array($exception->getCode(), static::$ignoredCodes)) { |
99
|
|
|
$this->testLogin(); |
100
|
|
|
} |
101
|
|
|
} catch (ConnectException $exception) { |
102
|
|
|
usleep(2000000); |
103
|
|
|
} |
104
|
|
|
} |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* 测试登录 |
109
|
|
|
*/ |
110
|
|
|
protected function testLogin() |
111
|
|
|
{ |
112
|
|
|
try { |
113
|
|
|
$this->client->getFriendsOnlineStatus(); |
114
|
|
|
} catch (ResponseException $exc) { |
115
|
|
|
//登录凭证可能失效 |
116
|
|
|
throw new RuntimeException('The credential may be expired, please login again.', $exc->getCode()); |
117
|
|
|
} |
118
|
|
|
} |
119
|
|
|
} |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.