├── .gitignore
├── LICENSE
├── README.md
├── app
├── Controller
│ ├── Controller.php
│ └── RoomController.php
├── Lib
│ └── Log.php
├── WebSocket.php
└── view
│ ├── index.view.php
│ ├── js.view.php
│ └── room.view.php
├── bootstrap
└── app.php
├── composer.json
├── composer.lock
├── config
├── config.php
└── session.php
├── handle.php
├── log
└── .gitignore
├── public
├── .gitignore
├── css
│ ├── OwO.css
│ ├── chat.css
│ └── s.css
├── img
│ └── header_bg.png
├── index.php
├── js
│ ├── OwO.js
│ ├── OwO.json
│ └── Reconnect.js
└── robots.txt
├── route
└── web.php
├── run.php
└── start_chat.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea/*
3 | vendor/
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 flxxyz
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # php-chat-websocket
2 |
3 | 这是一个基础聊天室,使用session区分各个用户,使用identicon来做随机头像
4 |
5 | ps:不清楚identicon的可以看看[identicon wiki][1]
6 |
7 | ## Init
8 | 依次执行下面命令
9 | ```shell
10 | git clone https://github.com/flxxyz/php-chat-websocket.git && cd php-chat-websocket
11 | composer update --no-dev
12 | ```
13 |
14 | ## Usage
15 | 1. 修改 `config/config.php` 4行
16 | ```php
17 | 'url' => 'http://domain/', //保留最后的斜杠
18 | ```
19 |
20 | 2. 修改`app/view/js.view.php` **155行**为websocket链接🔗
21 | ```javascript
22 | var socket = new ReconnectingWebSocket('ws://你的域名:9501', null, {debug: false, reconnectInterval: 2000, timeoutInterval: 3000});
23 | ```
24 |
25 | 3. 自定义ip端口号
26 | ```php
27 | Chat::run('自定义ip', '自定义端口号');
28 | ```
29 |
30 | 4. 开启websocket服务器
31 | ```shell
32 | php run.php // 同步检查控制台输出信息
33 | ```
34 |
35 | 如需要后台挂起服务看这里↓
36 | ```shell
37 | chmod +x start_chat.sh
38 | ./start_chat.sh
39 | ```
40 |
41 | 5. 伪静态设置
42 | nginx和apache需要设置伪静态规则,在这里只提供nginx的规则,apache不熟
43 | ```
44 | location / {
45 | try_files $uri $uri/ /index.php$is_args$query_string;
46 | }
47 | ```
48 |
49 |
50 | ## Route
51 | | 路径 | 说明 |
52 | |:--- |:--- |
53 | | / | 首页界面 |
54 | | /logout | 注销当前登陆用户 |
55 | | /room | 房间界面 |
56 |
57 |
58 |
59 | [1]: http://en.wikipedia.org/wiki/Identicon
--------------------------------------------------------------------------------
/app/Controller/Controller.php:
--------------------------------------------------------------------------------
1 | id = session_id();
18 | $this->config = config('config');
19 |
20 | session()->reset();
21 | }
22 |
23 | public function request()
24 | {
25 | return new Request;
26 | }
27 |
28 | public function json(string $msg = '', int $code = 200, $result = [])
29 | {
30 | $data = [
31 | 'message' => $msg,
32 | 'code' => $code,
33 | ];
34 |
35 | if ($code === 200) {
36 | $data['data'] = $result;
37 | }
38 |
39 | exit(json($data));
40 | }
41 | }
--------------------------------------------------------------------------------
/app/Controller/RoomController.php:
--------------------------------------------------------------------------------
1 | get('id')) && is_null(session()->get('name')) && is_null(session()->get('sex')) && is_null(session()->get('icon'))) {
11 | //redirect($this->config['url']);
12 | }
13 |
14 | view('index');
15 | }
16 |
17 | public function login() {
18 | $query = $this->request()->query;
19 | session()->set(['id' => mt_rand(1000, 1999)]);
20 | session()->set(['name' => $query['username']]);
21 | session()->set(['sex' => $query['sex']]);
22 |
23 | $identicon = new Identicon();
24 | //$identicon->displayImage($this->session->name);
25 | //$imageData = $identicon->getImageData('bar');
26 | $imageDataUri = $identicon->getImageDataUri(session()->get('name'));
27 |
28 | session()->set(['icon' => $imageDataUri]);
29 |
30 | redirect($this->config['url'] . 'room');
31 | }
32 |
33 | public function logout() {
34 | unset($_SESSION['id']);
35 | unset($_SESSION['name']);
36 | unset($_SESSION['sex']);
37 | unset($_SESSION['icon']);
38 |
39 | sleep(1);
40 | redirect($this->config['url']);
41 | }
42 |
43 | public function room() {
44 | if(is_null(session()->get('id')) && is_null(session()->get('name')) && is_null(session()->get('sex')) && is_null(session()->get('icon'))) {
45 | return redirect($this->config['url']);
46 | }
47 |
48 | view('room', [
49 | 'user' => [
50 | 'id' => session()->get('id'),
51 | 'name' => session()->get('name'),
52 | 'sex' => session()->get('sex'),
53 | 'icon' => session()->get('icon'),
54 | ],
55 | ]);
56 | }
57 | }
--------------------------------------------------------------------------------
/app/Lib/Log.php:
--------------------------------------------------------------------------------
1 | pushHandler(new StreamHandler('log/' . $channel . '.log'), Logger::INFO);
21 | $log->info($message, $param);
22 | }
23 |
24 | /**
25 | * 输出notice类型消息
26 | * @param string $channel
27 | * @param string $message
28 | * @param array $param
29 | */
30 | static function notice(string $channel, string $message, array $param = [])
31 | {
32 | echo self::message('NOTICE', $message, $param);
33 | $log = new Logger($channel);
34 | $log->pushHandler(new StreamHandler('log/' . $channel . '.log'), Logger::NOTICE);
35 | $log->notice($message, $param);
36 | }
37 |
38 | /**
39 | * 输出debug类型消息
40 | * @param string $channel
41 | * @param string $message
42 | * @param array $param
43 | */
44 | static function debug(string $channel, string $message, array $param = [])
45 | {
46 | echo self::message('DEBUG', $message, $param);
47 | $log = new Logger($channel);
48 | $log->pushHandler(new StreamHandler('log/' . $channel . '.log'), Logger::DEBUG);
49 | $log->debug($message, $param);
50 | }
51 |
52 | /**
53 | * 输出warn类型消息
54 | * @param string $channel
55 | * @param string $message
56 | * @param array $param
57 | */
58 | static function warn(string $channel, string $message, array $param = [])
59 | {
60 | echo self::message('WARNING', $message, $param);
61 | $log = new Logger($channel);
62 | $log->pushHandler(new StreamHandler('log/' . $channel . '.log'), Logger::WARNING);
63 | $log->warn($message, $param);
64 | }
65 |
66 | /**
67 | * 输出err类型消息
68 | * @param string $channel
69 | * @param string $message
70 | * @param array $param
71 | */
72 | static function err(string $channel, string $message, array $param = [])
73 | {
74 | echo self::message('ERROR', $message, $param);
75 | $log = new Logger($channel);
76 | $log->pushHandler(new StreamHandler('log/' . $channel . '.log'), Logger::ERROR);
77 | $log->err($message, $param);
78 | }
79 |
80 | /**
81 | * 命令行输出消息
82 | * @param $type
83 | * @param string $message
84 | * @param array $param
85 | * @return false|string
86 | */
87 | private static function message($type, string $message = '', array $param = [])
88 | {
89 | $str = date('Y-m-d H:i:s');
90 | $str .= " [{$type}] {$message} ";
91 | $str .= json_encode($param);
92 | $str .= "\n";
93 | return $str;
94 | }
95 | }
--------------------------------------------------------------------------------
/app/WebSocket.php:
--------------------------------------------------------------------------------
1 | host = $host;
23 | $this->port = $port;
24 | $this->serve = new swoole_websocket_server($this->host, $this->port);
25 | }
26 |
27 | /**
28 | * 打开websocket链接
29 | */
30 | public function open()
31 | {
32 | $this->serve->on('open', function (swoole_websocket_server $server, $request) {
33 | $fd = $request->fd;
34 | $server->users[$fd] = ['fd' => $fd]; //获取客户端id插入table
35 |
36 | // 记录创建链接数
37 | Log::info('user', "第{$fd}个连接, 创建成功");
38 | });
39 | }
40 |
41 | /**
42 | * 接受发送消息websocket
43 | */
44 | public function message()
45 | {
46 | $this->serve->on('message', function (swoole_websocket_server $server, $frame) {
47 | $fd = $frame->fd;
48 | $state = $frame->opcode;
49 | $data = json_decode($frame->data);
50 |
51 |
52 | $id = isset($data->id) ? $data->id : '';
53 | $name = isset($data->name) ? $data->name : '';
54 | $sex = isset($data->sex) ? $data->sex : '';
55 | $icon = isset($data->icon) ? $data->icon : '';
56 | $message = isset($data->message) ? $data->message : '';
57 | $result = [];
58 |
59 | if ($data->type == 'init') {
60 | $type = 'tips';
61 | $result['message'] = "欢迎{$name}进入";
62 | } else if ($data->type == 'message') {
63 | $type = 'message';
64 | $user = $server->users[$fd]['info'];
65 | $result['id'] = $user['id'];
66 | $result['name'] = $user['name'];
67 | $result['sex'] = $user['sex'];
68 | $result['icon'] = $user['icon'];
69 | $result['message'] = $message;
70 |
71 | // 记录用户发送消息
72 | $message = "{$user['name']}: {$message}";
73 | Log::notice('user', $message);
74 | } else {
75 | $type = 'other';
76 | }
77 | $result['type'] = $type;
78 |
79 | // 保留用户信息
80 | foreach ($server->users as $user) {
81 | if (!isset($server->users[$user['fd']]['info'])) {
82 | $server->users[$user['fd']]['info'] = [
83 | 'id' => $id,
84 | 'name' => $name,
85 | 'sex' => $sex,
86 | 'icon' => $icon,
87 | ];
88 | }
89 | }
90 |
91 | foreach ($server->users as $user) {
92 | $server->push($user['fd'], json_encode($result));//消息广播给所有客户端
93 | }
94 | });
95 | }
96 |
97 | /**
98 | * 退出websocket
99 | */
100 | public function close()
101 | {
102 | $this->serve->on('close', function (swoole_websocket_server $server, $fd) {
103 | $users = $server->users;
104 | $name = '';
105 | foreach ($users as $user) {
106 | if (isset($user['fd'])) {
107 | $userInfo = $users[$fd]['info'];
108 | $server->push($user['fd'], json_encode([
109 | 'type' => 'tips',
110 | 'name' => $userInfo['name'],
111 | 'message' => "用户{$userInfo['name']}退出",
112 | ]));//消息广播给所有客户端(除自己)
113 | $name = $userInfo['name'];
114 | }
115 | }
116 |
117 | // 记录用户退出
118 | $message = "用户{$name}退出";
119 | Log::info('user', $message);
120 | });
121 | }
122 |
123 | /**
124 | * 调用websocket
125 | */
126 | public function start()
127 | {
128 | // 记录系统
129 | $message = "websocket服务器运行在";
130 | Log::info('system', $message, ['host' => $this->host, 'port' => $this->port]);
131 | $this->serve->start();
132 | }
133 | }
--------------------------------------------------------------------------------
/app/view/index.view.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 | 首页 | php-chat-websockt
9 |
10 |
11 |
29 |
30 |
41 |
42 |
--------------------------------------------------------------------------------
/app/view/js.view.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/view/room.view.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 | 房间内 | php-chat-websockt
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
19 |
36 |
56 |
57 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/bootstrap/app.php:
--------------------------------------------------------------------------------
1 | file: {$errfile}";
27 | $error .= "
line: {$errline}";
28 | $str = "error_code: {$errno}
" . $error;
29 | exit($error);
30 | }
31 |
32 | require_once BASE_DIR . 'vendor/autoload.php';
33 |
34 | $core = Col\Core::instance();
35 | $core->request = Col\Request::instance();
36 | $core->route = Col\Route::instance($core->request);
37 | $core->session = Col\Session::make(config('session'));
38 | $route = $core->route;
39 |
40 | require_once BASE_DIR . 'route/web.php';
41 |
42 | $route->end();
43 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "php-chat-websocket",
3 | "version": "2.0",
4 | "require": {
5 | "php": ">=7.0.0",
6 | "monolog/monolog": "1.2.*",
7 | "yzalis/identicon": "^1.2",
8 | "gregwar/captcha": "1.*",
9 | "flxxyz/col": "*",
10 | "vrana/notorm": "dev-master"
11 | },
12 | "autoload": {
13 | "psr-4": {
14 | "Chat\\": "app/"
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "a00a36b9bf8429d0767d74927ab883a5",
8 | "packages": [
9 | {
10 | "name": "flxxyz/col",
11 | "version": "0.1.0",
12 | "source": {
13 | "type": "git",
14 | "url": "https://github.com/flxxyz/Col.git",
15 | "reference": "370247b70a47b8a4b1093f2c7a4dcd405b38fc49"
16 | },
17 | "dist": {
18 | "type": "zip",
19 | "url": "https://files.phpcomposer.com/files/flxxyz/Col/370247b70a47b8a4b1093f2c7a4dcd405b38fc49.zip",
20 | "reference": "370247b70a47b8a4b1093f2c7a4dcd405b38fc49",
21 | "shasum": ""
22 | },
23 | "require": {
24 | "php": ">=7.0",
25 | "php-curl-class/php-curl-class": "^8.0",
26 | "vrana/notorm": "dev-master"
27 | },
28 | "type": "library",
29 | "autoload": {
30 | "psr-4": {
31 | "Col\\": "src/"
32 | }
33 | },
34 | "notification-url": "https://packagist.org/downloads/",
35 | "license": [
36 | "MIT"
37 | ],
38 | "authors": [
39 | {
40 | "name": "flxxyz",
41 | "email": "i@0bug.work",
42 | "homepage": "https://toyou.ren"
43 | }
44 | ],
45 | "description": "This is a simple PHP framework",
46 | "homepage": "http://github.com/flxxyz/Col",
47 | "keywords": [
48 | "Simple",
49 | "framework",
50 | "notorm",
51 | "php",
52 | "简单框架"
53 | ],
54 | "time": "2018-03-01T03:29:33+00:00"
55 | },
56 | {
57 | "name": "gregwar/captcha",
58 | "version": "v1.1.5",
59 | "source": {
60 | "type": "git",
61 | "url": "https://github.com/Gregwar/Captcha.git",
62 | "reference": "1d06ac8e12d2b3e0df39586d78b9f50e086a0bea"
63 | },
64 | "dist": {
65 | "type": "zip",
66 | "url": "https://files.phpcomposer.com/files/Gregwar/Captcha/1d06ac8e12d2b3e0df39586d78b9f50e086a0bea.zip",
67 | "reference": "1d06ac8e12d2b3e0df39586d78b9f50e086a0bea",
68 | "shasum": ""
69 | },
70 | "require": {
71 | "ext-gd": "*",
72 | "ext-mbstring": "*",
73 | "php": ">=5.3.0",
74 | "symfony/finder": "~3.0|~4.0"
75 | },
76 | "require-dev": {
77 | "phpunit/phpunit": "^6.4"
78 | },
79 | "type": "captcha",
80 | "autoload": {
81 | "psr-4": {
82 | "Gregwar\\": "src/Gregwar"
83 | }
84 | },
85 | "notification-url": "https://packagist.org/downloads/",
86 | "license": [
87 | "MIT"
88 | ],
89 | "authors": [
90 | {
91 | "name": "Grégoire Passault",
92 | "email": "g.passault@gmail.com",
93 | "homepage": "http://www.gregwar.com/"
94 | },
95 | {
96 | "name": "Jeremy Livingston",
97 | "email": "jeremy.j.livingston@gmail.com"
98 | }
99 | ],
100 | "description": "Captcha generator",
101 | "homepage": "https://github.com/Gregwar/Captcha",
102 | "keywords": [
103 | "bot",
104 | "captcha",
105 | "spam"
106 | ],
107 | "time": "2017-12-30T16:18:44+00:00"
108 | },
109 | {
110 | "name": "monolog/monolog",
111 | "version": "1.2.1",
112 | "source": {
113 | "type": "git",
114 | "url": "https://github.com/Seldaek/monolog.git",
115 | "reference": "d16496318c3e08e3bccfc3866e104e49cf25488a"
116 | },
117 | "dist": {
118 | "type": "zip",
119 | "url": "https://api.github.com/repos/Seldaek/monolog/zipball/d16496318c3e08e3bccfc3866e104e49cf25488a",
120 | "reference": "d16496318c3e08e3bccfc3866e104e49cf25488a",
121 | "shasum": ""
122 | },
123 | "require": {
124 | "php": ">=5.3.0"
125 | },
126 | "require-dev": {
127 | "mlehner/gelf-php": "1.0.*"
128 | },
129 | "suggest": {
130 | "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
131 | "ext-mongo": "Allow sending log messages to a MongoDB server",
132 | "mlehner/gelf-php": "Allow sending log messages to a GrayLog2 server"
133 | },
134 | "type": "library",
135 | "extra": {
136 | "branch-alias": {
137 | "dev-master": "1.3.x-dev"
138 | }
139 | },
140 | "autoload": {
141 | "psr-0": {
142 | "Monolog": "src/"
143 | }
144 | },
145 | "notification-url": "https://packagist.org/downloads/",
146 | "license": [
147 | "MIT"
148 | ],
149 | "authors": [
150 | {
151 | "name": "Jordi Boggiano",
152 | "email": "j.boggiano@seld.be",
153 | "homepage": "http://seld.be",
154 | "role": "Developer"
155 | }
156 | ],
157 | "description": "Logging for PHP 5.3",
158 | "homepage": "http://github.com/Seldaek/monolog",
159 | "keywords": [
160 | "log",
161 | "logging"
162 | ],
163 | "time": "2012-08-29T11:53:20+00:00"
164 | },
165 | {
166 | "name": "php-curl-class/php-curl-class",
167 | "version": "8.0.1",
168 | "source": {
169 | "type": "git",
170 | "url": "https://github.com/php-curl-class/php-curl-class.git",
171 | "reference": "bdfe1fcca0c32562050c84e01e3a4cbdc31e22fd"
172 | },
173 | "dist": {
174 | "type": "zip",
175 | "url": "https://api.github.com/repos/php-curl-class/php-curl-class/zipball/bdfe1fcca0c32562050c84e01e3a4cbdc31e22fd",
176 | "reference": "bdfe1fcca0c32562050c84e01e3a4cbdc31e22fd",
177 | "shasum": ""
178 | },
179 | "require": {
180 | "ext-curl": "*",
181 | "php": ">=5.3"
182 | },
183 | "require-dev": {
184 | "phpunit/phpunit": "*",
185 | "squizlabs/php_codesniffer": "*"
186 | },
187 | "type": "library",
188 | "autoload": {
189 | "psr-4": {
190 | "Curl\\": "src/Curl/"
191 | }
192 | },
193 | "notification-url": "https://packagist.org/downloads/",
194 | "license": [
195 | "Unlicense"
196 | ],
197 | "authors": [
198 | {
199 | "name": "Zach Borboa"
200 | }
201 | ],
202 | "description": "PHP Curl Class makes it easy to send HTTP requests and integrate with web APIs.",
203 | "homepage": "https://github.com/php-curl-class/php-curl-class",
204 | "keywords": [
205 | "api",
206 | "class",
207 | "client",
208 | "curl",
209 | "framework",
210 | "http",
211 | "http client",
212 | "json",
213 | "php",
214 | "requests",
215 | "rest",
216 | "restful",
217 | "web service",
218 | "xml"
219 | ],
220 | "time": "2018-01-27T15:40:39+00:00"
221 | },
222 | {
223 | "name": "symfony/finder",
224 | "version": "v4.0.5",
225 | "source": {
226 | "type": "git",
227 | "url": "https://github.com/symfony/finder.git",
228 | "reference": "552e244df10237f845a94fd64b194f848805e34b"
229 | },
230 | "dist": {
231 | "type": "zip",
232 | "url": "https://files.phpcomposer.com/files/symfony/finder/552e244df10237f845a94fd64b194f848805e34b.zip",
233 | "reference": "552e244df10237f845a94fd64b194f848805e34b",
234 | "shasum": ""
235 | },
236 | "require": {
237 | "php": "^7.1.3"
238 | },
239 | "type": "library",
240 | "extra": {
241 | "branch-alias": {
242 | "dev-master": "4.0-dev"
243 | }
244 | },
245 | "autoload": {
246 | "psr-4": {
247 | "Symfony\\Component\\Finder\\": ""
248 | },
249 | "exclude-from-classmap": [
250 | "/Tests/"
251 | ]
252 | },
253 | "notification-url": "https://packagist.org/downloads/",
254 | "license": [
255 | "MIT"
256 | ],
257 | "authors": [
258 | {
259 | "name": "Fabien Potencier",
260 | "email": "fabien@symfony.com"
261 | },
262 | {
263 | "name": "Symfony Community",
264 | "homepage": "https://symfony.com/contributors"
265 | }
266 | ],
267 | "description": "Symfony Finder Component",
268 | "homepage": "https://symfony.com",
269 | "time": "2018-02-11T17:17:44+00:00"
270 | },
271 | {
272 | "name": "vrana/notorm",
273 | "version": "dev-master",
274 | "source": {
275 | "type": "git",
276 | "url": "https://github.com/vrana/notorm.git",
277 | "reference": "e49d5d2f1bfe440dc82b61f46172635dfcb6f6dd"
278 | },
279 | "dist": {
280 | "type": "zip",
281 | "url": "https://api.github.com/repos/vrana/notorm/zipball/e49d5d2f1bfe440dc82b61f46172635dfcb6f6dd",
282 | "reference": "e49d5d2f1bfe440dc82b61f46172635dfcb6f6dd",
283 | "shasum": ""
284 | },
285 | "type": "library",
286 | "autoload": {
287 | "files": [
288 | "NotORM.php"
289 | ]
290 | },
291 | "notification-url": "https://packagist.org/downloads/",
292 | "license": [
293 | "Apache-2.0",
294 | "GPL-2.0+"
295 | ],
296 | "authors": [
297 | {
298 | "name": "Jakub Vrana",
299 | "homepage": "http://www.vrana.cz/"
300 | }
301 | ],
302 | "description": "NotORM is a PHP library for simple working with data in the database.",
303 | "homepage": "http://www.notorm.com/",
304 | "keywords": [
305 | "database",
306 | "dbal"
307 | ],
308 | "time": "2014-10-30T16:55:08+00:00"
309 | },
310 | {
311 | "name": "yzalis/identicon",
312 | "version": "1.2.0",
313 | "source": {
314 | "type": "git",
315 | "url": "https://github.com/yzalis/Identicon.git",
316 | "reference": "228eca74299a45163be40fd82d334bf21e66b86b"
317 | },
318 | "dist": {
319 | "type": "zip",
320 | "url": "https://api.github.com/repos/yzalis/Identicon/zipball/228eca74299a45163be40fd82d334bf21e66b86b",
321 | "reference": "228eca74299a45163be40fd82d334bf21e66b86b",
322 | "shasum": ""
323 | },
324 | "require": {
325 | "php": ">=5.5.0"
326 | },
327 | "require-dev": {
328 | "ext-imagick": "*",
329 | "fzaninotto/faker": "^1.2.0",
330 | "phpunit/phpunit": "^4.0 || ^5.0"
331 | },
332 | "type": "library",
333 | "extra": {
334 | "branch-alias": {
335 | "dev-master": "1.2-dev"
336 | }
337 | },
338 | "autoload": {
339 | "psr-4": {
340 | "Identicon\\": "src/Identicon/"
341 | }
342 | },
343 | "notification-url": "https://packagist.org/downloads/",
344 | "license": [
345 | "MIT"
346 | ],
347 | "authors": [
348 | {
349 | "name": "Benjamin Laugueux",
350 | "email": "benjamin@yzalis.com"
351 | }
352 | ],
353 | "description": "Create awesome unique avatar.",
354 | "homepage": "http://identicon-php.org",
355 | "keywords": [
356 | "avatar",
357 | "identicon",
358 | "image"
359 | ],
360 | "time": "2017-08-01T14:39:05+00:00"
361 | }
362 | ],
363 | "packages-dev": [],
364 | "aliases": [],
365 | "minimum-stability": "stable",
366 | "stability-flags": {
367 | "vrana/notorm": 20
368 | },
369 | "prefer-stable": false,
370 | "prefer-lowest": false,
371 | "platform": {
372 | "php": ">=7.0.0"
373 | },
374 | "platform-dev": []
375 | }
376 |
--------------------------------------------------------------------------------
/config/config.php:
--------------------------------------------------------------------------------
1 | true,
4 | 'url' => 'http://127.0.0.1:8080/', //保留最后的斜杠
5 | 'timezone' => 'PRC',
6 | 'key' => '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
7 | ];
8 |
--------------------------------------------------------------------------------
/config/session.php:
--------------------------------------------------------------------------------
1 | true,
4 | 'expire' => 360, // 单位: 分钟
5 | 'limiter' => 'private',
6 | 'perfix' => 'chat',
7 | ];
8 |
--------------------------------------------------------------------------------
/handle.php:
--------------------------------------------------------------------------------
1 | open();
17 | $socket->message();
18 | $socket->close();
19 | $socket->start();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/log/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/public/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .*
3 | !.htaccess
4 | /log/*
5 | !/log/README.md
6 | !.gitignore
7 |
8 | application/cache/*
9 | !application/cache/index.html
10 | !application/cache/.htaccess
11 |
12 | application/logs/*
13 | !application/logs/index.html
14 | !application/logs/.htaccess
15 |
16 | composer.lock
17 |
18 | user_guide_src/build/*
19 | user_guide_src/cilexer/build/*
20 | user_guide_src/cilexer/dist/*
21 | user_guide_src/cilexer/pycilexer.egg-info/*
22 | /vendor/
23 |
24 | # IDE Files
25 | #-------------------------
26 | /nbproject/
27 | .idea/*
28 |
29 | ## Sublime Text cache files
30 | *.tmlanguage.cache
31 | *.tmPreferences.cache
32 | *.stTheme.cache
33 | *.sublime-workspace
34 | *.sublime-project
35 |
--------------------------------------------------------------------------------
/public/css/OwO.css:
--------------------------------------------------------------------------------
1 | .OwO {
2 | position: relative;
3 | -webkit-user-select: none;
4 | -moz-user-select: none;
5 | -ms-user-select: none;
6 | user-select: none;
7 | }
8 |
9 |
10 |
11 | .OwO.OwO-open .OwO-logo {
12 | border-radius: 4px 4px 0 0;
13 | border-bottom: none;
14 | color: #444;
15 | }
16 |
17 |
18 |
19 | .OwO:hover .OwO-logo {
20 | color: #444;
21 | }
22 |
23 |
24 | .OwO.OwO-open .OwO-body {
25 | display: block;
26 | }
27 |
28 |
29 | .OwO.OwO-up .OwO-body {
30 | top: inherit;
31 | bottom: 21px;
32 | border-radius: 4px 4px 4px 0;
33 | }
34 |
35 | .OwO.OwO-up .OwO-body .OwO-bar .OwO-packages li:nth-child(1) {
36 | border-radius: 0;
37 | }
38 |
39 | .OwO.OwO-up.OwO-open .OwO-logo {
40 | border: 1px solid #ddd;
41 | border-radius: 0 0 4px 4px;
42 | border-top: none;
43 | }
44 |
45 | .OwO .OwO-logo {
46 | position: relative;
47 | display: inline-block;
48 | color: #888;
49 | background: #fff;
50 | border: 1px solid #ddd;
51 | border-radius: 4px;
52 | font-size: 13px;
53 | padding: 2px 5px;
54 | cursor: pointer;
55 | height: 22px;
56 | box-sizing: border-box;
57 | z-index: 2;
58 | line-height: 16px;
59 | }
60 |
61 | .OwO .OwO-logo:hover span {
62 | display: inline-block;
63 | -webkit-animation: a 5s infinite ease-in-out;
64 | animation: a 5s infinite ease-in-out;
65 | }
66 |
67 | .OwO .OwO-body {
68 | display: none;
69 | position: absolute;
70 | width: 200px;
71 | background: #fff;
72 | border: 1px solid #ddd;
73 | z-index: 1;
74 | top: 21px;
75 | border-radius: 0 4px 4px 4px;
76 | }
77 | .OwO .OwO-body .OwO-items {
78 | -webkit-user-select: none;
79 | -moz-user-select: none;
80 | -ms-user-select: none;
81 | user-select: none;
82 | display: none;
83 | padding: 10px;
84 | margin: 0;
85 | overflow: scroll;
86 | font-size: 0;
87 | }
88 |
89 | .OwO .OwO-body .OwO-items .OwO-item {
90 | list-style-type: none;
91 | background: #f7f7f7;
92 | padding: 5px 10px;
93 | border-radius: 5px;
94 | display: inline-block;
95 | font-size: 12px;
96 | line-height: 14px;
97 | margin: 0 10px 12px 0;
98 | cursor: pointer;
99 | -webkit-transition: .3s;
100 | transition: .3s;
101 | }
102 |
103 | .OwO .OwO-body .OwO-items .OwO-item:hover {
104 | background: #eee;
105 | box-shadow: 0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.12);
106 | -webkit-animation: a 5s infinite ease-in-out;
107 | animation: a 5s infinite ease-in-out;
108 | }
109 |
110 | .OwO .OwO-body .OwO-items-emoji .OwO-item {
111 | font-size: 20px;
112 | line-height: 19px;
113 | }
114 |
115 | .OwO .OwO-body .OwO-items-image .OwO-item {
116 | max-width: calc(25% - 10px);
117 | box-sizing: border-box;
118 | }
119 |
120 | .OwO .OwO-body .OwO-items-image .OwO-item img {
121 | max-width: 100%;
122 | }
123 |
124 | .OwO .OwO-body .OwO-items-show {
125 | display: block;
126 | }
127 |
128 | .OwO .OwO-body .OwO-bar {
129 | width: 100%;
130 | height: 30px;
131 | border-top: 1px solid #ddd;
132 | background: #fff;
133 | border-radius: 0 0 4px 4px;
134 | color: #444;
135 | }
136 |
137 | .OwO .OwO-body .OwO-bar .OwO-packages {
138 | margin: 0;
139 | padding: 0;
140 | font-size: 0;
141 | }
142 |
143 | .OwO .OwO-body .OwO-bar .OwO-packages li {
144 | list-style-type: none;
145 | display: inline-block;
146 | line-height: 30px;
147 | font-size: 14px;
148 | padding: 0 10px;
149 | cursor: pointer;
150 | margin-right: 3px;
151 | }
152 |
153 | .OwO .OwO-body .OwO-bar .OwO-packages li:nth-child(1) {
154 | border-radius: 0 0 0 3px;
155 | }
156 |
157 | .OwO .OwO-body .OwO-bar .OwO-packages li:hover {
158 | background: #eee;
159 | }
160 |
161 | .OwO .OwO-body .OwO-bar .OwO-packages .OwO-package-active {
162 | background: #eee;
163 | -webkit-transition: .3s;
164 | transition: .3s;
165 | }
166 | @-webkit-keyframes a {
167 | 2% {
168 | -webkit-transform: translateY(1.5px) rotate(1.5deg);
169 | transform: translateY(1.5px) rotate(1.5deg);
170 | }
171 |
172 | 4% {
173 | -webkit-transform: translateY(-1.5px) rotate(-.5deg);
174 | transform: translateY(-1.5px) rotate(-.5deg);
175 | }
176 |
177 | 6% {
178 | -webkit-transform: translateY(1.5px) rotate(-1.5deg);
179 | transform: translateY(1.5px) rotate(-1.5deg);
180 | }
181 |
182 | 8% {
183 | -webkit-transform: translateY(-1.5px) rotate(-1.5deg);
184 | transform: translateY(-1.5px) rotate(-1.5deg);
185 | }
186 |
187 | 10% {
188 | -webkit-transform: translateY(2.5px) rotate(1.5deg);
189 | transform: translateY(2.5px) rotate(1.5deg);
190 | }
191 |
192 | 12% {
193 | -webkit-transform: translateY(-.5px) rotate(1.5deg);
194 | transform: translateY(-.5px) rotate(1.5deg);
195 | }
196 |
197 | 14% {
198 | -webkit-transform: translateY(-1.5px) rotate(1.5deg);
199 | transform: translateY(-1.5px) rotate(1.5deg);
200 | }
201 |
202 | 16% {
203 | -webkit-transform: translateY(-.5px) rotate(-1.5deg);
204 | transform: translateY(-.5px) rotate(-1.5deg);
205 | }
206 |
207 | 18% {
208 | -webkit-transform: translateY(.5px) rotate(-1.5deg);
209 | transform: translateY(.5px) rotate(-1.5deg);
210 | }
211 |
212 | 20% {
213 | -webkit-transform: translateY(-1.5px) rotate(2.5deg);
214 | transform: translateY(-1.5px) rotate(2.5deg);
215 | }
216 |
217 | 22% {
218 | -webkit-transform: translateY(.5px) rotate(-1.5deg);
219 | transform: translateY(.5px) rotate(-1.5deg);
220 | }
221 |
222 | 24% {
223 | -webkit-transform: translateY(1.5px) rotate(1.5deg);
224 | transform: translateY(1.5px) rotate(1.5deg);
225 | }
226 |
227 | 26% {
228 | -webkit-transform: translateY(.5px) rotate(.5deg);
229 | transform: translateY(.5px) rotate(.5deg);
230 | }
231 |
232 | 28% {
233 | -webkit-transform: translateY(.5px) rotate(1.5deg);
234 | transform: translateY(.5px) rotate(1.5deg);
235 | }
236 |
237 | 30% {
238 | -webkit-transform: translateY(-.5px) rotate(2.5deg);
239 | transform: translateY(-.5px) rotate(2.5deg);
240 | }
241 |
242 | 32%,34% {
243 | -webkit-transform: translateY(1.5px) rotate(-.5deg);
244 | transform: translateY(1.5px) rotate(-.5deg);
245 | }
246 |
247 | 36% {
248 | -webkit-transform: translateY(-1.5px) rotate(2.5deg);
249 | transform: translateY(-1.5px) rotate(2.5deg);
250 | }
251 |
252 | 38% {
253 | -webkit-transform: translateY(1.5px) rotate(-1.5deg);
254 | transform: translateY(1.5px) rotate(-1.5deg);
255 | }
256 |
257 | 40% {
258 | -webkit-transform: translateY(-.5px) rotate(2.5deg);
259 | transform: translateY(-.5px) rotate(2.5deg);
260 | }
261 |
262 | 42% {
263 | -webkit-transform: translateY(2.5px) rotate(-1.5deg);
264 | transform: translateY(2.5px) rotate(-1.5deg);
265 | }
266 |
267 | 44% {
268 | -webkit-transform: translateY(1.5px) rotate(.5deg);
269 | transform: translateY(1.5px) rotate(.5deg);
270 | }
271 |
272 | 46% {
273 | -webkit-transform: translateY(-1.5px) rotate(2.5deg);
274 | transform: translateY(-1.5px) rotate(2.5deg);
275 | }
276 |
277 | 48% {
278 | -webkit-transform: translateY(-.5px) rotate(.5deg);
279 | transform: translateY(-.5px) rotate(.5deg);
280 | }
281 |
282 | 50% {
283 | -webkit-transform: translateY(.5px) rotate(.5deg);
284 | transform: translateY(.5px) rotate(.5deg);
285 | }
286 |
287 | 52% {
288 | -webkit-transform: translateY(2.5px) rotate(2.5deg);
289 | transform: translateY(2.5px) rotate(2.5deg);
290 | }
291 |
292 | 54% {
293 | -webkit-transform: translateY(-1.5px) rotate(1.5deg);
294 | transform: translateY(-1.5px) rotate(1.5deg);
295 | }
296 |
297 | 56% {
298 | -webkit-transform: translateY(2.5px) rotate(2.5deg);
299 | transform: translateY(2.5px) rotate(2.5deg);
300 | }
301 |
302 | 58% {
303 | -webkit-transform: translateY(.5px) rotate(2.5deg);
304 | transform: translateY(.5px) rotate(2.5deg);
305 | }
306 |
307 | 60% {
308 | -webkit-transform: translateY(2.5px) rotate(2.5deg);
309 | transform: translateY(2.5px) rotate(2.5deg);
310 | }
311 |
312 | 62% {
313 | -webkit-transform: translateY(-.5px) rotate(2.5deg);
314 | transform: translateY(-.5px) rotate(2.5deg);
315 | }
316 |
317 | 64% {
318 | -webkit-transform: translateY(-.5px) rotate(1.5deg);
319 | transform: translateY(-.5px) rotate(1.5deg);
320 | }
321 |
322 | 66% {
323 | -webkit-transform: translateY(1.5px) rotate(-.5deg);
324 | transform: translateY(1.5px) rotate(-.5deg);
325 | }
326 |
327 | 68% {
328 | -webkit-transform: translateY(-1.5px) rotate(-.5deg);
329 | transform: translateY(-1.5px) rotate(-.5deg);
330 | }
331 |
332 | 70% {
333 | -webkit-transform: translateY(1.5px) rotate(.5deg);
334 | transform: translateY(1.5px) rotate(.5deg);
335 | }
336 |
337 | 72% {
338 | -webkit-transform: translateY(2.5px) rotate(1.5deg);
339 | transform: translateY(2.5px) rotate(1.5deg);
340 | }
341 |
342 | 74% {
343 | -webkit-transform: translateY(-.5px) rotate(.5deg);
344 | transform: translateY(-.5px) rotate(.5deg);
345 | }
346 |
347 | 76% {
348 | -webkit-transform: translateY(-.5px) rotate(2.5deg);
349 | transform: translateY(-.5px) rotate(2.5deg);
350 | }
351 |
352 | 78% {
353 | -webkit-transform: translateY(-.5px) rotate(1.5deg);
354 | transform: translateY(-.5px) rotate(1.5deg);
355 | }
356 |
357 | 80% {
358 | -webkit-transform: translateY(1.5px) rotate(1.5deg);
359 | transform: translateY(1.5px) rotate(1.5deg);
360 | }
361 |
362 | 82% {
363 | -webkit-transform: translateY(-.5px) rotate(.5deg);
364 | transform: translateY(-.5px) rotate(.5deg);
365 | }
366 |
367 | 84% {
368 | -webkit-transform: translateY(1.5px) rotate(2.5deg);
369 | transform: translateY(1.5px) rotate(2.5deg);
370 | }
371 |
372 | 86% {
373 | -webkit-transform: translateY(-1.5px) rotate(-1.5deg);
374 | transform: translateY(-1.5px) rotate(-1.5deg);
375 | }
376 |
377 | 88% {
378 | -webkit-transform: translateY(-.5px) rotate(2.5deg);
379 | transform: translateY(-.5px) rotate(2.5deg);
380 | }
381 |
382 | 90% {
383 | -webkit-transform: translateY(2.5px) rotate(-.5deg);
384 | transform: translateY(2.5px) rotate(-.5deg);
385 | }
386 |
387 | 92% {
388 | -webkit-transform: translateY(.5px) rotate(-.5deg);
389 | transform: translateY(.5px) rotate(-.5deg);
390 | }
391 |
392 | 94% {
393 | -webkit-transform: translateY(2.5px) rotate(.5deg);
394 | transform: translateY(2.5px) rotate(.5deg);
395 | }
396 |
397 | 96% {
398 | -webkit-transform: translateY(-.5px) rotate(1.5deg);
399 | transform: translateY(-.5px) rotate(1.5deg);
400 | }
401 |
402 | 98% {
403 | -webkit-transform: translateY(-1.5px) rotate(-.5deg);
404 | transform: translateY(-1.5px) rotate(-.5deg);
405 | }
406 |
407 | 0%,to {
408 | -webkit-transform: translate(0) rotate(0deg);
409 | transform: translate(0) rotate(0deg);
410 | }
411 | }
412 |
413 | @keyframes a {
414 | 2% {
415 | -webkit-transform: translateY(1.5px) rotate(1.5deg);
416 | transform: translateY(1.5px) rotate(1.5deg);
417 | }
418 |
419 | 4% {
420 | -webkit-transform: translateY(-1.5px) rotate(-.5deg);
421 | transform: translateY(-1.5px) rotate(-.5deg);
422 | }
423 |
424 | 6% {
425 | -webkit-transform: translateY(1.5px) rotate(-1.5deg);
426 | transform: translateY(1.5px) rotate(-1.5deg);
427 | }
428 |
429 | 8% {
430 | -webkit-transform: translateY(-1.5px) rotate(-1.5deg);
431 | transform: translateY(-1.5px) rotate(-1.5deg);
432 | }
433 |
434 | 10% {
435 | -webkit-transform: translateY(2.5px) rotate(1.5deg);
436 | transform: translateY(2.5px) rotate(1.5deg);
437 | }
438 |
439 | 12% {
440 | -webkit-transform: translateY(-.5px) rotate(1.5deg);
441 | transform: translateY(-.5px) rotate(1.5deg);
442 | }
443 |
444 | 14% {
445 | -webkit-transform: translateY(-1.5px) rotate(1.5deg);
446 | transform: translateY(-1.5px) rotate(1.5deg);
447 | }
448 |
449 | 16% {
450 | -webkit-transform: translateY(-.5px) rotate(-1.5deg);
451 | transform: translateY(-.5px) rotate(-1.5deg);
452 | }
453 |
454 | 18% {
455 | -webkit-transform: translateY(.5px) rotate(-1.5deg);
456 | transform: translateY(.5px) rotate(-1.5deg);
457 | }
458 |
459 | 20% {
460 | -webkit-transform: translateY(-1.5px) rotate(2.5deg);
461 | transform: translateY(-1.5px) rotate(2.5deg);
462 | }
463 |
464 | 22% {
465 | -webkit-transform: translateY(.5px) rotate(-1.5deg);
466 | transform: translateY(.5px) rotate(-1.5deg);
467 | }
468 |
469 | 24% {
470 | -webkit-transform: translateY(1.5px) rotate(1.5deg);
471 | transform: translateY(1.5px) rotate(1.5deg);
472 | }
473 |
474 | 26% {
475 | -webkit-transform: translateY(.5px) rotate(.5deg);
476 | transform: translateY(.5px) rotate(.5deg);
477 | }
478 |
479 | 28% {
480 | -webkit-transform: translateY(.5px) rotate(1.5deg);
481 | transform: translateY(.5px) rotate(1.5deg);
482 | }
483 |
484 | 30% {
485 | -webkit-transform: translateY(-.5px) rotate(2.5deg);
486 | transform: translateY(-.5px) rotate(2.5deg);
487 | }
488 |
489 | 32%,34% {
490 | -webkit-transform: translateY(1.5px) rotate(-.5deg);
491 | transform: translateY(1.5px) rotate(-.5deg);
492 | }
493 |
494 | 36% {
495 | -webkit-transform: translateY(-1.5px) rotate(2.5deg);
496 | transform: translateY(-1.5px) rotate(2.5deg);
497 | }
498 |
499 | 38% {
500 | -webkit-transform: translateY(1.5px) rotate(-1.5deg);
501 | transform: translateY(1.5px) rotate(-1.5deg);
502 | }
503 |
504 | 40% {
505 | -webkit-transform: translateY(-.5px) rotate(2.5deg);
506 | transform: translateY(-.5px) rotate(2.5deg);
507 | }
508 |
509 | 42% {
510 | -webkit-transform: translateY(2.5px) rotate(-1.5deg);
511 | transform: translateY(2.5px) rotate(-1.5deg);
512 | }
513 |
514 | 44% {
515 | -webkit-transform: translateY(1.5px) rotate(.5deg);
516 | transform: translateY(1.5px) rotate(.5deg);
517 | }
518 |
519 | 46% {
520 | -webkit-transform: translateY(-1.5px) rotate(2.5deg);
521 | transform: translateY(-1.5px) rotate(2.5deg);
522 | }
523 |
524 | 48% {
525 | -webkit-transform: translateY(-.5px) rotate(.5deg);
526 | transform: translateY(-.5px) rotate(.5deg);
527 | }
528 |
529 | 50% {
530 | -webkit-transform: translateY(.5px) rotate(.5deg);
531 | transform: translateY(.5px) rotate(.5deg);
532 | }
533 |
534 | 52% {
535 | -webkit-transform: translateY(2.5px) rotate(2.5deg);
536 | transform: translateY(2.5px) rotate(2.5deg);
537 | }
538 |
539 | 54% {
540 | -webkit-transform: translateY(-1.5px) rotate(1.5deg);
541 | transform: translateY(-1.5px) rotate(1.5deg);
542 | }
543 |
544 | 56% {
545 | -webkit-transform: translateY(2.5px) rotate(2.5deg);
546 | transform: translateY(2.5px) rotate(2.5deg);
547 | }
548 |
549 | 58% {
550 | -webkit-transform: translateY(.5px) rotate(2.5deg);
551 | transform: translateY(.5px) rotate(2.5deg);
552 | }
553 |
554 | 60% {
555 | -webkit-transform: translateY(2.5px) rotate(2.5deg);
556 | transform: translateY(2.5px) rotate(2.5deg);
557 | }
558 |
559 | 62% {
560 | -webkit-transform: translateY(-.5px) rotate(2.5deg);
561 | transform: translateY(-.5px) rotate(2.5deg);
562 | }
563 |
564 | 64% {
565 | -webkit-transform: translateY(-.5px) rotate(1.5deg);
566 | transform: translateY(-.5px) rotate(1.5deg);
567 | }
568 |
569 | 66% {
570 | -webkit-transform: translateY(1.5px) rotate(-.5deg);
571 | transform: translateY(1.5px) rotate(-.5deg);
572 | }
573 |
574 | 68% {
575 | -webkit-transform: translateY(-1.5px) rotate(-.5deg);
576 | transform: translateY(-1.5px) rotate(-.5deg);
577 | }
578 |
579 | 70% {
580 | -webkit-transform: translateY(1.5px) rotate(.5deg);
581 | transform: translateY(1.5px) rotate(.5deg);
582 | }
583 |
584 | 72% {
585 | -webkit-transform: translateY(2.5px) rotate(1.5deg);
586 | transform: translateY(2.5px) rotate(1.5deg);
587 | }
588 |
589 | 74% {
590 | -webkit-transform: translateY(-.5px) rotate(.5deg);
591 | transform: translateY(-.5px) rotate(.5deg);
592 | }
593 |
594 | 76% {
595 | -webkit-transform: translateY(-.5px) rotate(2.5deg);
596 | transform: translateY(-.5px) rotate(2.5deg);
597 | }
598 |
599 | 78% {
600 | -webkit-transform: translateY(-.5px) rotate(1.5deg);
601 | transform: translateY(-.5px) rotate(1.5deg);
602 | }
603 |
604 | 80% {
605 | -webkit-transform: translateY(1.5px) rotate(1.5deg);
606 | transform: translateY(1.5px) rotate(1.5deg);
607 | }
608 |
609 | 82% {
610 | -webkit-transform: translateY(-.5px) rotate(.5deg);
611 | transform: translateY(-.5px) rotate(.5deg);
612 | }
613 |
614 | 84% {
615 | -webkit-transform: translateY(1.5px) rotate(2.5deg);
616 | transform: translateY(1.5px) rotate(2.5deg);
617 | }
618 |
619 | 86% {
620 | -webkit-transform: translateY(-1.5px) rotate(-1.5deg);
621 | transform: translateY(-1.5px) rotate(-1.5deg);
622 | }
623 |
624 | 88% {
625 | -webkit-transform: translateY(-.5px) rotate(2.5deg);
626 | transform: translateY(-.5px) rotate(2.5deg);
627 | }
628 |
629 | 90% {
630 | -webkit-transform: translateY(2.5px) rotate(-.5deg);
631 | transform: translateY(2.5px) rotate(-.5deg);
632 | }
633 |
634 | 92% {
635 | -webkit-transform: translateY(.5px) rotate(-.5deg);
636 | transform: translateY(.5px) rotate(-.5deg);
637 | }
638 |
639 | 94% {
640 | -webkit-transform: translateY(2.5px) rotate(.5deg);
641 | transform: translateY(2.5px) rotate(.5deg);
642 | }
643 |
644 | 96% {
645 | -webkit-transform: translateY(-.5px) rotate(1.5deg);
646 | transform: translateY(-.5px) rotate(1.5deg);
647 | }
648 |
649 | 98% {
650 | -webkit-transform: translateY(-1.5px) rotate(-.5deg);
651 | transform: translateY(-1.5px) rotate(-.5deg);
652 | }
653 |
654 | 0%,to {
655 | -webkit-transform: translate(0) rotate(0deg);
656 | transform: translate(0) rotate(0deg);
657 | }
658 |
659 | }
--------------------------------------------------------------------------------
/public/css/chat.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | }
5 | html,body {
6 | width: 100%;
7 | height: 100%;
8 | }
9 | body {
10 | overflow: hidden;
11 | }
12 | input, button, textarea{
13 | border: 0;
14 | outline: 0;
15 | outline-offset: 0;
16 | }
17 | :after,:before {
18 | box-sizing: border-box;
19 | }
20 | ::-webkit-scrollbar {
21 | width: 2px;
22 | background-color: #f5f5f5;
23 | }
24 | ::-webkit-scrollbar-thumb {
25 | background-color: #999;
26 | }
27 | ::-webkit-scrollbar-track {
28 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
29 | -moz-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
30 | box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
31 | background-color: #f5f5f5;
32 | }
33 | ::-webkit-scrollbar:window-inactive,::-webkit-scrollbar-track:window-inactive,::-webkit-scrollbar-thumb:window-inactive {
34 | visibility: hidden;
35 | }
36 |
37 |
38 | #chat-header {
39 | position: relative;
40 | top: 0;
41 | left: 0;
42 | padding: 8px 0;
43 | width: 100%;
44 | text-align: center;
45 | font-size: 1em;
46 | color: #fff;
47 | background-color: #3097D1;
48 | background-image: url(../img/header_bg.png);
49 | }
50 | #chat-list {
51 | position: relative;
52 | top: 0;
53 | left: 0;
54 | max-width: 100%;
55 | width: 100%;
56 | height: 86%;
57 | background: #F1F2F7;
58 | overflow: scroll;
59 | overflow-x: hidden;
60 | overflow-y: scroll;
61 | }
62 | #chat-footer {
63 | position: fixed;
64 | bottom: 0;
65 | left: 0;
66 | width: 100%;
67 | height: 10%;
68 | background: #F1F2F7;
69 | }
70 |
71 | .chat {
72 | padding: 15px 0;
73 | position: relative;
74 | top: 0;
75 | left: 0;
76 | }
77 | .chat-img {
78 | position: absolute;
79 | top: 25px;
80 | margin-top: -10px;
81 | width: 50px;
82 | height: 50px;
83 | -webkit-border-radius: 50%;
84 | -moz-border-radius: 50%;
85 | border-radius: 50%;
86 | background: #fff;
87 | }
88 | .chat-info {
89 | font-size: .3em;
90 | }
91 | .chat-s {
92 | padding: 0 5px;
93 | color: #fff;
94 | background: #FF988A;
95 | -webkit-border-radius: 7px;
96 | -moz-border-radius: 7px;
97 | border-radius: 7px;
98 | }
99 | .chat-name {
100 | color: rgb(144,145,149);
101 | }
102 | .chat-sex {
103 | font-size: 4em;
104 | font-weight: bold;
105 | }
106 | .chat-sex.male {
107 | color: #5FD4F2;
108 | }
109 | .chat-sex.female {
110 | color: #FF758F;
111 | }
112 | .chat-sex.maf {
113 | color: rgb(205,33,230);
114 | }
115 | .chat-message {
116 | margin: 5px 70px 0 70px;
117 | word-wrap:break-word;
118 | word-break:normal;
119 | display: inline-block;
120 | padding: 5px;
121 | border: 1px solid #fff;
122 | -webkit-border-radius: 5px;
123 | -moz-border-radius: 5px;
124 | border-radius: 5px;
125 | background: #fff;
126 | box-shadow: 2px 2px 2px 0 rgba(0,0,0,.1);
127 | }
128 | .chat-message:after {
129 | content: "";
130 | position: absolute;
131 | border-bottom: 8px solid rgba(255, 255, 255, 0);
132 | }
133 | .chat-message > img {
134 | max-width: 100%;
135 | width: 100%;
136 | }
137 | .chat-me {
138 | text-align: right;
139 | }
140 | .chat-me > img {
141 | right: 10px;
142 | }
143 | .chat-me > p:after {
144 | right: 60px;
145 | top: 50px;
146 | border-left: 12px solid #fff;
147 | }
148 | .chat-me > .chat-info {
149 | margin-right: 70px;
150 | }
151 | .chat-ta {
152 | text-align: left;
153 | }
154 | .chat-ta > img {
155 | left: 10px;
156 | }
157 | .chat-ta > p:after {
158 | left: 60px;
159 | top: 50px;
160 | border-right: 12px solid #fff;
161 | }
162 | .chat-ta > .chat-info {
163 | margin-left: 70px;
164 | }
165 | /* 用户 */
166 | .chat-type-message {
167 |
168 | }
169 | /* 系统 */
170 | .chat-type-system {
171 |
172 | }
173 | /* 小提示 */
174 | .chat-type-tips {
175 |
176 | }
177 | .chat-type-system, .chat-type-tips {
178 | text-align: center;
179 | font-size: .5em;
180 | }
181 | .chat-type-system > span {
182 | display: inline-block;
183 | padding: 4px;
184 | color: #ffffff;
185 | background-color: #cccccc;
186 | -webkit-border-radius: 7px;
187 | -moz-border-radius: 7px;
188 | border-radius: 7px;
189 | }
190 | .chat-type-tips > span {
191 | padding: 2px 8px;
192 | color: #fff;
193 | background: #FF0000;
194 | -webkit-border-radius: 7px;
195 | -moz-border-radius: 7px;
196 | border-radius: 7px;
197 | }
198 | .chat-input > .message {
199 | margin: 2px 0 2px 3%;
200 | padding: 5px 3px;
201 | width: 80%;
202 | height: 24px;
203 | -webkit-border-radius: 2px;
204 | -moz-border-radius: 2px;
205 | border-radius: 3px;
206 | background: #fff;
207 | }
208 | .chat-input > .message:focus {
209 | box-shadow: inset 0 0 1px 2px rgba(0,0,0,0.1)
210 | }
211 | .chat-input > .message:active {
212 | box-shadow: inset 0 0 1px 2px rgba(0,0,0,0.1)
213 | }
214 | .chat-input > .message::-webkit-scrollbar {
215 | width: 1px;
216 | background-color: #f5f5f5;
217 | }
218 | .chat-input > .message::-webkit-scrollbar-thumb {
219 | background-color: #999;
220 | }
221 | .chat-input > .message::-webkit-scrollbar-track {
222 | -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
223 | -moz-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
224 | box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
225 | background-color: #f5f5f5;
226 | }
227 | .chat-input > .btn {
228 | margin: 1px 1.5% 1px 1.5%;
229 | width: 12%;
230 | height: 36px;
231 | float: right;
232 | border-radius: 6px;
233 | color: #fff;
234 | }
235 | .chat-input > .btn.y {
236 | background: #12B7F5;
237 | }
238 | .chat-input > .btn.n {
239 | background: #DDDEE2;
240 | }
241 | .chat-more {
242 | margin: 0 3%;
243 | }
244 |
--------------------------------------------------------------------------------
/public/css/s.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flxxyz/php-chat-websocket/a6717d073f26685651ab9c5a2e3239841684ca80/public/css/s.css
--------------------------------------------------------------------------------
/public/img/header_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flxxyz/php-chat-websocket/a6717d073f26685651ab9c5a2e3239841684ca80/public/img/header_bg.png
--------------------------------------------------------------------------------
/public/index.php:
--------------------------------------------------------------------------------
1 | = 200 && i.status < 300 || 304 === i.status ? (a.odata = JSON.parse(i.responseText), a.init(t)) : console.log("OwO data request was unsuccessful: " + i.status))
40 | }, i.open("get", t.api, !0), i.send(null)
41 | }
42 |
43 | return _createClass(e, [{
44 | key: "init",
45 | value: function (e) {
46 | var t = this;
47 | this.area = e.target, this.packages = Object.keys(this.odata);
48 | for (var a = '\n ' + e.logo + '
\n ', s = 0; s < this.packages.length; s++) {
49 | a += '\n
';
50 | for (var n = this.odata[this.packages[s]].container, i = 0; i < n.length; i++) a += '\n - ' + n[i].icon + "
";
51 | a += "\n
"
52 | }
53 | a += '\n
\n
';
54 | for (var o = 0; o < this.packages.length; o++) a += "\n - " + this.packages[o] + "
";
55 | a += "\n
\n
\n
\n ", this.container.innerHTML = a, this.logo = this.container.getElementsByClassName("OwO-logo")[0], this.logo.addEventListener("click", function () {
56 | t.toggle()
57 | }), this.container.getElementsByClassName("OwO-body")[0].addEventListener("click", function (e) {
58 | var a = null;
59 | if (e.target.classList.contains("OwO-item") ? a = e.target : e.target.parentNode.classList.contains("OwO-item") && (a = e.target.parentNode), a) {
60 | var s = t.area.selectionEnd, n = t.area.value;
61 | if(//.test(a.innerHTML)) {
62 | return;
63 | }
64 | t.area.value = n.slice(0, s) + a.innerHTML + n.slice(s),t.area.focus() //t.toggle()
65 | }
66 | }), this.packagesEle = this.container.getElementsByClassName("OwO-packages")[0];
67 | for (var c = function (e) {
68 | !function (a) {
69 | t.packagesEle.children[e].addEventListener("click", function () {
70 | t.tab(a)
71 | })
72 | }(e)
73 | }, l = 0; l < this.packagesEle.children.length; l++) c(l);
74 | this.tab(0)
75 | }
76 | }, {
77 | key: "toggle",
78 | value: function () {
79 | this.container.classList.contains("OwO-open") ? this.container.classList.remove("OwO-open") : this.container.classList.add("OwO-open")
80 | }
81 | }, {
82 | key: "tab",
83 | value: function (e) {
84 | var t = this.container.getElementsByClassName("OwO-items-show")[0];
85 | t && t.classList.remove("OwO-items-show"), this.container.getElementsByClassName("OwO-items")[e].classList.add("OwO-items-show");
86 | var a = this.container.getElementsByClassName("OwO-package-active")[0];
87 | a && a.classList.remove("OwO-package-active"), this.packagesEle.getElementsByTagName("li")[e].classList.add("OwO-package-active")
88 | }
89 | }]), e
90 | }();
91 | "undefined" != typeof module && "undefined" != typeof module.exports ? module.exports = e : window.OwO = e
92 | }();
--------------------------------------------------------------------------------
/public/js/OwO.json:
--------------------------------------------------------------------------------
1 | {
2 | "颜文字": {
3 | "type": "emoticon",
4 | "container": [
5 | {
6 | "icon": "OωO",
7 | "text": "Author: DIYgod"
8 | },
9 | {
10 | "icon": "|´・ω・)ノ",
11 | "text": "Hi"
12 | },
13 | {
14 | "icon": "ヾ(≧∇≦*)ゝ",
15 | "text": "开心"
16 | },
17 | {
18 | "icon": "(☆ω☆)",
19 | "text": "星星眼"
20 | },
21 | {
22 | "icon": "(╯‵□′)╯︵┴─┴",
23 | "text": "掀桌"
24 | },
25 | {
26 | "icon": " ̄﹃ ̄",
27 | "text": "流口水"
28 | },
29 | {
30 | "icon": "(/ω\)",
31 | "text": "捂脸"
32 | },
33 | {
34 | "icon": "∠( ᐛ 」∠)_",
35 | "text": "给跪"
36 | },
37 | {
38 | "icon": "(๑•̀ㅁ•́ฅ)",
39 | "text": "Hi"
40 | },
41 | {
42 | "icon": "→_→",
43 | "text": "斜眼"
44 | },
45 | {
46 | "icon": "୧(๑•̀⌄•́๑)૭",
47 | "text": "加油"
48 | },
49 | {
50 | "icon": "٩(ˊᗜˋ*)و",
51 | "text": "有木有WiFi"
52 | },
53 | {
54 | "icon": "(ノ°ο°)ノ",
55 | "text": "前方高能预警"
56 | },
57 | {
58 | "icon": "(´இ皿இ`)",
59 | "text": "我从未见过如此厚颜无耻之人"
60 | },
61 | {
62 | "icon": "⌇●﹏●⌇",
63 | "text": "吓死宝宝惹"
64 | },
65 | {
66 | "icon": "(ฅ´ω`ฅ)",
67 | "text": "已阅留爪"
68 | },
69 | {
70 | "icon": "(╯°A°)╯︵○○○",
71 | "text": "去吧大师球"
72 | },
73 | {
74 | "icon": "φ( ̄∇ ̄o)",
75 | "text": "太萌惹"
76 | },
77 | {
78 | "icon": "ヾ(´・ ・`。)ノ\"",
79 | "text": "咦咦咦"
80 | },
81 | {
82 | "icon": "( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃",
83 | "text": "气呼呼"
84 | },
85 | {
86 | "icon": "(ó﹏ò。)",
87 | "text": "我受到了惊吓"
88 | },
89 | {
90 | "icon": "Σ(っ °Д °;)っ",
91 | "text": "什么鬼"
92 | },
93 | {
94 | "icon": "( ,,´・ω・)ノ\"(´っω・`。)",
95 | "text": "摸摸头"
96 | },
97 | {
98 | "icon": "╮(╯▽╰)╭ ",
99 | "text": "无奈"
100 | },
101 | {
102 | "icon": "o(*////▽////*)q ",
103 | "text": "脸红"
104 | },
105 | {
106 | "icon": ">﹏<",
107 | "text": ""
108 | },
109 | {
110 | "icon": "( ๑´•ω•) \"(ㆆᴗㆆ)",
111 | "text": ""
112 | },
113 | {
114 | "icon": "(。•ˇ‸ˇ•。)",
115 | "text": ""
116 | }
117 | ]
118 | },
119 | "emoji": {
120 | "type": "emoji",
121 | "container": [
122 | {
123 | "icon": "😂",
124 | "text": ""
125 | },
126 | {
127 | "icon": "😀",
128 | "text": ""
129 | },
130 | {
131 | "icon": "😅",
132 | "text": ""
133 | },
134 | {
135 | "icon": "😊",
136 | "text": ""
137 | },
138 | {
139 | "icon": "🙂",
140 | "text": ""
141 | },
142 | {
143 | "icon": "🙃",
144 | "text": ""
145 | },
146 | {
147 | "icon": "😌",
148 | "text": ""
149 | },
150 | {
151 | "icon": "😍",
152 | "text": ""
153 | },
154 | {
155 | "icon": "😘 ",
156 | "text": ""
157 | },
158 | {
159 | "icon": "😜",
160 | "text": ""
161 | },
162 | {
163 | "icon": "😝",
164 | "text": ""
165 | },
166 | {
167 | "icon": "😏",
168 | "text": ""
169 | },
170 | {
171 | "icon": "😒",
172 | "text": ""
173 | },
174 | {
175 | "icon": "🙄",
176 | "text": ""
177 | },
178 | {
179 | "icon": "😳 ",
180 | "text": ""
181 | },
182 | {
183 | "icon": "😡",
184 | "text": ""
185 | },
186 | {
187 | "icon": "😔",
188 | "text": ""
189 | },
190 | {
191 | "icon": "😫",
192 | "text": ""
193 | },
194 | {
195 | "icon": "😱",
196 | "text": ""
197 | },
198 | {
199 | "icon": "😭",
200 | "text": ""
201 | },
202 | {
203 | "icon": "💩",
204 | "text": ""
205 | },
206 | {
207 | "icon": "👻",
208 | "text": ""
209 | },
210 | {
211 | "icon": "🙌",
212 | "text": ""
213 | },
214 | {
215 | "icon": "🖕",
216 | "text": ""
217 | },
218 | {
219 | "icon": "👍",
220 | "text": ""
221 | },
222 | {
223 | "icon": "👫",
224 | "text": ""
225 | },
226 | {
227 | "icon": "👬",
228 | "text": ""
229 | },
230 | {
231 | "icon": "👭",
232 | "text": ""
233 | },
234 | {
235 | "icon": "🌚",
236 | "text": ""
237 | },
238 | {
239 | "icon": "🌝",
240 | "text": ""
241 | },
242 | {
243 | "icon": "🙈",
244 | "text": ""
245 | },
246 | {
247 | "icon": "💊",
248 | "text": ""
249 | },
250 | {
251 | "icon": "😶",
252 | "text": ""
253 | },
254 | {
255 | "icon": "🙏",
256 | "text": ""
257 | },
258 | {
259 | "icon": "🍦",
260 | "text": ""
261 | },
262 | {
263 | "icon": "🍉",
264 | "text": ""
265 | },
266 | {
267 | "icon": "😣",
268 | "text": ""
269 | }
270 | ]
271 | },
272 | "斗图模式": {
273 | "type": "image",
274 | "container": [
275 | {
276 | "icon": "
",
277 | "text": "face1"
278 | },
279 | {
280 | "icon": "
",
281 | "text": "face2"
282 | },
283 | {
284 | "icon": "
",
285 | "text": "face3"
286 | },
287 | {
288 | "icon": "
",
289 | "text": "face4"
290 | },
291 | {
292 | "icon": "
",
293 | "text": "face5"
294 | },
295 | {
296 | "icon": "
",
297 | "text": "face6"
298 | },
299 | {
300 | "icon": "
",
301 | "text": "face7"
302 | },
303 | {
304 | "icon": "
",
305 | "text": "face8"
306 | },
307 | {
308 | "icon": "
",
309 | "text": "face9"
310 | },
311 | {
312 | "icon": "
",
313 | "text": "face10"
314 | },
315 | {
316 | "icon": "
",
317 | "text": "face11"
318 | },
319 | {
320 | "icon": "
",
321 | "text": "face12"
322 | },
323 | {
324 | "icon": "
",
325 | "text": "face13"
326 | },
327 | {
328 | "icon": "
",
329 | "text": "face14"
330 | },
331 | {
332 | "icon": "
",
333 | "text": "face15"
334 | },
335 | {
336 | "icon": "
",
337 | "text": "face16"
338 | },
339 | {
340 | "icon": "
",
341 | "text": "face17"
342 | },
343 | {
344 | "icon": "
",
345 | "text": "face18"
346 | },
347 | {
348 | "icon": "
",
349 | "text": "face19"
350 | },
351 | {
352 | "icon": "
",
353 | "text": "face20"
354 | },
355 | {
356 | "icon": "
",
357 | "text": "face21"
358 | },
359 | {
360 | "icon": "
",
361 | "text": "face22"
362 | },
363 | {
364 | "icon": "
",
365 | "text": "face23"
366 | },
367 | {
368 | "icon": "
",
369 | "text": "face24"
370 | },
371 | {
372 | "icon": "
",
373 | "text": "face25"
374 | },
375 | {
376 | "icon": "
",
377 | "text": "face26"
378 | },
379 | {
380 | "icon": "
",
381 | "text": "face27"
382 | },
383 | {
384 | "icon": "
",
385 | "text": "face28"
386 | }
387 | ]
388 | }
389 | }
390 |
--------------------------------------------------------------------------------
/public/js/Reconnect.js:
--------------------------------------------------------------------------------
1 | !function(a,b){"function"==typeof define&&define.amd?define([],b):"undefined"!=typeof module&&module.exports?module.exports=b():a.ReconnectingWebSocket=b()}(this,function(){function a(b,c,d){function l(a,b){var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,!1,!1,b),c}var e={debug:!1,automaticOpen:!0,reconnectInterval:1e3,maxReconnectInterval:3e4,reconnectDecay:1.5,timeoutInterval:2e3};d||(d={});for(var f in e)this[f]="undefined"!=typeof d[f]?d[f]:e[f];this.url=b,this.reconnectAttempts=0,this.readyState=WebSocket.CONNECTING,this.protocol=null;var h,g=this,i=!1,j=!1,k=document.createElement("div");k.addEventListener("open",function(a){g.onopen(a)}),k.addEventListener("close",function(a){g.onclose(a)}),k.addEventListener("connecting",function(a){g.onconnecting(a)}),k.addEventListener("message",function(a){g.onmessage(a)}),k.addEventListener("error",function(a){g.onerror(a)}),this.addEventListener=k.addEventListener.bind(k),this.removeEventListener=k.removeEventListener.bind(k),this.dispatchEvent=k.dispatchEvent.bind(k),this.open=function(b){h=new WebSocket(g.url,c||[]),b||k.dispatchEvent(l("connecting")),(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","attempt-connect",g.url);var d=h,e=setTimeout(function(){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","connection-timeout",g.url),j=!0,d.close(),j=!1},g.timeoutInterval);h.onopen=function(){clearTimeout(e),(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onopen",g.url),g.protocol=h.protocol,g.readyState=WebSocket.OPEN,g.reconnectAttempts=0;var d=l("open");d.isReconnect=b,b=!1,k.dispatchEvent(d)},h.onclose=function(c){if(clearTimeout(e),h=null,i)g.readyState=WebSocket.CLOSED,k.dispatchEvent(l("close"));else{g.readyState=WebSocket.CONNECTING;var d=l("connecting");d.code=c.code,d.reason=c.reason,d.wasClean=c.wasClean,k.dispatchEvent(d),b||j||((g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onclose",g.url),k.dispatchEvent(l("close")));var e=g.reconnectInterval*Math.pow(g.reconnectDecay,g.reconnectAttempts);setTimeout(function(){g.reconnectAttempts++,g.open(!0)},e>g.maxReconnectInterval?g.maxReconnectInterval:e)}},h.onmessage=function(b){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onmessage",g.url,b.data);var c=l("message");c.data=b.data,k.dispatchEvent(c)},h.onerror=function(b){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onerror",g.url,b),k.dispatchEvent(l("error"))}},1==this.automaticOpen&&this.open(!1),this.send=function(b){if(h)return(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","send",g.url,b),h.send(b);throw"INVALID_STATE_ERR : Pausing to reconnect websocket"},this.close=function(a,b){"undefined"==typeof a&&(a=1e3),i=!0,h&&h.close(a,b)},this.refresh=function(){h&&h.close()}}return a.prototype.onopen=function(){},a.prototype.onclose=function(){},a.prototype.onconnecting=function(){},a.prototype.onmessage=function(){},a.prototype.onerror=function(){},a.debugAll=!1,a.CONNECTING=WebSocket.CONNECTING,a.OPEN=WebSocket.OPEN,a.CLOSING=WebSocket.CLOSING,a.CLOSED=WebSocket.CLOSED,a});
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | allow: /
--------------------------------------------------------------------------------
/route/web.php:
--------------------------------------------------------------------------------
1 | group('/', function() {
6 | $this->get('/', [new RoomController, 'index']);
7 |
8 | $this->get('/login', [new RoomController, 'login']);
9 |
10 | $this->get('/logout', [new RoomController, 'logout']);
11 |
12 | $this->get('/room', [new RoomController, 'room']);
13 | });
14 |
--------------------------------------------------------------------------------
/run.php:
--------------------------------------------------------------------------------
1 | /dev/null 2>&1 &
3 |
--------------------------------------------------------------------------------