10 protected WebSocket\Client
$connection;
15 public function __construct(string $uri, string $api_login, array $options = null)
17 $context = $options["context"] ?? stream_context_create();
19 if (isset($options["tls_verify"]) && !$options["tls_verify"]) {
20 stream_context_set_option($context, 'ssl', 'verify_peer', false);
21 stream_context_set_option($context, 'ssl', 'verify_peer_name', false);
24 $this->connection
= new WebSocket\
Client($uri, [
25 'context' => $context,
27 'Authorization' => sprintf('Basic %s', base64_encode($api_login)),
32 /* Start the connection now */
33 $this->connection
->ping();
37 * Encode and send a query to the RPC server.
39 * @note I'm not sure on the response type except that it may be either an object or array.
41 * @param string $method
42 * @param array|null $params
44 * @return object|array|bool
47 public function query(string $method, array|null $params = null): object|array|bool
49 $id = random_int(1, 99999);
58 $json_rpc = json_encode($rpc);
59 $this->connection
->text($json_rpc);
62 $reply = $this->connection
->receive();
64 $reply = json_decode($reply);
66 if (property_exists($reply, 'result')) {
67 /* Possibly we are streaming log events, then ignore this event
68 * NOTE: This does mean that this event is "lost"
70 if ($id !== $reply->id
)
74 return $reply->result
;
77 if (property_exists($reply, 'error')) {
78 $this->errno
= $reply->error
->code
;
79 $this->error
= $reply->error
->message
;
84 /* This should never happen */
85 throw new Exception('Invalid JSON-RPC response from UnrealIRCd: not an error and not a result.');
89 * Grab and/or wait for next event. Used for log streaming.
90 * @note This function will return NULL after a 10 second timeout,
91 * this so the function is not entirely blocking. You can safely
92 * retry the operation if the return value === NULL.
94 * @return object|array|bool|null
97 public function eventloop(): object|array|bool|null
99 $starttime = microtime(true);
101 $reply = $this->connection
->receive();
102 } catch (WebSocket\TimeoutException
$e) {
103 if (microtime(true) - $starttime < 1)
105 /* There's some bug in the library: if we
106 * caught the timeout exception once (so
107 * harmless) and then later the server gets
108 * killed or closes the connection otherwise,
109 * then it will again throw WebSocket\TimeoutException
110 * even though it has nothing to do with timeouts.
111 * We detect this by checking if the timeout
112 * took less than 1 second, then we know for sure
113 * that it wasn't really a timeout (since the
114 * timeout is normally 10 seconds).
121 $reply = json_decode($reply);
123 if (property_exists($reply, 'result')) {
126 return $reply->result
;
129 /* This would be weird */
130 if (property_exists($reply, 'error')) {
131 $this->errno
= $reply->error
->code
;
132 $this->error
= $reply->error
->message
;
136 /* This should never happen */
137 throw new Exception('Invalid JSON-RPC data from UnrealIRCd: not an error and not a result.');
140 public function rpc(): Rpc
142 return new Rpc($this);
145 public function stats(): Stats
147 return new Stats($this);
150 public function user(): User
152 return new User($this);
155 public function channel(): Channel
157 return new Channel($this);
160 public function serverban(): ServerBan
162 return new ServerBan($this);
165 public function spamfilter(): Spamfilter
167 return new Spamfilter($this);
170 public function nameban(): NameBan
172 return new NameBan($this);
175 public function server(): Server
177 return new Server($this);
180 public function serverbanexception(): ServerBanException
182 return new ServerBanException($this);
185 public function log(): Log
187 return new Log($this);