├── .example.env ├── .gitignore ├── .travis.yml ├── Database.sql ├── LICENSE ├── README.md ├── app ├── AppService.php ├── ExceptionHandle.php ├── Request.php ├── api │ ├── BaseController.php │ ├── controller │ │ ├── Activity.php │ │ ├── Attach.php │ │ ├── Badge.php │ │ ├── Error.php │ │ ├── Index.php │ │ ├── Message.php │ │ ├── Room.php │ │ ├── Sms.php │ │ ├── Song.php │ │ ├── System.php │ │ ├── User.php │ │ └── Weapp.php │ └── view │ │ ├── activity │ │ └── index.html │ │ ├── badge │ │ ├── bg.html │ │ └── player.html │ │ └── song │ │ └── search_chrome.html ├── command │ ├── BaseCommand.php │ ├── Download.php │ └── Song.php ├── common.php ├── event.php ├── index │ ├── BaseController.php │ └── controller │ │ ├── Error.php │ │ └── Index.php ├── middleware.php ├── model │ ├── Access.php │ ├── App.php │ ├── Attach.php │ ├── BaseModel.php │ ├── Conf.php │ ├── Keywords.php │ ├── Message.php │ ├── Room.php │ ├── Sms.php │ ├── Song.php │ ├── User.php │ └── Weapp.php ├── provider.php └── service.php ├── composer.json ├── config ├── app.php ├── cache.php ├── console.php ├── cookie.php ├── database.php ├── filesystem.php ├── lang.php ├── log.php ├── middleware.php ├── route.php ├── session.php ├── trace.php └── view.php ├── extend └── .gitignore ├── public ├── .htaccess ├── chrome.xml ├── favicon.ico ├── index.html ├── index.php ├── new │ ├── favicon.ico │ ├── images │ │ ├── bg.jpg │ │ ├── bg_dark.jpg │ │ ├── bg_light.jpg │ │ ├── button_emoji.png │ │ ├── button_image.png │ │ ├── emoji │ │ │ ├── 1.png │ │ │ ├── 10.png │ │ │ ├── 11.png │ │ │ ├── 12.png │ │ │ ├── 13.png │ │ │ ├── 14.png │ │ │ ├── 15.png │ │ │ ├── 16.png │ │ │ ├── 17.png │ │ │ ├── 18.png │ │ │ ├── 19.png │ │ │ ├── 2.png │ │ │ ├── 20.png │ │ │ ├── 21.png │ │ │ ├── 22.png │ │ │ ├── 23.png │ │ │ ├── 24.png │ │ │ ├── 25.png │ │ │ ├── 26.png │ │ │ ├── 27.png │ │ │ ├── 28.png │ │ │ ├── 29.png │ │ │ ├── 3.png │ │ │ ├── 30.png │ │ │ ├── 4.png │ │ │ ├── 5.png │ │ │ ├── 6.png │ │ │ ├── 7.png │ │ │ ├── 8.png │ │ │ └── 9.png │ │ ├── error.jpg │ │ ├── gh_42bdbe5c9412_1280.jpg │ │ ├── linus.jpg │ │ ├── loading.gif │ │ ├── loading.png │ │ ├── logo.png │ │ ├── menubar_mysong.png │ │ ├── menubar_pickedsong.png │ │ ├── menubar_picksong.png │ │ ├── menubar_selectroom.png │ │ ├── menubar_setting.png │ │ ├── menubar_upload.png │ │ ├── nohead.jpg │ │ ├── player_bar.png │ │ ├── player_bg.png │ │ ├── qrcode.jpg │ │ ├── snow1.png │ │ └── snow2.png │ └── mp3 │ │ ├── ci.m4a │ │ ├── da.m4a │ │ ├── dingdong.mp3 │ │ ├── dong.m4a │ │ └── message.mp3 ├── router.php ├── sdk │ └── bbbug.js └── uploads │ └── .gitignore ├── route └── app.php ├── runtime └── .gitignore ├── think └── websocket_bbbug_chat.js /.example.env: -------------------------------------------------------------------------------- 1 | APP_DEBUG = false 2 | SYSTEM_SALT= BBBUG_COM 3 | 4 | [APP] 5 | DEFAULT_TIMEZONE = Asia/Chongqing 6 | 7 | [DATABASE] 8 | TYPE = mysql 9 | HOSTNAME = 127.0.0.1 10 | DATABASE = BBBUG_COM 11 | USERNAME = root 12 | PASSWORD = 123456 13 | HOSTPORT = 3306 14 | CHARSET = utf8 15 | DEBUG = false 16 | PREFIX = sa_ 17 | 18 | [LANG] 19 | default_lang = zh-cn -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /.vscode 3 | /vendor 4 | /public/install 5 | /public/music 6 | /public/weapp_code 7 | *.log 8 | .env 9 | composer.lock 10 | .DS_Store 11 | /app/api/controller/Test.php 12 | /app/command/Test.php 13 | /app/api/view/test -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: php 4 | 5 | branches: 6 | only: 7 | - stable 8 | 9 | cache: 10 | directories: 11 | - $HOME/.composer/cache 12 | 13 | before_install: 14 | - composer self-update 15 | 16 | install: 17 | - composer install --no-dev --no-interaction --ignore-platform-reqs 18 | - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Core.zip . 19 | - composer require --update-no-dev --no-interaction "topthink/think-image:^1.0" 20 | - composer require --update-no-dev --no-interaction "topthink/think-migration:^1.0" 21 | - composer require --update-no-dev --no-interaction "topthink/think-captcha:^1.0" 22 | - composer require --update-no-dev --no-interaction "topthink/think-mongo:^1.0" 23 | - composer require --update-no-dev --no-interaction "topthink/think-worker:^1.0" 24 | - composer require --update-no-dev --no-interaction "topthink/think-helper:^1.0" 25 | - composer require --update-no-dev --no-interaction "topthink/think-queue:^1.0" 26 | - composer require --update-no-dev --no-interaction "topthink/think-angular:^1.0" 27 | - composer require --dev --update-no-dev --no-interaction "topthink/think-testing:^1.0" 28 | - zip -r --exclude='*.git*' --exclude='*.zip' --exclude='*.travis.yml' ThinkPHP_Full.zip . 29 | 30 | script: 31 | - php think unit 32 | 33 | deploy: 34 | provider: releases 35 | api_key: 36 | secure: TSF6bnl2JYN72UQOORAJYL+CqIryP2gHVKt6grfveQ7d9rleAEoxlq6PWxbvTI4jZ5nrPpUcBUpWIJHNgVcs+bzLFtyh5THaLqm39uCgBbrW7M8rI26L8sBh/6nsdtGgdeQrO/cLu31QoTzbwuz1WfAVoCdCkOSZeXyT/CclH99qV6RYyQYqaD2wpRjrhA5O4fSsEkiPVuk0GaOogFlrQHx+C+lHnf6pa1KxEoN1A0UxxVfGX6K4y5g4WQDO5zT4bLeubkWOXK0G51XSvACDOZVIyLdjApaOFTwamPcD3S1tfvuxRWWvsCD5ljFvb2kSmx5BIBNwN80MzuBmrGIC27XLGOxyMerwKxB6DskNUO9PflKHDPI61DRq0FTy1fv70SFMSiAtUv9aJRT41NQh9iJJ0vC8dl+xcxrWIjU1GG6+l/ZcRqVx9V1VuGQsLKndGhja7SQ+X1slHl76fRq223sMOql7MFCd0vvvxVQ2V39CcFKao/LB1aPH3VhODDEyxwx6aXoTznvC/QPepgWsHOWQzKj9ftsgDbsNiyFlXL4cu8DWUty6rQy8zT2b4O8b1xjcwSUCsy+auEjBamzQkMJFNlZAIUrukL/NbUhQU37TAbwsFyz7X0E/u/VMle/nBCNAzgkMwAUjiHM6FqrKKBRWFbPrSIixjfjkCnrMEPw= 37 | file: 38 | - ThinkPHP_Core.zip 39 | - ThinkPHP_Full.zip 40 | skip_cleanup: true 41 | on: 42 | tags: true 43 | -------------------------------------------------------------------------------- /Database.sql: -------------------------------------------------------------------------------- 1 | -- phpMyAdmin SQL Dump 2 | -- version 4.6.6 3 | -- https://www.phpmyadmin.net/ 4 | -- 5 | -- Host: 127.0.0.1:3306 6 | -- Generation Time: 2021-06-30 20:32:25 7 | -- 服务器版本: 5.6.48-log 8 | -- PHP Version: 7.1.32 9 | 10 | SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; 11 | SET time_zone = "+00:00"; 12 | 13 | 14 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 15 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 16 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 17 | /*!40101 SET NAMES utf8mb4 */; 18 | 19 | -- 20 | -- Database: `BBBBUG_Export` 21 | -- 22 | 23 | -- -------------------------------------------------------- 24 | 25 | -- 26 | -- 表的结构 `sa_access` 27 | -- 28 | 29 | CREATE TABLE `sa_access` ( 30 | `access_id` int(11) NOT NULL, 31 | `access_user` int(11) NOT NULL DEFAULT '0' COMMENT '用户ID', 32 | `access_token` varchar(255) NOT NULL DEFAULT '' COMMENT 'AccessToken', 33 | `access_plat` varchar(255) NOT NULL DEFAULT 'all' COMMENT '登录平台', 34 | `access_ip` varchar(255) NOT NULL DEFAULT '' COMMENT 'IP', 35 | `access_status` int(11) NOT NULL DEFAULT '0' COMMENT '状态', 36 | `access_createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间', 37 | `access_updatetime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间' 38 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='授权信息表'; 39 | 40 | -- -------------------------------------------------------- 41 | 42 | -- 43 | -- 表的结构 `sa_app` 44 | -- 45 | 46 | CREATE TABLE `sa_app` ( 47 | `app_id` int(11) NOT NULL, 48 | `app_key` varchar(255) NOT NULL DEFAULT '' COMMENT 'key', 49 | `app_name` varchar(255) NOT NULL DEFAULT '' COMMENT 'name', 50 | `app_url` varchar(255) NOT NULL DEFAULT '' COMMENT 'url', 51 | `app_user` int(11) NOT NULL DEFAULT '0' COMMENT 'user', 52 | `app_scope` varchar(255) NOT NULL DEFAULT '' COMMENT 'scope', 53 | `app_status` int(11) NOT NULL DEFAULT '0' COMMENT '状态', 54 | `app_createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间', 55 | `app_updatetime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间' 56 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用表'; 57 | 58 | -- 59 | -- 转存表中的数据 `sa_app` 60 | -- 61 | 62 | INSERT INTO `sa_app` (`app_id`, `app_key`, `app_name`, `app_url`, `app_user`, `app_scope`, `app_status`, `app_createtime`, `app_updatetime`) VALUES 63 | (1, '请重置后对接', 'BBBUG', 'https://bbbug.com', 1, '', 0, 0, 0), 64 | (1001, '请重置后对接', 'Gitee', 'https://gitee.com/#extra#', 1, '', 0, 0, 0), 65 | (1002, '请重置后对接', 'OSChina', 'https://my.oschina.net/#extra#', 1, '', 0, 0, 0), 66 | (1003, '请重置后对接', 'QQ', 'https://hamm.cn', 1, '', 0, 0, 0), 67 | (1004, '请重置后对接', '钉钉', 'https://hamm.cn', 1, '', 0, 0, 0), 68 | (1005, '请重置后对接', '微信小程序', 'https://hamm.cn', 1, '', 0, 0, 0); 69 | 70 | -- -------------------------------------------------------- 71 | 72 | -- 73 | -- 表的结构 `sa_attach` 74 | -- 75 | 76 | CREATE TABLE `sa_attach` ( 77 | `attach_id` int(11) NOT NULL, 78 | `attach_path` varchar(255) NOT NULL DEFAULT '' COMMENT '路径', 79 | `attach_used` int(11) NOT NULL DEFAULT '0', 80 | `attach_thumb` varchar(255) NOT NULL DEFAULT '', 81 | `attach_type` varchar(255) NOT NULL DEFAULT '' COMMENT '类型', 82 | `attach_sha` varchar(255) NOT NULL DEFAULT '', 83 | `attach_size` int(11) NOT NULL DEFAULT '0' COMMENT '大小', 84 | `attach_user` int(11) NOT NULL DEFAULT '0' COMMENT '用户', 85 | `attach_status` int(11) NOT NULL DEFAULT '0' COMMENT '状态', 86 | `attach_createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间', 87 | `attach_updatetime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间' 88 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='附件表'; 89 | 90 | -- -------------------------------------------------------- 91 | 92 | -- 93 | -- 表的结构 `sa_conf` 94 | -- 95 | 96 | CREATE TABLE `sa_conf` ( 97 | `conf_id` int(11) NOT NULL, 98 | `conf_key` varchar(255) CHARACTER SET utf8 NOT NULL COMMENT '参数名', 99 | `conf_value` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '参数值', 100 | `conf_desc` varchar(255) CHARACTER SET utf8 DEFAULT '' COMMENT '参数描述', 101 | `conf_int` int(11) NOT NULL DEFAULT '0' COMMENT '参数到期', 102 | `conf_status` int(11) NOT NULL DEFAULT '0', 103 | `conf_createtime` int(11) NOT NULL DEFAULT '0', 104 | `conf_updatetime` int(11) NOT NULL DEFAULT '0' 105 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置表'; 106 | 107 | -- 108 | -- 转存表中的数据 `sa_conf` 109 | -- 110 | 111 | INSERT INTO `sa_conf` (`conf_id`, `conf_key`, `conf_value`, `conf_desc`, `conf_int`, `conf_status`, `conf_createtime`, `conf_updatetime`) VALUES 112 | (11, 'weapp_appid', '', '小程序APPID', 0, 0, 0, 0), 113 | (12, 'weapp_appkey', '', '小程序SECRET', 0, 0, 0, 0), 114 | (39, 'upload_max_file', '2097152', '最大文件上传限制', 0, 0, 0, 0), 115 | (40, 'upload_file_type', 'jpg,png,gif,jpeg,bmp,txt,pdf,mp3,mp4,amr,m4a,xls,xlsx,ppt,pptx,doc,docx', '允许文件上传类型', 0, 0, 0, 0), 116 | (41, 'upload_max_image', '2097152', '最大图片上传限制', 0, 0, 0, 0), 117 | (42, 'upload_image_type', 'jpg,png,gif,jpeg,bmp', '允许上传图片类型', 0, 0, 0, 0), 118 | (47, 'default_group', '5', '注册默认用户组', 0, 0, 0, 1598539052), 119 | (48, 'email_account', 'admin@mail.bbbug.com', '邮箱账号', 0, 0, 0, 1598539052), 120 | (49, 'email_password', '123456', '邮箱密码', 0, 0, 0, 1598539052), 121 | (50, 'email_host', 'smtp.exmail.qq.com', '邮箱服务器', 0, 0, 0, 1598539052), 122 | (51, 'email_remark', 'BBBUG TEAM', '邮箱签名', 0, 0, 0, 1598539052), 123 | (52, 'email_port', '465', '邮箱端口号', 0, 0, 0, 1598539052), 124 | (53, 'websocket_http', 'http://127.0.0.1:10012/', 'WebsocketHTTP请求地址', 0, 0, 0, 1598539052), 125 | (54, 'websocket_token', 'wss_bbbug_com', 'Websocket验证串', 0, 0, 0, 1598539052), 126 | (55, 'api_guest_token', '45af3cfe44942c956e026d5fd58f0feffbd3a237', '临时用户access_token', 0, 0, 0, 1598539052), 127 | (56, 'frontend_url', '', '前端地址', 0, 0, 0, 0), 128 | (57, 'api_url', '', 'API地址', 0, 0, 0, 0), 129 | (58, 'tencent_ai_appid', '', '腾讯AI的APPID', 0, 0, 0, 1598539052), 130 | (59, 'tencent_ai_appkey', '', '腾讯AI的APPKEY', 0, 0, 0, 1598539052), 131 | (60, 'static_url', '', 'Static文件地址', 0, 0, 0, 0); 132 | 133 | -- -------------------------------------------------------- 134 | 135 | -- 136 | -- 表的结构 `sa_keywords` 137 | -- 138 | 139 | CREATE TABLE `sa_keywords` ( 140 | `keywords_id` int(11) NOT NULL, 141 | `keywords_source` varchar(255) NOT NULL DEFAULT '' COMMENT '原串', 142 | `keywords_target` varchar(255) NOT NULL DEFAULT '' COMMENT '替换', 143 | `keywords_all` int(11) NOT NULL DEFAULT '0' COMMENT '全替换', 144 | `keywords_status` int(11) NOT NULL DEFAULT '0' COMMENT '状态', 145 | `keywords_createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间', 146 | `keywords_updatetime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间' 147 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='关键词表'; 148 | 149 | -- 150 | -- 转存表中的数据 `sa_keywords` 151 | -- 152 | 153 | INSERT INTO `sa_keywords` (`keywords_id`, `keywords_source`, `keywords_target`, `keywords_all`, `keywords_status`, `keywords_createtime`, `keywords_updatetime`) VALUES 154 | (3, ' 130 | 131 | 132 | 133 |
134 |
135 | 136 | 137 | 138 |
139 |
140 |
数据加载中...
141 |
 
142 |
ID:{$room['room_id']} {$room['room_name']} 在线:{$room['room_online']}
144 |
145 |
146 | 147 |
148 | 149 | 228 | 229 | -------------------------------------------------------------------------------- /app/api/view/song/search_chrome.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 搜索结果 9 | 62 | 63 | 64 | 65 |
返回BBBUG主站
66 | 69 |
70 |
71 |
{$item['name']} - {$item['singer']}
72 |
{$item['album']}
73 |
74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /app/command/BaseCommand.php: -------------------------------------------------------------------------------- 1 | select()->toArray(); 15 | $c = []; 16 | foreach ($configs as $config) { 17 | $c[$config['conf_key']] = $config['conf_value']; 18 | } 19 | config($c, 'startadmin'); 20 | } 21 | protected function console($text, $break = true) 22 | { 23 | print_r($text . ($break ? PHP_EOL : '')); 24 | } 25 | protected function success($text, $break = true) 26 | { 27 | print_r(chr(27) . "[42m" . "$text" . chr(27) . "[0m" . ($break ? PHP_EOL : '')); 28 | } 29 | protected function error($text, $break = true) 30 | { 31 | print_r(chr(27) . "[41m" . "$text" . chr(27) . "[0m" . ($break ? PHP_EOL : '')); 32 | } 33 | protected function warning($text, $break = true) 34 | { 35 | print_r(chr(27) . "[43m" . "$text" . chr(27) . "[0m" . ($break ? PHP_EOL : '')); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/command/Download.php: -------------------------------------------------------------------------------- 1 | setName('Download') 16 | ->setDescription('StartAdmin Test Command'); 17 | } 18 | 19 | protected function execute(Input $input, Output $output) 20 | { 21 | // cache('song_downloaded_list',null); 22 | // cache('song_waiting_download_list',null); 23 | // return; 24 | while (true) { 25 | $cacheList = cache('song_waiting_download_list') ?? []; 26 | if (count($cacheList) > 0) { 27 | if ($cacheList[0]['url']) { 28 | $url = $cacheList[0]['url']; 29 | $mid = $cacheList[0]['mid']; 30 | try{ 31 | file_put_contents(__dir__ . "/../../public/music/" . $mid . ".jpg", file_get_contents($url)); 32 | 33 | $downloaded_song_list = cache('song_downloaded_list') ?? []; 34 | $isExist = false; 35 | foreach ($downloaded_song_list as $_mid) { 36 | if ($mid == $_mid) { 37 | $isExist = true; 38 | break; 39 | } 40 | } 41 | if (!$isExist) { 42 | array_push($downloaded_song_list, $mid); 43 | } 44 | cache('song_downloaded_list', $downloaded_song_list); 45 | }catch(\Exception $e){ 46 | 47 | } 48 | array_shift($cacheList); 49 | cache('song_waiting_download_list', $cacheList); //删掉已下载的文件item 50 | cache('song_download_mid_' . $mid, time()); //缓存当前时间 51 | 52 | } else { 53 | array_shift($cacheList); 54 | cache('song_waiting_download_list', $cacheList); 55 | } 56 | } 57 | $downloaded_song_list = cache('song_downloaded_list') ?? []; 58 | // print_r($downloaded_song_list); 59 | for ($i = 0; $i < count($downloaded_song_list); $i++) { 60 | $_mid = $downloaded_song_list[$i]; 61 | $songCache = cache('song_download_mid_' . $_mid) ?? false; 62 | // print_r($songCache); 63 | if ($songCache) { 64 | if (time() - $songCache > 600) { 65 | echo "超时" . PHP_EOL; 66 | $fileName = __dir__ . "/../../public/music/" . $_mid . ".jpg"; 67 | if (file_exists($fileName)) { 68 | unlink($fileName); 69 | cache('song_download_mid_' . $_mid, null); 70 | array_splice($downloaded_song_list, $i, 1); 71 | cache('song_downloaded_list', $downloaded_song_list); 72 | } 73 | } else { 74 | // echo "有效" . PHP_EOL; 75 | } 76 | } else { 77 | // echo "下载已移出" . PHP_EOL; 78 | } 79 | } 80 | sleep(1); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /app/command/Song.php: -------------------------------------------------------------------------------- 1 | setName('Test') 19 | ->setDescription('StartAdmin Test Command'); 20 | } 21 | 22 | protected function execute(Input $input, Output $output) 23 | { 24 | $this->loadConfig(); 25 | while (true) { 26 | //暂停一下 避免对redis频繁读取 27 | usleep(500 * 1000); 28 | $rooms = $this->getRoomList(); 29 | if (!$rooms) { 30 | print_r('暂无房间开启点歌' . PHP_EOL); 31 | continue; 32 | } 33 | foreach ($rooms as $room) { 34 | try { 35 | $song = $this->getPlayingSong($room['room_id']); 36 | if ($song && $song['song']) { 37 | //歌曲正在播放 38 | if (time() < $song['song']['length'] + $song['since']) { 39 | //预先缓存下一首歌 40 | $this->preLoadMusicUrl($room); 41 | continue; 42 | } 43 | // 歌曲已超时 44 | if ($room['room_type'] == 4 && $room['room_playone']) { 45 | //是单曲循环的电台房间 重置播放时间 46 | $song['since'] = time(); 47 | $this->playSong($room['room_id'], $song, true); //给true 保留当前房间歌曲 48 | continue; 49 | } 50 | } 51 | //其他房间 52 | $song = $this->getSongFromList($room['room_id']); 53 | if ($song) { 54 | $this->playSong($room['room_id'], $song); 55 | } else { 56 | if ($room['room_type'] == 4) { 57 | //电台模式 58 | $song = $this->getSongByUser($room['room_user']); 59 | if ($song) { 60 | $this->playSong($room['room_id'], $song); 61 | } 62 | } else { 63 | if ($room['room_robot'] == 0) { 64 | $song = $this->getSongByRobot(); 65 | $this->playSong($room['room_id'], $song); 66 | } 67 | } 68 | } 69 | } catch (\Exception $e) { 70 | print_r($e->getLine()); 71 | print_r($e->getMessage()); 72 | // print_r($song); 73 | // print_r($room['room_id']); 74 | cache('SongNow_' . $room['room_id'], null); 75 | continue; 76 | } 77 | } 78 | } 79 | } 80 | protected function addSongToList($room_id, $song) 81 | { 82 | $songList = cache('SongList_' . $room_id) ?? []; 83 | $isExist = false; 84 | for ($i = 0; $i < count($songList); $i++) { 85 | if ($songList[$i]['song']['mid'] == $song['song']['mid']) { 86 | $isExist = true; 87 | } 88 | } 89 | if (!$isExist) { 90 | array_push($songList, $song); 91 | cache('SongList_' . $room_id, $songList, 86400); 92 | } 93 | } 94 | protected function preLoadMusicUrl($room) 95 | { 96 | $preRoomId = $room['room_id']; 97 | $songList = $this->getSongList($preRoomId); 98 | $song = false; 99 | if (count($songList) > 0) { 100 | $song = $songList[0]; 101 | } else { 102 | if ($room['room_type'] == 4) { 103 | $song = $this->getSongByUser($room['room_user']); 104 | } else { 105 | if ($room['room_robot'] == 0) { 106 | $song = $this->getSongByRobot(); 107 | } 108 | } 109 | if ($song) { 110 | $this->addSongToList($preRoomId, $song); 111 | } 112 | } 113 | if (!$song) { 114 | return; 115 | } 116 | $preMid = $song['song']['mid']; 117 | if ($preMid > 0) { 118 | $preSong = cache('song_play_temp_url_' . $preMid) ?? false; 119 | $preCount = cache('song_pre_load_count') ?? 0; 120 | if (!$preSong && $preCount < 5) { 121 | print_r("请缓存 " . $room['room_id'] . " " . $preMid); 122 | cache('song_pre_load_count', $preCount + 1, 60); 123 | $url = 'http://kuwo.cn/url?rid=' . $preMid . '&type=convert_url3&br=128kmp3'; 124 | $result = curlHelper($url)['body']; 125 | $arr = json_decode($result, true); 126 | if ($arr['code'] == 200) { 127 | if ($arr['url']) { 128 | $tempList = cache('song_waiting_download_list') ?? []; 129 | array_push($tempList, [ 130 | 'mid' => $preMid, 131 | 'url' => $arr['url'] 132 | ]); 133 | cache('song_waiting_download_list', $tempList); 134 | cache('song_play_temp_url_' . $preMid, $arr['url'], 3600); 135 | } 136 | } 137 | } 138 | } else { 139 | //用户自己上传的歌曲 刷新一遍CDN 140 | $isCdnLoaded = cache('cdn_load_mid_' . $preMid) ?? false; 141 | if (!$isCdnLoaded) { 142 | $loadUrl = config('startadmin.api_url') . "/api/song/playurl?mid=" . $preMid; 143 | echo $loadUrl . PHP_EOL; 144 | $ch = curl_init(); 145 | $curl_opt = array( 146 | CURLOPT_URL, $loadUrl, 147 | CURLOPT_RETURNTRANSFER, 1, 148 | CURLOPT_TIMEOUT, 1, 149 | CURLOPT_SSL_VERIFYPEER, false, 150 | CURLOPT_SSL_VERIFYHOST, false 151 | ); 152 | curl_setopt_array($ch, $curl_opt); 153 | curl_exec($ch); 154 | curl_close($ch); 155 | cache('cdn_load_mid_' . $preMid, 1, 60); 156 | } 157 | } 158 | $isPreloadSend = cache('pre_load_mid_' . $preMid) ?? false; 159 | if (!$isPreloadSend) { 160 | $msg = [ 161 | "url" => config('startadmin.api_url') . "/api/song/playurl?mid=" . $preMid, 162 | "type" => "preload", 163 | "time" => date('H:i:s'), 164 | ]; 165 | sendWebsocketMessage('channel', $preRoomId, $msg); 166 | cache('pre_load_mid_' . $preMid, 1, 60); 167 | } 168 | } 169 | protected function getSongByUser($user_id) 170 | { 171 | $userModel = new UserModel(); 172 | $songModel = new SongModel(); 173 | $playerWaitSong = $songModel->where('song_user', $user_id)->orderRand()->find(); 174 | if (!$playerWaitSong) { 175 | return false; 176 | } 177 | $playerWaitSong = [ 178 | 'mid' => $playerWaitSong['song_mid'], 179 | 'name' => $playerWaitSong['song_name'], 180 | 'pic' => $playerWaitSong['song_pic'] ?? '', 181 | 'length' => $playerWaitSong['song_length'], 182 | 'singer' => $playerWaitSong['song_singer'], 183 | ]; 184 | $user = $userModel->where('user_id', $user_id)->find(); 185 | if (!$user) { 186 | return false; 187 | } 188 | $song = [ 189 | 'user' => getUserData($user), 190 | 'song' => $playerWaitSong, 191 | 'since' => time(), 192 | ]; 193 | return $song; 194 | } 195 | protected function playSong($room_id, $song, $last = false) 196 | { 197 | if ($last) { 198 | cache('SongNow_' . $room_id, $song); 199 | } else { 200 | cache('SongNow_' . $room_id, $song, 3600); 201 | } 202 | $songList = $this -> getSongList($room_id); 203 | 204 | cache("song_detail_" . $song['song']['mid'], $song['song'], 3600); 205 | $msg = [ 206 | 'at' => $song['at'] ?? false, 207 | 'user' => $song['user'], 208 | 'song' => $song['song'], 209 | 'since' => $song['since'], 210 | "type" => "playSong", 211 | "time" => date('H:i:s'), 212 | 'count' => count($songList) ?? 0 213 | ]; 214 | sendWebsocketMessage('channel', $room_id, $msg); 215 | } 216 | protected function getPlayingSong($room_id) 217 | { 218 | return cache('SongNow_' . $room_id) ?? false; 219 | } 220 | protected function getSongFromList($room_id) 221 | { 222 | $songList = cache('SongList_' . $room_id) ?? []; 223 | if (count($songList) > 0) { 224 | $songNow = $songList[0]; 225 | $songNow['since'] = time() + 5; 226 | array_shift($songList); 227 | cache('SongList_' . $room_id, $songList, 86400); 228 | return $songNow; 229 | } else { 230 | return false; 231 | } 232 | } 233 | protected function getSongList($room_id) 234 | { 235 | $songList = cache('SongList_' . $room_id) ?? []; 236 | return $songList; 237 | } 238 | protected function getRoomList() 239 | { 240 | $roomModel = new RoomModel(); 241 | $rooms = cache('RoomList') ?? false; 242 | if (!$rooms) { 243 | $rooms = $roomModel->field('room_id,room_robot,room_type,room_playone,room_user')->where('room_type in (1,4) and room_realonline > 0 or room_id = 888')->select(); 244 | $rooms = $rooms ? $rooms->toArray() : []; 245 | if ($rooms) { 246 | cache('RoomList', $rooms, 5); 247 | } 248 | } 249 | return $rooms; 250 | } 251 | protected function getSongByRobot() 252 | { 253 | // 从热门榜单中随机点一首歌 254 | $bangIdArray = [278, 284, 26, 64, 187, 281, 153, 17, 16, 158, 145, 93, 185, 290, 279, 264, 283, 282, 255]; 255 | $bangId = $bangIdArray[rand(0, count($bangIdArray) - 1)]; 256 | $randNumber = rand(10000000, 99999999); 257 | //function curlHelper($url, $method = 'GET', $data = null, $header = [], $cookies = "") 258 | $result = curlHelper('http://kuwo.cn/api/www/bang/bang/musicList?bangId=' . $bangId . '&pn=1&rn=100', 'GET', null, [ 259 | 'csrf: ' . $randNumber, 260 | ], "kw_token=" . $randNumber); 261 | if (!$result['body']) { 262 | return false; 263 | } 264 | $arr = json_decode($result['body'], true); 265 | if ($arr['code'] != 200) { 266 | return false; 267 | } 268 | $list = $arr['data']['musicList']; 269 | $song = $list[rand(0, count($list) - 1)]; 270 | cache('song_detail_' . $song['rid'], [ 271 | 'mid' => $song['rid'], 272 | 'name' => $song['name'], 273 | 'pic' => $song['pic'], 274 | 'length' => $song['duration'], 275 | 'singer' => $song['artist'], 276 | ], 3600); 277 | 278 | $userModel = new UserModel(); 279 | $robotInfo = $userModel->where("user_id", 1)->find(); 280 | return [ 281 | 'song' => [ 282 | 'mid' => $song['rid'], 283 | 'name' => $song['name'], 284 | 'pic' => $song['pic'], 285 | 'length' => $song['duration'], 286 | 'singer' => $song['artist'], 287 | ], 288 | 'since' => time(), 289 | 'count' => 1, 290 | 'user' => [ 291 | "app_id" => 1, 292 | "app_name" => "BBBUG", 293 | "app_url" => "https://bbbug.com", 294 | "user_admin" => $robotInfo['user_admin'], 295 | "user_head" => $robotInfo['user_head'], 296 | "user_id" => $robotInfo['user_id'], 297 | "user_name" => rawurldecode($robotInfo['user_name']), 298 | "user_remark" => rawurldecode($robotInfo['user_remark']), 299 | ], 300 | ]; 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /app/common.php: -------------------------------------------------------------------------------- 1 | $value) 7 | { 8 | if ($value !== '') 9 | { 10 | $str .= $key . '=' . urlencode($value) . '&'; 11 | } 12 | } 13 | $str .= 'app_key=' . $appkey; 14 | $sign = strtoupper(md5($str)); 15 | return $sign; 16 | } 17 | function getTempToken() 18 | { 19 | return config('startadmin.api_guest_token'); 20 | } 21 | function getUserData($user) 22 | { 23 | return [ 24 | "user_id" => $user['user_id'], 25 | "user_icon" => $user['user_icon'], 26 | "user_touchtip" => rawurldecode($user['user_touchtip']), 27 | "user_sex" => $user['user_sex'], 28 | "user_vip" => $user['user_vip'], 29 | "user_extra" => $user['user_extra'], 30 | "user_device" => $user['user_device'], 31 | "user_name" => ($user['user_name']), 32 | "user_head" => ($user['user_head']), 33 | "user_remark" => ($user['user_remark']), 34 | "app_id" => $user['app_id'], 35 | "app_name" => $user['app_name'], 36 | "app_url" => $user['app_url'], 37 | "user_admin" => getIsAdmin($user), 38 | ]; 39 | } 40 | function getTopHost($url){ 41 | $url = strtolower($url); //首先转成小写 42 | $hosts = parse_url($url); 43 | return $hosts['host'] ?? ''; 44 | } 45 | function getIsAdmin($user) 46 | { 47 | return in_array($user['user_group'], [1]); 48 | } 49 | function getWebsocketApiUrl() 50 | { 51 | return config('startadmin.websocket_http'); 52 | } 53 | function sendWebsocketMessage($type,$to,$msg){ 54 | $ret = curlHelper(getWebsocketApiUrl(), "POST", http_build_query([ 55 | 'type' => $type, 56 | 'to' => $to, 57 | 'token' => sha1(config('startadmin.websocket_token')), 58 | 'msg' => json_encode($msg), 59 | ]), [ 60 | 'content-type:application/x-www-form-rawurlencode', 61 | ]); 62 | } 63 | /** 64 | * 输出正常JSON 65 | * 66 | * @param string 提示信息 67 | * @param array 输出数据 68 | * @return json 69 | */ 70 | function jok($msg = 'success', $data = null) 71 | { 72 | header("content-type:application/json;chartset=uft-8"); 73 | if ($data !== null) { 74 | echo json_encode(["code" => 200, "msg" => $msg, 'data' => $data]); 75 | } else { 76 | echo json_encode(["code" => 200, "msg" => $msg]); 77 | } 78 | die; 79 | } 80 | /** 81 | * 输出错误JSON 82 | * 83 | * @param string 错误信息 84 | * @param int 错误代码 85 | * @return json 86 | */ 87 | function jerr($msg = 'error', $code = 500) 88 | { 89 | header("content-type:application/json;chartset=uft-8"); 90 | echo json_encode(["code" => $code, "msg" => $msg]); 91 | die; 92 | } 93 | /** 94 | * 密码+盐 加密 95 | * 96 | * @param string 明文密码 97 | * @param string 盐 98 | * @return string 99 | */ 100 | function encodePassword($password, $salt) 101 | { 102 | return sha1($password . $salt . $password . $salt); 103 | } 104 | /** 105 | * 密码校验 6-16 106 | * 107 | * @param string 明文密码 108 | * @return boolean 是否校验通过 109 | */ 110 | function isValidPassword($password) 111 | { 112 | return preg_match('/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?!.*\s).{6,}/', $password); 113 | } 114 | /** 115 | * 获取随机字符 116 | * 117 | * @param int $len 118 | * @return void 119 | */ 120 | function getRandString($len) 121 | { 122 | $string = ''; 123 | $randString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 124 | for ($i = 0; $i < $len; $i++) { 125 | $string .= $randString[rand(0, strlen($randString) - 1)]; 126 | } 127 | return $string; 128 | } 129 | /** 130 | * 获取随机字母 131 | * 132 | * @param int 长度 133 | * @return string 134 | */ 135 | function getRandChar($len) 136 | { 137 | $string = ''; 138 | $randString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 139 | for ($i = 0; $i < $len; $i++) { 140 | $string .= $randString[rand(0, strlen($randString) - 1)]; 141 | } 142 | return $string; 143 | } 144 | /** 145 | * 遍历类的方法 146 | * 147 | * @param string 指定的类名称 148 | * @return array 149 | */ 150 | function getClassMethods($class) 151 | { 152 | $array_result = []; 153 | $array_all = get_class_methods($class); 154 | if ($parent_class = get_parent_class($class)) { 155 | $array_parent = get_class_methods($parent_class); 156 | $array_result = array_diff($array_all, $array_parent); 157 | } else { 158 | $array_result = $array_all; 159 | } 160 | return $array_result; 161 | } 162 | /** 163 | * 获取包含协议和端口的域名 164 | * 165 | * @return string 166 | */ 167 | function getFullDomain() 168 | { 169 | return ($_SERVER['HTTP_X_FORWARDED_PROTO'] ?? $_SERVER['REQUEST_SCHEME']) . "://" . $_SERVER['HTTP_HOST']; 170 | } 171 | /** 172 | * 获取客户端IP 173 | * 174 | * @return string 175 | */ 176 | function getClientIp() 177 | { 178 | foreach (array( 179 | 'HTTP_CLIENT_IP', 180 | 'HTTP_X_FORWARDED_FOR', 181 | 'HTTP_X_FORWARDED', 182 | 'HTTP_X_CLUSTER_CLIENT_IP', 183 | 'HTTP_FORWARDED_FOR', 184 | 'HTTP_FORWARDED', 185 | 'REMOTE_ADDR', 186 | ) as $key) { 187 | if (array_key_exists($key, $_SERVER)) { 188 | foreach (explode(',', $_SERVER[$key]) as $ip) { 189 | $ip = trim($ip); 190 | if ((bool) filter_var( 191 | $ip, 192 | FILTER_VALIDATE_IP, 193 | FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 194 | // FILTER_FLAG_NO_PRIV_RANGE | 195 | // FILTER_FLAG_NO_RES_RANGE 196 | )) { 197 | return $ip; 198 | } 199 | } 200 | } 201 | } 202 | return null; 203 | } 204 | 205 | /** 206 | * 取文本中间 207 | * 208 | * @param string 原始字符串 209 | * @param string 左边字符串 210 | * @param string 右边字符串 211 | * @return string 212 | */ 213 | function getSubstr($str, $leftStr, $rightStr) 214 | { 215 | $left = strpos($str, $leftStr); 216 | $right = strpos($str, $rightStr, $left); 217 | if ($left < 0 or $right < $left) { 218 | return ''; 219 | } 220 | 221 | return substr($str, $left + strlen($leftStr), $right - $left - strlen($leftStr)); 222 | } 223 | /** 224 | * 获取操作系统 225 | * 226 | * @return string 227 | */ 228 | function getOs() 229 | { 230 | if (empty($_SERVER['HTTP_USER_AGENT'])) { 231 | return 'Other'; 232 | } 233 | $agent = strtolower($_SERVER['HTTP_USER_AGENT']); 234 | if (strpos($agent, 'windows nt')) { 235 | $platform = 'Windows'; 236 | } elseif (strpos($agent, 'macintosh')) { 237 | $platform = 'MacOS'; 238 | } elseif (strpos($agent, 'ipod')) { 239 | $platform = 'iPod'; 240 | } elseif (strpos($agent, 'ipad')) { 241 | $platform = 'iPad'; 242 | } elseif (strpos($agent, 'iphone')) { 243 | $platform = 'iPhone'; 244 | } elseif (strpos($agent, 'android')) { 245 | $platform = 'Android'; 246 | } elseif (strpos($agent, 'unix')) { 247 | $platform = 'Unix'; 248 | } elseif (strpos($agent, 'linux')) { 249 | $platform = 'Linux'; 250 | } else { 251 | $platform = 'Other'; 252 | } 253 | return $platform; 254 | } 255 | /** 256 | * 获取浏览器 257 | * 258 | * @return void 259 | */ 260 | function getBrowser() 261 | { 262 | if (empty($_SERVER['HTTP_USER_AGENT'])) { 263 | return 'Unknown'; 264 | } 265 | $agent = $_SERVER["HTTP_USER_AGENT"]; 266 | if (strpos($agent, 'MSIE') !== false || strpos($agent, 'rv:11.0')) //ie11判断 267 | { 268 | return "IE"; 269 | } else if (strpos($agent, 'Firefox') !== false) { 270 | return "Firefox"; 271 | } else if (strpos($agent, 'Chrome') !== false) { 272 | return "Chrome"; 273 | } else if (strpos($agent, 'Opera') !== false) { 274 | return 'Opera'; 275 | } else if ((strpos($agent, 'Chrome') == false) && strpos($agent, 'Safari') !== false) { 276 | return 'Safari'; 277 | } else { 278 | return 'Unknown'; 279 | } 280 | } 281 | /** 282 | * 是否手机请求 283 | * 284 | * @return boolean 285 | */ 286 | function isMobileRequest() 287 | { 288 | $_SERVER['ALL_HTTP'] = isset($_SERVER['ALL_HTTP']) ? $_SERVER['ALL_HTTP'] : ''; 289 | $mobile_browser = '0'; 290 | if (preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone|iphone|uc|qq|wechat|micro|messenger|ipad|ipod|android|xoom)/i', strtolower($_SERVER['HTTP_USER_AGENT']))) { 291 | $mobile_browser++; 292 | } 293 | 294 | if ((isset($_SERVER['HTTP_ACCEPT'])) and (strpos(strtolower($_SERVER['HTTP_ACCEPT']), 'application/vnd.wap.xhtml+xml') !== false)) { 295 | $mobile_browser++; 296 | } 297 | 298 | if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) { 299 | $mobile_browser++; 300 | } 301 | 302 | if (isset($_SERVER['HTTP_PROFILE'])) { 303 | $mobile_browser++; 304 | } 305 | 306 | $mobile_ua = strtolower(substr($_SERVER['HTTP_USER_AGENT'], 0, 4)); 307 | $mobile_agents = array( 308 | 'w3c ', 'acs-', 'alav', 'alca', 'amoi', 'audi', 'avan', 'benq', 'bird', 'blac', 309 | 'blaz', 'brew', 'cell', 'cldc', 'cmd-', 'dang', 'doco', 'eric', 'hipt', 'inno', 310 | 'ipaq', 'java', 'jigs', 'kddi', 'keji', 'leno', 'lg-c', 'lg-d', 'lg-g', 'lge-', 311 | 'maui', 'maxo', 'midp', 'mits', 'mmef', 'mobi', 'mot-', 'moto', 'mwbp', 'nec-', 312 | 'newt', 'noki', 'oper', 'palm', 'pana', 'pant', 'phil', 'play', 'port', 'prox', 313 | 'qwap', 'sage', 'sams', 'sany', 'sch-', 'sec-', 'send', 'seri', 'sgh-', 'shar', 314 | 'sie-', 'siem', 'smal', 'smar', 'sony', 'sph-', 'symb', 't-mo', 'teli', 'tim-', 315 | 'tosh', 'tsm-', 'upg1', 'upsi', 'vk-v', 'voda', 'wap-', 'wapa', 'wapi', 'wapp', 316 | 'wapr', 'webc', 'winw', 'winw', 'xda', 'xda-', 317 | ); 318 | if (in_array($mobile_ua, $mobile_agents)) { 319 | $mobile_browser++; 320 | } 321 | 322 | if (strpos(strtolower($_SERVER['ALL_HTTP']), 'operamini') !== false) { 323 | $mobile_browser++; 324 | } 325 | 326 | // Pre-final check to reset everything if the user is on Windows 327 | if (strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows') !== false) { 328 | $mobile_browser = 0; 329 | } 330 | 331 | // But WP7 is also Windows, with a slightly different characteristic 332 | if (strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows phone') !== false) { 333 | $mobile_browser++; 334 | } 335 | 336 | if ($mobile_browser > 0) { 337 | return true; 338 | } else { 339 | return false; 340 | } 341 | 342 | } 343 | /** 344 | * 身份证号验证 345 | * @param $id 346 | * @return bool 347 | */ 348 | function isIDCard($id) 349 | { 350 | $id = strtoupper($id); 351 | $regx = "/(^\d{15}$)|(^\d{17}([0-9]|X)$)/"; 352 | $arr_split = array(); 353 | if (!preg_match($regx, $id)) { 354 | return false; 355 | } 356 | if (15 == strlen($id)) //检查15位 357 | { 358 | $regx = "/^(\d{6})+(\d{2})+(\d{2})+(\d{2})+(\d{3})$/"; 359 | @preg_match($regx, $id, $arr_split); 360 | //检查生日日期是否正确 361 | $dtm_birth = "19" . $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4]; 362 | if (!strtotime($dtm_birth)) { 363 | return false; 364 | } else { 365 | return true; 366 | } 367 | } else { //检查18位 368 | $regx = "/^(\d{6})+(\d{4})+(\d{2})+(\d{2})+(\d{3})([0-9]|X)$/"; 369 | @preg_match($regx, $id, $arr_split); 370 | $dtm_birth = $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4]; 371 | if (!strtotime($dtm_birth)) //检查生日日期是否正确 372 | { 373 | return false; 374 | } else { 375 | //检验18位身份证的校验码是否正确。 376 | //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。 377 | $arr_int = array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); 378 | $arr_ch = array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); 379 | $sign = 0; 380 | for ($i = 0; $i < 17; $i++) { 381 | $b = (int) $id[$i]; 382 | $w = $arr_int[$i]; 383 | $sign += $b * $w; 384 | } 385 | $n = $sign % 11; 386 | $val_num = $arr_ch[$n]; 387 | if ($val_num != substr($id, 17, 1)) { 388 | return false; 389 | } else { 390 | return true; 391 | } 392 | } 393 | } 394 | } 395 | /** 396 | * 是否是整数 397 | * 398 | * @param string 输入内容 399 | * @return boolean 400 | */ 401 | function isInteger($input) 402 | { 403 | return (ctype_digit(strval($input))); 404 | } 405 | function hmac($data, $key) 406 | { 407 | if (function_exists('hash_hmac')) { 408 | return hash_hmac('md5', $data, $key); 409 | } 410 | 411 | $key = (strlen($key) > 64) ? pack('H32', 'md5') : str_pad($key, 64, chr(0)); 412 | $ipad = substr($key, 0, 64) ^ str_repeat(chr(0x36), 64); 413 | $opad = substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64); 414 | return md5($opad . pack('H32', md5($ipad . $data))); 415 | } 416 | /** 417 | * 获取一个key摘要 418 | * 419 | * @param string 原始key 420 | * @return string 421 | */ 422 | function getTicket($key) 423 | { 424 | return sha1($key . (env('SYSTEM_SALT') ?? 'StartAdmin') . $key); 425 | } 426 | /** 427 | * CURL请求 428 | * 429 | * @param string URL地址 430 | * @param mixed 请求方法,支持GET/POST/PUT/DELETE/PATCH/TRACE/OPTION/HEAD 默认GET 431 | * @param mixed 请求数据包体 432 | * @param mixed 请求头 数组 433 | * @param mixed 请求COOKIES字符串 434 | * @return void 435 | */ 436 | function curlHelper($url, $method = 'GET', $data = null, $header = [], $cookies = "") 437 | { 438 | $ch = curl_init(); 439 | curl_setopt($ch, CURLOPT_URL, $url); 440 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 441 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 442 | curl_setopt($ch, CURLOPT_HTTPHEADER, $header); 443 | curl_setopt($ch, CURLOPT_COOKIE, $cookies); 444 | switch ($method) { 445 | case "GET": 446 | curl_setopt($ch, CURLOPT_HTTPGET, true); 447 | break; 448 | case "POST": 449 | curl_setopt($ch, CURLOPT_POST, true); 450 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 451 | break; 452 | case "PUT": 453 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); 454 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 455 | break; 456 | case "DELETE": 457 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE"); 458 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 459 | break; 460 | case "PATCH": 461 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PATCH"); 462 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 463 | break; 464 | case "TRACE": 465 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "TRACE"); 466 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 467 | break; 468 | case "OPTIONS": 469 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "OPTIONS"); 470 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 471 | break; 472 | case "HEAD": 473 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "HEAD"); 474 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 475 | break; 476 | default: 477 | } 478 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 479 | curl_setopt($ch, CURLOPT_HEADER, 1); 480 | curl_setopt($ch, CURLOPT_TIMEOUT,3); //只需要设置一个秒的数量就可以 481 | $response = curl_exec($ch); 482 | $output = []; 483 | $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); 484 | // 根据头大小去获取头信息内容 485 | $output['header'] = substr($response, 0, $headerSize); 486 | $output['body'] = substr($response, $headerSize, strlen($response) - $headerSize); 487 | $output['detail'] = curl_getinfo($ch); 488 | curl_close($ch); 489 | return $output; 490 | } 491 | /** 492 | * 模拟表单上传文件请求 493 | * @param $$url 提交地址 494 | * @param $data 提交数据 495 | * @param $cookies 如设置了Content-Type将被自动覆写为formdata 496 | * ex. 497 | * $data = ['file'=>new \CURLFile(realpath($file_dir)),appid"=>"1234"]; 498 | * $result = curl_form($url,$data); 499 | * @return mixed 500 | */ 501 | function curlForm($url, $data = null, $header = [], $cookies = "") 502 | { 503 | $header[] = 'Content-Type: multipart/form-data'; 504 | return curlHelper($url, "POST", $data, $header, $cookies); 505 | } 506 | /** 507 | * 多维数组合并(支持多数组) 508 | * @param arraylist arrayMergeMulti(['1'=>'1','2'=>'2','3'=>'3'],['4'=>'4','5'=>'5','6'=>'6']) 509 | * @return array 510 | */ 511 | function arrayMergeMulti() 512 | { 513 | //获取当前方法捕获到的所有参数数组 514 | $args = func_get_args(); 515 | $array = []; 516 | foreach ($args as $arg) { 517 | if (is_array($arg)) { 518 | foreach ($arg as $k => $v) { 519 | if (is_array($v)) { 520 | $array[$k] = isset($array[$k]) ? $array[$k] : []; 521 | $array[$k] = arrayMergeMulti($array[$k], $v); 522 | } else { 523 | $array[$k] = $v; 524 | } 525 | } 526 | } 527 | } 528 | 529 | return $array; 530 | } 531 | /** 532 | * 对查询结果集进行排序 533 | * @access public 534 | * @param array $list 查询结果 535 | * @param string $field 排序的字段名 536 | * @param array $sortBy 排序类型 537 | * asc正向排序 desc逆向排序 nat自然排序 538 | * @return array|bool 539 | */ 540 | function listSortBy($list, $field, $sortBy = 'asc') 541 | { 542 | if (is_array($list)) { 543 | $refer = $resultSet = []; 544 | foreach ($list as $i => $data) { 545 | $refer[$i] = &$data[$field]; 546 | } 547 | switch ($sortBy) { 548 | case 'asc': // 正向排序 549 | asort($refer); 550 | break; 551 | case 'desc': // 逆向排序 552 | arsort($refer); 553 | break; 554 | case 'nat': // 自然排序 555 | natcasesort($refer); 556 | break; 557 | } 558 | foreach ($refer as $key => $val) { 559 | $resultSet[] = &$list[$key]; 560 | } 561 | return $resultSet; 562 | } 563 | 564 | return false; 565 | } 566 | 567 | /** 568 | * 格式化字节大小 569 | * @param number $size 字节数 570 | * @param int $float 小数保留位数 571 | * @param string $delimiter 数字和单位分隔符 572 | * @return string 格式化后的带单位的大小 573 | */ 574 | function formatBytes($size, $float = 2, $delimiter = '') 575 | { 576 | $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']; 577 | for ($i = 0; $size >= 1024 && $i < 5; $i++) { 578 | $size /= 1024; 579 | } 580 | 581 | return round($size, $float) . $delimiter . $units[$i]; 582 | } 583 | /** 584 | * 生成标准UUID 585 | * 586 | * @return string 587 | */ 588 | function getUuid() 589 | { 590 | mt_srand((float) microtime() * 10000); 591 | $uuid = sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535)); 592 | return $uuid; 593 | } 594 | -------------------------------------------------------------------------------- /app/event.php: -------------------------------------------------------------------------------- 1 | [ 5 | ], 6 | 7 | 'listen' => [ 8 | 'AppInit' => [], 9 | 'HttpRun' => [], 10 | 'HttpEnd' => [], 11 | 'LogLevel' => [], 12 | 'LogWrite' => [], 13 | ], 14 | 15 | 'subscribe' => [ 16 | ], 17 | ]; 18 | -------------------------------------------------------------------------------- /app/index/BaseController.php: -------------------------------------------------------------------------------- 1 | app = $app; 34 | $this->request = $this->app->request; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/index/controller/Error.php: -------------------------------------------------------------------------------- 1 | Hello BBBUG.COM!"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/middleware.php: -------------------------------------------------------------------------------- 1 | where([ 20 | "access_user" => $access_user, 21 | "access_plat" => $access_plat, 22 | ])->update(['access_status' => 1]); 23 | //生成一个新的Access_token 24 | $access_token = sha1(time()) . rand(100000, 99999) . sha1(time()); 25 | $access_id = $this->insertGetId([ 26 | "access_user" => $access_user, 27 | "access_plat" => $access_plat, 28 | "access_token" => $access_token, 29 | "access_ip" => request()->ip(), 30 | "access_createtime" => time(), 31 | "access_updatetime" => time(), 32 | ]); 33 | $access = $this->where("access_id", $access_id)->find(); 34 | return $access ?? false; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/model/App.php: -------------------------------------------------------------------------------- 1 | where([ 26 | "conf_key" => $key, 27 | "conf_readonly" => 0, 28 | ])->update($data); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/model/Keywords.php: -------------------------------------------------------------------------------- 1 | view('room', $field)->view('user', 'user_id,user_name,user_group,user_head', 'room.room_user = user.user_id'); 12 | 13 | $resource = $resource->whereRaw("(room_online > 0 or room_order > 1000000) and room_hide = 0"); 14 | if ($order) { 15 | $resource = $resource->order($order); 16 | } 17 | $list = $resource->select(); 18 | for ($i = 0; $i < count($list); $i++) { 19 | $list[$i]['room_name'] = urldecode($list[$i]['room_name']); 20 | $list[$i]['room_notice'] = urldecode($list[$i]['room_notice']); 21 | } 22 | return $list; 23 | } 24 | public function getRoomById($room_id) 25 | { 26 | $room = $this->where('room_id', $room_id)->find(); 27 | if ($room) { 28 | $room['room_name'] = urldecode($room['room_name']); 29 | $room['room_notice'] = urldecode($room['room_notice']); 30 | } 31 | return $room ?? false; 32 | } 33 | public function getRoomByUser($user_id) 34 | { 35 | $room = $this->where('room_user', $user_id)->find(); 36 | if ($room) { 37 | $room['room_name'] = urldecode($room['room_name']); 38 | $room['room_notice'] = urldecode($room['room_notice']); 39 | } 40 | return $room ?? false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/model/Sms.php: -------------------------------------------------------------------------------- 1 | where([ 20 | "user_account" => $user_account, 21 | ])->find(); 22 | 23 | if (preg_match("/^[1-9][0-9]*$/", $user_account)) { 24 | $user = $this->where([ 25 | "user_id" => $user_account, 26 | ])->find(); 27 | } 28 | if ($user) { 29 | //判断密码是否正确 30 | $salt = $user['user_salt']; 31 | $password = $user['user_password']; 32 | if ($password != encodePassword($user_password, $salt)) { 33 | return false; 34 | } 35 | return $user->toArray() ?? false; 36 | } else { 37 | return false; 38 | } 39 | } 40 | 41 | /** 42 | * 用户注册 43 | * 44 | * @param string 手机号 45 | * @param string 密码 46 | * @param string 昵称 47 | * @return void 48 | */ 49 | public function reg($phone, $password, $name) 50 | { 51 | $name = mb_substr($name, 0, $this->maxNickName, 'utf-8'); 52 | $name = rawurlencode($name); 53 | $salt = getRandString(4); 54 | $password = encodePassword($password, $salt); 55 | return $this->insert([ 56 | "user_account" => $phone, 57 | "user_password" => $password, 58 | "user_salt" => $salt, 59 | "user_name" => $name, 60 | "user_group" => config('startadmin.default_group') ?? 0, 61 | "user_ipreg" => request()->ip(), 62 | "user_remark" => $this->getOneRemark(), 63 | "user_createtime" => time(), 64 | "user_updatetime" => time(), 65 | ]); 66 | } 67 | public function getOneRemark() 68 | { 69 | $url = 'http://guozhivip.com/yy/api/api.php'; 70 | $result = curlHelper($url); 71 | if ($result['body']) { 72 | if (preg_match('/"(.*?)"/', $result['body'], $matches)) { 73 | $remark = $matches[1]; 74 | $remark = mb_substr($remark, 0, 100, 'utf-8'); 75 | return $remark; 76 | } 77 | } 78 | return '每个人都应该有签名,但偏偏我没有.'; 79 | } 80 | public function regByLogin($account, $name) 81 | { 82 | $name = mb_substr($name, 0, $this->maxNickName, 'utf-8'); 83 | $name = rawurlencode($name); 84 | return $this->insert([ 85 | "user_account" => $account, 86 | "user_password" => '123456', 87 | "user_salt" => 'Love', 88 | "user_name" => $name, 89 | "user_group" => config('startadmin.default_group') ?? 0, 90 | "user_ipreg" => request()->ip(), 91 | "user_remark" => $this->getOneRemark(), 92 | "user_createtime" => time(), 93 | "user_updatetime" => time(), 94 | ]); 95 | } 96 | public function regByOpen($account, $name, $head, $sex, $appid, $extra = '') 97 | { 98 | $name = mb_substr($name, 0, $this->maxNickName, 'utf-8'); 99 | $name = rawurlencode($name); 100 | return $this->insert([ 101 | "user_account" => sha1($account), 102 | "user_password" => '123456', 103 | "user_salt" => 'Love', 104 | "user_sex" => $sex, 105 | "user_head" => $head, 106 | "user_openid" => $account, 107 | "user_app" => $appid, 108 | "user_name" => $name, 109 | "user_group" => config('startadmin.default_group') ?? 0, 110 | "user_ipreg" => request()->ip(), 111 | "user_extra" => $extra, 112 | "user_remark" => $this->getOneRemark(), 113 | "user_createtime" => time(), 114 | "user_updatetime" => time(), 115 | ]); 116 | } 117 | 118 | /** 119 | * 重置密码 120 | * 121 | * @param string UID 122 | * @param string 密码 123 | * @return void 124 | */ 125 | public function motifyPassword($user_id, $password) 126 | { 127 | $access = new Access(); 128 | //将所有授权记录标记为失效 129 | $access->where('access_user', $user_id)->update(['access_status' => 1]); 130 | $salt = getRandString(4); 131 | $password = encodePassword($password, $salt); 132 | return $this->where([ 133 | "user_id" => $user_id, 134 | ])->update([ 135 | "user_password" => $password, 136 | "user_salt" => $salt, 137 | ]); 138 | } 139 | 140 | /** 141 | * 通过帐号获取用户信息 142 | * 143 | * @param string 帐号/手机号 144 | * @return void 145 | */ 146 | public function getUserByAccount($user_account) 147 | { 148 | $user = $this->where([ 149 | "user_account" => $user_account, 150 | ])->find(); 151 | if ($user) { 152 | return $user->toArray() ?? false; 153 | } else { 154 | return false; 155 | } 156 | } 157 | /** 158 | * AccessToken获取用户信息 159 | * 160 | * @param string access_token 161 | * @return void 162 | */ 163 | public function getUserByAccessToken($access_token) 164 | { 165 | $Access = new Access(); 166 | $access = $Access->where([ 167 | "access_token" => $access_token, 168 | "access_status" => 0, 169 | ])->find(); 170 | if ($access) { 171 | if (time() > $access['access_updatetime'] + 86400 * 7) { 172 | return false; 173 | } 174 | if ($access['access_updatetime'] - $access['access_createtime'] > 86400 * 31) { 175 | return false; 176 | } 177 | $Access->where([ 178 | "access_id" => $access['access_id'], 179 | ])->update([ 180 | 'access_updatetime' => time(), 181 | ]); 182 | $this->where("user_id", $access['access_user'])->update([ 183 | 'user_updatetime' => time(), 184 | ]); 185 | $user = $this->where("user_id", $access['access_user'])->find(); 186 | return $user->toArray() ?? false; 187 | } else { 188 | return false; 189 | } 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /app/model/Weapp.php: -------------------------------------------------------------------------------- 1 | Request::class, 8 | 'think\exception\Handle' => ExceptionHandle::class, 9 | ]; 10 | -------------------------------------------------------------------------------- /app/service.php: -------------------------------------------------------------------------------- 1 | =7.1.0", 18 | "topthink/framework": "^6.0.0", 19 | "topthink/think-orm": "^2.0", 20 | "topthink/think-multi-app": "^1.0", 21 | "topthink/think-view": "^1.0", 22 | "overtrue/wechat": "~4.0", 23 | "topthink/think-image": "^1.0", 24 | "phpmailer/phpmailer": "^6.1" 25 | }, 26 | "require-dev": { 27 | "symfony/var-dumper": "^4.2", 28 | "topthink/think-trace": "^1.0" 29 | }, 30 | "autoload": { 31 | "psr-4": { 32 | "app\\": "app" 33 | }, 34 | "psr-0": { 35 | "": "extend/" 36 | } 37 | }, 38 | "config": { 39 | "preferred-install": "dist" 40 | }, 41 | "scripts": { 42 | "post-autoload-dump": [ 43 | "@php think service:discover", 44 | "@php think vendor:publish" 45 | ] 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /config/app.php: -------------------------------------------------------------------------------- 1 | env('app.host', ''), 9 | // 应用的命名空间 10 | 'app_namespace' => '', 11 | // 是否启用路由 12 | 'with_route' => true, 13 | // 是否启用事件 14 | 'with_event' => true, 15 | // 默认应用 16 | 'default_app' => 'index', 17 | // 默认时区 18 | 'default_timezone' => env('DEFAULT_TIMEZONE','Asia/Chongqing'), 19 | 20 | // 应用映射(自动多应用模式有效) 21 | 'app_map' => [], 22 | // 域名绑定(自动多应用模式有效) 23 | 'domain_bind' => [], 24 | // 禁止URL访问的应用列表(自动多应用模式有效) 25 | 'deny_app_list' => [], 26 | 27 | // 异常页面的模板文件 28 | 'exception_tmpl' => false, 29 | 30 | // 错误显示信息,非调试模式有效 31 | 'error_message' => '系统异常,请稍后再试。', 32 | // 显示错误信息 33 | 'show_error_msg' => false, 34 | ]; 35 | -------------------------------------------------------------------------------- /config/cache.php: -------------------------------------------------------------------------------- 1 | env('cache.driver', 'redis'), 10 | 11 | // 缓存连接方式配置 12 | 'stores' => [ 13 | 'file' => [ 14 | // 驱动方式 15 | 'type' => 'File', 16 | // 缓存保存目录 17 | 'path' => '', 18 | // 缓存前缀 19 | 'prefix' => '', 20 | // 缓存有效期 0表示永久缓存 21 | 'expire' => 0, 22 | // 缓存标签前缀 23 | 'tag_prefix' => 'tag:', 24 | // 序列化机制 例如 ['serialize', 'unserialize'] 25 | 'serialize' => [], 26 | ], 27 | 'redis' => [ 28 | 'type' => 'redis', 29 | 'host' => '127.0.0.1', 30 | 'port' => '6379', 31 | 'password' => '', 32 | 'select' => '0', 33 | // 全局缓存有效期(0为永久有效) 34 | 'expire' => 0, 35 | // 缓存前缀 36 | 'prefix' => 'bbbug_', 37 | 'timeout' => 0, 38 | ], 39 | ], 40 | ]; 41 | -------------------------------------------------------------------------------- /config/console.php: -------------------------------------------------------------------------------- 1 | [ 8 | 'Song' => 'app\command\Song', 9 | 'User' => 'app\command\User', 10 | 'Online' => 'app\command\Online', 11 | 'Download' => 'app\command\Download', 12 | 'Test' => 'app\command\Test', 13 | ], 14 | ]; 15 | -------------------------------------------------------------------------------- /config/cookie.php: -------------------------------------------------------------------------------- 1 | 0, 8 | // cookie 保存路径 9 | 'path' => '/', 10 | // cookie 有效域名 11 | 'domain' => '', 12 | // cookie 启用安全传输 13 | 'secure' => false, 14 | // httponly设置 15 | 'httponly' => false, 16 | // 是否使用 setcookie 17 | 'setcookie' => true, 18 | ]; 19 | -------------------------------------------------------------------------------- /config/database.php: -------------------------------------------------------------------------------- 1 | env('database.driver', 'mysql'), 6 | 7 | // 自定义时间查询规则 8 | 'time_query_rule' => [], 9 | 10 | // 自动写入时间戳字段 11 | // true为自动识别类型 false关闭 12 | // 字符串则明确指定时间字段类型 支持 int timestamp datetime date 13 | 'auto_timestamp' => true, 14 | 15 | // 时间字段取出后的默认时间格式 16 | 'datetime_format' => 'Y-m-d H:i:s', 17 | 18 | // 数据库连接配置信息 19 | 'connections' => [ 20 | 'mysql' => [ 21 | // 数据库类型 22 | 'type' => env('database.type', 'mysql'), 23 | // 服务器地址 24 | 'hostname' => env('database.hostname', '127.0.0.1'), 25 | // 数据库名 26 | 'database' => env('database.database', ''), 27 | // 用户名 28 | 'username' => env('database.username', 'root'), 29 | // 密码 30 | 'password' => env('database.password', ''), 31 | // 端口 32 | 'hostport' => env('database.hostport', '3306'), 33 | // 数据库连接参数 34 | 'params' => [], 35 | // 数据库编码默认采用utf8 36 | 'charset' => env('database.charset', 'utf8'), 37 | // 数据库表前缀 38 | 'prefix' => env('database.prefix', ''), 39 | 40 | // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) 41 | 'deploy' => 0, 42 | // 数据库读写是否分离 主从式有效 43 | 'rw_separate' => false, 44 | // 读写分离后 主服务器数量 45 | 'master_num' => 1, 46 | // 指定从服务器序号 47 | 'slave_no' => '', 48 | // 是否严格检查字段是否存在 49 | 'fields_strict' => true, 50 | // 是否需要断线重连 51 | 'break_reconnect' => false, 52 | // 监听SQL 53 | 'trigger_sql' => env('app_debug', true), 54 | // 开启字段缓存 55 | 'fields_cache' => false, 56 | // 字段缓存路径 57 | 'schema_cache_path' => app()->getRuntimePath() . 'schema' . DIRECTORY_SEPARATOR, 58 | ], 59 | 60 | // 更多的数据库配置信息 61 | ], 62 | ]; 63 | -------------------------------------------------------------------------------- /config/filesystem.php: -------------------------------------------------------------------------------- 1 | 'public', 6 | // 磁盘列表 7 | 'disks' => [ 8 | 'public' => [ 9 | 'type' => 'local', 10 | 'root' => 'uploads', 11 | ], 12 | ], 13 | ]; 14 | -------------------------------------------------------------------------------- /config/lang.php: -------------------------------------------------------------------------------- 1 | env('lang.default_lang', 'zh-cn'), 9 | // 允许的语言列表 10 | 'allow_lang_list' => [], 11 | // 多语言自动侦测变量名 12 | 'detect_var' => 'lang', 13 | // 是否使用Cookie记录 14 | 'use_cookie' => true, 15 | // 多语言cookie变量 16 | 'cookie_var' => 'think_lang', 17 | // 扩展语言包 18 | 'extend_list' => [], 19 | // Accept-Language转义为对应语言包名称 20 | 'accept_language' => [ 21 | 'zh-hans-cn' => 'zh-cn', 22 | ], 23 | // 是否支持语言分组 24 | 'allow_group' => false, 25 | ]; 26 | -------------------------------------------------------------------------------- /config/log.php: -------------------------------------------------------------------------------- 1 | env('log.channel', 'file'), 9 | // 日志记录级别 10 | 'level' => [], 11 | // 日志类型记录的通道 ['error'=>'email',...] 12 | 'type_channel' => [], 13 | // 关闭全局日志写入 14 | 'close' => false, 15 | // 全局日志处理 支持闭包 16 | 'processor' => null, 17 | 18 | // 日志通道列表 19 | 'channels' => [ 20 | 'file' => [ 21 | // 日志记录方式 22 | 'type' => 'File', 23 | // 日志保存目录 24 | 'path' => '', 25 | // 单文件日志写入 26 | 'single' => false, 27 | // 独立日志级别 28 | 'apart_level' => [], 29 | // 最大日志文件数量 30 | 'max_files' => 0, 31 | // 使用JSON格式记录 32 | 'json' => false, 33 | // 日志处理 34 | 'processor' => null, 35 | // 关闭通道日志写入 36 | 'close' => false, 37 | // 日志输出格式化 38 | 'format' => '[%s][%s] %s', 39 | // 是否实时写入 40 | 'realtime_write' => false, 41 | ], 42 | // 其它日志通道配置 43 | ], 44 | 45 | ]; 46 | -------------------------------------------------------------------------------- /config/middleware.php: -------------------------------------------------------------------------------- 1 | [], 6 | // 优先级设置,此数组中的中间件会按照数组中的顺序优先执行 7 | 'priority' => [], 8 | ]; 9 | -------------------------------------------------------------------------------- /config/route.php: -------------------------------------------------------------------------------- 1 | '/', 9 | // URL伪静态后缀 10 | 'url_html_suffix' => 'html', 11 | // URL普通方式参数 用于自动生成 12 | 'url_common_param' => true, 13 | // 是否开启路由延迟解析 14 | 'url_lazy_route' => false, 15 | // 是否强制使用路由 16 | 'url_route_must' => false, 17 | // 合并路由规则 18 | 'route_rule_merge' => false, 19 | // 路由是否完全匹配 20 | 'route_complete_match' => false, 21 | // 访问控制器层名称 22 | 'controller_layer' => 'controller', 23 | // 空控制器名 24 | 'empty_controller' => 'Error', 25 | // 是否使用控制器后缀 26 | 'controller_suffix' => false, 27 | // 默认的路由变量规则 28 | 'default_route_pattern' => '[\w\.]+', 29 | // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则 30 | 'request_cache' => false, 31 | // 请求缓存有效期 32 | 'request_cache_expire' => null, 33 | // 全局请求缓存排除规则 34 | 'request_cache_except' => [], 35 | // 默认控制器名 36 | 'default_controller' => 'Index', 37 | // 默认操作名 38 | 'default_action' => 'index', 39 | // 操作方法后缀 40 | 'action_suffix' => '', 41 | // 默认JSONP格式返回的处理方法 42 | 'default_jsonp_handler' => 'jsonpReturn', 43 | // 默认JSONP处理方法 44 | 'var_jsonp_handler' => 'callback', 45 | ]; 46 | -------------------------------------------------------------------------------- /config/session.php: -------------------------------------------------------------------------------- 1 | 'PHPSESSID', 9 | // SESSION_ID的提交变量,解决flash上传跨域 10 | 'var_session_id' => '', 11 | // 驱动方式 支持file cache 12 | 'type' => 'file', 13 | // 存储连接标识 当type使用cache的时候有效 14 | 'store' => null, 15 | // 过期时间 16 | 'expire' => 1440, 17 | // 前缀 18 | 'prefix' => '', 19 | ]; 20 | -------------------------------------------------------------------------------- /config/trace.php: -------------------------------------------------------------------------------- 1 | 'Console', 8 | // 读取的日志通道名 9 | 'channel' => '', 10 | ]; 11 | -------------------------------------------------------------------------------- /config/view.php: -------------------------------------------------------------------------------- 1 | 'Think', 9 | // 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法 10 | 'auto_rule' => 1, 11 | // 模板目录名 12 | 'view_dir_name' => 'view', 13 | // 模板后缀 14 | 'view_suffix' => 'html', 15 | // 模板文件名分隔符 16 | 'view_depr' => DIRECTORY_SEPARATOR, 17 | // 模板引擎普通标签开始标记 18 | 'tpl_begin' => '{', 19 | // 模板引擎普通标签结束标记 20 | 'tpl_end' => '}', 21 | // 标签库标签开始标记 22 | 'taglib_begin' => '{', 23 | // 标签库标签结束标记 24 | 'taglib_end' => '}', 25 | ]; 26 | -------------------------------------------------------------------------------- /extend/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | Options +FollowSymlinks -Multiviews 3 | RewriteEngine On 4 | 5 | RewriteCond %{REQUEST_FILENAME} !-d 6 | RewriteCond %{REQUEST_FILENAME} !-f 7 | RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] 8 | -------------------------------------------------------------------------------- /public/chrome.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | BBBUG音乐 4 | 一个快捷的MP3歌曲搜索工具 5 | BBBUG.COM 6 | admin@hamm.cn 7 | 8 | 9 | 10 | BBBUG开放音乐MP3搜索工具 11 | 12 | 13 | 14 | 15 | admin@hamm.cn 16 | 17 | 所有资源来源第三方,请勿进行商业或非法用途! 18 | 19 | open 20 | false 21 | zh-cn 22 | UTF-8 23 | UTF-8 24 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Fuck your bugs! 7 | 8 | 9 |
10 |

屌毛,你访问的文件路径呢?

11 |
12 |

Sorry but fuck your url path?!




14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | // [ 应用入口文件 ] 13 | namespace think; 14 | 15 | require __DIR__ . '/../vendor/autoload.php'; 16 | 17 | // 执行HTTP应用并响应 18 | $http = (new App())->http; 19 | 20 | $response = $http->run(); 21 | 22 | $response->send(); 23 | 24 | $http->end($response); 25 | -------------------------------------------------------------------------------- /public/new/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/favicon.ico -------------------------------------------------------------------------------- /public/new/images/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/bg.jpg -------------------------------------------------------------------------------- /public/new/images/bg_dark.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/bg_dark.jpg -------------------------------------------------------------------------------- /public/new/images/bg_light.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/bg_light.jpg -------------------------------------------------------------------------------- /public/new/images/button_emoji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/button_emoji.png -------------------------------------------------------------------------------- /public/new/images/button_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/button_image.png -------------------------------------------------------------------------------- /public/new/images/emoji/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/1.png -------------------------------------------------------------------------------- /public/new/images/emoji/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/10.png -------------------------------------------------------------------------------- /public/new/images/emoji/11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/11.png -------------------------------------------------------------------------------- /public/new/images/emoji/12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/12.png -------------------------------------------------------------------------------- /public/new/images/emoji/13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/13.png -------------------------------------------------------------------------------- /public/new/images/emoji/14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/14.png -------------------------------------------------------------------------------- /public/new/images/emoji/15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/15.png -------------------------------------------------------------------------------- /public/new/images/emoji/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/16.png -------------------------------------------------------------------------------- /public/new/images/emoji/17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/17.png -------------------------------------------------------------------------------- /public/new/images/emoji/18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/18.png -------------------------------------------------------------------------------- /public/new/images/emoji/19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/19.png -------------------------------------------------------------------------------- /public/new/images/emoji/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/2.png -------------------------------------------------------------------------------- /public/new/images/emoji/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/20.png -------------------------------------------------------------------------------- /public/new/images/emoji/21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/21.png -------------------------------------------------------------------------------- /public/new/images/emoji/22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/22.png -------------------------------------------------------------------------------- /public/new/images/emoji/23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/23.png -------------------------------------------------------------------------------- /public/new/images/emoji/24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/24.png -------------------------------------------------------------------------------- /public/new/images/emoji/25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/25.png -------------------------------------------------------------------------------- /public/new/images/emoji/26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/26.png -------------------------------------------------------------------------------- /public/new/images/emoji/27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/27.png -------------------------------------------------------------------------------- /public/new/images/emoji/28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/28.png -------------------------------------------------------------------------------- /public/new/images/emoji/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/29.png -------------------------------------------------------------------------------- /public/new/images/emoji/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/3.png -------------------------------------------------------------------------------- /public/new/images/emoji/30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/30.png -------------------------------------------------------------------------------- /public/new/images/emoji/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/4.png -------------------------------------------------------------------------------- /public/new/images/emoji/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/5.png -------------------------------------------------------------------------------- /public/new/images/emoji/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/6.png -------------------------------------------------------------------------------- /public/new/images/emoji/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/7.png -------------------------------------------------------------------------------- /public/new/images/emoji/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/8.png -------------------------------------------------------------------------------- /public/new/images/emoji/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/emoji/9.png -------------------------------------------------------------------------------- /public/new/images/error.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/error.jpg -------------------------------------------------------------------------------- /public/new/images/gh_42bdbe5c9412_1280.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/gh_42bdbe5c9412_1280.jpg -------------------------------------------------------------------------------- /public/new/images/linus.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/linus.jpg -------------------------------------------------------------------------------- /public/new/images/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/loading.gif -------------------------------------------------------------------------------- /public/new/images/loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/loading.png -------------------------------------------------------------------------------- /public/new/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/logo.png -------------------------------------------------------------------------------- /public/new/images/menubar_mysong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/menubar_mysong.png -------------------------------------------------------------------------------- /public/new/images/menubar_pickedsong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/menubar_pickedsong.png -------------------------------------------------------------------------------- /public/new/images/menubar_picksong.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/menubar_picksong.png -------------------------------------------------------------------------------- /public/new/images/menubar_selectroom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/menubar_selectroom.png -------------------------------------------------------------------------------- /public/new/images/menubar_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/menubar_setting.png -------------------------------------------------------------------------------- /public/new/images/menubar_upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/menubar_upload.png -------------------------------------------------------------------------------- /public/new/images/nohead.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/nohead.jpg -------------------------------------------------------------------------------- /public/new/images/player_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/player_bar.png -------------------------------------------------------------------------------- /public/new/images/player_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/player_bg.png -------------------------------------------------------------------------------- /public/new/images/qrcode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/qrcode.jpg -------------------------------------------------------------------------------- /public/new/images/snow1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/snow1.png -------------------------------------------------------------------------------- /public/new/images/snow2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/images/snow2.png -------------------------------------------------------------------------------- /public/new/mp3/ci.m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/mp3/ci.m4a -------------------------------------------------------------------------------- /public/new/mp3/da.m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/mp3/da.m4a -------------------------------------------------------------------------------- /public/new/mp3/dingdong.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/mp3/dingdong.mp3 -------------------------------------------------------------------------------- /public/new/mp3/dong.m4a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/mp3/dong.m4a -------------------------------------------------------------------------------- /public/new/mp3/message.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bbbug-com/BBBUG-API/ec7a9916b2f9e9ce88ea8eb2a23426df4fc0a47c/public/new/mp3/message.mp3 -------------------------------------------------------------------------------- /public/router.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | // $Id$ 12 | 13 | if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) { 14 | return false; 15 | } else { 16 | $_SERVER["SCRIPT_FILENAME"] = __DIR__ . '/index.php'; 17 | 18 | require __DIR__ . "/index.php"; 19 | } 20 | -------------------------------------------------------------------------------- /public/sdk/bbbug.js: -------------------------------------------------------------------------------- 1 | var BBBUG = { 2 | sendTextMessage(message) { 3 | parent.window.postMessage({ 4 | event: "sendTextMessage", 5 | message: message 6 | }, "*"); 7 | }, 8 | hideLrc() { 9 | parent.window.postMessage({ 10 | event: "hideLrc" 11 | }, "*"); 12 | }, 13 | showLrc() { 14 | parent.window.postMessage({ 15 | event: "showLrc" 16 | }, "*"); 17 | }, 18 | setVolume(volume) { 19 | parent.window.postMessage({ 20 | event: "setVolume", 21 | volume: volume 22 | }, "*"); 23 | }, 24 | showUserInfo(userId) { 25 | parent.window.postMessage({ 26 | event: "showUserInfo", 27 | userId: userId 28 | }, "*"); 29 | }, 30 | showPlayer() { 31 | parent.window.postMessage({ 32 | event: "showPlayer" 33 | }, "*"); 34 | }, 35 | hidePlayer() { 36 | parent.window.postMessage({ 37 | event: "hidePlayer" 38 | }, "*"); 39 | }, 40 | passTheSong() { 41 | parent.window.postMessage({ 42 | event: "passTheSong" 43 | }, "*"); 44 | }, 45 | loveTheSong() { 46 | parent.window.postMessage({ 47 | event: "loveTheSong" 48 | }, "*"); 49 | }, 50 | getNowSong() { 51 | parent.window.postMessage({ 52 | event: "getNowSong" 53 | }, "*"); 54 | }, 55 | getLrcObj() { 56 | parent.window.postMessage({ 57 | event: "getLrcObj" 58 | }, "*"); 59 | }, 60 | getThemeMode() { 61 | parent.window.postMessage({ 62 | event: "getThemeMode" 63 | }, "*"); 64 | }, 65 | hideAll() { 66 | parent.window.postMessage({ 67 | event: "hideAll" 68 | }, "*"); 69 | }, 70 | sendImage(url) { 71 | parent.window.postMessage({ 72 | event: "sendImage", 73 | url: url 74 | }, "*"); 75 | }, 76 | getMessageList() { 77 | parent.window.postMessage({ 78 | event: "getMessageList", 79 | }, "*"); 80 | } 81 | }; -------------------------------------------------------------------------------- /public/uploads/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /route/app.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | use think\facade\Route; 12 | 13 | Route::get('think', function () { 14 | return 'hello,ThinkPHP6!'; 15 | }); 16 | 17 | Route::get('hello/:name', 'index/hello'); 18 | -------------------------------------------------------------------------------- /runtime/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /think: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | console->run(); -------------------------------------------------------------------------------- /websocket_bbbug_chat.js: -------------------------------------------------------------------------------- 1 | console.log("Ready now.\n**********************************"); 2 | var Config = { 3 | portSocket: 10011,//websocket端口 如果前端配置了https,你需要反代一下这个端口到443实现wss 4 | portHttp: 10012,//api端通过这个端口的http服务来获取在线用户信息 5 | secret: "wss_bbbug_com", 6 | apiUrl: "https://api.bbbug.com",//这里修改为你部署的API端地址 7 | }; 8 | var websocket = require("nodejs-websocket"), 9 | crypto = require('crypto'), 10 | http = require('http'), 11 | https = require('https'); 12 | var webSocketServer = websocket.createServer(function (conn) { 13 | var query = login(conn.path); 14 | if (!query) { 15 | console.error("客户端登录失败"); 16 | conn.close(); 17 | } else { 18 | console.log("客户端连接成功 " + query.account); 19 | var url = Config.apiUrl + '/api/song/now?room_id=' + query.channel; 20 | https.get(url, function (res) { 21 | var dataString = ""; 22 | res.on("data", function (data) { 23 | dataString += data; 24 | }); 25 | res.on("end", function () { 26 | try { 27 | conn.sendText(JSON.stringify({ 28 | type: JSON.parse(dataString).type, 29 | time: 'now', 30 | song: JSON.parse(dataString).song || null, 31 | story: JSON.parse(dataString).story || null, 32 | since: JSON.parse(dataString).since || 0, 33 | count: JSON.parse(dataString).count || 0, 34 | user: JSON.parse(dataString).user || null, 35 | at: JSON.parse(dataString).at || false, 36 | })); 37 | } catch (e) { 38 | } 39 | }); 40 | }); 41 | sendOnlineList(query.channel); 42 | } 43 | conn.on("close", function (code, reason) { 44 | console.error("客户端断开"); 45 | sendOnlineList(query.channel); 46 | }); 47 | conn.on("error", function (code, reason) { 48 | console.error("客户端断开"); 49 | sendOnlineList(query.channel); 50 | }); 51 | conn.on("text", function (msg) { 52 | if (msg == 'getNowSong') { 53 | var url = Config.apiUrl + '/api/song/now?room_id=' + query.channel; 54 | https.get(url, function (res) { 55 | var dataString = ""; 56 | res.on("data", function (data) { 57 | dataString += data; 58 | }); 59 | res.on("end", function () { 60 | try { 61 | conn.sendText(JSON.stringify({ 62 | type: JSON.parse(dataString).type, 63 | time: 'now', 64 | song: JSON.parse(dataString).song || null, 65 | story: JSON.parse(dataString).story || null, 66 | since: JSON.parse(dataString).since || 0, 67 | user: JSON.parse(dataString).user || null, 68 | at: JSON.parse(dataString).at || false, 69 | })); 70 | } catch (e) { 71 | } 72 | }); 73 | }); 74 | } else if (msg == 'bye') { 75 | console.error('用户主动断开链接'); 76 | conn.close(); 77 | } 78 | }); 79 | }); 80 | webSocketServer.listen(Config.portSocket); 81 | console.log("服务启动成功(" + Config.portSocket.toString() + ")Websocket"); 82 | checkConnection(); 83 | 84 | function checkConnection() { 85 | console.log("当前在线连接数:(" + webSocketServer.connections.length + ")"); 86 | setTimeout(function () { 87 | checkConnection(); 88 | }, 89 | 5000); 90 | } 91 | 92 | function sendOnlineList(channel) { 93 | var url = Config.apiUrl + '/api/user/online?sync=yes&room_id=' + channel; 94 | https.get(url, function (res) { 95 | var dataString = ""; 96 | res.on("data", function (data) { 97 | dataString += data; 98 | }); 99 | res.on("end", function () { 100 | webSocketServer.connections.forEach(function (conn) { 101 | try { 102 | var query = login(conn.path); 103 | if (query.channel == channel) { 104 | conn.sendText(JSON.stringify({ 105 | type: "online", 106 | channel: channel, 107 | data: JSON.parse(dataString).data 108 | })); 109 | } 110 | } catch (e) { 111 | } 112 | }); 113 | }); 114 | }); 115 | } 116 | 117 | var http = require('http'); 118 | var url = require('url'); 119 | var querystring = require('querystring'); 120 | var httpServer = http.createServer(function (req, res) { 121 | if (req.method.toUpperCase() == 'POST') { 122 | res.writeHead(200, { 123 | 'Content-Type': 'application/json;charset=utf-8' 124 | }); 125 | var postData = ''; 126 | req.on('data', function (chunk) { 127 | postData += chunk; 128 | }); 129 | req.on('end', function () { 130 | postData = querystring.parse(postData); 131 | if (postData.token == sha1(Config.secret)) { 132 | switch (postData.type) { 133 | case 'chat': 134 | webSocketServer.connections.forEach(function (conn) { 135 | var query = new QueryString(conn.path); 136 | if (query.account == postData.to) { 137 | conn.sendText(postData.msg); 138 | } 139 | }); 140 | break; 141 | case 'channel': 142 | webSocketServer.connections.forEach(function (conn) { 143 | var query = new QueryString(conn.path); 144 | if (query.channel == postData.to) { 145 | conn.sendText(postData.msg); 146 | } 147 | }); 148 | break; 149 | case 'system': 150 | webSocketServer.connections.forEach(function (conn) { 151 | conn.sendText(postData.msg); 152 | }); 153 | break; 154 | default: 155 | } 156 | res.end(); 157 | } else { 158 | res.end("token error"); 159 | } 160 | }); 161 | } else if (req.method.toUpperCase() == 'GET') { 162 | res.writeHead(200, { 163 | 'Content-Type': 'application/json;charset=utf-8' 164 | }); 165 | var onlineList = []; 166 | var gets = new QueryString(req.url); 167 | webSocketServer.connections.forEach(function (conn) { 168 | var query = new QueryString(conn.path); 169 | if (gets.channel) { 170 | if (gets.channel == query.channel) { 171 | onlineList.push(query.account); 172 | } 173 | } else { 174 | onlineList.push(query.account); 175 | } 176 | }); 177 | res.end(JSON.stringify(onlineList)); 178 | } else { 179 | res.writeHead(403, { 180 | 'Content-Type': 'application/json;charset=utf-8' 181 | }); 182 | res.end(); 183 | } 184 | }); 185 | httpServer.listen(Config.portHttp); 186 | console.log("Web服务{" + Config.portHttp + "}启动成功!"); 187 | 188 | 189 | function getTime() { 190 | var now = new Date(); 191 | var hours = now.getHours(); 192 | var minutes = now.getMinutes(); 193 | var seconds = now.getSeconds(); 194 | if (hours < 10) { 195 | hours = "0" + hours; 196 | } 197 | if (minutes < 10) { 198 | minutes = "0" + minutes; 199 | } 200 | if (seconds < 10) { 201 | seconds = "0" + seconds; 202 | } 203 | return hours + ":" + minutes + ":" + seconds; 204 | } 205 | 206 | function debug(message) { 207 | console.log(getTime() + " : " + message); 208 | } 209 | 210 | function login(url) { 211 | var query = new QueryString(url); 212 | if (sha1("account" + query.account + "channel" + query.channel + 'salt' + query.channel) == query.ticket) { 213 | return query; 214 | } else { 215 | return false; 216 | } 217 | } 218 | 219 | function QueryString(url) { 220 | var name, value; 221 | url = url.replace("/?", ""); 222 | var arr = url.split("&"); //各个参数放到数组里 223 | for (var i = 0; i < arr.length; i++) { 224 | num = arr[i].indexOf("="); 225 | if (num > 0) { 226 | name = arr[i].substring(0, num); 227 | value = arr[i].substr(num + 1); 228 | this[name] = value; 229 | } 230 | } 231 | } 232 | 233 | function getTimeStamp() { 234 | return Date.parse(new Date()) / 1000; 235 | } 236 | 237 | function sha1(str) { 238 | var sha1 = crypto.createHash("sha1"); //定义加密方式:md5不可逆,此处的md5可以换成任意hash加密的方法名称; 239 | sha1.update(str); 240 | var res = sha1.digest("hex"); //加密后的值d 241 | return res; 242 | } --------------------------------------------------------------------------------