├── .gitignore ├── LICENSE ├── README.md ├── _coverpage.md ├── app ├── config │ ├── BtConfig.php │ ├── bookSources.json │ └── config.inc.php ├── controller │ ├── Bing.php │ ├── admin.php │ ├── api.php │ ├── bt.php │ ├── day.php │ ├── email.php │ ├── img.php │ ├── news.php │ ├── novel.php │ ├── one.php │ ├── sports.php │ ├── test.php │ ├── user.php │ ├── wechat.php │ └── weibo.php ├── model │ ├── Aliyun.php │ ├── BT.php │ ├── Lunar.php │ └── test.php └── route │ └── route.php ├── core ├── App.php ├── Exception │ └── SystemException.php ├── controller │ ├── Controller.php │ └── Monitor.php ├── init.php ├── lib │ ├── Auth │ │ └── Authentication.php │ ├── AutoLoad.php │ ├── Check.php │ ├── data │ │ ├── config.php │ │ └── route.php │ ├── db │ │ ├── DB.php │ │ ├── Medoo.php │ │ ├── MySQL.php │ │ └── SQL.php │ ├── header.php │ ├── lib.php │ └── route │ │ └── route.php ├── map │ └── map.php ├── plugins │ └── simple_html_dom.php ├── route │ └── route.php └── utils │ ├── Http.php │ ├── LoadImage.php │ ├── Updata.php │ └── utils.php ├── favicon.ico ├── index.php ├── nginx.htaccess ├── public ├── Bing │ ├── README.md │ ├── _coverpage.md │ └── index.html ├── Novel │ ├── README.md │ ├── _coverpage.md │ └── index.html ├── One │ ├── README.md │ ├── _coverpage.md │ └── index.html ├── admin │ └── index.html ├── api │ ├── README.md │ ├── _coverpage.md │ └── index.html ├── day │ ├── README.md │ ├── _coverpage.md │ └── index.html ├── error │ ├── 403.html │ └── 404.html ├── favicon.ico ├── index.html ├── static │ ├── docsify.min.js │ ├── test.css │ ├── test.js │ └── vue.css ├── test.html └── user │ ├── login.html │ ├── reg.html │ └── user.html └── test.php /.gitignore: -------------------------------------------------------------------------------- 1 | test.php 2 | /sql 3 | /app/cookie 4 | config.php -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 xygeng 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## OpenApi 2 | 3 | ### 从2022年4月起,此接口将会从php转向nodejs继续开发,php项目将不会再更新,新的项目[地址](https://github.com/xygengcn/koa-api) 4 | 5 | 开源api系统,将会汇集搜集开源的所有api接口,个人开发简版操作 6 | 7 | 8 | 9 | ![](https://img.shields.io/badge/PHP->=7-.svg) ![](https://img.shields.io/badge/license-MIT-.svg) ![](https://img.shields.io/badge/Medoo-v1.6-.svg) ![](https://img.shields.io/badge/MySQL-v1.15.11-.svg) ![](https://img.shields.io/badge/Redis-v3.0.0-.svg) 10 | 11 | 12 | [TOC] 13 | 14 | ### 安装 15 | 1. 直接把工程放到网站 16 | 2. 配置nginx伪静态.htaccess文件【重点】 17 | 3. 把config.inc.php改成config.php【重点】 18 | 4. 配置数据库,redis地址账号密码等【重点】 19 | 20 | ### 框架结构 21 | 22 | 1. app -> 用户定义控制器、模板、配置文件和路由 23 | 2. core -> 框架核心 24 | 3. public -> 界面文件 25 | 4. index.php -> 入口文件 26 | 5. nginx.htaccess -> nginx伪静态 27 | 28 | 29 | ### 控制器操作 30 | 31 | 在app\controller新建文件,类名和文件保持一致。如果使用模板文件model,请在model文件夹新建文件保持类名和文件一致。不建议类名和函数名一样。 32 | 33 | ```php 34 | 默认 函数名是index,执行控制器的index()函数 77 | ``` 78 | 79 | #### 路由模板 80 | 81 | ``` 82 | http://YourDomain.com/路由名/[参数]/[参数]... 83 | ``` 84 | 85 | 路由名需要在app\route的route文件定义: 86 | 87 | ```php 88 | return [ 89 | "/test" => "test@index", 90 | "/test/test2" => "test@test", 91 | ]; 92 | ``` 93 | 94 | 例子: 95 | 96 | ``` 97 | http://YourDomain.com/test/123/123 98 | 99 | 将会对应访问:test类的index函数,传入(123,123)两个参数 100 | ``` 101 | 102 | ### 内置数据库 103 | 104 | 105 | #### 数据库连接 106 | 107 | 在app\config的database文件设置数据库连接信息 108 | 109 | ```php 110 | return [ 111 | "database_type" => "mysql", //只支持mysql 112 | "server" => "localhost", //数据库地址 113 | "port" => 3306, //默认3306 114 | "database_name" => "api", //数据库名 115 | "username" => "root", //用户名 116 | "password" => "root", //密码 117 | 118 | //不了解下面勿动 119 | 'charset' => 'utf8', 120 | 'prefix' => '', 121 | 'logging' => true, 122 | 'socket' => '/tmp/mysql.sock', 123 | 'option' => [ 124 | PDO::ATTR_CASE => PDO::CASE_NATURAL, 125 | ], 126 | 'command' => [ 127 | 'SET SQL_MODE=ANSI_QUOTES', 128 | ] 129 | ]; 130 | ``` 131 | 132 | 133 | 134 | #### 插入数据 135 | 136 | 单条插入数据 137 | 138 | ```php 139 | DB("表名")->insert([key => value,key =>value]); 140 | 141 | DB("test")->insert(["name" => "/21123/test"]); 142 | ``` 143 | 144 | 多条数据插入 145 | 146 | ```php 147 | #使用insert函数 148 | DB("表名")->insert([key => value,key =>value],[key => value,key =>value]); 149 | 150 | #示例: 151 | DB("test")->insert(["name" => "11"], ["name" => "22", "remark" => "2"], ["name" => "33", "remark" => "3"]); 152 | 153 | #使用inserts函数,第一个数据是放插入属性,后面每个数组是一条数据。 154 | DB("表名")->inserts([key,key...],[value,value...],[value,value...]); 155 | 156 | #示例 157 | DB("test")->inserts(["name", "remark"], ["aa", "bb"], ["cc", "dd"]); 158 | ``` 159 | 160 | 161 | 162 | #### 删除数据 163 | 164 | ```php 165 | #删除 id=75的数据,具体where的用法在后面 166 | 167 | DB("test")->where(["id", "=", "75"])->delete(); 168 | DB("test")->where("id", "=", "75")->delete(); 169 | ``` 170 | 171 | #### 更新数据 172 | 173 | ```php 174 | #更新id=77的数据的remark属性为88,updata一个数组一个属性更改,具体where的用法在后面 175 | DB("test")->where("id", "=", "77")->updata(["remark", "88"]); 176 | 177 | #更改remark和name为88 178 | DB("test")->where("id", "=", "77")->updata(["remark", "88"],["name","88"]); 179 | ``` 180 | 181 | #### 查询数据 182 | 183 | ```php 184 | #查询全表 185 | 186 | DB("test")->select(); 187 | 188 | #只查询全表某些属性 189 | 190 | DB("test")->select("id", "name"); 191 | 192 | #使用where,具体用法在后面 193 | 194 | DB("test")->where(["id", ">", "10"])->select(); 195 | ``` 196 | 197 | #### where语句 198 | 199 | 简单where语句: 200 | 201 | 单个属性,两者都可 202 | 203 | ```php 204 | DB("test")->where(["id", ">", "10"])->select(); 205 | 206 | DB("test")->where("id", ">", "10")->select(); 207 | ``` 208 | 209 | 多个属性,where默认and语句 210 | 211 | ```php 212 | DB("test")->where(["id", ">", "10"], ["id", ">", "10"])->select(); 213 | ``` 214 | 215 | and语句 216 | 217 | ```php 218 | DB("test")->and(["id", "=", "80"], ["id", "=", "81"])->select() 219 | ``` 220 | 221 | or语句 222 | 223 | ```php 224 | DB("test")->or(["id", "=", "80"], ["id", "=", "81"])->select() 225 | ``` 226 | 227 | orderby 语句 228 | 229 | ```php 230 | #单个,默认升序ASC 231 | DB("test")->where("id", ">", "80")->order('id DESC')->select() 232 | 233 | #多个参数,设置倒序 234 | DB("test")->order('id DESC',"...")->select() 235 | ``` 236 | 237 | limit 语句 238 | 239 | ```php 240 | DB("test")->limit(0,1)->select() 241 | ``` 242 | 243 | 244 | ### Medoo数据库 245 | 246 | #### 基础操作 247 | 248 | 在app\config的database文件设置数据库连接信息 249 | 250 | ```php 251 | $db = Medoo();//获取对象,注意没有new 252 | 253 | //查询全表 254 | $db->select("test", "*"); 255 | 256 | //查询个别 257 | $db->select("account", "user_name"); 258 | ``` 259 | 260 | #### 高级用法 261 | 262 | [详细操作手册](https://medoo.lvtao.net/1.2/doc.php) 263 | 264 | ### 内置验证函数 265 | 266 | #### 本地域名验证 267 | ```php 268 | Auth("domain");//只能系统请求 269 | ``` 270 | #### token验证 271 | 272 | 如果接口出现没有权限,基本来自没有token验证,需要用户登录注册 273 | 274 | ```php 275 | Auth();//函数直接使用,可以用header,cookie,get获取token,验证redis即可 276 | ``` 277 | 278 | ### 全局函数 279 | 280 | #### 常量输出 281 | 282 | ```php 283 | _e($data);# $data支持数字,字符串,对象,数组,null 284 | ``` 285 | 286 | #### 接口返回 287 | 288 | ```php 289 | response($data,$code=200) #$data支持数字,数组,对象数组,字符串 290 | 291 | { 292 | "code": 200, 293 | "data": { 294 | "id": "807", 295 | "tag": "漫画", 296 | "origin": "《萤火之森》", 297 | "content": "其实美丽的故事都是没有结局的,只因为它没有结局所以才会美丽。", 298 | "datetime": "1548230343" 299 | } 300 | } 301 | ``` 302 | 303 | 304 | 305 | #### 错误提示 306 | 307 | ```php 308 | //抛出错误,会终止程序运行 309 | 310 | error($msg,$code=404); # $msg是错误提示信息,$code是错误代码,默认404 311 | 312 | //返回 313 | { 314 | "code": 404, 315 | "error": "控制器:\\app\\controller\\one5 未定义文件" 316 | } 317 | ``` 318 | 319 | #### 时间戳 320 | 321 | ``` php 322 | # 默认返回13位,可以输出10位 323 | 324 | timestamp($num =13); 325 | ``` 326 | 327 | #### 服务器网址 328 | 329 | ```php 330 | site_url();//https://xygeng.cn 331 | ``` 332 | 333 | #### 请求来源域名 334 | 335 | ```php 336 | getOriginDomain();#https://api.xygeng.cn 337 | ``` 338 | 339 | #### 去特殊符号 340 | 341 | ```php 342 | #字符串去特殊符号 343 | str_clean($str); 344 | ``` 345 | 346 | #### 爬取函数 347 | 348 | ```php 349 | #单条网址爬取,返回字符串 350 | curl_fetch($url, $cookie = '', $referer = '', $timeout = 10, $ishead = 0) 351 | 352 | #多条网址,返回数组 353 | curl_multi_fetch($urlarr = array(), $timeout = 10) 354 | ``` 355 | 356 | 357 | ### 返回代码 358 | 359 | #### 200 360 | 361 | 成功返回 362 | 363 | ```json 364 | { 365 | "code": 200, 366 | "data": { 367 | .... 368 | } 369 | } 370 | ``` 371 | 372 | #### 404 373 | 374 | 接口失败返回 375 | 376 | ```json 377 | { 378 | "code": 404, 379 | "error": ""//错误提示 380 | } 381 | ``` 382 | 383 | #### 7xx 384 | 385 | 没有权限 386 | 387 | ```json 388 | { 389 | "code": 701, 390 | "error": "没有token权限"//具体权限说明 391 | } 392 | ``` 393 | 394 | ###### 代码表查询 395 | 396 | | 代码 | 返回 | 解释 | 397 | | ---- | ------------- | ---------------------- | 398 | | 700 | 没有域名权限 | 请求域名不在允许访问内 | 399 | | 701 | 没有IP权限 | 请求ip不在允许访问内 | 400 | | 702 | 没有token权限 | 请求没有自带token | 401 | | | | | 402 | 403 | -------------------------------------------------------------------------------- /_coverpage.md: -------------------------------------------------------------------------------- 1 | # XY笔记 - 开源API - OpenApi 2 | 3 | > 开源api系统,将会汇集搜集开源的所有api接口,个人开发简版操作. 4 | 5 | - ONE一句,必应每日一图,新闻接口,宝塔接口,小说接口 6 | - 微信接口,球赛接口,邮件接口 7 | 8 | 9 | 10 | [GitHub](https://github.com/xygengcn/OpenApi) 11 | [Get Started](#main) -------------------------------------------------------------------------------- /app/config/BtConfig.php: -------------------------------------------------------------------------------- 1 | '/system?action=GetSystemTotal', //获取系统基础统计 8 | 'GetDiskInfo' => '/system?action=GetDiskInfo', //获取磁盘分区信息 9 | 'GetNetWork' => '/system?action=GetNetWork', //获取实时状态信息( CPU、内存、网络、负载 ) 10 | 'GetTaskCount' => '/ajax?action=GetTaskCount', //检查是否有安装任务 11 | 'UpdatePanel' => '/ajax?action=UpdatePanel', //检查面板更新 12 | # 网站管理相关接口 13 | 'Websites' => '/data?action=getData&table=sites', //获取网站列表 14 | 'Webtypes' => '/site?action=get_site_types', //获取网站分类 15 | 'GetPHPVersion' => '/site?action=GetPHPVersion', //获取已安装的 PHP 版本列表 16 | 'GetSitePHPVersion' => '/site?action=GetSitePHPVersion', //获取指定网站运行的PHP版本 17 | 'SetPHPVersion' => '/site?action=SetPHPVersion', //修改指定网站的PHP版本 18 | 'SetHasPwd' => '/site?action=SetHasPwd', //开启并设置网站密码访问 19 | 'CloseHasPwd' => '/site?action=CloseHasPwd', //关闭网站密码访问 20 | 'GetDirUserINI' => '/site?action=GetDirUserINI', //获取网站几项开关(防跨站、日志、密码访问) 21 | 'WebAddSite' => '/site?action=AddSite', //创建网站 22 | 'WebDeleteSite' => '/site?action=DeleteSite', //删除网站 23 | 'WebSiteStop' => '/site?action=SiteStop', //停用网站 24 | 'WebSiteStart' => '/site?action=SiteStart', //启用网站 25 | 'WebSetEdate' => '/site?action=SetEdate', //设置网站有效期 26 | 'WebSetPs' => '/data?action=setPs&table=sites', //修改网站备注 27 | 'WebBackupList' => '/data?action=getData&table=backup', //获取网站备份列表 28 | 'WebToBackup' => '/site?action=ToBackup', //创建网站备份 29 | 'WebDelBackup' => '/site?action=DelBackup', //删除网站备份 30 | 'WebDoaminList' => '/data?action=getData&table=domain', //获取网站域名列表 31 | 'GetDirBinding' => '/site?action=GetDirBinding', //获取网站域名绑定二级目录信息 32 | 'AddDirBinding' => '/site?action=AddDirBinding', //添加网站子目录域名 33 | 'DelDirBinding' => '/site?action=DelDirBinding', //删除网站绑定子目录 34 | 'GetDirRewrite' => '/site?action=GetDirRewrite', //获取网站子目录伪静态规则 35 | 'WebAddDomain' => '/site?action=AddDomain', //添加网站域名 36 | 'WebDelDomain' => '/site?action=DelDomain', //删除网站域名 37 | 'GetSiteLogs' => '/site?action=GetSiteLogs', //获取网站日志 38 | 'GetSecurity' => '/site?action=GetSecurity', //获取网站盗链状态及规则信息 39 | 'SetSecurity' => '/site?action=SetSecurity', //设置网站盗链状态及规则信息 40 | 'GetSSL' => '/site?action=GetSSL', //获取SSL状态及证书详情 41 | 'HttpToHttps' => '/site?action=HttpToHttps', //强制HTTPS 42 | 'CloseToHttps' => '/site?action=CloseToHttps', //关闭强制HTTPS 43 | 'SetSSL' => '/site?action=SetSSL', //设置SSL证书 44 | 'CloseSSLConf' => '/site?action=CloseSSLConf', //关闭SSL 45 | 'WebGetIndex' => '/site?action=GetIndex', //获取网站默认文件 46 | 'WebSetIndex' => '/site?action=SetIndex', //设置网站默认文件 47 | 'GetLimitNet' => '/site?action=GetLimitNet', //获取网站流量限制信息 48 | 'SetLimitNet' => '/site?action=SetLimitNet', //设置网站流量限制信息 49 | 'CloseLimitNet' => '/site?action=CloseLimitNet', //关闭网站流量限制 50 | 'Get301Status' => '/site?action=Get301Status', //获取网站301重定向信息 51 | 'Set301Status' => '/site?action=Set301Status', //设置网站301重定向信息 52 | 'GetRewriteList' => '/site?action=GetRewriteList', //获取可选的预定义伪静态列表 53 | 'GetFileBody' => '/files?action=GetFileBody', //获取指定预定义伪静态规则内容( 获取文件内容 ) 54 | 'SaveFileBody' => '/files?action=SaveFileBody', //保存伪静态规则内容( 保存文件内容 ) 55 | 'GetProxyList' => '/site?action=GetProxyList', //获取网站反代信息及状态 56 | 'CreateProxy' => '/site?action=CreateProxy', //添加网站反代信息 57 | 'ModifyProxy' => '/site?action=ModifyProxy', //修改网站反代信息 58 | 59 | # Ftp管理 60 | 'WebFtpList' => '/data?action=getData&table=ftps', //获取FTP信息列表 61 | 'SetUserPassword' => '/ftp?action=SetUserPassword', //修改FTP账号密码 62 | 'SetStatus' => '/ftp?action=SetStatus', //启用/禁用FTP 63 | 64 | # Sql管理 65 | 'WebSqlList' => '/data?action=getData&table=databases', //获取SQL信息列表 66 | 'ResDatabasePass' => '/database?action=ResDatabasePassword', //修改SQL账号密码 67 | 'SQLToBackup' => '/database?action=ToBackup', //创建sql备份 68 | 'SQLDelBackup' => '/database?action=DelBackup', //删除sql备份 69 | 70 | 'download' => '/download?filename=', //下载备份文件( 目前暂停使用 ) 71 | 72 | # 插件管理 73 | 'deployment' => '/plugin?action=a&name=deployment&s=GetList&type=0', //宝塔一键部署列表 74 | 'SetupPackage' => '/plugin?action=a&name=deployment&s=SetupPackage', //部署任务 75 | 76 | # 计划任务 77 | 'crontabList' =>'/crontab?action=GetCrontab',//计划列表 78 | 'AddCrontab' =>'/crontab?action=AddCrontab',//添加计划任务 79 | ); -------------------------------------------------------------------------------- /app/config/bookSources.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "爱看小说网", 4 | "host": "https://www.aikantxt.la", 5 | "listUrl": "https://www.aikantxt.la/xiaoshuodaquan/", 6 | "listRuleDom": "#main .novellist a", 7 | "bookNameRuleDom": "h1", 8 | "bookNameRuleIndex": 0, 9 | "bookNameRuleRegs": "", 10 | "bookImageRuleDom": "#fmimg img", 11 | "bookImageRuleIndex": 0, 12 | "bookAuthorRuleDom": "#maininfo #info p", 13 | "bookAuthorRuleIndex": 0, 14 | "bookAuthorRuleReg": "/(?<=:)(.*)+/", 15 | "bookIntroRuleDom": "#intro p", 16 | "bookIntroRuleIndex": 0, 17 | "bookIntroRuleReg": "{]*>(.*?)}", 18 | "bookLastTimeRuleDom": "#maininfo #info p", 19 | "bookLastTimeRuleIndex": 2, 20 | "bookLastTimeRuleReg": "/(?<=:)(.*)+/", 21 | "bookLastSectionRuleDom": "#info a", 22 | "bookLastSectionRuleIndex": 3, 23 | "bookLastSectionRuleReg": "", 24 | "bookCatalogueRuleDom": "#list dl dd a", 25 | "chapterNameRuleDom": "h1", 26 | "chapterNameRuleIndex": 0, 27 | "chapterNameRuleReg": "", 28 | "chapterCatalogueUrlDom": ".bottem1 a", 29 | "chapterCatalogueUrlIndex": 2, 30 | "chapterNextDom": ".bottem1 a", 31 | "chapterNextIndex": 3, 32 | "chapterPreviousDom": ".bottem1 a", 33 | "chapterPreviousIndex": 1, 34 | "chapterContentDom": "#content", 35 | "chapterContentIndex": 0, 36 | "chapterContentReg": "/((---+.*)|(<[pa(div)]>.*))/si" 37 | }, 38 | { 39 | "name": "笔趣阁", 40 | "host": "http://www.xbiquge.la", 41 | "listUrl": "http://www.xbiquge.la/xiaoshuodaquan/", 42 | "listRuleDom": "#main .novellist a", 43 | "bookNameRuleDom": "h1", 44 | "bookNameRuleIndex": 0, 45 | "bookNameRuleRegs": "", 46 | "bookImageRuleDom": "#fmimg img", 47 | "bookImageRuleIndex": 0, 48 | "bookAuthorRuleDom": "#maininfo #info p", 49 | "bookAuthorRuleIndex": 0, 50 | "bookAuthorRuleReg": "/(?<=:)(.*)+/", 51 | "bookIntroRuleDom": "#intro p", 52 | "bookIntroRuleIndex": 1, 53 | "bookIntroRuleReg": "{]*>(.*?)}", 54 | "bookLastTimeRuleDom": "#maininfo #info p", 55 | "bookLastTimeRuleIndex": 2, 56 | "bookLastTimeRuleReg": "/(?<=:)(.*)+/", 57 | "bookLastSectionRuleDom": "#info a", 58 | "bookLastSectionRuleIndex": 3, 59 | "bookLastSectionRuleReg": "", 60 | "bookCatalogueRuleDom": "#list dl dd a", 61 | "chapterNameRuleDom": "h1", 62 | "chapterNameRuleIndex": 0, 63 | "chapterNameRuleReg": "", 64 | "chapterCatalogueUrlDom": ".bottem1 a", 65 | "chapterCatalogueUrlIndex": 2, 66 | "chapterNextDom": ".bottem1 a", 67 | "chapterNextIndex": 3, 68 | "chapterPreviousDom": ".bottem1 a", 69 | "chapterPreviousIndex": 1, 70 | "chapterContentDom": "#content", 71 | "chapterContentIndex": 0, 72 | "chapterContentReg": "/((---+.*)|(<[pa(div)]>.*))/si" 73 | } 74 | ] -------------------------------------------------------------------------------- /app/config/config.inc.php: -------------------------------------------------------------------------------- 1 | '', //管理账号,可以忽略两个小时的限制 7 | 'secret'=>'', //个人密钥 8 | 'database' =>[ 9 | 'database_type' => 'mysql', //只支持mysql 10 | 'server' => 'localhost', //数据库地址 11 | 'port' => 3306, //默认3306 12 | 'database_name' => 'api', //数据库名 13 | 'username' => 'root', //用户名 14 | 'password' => 'root', //密码 15 | //不了解下面勿动 16 | 'charset' => 'utf8', 17 | 'prefix' => '', 18 | 'logging' => true, 19 | 'socket' => '/tmp/mysql.sock', 20 | 'option' => [ 21 | PDO::ATTR_CASE => PDO::CASE_NATURAL, 22 | ], 23 | 'command' => [ 24 | 'SET SQL_MODE=ANSI_QUOTES', 25 | ] 26 | ], 27 | 'header'=>[ 28 | //时区设置,默认上海 29 | 'timezone' => 'Asia/Shanghai', 30 | 31 | //debug 32 | 'ini' => [ 33 | //打开错误提示 34 | 'display_errors' => 'On', 35 | //显示所有错误 36 | 'error_reporting' => E_ALL, 37 | ], 38 | //头部跨域等 39 | 'header' => [ 40 | 'Content-Type' => 'application/json; charset=utf-8;application/x-www-form-urlencoded', //内容类型, 编码 41 | 42 | 'Access-Control-Allow-Origin' => '*', //*代表允许任何网址请求,跨域设置 43 | 44 | 'Access-Control-Allow-Methods' => 'POST,GET,OPTIONS,DELETE', // 允许请求的类型 45 | 46 | 'Access-Control-Allow-Credentials' => 'true', // 设置是否允许发送 cookies 47 | 48 | 'Access-Control-Allow-Headers' => ' Content-Type,Content-Length,Accept-Encoding,X-Requested-with, Origin,token', // 设置允许自定义请求头的字段 49 | ] 50 | ], 51 | //环境检查 52 | 'check'=>1, 53 | 54 | //开发环境 55 | 'mode'=>'pro',//dev、pro 56 | 57 | //开启监控请求, 需要redis支持,默认关闭 58 | 'monitor'=>0, 59 | 60 | 'redis'=>[ 61 | 'server' => '127.0.0.1', //redis地址 62 | 'port' => '6379', //redis端口 63 | 'index' =>9//默认9号仓库 64 | ], 65 | 66 | //微信 67 | 'wechat'=>[ 68 | 'corpid'=>'', //企业ID 69 | 'agentid'=>'', //企业应用ID 70 | 'corpsecret'=>'', //应用Secret 71 | ], 72 | 73 | //阿里云邮件 74 | 'aliyunMail' =>[ 75 | 'accountName'=>'', //管理控制台的发信地址 76 | 'region'=>'', //hangzhou, singapore, sydney 77 | 'AccessKeyID'=>'', //请填入在阿里云生成的AccessKey ID 78 | 'AccessKeySecret'=>''//请填入在阿里云生成的Access Key Secret 79 | ], 80 | 81 | //宝塔接口 82 | 'bt' =>[ 83 | 'api'=>'', //面板地址 84 | 'key'=>''//面板密钥 85 | ] 86 | 87 | ]; -------------------------------------------------------------------------------- /app/controller/Bing.php: -------------------------------------------------------------------------------- 1 | get( 'api_bing_url' ); 24 | if ( isset( $api_bing_url ) && !empty( $api_bing_url ) ) { 25 | $imgurl = $api_bing_url; 26 | } else { 27 | $str = file_get_contents( $this->url . '&idx=0&n=1' ); 28 | $str = json_decode( $str, true ); 29 | $imgurl = 'http://cn.bing.com' . $str['images'][0]['url']; 30 | $expireTime = mktime( 23, 59, 59, date( 'm' ), date( 'd' ), date( 'Y' ) ); 31 | $redis->setex( 'api_bing_url', $expireTime - timestamp( 10 ), $imgurl ); 32 | } 33 | if ( $imgurl ) { 34 | $opt = new \core\utils\LoadImage(); 35 | $opt->create()->load( $imgurl ); 36 | } else { 37 | error( '获取图片错误' ); 38 | } 39 | } 40 | 41 | public function url() { 42 | $redis = redis(); 43 | $api_bing_url = $redis->get( 'api_bing_url' ); 44 | if ( isset( $api_bing_url ) && !empty( $api_bing_url ) ) { 45 | $imgurl = $api_bing_url; 46 | } else { 47 | $str = file_get_contents( $this->url . '&idx=0&n=1' ); 48 | $str = json_decode( $str, true ); 49 | $imgurl = 'http://cn.bing.com' . $str['images'][0]['url']; 50 | $expireTime = mktime( 23, 59, 59, date( 'm' ), date( 'd' ), date( 'Y' ) ); 51 | $redis->setex( 'api_bing_url', $expireTime - timestamp( 10 ), $imgurl ); 52 | } 53 | if ( $imgurl ) { 54 | response( $imgurl ); 55 | } else { 56 | error( '获取图片错误' ); 57 | } 58 | } 59 | 60 | public function week() 61 | { 62 | $redis = redis(); 63 | $lLen = $redis->lLen( 'api_bing_week' ); 64 | if ( $lLen != 0 ) { 65 | $bingWeek = $redis->lrange( 'api_bing_week', 0, -1 ); 66 | } else { 67 | for ( $i = 0; $i <= 7; $i++ ) { 68 | $contents = $this->url . '&idx=' . '' . $i . '' . '&n=1'; 69 | $str = file_get_contents( $contents ); 70 | $str = json_decode( $str, true ); 71 | $bingWeek[] = 'http://cn.bing.com' . $str['images'][0]['url']; 72 | $redis->lpush( 'api_bing_week', 'http://cn.bing.com' . $str['images'][0]['url'] ); 73 | } 74 | $expireTime = mktime( 23, 59, 59, date( 'm' ), date( 'd' ), date( 'Y' ) ); 75 | $redis->expireAt( 'api_bing_week', $expireTime ); 76 | } 77 | response( $bingWeek ); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/controller/admin.php: -------------------------------------------------------------------------------- 1 | keys( '*' ); 24 | foreach ( $keys as $key ) { 25 | if ( strpos( $key, 'total_' ) !== false ) { 26 | $route = substr( $key, 6 ); 27 | $route = explode( '_', $route ); 28 | $name = '/'.implode( '/', $route ); 29 | $total[$name] = intval( $redis->get( $key ) ); 30 | $today_total[$name] = $total[$name]; 31 | } 32 | } 33 | 34 | $db = Medoo(); 35 | $data = $db->query( 'SELECT api_name,SUM(total) as total FROM `data` GROUP BY api_name ORDER BY total DESC' )->fetchAll(); 36 | if ( $data ) { 37 | foreach ( $data as $value ) { 38 | if ( isset( $total[$value['api_name']] ) ) { 39 | $total[$value['api_name']] += $value['total']; 40 | } else { 41 | $total[$value['api_name']] = intval( $value['total'] ); 42 | } 43 | 44 | } 45 | } 46 | 47 | $history_total = []; 48 | //历史统计 49 | $data = $db->query( "SELECT api_name,total,`date` FROM `data` WHERE `type` != 'total' ORDER BY api_name,`date`" )->fetchAll(); 50 | if ( $data ) { 51 | foreach ( $data as $value ) { 52 | $history_total[$value['api_name']][$value['date']] = $value['total']; 53 | } 54 | } 55 | response( ['total'=>$total, 'today' =>$today_total, 'history'=>$history_total] ); 56 | 57 | } 58 | 59 | public function task() { 60 | 61 | $redis = redis(); 62 | $total = []; 63 | $keys = $redis->keys( '*' ); 64 | foreach ( $keys as $key ) { 65 | if ( strpos( $key, 'total_' ) !== false ) { 66 | $route = substr( $key, 6 ); 67 | $route = explode( '_', $route ); 68 | $item['api_name'] = '/'.implode( '/', $route ); 69 | $item['total'] = $redis->get( $key ); 70 | $item['type'] = $route[0]; 71 | $item['date'] = date( 'Y-m-d' ); 72 | $total[] = $item; 73 | } 74 | } 75 | if ( DB( 'data' )->insert( ...$total ) ) { 76 | response( 'success' ); 77 | } else { 78 | error( 'error' ); 79 | } 80 | 81 | } 82 | } -------------------------------------------------------------------------------- /app/controller/bt.php: -------------------------------------------------------------------------------- 1 | convertSolarToLunar( date( 'Y' ), date( 'm' ), date( 'd' ) ); 11 | $festival = $lunar->getFestival( date( 'Y-m-d' ) ); 12 | response( [ 13 | 'solar'=>[ 14 | 'year'=>date( 'Y' ), 15 | 'month'=>date( 'm' ), 16 | 'date'=>date( 'd' ), 17 | 'day'=>weekday(), 18 | ], 19 | 'lunar'=>[ 20 | 'year'=>$day_lunar[3], 21 | 'animal'=>$day_lunar[6], 22 | 'month'=>$day_lunar[1], 23 | 'date'=>$day_lunar[2], 24 | ], 25 | 'festival'=> $festival 26 | ] ); 27 | } 28 | } -------------------------------------------------------------------------------- /app/controller/email.php: -------------------------------------------------------------------------------- 1 | '321772514@qq.com', 18 | 'fromName'=>'XY助手', 19 | 'subject'=>'这是一封邮件', 20 | 'html'=>array( 'title'=>'XY助手提醒你!', 'content'=>'注意身体!' ), 21 | ]; 22 | Aliyun::send( $data ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/controller/img.php: -------------------------------------------------------------------------------- 1 | $url, 41 | 'base64'=>$imgBase64 42 | ) ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/controller/news.php: -------------------------------------------------------------------------------- 1 | dom = new simple_html_dom(); 17 | } 18 | 19 | public function index() { 20 | 21 | response( $this->news_flash() ); 22 | } 23 | 24 | public function more( $date, $page ) { 25 | $url = "https://a.jiemian.com/index.php?m=lists&a=ajaxNews&cid=4&page=$page&date=$date"; 26 | $news = array(); 27 | $news['page'] = $page; 28 | $news['date'] = $date; 29 | $html = curl_fetch( $url ); 30 | $html = json_decode( rtrim( ltrim( $html, '(' ), ')' ) )->rst; 31 | $this->dom->load( $html ); 32 | if ( $lists = $this->dom->find( '.item-news' ) ) { 33 | foreach ( $lists as $item ) { 34 | $temp['datetime'] = $item->first_child()->innertext; 35 | $temp['title'] = $item->find( 'p a', 0 )->innertext; 36 | $temp['url'] = $item->find( 'p a', 0 )->href; 37 | $temp['content'] = $item->find( 'p', 0 )->innertext; 38 | $temp['text'] = preg_replace( '/\\t*【.*】/', '', $temp['content'] ); 39 | $news['news'][] = $temp; 40 | } 41 | } 42 | response( $news ); 43 | } 44 | 45 | private function news_flash() { 46 | $news = array(); 47 | $html = curl_fetch( 'https://www.jiemian.com/lists/4.html' ); 48 | $this->dom->load( $html ); 49 | if ( $list = $this->dom->find( '#lists', 0 ) ) { 50 | $news['page'] = 1; 51 | $news['date'] = $list->first_child()->innertext; 52 | $lists = $list->find( '.item-news' ); 53 | foreach ( $lists as $item ) { 54 | $temp['datetime'] = $item->first_child()->innertext; 55 | $temp['title'] = $item->find( 'p a', 0 )->innertext; 56 | $temp['url'] = $item->find( 'p a', 0 )->href; 57 | $temp['content'] = $item->find( 'p', 0 )->innertext; 58 | $temp['text'] = preg_replace( '/\\t*【.*】/', '', $temp['content'] ); 59 | $news['news'][] = $temp; 60 | } 61 | } 62 | if ( $more = $this->dom->find( '.load-view .load-more', 0 ) ) { 63 | $news['more']['date'] = $more->getAttribute( 'date' ); 64 | $news['more']['page'] = $more->getAttribute( 'page' ); 65 | } 66 | return $news; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/controller/novel.php: -------------------------------------------------------------------------------- 1 | dom = new \simple_html_dom(); 18 | $this->bookSource(); 19 | } 20 | 21 | public function index() { 22 | display( 'novel/index.html' ); 23 | } 24 | 25 | //书籍大全 26 | 27 | public function books() { 28 | $url_arr = array(); 29 | foreach ( $this->bookSources as $key => $item ) { 30 | array_push( $url_arr, $item['listUrl'] ); 31 | } 32 | $data = curl_multi_fetch( $url_arr ); 33 | $list = array(); 34 | foreach ( $data as $key => $value ) { 35 | $this->dom->load( $value ); 36 | if ( $str = $this->dom->find( $this->bookSources[$key]['listRuleDom'] ) ) { 37 | foreach ( $str as $a ) { 38 | array_push( $list, array( 'book' => $a->innertext, 'source' => $a->href, 'api' => $this->urlEnApi( $key, $a->href, 'Novel/book' ) ) ); 39 | } 40 | } 41 | } 42 | response( $list ); 43 | } 44 | 45 | //书籍详细 46 | 47 | public function book( $source = 0 ) { 48 | if ( func_num_args() == 0 ) { 49 | error( '参数不完整' ); 50 | } else { 51 | $url = $this->urlDeApi( func_get_args() ); 52 | $html = curl_fetch( $url ); 53 | 54 | } 55 | } 56 | 57 | //源地址解析成接口地址 58 | 59 | private function urlEnApi( $index, $url, $api ) { 60 | $str = site_url(); 61 | return $str . "/$api/$index" . parse_url( $url, PHP_URL_PATH ); 62 | } 63 | //接口地址解析成源地址 64 | 65 | private function urlDeApi( $params = array() ) { 66 | array_shift( $params ); 67 | return $this->bookSources[$source]['host'] . '/' . implode( '/', $params ); 68 | } 69 | 70 | //书源 71 | 72 | private function bookSource() { 73 | if ( $json_string = file_get_contents( __ROOT__ . '/app/config/bookSources.json' ) ) { 74 | $this->bookSources = json_decode( $json_string, true ); 75 | } else { 76 | error( '书源读取失败' ); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/controller/one.php: -------------------------------------------------------------------------------- 1 | get( 'api_one' ); 14 | if ( isset( $api_one ) && !empty( $api_one ) ) { 15 | $this->api_one = json_decode( $api_one, true ); 16 | } else { 17 | $this->api_one = DB( 'one' )->rand( 1 )->select( 'id', 'tag', 'origin', 'content', 'datetime' ); 18 | $redis->setex( 'api_one', 60, json_encode( $this->api_one ) ); 19 | } 20 | } 21 | 22 | public function index() { 23 | response( ...$this->api_one ); 24 | } 25 | 26 | public function get() { 27 | $data = $this->api_one[0]['content'] . '————' . $this->api_one[0]['origin']; 28 | _e( "document.write('$data')" ); 29 | } 30 | } -------------------------------------------------------------------------------- /app/controller/sports.php: -------------------------------------------------------------------------------- 1 | soccerApi.$start ) ); 17 | 18 | $lists = $data->list; 19 | 20 | $newsList = []; 21 | 22 | foreach ( $lists as $item ) { 23 | $time = date( $item->sort_timestamp+60*60*8 ); 24 | $date = date( 'Y-m-d', $time ); 25 | $datetime = date( 'H:i:s', $time ); 26 | $item->timestamp = $time; 27 | $item->time = $datetime; 28 | $item->date = $date; 29 | $newsList[$date][] = $item; 30 | } 31 | $data->Date = $start; 32 | $data->list = $newsList; 33 | response( $data ); 34 | } 35 | } -------------------------------------------------------------------------------- /app/controller/test.php: -------------------------------------------------------------------------------- 1 | where('email', '=', $email)->select(); 28 | if ($user == []) { 29 | error('未注册用户!'); 30 | } 31 | if (password_verify($password, $user[0]['password'])) { 32 | $redis = redis(); 33 | $token = password_hash($user[0]['secret'], PASSWORD_BCRYPT); 34 | $redis->setex('token_' . $token, $timeout, getDevice()['device']); 35 | response(['status' => 'success', 'username' => $user[0]['username'], 'email' => $email, 'token' => $token, 'expire' => $timeout]); 36 | return; 37 | } else { 38 | error('密码不正确'); 39 | } 40 | } else if ($code && $email) { 41 | $redis = redis(); 42 | if ($redis->hKeys('verify_' . $code)) { 43 | $user = $redis->hMget('verify_' . $code, ['username', 'token']); 44 | response(['status' => 'success', 'username' => $user['username'], 'email' => $email, 'token' => $user['token'], 'expire' => $timeout]); 45 | } else { 46 | error('安全码过期'); 47 | } 48 | } else { 49 | error('参数缺失'); 50 | } 51 | } 52 | 53 | public function reg() 54 | { 55 | 56 | $username = getParam('username'); 57 | $email = getParam('email'); 58 | $password = getParam('password'); 59 | if (empty($username) || empty($email) || empty($password)) { 60 | error("参数不完整"); 61 | } 62 | $user = DB('user')->where('email', '=', $email)->select(); 63 | if ($user != []) { 64 | error('已注册用户'); 65 | } 66 | $password = password_hash($password, PASSWORD_BCRYPT); 67 | $secret = self::getSecret(); 68 | $result = DB('user')->insert(['username' => $username, 'email' => $email, 'password' => $password, 'secret' => $secret]); 69 | if ($result > 0) { 70 | response('注册成功'); 71 | } else { 72 | error('注册失败'); 73 | } 74 | } 75 | 76 | public function logout() 77 | { 78 | $token = getToken(); 79 | if ($token) { 80 | $redis = redis(); 81 | if ($redis->get('token_' . $token)) { 82 | $redis->del('token_' . $token); 83 | } 84 | response("success"); 85 | return; 86 | } 87 | error("error"); 88 | } 89 | 90 | public function verify() 91 | { 92 | $email = getParam('email'); 93 | $username = getParam('username'); 94 | $password = getParam('password'); 95 | $token = getToken(); 96 | if ($email && $password) { 97 | $user = DB('user')->where('email', '=', $email)->select(); 98 | if ($user == []) { 99 | error('未注册用户!'); 100 | } 101 | if (password_verify($password, $user[0]['password'])) { 102 | $verify_code = rand(1000, 9999); 103 | $redis = redis(); 104 | $redis->hMset('verify_' . $verify_code, ['username' => $username, 'token' => $token]); 105 | $redis->expire('verify_' . $verify_code, 30); 106 | response(["code" => $verify_code, "email" => $email, 'username' => $username, 'token' => $token]); 107 | return; 108 | } else { 109 | error('验证错误'); 110 | } 111 | } else { 112 | error('参数缺失'); 113 | } 114 | } 115 | 116 | private static function getSecret() 117 | { 118 | $charid = md5(uniqid(mt_rand(), true)); 119 | $secret = strtoupper(substr($charid, 0, 8)) . substr($charid, 8, 4) . substr($charid, 12, 4) . substr($charid, 16, 4) . strtoupper(substr($charid, 20, 12)); 120 | $secret = str_replace('.', '', $secret); 121 | return substr(password_hash($secret, PASSWORD_BCRYPT), 10, strlen($secret)); 122 | } 123 | } -------------------------------------------------------------------------------- /app/controller/wechat.php: -------------------------------------------------------------------------------- 1 | getAccessToken(); 20 | } 21 | 22 | private function getAccessToken() { 23 | $redis = redis(); 24 | $access_token = $redis->get( 'Wechat_Access_Token' ); 25 | if ( $access_token ) { 26 | $this->access_token = $access_token; 27 | } else { 28 | $url = $this->access_token_url.'?corpid='.config( 'wechat' )['corpid'].'&corpsecret='.config( 'wechat' )['corpsecret']; 29 | $result = json_decode( get( $url ) ); 30 | $this->access_token = $result->access_token; 31 | $redis->setex( 'Wechat_Access_Token', $result->expires_in, $result->access_token ); 32 | } 33 | } 34 | 35 | public function index() { 36 | response( 'success' ); 37 | } 38 | 39 | public function send() { 40 | $message = array(); 41 | $message['to'] = '@all'; 42 | $message['content'] = getParam( 'content' ); 43 | $message['type'] = 'text'; 44 | self::post( $message ); 45 | } 46 | 47 | public function post( $url, $data ) { 48 | $url = $this->send_url.$this->access_token; 49 | $data = $this->message( $message ); 50 | $result = json_decode( post( $url, $data ) ); 51 | response( $result ); 52 | } 53 | 54 | private function message( $data = array() ) { 55 | return array( 56 | 'touser'=>$data['to']?$data['to']:'@all', 57 | 'msgtype'=>$data['type']?$data['type']:'text', 58 | 'agentid'=>config( 'wechat' )['agentid'], 59 | 'text'=>array( 60 | 'content'=>$data['content']?$data['content']:'Hello World' 61 | ), 62 | 'safe'=>0, 63 | 'enable_id_trans'=>0, 64 | 'enable_duplicate_check'=> 1, 65 | 'duplicate_check_interval'=> 1800 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/controller/weibo.php: -------------------------------------------------------------------------------- 1 | hot_api ); 13 | $data = substr( $data, 13, strlen( $data )-25 ); 14 | $data = json_decode( $data, true ); 15 | response( $data['data'] ); 16 | } 17 | 18 | public function hots() { 19 | 20 | $dom = new simple_html_dom(); 21 | $data = array(); 22 | $html = curl_fetch( $this->hots_api ); 23 | $dom->load( $html ); 24 | if ( $list = $dom->find( '#pl_top_realtimehot tbody', 0 ) ) { 25 | $list = $list->find( 'tr' ); 26 | foreach ( $list as $key => $item ) { 27 | if ( $item->find( '.td-02 a', 0 ) ) { 28 | $temp['realpos'] = $key-1; 29 | $temp['note'] = $item->find( '.td-02 a', 0 )->innertext; 30 | $temp['url'] = 'https://s.weibo.com'.$item->find( '.td-02 a', 0 )->href; 31 | if ( $item->find( '.td-02 img', 0 ) ) { 32 | $temp['icon'] = 'https:'.$item->find( '.td-02 img', 0 )->src; 33 | } else { 34 | $temp['icon'] = ''; 35 | } 36 | if ( $item->find( '.td-02 span', 0 ) ) { 37 | $temp['num'] = $item->find( '.td-02 span', 0 )->innertext; 38 | } else { 39 | $temp['num'] = ''; 40 | } 41 | if ( $item->find( '.td-03 i', 0 ) ) { 42 | $temp['tag'] = $item->find( '.td-03 i', 0 )->innertext; 43 | } else { 44 | $temp['tag'] = ''; 45 | } 46 | $data[] = $temp; 47 | } 48 | 49 | } 50 | } 51 | 52 | response( $data ); 53 | 54 | } 55 | } -------------------------------------------------------------------------------- /app/model/Aliyun.php: -------------------------------------------------------------------------------- 1 | array( 'api'=>'https://dm.aliyuncs.com/', 'version'=>'2015-11-23', 'region'=>'cn-hangzhou' ), 9 | 'singapore'=>array( 'api'=>'https://dm.ap-southeast-1.aliyuncs.com/', 'version'=>'2017-06-22', 'region'=>'ap-southeast-1' ), 10 | 'sydney'=>array( 'api'=>'https://dm.ap-southeast-2.aliyuncs.com/', 'version'=>'2015-11-23', 'region'=>'ap-southeast-2' ), 11 | ]; 12 | 13 | public static function send($param) { 14 | 15 | $data =[ 16 | "to"=>$param["to"], 17 | "fromName"=>$param["fromName"], 18 | "subject"=>$param["subject"], 19 | "content"=>self::html(array("title"=>$param["html"]["title"],"content"=>$param["html"]["content"])), 20 | ]; 21 | self::aliyun($data); 22 | } 23 | 24 | private static function aliyun( $param ) { 25 | 26 | $config =config("aliyunMail"); 27 | $api =self::$aliyun_region[$config['region']]['api']; 28 | // 重新组合为阿里云所使用的参数 29 | $data = array( 30 | 'Action' => 'SingleSendMail', // 操作接口名 31 | 'AccountName' => $config['accountName'], // 发件地址 32 | 'ReplyToAddress' => 'true', // 回信地址 33 | 'AddressType' => 1, // 地址类型 34 | 'ToAddress' => $param['to'], // 收件地址 35 | 'FromAlias' => $param['fromName'], // 发件人名称 36 | 'Subject' => $param['subject'], // 邮件标题 37 | 'HtmlBody' => $param['content'], // 邮件内容 38 | 'Format' => 'JSON', // 返回JSON 39 | 'Version' =>self::$aliyun_region[$config['region']]['version'], // API版本号 40 | 'AccessKeyId' => $config['AccessKeyID'], // Access Key ID 41 | 'SignatureMethod' => 'HMAC-SHA1', // 签名方式 42 | 'Timestamp' => gmdate( 'Y-m-d\TH:i:s\Z' ), // 请求时间 43 | 'SignatureVersion' => '1.0', // 签名算法版本 44 | 'SignatureNonce' => md5( time() ), // 唯一随机数 45 | 'RegionId' => self::$aliyun_region[$config['region']]['region'] // 机房信息 46 | ); 47 | // 请求签名 48 | $data['Signature'] = self::sign( $data, $config['AccessKeySecret'] ); 49 | // 初始化Curl 50 | $ch = curl_init(); 51 | // 设置为POST请求 52 | curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, 'POST' ); 53 | // 请求地址 54 | curl_setopt( $ch, CURLOPT_URL,$api); 55 | // 返回数据 56 | curl_setopt( $ch, CURLOPT_RETURNTRANSFER, TRUE ); 57 | // 提交参数 58 | curl_setopt( $ch, CURLOPT_POSTFIELDS, self::getPostHttpBody( $data ) ); 59 | // 关闭ssl验证 60 | curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, FALSE ); 61 | curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, FALSE ); 62 | // 执行请求 63 | $result = curl_exec( $ch ); 64 | // 获取错误代码 65 | $errno = curl_errno( $ch ); 66 | // 获取错误信息 67 | $error = curl_error( $ch ); 68 | // 获取返回状态码 69 | $httpCode = curl_getinfo( $ch, CURLINFO_HTTP_CODE ); 70 | // 关闭请求 71 | curl_close( $ch ); 72 | // 成功标识 73 | $flag = TRUE; 74 | // 如果失败 75 | if ( $errno ) { 76 | // 设置失败 77 | $flag = FALSE; 78 | error( '邮件发送失败, 错误代码:' . $errno . ',错误提示: ' . $error . PHP_EOL ); 79 | } 80 | // 如果失败 81 | if ( 400 <= $httpCode ) { 82 | // 设置失败 83 | $flag = FALSE; 84 | // 尝试转换json 85 | if ( $json = json_decode( $result ) ) { 86 | error( '邮件发送失败,错误代码:' . $json->Code . ',错误提示:' . $json->Message . PHP_EOL ); 87 | } else { 88 | error( '邮件发送失败, 请求返回HTTP Code:' . $httpCode . PHP_EOL ); 89 | } 90 | } 91 | // 返回结果 92 | return $flag; 93 | } 94 | 95 | /** 96 | * 阿里云签名 97 | * 98 | * @static 99 | * @access private 100 | * 101 | * @param $param 102 | * @param $accesssecret 103 | * 104 | * @return string 105 | */ 106 | 107 | private static function sign( $param, $accesssecret ) { 108 | // 参数排序 109 | ksort( $param ); 110 | // 组合基础 111 | $stringToSign = 'POST&' . self::percentEncode( '/' ) . '&'; 112 | // 临时变量 113 | $tmp = ''; 114 | // 循环参数列表 115 | foreach ( $param as $k => $v ) { 116 | // 组合参数 117 | $tmp .= '&' . self::percentEncode( $k ) . '=' . self::percentEncode( $v ); 118 | } 119 | // 去除最后一个& 120 | $tmp = trim( $tmp, '&' ); 121 | // 组合签名参数 122 | $stringToSign = $stringToSign . self::percentEncode( $tmp ); 123 | // 数据签名 124 | $signature = base64_encode( hash_hmac( 'sha1', $stringToSign, $accesssecret . '&', TRUE ) ); 125 | // 返回签名 126 | return $signature; 127 | } 128 | 129 | /** 130 | * 阿里云签名编码转换 131 | * 132 | * @access private 133 | * 134 | * @param $val 135 | * 136 | * @return string|string[]|null 137 | */ 138 | 139 | private static function percentEncode( $val ) { 140 | // URL编码 141 | $res = urlencode( $val ); 142 | // 加号转换为%20 143 | $res = preg_replace( '/\+/', '%20', $res ); 144 | // 星号转换为%2A 145 | $res = preg_replace( '/\*/', '%2A', $res ); 146 | // %7E转换为~ 147 | $res = preg_replace( '/%7E/', '~', $res ); 148 | return $res; 149 | } 150 | 151 | /** 152 | * 阿里云请求参数组合 153 | * 154 | * @access private 155 | * 156 | * @param $param 157 | * 158 | * @return bool|string 159 | */ 160 | private static function getPostHttpBody( $param ) { 161 | // 空字符串 162 | $str = ''; 163 | // 循环参数 164 | foreach ( $param as $k => $v ) { 165 | // 组合参数 166 | $str .= $k . '=' . urlencode( $v ) . '&'; 167 | } 168 | // 去除第一个& 169 | return substr( $str, 0, -1 ); 170 | } 171 | 172 | /** 173 | * 生成模板 174 | */ 175 | 176 | private static function html( $data ) { 177 | 178 | $html = '

{title}

{content}
'; 179 | return str_replace( array( '{title}', '{content}' ), array( trim( $data['title'] ), trim( $data['content'] ) ), $html ); 180 | } 181 | } -------------------------------------------------------------------------------- /app/model/BT.php: -------------------------------------------------------------------------------- 1 | BT_PANEL = $bt_panel; 22 | if ($bt_key) $this->BT_KEY = $bt_key; 23 | } 24 | 25 | /** 26 | * 获取系统基础统计 27 | */ 28 | 29 | public function GetSystemTotal() 30 | { 31 | $url = $this->BT_PANEL . $this->config('GetSystemTotal'); 32 | 33 | $p_data = $this->GetKeyData(); 34 | 35 | $result = $this->HttpPostCookie($url, $p_data); 36 | 37 | $data = json_decode($result, true); 38 | return $data; 39 | } 40 | 41 | /** 42 | * 获取磁盘分区信息 43 | */ 44 | 45 | public function GetDiskInfo() 46 | { 47 | $url = $this->BT_PANEL . $this->config('GetDiskInfo'); 48 | 49 | $p_data = $this->GetKeyData(); 50 | 51 | $result = $this->HttpPostCookie($url, $p_data); 52 | 53 | $data = json_decode($result, true); 54 | return $data; 55 | } 56 | 57 | /** 58 | * 获取实时状态信息 59 | * ( CPU、内存、网络、负载 ) 60 | */ 61 | 62 | public function GetNetWork() 63 | { 64 | $url = $this->BT_PANEL . $this->config('GetNetWork'); 65 | $p_data = $this->GetKeyData(); 66 | 67 | $result = $this->HttpPostCookie($url, $p_data); 68 | 69 | $data = json_decode($result, true); 70 | 71 | return $data; 72 | } 73 | 74 | /** 75 | * 检查是否有安装任务 76 | */ 77 | 78 | public function GetTaskCount() 79 | { 80 | $url = $this->BT_PANEL . $this->config('GetTaskCount'); 81 | 82 | $p_data = $this->GetKeyData(); 83 | 84 | $result = $this->HttpPostCookie($url, $p_data); 85 | 86 | $data = json_decode($result, true); 87 | return $data; 88 | } 89 | 90 | /** 91 | * 检查面板更新 92 | */ 93 | 94 | public function UpdatePanel($check = false, $force = false) 95 | { 96 | $url = $this->BT_PANEL . $this->config('UpdatePanel'); 97 | 98 | $p_data = $this->GetKeyData(); 99 | $p_data['check'] = $check; 100 | $p_data['force'] = $force; 101 | 102 | $result = $this->HttpPostCookie($url, $p_data); 103 | 104 | $data = json_decode($result, true); 105 | return $data; 106 | } 107 | 108 | /** 109 | * 获取网站列表 110 | * @param string $page 当前分页 111 | * @param string $limit 取出的数据行数 112 | * @param string $type 分类标识 -1: 分部分类 0: 默认分类 113 | * @param string $order 排序规则 使用 id 降序:id desc 使用名称升序:name desc 114 | * @param string $tojs 分页 JS 回调, 若不传则构造 URI 分页连接 115 | * @param string $search 搜索内容 116 | */ 117 | 118 | public function Websites($search = '', $page = '1', $limit = '15', $type = '-1', $order = 'id desc', $tojs = '') 119 | { 120 | $url = $this->BT_PANEL . $this->config('Websites'); 121 | 122 | $p_data = $this->GetKeyData(); 123 | $p_data['p'] = $page; 124 | $p_data['limit'] = $limit; 125 | $p_data['type'] = $type; 126 | $p_data['order'] = $order; 127 | $p_data['tojs'] = $tojs; 128 | $p_data['search'] = $search; 129 | 130 | $result = $this->HttpPostCookie($url, $p_data); 131 | 132 | $data = json_decode($result, true); 133 | return $data; 134 | } 135 | 136 | /** 137 | * 获取网站FTP列表 138 | * @param string $page 当前分页 139 | * @param string $limit 取出的数据行数 140 | * @param string $type 分类标识 -1: 分部分类 0: 默认分类 141 | * @param string $order 排序规则 使用 id 降序:id desc 使用名称升序:name desc 142 | * @param string $tojs 分页 JS 回调, 若不传则构造 URI 分页连接 143 | * @param string $search 搜索内容 144 | */ 145 | 146 | public function WebFtpList($search = '', $page = '1', $limit = '15', $type = '-1', $order = 'id desc', $tojs = '') 147 | { 148 | $url = $this->BT_PANEL . $this->config('WebFtpList'); 149 | 150 | $p_data = $this->GetKeyData(); 151 | $p_data['p'] = $page; 152 | $p_data['limit'] = $limit; 153 | $p_data['type'] = $type; 154 | $p_data['order'] = $order; 155 | $p_data['tojs'] = $tojs; 156 | $p_data['search'] = $search; 157 | 158 | $result = $this->HttpPostCookie($url, $p_data); 159 | 160 | $data = json_decode($result, true); 161 | return $data; 162 | } 163 | 164 | /** 165 | * 获取网站SQL列表 166 | * @param string $page 当前分页 167 | * @param string $limit 取出的数据行数 168 | * @param string $type 分类标识 -1: 分部分类 0: 默认分类 169 | * @param string $order 排序规则 使用 id 降序:id desc 使用名称升序:name desc 170 | * @param string $tojs 分页 JS 回调, 若不传则构造 URI 分页连接 171 | * @param string $search 搜索内容 172 | */ 173 | 174 | public function WebSqlList($search = '', $page = '1', $limit = '15', $type = '-1', $order = 'id desc', $tojs = '') 175 | { 176 | $url = $this->BT_PANEL . $this->config('WebSqlList'); 177 | 178 | $p_data = $this->GetKeyData(); 179 | $p_data['p'] = $page; 180 | $p_data['limit'] = $limit; 181 | $p_data['type'] = $type; 182 | $p_data['order'] = $order; 183 | $p_data['tojs'] = $tojs; 184 | $p_data['search'] = $search; 185 | 186 | $result = $this->HttpPostCookie($url, $p_data); 187 | 188 | $data = json_decode($result, true); 189 | return $data; 190 | } 191 | 192 | /** 193 | * 获取所有网站分类 194 | */ 195 | 196 | public function Webtypes() 197 | { 198 | $url = $this->BT_PANEL . $this->config('Webtypes'); 199 | 200 | $p_data = $this->GetKeyData(); 201 | 202 | $result = $this->HttpPostCookie($url, $p_data); 203 | 204 | $data = json_decode($result, true); 205 | return $data; 206 | } 207 | 208 | /** 209 | * 获取已安装的 PHP 版本列表 210 | */ 211 | 212 | public function GetPHPVersion() 213 | { 214 | //拼接URL地址 215 | $url = $this->BT_PANEL . $this->config('GetPHPVersion'); 216 | 217 | //准备POST数据 218 | $p_data = $this->GetKeyData(); 219 | //取签名 220 | 221 | //请求面板接口 222 | $result = $this->HttpPostCookie($url, $p_data); 223 | 224 | //解析JSON数据 225 | $data = json_decode($result, true); 226 | 227 | return $data; 228 | } 229 | 230 | /** 231 | * 修改指定网站的PHP版本 232 | * @param [type] $site 网站名 233 | * @param [type] $php PHP版本 234 | */ 235 | 236 | public function SetPHPVersion($site, $php) 237 | { 238 | 239 | $url = $this->BT_PANEL . $this->config('SetPHPVersion'); 240 | 241 | $p_data = $this->GetKeyData(); 242 | $p_data['siteName'] = $site; 243 | $p_data['version'] = $php; 244 | $result = $this->HttpPostCookie($url, $p_data); 245 | 246 | $data = json_decode($result, true); 247 | return $data; 248 | } 249 | 250 | /** 251 | * 获取指定网站运行的PHP版本 252 | * @param [type] $site 网站名 253 | */ 254 | 255 | public function GetSitePHPVersion($site) 256 | { 257 | $url = $this->BT_PANEL . $this->config('GetSitePHPVersion'); 258 | 259 | $p_data = $this->GetKeyData(); 260 | $p_data['siteName'] = $site; 261 | $result = $this->HttpPostCookie($url, $p_data); 262 | 263 | $data = json_decode($result, true); 264 | return $data; 265 | } 266 | 267 | /** 268 | * 新增网站 269 | * @param [type] $webname 网站域名 json格式 270 | * @param [type] $path 网站路径 271 | * @param [type] $type_id 网站分类ID 272 | * @param string $type 网站类型 273 | * @param [type] $version PHP版本 274 | * @param [type] $port 网站端口 275 | * @param [type] $ps 网站备注 276 | * @param [type] $ftp 网站是否开通FTP 277 | * @param [type] $ftp_username FTP用户名 278 | * @param [type] $ftp_password FTP密码 279 | * @param [type] $sql 网站是否开通数据库 280 | * @param [type] $codeing 数据库编码类型 utf8|utf8mb4|gbk|big5 281 | * @param [type] $datauser 数据库账号 282 | * @param [type] $datapassword 数据库密码 283 | */ 284 | 285 | public function AddSite($infoArr = []) 286 | { 287 | $url = $this->BT_PANEL . $this->config('WebAddSite'); 288 | 289 | //准备POST数据 290 | $p_data = $this->GetKeyData(); 291 | //取签名 292 | $p_data['webname'] = $infoArr['webname']; 293 | $p_data['path'] = $infoArr['path']; 294 | $p_data['type_id'] = $infoArr['type_id']; 295 | $p_data['type'] = $infoArr['type']; 296 | $p_data['version'] = $infoArr['version']; 297 | $p_data['port'] = $infoArr['port']; 298 | $p_data['ps'] = $infoArr['ps']; 299 | $p_data['ftp'] = $infoArr['ftp']; 300 | $p_data['ftp_username'] = $infoArr['ftp_username']; 301 | $p_data['ftp_password'] = $infoArr['ftp_password']; 302 | $p_data['sql'] = $infoArr['sql']; 303 | $p_data['codeing'] = $infoArr['codeing']; 304 | $p_data['datauser'] = $infoArr['datauser']; 305 | $p_data['datapassword'] = $infoArr['datapassword']; 306 | 307 | //请求面板接口 308 | $result = $this->HttpPostCookie($url, $p_data); 309 | 310 | //解析JSON数据 311 | $data = json_decode($result, true); 312 | return $data; 313 | } 314 | 315 | /** 316 | * 删除网站 317 | * @param [type] $id 网站ID 318 | * @param [type] $webname 网站名称 319 | * @param [type] $ftp 是否删除关联FTP 320 | * @param [type] $database 是否删除关联数据库 321 | * @param [type] $path 是否删除关联网站根目录 322 | * 323 | */ 324 | 325 | public function WebDeleteSite($id, $webname, $ftp, $database, $path) 326 | { 327 | $url = $this->BT_PANEL . $this->config('WebDeleteSite'); 328 | 329 | $p_data = $this->GetKeyData(); 330 | $p_data['id'] = $id; 331 | $p_data['webname'] = $webname; 332 | $p_data['ftp'] = $ftp; 333 | $p_data['database'] = $database; 334 | $p_data['path'] = $path; 335 | 336 | $result = $this->HttpPostCookie($url, $p_data); 337 | 338 | $data = json_decode($result, true); 339 | return $data; 340 | } 341 | 342 | /** 343 | * 停用站点 344 | * @param [type] $id 网站ID 345 | * @param [type] $name 网站域名 346 | */ 347 | 348 | public function WebSiteStop($id, $name) 349 | { 350 | $url = $this->BT_PANEL . $this->config('WebSiteStop'); 351 | 352 | $p_data = $this->GetKeyData(); 353 | $p_data['id'] = $id; 354 | $p_data['name'] = $name; 355 | $result = $this->HttpPostCookie($url, $p_data); 356 | 357 | $data = json_decode($result, true); 358 | return $data; 359 | } 360 | 361 | /** 362 | * 启用网站 363 | * @param [type] $id 网站ID 364 | * @param [type] $name 网站域名 365 | */ 366 | 367 | public function WebSiteStart($id, $name) 368 | { 369 | $url = $this->BT_PANEL . $this->config('WebSiteStart'); 370 | 371 | $p_data = $this->GetKeyData(); 372 | $p_data['id'] = $id; 373 | $p_data['name'] = $name; 374 | $result = $this->HttpPostCookie($url, $p_data); 375 | 376 | $data = json_decode($result, true); 377 | return $data; 378 | } 379 | 380 | /** 381 | * 设置网站到期时间 382 | * @param [type] $id 网站ID 383 | * @param [type] $edate 网站到期时间 格式:2019-01-01,永久:0000-00-00 384 | */ 385 | 386 | public function WebSetEdate($id, $edate) 387 | { 388 | $url = $this->BT_PANEL . $this->config('WebSetEdate'); 389 | 390 | $p_data = $this->GetKeyData(); 391 | $p_data['id'] = $id; 392 | $p_data['edate'] = $edate; 393 | $result = $this->HttpPostCookie($url, $p_data); 394 | 395 | $data = json_decode($result, true); 396 | return $data; 397 | } 398 | 399 | /** 400 | * 修改网站备注 401 | * @param [type] $id 网站ID 402 | * @param [type] $ps 网站备注 403 | */ 404 | 405 | public function WebSetPs($id, $ps) 406 | { 407 | $url = $this->BT_PANEL . $this->config('WebSetPs'); 408 | 409 | $p_data = $this->GetKeyData(); 410 | $p_data['id'] = $id; 411 | $p_data['ps'] = $ps; 412 | $result = $this->HttpPostCookie($url, $p_data); 413 | 414 | $data = json_decode($result, true); 415 | return $data; 416 | } 417 | 418 | /** 419 | * 获取网站备份列表 420 | * @param [type] $id 网站ID 421 | * @param string $page 当前分页 422 | * @param string $limit 每页取出的数据行数 423 | * @param string $type 备份类型 目前固定为0 424 | * @param string $tojs 分页js回调若不传则构造 URI 分页连接 get_site_backup 425 | */ 426 | 427 | public function WebBackupList($id, $page = '1', $limit = '5', $type = '0', $tojs = '') 428 | { 429 | $url = $this->BT_PANEL . $this->config('WebBackupList'); 430 | 431 | $p_data = $this->GetKeyData(); 432 | $p_data['p'] = $page; 433 | $p_data['limit'] = $limit; 434 | $p_data['type'] = $type; 435 | $p_data['tojs'] = $tojs; 436 | $p_data['search'] = $id; 437 | $result = $this->HttpPostCookie($url, $p_data); 438 | 439 | $data = json_decode($result, true); 440 | return $data; 441 | } 442 | 443 | /** 444 | * 创建网站备份 445 | * @param [type] $id 网站ID 446 | */ 447 | 448 | public function WebToBackup($id) 449 | { 450 | $url = $this->BT_PANEL . $this->config('WebToBackup'); 451 | 452 | $p_data = $this->GetKeyData(); 453 | $p_data['id'] = $id; 454 | $result = $this->HttpPostCookie($url, $p_data); 455 | 456 | $data = json_decode($result, true); 457 | return $data; 458 | } 459 | 460 | /** 461 | * 删除网站备份 462 | * @param [type] $id 网站备份ID 463 | */ 464 | 465 | public function WebDelBackup($id) 466 | { 467 | $url = $this->BT_PANEL . $this->config('WebDelBackup'); 468 | 469 | $p_data = $this->GetKeyData(); 470 | $p_data['id'] = $id; 471 | $result = $this->HttpPostCookie($url, $p_data); 472 | 473 | $data = json_decode($result, true); 474 | return $data; 475 | } 476 | 477 | /** 478 | * 删除数据库备份 479 | * @param [type] $id 数据库备份ID 480 | */ 481 | 482 | public function SQLDelBackup($id) 483 | { 484 | $url = $this->BT_PANEL . $this->config('SQLDelBackup'); 485 | 486 | $p_data = $this->GetKeyData(); 487 | $p_data['id'] = $id; 488 | $result = $this->HttpPostCookie($url, $p_data); 489 | 490 | $data = json_decode($result, true); 491 | return $data; 492 | } 493 | 494 | /** 495 | * 备份数据库 496 | * @param [type] $id 数据库列表ID 497 | */ 498 | 499 | public function SQLToBackup($id) 500 | { 501 | $url = $this->BT_PANEL . $this->config('SQLToBackup'); 502 | 503 | $p_data = $this->GetKeyData(); 504 | $p_data['id'] = $id; 505 | $result = $this->HttpPostCookie($url, $p_data); 506 | 507 | $data = json_decode($result, true); 508 | return $data; 509 | } 510 | 511 | /** 512 | * 获取网站域名列表 513 | * @param [type] $id 网站ID 514 | * @param boolean $list 固定传true 515 | */ 516 | 517 | public function WebDoaminList($id, $list = true) 518 | { 519 | $url = $this->BT_PANEL . $this->config('WebDoaminList'); 520 | 521 | $p_data = $this->GetKeyData(); 522 | $p_data['search'] = $id; 523 | $p_data['list'] = $list; 524 | $result = $this->HttpPostCookie($url, $p_data); 525 | 526 | $data = json_decode($result, true); 527 | return $data; 528 | } 529 | 530 | /** 531 | * 添加域名 532 | * @param [type] $id 网站ID 533 | * @param [type] $webname 网站名称 534 | * @param [type] $domain 要添加的域名:端口 80 端品不必构造端口, 多个域名用换行符隔开 535 | */ 536 | 537 | public function WebAddDomain($id, $webname, $domain) 538 | { 539 | $url = $this->BT_PANEL . $this->config('WebAddDomain'); 540 | 541 | $p_data = $this->GetKeyData(); 542 | $p_data['id'] = $id; 543 | $p_data['webname'] = $webname; 544 | $p_data['domain'] = $domain; 545 | $result = $this->HttpPostCookie($url, $p_data); 546 | 547 | $data = json_decode($result, true); 548 | return $data; 549 | } 550 | 551 | /** 552 | * 删除网站域名 553 | * @param [type] $id 网站ID 554 | * @param [type] $webname 网站名 555 | * @param [type] $domain 网站域名 556 | * @param [type] $port 网站域名端口 557 | */ 558 | 559 | public function WebDelDomain($id, $webname, $domain, $port) 560 | { 561 | $url = $this->BT_PANEL . $this->config('WebDelDomain'); 562 | 563 | $p_data = $this->GetKeyData(); 564 | $p_data['id'] = $id; 565 | $p_data['webname'] = $webname; 566 | $p_data['domain'] = $domain; 567 | $p_data['port'] = $port; 568 | $result = $this->HttpPostCookie($url, $p_data); 569 | 570 | $data = json_decode($result, true); 571 | return $data; 572 | } 573 | 574 | /** 575 | * 获取可选的预定义伪静态列表 576 | * @param [type] $siteName 网站名 577 | */ 578 | 579 | public function GetRewriteList($siteName) 580 | { 581 | $url = $this->BT_PANEL . $this->config('GetRewriteList'); 582 | 583 | $p_data = $this->GetKeyData(); 584 | $p_data['siteName'] = $siteName; 585 | $result = $this->HttpPostCookie($url, $p_data); 586 | 587 | $data = json_decode($result, true); 588 | return $data; 589 | } 590 | 591 | /** 592 | * 获取预置伪静态规则内容(文件内容) 593 | * @param [type] $path 规则名 594 | * @param [type] $type 0->获取内置伪静态规则; 595 | 1->获取当前站点伪静态规则 596 | */ 597 | 598 | public function GetFileBody($path, $type = 0) 599 | { 600 | $url = $this->BT_PANEL . $this->config('GetFileBody'); 601 | $p_data = $this->GetKeyData(); 602 | $path_dir = $type ? 'vhost/rewrite' : 'rewrite/nginx'; 603 | 604 | //获取当前站点伪静态规则 605 | ///www/server/panel/vhost/rewrite/user_hvVBT_1.test.com.conf 606 | //获取内置伪静态规则 607 | ///www/server/panel/rewrite/nginx/EmpireCMS.conf 608 | //保存伪静态规则到站点 609 | ///www/server/panel/vhost/rewrite/user_hvVBT_1.test.com.conf 610 | ///www/server/panel/rewrite/nginx/typecho.conf 611 | $p_data['path'] = '/www/server/panel/' . $path_dir . '/' . $path . '.conf'; 612 | //var_dump( $p_data['path'] ); 613 | $result = $this->HttpPostCookie($url, $p_data); 614 | 615 | $data = json_decode($result, true); 616 | return $data; 617 | } 618 | 619 | /** 620 | * 保存伪静态规则内容( 保存文件内容 ) 621 | * @param [type] $path 规则名 622 | * @param [type] $data 规则内容 623 | * @param string $encoding 规则编码强转utf-8 624 | * @param number $type 0->系统默认路径; 625 | * 1->自定义全路径 626 | */ 627 | 628 | public function SaveFileBody($path, $data, $encoding = 'utf-8', $type = 0) 629 | { 630 | $url = $this->BT_PANEL . $this->config('SaveFileBody'); 631 | if ($type) { 632 | $path_dir = $path; 633 | } else { 634 | $path_dir = '/www/server/panel/vhost/rewrite/' . $path . '.conf'; 635 | } 636 | $p_data = $this->GetKeyData(); 637 | $p_data['path'] = $path_dir; 638 | $p_data['data'] = $data; 639 | $p_data['encoding'] = $encoding; 640 | $result = $this->HttpPostCookie($url, $p_data); 641 | 642 | $data = json_decode($result, true); 643 | return $data; 644 | } 645 | 646 | /** 647 | * 设置密码访问网站 648 | * @param [type] $id 网站ID 649 | * @param [type] $username 用户名 650 | * @param [type] $password 密码 651 | */ 652 | 653 | public function SetHasPwd($id, $username, $password) 654 | { 655 | $url = $this->BT_PANEL . $this->config('SetHasPwd'); 656 | 657 | $p_data = $this->GetKeyData(); 658 | $p_data['id'] = $id; 659 | $p_data['username'] = $username; 660 | $p_data['password'] = $password; 661 | $result = $this->HttpPostCookie($url, $p_data); 662 | 663 | $data = json_decode($result, true); 664 | return $data; 665 | } 666 | 667 | /** 668 | * 关闭密码访问网站 669 | * @param [type] $id 网站ID 670 | */ 671 | 672 | public function CloseHasPwd($id) 673 | { 674 | $url = $this->BT_PANEL . $this->config('CloseHasPwd'); 675 | 676 | $p_data = $this->GetKeyData(); 677 | $p_data['id'] = $id; 678 | $result = $this->HttpPostCookie($url, $p_data); 679 | 680 | $data = json_decode($result, true); 681 | return $data; 682 | } 683 | 684 | /** 685 | * 获取网站日志 686 | * @param [type] $site 网站名 687 | */ 688 | 689 | public function GetSiteLogs($site) 690 | { 691 | $url = $this->BT_PANEL . $this->config('GetSiteLogs'); 692 | 693 | $p_data = $this->GetKeyData(); 694 | $p_data['siteName'] = $site; 695 | $result = $this->HttpPostCookie($url, $p_data); 696 | 697 | $data = json_decode($result, true); 698 | return $data; 699 | } 700 | 701 | /** 702 | * 获取网站盗链状态及规则信息 703 | * @param [type] $id 网站ID 704 | * @param [type] $site 网站名 705 | */ 706 | 707 | public function GetSecurity($id, $site) 708 | { 709 | $url = $this->BT_PANEL . $this->config('GetSecurity'); 710 | 711 | $p_data = $this->GetKeyData(); 712 | $p_data['id'] = $id; 713 | $p_data['name'] = $site; 714 | $result = $this->HttpPostCookie($url, $p_data); 715 | 716 | $data = json_decode($result, true); 717 | return $data; 718 | } 719 | 720 | /** 721 | * 设置网站盗链状态及规则信息 722 | * @param [type] $id 网站ID 723 | * @param [type] $site 网站名 724 | * @param [type] $fix URL后缀 725 | * @param [type] $domains 许可域名 726 | * @param [type] $status 状态 727 | */ 728 | 729 | public function SetSecurity($id, $site, $fix, $domains, $status) 730 | { 731 | $url = $this->BT_PANEL . $this->config('SetSecurity'); 732 | 733 | $p_data = $this->GetKeyData(); 734 | $p_data['id'] = $id; 735 | $p_data['name'] = $site; 736 | $p_data['fix'] = $fix; 737 | $p_data['domains'] = $domains; 738 | $p_data['status'] = $status; 739 | $result = $this->HttpPostCookie($url, $p_data); 740 | 741 | $data = json_decode($result, true); 742 | return $data; 743 | } 744 | 745 | /** 746 | * 获取网站三项配置开关(防跨站、日志、密码访问) 747 | * @param [type] $id 网站ID 748 | * @param [type] $path 网站运行目录 749 | */ 750 | 751 | public function GetDirUserINI($id, $path) 752 | { 753 | $url = $this->BT_PANEL . $this->config('GetDirUserINI'); 754 | 755 | $p_data = $this->GetKeyData(); 756 | $p_data['id'] = $id; 757 | $p_data['path'] = $path; 758 | $result = $this->HttpPostCookie($url, $p_data); 759 | 760 | $data = json_decode($result, true); 761 | return $data; 762 | } 763 | 764 | /** 765 | * 开启强制HTTPS 766 | * @param [type] $site 网站域名(纯域名) 767 | */ 768 | 769 | public function HttpToHttps($site) 770 | { 771 | $url = $this->BT_PANEL . $this->config('HttpToHttps'); 772 | 773 | $p_data = $this->GetKeyData(); 774 | $p_data['siteName'] = $site; 775 | $result = $this->HttpPostCookie($url, $p_data); 776 | 777 | $data = json_decode($result, true); 778 | return $data; 779 | } 780 | 781 | /** 782 | * 关闭强制HTTPS 783 | * @param [type] $site 域名( 纯域名 ) 784 | */ 785 | 786 | public function CloseToHttps($site) 787 | { 788 | $url = $this->BT_PANEL . $this->config('CloseToHttps'); 789 | 790 | $p_data = $this->GetKeyData(); 791 | $p_data['siteName'] = $site; 792 | $result = $this->HttpPostCookie($url, $p_data); 793 | 794 | $data = json_decode($result, true); 795 | return $data; 796 | } 797 | 798 | /** 799 | * 设置SSL域名证书 800 | * @param [type] $type 类型 801 | * @param [type] $site 网站名 802 | * @param [type] $key 证书key 803 | * @param [type] $csr 证书PEM 804 | */ 805 | 806 | public function SetSSL($type, $site, $key, $csr) 807 | { 808 | $url = $this->BT_PANEL . $this->config('SetSSL'); 809 | 810 | $p_data = $this->GetKeyData(); 811 | $p_data['type'] = $type; 812 | $p_data['siteName'] = $site; 813 | $p_data['key'] = $key; 814 | $p_data['csr'] = $csr; 815 | $result = $this->HttpPostCookie($url, $p_data); 816 | 817 | $data = json_decode($result, true); 818 | return $data; 819 | } 820 | 821 | /** 822 | * 关闭SSL 823 | * @param [type] $updateOf 修改状态码 824 | * @param [type] $site 域名( 纯域名 ) 825 | */ 826 | 827 | public function CloseSSLConf($updateOf, $site) 828 | { 829 | $url = $this->BT_PANEL . $this->config('CloseSSLConf'); 830 | 831 | $p_data = $this->GetKeyData(); 832 | $p_data['updateOf'] = $updateOf; 833 | $p_data['siteName'] = $site; 834 | $result = $this->HttpPostCookie($url, $p_data); 835 | 836 | $data = json_decode($result, true); 837 | return $data; 838 | } 839 | 840 | /** 841 | * 获取SSL状态及证书信息 842 | * @param [type] $site 域名(纯域名) 843 | */ 844 | 845 | public function GetSSL($site) 846 | { 847 | $url = $this->BT_PANEL . $this->config('GetSSL'); 848 | 849 | $p_data = $this->GetKeyData(); 850 | $p_data['siteName'] = $site; 851 | $result = $this->HttpPostCookie($url, $p_data); 852 | 853 | $data = json_decode($result, true); 854 | return $data; 855 | } 856 | 857 | /** 858 | * 获取网站默认文件 859 | * @param [type] $id 网站ID 860 | */ 861 | 862 | public function WebGetIndex($id) 863 | { 864 | $url = $this->BT_PANEL . $this->config('WebGetIndex'); 865 | 866 | $p_data = $this->GetKeyData(); 867 | $p_data['id'] = $id; 868 | $result = $this->HttpPostCookie($url, $p_data); 869 | 870 | $data = json_decode($result, true); 871 | return $data; 872 | } 873 | 874 | /** 875 | * 设置网站默认文件 876 | * @param [type] $id 网站ID 877 | * @param [type] $index 内容 878 | */ 879 | 880 | public function WebSetIndex($id, $index) 881 | { 882 | $url = $this->BT_PANEL . $this->config('WebSetIndex'); 883 | 884 | $p_data = $this->GetKeyData(); 885 | $p_data['id'] = $id; 886 | $p_data['Index'] = $index; 887 | $result = $this->HttpPostCookie($url, $p_data); 888 | 889 | $data = json_decode($result, true); 890 | return $data; 891 | } 892 | 893 | /** 894 | * 获取网站流量限制信息 895 | * @param [type] $id [description] 896 | */ 897 | 898 | public function GetLimitNet($id) 899 | { 900 | $url = $this->BT_PANEL . $this->config('GetLimitNet'); 901 | 902 | $p_data = $this->GetKeyData(); 903 | $p_data['id'] = $id; 904 | $result = $this->HttpPostCookie($url, $p_data); 905 | 906 | $data = json_decode($result, true); 907 | return $data; 908 | } 909 | 910 | /** 911 | * 设置网站流量限制信息 912 | * @param [type] $id 网站ID 913 | * @param [type] $perserver 并发限制 914 | * @param [type] $perip 单IP限制 915 | * @param [type] $limit_rate 流量限制 916 | */ 917 | 918 | public function SetLimitNet($id, $perserver, $perip, $limit_rate) 919 | { 920 | $url = $this->BT_PANEL . $this->config('SetLimitNet'); 921 | 922 | $p_data = $this->GetKeyData(); 923 | $p_data['id'] = $id; 924 | $p_data['perserver'] = $perserver; 925 | $p_data['perip'] = $perip; 926 | $p_data['limit_rate'] = $limit_rate; 927 | $result = $this->HttpPostCookie($url, $p_data); 928 | 929 | $data = json_decode($result, true); 930 | return $data; 931 | } 932 | 933 | /** 934 | * 关闭网站流量限制 935 | * @param [type] $id 网站ID 936 | */ 937 | 938 | public function CloseLimitNet($id) 939 | { 940 | $url = $this->BT_PANEL . $this->config('CloseLimitNet'); 941 | 942 | $p_data = $this->GetKeyData(); 943 | $p_data['id'] = $id; 944 | $result = $this->HttpPostCookie($url, $p_data); 945 | 946 | $data = json_decode($result, true); 947 | return $data; 948 | } 949 | 950 | /** 951 | * 获取网站301重定向信息 952 | * @param [type] $site 网站名 953 | */ 954 | 955 | public function Get301Status($site) 956 | { 957 | $url = $this->BT_PANEL . $this->config('Get301Status'); 958 | 959 | $p_data = $this->GetKeyData(); 960 | $p_data['siteName'] = $site; 961 | $result = $this->HttpPostCookie($url, $p_data); 962 | 963 | $data = json_decode($result, true); 964 | return $data; 965 | } 966 | 967 | /** 968 | * 设置网站301重定向信息 969 | * @param [type] $site 网站名 970 | * @param [type] $toDomain 目标Url 971 | * @param [type] $srcDomain 来自Url 972 | * @param [type] $type 类型 973 | */ 974 | 975 | public function Set301Status($site, $toDomain, $srcDomain, $type) 976 | { 977 | $url = $this->BT_PANEL . $this->config('Set301Status'); 978 | 979 | $p_data = $this->GetKeyData(); 980 | $p_data['siteName'] = $site; 981 | $p_data['toDomain'] = $toDomain; 982 | $p_data['srcDomain'] = $srcDomain; 983 | $p_data['type'] = $type; 984 | $result = $this->HttpPostCookie($url, $p_data); 985 | 986 | $data = json_decode($result, true); 987 | return $data; 988 | } 989 | 990 | /** 991 | * 获取网站反代信息及状态 992 | * @param [type] $site [description] 993 | */ 994 | 995 | public function GetProxyList($site) 996 | { 997 | $url = $this->BT_PANEL . $this->config('GetProxyList'); 998 | 999 | $p_data = $this->GetKeyData(); 1000 | $p_data['sitename'] = $site; 1001 | $result = $this->HttpPostCookie($url, $p_data); 1002 | 1003 | $data = json_decode($result, true); 1004 | return $data; 1005 | } 1006 | 1007 | /** 1008 | * 添加网站反代信息 1009 | * @param [type] $cache 是否缓存 1010 | * @param [type] $proxyname 代理名称 1011 | * @param [type] $cachetime 缓存时长 /小时 1012 | * @param [type] $proxydir 代理目录 1013 | * @param [type] $proxysite 反代URL 1014 | * @param [type] $todomain 目标域名 1015 | * @param [type] $advanced 高级功能:开启代理目录 1016 | * @param [type] $sitename 网站名 1017 | * @param [type] $subfilter 文本替换json格式 1018 | */ 1019 | 1020 | public function CreateProxy($cache, $proxyname, $cachetime, $proxydir, $proxysite, $todomain, $advanced, $sitename, $subfilter, $type) 1021 | { 1022 | $url = $this->BT_PANEL . $this->config('CreateProxy'); 1023 | 1024 | $p_data = $this->GetKeyData(); 1025 | $p_data['cache'] = $cache; 1026 | $p_data['proxyname'] = $proxyname; 1027 | $p_data['cachetime'] = $cachetime; 1028 | $p_data['proxydir'] = $proxydir; 1029 | $p_data['proxysite'] = $proxysite; 1030 | $p_data['todomain'] = $todomain; 1031 | $p_data['advanced'] = $advanced; 1032 | $p_data['sitename'] = $sitename; 1033 | $p_data['subfilter'] = $subfilter; 1034 | $p_data['type'] = $type; 1035 | $result = $this->HttpPostCookie($url, $p_data); 1036 | 1037 | $data = json_decode($result, true); 1038 | return $data; 1039 | } 1040 | 1041 | /** 1042 | * 添加网站反代信息 1043 | * @param [type] $cache 是否缓存 1044 | * @param [type] $proxyname 代理名称 1045 | * @param [type] $cachetime 缓存时长 /小时 1046 | * @param [type] $proxydir 代理目录 1047 | * @param [type] $proxysite 反代URL 1048 | * @param [type] $todomain 目标域名 1049 | * @param [type] $advanced 高级功能:开启代理目录 1050 | * @param [type] $sitename 网站名 1051 | * @param [type] $subfilter 文本替换json格式 1052 | */ 1053 | 1054 | public function ModifyProxy($cache, $proxyname, $cachetime, $proxydir, $proxysite, $todomain, $advanced, $sitename, $subfilter, $type) 1055 | { 1056 | $url = $this->BT_PANEL . $this->config('ModifyProxy'); 1057 | 1058 | $p_data = $this->GetKeyData(); 1059 | $p_data['cache'] = $cache; 1060 | $p_data['proxyname'] = $proxyname; 1061 | $p_data['cachetime'] = $cachetime; 1062 | $p_data['proxydir'] = $proxydir; 1063 | $p_data['proxysite'] = $proxysite; 1064 | $p_data['todomain'] = $todomain; 1065 | $p_data['advanced'] = $advanced; 1066 | $p_data['sitename'] = $sitename; 1067 | $p_data['subfilter'] = $subfilter; 1068 | $p_data['type'] = $type; 1069 | $result = $this->HttpPostCookie($url, $p_data); 1070 | 1071 | $data = json_decode($result, true); 1072 | return $data; 1073 | } 1074 | 1075 | /** 1076 | * 获取网站域名绑定二级目录信息 1077 | * @param [type] $id 网站ID 1078 | */ 1079 | 1080 | public function GetDirBinding($id) 1081 | { 1082 | $url = $this->BT_PANEL . $this->config('GetDirBinding'); 1083 | 1084 | $p_data = $this->GetKeyData(); 1085 | $p_data['id'] = $id; 1086 | $result = $this->HttpPostCookie($url, $p_data); 1087 | 1088 | $data = json_decode($result, true); 1089 | return $data; 1090 | } 1091 | 1092 | /** 1093 | * 设置网站域名绑定二级目录 1094 | * @param [type] $id 网站ID 1095 | * @param [type] $domain 域名 1096 | * @param [type] $dirName 目录 1097 | */ 1098 | 1099 | public function AddDirBinding($id, $domain, $dirName) 1100 | { 1101 | $url = $this->BT_PANEL . $this->config('AddDirBinding'); 1102 | 1103 | $p_data = $this->GetKeyData(); 1104 | $p_data['id'] = $id; 1105 | $p_data['domain'] = $domain; 1106 | $p_data['dirName'] = $dirName; 1107 | $result = $this->HttpPostCookie($url, $p_data); 1108 | 1109 | $data = json_decode($result, true); 1110 | return $data; 1111 | } 1112 | 1113 | /** 1114 | * 删除网站域名绑定二级目录 1115 | * @param [type] $dirid 子目录ID 1116 | */ 1117 | 1118 | public function DelDirBinding($dirid) 1119 | { 1120 | $url = $this->BT_PANEL . $this->config('DelDirBinding'); 1121 | 1122 | $p_data = $this->GetKeyData(); 1123 | $p_data['id'] = $dirid; 1124 | $result = $this->HttpPostCookie($url, $p_data); 1125 | 1126 | $data = json_decode($result, true); 1127 | return $data; 1128 | } 1129 | 1130 | /** 1131 | * 获取网站子目录绑定伪静态信息 1132 | * @param [type] $dirid 子目录绑定ID 1133 | */ 1134 | 1135 | public function GetDirRewrite($dirid, $type = 0) 1136 | { 1137 | $url = $this->BT_PANEL . $this->config('GetDirRewrite'); 1138 | 1139 | $p_data = $this->GetKeyData(); 1140 | $p_data['id'] = $dirid; 1141 | if ($type) { 1142 | $p_data['add'] = 1; 1143 | } 1144 | $result = $this->HttpPostCookie($url, $p_data); 1145 | 1146 | $data = json_decode($result, true); 1147 | return $data; 1148 | } 1149 | 1150 | /** 1151 | * 修改FTP账号密码 1152 | * @param [type] $id FTPID 1153 | * @param [type] $ftp_username 用户名 1154 | * @param [type] $new_password 密码 1155 | */ 1156 | 1157 | public function SetUserPassword($id, $ftp_username, $new_password) 1158 | { 1159 | $url = $this->BT_PANEL . $this->config('SetUserPassword'); 1160 | 1161 | $p_data = $this->GetKeyData(); 1162 | $p_data['id'] = $id; 1163 | $p_data['ftp_username'] = $ftp_username; 1164 | $p_data['new_password'] = $new_password; 1165 | $result = $this->HttpPostCookie($url, $p_data); 1166 | 1167 | $data = json_decode($result, true); 1168 | return $data; 1169 | } 1170 | 1171 | /** 1172 | * 修改SQL账号密码 1173 | * @param [type] $id SQLID 1174 | * @param [type] $ftp_username 用户名 1175 | * @param [type] $new_password 密码 1176 | */ 1177 | 1178 | public function ResDatabasePass($id, $name, $password) 1179 | { 1180 | $url = $this->BT_PANEL . $this->config('ResDatabasePass'); 1181 | 1182 | $p_data = $this->GetKeyData(); 1183 | $p_data['id'] = $id; 1184 | $p_data['name'] = $name; 1185 | $p_data['password'] = $password; 1186 | $result = $this->HttpPostCookie($url, $p_data); 1187 | 1188 | $data = json_decode($result, true); 1189 | return $data; 1190 | } 1191 | 1192 | /** 1193 | * 启用/禁用FTP 1194 | * @param [type] $id FTPID 1195 | * @param [type] $username 用户名 1196 | * @param [type] $status 状态 0->关闭, 1->开启 1197 | */ 1198 | 1199 | public function SetStatus($id, $username, $status) 1200 | { 1201 | $url = $this->BT_PANEL . $this->config('SetStatus'); 1202 | 1203 | $p_data = $this->GetKeyData(); 1204 | $p_data['id'] = $id; 1205 | $p_data['username'] = $username; 1206 | $p_data['status'] = $status; 1207 | $result = $this->HttpPostCookie($url, $p_data); 1208 | 1209 | $data = json_decode($result, true); 1210 | return $data; 1211 | } 1212 | 1213 | /** 1214 | * 宝塔一键部署列表 1215 | * @param string $search 搜索关键词 1216 | * @return [type] [description] 1217 | */ 1218 | 1219 | public function deployment($search = '') 1220 | { 1221 | if ($search) { 1222 | $url = $this->BT_PANEL . $this->config('deployment') . '&search=' . $search; 1223 | } else { 1224 | $url = $this->BT_PANEL . $this->config('deployment'); 1225 | } 1226 | 1227 | $p_data = $this->GetKeyData(); 1228 | $result = $this->HttpPostCookie($url, $p_data); 1229 | 1230 | $data = json_decode($result, true); 1231 | return $data; 1232 | } 1233 | 1234 | /** 1235 | * 宝塔一键部署执行 1236 | * @param [type] $dname 部署程序名 1237 | * @param [type] $site_name 部署到网站名 1238 | * @param [type] $php_version PHP版本 1239 | */ 1240 | 1241 | public function SetupPackage($dname, $site_name, $php_version) 1242 | { 1243 | $url = $this->BT_PANEL . $this->config('SetupPackage'); 1244 | 1245 | $p_data = $this->GetKeyData(); 1246 | $p_data['dname'] = $dname; 1247 | $p_data['site_name'] = $site_name; 1248 | $p_data['php_version'] = $php_version; 1249 | $result = $this->HttpPostCookie($url, $p_data); 1250 | 1251 | $data = json_decode($result, true); 1252 | return $data; 1253 | } 1254 | /** 1255 | * 计划任务列表 1256 | * @return [string] 1257 | */ 1258 | 1259 | public function CrontabList() 1260 | { 1261 | $url = $this->BT_PANEL . $this->config('crontabList'); 1262 | $p_data = $this->GetKeyData(); 1263 | $p_data['name'] = ''; 1264 | $p_data['sType'] = ''; 1265 | $result = $this->HttpPostCookie($url, $p_data); 1266 | return $result; 1267 | } 1268 | 1269 | public function AddCrontab() 1270 | { 1271 | $url = $this->BT_PANEL . $this->config('AddCrontab'); 1272 | 1273 | $p_data = $this->GetKeyData(); 1274 | $result = $this->HttpPostCookie($url, $p_data); 1275 | return $result; 1276 | } 1277 | 1278 | /** 1279 | * 构造带有签名的关联数组 1280 | */ 1281 | 1282 | public function GetKeyData() 1283 | { 1284 | $now_time = time(); 1285 | $p_data = array( 1286 | 'request_token' => md5($now_time . '' . md5($this->BT_KEY)), 1287 | 'request_time' => $now_time 1288 | ); 1289 | return $p_data; 1290 | } 1291 | 1292 | /** 1293 | * 发起POST请求 1294 | * @param String $url 目标网填,带http:// 1295 | * @param Array|String $data 欲提交的数据 1296 | * @return string 1297 | */ 1298 | 1299 | private function HttpPostCookie($url, $data, $timeout = 60) 1300 | { 1301 | //定义cookie保存位置 1302 | $cookie_file = 'app/cookie/' . md5($this->BT_PANEL) . '.cookie'; 1303 | if (!file_exists($cookie_file)) { 1304 | $fopen = fopen($cookie_file, 'wb '); //新建文bai件命令du 1305 | fputs($fopen, ''); //向文zhi件中写入内容; 1306 | fclose($fopen); 1307 | } 1308 | 1309 | $ch = curl_init(); 1310 | curl_setopt($ch, CURLOPT_URL, $url); 1311 | curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); 1312 | curl_setopt($ch, CURLOPT_POST, 1); 1313 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 1314 | curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file); 1315 | curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file); 1316 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 1317 | curl_setopt($ch, CURLOPT_HEADER, 0); 1318 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 1319 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 1320 | $output = curl_exec($ch); 1321 | curl_close($ch); 1322 | return $output; 1323 | } 1324 | 1325 | /** 1326 | * 加载宝塔数据接口 1327 | * @param [type] $str [description] 1328 | * @return [type] [description] 1329 | */ 1330 | 1331 | private function config($str) 1332 | { 1333 | require_once(__ROOT__ . '/app/config/BtConfig.php'); 1334 | return $config[$str]; 1335 | } 1336 | } -------------------------------------------------------------------------------- /app/model/Lunar.php: -------------------------------------------------------------------------------- 1 | lunarInfo[$year-$this->MIN_YEAR]; 57 | if ( $year == $this->MIN_YEAR && $month <= 2 && $date <= 9 ) return array( 1891, '正月', '初一', '辛卯', 1, 1, '兔' ); 58 | return $this->getLunarByBetween( $year, $this->getDaysBetweenSolar( $year, $month, $date, $yearData[1], $yearData[2] ) ); 59 | } 60 | 61 | function convertSolarMonthToLunar( $year, $month ) 62 | { 63 | $yearData = $this->lunarInfo[$year-$this->MIN_YEAR]; 64 | if ( $year == $this->MIN_YEAR && $month <= 2 && $date <= 9 ) return array( 1891, '正月', '初一', '辛卯', 1, 1, '兔' ); 65 | $month_days_ary = array( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ); 66 | $dd = $month_days_ary[$month]; 67 | if ( $this->isLeapYear( $year ) && $month == 2 ) $dd++; 68 | $lunar_ary = array(); 69 | for ( $i = 1; $i < $dd; $i++ ) 70 | { 71 | $array = $this->getLunarByBetween( $year, $this->getDaysBetweenSolar( $year, $month, $i, $yearData[1], $yearData[2] ) ); 72 | $array[] = $year . '-' . $month . '-' . $i; 73 | $lunar_ary[$i] = $array; 74 | } 75 | return $lunar_ary; 76 | } 77 | /** 78 | * 将阴历转换为阳历 79 | * @param year 阴历-年 80 | * @param month 阴历-月,闰月处理:例如如果当年闰五月,那么第二个五月就传六月,相当于阴历有13个月,只是有的时候第13个月的天数为0 81 | * @param date 阴历-日 82 | */ 83 | 84 | function convertLunarToSolar( $year, $month, $date ) 85 | { 86 | $yearData = $this->lunarInfo[$year-$this->MIN_YEAR]; 87 | $between = $this->getDaysBetweenLunar( $year, $month, $date ); 88 | $res = mktime( 0, 0, 0, $yearData[1], $yearData[2], $year ); 89 | $res = date( 'Y-m-d', $res+$between*24*60*60 ); 90 | $day = explode( '-', $res ); 91 | $year = $day[0]; 92 | $month = $day[1]; 93 | $day = $day[2]; 94 | return array( $year, $month, $day ); 95 | } 96 | /** 97 | * 判断是否是闰年 98 | * @param year 99 | */ 100 | 101 | function isLeapYear( $year ) 102 | { 103 | return ( ( $year%4 == 0 && $year%100 != 0 ) || ( $year%400 == 0 ) ); 104 | } 105 | /** 106 | * 获取干支纪年 107 | * @param year 108 | */ 109 | 110 | function getLunarYearName( $year ) 111 | { 112 | $sky = array( '庚', '辛', '壬', '癸', '甲', '乙', '丙', '丁', '戊', '己' ); 113 | $earth = array( '申', '酉', '戌', '亥', '子', '丑', '寅', '卯', '辰', '巳', '午', '未' ); 114 | $year = $year.''; 115 | return $sky[$year { 116 | 3} 117 | ].$earth[$year%12]; 118 | } 119 | /** 120 | * 根据阴历年获取生肖 121 | * @param year 阴历年 122 | */ 123 | 124 | function getYearZodiac( $year ) 125 | { 126 | $zodiac = array( '猴', '鸡', '狗', '猪', '鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊' ); 127 | return $zodiac[$year%12]; 128 | } 129 | /** 130 | * 获取阳历月份的天数 131 | * @param year 阳历-年 132 | * @param month 阳历-月 133 | */ 134 | 135 | function getSolarMonthDays( $year, $month ) 136 | { 137 | $monthHash = array( '1'=>31, '2'=>$this->isLeapYear( $year )?29:28, '3'=>31, '4'=>30, '5'=>31, '6'=>30, '7'=>31, '8'=>31, '9'=>30, '10'=>31, '11'=>30, '12'=>31 ); 138 | return $monthHash["$month"]; 139 | } 140 | /** 141 | * 获取阴历月份的天数 142 | * @param year 阴历-年 143 | * @param month 阴历-月,从一月开始 144 | */ 145 | 146 | function getLunarMonthDays( $year, $month ) 147 | { 148 | $monthData = $this->getLunarMonths( $year ); 149 | return $monthData[$month-1]; 150 | } 151 | /** 152 | * 获取阴历每月的天数的数组 153 | * @param year 154 | */ 155 | 156 | function getLunarMonths( $year ) 157 | { 158 | $yearData = $this->lunarInfo[$year - $this->MIN_YEAR]; 159 | $leapMonth = $yearData[0]; 160 | $bit = decbin( $yearData[3] ); 161 | for ( $i = 0; $i < strlen( $bit ); 162 | $i ++ ) $bitArray[$i] = substr( $bit, $i, 1 ); 163 | for ( $k = 0, $klen = 16-count( $bitArray ); 164 | $k<$klen; 165 | $k++ ) array_unshift( $bitArray, '0' ); 166 | $bitArray = array_slice( $bitArray, 0, ( $leapMonth == 0?12:13 ) ); 167 | for ( $i = 0; $ilunarInfo[$year-$this->MIN_YEAR]; 179 | $monthArray = $this->getLunarYearMonths( $year ); 180 | $len = count( $monthArray ); 181 | return ( $monthArray[$len-1] == 0?$monthArray[$len-2]:$monthArray[$len-1] ); 182 | } 183 | 184 | function getLunarYearMonths( $year ) 185 | { 186 | //debugger; 187 | $monthData = $this->getLunarMonths( $year ); 188 | $res = array(); 189 | $temp = 0; 190 | $yearData = $this->lunarInfo[$year-$this->MIN_YEAR]; 191 | $len = ( $yearData[0] == 0?12:13 ); 192 | for ( $i = 0; $i<$len; $i++ ) 193 | { 194 | $temp = 0; 195 | for ( $j = 0; $j <= $i; $j++ ) $temp += $monthData[$j]; 196 | array_push( $res, $temp ); 197 | } 198 | return $res; 199 | } 200 | /** 201 | * 获取闰月 202 | * @param year 阴历年份 203 | */ 204 | 205 | function getLeapMonth( $year ) 206 | { 207 | $yearData = $this->lunarInfo[$year-$this->MIN_YEAR]; 208 | return $yearData[0]; 209 | } 210 | /** 211 | * 计算阴历日期与正月初一相隔的天数 212 | * @param year 213 | * @param month 214 | * @param date 215 | */ 216 | 217 | function getDaysBetweenLunar( $year, $month, $date ) 218 | { 219 | $yearMonth = $this->getLunarMonths( $year ); 220 | $res = 0; 221 | for ( $i = 1; $i<$month; $i++ ) $res += $yearMonth[$i-1]; 222 | $res += $date-1; 223 | return $res; 224 | } 225 | /** 226 | * 计算2个阳历日期之间的天数 227 | * @param year 阳历年 228 | * @param cmonth 229 | * @param cdate 230 | * @param dmonth 阴历正月对应的阳历月份 231 | * @param ddate 阴历初一对应的阳历天数 232 | */ 233 | 234 | function getDaysBetweenSolar( $year, $cmonth, $cdate, $dmonth, $ddate ) 235 | { 236 | $a = mktime( 0, 0, 0, $cmonth, $cdate, $year ); 237 | $b = mktime( 0, 0, 0, $dmonth, $ddate, $year ); 238 | return ceil( ( $a-$b )/24/3600 ); 239 | } 240 | /** 241 | * 根据距离正月初一的天数计算阴历日期 242 | * @param year 阳历年 243 | * @param between 天数 244 | */ 245 | 246 | function getLunarByBetween( $year, $between ) 247 | { 248 | //debugger; 249 | $lunarArray = array(); 250 | $yearMonth = array(); 251 | $t = 0; 252 | $e = 0; 253 | $leapMonth = 0; 254 | $m = ''; 255 | if ( $between == 0 ) 256 | { 257 | array_push( $lunarArray, $year, '正月', '初一' ); 258 | $t = 1; 259 | $e = 1; 260 | } else { 261 | $year = $between>0? $year : ( $year-1 ); 262 | $yearMonth = $this->getLunarYearMonths( $year ); 263 | $leapMonth = $this->getLeapMonth( $year ); 264 | $between = $between>0?$between : ( $this->getLunarYearDays( $year )+$between ); 265 | for ( $i = 0; $i<13; $i++ ) 266 | { 267 | if ( $between == $yearMonth[$i] ) 268 | { 269 | $t = $i+2; 270 | $e = 1; 271 | break; 272 | } else if ( $between<$yearMonth[$i] ) 273 | { 274 | $t = $i+1; 275 | $e = $between-( empty( $yearMonth[$i-1] )?0:$yearMonth[$i-1] )+1; 276 | break; 277 | } 278 | } 279 | $m = ( $leapMonth != 0 && $t == $leapMonth+1 )?( '闰'.$this->getCapitalNum( $t- 1, true ) ):$this->getCapitalNum( ( $leapMonth != 0 && $leapMonth+1<$t?( $t-1 ):$t ), true ); 280 | array_push( $lunarArray, $year, $m, $this->getCapitalNum( $e, false ) ); 281 | } 282 | array_push( $lunarArray, $this->getLunarYearName( $year ) ); 283 | // 天干地支 284 | array_push( $lunarArray, $t, $e ); 285 | array_push( $lunarArray, $this->getYearZodiac( $year ) ); 286 | // 12生肖 287 | array_push( $lunarArray, $leapMonth ); 288 | // 闰几月 289 | return $lunarArray; 290 | } 291 | /** 292 | * 获取数字的阴历叫法 293 | * @param num 数字 294 | * @param isMonth 是否是月份的数字 295 | */ 296 | 297 | function getCapitalNum( $num, $isMonth ) 298 | { 299 | $isMonth = $isMonth || false; 300 | $dateHash = array( '0'=>'', '1'=>'一', '2'=>'二', '3'=>'三', '4'=>'四', '5'=>'五', '6'=>'六', '7'=>'七', '8'=>'八', '9'=>'九', '10'=>'十 ' ); 301 | $monthHash = array( '0'=>'', '1'=>'正月', '2'=>'二月', '3'=>'三月', '4'=>'四月', '5'=>'五月', '6'=>'六月', '7'=>'七月', '8'=>'八月', '9'=>'九月', '10'=>'十月', '11'=>'冬月', '12'=>'腊月' ); 302 | $res = ''; 303 | if ( $isMonth ) $res = $monthHash[$num]; 304 | else { 305 | if ( $num <= 10 ) $res = '初'.$dateHash[$num]; 306 | else if ( $num>10 && $num<20 ) $res = '十'.$dateHash[$num-10]; 307 | else if ( $num == 20 ) $res = '二十'; 308 | else if ( $num>20 && $num<30 ) $res = '廿'.$dateHash[$num-20]; 309 | else if ( $num == 30 ) $res = '三十'; 310 | } 311 | return $res; 312 | } 313 | /* 314 | * 节气通用算法 315 | */ 316 | 317 | function getJieQi( $_year, $month, $day ) 318 | { 319 | $year = substr( $_year, -2 )+0; 320 | $coefficient = array( 321 | array( 5.4055, 2019, -1 ), //小寒 322 | array( 20.12, 2082, 1 ), //大寒 323 | array( 3.87 ), //立春 324 | array( 18.74, 2026, -1 ), //雨水 325 | array( 5.63 ), //惊蛰 326 | array( 20.646, 2084, 1 ), //春分 327 | array( 4.81 ), //清明 328 | array( 20.1 ), //谷雨 329 | array( 5.52, 1911, 1 ), //立夏 330 | array( 21.04, 2008, 1 ), //小满 331 | array( 5.678, 1902, 1 ), //芒种 332 | array( 21.37, 1928, 1 ), //夏至 333 | array( 7.108, 2016, 1 ), //小暑 334 | array( 22.83, 1922, 1 ), //大暑 335 | array( 7.5, 2002, 1 ), //立秋 336 | array( 23.13 ), //处暑 337 | array( 7.646, 1927, 1 ), //白露 338 | array( 23.042, 1942, 1 ), //秋分 339 | array( 8.318 ), //寒露 340 | array( 23.438, 2089, 1 ), //霜降 341 | array( 7.438, 2089, 1 ), //立冬 342 | array( 22.36, 1978, 1 ), //小雪 343 | array( 7.18, 1954, 1 ), //大雪 344 | array( 21.94, 2021, -1 )//冬至 345 | ); 346 | $term_name = array( 347 | '小寒', '大寒', '立春', '雨水', '惊蛰', '春分', '清明', '谷雨', 348 | '立夏', '小满', '芒种', '夏至', '小暑', '大暑', '立秋', '处暑', 349 | '白露', '秋分', '寒露', '霜降', '立冬', '小雪', '大雪', '冬至' ); 350 | $idx1 = ( $month-1 )*2; 351 | $_leap_value = floor( ( $year-1 )/4 ); 352 | $day1 = floor( $year*0.2422+$coefficient[$idx1][0] )-$_leap_value; 353 | if ( isset( $coefficient[$idx1][1] ) && $coefficient[$idx1][1] == $_year ) $day1 += $coefficient[$idx1][2]; 354 | $day2 = floor( $year*0.2422+$coefficient[$idx1+1][0] )-$_leap_value; 355 | if ( isset( $coefficient[$idx1+1][1] ) && $coefficient[$idx1+1][1] == $_year ) $day1 += $coefficient[$idx1+1][2]; 356 | //echo __FILE__.'->'.__LINE__.' $day1='.$day1, ',$day2='.$day2.'
'.chr( 10 ); 357 | $data = array(); 358 | if ( $day<$day1 ) { 359 | $data['name'] = $term_name[$idx1-1]; 360 | $data['type'] = 'after'; 361 | } else if ( $day == $day1 ) { 362 | $data['name'] = $term_name[$idx1]; 363 | $data['type'] = 'today'; 364 | } else if ( $day>$day1 && $day<$day2 ) { 365 | $data['name'] = $term_name[$idx1]; 366 | $data['type'] = 'after'; 367 | } else if ( $day == $day2 ) { 368 | $data['name'] = $term_name[$idx1+1]; 369 | $data['type'] = 'today'; 370 | } else if ( $day>$day2 ) { 371 | $data['name'] = $term_name[$idx1+1]; 372 | $data['type'] = 'after'; 373 | } 374 | return $data; 375 | } 376 | /* 377 | * 获取节日:特殊的节日只能修改此函数来计算 378 | */ 379 | 380 | function getFestival( $today, $nl_info = false, $config = 1 ) 381 | { 382 | if ( $config == 1 ) 383 | { 384 | $arr_lunar = array( '01-01'=>'春节', '01-15'=>'元宵节', '02-02'=>'二月二', '05-05'=>'端午节', '07-07'=>'七夕节', '08-15'=>'中秋节', '09-09'=>'重阳节', '12-08'=>'腊八节', '12-23'=>'小年' ); 385 | $arr_solar = array( '01-01'=>'元旦', '02-14'=>'情人节', '03-12'=>'植树节', '04-01'=>'愚人节', '05-01'=>'劳动节', '06-01'=>'儿童节', '10-01'=>'国庆节', '10-31'=>'万圣节', '12-24'=>'平安夜', '12-25'=>'圣诞节' ); 386 | } 387 | //需要不同节日的,用不同的$config, 然后配置$arr_lunar和$arr_solar 388 | $festivals = array(); 389 | list( $y, $m, $d ) = explode( '-', $today ); 390 | if ( !$nl_info ) $nl_info = $this->convertSolarToLunar( $y, intval( $m ), intval( $d ) ); 391 | if ( $nl_info[7]>0 && $nl_info[7]<$nl_info[4] ) $nl_info[4] -= 1; 392 | $md_lunar = substr( '0'.$nl_info[4], -2 ).'-'.substr( '0'.$nl_info[5], -2 ); 393 | $md_solar = substr_replace( $today, '', 0, 5 ); 394 | isset( $arr_lunar[$md_lunar] )?array_push( $festivals, $arr_lunar[$md_lunar] ):''; 395 | isset( $arr_solar[$md_solar] )?array_push( $festivals, $arr_solar[$md_solar] ):''; 396 | $glweek = date( 'w', strtotime( $today ) ); 397 | //0-6 398 | if ( $m == 5 && ( $d>7 ) && ( $d<15 ) && ( $glweek == 0 ) )array_push( $festivals, '母亲节' ); 399 | if ( $m == 6 && ( $d>14 ) && ( $d<22 ) && ( $glweek == 0 ) )array_push( $festivals, '父亲节' ); 400 | //$jieqi = $this->getJieQi( $y, $m, $d ); 401 | //if ( $jieqi )array_push( $festivals, $jieqi ); 402 | return $festivals; 403 | } 404 | /* 405 | * 获取当前时间属于哪个时辰 406 | @param int $time 时间戳 407 | */ 408 | 409 | function getTheHour( $h ) { 410 | $d = $h; 411 | if ( $d == 23 || $d == 0 ) { 412 | return '子时'; 413 | } else if ( $d == 1 || $d == 2 ) { 414 | return '丑时'; 415 | } else if ( $d == 3 || $d == 4 ) { 416 | return '寅时'; 417 | } else if ( $d == 5 || $d == 6 ) { 418 | return '卯时'; 419 | } else if ( $d == 7 || $d == 8 ) { 420 | return '辰时'; 421 | } else if ( $d == 9 || $d == 10 ) { 422 | return '巳时'; 423 | } else if ( $d == 11 || $d == 12 ) { 424 | return '午时'; 425 | } else if ( $d == 13 || $d == 14 ) { 426 | return '未时'; 427 | } else if ( $d == 15 || $d == 16 ) { 428 | return '申时'; 429 | } else if ( $d == 17 || $d == 18 ) { 430 | return '酉时'; 431 | } else if ( $d == 19 || $d == 20 ) { 432 | return '戌时'; 433 | } else if ( $d == 21 || $d == 22 ) { 434 | return '亥时'; 435 | } 436 | } 437 | } -------------------------------------------------------------------------------- /app/model/test.php: -------------------------------------------------------------------------------- 1 | "/test/test", 11 | ); 12 | 13 | // display('index.html'); 14 | 15 | //插入 16 | //DB("test")->insert(["name" => "/21123/test"]); 17 | //批量插入 18 | //DB("test")->insert(["name" => "11"], ["name" => "22", "remark" => "2"], ["name" => "33", "remark" => "3"]); 19 | 20 | //DB("test")->inserts(["name", "remark"], ["aa", "bb"], ["cc", "dd"]); 21 | 22 | //删除 23 | //DB("test")->where(["id", "=", "75"])->delete(); 24 | 25 | //查询 26 | //DB("test")->select("id", "name") 27 | //DB("test")->where(["id", ">", "10"], ["id", ">", "10"])->select() 28 | //DB("test")->where(["id", ">", "10"])->select() 29 | //DB("test")->where("id", ">", "10")->select() 30 | //_e(DB("test")->or(["id", "=", "80"], ["id", "=", "81"])->select("name", "id")); 31 | 32 | //更新 33 | //DB("test")->where("id", "=", "77")->updata(["remark", "88"]); 34 | //DB("test")->where("id", "=", "77")->updata(["remark", "88"],['name','88']); 35 | 36 | //_e(DB("test")->where("id", ">", "80")->order('id DESC')->select()); 37 | 38 | //medoo 39 | //$db = Medoo(); 40 | //$db->select("test", "*"); 41 | 42 | } 43 | } -------------------------------------------------------------------------------- /app/route/route.php: -------------------------------------------------------------------------------- 1 | [ 6 | 'api'=>'bing@index', 7 | 'monitor'=>true 8 | ], 9 | '/bing/url'=>[ 10 | 'api'=>'bing@url', 11 | 'monitor'=>true 12 | ], 13 | '/bing/week' =>[ 14 | 'api'=>'bing@week', 15 | 'monitor'=>true 16 | ], 17 | '/bt'=>[ 18 | 'api'=>'bt@index', 19 | 'monitor'=>true 20 | ], 21 | '/api/task'=>[ 22 | 'api'=>'api@task', 23 | 'monitor'=>false 24 | ], 25 | '/api/total'=>[ 26 | 'api'=>'api@total', 27 | 'monitor'=>false 28 | ], 29 | '/user/reg'=>[ 30 | 'api'=>'user@reg', 31 | 'monitor'=>false 32 | ], 33 | '/user/login'=>[ 34 | 'api'=>'user@login', 35 | 'monitor'=>false 36 | ] 37 | 38 | ]; -------------------------------------------------------------------------------- /core/App.php: -------------------------------------------------------------------------------- 1 | hasMethod( $method ) ) { 33 | throw new SystemException( '控制函数:' . $method . ' 未定义', 404 ); 34 | return; 35 | } 36 | 37 | } catch ( SystemException $e ) { 38 | $e->output( $e ); 39 | 40 | } 41 | $class = new $controller(); 42 | 43 | call_user_func_array( array( $class, $method ), $params ); 44 | 45 | Monitor::run( $controllerName, $method, $route['controller']['monitor'] ); 46 | 47 | } 48 | 49 | private static function getController( $route ) { 50 | 51 | $array = explode( '@', $route['controller']['api'] ); 52 | 53 | return strtolower( array_shift( $array ) ); 54 | } 55 | 56 | private static function getMethod( $route ) { 57 | $array = explode( '@', $route['controller']['api'] ); 58 | 59 | return array_pop( $array ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /core/controller/Monitor.php: -------------------------------------------------------------------------------- 1 | get( $key ); 13 | if ( $record ) { 14 | $redis->incr( $key ); 15 | } else { 16 | $expireTime = mktime( 23, 59, 59, date( 'm' ), date( 'd' ), date( 'Y' ) ); 17 | $redis->setex( $key, $expireTime - timestamp( 10 ), 1 ); 18 | } 19 | 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /core/init.php: -------------------------------------------------------------------------------- 1 | get('token_' . $token)) { 63 | // if ($device == getDevice()['device']) { 64 | // return; 65 | // } 66 | // error('没有设备权限', 703); 67 | return; 68 | } 69 | error('token过期', 704); 70 | } 71 | } -------------------------------------------------------------------------------- /core/lib/AutoLoad.php: -------------------------------------------------------------------------------- 1 | 1) { 50 | return true; 51 | } else { 52 | return false; 53 | } 54 | } 55 | } 56 | 57 | spl_autoload_register('AutoLoad::_autoLoad'); -------------------------------------------------------------------------------- /core/lib/Check.php: -------------------------------------------------------------------------------- 1 | connect($config['server'], $config['port'])) { 22 | throw new \RedisException('Redis is not Running!'); 23 | } 24 | if (!$redis->ping()) { 25 | throw new \RedisException('Redis is not connecting successfully!'); 26 | } 27 | }catch (\RedisException $e) { 28 | die($e->getMessage()); 29 | } 30 | 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /core/lib/data/config.php: -------------------------------------------------------------------------------- 1 | sql = new SQL($table); 12 | parent::__construct(); 13 | } 14 | 15 | //返回插入的id 16 | public function insert() 17 | { 18 | 19 | //_e($this->sql->insert(func_get_args())); 20 | return $this->pdoExec($this->sql->insert(func_get_args())); 21 | 22 | } 23 | public function inserts() 24 | { 25 | 26 | $args = func_get_args(); 27 | $param = array_shift($args); 28 | // _e($this->sql->inserts($param)); 29 | return $this->pdoExec($this->sql->inserts($param), [$param, $args]); 30 | 31 | } 32 | public function select() 33 | { 34 | //echo $this->sql->select(func_get_args()); 35 | return $this->pdoSelect($this->sql->select(func_get_args())); 36 | 37 | } 38 | //返回影响的行数 39 | public function delete() 40 | { 41 | return $this->pdoExec($this->sql->delete()); 42 | 43 | } 44 | public function where() 45 | { 46 | $this->sql->where(func_get_args()); 47 | return $this; 48 | } 49 | function and () { 50 | $this->sql->where(func_get_args(), " AND "); 51 | return $this; 52 | } 53 | function or () { 54 | $this->sql->where(func_get_args(), " OR "); 55 | return $this; 56 | } 57 | public function updata() 58 | { 59 | //echo $this->sql->updata(func_get_args()); 60 | return $this->pdoExec($this->sql->updata(func_get_args())); 61 | } 62 | 63 | public function order() 64 | { 65 | 66 | $this->sql->order(func_get_args()); 67 | return $this; 68 | } 69 | public function limit() 70 | { 71 | $this->sql->limit(func_get_args()); 72 | return $this; 73 | } 74 | public function rand($limit = 1, $row = 'id') 75 | { 76 | $this->sql->rand($limit, $row); 77 | return $this; 78 | } 79 | public function sql($sql) 80 | { 81 | $this->sql->sql($sql); 82 | return $this; 83 | } 84 | } -------------------------------------------------------------------------------- /core/lib/db/MySQL.php: -------------------------------------------------------------------------------- 1 | db_config = config("database"); 17 | } 18 | public function pdoStart() 19 | { 20 | $dsn = $this->db_config["database_type"] . ":host=" . $this->db_config["server"] . ":" . $this->db_config["port"] . ";dbname=" . $this->db_config["database_name"]; 21 | try { 22 | $pdo = new \pdo($dsn, $this->db_config['username'], $this->db_config['password']); 23 | $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); 24 | } catch (\PDOException $e) { 25 | error("数据库连接失败: " . $e->getMessage(), $e->getCode()); 26 | } 27 | $pdo->query("set names " . $this->db_config["charset"]); 28 | return $pdo; 29 | } 30 | /** 31 | * 数据断开 32 | */ 33 | public function pdoStop() 34 | { 35 | $this->pdo = null; 36 | } 37 | /** 38 | * 单条数据查询 39 | */ 40 | public function pdoSelect($sql) 41 | { 42 | try { 43 | $pdo = $this->pdoStart(); 44 | $stmt = $pdo->prepare($sql); 45 | $stmt->execute(); 46 | $stmt->setFetchMode(\PDO::FETCH_ASSOC); 47 | return $stmt->fetchAll(); 48 | } catch (\PDOException $e) { 49 | error("查询失败: " . $e->getMessage(), $e->getCode()); 50 | } 51 | } 52 | 53 | public function pdoExec($sql, $row = []) 54 | { 55 | $lastInsertId = []; 56 | try { 57 | $pdo = $this->pdoStart(); 58 | if (is_string($sql)) { 59 | $stmt = $pdo->prepare($sql); 60 | $stmt->setFetchMode(\PDO::FETCH_ASSOC); 61 | if ($row != [] && $row != null) { 62 | foreach ($row[1] as $key) { 63 | foreach ($key as $k => $i) { 64 | $stmt->bindValue(":" . $row[0][$k], $i); 65 | } 66 | $stmt->execute(); 67 | $lastInsertId[] = $pdo->lastInsertId(); 68 | } 69 | return $lastInsertId; 70 | } else { 71 | $stmt->execute(); 72 | return $pdo->lastInsertId() ? $pdo->lastInsertId() : $stmt->rowcount(); 73 | } 74 | } 75 | if (is_array($sql)) { 76 | foreach ($sql as $item) { 77 | $stmt = $pdo->prepare($item); 78 | $stmt->setFetchMode(\PDO::FETCH_ASSOC); 79 | $stmt->execute(); 80 | $lastInsertId[] = $pdo->lastInsertId(); 81 | } 82 | return $lastInsertId; 83 | } 84 | return false; 85 | 86 | } catch (\PDOException $e) { 87 | error("操作失败: " . $e->getMessage(), $e->getCode()); 88 | } 89 | } 90 | /** 91 | * 多数据查询 92 | */ 93 | public function pdoSelects($table, $data2, $limit, $desc = 'id') 94 | { 95 | $pdo = $this->pdo; 96 | if ($pdo != null) { 97 | $data = array(); 98 | $sql = "select * from " . $table . " where " . $data2['key'] . " = '" . $data2['value'] . "' ORDER BY " . $desc . " DESC LIMIT " . $limit['min'] . "," . $limit['max']; 99 | foreach ($pdo->query($sql) as $row) { 100 | array_push($data, $row); 101 | } 102 | $this->result = $data; 103 | } 104 | return $this; 105 | } 106 | /** 107 | * 单表查询 108 | */ 109 | public function pdoSelectAll($table, $limit, $desc = 'id') 110 | { 111 | $pdo = $this->pdo; 112 | if ($pdo != null) { 113 | $data = array(); 114 | $sql = "select * from " . $table . " ORDER BY " . $desc . " DESC LIMIT " . $limit['min'] . "," . $limit['max']; 115 | foreach ($pdo->query($sql) as $row) { 116 | array_push($data, $row); 117 | } 118 | $this->result = $data; 119 | } 120 | return $this; 121 | } 122 | /** 123 | * 更新数据 124 | */ 125 | public function pdoUpdate($table, $data) 126 | { 127 | $pdo = $this->pdo; 128 | $sql = null; 129 | foreach ($data as $key => $value) { 130 | if ($key != 'id') { 131 | $sql = $sql . $key . " ='" . $value . "',"; 132 | } 133 | } 134 | $sql = rtrim($sql, ","); 135 | $sql = "UPDATE " . $table . " SET " . $sql . " WHERE `id`=" . $data['id']; 136 | $stmt = $pdo->prepare($sql); 137 | $num = $stmt->execute(); 138 | $count = $stmt->rowCount(); //受影响行数 139 | $this->result = $count; 140 | return $this; 141 | } 142 | /** 143 | * 单表数据统计 144 | */ 145 | public function pdoCount($table) 146 | { 147 | $pdo = $this->pdo; 148 | $sql = "select count(*) num from " . $table; 149 | foreach ($pdo->query($sql) as $row) { 150 | $this->result = $row; 151 | } 152 | return $this; 153 | } 154 | /** 155 | * 多表统计 156 | */ 157 | public function pdoCounts() 158 | { 159 | global $dbName; 160 | $pdo = $this->pdo; 161 | $sql = "select TABLE_NAME,TABLE_ROWS from information_schema.tables where table_schema='" . $dbName . "'"; 162 | $stmt = $pdo->prepare($sql); 163 | $stmt->execute(); 164 | $this->result = $stmt->fetchAll(); 165 | return $this; 166 | } 167 | } -------------------------------------------------------------------------------- /core/lib/db/SQL.php: -------------------------------------------------------------------------------- 1 | table = $table; 24 | } 25 | 26 | /** 27 | * 查询 28 | */ 29 | public function select($arr) 30 | { 31 | if ($this->sql != "") { 32 | return $this->sql; 33 | } 34 | $key = "*"; 35 | if ($arr != [] && is_array($arr)) { 36 | $key = implode($arr, ","); 37 | } 38 | if (is_string($arr)) { 39 | $key = $arr; 40 | } 41 | return $this->select . $key . $this->from . $this->table . $this->join . $this->where . $this->order . $this->limit; 42 | } 43 | /** 44 | * 插入 45 | */ 46 | public function insert($data) 47 | { 48 | if ($this->sql != "") { 49 | return $this->sql; 50 | } 51 | if ($data != []) { 52 | foreach ($data as $index) { 53 | $keyArr = []; 54 | $valueArr = []; 55 | foreach ($index as $key => $value) { 56 | $keyArr[] = $key; 57 | $valueArr[] = str_rl($value); 58 | } 59 | $sql[] = $this->insert . $this->table . " (" . implode($keyArr, ",") . ")" . $this->value . "(" . implode($valueArr, ",") . "); "; 60 | } 61 | return $sql; 62 | } else { 63 | error("无插入数据"); 64 | } 65 | 66 | } 67 | /** 68 | * 批量插入 69 | */ 70 | public function inserts($data) 71 | { 72 | 73 | if (is_array($data)) { 74 | foreach ($data as $key) { 75 | $keyArr[] = $key; 76 | $valueArr[] = ":" . $key; 77 | } 78 | return $this->insert . $this->table . " (" . implode($keyArr, ",") . ")" . $this->value . "(" . implode($valueArr, ",") . ") "; 79 | } else { 80 | error("无插入数据"); 81 | } 82 | 83 | } 84 | /** 85 | * 更新 86 | */ 87 | public function updata($arr) 88 | { 89 | if ($this->sql != "") { 90 | return $this->sql; 91 | } 92 | if ($arr == []) { 93 | error("updata参数为零"); 94 | } 95 | if (is_array($arr[0])) { 96 | foreach ($arr as $val) { 97 | $str[] = $val[0] . $this->space . "=" . $this->space . str_rl($val[1]); 98 | } 99 | return $this->updata . $this->table . $this->set . implode(" , ", $str) . $this->where; 100 | 101 | } else { 102 | if (count($arr) == 2) { 103 | return $this->updata . $this->table . $this->set . $arr[0] . $this->space . "=" . $this->space . str_rl($arr[1]) . $this->where; 104 | } else { 105 | error("updata参数格式不对"); 106 | } 107 | } 108 | 109 | } 110 | /** 111 | * 删除 112 | */ 113 | public function delete() 114 | { 115 | if ($this->sql != "") { 116 | return $this->sql; 117 | } 118 | return $this->delete . $this->table . $this->where; 119 | } 120 | /** 121 | * where语句 122 | */ 123 | public function where($arr, $type = " AND ") 124 | { 125 | if ($arr == []) { 126 | error("where参数为零"); 127 | } 128 | if (is_string($arr)) { 129 | $str = $arr; 130 | } 131 | if (is_array($arr[0])) { 132 | foreach ($arr as $val) { 133 | $str[] = $this->stringJoin($val); 134 | } 135 | $str = implode($type, $str); 136 | } 137 | if (is_array($arr) && count($arr) == 3) { 138 | $str = $this->stringJoin(func_get_arg(0)); 139 | } 140 | if (is_array($arr) && count($arr) != 3) { 141 | error("where参数格式不对"); 142 | } 143 | $this->where = ' WHERE ' . $str; 144 | } 145 | 146 | public function stringJoin($arr) 147 | { 148 | return $arr[0] . $this->space . $arr[1] . $this->space . str_rl($arr[2]) . $this->space; 149 | } 150 | 151 | /** 152 | * order 153 | */ 154 | public function order($arr) 155 | { 156 | if ($arr != []) { 157 | $this->order = " ORDER BY " . implode(",", $arr); 158 | } 159 | 160 | } 161 | /** 162 | * limit 163 | */ 164 | public function limit($arr) 165 | { 166 | if ($arr != []) { 167 | $this->limit = " LIMIT " . implode(",", $arr); 168 | } 169 | 170 | } 171 | /** 172 | * 随机函数 173 | */ 174 | public function rand($limit, $row) 175 | { 176 | 177 | $this->join(" AS t1 JOIN (SELECT ROUND(RAND() * ((" . $this->select("MAX(" . str_clean($row) . ")") . ")-(" . $this->select("MIN(" . str_clean($row) . ")") . "))+(" . $this->select("MIN(" . str_clean($row) . ")") . ")) AS sid) AS t2"); 178 | $this->where("t1." . str_clean($row) . ">=t2.s" . str_clean($row)); 179 | $this->limit([$limit]); 180 | $this->order(["t1." . str_clean($row)]); 181 | } 182 | 183 | public function join($sql) 184 | { 185 | $this->join = $this->space . $sql . $this->space; 186 | } 187 | 188 | public function sql($sql) 189 | { 190 | $this->sql = $sql; 191 | 192 | } 193 | } -------------------------------------------------------------------------------- /core/lib/header.php: -------------------------------------------------------------------------------- 1 | config = config( 'header' ); 11 | date_default_timezone_set( $obj->config['timezone'] ); 12 | self::_header( $obj->config['header'] ); 13 | self::_ini_set( $obj->config['ini'] ); 14 | 15 | } 16 | private static function _header( $config ) { 17 | 18 | foreach ( $config as $key => $val ) { 19 | header( $key . ':' . $val ); 20 | } 21 | 22 | } 23 | private static function _ini_set( $config ) { 24 | 25 | foreach ( $config as $key => $val ) { 26 | ini_set( $key, $val ); 27 | } 28 | 29 | } 30 | public static function getheaders() { 31 | foreach ( $_SERVER as $name => $value ) { 32 | if ( substr( $name, 0, 5 ) == 'HTTP_' ) { 33 | $headers[str_replace( ' ', '-', ucwords( strtolower( str_replace( '_', ' ', substr( $name, 5 ) ) ) ) )] = $value; 34 | } 35 | } 36 | return $headers; 37 | } 38 | } -------------------------------------------------------------------------------- /core/lib/lib.php: -------------------------------------------------------------------------------- 1 | connect($config['server'], $config['port']); 66 | if ($redis->ping()) { 67 | $redis->select($config['index']); 68 | return $redis; 69 | } else { 70 | error('Redis连接失败!'); 71 | } 72 | } 73 | 74 | function get($url, $headers = []) 75 | { 76 | return \core\utils\Http::get($url, $headers); 77 | } 78 | 79 | function post($url, $param, $headers = []) 80 | { 81 | return \core\utils\Http::post($url, $param, $headers); 82 | } 83 | //域名权限 84 | 85 | function Auth($type = 'secret') 86 | { 87 | switch ($type) { 88 | case 'secret': 89 | return \core\lib\Auth\Authentication::AuthSecret(); 90 | break; 91 | case 'domain': 92 | return \core\lib\Auth\Authentication::AuthDomain(); 93 | break; 94 | case 'ip': 95 | return \core\lib\Auth\Authentication::AuthIP(); 96 | break; 97 | default: 98 | return; 99 | break; 100 | } 101 | } -------------------------------------------------------------------------------- /core/lib/route/route.php: -------------------------------------------------------------------------------- 1 | routes = \core\lib\data\route::route(); 17 | } 18 | public static function run($urlParam) 19 | { 20 | $route = ""; 21 | $param = []; 22 | $count = count($urlParam); 23 | for ($i = 0; $i < $count; $i++) { 24 | $route = "/" . implode("/", $urlParam); 25 | if ($class = self::isRoute($route)) { 26 | return [$class, $param, $route]; 27 | } 28 | array_unshift($param, array_pop($urlParam)); 29 | } 30 | return false; 31 | } 32 | public static function isRoute($route) 33 | { 34 | $obj = new self(); 35 | if (array_key_exists($route, $obj->routes)) { 36 | return $obj->routes[$route]; 37 | } 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /core/map/map.php: -------------------------------------------------------------------------------- 1 | __ROOT__ . '/core/App.php', 5 | 'Model' => __ROOT__ . '/core/lib/Model.php', 6 | 'header' => __ROOT__ . '/core/lib/header.php', 7 | 'Medoo' => __ROOT__ . '/core/lib/db/Medoo.php', 8 | 'simple_html_dom'=>__ROOT__ .'/core/plugins/simple_html_dom.php', 9 | 'LoadImage'=>__ROOT__ .'/core/utils/LoadImage.php', 10 | 'Http'=>__ROOT__ .'/core/utils/Http.php', 11 | ); -------------------------------------------------------------------------------- /core/route/route.php: -------------------------------------------------------------------------------- 1 | routes = \core\lib\data\route::route(); 14 | } 15 | public static function run() { 16 | $urlParam = urlParams(); 17 | $route = self::runRoutes( $urlParam ); 18 | if ( $route ) { 19 | return $route; 20 | } 21 | return self::createRouters( $urlParam ); 22 | } 23 | private static function runRoutes( $urlParam ) { 24 | $route = ''; 25 | $param = []; 26 | $count = count( $urlParam ); 27 | for ( $i = 0; $i < $count; $i++ ) { 28 | //循环,[bing, url]=>/bing/url 29 | $route = '/' . implode( '/', $urlParam ); 30 | 31 | if ( $controller = self::isRoute( $route ) ) { 32 | 33 | return ['controller'=>$controller, 'params'=>$param, 'route'=>$route, 'type'=>'api']; 34 | } 35 | //提取最后一个元素作为参数 36 | array_unshift( $param, array_pop( $urlParam ) ); 37 | } 38 | return false; 39 | } 40 | 41 | private static function createRouters( $urlParam ) { 42 | $count = count( $urlParam ); 43 | if ( $count == 0 ) { 44 | display(); 45 | } 46 | //默认 47 | if ( $count == 1 ) { 48 | $route = '/'.$urlParam[0]; 49 | $controller = [ 50 | 'api'=>array_shift( $urlParam ).'@index', 51 | 'monitor'=>true 52 | ]; 53 | return ['controller'=>$controller, 'params'=>$urlParam, 'route'=>$route, 'type'=>'api']; 54 | } 55 | if ( $count >= 2 ) { 56 | $route = '/'.$urlParam[0].'/'.$urlParam[1]; 57 | $controller = [ 58 | 'api'=>array_shift( $urlParam ).'@'.array_shift( $urlParam ), 59 | 'monitor'=>true 60 | ]; 61 | return ['controller'=>$controller, 'params'=>$urlParam, 'route'=>$route, 'type'=>'api']; 62 | } 63 | return false; 64 | } 65 | private static function isRoute( $route ) { 66 | $obj = new self(); 67 | if ( array_key_exists( $route, $obj->routes ) ) { 68 | return $obj->routes[$route]; 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /core/utils/Http.php: -------------------------------------------------------------------------------- 1 | $code, 'data' => $data)); 15 | return; 16 | } 17 | if ($code == 200 && is_array($data)) { 18 | 19 | echo json_encode(array('code' => $code, 'data' => $data)); 20 | return; 21 | } 22 | if ($code == 200 && is_object($data)) { 23 | echo json_encode(array('code' => $code, 'data' => $data)); 24 | return; 25 | } 26 | echo json_encode(array('code' => $code, 'data' => $data)); 27 | } 28 | /** 29 | * 输出 30 | */ 31 | 32 | function _e($data) 33 | { 34 | 35 | if (is_string($data) || is_numeric($data) || is_float($data) || is_int($data)) { 36 | echo $data; 37 | return; 38 | } 39 | if (is_array($data)) { 40 | echo json_encode($data); 41 | return; 42 | } 43 | if (is_object($data)) { 44 | var_dump($data); 45 | return; 46 | } 47 | echo $data; 48 | } 49 | /** 50 | * 报错输出 51 | */ 52 | 53 | function error($error = '未知错误', $code = 404) 54 | { 55 | die(json_encode(array('code' => $code, 'error' => $error))); 56 | } 57 | 58 | /** 59 | * 时间戳 60 | */ 61 | 62 | function timestamp($num = 13) 63 | { 64 | if ($num == 10) { 65 | return time(); 66 | } 67 | list($s1, $s2) = explode(' ', microtime()); 68 | return (float) sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000); 69 | } 70 | /** 71 | * 加引号 72 | */ 73 | 74 | function str_rl($str, $n = 1, $char = "'") 75 | { 76 | return str_suffix(str_prefix($str, $n, $char), $n, $char); 77 | } 78 | 79 | function str_prefix($str, $n = 1, $char = ' ') 80 | { 81 | for ($x = 0; $x < $n; $x++) { 82 | $str = $char . $str; 83 | } 84 | return $str; 85 | } 86 | 87 | function str_suffix($str, $n = 1, $char = ' ') 88 | { 89 | for ($x = 0; $x < $n; $x++) { 90 | $str = $str . $char; 91 | } 92 | return $str; 93 | } 94 | 95 | function getParam($key) 96 | { 97 | if (@$_COOKIE[$key]) { 98 | return $_COOKIE[$key]; 99 | } 100 | if (@$_GET[$key]) { 101 | return $_GET[$key]; 102 | } 103 | if (@$_POST[$key]) { 104 | return $_POST[$key]; 105 | } 106 | if (@$_FILES[$key]) { 107 | return $_FILES[$key]; 108 | } 109 | return null; 110 | } 111 | function getToken() 112 | { 113 | if (isset(header::getheaders()['Token'])) { 114 | return header::getheaders()['Token']; 115 | } elseif (isset($_COOKIE['token'])) { 116 | 117 | return $_COOKIE['token']; 118 | } elseif (!empty(getParam('token'))) { 119 | return getParam('token'); 120 | } else { 121 | return null; 122 | } 123 | } 124 | //获取服务器域名加协议 125 | 126 | function site_url() 127 | { 128 | $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? 'https://' : 'http://'; 129 | $domainName = $_SERVER['HTTP_HOST']; 130 | return $protocol . $domainName; 131 | } 132 | //获取网址参数数组 133 | 134 | function urlParams() 135 | { 136 | $urlParam = rtrim(preg_replace('/\?.*/', '', $_SERVER['REQUEST_URI']), '/'); 137 | return explode('/', trim($urlParam, '/')); 138 | } 139 | //去掉特殊符号 140 | 141 | function str_clean($str) 142 | { 143 | return preg_replace('/[-\', \.\$\^\*-+!\?\/@"\|\\()]/i', "", $str); 144 | } 145 | 146 | //获取来源域名 147 | function getOriginDomain() 148 | { 149 | if (isset($_SERVER["HTTP_REFERER"])) { 150 | return parse_url($_SERVER["HTTP_REFERER"])['host']; 151 | } else { 152 | return ""; 153 | } 154 | } 155 | function getDomain() 156 | { 157 | return $_SERVER['HTTP_HOST']; 158 | } 159 | 160 | //单条抓取 161 | function curl_fetch($url, $cookie = '', $referer = '', $timeout = 10, $ishead = 0) 162 | { 163 | $curl = curl_init(); 164 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 165 | curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); 166 | curl_setopt($curl, CURLOPT_ACCEPT_ENCODING, 'gzip,deflate'); 167 | curl_setopt($curl, CURLOPT_URL, $url); 168 | curl_setopt($curl, CURLOPT_TIMEOUT, $timeout); 169 | curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'); 170 | if ($cookie) { 171 | curl_setopt($curl, CURLOPT_COOKIE, $cookie); 172 | } 173 | if ($referer) { 174 | curl_setopt($curl, CURLOPT_REFERER, $referer); 175 | } 176 | $ssl = substr($url, 0, 8) == 'https://' ? true : false; 177 | if ($ssl) { 178 | curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); 179 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 180 | } 181 | $res = curl_exec($curl); 182 | $encode = mb_detect_encoding($res, array('ASCII', 'UTF-8', 'GB2312', 'GBK', 'BIG5')); 183 | $str_encode = mb_convert_encoding($res, 'UTF-8', $encode); 184 | curl_close($curl); 185 | return $str_encode; 186 | } 187 | function curl_multi_fetch($urlarr = array(), $timeout = 10) 188 | { 189 | $result = $res = $ch = array(); 190 | $nch = 0; 191 | $mh = curl_multi_init(); 192 | foreach ($urlarr as $url) { 193 | $ch[$nch] = curl_init(); 194 | $ssl = substr($url, 0, 8) == 'https://' ? true : false; 195 | if ($ssl) { 196 | curl_setopt_array($ch[$nch], array( 197 | CURLOPT_URL => $url, 198 | CURLOPT_HEADER => false, 199 | CURLOPT_RETURNTRANSFER => true, 200 | CURLOPT_FOLLOWLOCATION => true, 201 | CURLOPT_TIMEOUT => $timeout, 202 | CURLOPT_ACCEPT_ENCODING => 'gzip,deflate', 203 | CURLOPT_SSL_VERIFYHOST => false, 204 | CURLOPT_SSL_VERIFYPEER => false, 205 | CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36', 206 | )); 207 | } else { 208 | curl_setopt_array($ch[$nch], array( 209 | CURLOPT_URL => $url, 210 | CURLOPT_HEADER => false, 211 | CURLOPT_RETURNTRANSFER => true, 212 | CURLOPT_FOLLOWLOCATION => true, 213 | CURLOPT_TIMEOUT => $timeout, 214 | CURLOPT_ACCEPT_ENCODING => 'gzip,deflate', 215 | CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36', 216 | )); 217 | } 218 | curl_multi_add_handle($mh, $ch[$nch]); 219 | ++$nch; 220 | } 221 | do { 222 | $mrc = curl_multi_exec($mh, $running); 223 | } while (CURLM_CALL_MULTI_PERFORM == $mrc); 224 | 225 | while ($running && $mrc == CURLM_OK) { 226 | if (curl_multi_select($mh, 0.5) > -1) { 227 | do { 228 | $mrc = curl_multi_exec($mh, $running); 229 | } while (CURLM_CALL_MULTI_PERFORM == $mrc); 230 | } 231 | } 232 | if ($mrc != CURLM_OK) { 233 | error_log("CURL Data Error"); 234 | } 235 | $nch = 0; 236 | foreach ($urlarr as $node) { 237 | if (($err = curl_error($ch[$nch])) == '') { 238 | $res[$nch] = curl_multi_getcontent($ch[$nch]); 239 | $encode = mb_detect_encoding($res[$nch], array('ASCII', 'UTF-8', 'GB2312', 'GBK', 'BIG5')); 240 | $str_encode = mb_convert_encoding($res[$nch], 'UTF-8', $encode); 241 | $result[] = $str_encode; 242 | } else { 243 | error_log("curl error"); 244 | } 245 | curl_multi_remove_handle($mh, $ch[$nch]); 246 | curl_close($ch[$nch]); 247 | ++$nch; 248 | } 249 | curl_multi_close($mh); 250 | return $result; 251 | } 252 | 253 | //星期几 254 | function weekday($format = "星期w") 255 | { 256 | 257 | $weekdays = ['日', '一', '二', '三', '四', '五', '六']; 258 | 259 | return str_replace('w', $weekdays[date('w')], $format); 260 | } 261 | 262 | //获取设备 263 | function getDevice() 264 | { 265 | $user_agent = $_SERVER['HTTP_USER_AGENT']; 266 | $reg = "/(?<=\()[^\)]+/"; 267 | preg_match($reg, $user_agent, $result); 268 | $device['agent'] = $user_agent; 269 | $device['device'] = $result[0]; 270 | $device['os'] = explode(";", $result[0]); 271 | foreach ($device['os'] as $key => $item) { 272 | $device['os'][$key] = trim($item); 273 | } 274 | return $device; 275 | } 276 | 277 | //获取ip 278 | function getIP() 279 | { 280 | 281 | static $ip = ''; 282 | 283 | $ip = $_SERVER['REMOTE_ADDR']; 284 | 285 | if (isset($_SERVER['HTTP_CDN_SRC_IP'])) { 286 | 287 | $ip = $_SERVER['HTTP_CDN_SRC_IP']; 288 | } elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) { 289 | 290 | $ip = $_SERVER['HTTP_CLIENT_IP']; 291 | } elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) and preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) { 292 | 293 | foreach ($matches[0] as $xip) { 294 | 295 | if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) { 296 | 297 | $ip = $xip; 298 | 299 | break; 300 | } 301 | } 302 | } 303 | 304 | return $ip; 305 | } -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xygengcn/OpenApi-php/9c645b49a3e4e28f34e631d212cb3a3dce7217a5/favicon.ico -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 33 | 34 | ``` 35 | ```markdown 36 | 37 | ![bing](https://api.xygeng.cn/Bing/) 38 | ``` 39 | 40 | #### 4、一周七图 41 | 42 | 接口:GET请求 [API测试平台](https://api.xygeng.cn/test.html) 43 | 44 | ``` 45 | https://api.xygeng.cn/Bing/week/ 46 | ``` 47 | 48 | 结果: 49 | 50 | ```json 51 | { 52 | "code": 200, 53 | "data": [ 54 | "http://cn.bing.c224_1920x1080.jpg&rf=LaDigue_1920x1080.jpg", 55 | "http://cn.bing.c224_1920x1080.jpg&rf=LaDigue_1920x1080.jpg", 56 | "http://cn.bing.c224_1920x1080.jpg&rf=LaDigue_1920x1080.jpg", 57 | "http://cn.bing.c224_1920x1080.jpg&rf=LaDigue_1920x1080.jpg", 58 | "http://cn.bing.c224_1920x1080.jpg&rf=LaDigue_1920x1080.jpg", 59 | "http://cn.bing.c224_1920x1080.jpg&rf=LaDigue_1920x1080.jpg", 60 | "http://cn.bing.c224_1920x1080.jpg&rf=LaDigue_1920x1080.jpg" 61 | ] 62 | } 63 | ``` -------------------------------------------------------------------------------- /public/Bing/_coverpage.md: -------------------------------------------------------------------------------- 1 | # 必应每日一图 2 | 3 | > 必应每日一图,每周七图 4 | 5 | [GitHub](https://github.com/xygengcn/OpenApi) 6 | [Get Started](#main) -------------------------------------------------------------------------------- /public/Bing/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | OpenApi - XY笔记 - 开源API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 |
加载中,不着急
22 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /public/Novel/README.md: -------------------------------------------------------------------------------- 1 | ## 每日一图 2 | 为了方便随机切换图片,我们可以使用必应每日一图来参考写出接口,方便我们切换图片和收集图片。全新代码构建,全新界面。 3 | 4 | [页面展示](https://api.xygeng.cn/Novel/index.html) 5 | 6 | -------------------------------------------------------------------------------- /public/Novel/_coverpage.md: -------------------------------------------------------------------------------- 1 | # XY小说接口 2 | 3 | > 免费小说接口,网络书源接口 4 | 5 | [GitHub](https://github.com/xygengcn/OpenApi) 6 | [Get Started](#main) -------------------------------------------------------------------------------- /public/Novel/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | OpenApi - XY笔记 - 开源API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 |
加载中,不着急
22 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /public/One/README.md: -------------------------------------------------------------------------------- 1 | 2 | ### ONE一句 3 | 4 | 每个人都会有有一句心里话感动着自己,在动画,在影视,在小说,在名著中,总有一句话温暖着自己,我将会收集那些心动的话语汇成一言库,在这里将会形成接口和分享网站给大家使用,同时我们将会面向网络收集能穿透人心的话语,水滴成海汇聚成汪洋大浪。一句话可以是人物随意的一句话语,可以是笔下一绝句,可以网络感动许许多多人的话语,在这里我都将会欢迎大家投稿。 5 | 6 | #### 普通请求 7 | 8 | 请求类型:GET 9 | 10 | [API测试平台](https://api.xygeng.cn/test.html) 11 | 12 | 接口地址: 13 | 14 | ``` 15 | https://api.xygeng.cn/one 16 | ``` 17 | 18 | 接口结果: 19 | 20 | ```json 21 | { 22 | "code": 200, 23 | "data": { 24 | "id": "807", 25 | "tag": "漫画",//主题 26 | "origin": "《萤火之森》",//来自 27 | "content": "其实美丽的故事都是没有结局的,只因为它没有结局所以才会美丽。",//内容 28 | "datetime": "1548230343" 29 | } 30 | } 31 | ``` 32 | 33 | 34 | 35 | #### 直接调用 36 | 37 | 直接在网页上插入下面代码即可 38 | 39 | ```html 40 | 41 | ``` 42 | 43 | -------------------------------------------------------------------------------- /public/One/_coverpage.md: -------------------------------------------------------------------------------- 1 | # ONE一句 2 | 3 | > 一言一句记录生活 4 | 5 | [GitHub](https://github.com/xygengcn/OpenApi) 6 | [Get Started](#main) -------------------------------------------------------------------------------- /public/One/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | OpenApi - XY笔记 - 开源API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 21 |
加载中,不着急
22 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /public/admin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | hah 10 | 11 | -------------------------------------------------------------------------------- /public/api/README.md: -------------------------------------------------------------------------------- 1 | ## OpenApi接口集合 2 | 3 | 集合框架内的接口说明 4 | 5 | ## One一言接口 6 | 7 | 详细请看:[one一言接口](https://api.xygeng.cn/one/index.html) 8 | 9 | ## Bing每日一图接口 10 | 11 | 详细请看:[每日一图](https://api.xygeng.cn/bing/index.html) 12 | 13 | ## 万年历接口 14 | 15 | 详细请看:[万年历接口](https://api.xygeng.cn/day/index.html) 16 | 17 | ## 新闻快讯接口 18 | 19 | ## 微博热搜接口 20 | 21 | ## 足球比赛接口 22 | 23 | ## 用户注册接口 24 | 25 | ## 用户登录接口 -------------------------------------------------------------------------------- /public/api/_coverpage.md: -------------------------------------------------------------------------------- 1 | # OpenApi开源接口集合 2 | 3 | > 开源Api,关心生活琐事 4 | 5 | [GitHub](https://github.com/xygengcn/OpenApi) 6 | [Get Started](#main) -------------------------------------------------------------------------------- /public/api/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | OpenApi - XY笔记 - 开源API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 |
加载中,不着急
23 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /public/day/README.md: -------------------------------------------------------------------------------- 1 | ## 万年历接口 2 | 万年历接口,提供当日的阳历、阴历日期和当天节日 3 | 4 | [页面展示](https://api.xygeng.cn/day/index.html) 5 | 6 | ### 接口详细 7 | 8 | 接口:GET请求 [API测试平台](https://api.xygeng.cn/test.html) 9 | 10 | ``` 11 | https://api.xygeng.cn/day 12 | ``` 13 | 14 | 结果: 15 | 16 | ```json 17 | { 18 | "code": 200, 19 | "data": { 20 | "solar": { 21 | "year": "2020", 22 | "month": "07", 23 | "date": "07", 24 | "day": "星期二" 25 | }, 26 | "lunar": { 27 | "year": "庚子", 28 | "animal": "鼠", 29 | "month": "五月", 30 | "date": "十七" 31 | }, 32 | "festival": [] 33 | } 34 | } 35 | ``` 36 | 37 | -------------------------------------------------------------------------------- /public/day/_coverpage.md: -------------------------------------------------------------------------------- 1 | # 万年历接口 2 | 3 | > 万年历接口,生活每一天 4 | 5 | [GitHub](https://github.com/xygengcn/OpenApi) 6 | [Get Started](#main) -------------------------------------------------------------------------------- /public/day/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | OpenApi - XY笔记 - 开源API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 |
加载中,不着急
23 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /public/error/403.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 403 12 | 13 | 14 | -------------------------------------------------------------------------------- /public/error/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 404 8 | 9 | 10 | 11 |

页面不存在404

12 | 13 | 14 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xygengcn/OpenApi-php/9c645b49a3e4e28f34e631d212cb3a3dce7217a5/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | OpenApi - XY笔记 - 开源API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 24 |
加载中,不着急
25 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /public/static/test.css: -------------------------------------------------------------------------------- 1 | pre { 2 | background-color: #333333; 3 | } 4 | 5 | code[class*="language-"], 6 | pre[class*="language-"] { 7 | color: #ccc; 8 | background: none; 9 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 10 | font-size: 1em; 11 | text-align: left; 12 | white-space: pre; 13 | word-spacing: normal; 14 | word-break: normal; 15 | word-wrap: normal; 16 | line-height: 1.5; 17 | -moz-tab-size: 4; 18 | -o-tab-size: 4; 19 | tab-size: 4; 20 | -webkit-hyphens: none; 21 | -moz-hyphens: none; 22 | -ms-hyphens: none; 23 | hyphens: none; 24 | } 25 | 26 | section.cover.show { 27 | background: linear-gradient(to left bottom, hsl(209, 100%, 85%) 0%, hsl(154, 100%, 85%) 100%); 28 | } 29 | 30 | pre.result { 31 | height: 500px; 32 | padding: 10px 30px; 33 | overflow: auto; 34 | } 35 | 36 | #main { 37 | width: 1024px; 38 | margin: 0px auto; 39 | padding-top: 50px; 40 | } 41 | 42 | #main h1 { 43 | text-align: center; 44 | margin-bottom: 50px; 45 | } 46 | 47 | .div_input { 48 | display: flex; 49 | border: 1px solid #333; 50 | } 51 | 52 | .div_input label { 53 | background: #333; 54 | color: #fff; 55 | box-sizing: border-box; 56 | line-height: 40px; 57 | padding: 0px 20px; 58 | 59 | } 60 | 61 | .div_input input { 62 | font-size: 1.2em; 63 | height: 40px; 64 | border: none; 65 | box-sizing: border-box; 66 | outline: none; 67 | flex: 1; 68 | padding: 0px 20px; 69 | } 70 | 71 | #main .btnTest { 72 | height: 40px; 73 | background: #333; 74 | color: #fff; 75 | text-align: center; 76 | line-height: 40px; 77 | margin: 15px 0px; 78 | cursor: pointer; 79 | } -------------------------------------------------------------------------------- /public/static/test.js: -------------------------------------------------------------------------------- 1 | // 格式化json 2 | var formatJson = function (json, options) { 3 | var reg = null, 4 | formatted = '', 5 | pad = 0, 6 | PADDING = ' '; 7 | options = options || {}; 8 | options.newlineAfterColonIfBeforeBraceOrBracket = (options.newlineAfterColonIfBeforeBraceOrBracket === 9 | true) ? true : false; 10 | options.spaceAfterColon = (options.spaceAfterColon === false) ? false : true; 11 | 12 | if (typeof json !== 'string') { 13 | json = JSON.stringify(json); 14 | } 15 | json = JSON.parse(json); 16 | json = JSON.stringify(json); 17 | reg = /([\{\}])/g; 18 | json = json.replace(reg, '\r\n$1\r\n'); 19 | reg = /([\[\]])/g; 20 | json = json.replace(reg, '\r\n$1\r\n'); 21 | reg = /(\,)/g; 22 | json = json.replace(reg, '$1\r\n'); 23 | reg = /(\r\n\r\n)/g; 24 | json = json.replace(reg, '\r\n'); 25 | reg = /\r\n\,/g; 26 | json = json.replace(reg, ','); 27 | if (!options.newlineAfterColonIfBeforeBraceOrBracket) { 28 | reg = /\:\r\n\{/g; 29 | json = json.replace(reg, ':{'); 30 | reg = /\:\r\n\[/g; 31 | json = json.replace(reg, ':['); 32 | } 33 | if (options.spaceAfterColon) { 34 | reg = /\:/g; 35 | json = json.replace(reg, ': '); 36 | } 37 | json.split('\r\n').forEach(function (node, index) { 38 | var i = 0, 39 | indent = 0, 40 | padding = ''; 41 | 42 | if (node.match(/\{$/) || node.match(/\[$/)) { 43 | indent = 1; 44 | } else if (node.match(/\}/) || node.match(/\]/)) { 45 | if (pad !== 0) { 46 | pad -= 1; 47 | } 48 | } else { 49 | indent = 0; 50 | } 51 | 52 | for (i = 0; i < pad; i++) { 53 | padding += PADDING; 54 | } 55 | formatted += padding + node + '\r\n'; 56 | pad += indent; 57 | }); 58 | return formatted; 59 | }; 60 | /** 61 | * 复制内容到粘贴板 62 | * content : 需要复制的内容 63 | * message : 复制完后的提示,不传则默认提示"复制成功" 64 | */ 65 | function copyToClip(content) { 66 | var aux = document.createElement("input"); 67 | aux.setAttribute("value", content); 68 | document.body.appendChild(aux); 69 | aux.select(); 70 | document.execCommand("copy"); 71 | document.body.removeChild(aux); 72 | } 73 | 74 | //跳转动画 75 | function scollAnimate(el, time = 10) { 76 | let to = document.querySelector(el).offsetTop; 77 | let curr_top = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop; 78 | let time_id = setInterval(() => { 79 | curr_top += 10; 80 | document.body.scollTop = curr_top; 81 | document.documentElement.scrollTop = curr_top; 82 | if (curr_top >= to) { 83 | clearInterval(time_id); 84 | } 85 | }, time); 86 | } 87 | 88 | //get 89 | function get(url) { 90 | return new Promise(function (resolve, reject) { 91 | var xml = new XMLHttpRequest(); 92 | xml.open("GET", url, true); 93 | xml.send(); 94 | xml.onreadystatechange = function () { 95 | if (xml.readyState == 4 && xml.status == 200) { 96 | resolve(xml.responseText) 97 | } 98 | } 99 | }) 100 | } 101 | 102 | function test() { 103 | var url = document.querySelector("#url").value; 104 | var result = document.querySelector("#result"); 105 | get(url).then(function (res) { 106 | let json = formatJson(res); 107 | result.innerHTML = json; 108 | }) 109 | 110 | } -------------------------------------------------------------------------------- /public/static/vue.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600"); 2 | * { 3 | -webkit-font-smoothing: antialiased; 4 | -webkit-overflow-scrolling: touch; 5 | -webkit-tap-highlight-color: rgba(0,0,0,0); 6 | -webkit-text-size-adjust: none; 7 | -webkit-touch-callout: none; 8 | box-sizing: border-box; 9 | } 10 | body:not(.ready) { 11 | overflow: hidden; 12 | } 13 | body:not(.ready) [data-cloak], 14 | body:not(.ready) .app-nav, 15 | body:not(.ready) > nav { 16 | display: none; 17 | } 18 | div#app { 19 | font-size: 30px; 20 | font-weight: lighter; 21 | margin: 40vh auto; 22 | text-align: center; 23 | } 24 | div#app:empty::before { 25 | content: 'Loading...'; 26 | } 27 | .emoji { 28 | height: 1.2rem; 29 | vertical-align: middle; 30 | } 31 | .progress { 32 | background-color: var(--theme-color, #42b983); 33 | height: 2px; 34 | left: 0px; 35 | position: fixed; 36 | right: 0px; 37 | top: 0px; 38 | transition: width 0.2s, opacity 0.4s; 39 | width: 0%; 40 | z-index: 999999; 41 | } 42 | .search a:hover { 43 | color: var(--theme-color, #42b983); 44 | } 45 | .search .search-keyword { 46 | color: var(--theme-color, #42b983); 47 | font-style: normal; 48 | font-weight: bold; 49 | } 50 | html, 51 | body { 52 | height: 100%; 53 | } 54 | body { 55 | -moz-osx-font-smoothing: grayscale; 56 | -webkit-font-smoothing: antialiased; 57 | color: #34495e; 58 | font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif; 59 | font-size: 15px; 60 | letter-spacing: 0; 61 | margin: 0; 62 | overflow-x: hidden; 63 | } 64 | img { 65 | max-width: 100%; 66 | } 67 | a[disabled] { 68 | cursor: not-allowed; 69 | opacity: 0.6; 70 | } 71 | kbd { 72 | border: solid 1px #ccc; 73 | border-radius: 3px; 74 | display: inline-block; 75 | font-size: 12px !important; 76 | line-height: 12px; 77 | margin-bottom: 3px; 78 | padding: 3px 5px; 79 | vertical-align: middle; 80 | } 81 | li input[type='checkbox'] { 82 | margin: 0 0.2em 0.25em 0; 83 | vertical-align: middle; 84 | } 85 | .app-nav { 86 | margin: 25px 60px 0 0; 87 | position: absolute; 88 | right: 0; 89 | text-align: right; 90 | z-index: 10; 91 | /* navbar dropdown */ 92 | } 93 | .app-nav.no-badge { 94 | margin-right: 25px; 95 | } 96 | .app-nav p { 97 | margin: 0; 98 | } 99 | .app-nav > a { 100 | margin: 0 1rem; 101 | padding: 5px 0; 102 | } 103 | .app-nav ul, 104 | .app-nav li { 105 | display: inline-block; 106 | list-style: none; 107 | margin: 0; 108 | } 109 | .app-nav a { 110 | color: inherit; 111 | font-size: 16px; 112 | text-decoration: none; 113 | transition: color 0.3s; 114 | } 115 | .app-nav a:hover { 116 | color: var(--theme-color, #42b983); 117 | } 118 | .app-nav a.active { 119 | border-bottom: 2px solid var(--theme-color, #42b983); 120 | color: var(--theme-color, #42b983); 121 | } 122 | .app-nav li { 123 | display: inline-block; 124 | margin: 0 1rem; 125 | padding: 5px 0; 126 | position: relative; 127 | cursor: pointer; 128 | } 129 | .app-nav li ul { 130 | background-color: #fff; 131 | border: 1px solid #ddd; 132 | border-bottom-color: #ccc; 133 | border-radius: 4px; 134 | box-sizing: border-box; 135 | display: none; 136 | max-height: calc(100vh - 61px); 137 | overflow-y: auto; 138 | padding: 10px 0; 139 | position: absolute; 140 | right: -15px; 141 | text-align: left; 142 | top: 100%; 143 | white-space: nowrap; 144 | } 145 | .app-nav li ul li { 146 | display: block; 147 | font-size: 14px; 148 | line-height: 1rem; 149 | margin: 0; 150 | margin: 8px 14px; 151 | white-space: nowrap; 152 | } 153 | .app-nav li ul a { 154 | display: block; 155 | font-size: inherit; 156 | margin: 0; 157 | padding: 0; 158 | } 159 | .app-nav li ul a.active { 160 | border-bottom: 0; 161 | } 162 | .app-nav li:hover ul { 163 | display: block; 164 | } 165 | .github-corner { 166 | border-bottom: 0; 167 | position: fixed; 168 | right: 0; 169 | text-decoration: none; 170 | top: 0; 171 | z-index: 1; 172 | } 173 | .github-corner:hover .octo-arm { 174 | -webkit-animation: octocat-wave 560ms ease-in-out; 175 | animation: octocat-wave 560ms ease-in-out; 176 | } 177 | .github-corner svg { 178 | color: #fff; 179 | fill: var(--theme-color, #42b983); 180 | height: 80px; 181 | width: 80px; 182 | } 183 | main { 184 | display: block; 185 | position: relative; 186 | width: 100vw; 187 | height: 100%; 188 | z-index: 0; 189 | } 190 | main.hidden { 191 | display: none; 192 | } 193 | .anchor { 194 | display: inline-block; 195 | text-decoration: none; 196 | transition: all 0.3s; 197 | } 198 | .anchor span { 199 | color: #34495e; 200 | } 201 | .anchor:hover { 202 | text-decoration: underline; 203 | } 204 | .sidebar { 205 | border-right: 1px solid rgba(0,0,0,0.07); 206 | overflow-y: auto; 207 | padding: 40px 0 0; 208 | position: absolute; 209 | top: 0; 210 | bottom: 0; 211 | left: 0; 212 | transition: transform 250ms ease-out; 213 | width: 300px; 214 | z-index: 20; 215 | } 216 | .sidebar > h1 { 217 | margin: 0 auto 1rem; 218 | font-size: 1.5rem; 219 | font-weight: 300; 220 | text-align: center; 221 | } 222 | .sidebar > h1 a { 223 | color: inherit; 224 | text-decoration: none; 225 | } 226 | .sidebar > h1 .app-nav { 227 | display: block; 228 | position: static; 229 | } 230 | .sidebar .sidebar-nav { 231 | line-height: 2em; 232 | padding-bottom: 40px; 233 | } 234 | .sidebar li.collapse .app-sub-sidebar { 235 | display: none; 236 | } 237 | .sidebar ul { 238 | margin: 0 0 0 15px; 239 | padding: 0; 240 | } 241 | .sidebar li > p { 242 | font-weight: 700; 243 | margin: 0; 244 | } 245 | .sidebar ul, 246 | .sidebar ul li { 247 | list-style: none; 248 | } 249 | .sidebar ul li a { 250 | border-bottom: none; 251 | display: block; 252 | } 253 | .sidebar ul li ul { 254 | padding-left: 20px; 255 | } 256 | .sidebar::-webkit-scrollbar { 257 | width: 4px; 258 | } 259 | .sidebar::-webkit-scrollbar-thumb { 260 | background: transparent; 261 | border-radius: 4px; 262 | } 263 | .sidebar:hover::-webkit-scrollbar-thumb { 264 | background: rgba(136,136,136,0.4); 265 | } 266 | .sidebar:hover::-webkit-scrollbar-track { 267 | background: rgba(136,136,136,0.1); 268 | } 269 | .sidebar-toggle { 270 | background-color: transparent; 271 | background-color: rgba(255,255,255,0.8); 272 | border: 0; 273 | outline: none; 274 | padding: 10px; 275 | position: absolute; 276 | bottom: 0; 277 | left: 0; 278 | text-align: center; 279 | transition: opacity 0.3s; 280 | width: 284px; 281 | z-index: 30; 282 | cursor: pointer; 283 | } 284 | .sidebar-toggle:hover .sidebar-toggle-button { 285 | opacity: 0.4; 286 | } 287 | .sidebar-toggle span { 288 | background-color: var(--theme-color, #42b983); 289 | display: block; 290 | margin-bottom: 4px; 291 | width: 16px; 292 | height: 2px; 293 | } 294 | body.sticky .sidebar, 295 | body.sticky .sidebar-toggle { 296 | position: fixed; 297 | } 298 | .content { 299 | padding-top: 60px; 300 | position: absolute; 301 | top: 0; 302 | right: 0; 303 | bottom: 0; 304 | left: 300px; 305 | transition: left 250ms ease; 306 | } 307 | .markdown-section { 308 | margin: 0 auto; 309 | max-width: 80%; 310 | padding: 30px 15px 40px 15px; 311 | position: relative; 312 | } 313 | .markdown-section > * { 314 | box-sizing: border-box; 315 | font-size: inherit; 316 | } 317 | .markdown-section > :first-child { 318 | margin-top: 0 !important; 319 | } 320 | .markdown-section hr { 321 | border: none; 322 | border-bottom: 1px solid #eee; 323 | margin: 2em 0; 324 | } 325 | .markdown-section iframe { 326 | border: 1px solid #eee; 327 | /* fix horizontal overflow on iOS Safari */ 328 | width: 1px; 329 | min-width: 100%; 330 | } 331 | .markdown-section table { 332 | border-collapse: collapse; 333 | border-spacing: 0; 334 | display: block; 335 | margin-bottom: 1rem; 336 | overflow: auto; 337 | width: 100%; 338 | } 339 | .markdown-section th { 340 | border: 1px solid #ddd; 341 | font-weight: bold; 342 | padding: 6px 13px; 343 | } 344 | .markdown-section td { 345 | border: 1px solid #ddd; 346 | padding: 6px 13px; 347 | } 348 | .markdown-section tr { 349 | border-top: 1px solid #ccc; 350 | } 351 | .markdown-section tr:nth-child(2n) { 352 | background-color: #f8f8f8; 353 | } 354 | .markdown-section p.tip { 355 | background-color: #f8f8f8; 356 | border-bottom-right-radius: 2px; 357 | border-left: 4px solid #f66; 358 | border-top-right-radius: 2px; 359 | margin: 2em 0; 360 | padding: 12px 24px 12px 30px; 361 | position: relative; 362 | } 363 | .markdown-section p.tip:before { 364 | background-color: #f66; 365 | border-radius: 100%; 366 | color: #fff; 367 | content: '!'; 368 | font-family: 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif; 369 | font-size: 14px; 370 | font-weight: bold; 371 | left: -12px; 372 | line-height: 20px; 373 | position: absolute; 374 | height: 20px; 375 | width: 20px; 376 | text-align: center; 377 | top: 14px; 378 | } 379 | .markdown-section p.tip code { 380 | background-color: #efefef; 381 | } 382 | .markdown-section p.tip em { 383 | color: #34495e; 384 | } 385 | .markdown-section p.warn { 386 | background: rgba(66,185,131,0.1); 387 | border-radius: 2px; 388 | padding: 1rem; 389 | } 390 | .markdown-section ul.task-list > li { 391 | list-style-type: none; 392 | } 393 | body.close .sidebar { 394 | transform: translateX(-300px); 395 | } 396 | body.close .sidebar-toggle { 397 | width: auto; 398 | } 399 | body.close .content { 400 | left: 0; 401 | } 402 | @media print { 403 | .github-corner, 404 | .sidebar-toggle, 405 | .sidebar, 406 | .app-nav { 407 | display: none; 408 | } 409 | } 410 | @media screen and (max-width: 768px) { 411 | .github-corner, 412 | .sidebar-toggle, 413 | .sidebar { 414 | position: fixed; 415 | } 416 | .app-nav { 417 | margin-top: 16px; 418 | } 419 | .app-nav li ul { 420 | top: 30px; 421 | } 422 | main { 423 | height: auto; 424 | overflow-x: hidden; 425 | } 426 | .sidebar { 427 | left: -300px; 428 | transition: transform 250ms ease-out; 429 | } 430 | .content { 431 | left: 0; 432 | max-width: 100vw; 433 | position: static; 434 | padding-top: 20px; 435 | transition: transform 250ms ease; 436 | } 437 | .app-nav, 438 | .github-corner { 439 | transition: transform 250ms ease-out; 440 | } 441 | .sidebar-toggle { 442 | background-color: transparent; 443 | width: auto; 444 | padding: 30px 30px 10px 10px; 445 | } 446 | body.close .sidebar { 447 | transform: translateX(300px); 448 | } 449 | body.close .sidebar-toggle { 450 | background-color: rgba(255,255,255,0.8); 451 | transition: 1s background-color; 452 | width: 284px; 453 | padding: 10px; 454 | } 455 | body.close .content { 456 | transform: translateX(300px); 457 | } 458 | body.close .app-nav, 459 | body.close .github-corner { 460 | display: none; 461 | } 462 | .github-corner:hover .octo-arm { 463 | -webkit-animation: none; 464 | animation: none; 465 | } 466 | .github-corner .octo-arm { 467 | -webkit-animation: octocat-wave 560ms ease-in-out; 468 | animation: octocat-wave 560ms ease-in-out; 469 | } 470 | } 471 | @-webkit-keyframes octocat-wave { 472 | 0%, 100% { 473 | transform: rotate(0); 474 | } 475 | 20%, 60% { 476 | transform: rotate(-25deg); 477 | } 478 | 40%, 80% { 479 | transform: rotate(10deg); 480 | } 481 | } 482 | @keyframes octocat-wave { 483 | 0%, 100% { 484 | transform: rotate(0); 485 | } 486 | 20%, 60% { 487 | transform: rotate(-25deg); 488 | } 489 | 40%, 80% { 490 | transform: rotate(10deg); 491 | } 492 | } 493 | section.cover { 494 | align-items: center; 495 | background-position: center center; 496 | background-repeat: no-repeat; 497 | background-size: cover; 498 | height: 100vh; 499 | display: none; 500 | } 501 | section.cover.show { 502 | display: flex; 503 | } 504 | section.cover.has-mask .mask { 505 | background-color: #fff; 506 | opacity: 0.8; 507 | position: absolute; 508 | top: 0; 509 | height: 100%; 510 | width: 100%; 511 | } 512 | section.cover .cover-main { 513 | flex: 1; 514 | margin: -20px 16px 0; 515 | text-align: center; 516 | z-index: 1; 517 | } 518 | section.cover a { 519 | color: inherit; 520 | text-decoration: none; 521 | } 522 | section.cover a:hover { 523 | text-decoration: none; 524 | } 525 | section.cover p { 526 | line-height: 1.5rem; 527 | margin: 1em 0; 528 | } 529 | section.cover h1 { 530 | color: inherit; 531 | font-size: 2.5rem; 532 | font-weight: 300; 533 | margin: 0.625rem 0 2.5rem; 534 | position: relative; 535 | text-align: center; 536 | } 537 | section.cover h1 a { 538 | display: block; 539 | } 540 | section.cover h1 small { 541 | bottom: -0.4375rem; 542 | font-size: 1rem; 543 | position: absolute; 544 | } 545 | section.cover blockquote { 546 | font-size: 1.5rem; 547 | text-align: center; 548 | } 549 | section.cover ul { 550 | line-height: 1.8; 551 | list-style-type: none; 552 | margin: 1em auto; 553 | max-width: 500px; 554 | padding: 0; 555 | } 556 | section.cover .cover-main > p:last-child a { 557 | border-color: var(--theme-color, #42b983); 558 | border-radius: 2rem; 559 | border-style: solid; 560 | border-width: 1px; 561 | box-sizing: border-box; 562 | color: var(--theme-color, #42b983); 563 | display: inline-block; 564 | font-size: 1.05rem; 565 | letter-spacing: 0.1rem; 566 | margin: 0.5rem 1rem; 567 | padding: 0.75em 2rem; 568 | text-decoration: none; 569 | transition: all 0.15s ease; 570 | } 571 | section.cover .cover-main > p:last-child a:last-child { 572 | background-color: var(--theme-color, #42b983); 573 | color: #fff; 574 | } 575 | section.cover .cover-main > p:last-child a:last-child:hover { 576 | color: inherit; 577 | opacity: 0.8; 578 | } 579 | section.cover .cover-main > p:last-child a:hover { 580 | color: inherit; 581 | } 582 | section.cover blockquote > p > a { 583 | border-bottom: 2px solid var(--theme-color, #42b983); 584 | transition: color 0.3s; 585 | } 586 | section.cover blockquote > p > a:hover { 587 | color: var(--theme-color, #42b983); 588 | } 589 | body { 590 | background-color: #fff; 591 | } 592 | /* sidebar */ 593 | .sidebar { 594 | background-color: #fff; 595 | color: #364149; 596 | } 597 | .sidebar li { 598 | margin: 6px 0 6px 0; 599 | } 600 | .sidebar ul li a { 601 | color: #505d6b; 602 | font-size: 14px; 603 | font-weight: normal; 604 | overflow: hidden; 605 | text-decoration: none; 606 | text-overflow: ellipsis; 607 | white-space: nowrap; 608 | } 609 | .sidebar ul li a:hover { 610 | text-decoration: underline; 611 | } 612 | .sidebar ul li ul { 613 | padding: 0; 614 | } 615 | .sidebar ul li.active > a { 616 | border-right: 2px solid; 617 | color: var(--theme-color, #42b983); 618 | font-weight: 600; 619 | } 620 | .app-sub-sidebar li::before { 621 | content: '-'; 622 | padding-right: 4px; 623 | float: left; 624 | } 625 | /* markdown content found on pages */ 626 | .markdown-section h1, 627 | .markdown-section h2, 628 | .markdown-section h3, 629 | .markdown-section h4, 630 | .markdown-section strong { 631 | color: #2c3e50; 632 | font-weight: 600; 633 | } 634 | .markdown-section a { 635 | color: var(--theme-color, #42b983); 636 | font-weight: 600; 637 | } 638 | .markdown-section h1 { 639 | font-size: 2rem; 640 | margin: 0 0 1rem; 641 | } 642 | .markdown-section h2 { 643 | font-size: 1.75rem; 644 | margin: 45px 0 0.8rem; 645 | } 646 | .markdown-section h3 { 647 | font-size: 1.5rem; 648 | margin: 40px 0 0.6rem; 649 | } 650 | .markdown-section h4 { 651 | font-size: 1.25rem; 652 | } 653 | .markdown-section h5 { 654 | font-size: 1rem; 655 | } 656 | .markdown-section h6 { 657 | color: #777; 658 | font-size: 1rem; 659 | } 660 | .markdown-section figure, 661 | .markdown-section p { 662 | margin: 1.2em 0; 663 | } 664 | .markdown-section p, 665 | .markdown-section ul, 666 | .markdown-section ol { 667 | line-height: 1.6rem; 668 | word-spacing: 0.05rem; 669 | } 670 | .markdown-section ul, 671 | .markdown-section ol { 672 | padding-left: 1.5rem; 673 | } 674 | .markdown-section blockquote { 675 | border-left: 4px solid var(--theme-color, #42b983); 676 | color: #858585; 677 | margin: 2em 0; 678 | padding-left: 20px; 679 | } 680 | .markdown-section blockquote p { 681 | font-weight: 600; 682 | margin-left: 0; 683 | } 684 | .markdown-section iframe { 685 | margin: 1em 0; 686 | } 687 | .markdown-section em { 688 | color: #7f8c8d; 689 | } 690 | .markdown-section code { 691 | background-color: #f8f8f8; 692 | border-radius: 2px; 693 | color: #e96900; 694 | font-family: 'Roboto Mono', Monaco, courier, monospace; 695 | font-size: 0.8rem; 696 | margin: 0 2px; 697 | padding: 3px 5px; 698 | white-space: pre-wrap; 699 | } 700 | .markdown-section pre { 701 | -moz-osx-font-smoothing: initial; 702 | -webkit-font-smoothing: initial; 703 | background-color: #f8f8f8; 704 | font-family: 'Roboto Mono', Monaco, courier, monospace; 705 | line-height: 1.5rem; 706 | margin: 1.2em 0; 707 | overflow: auto; 708 | padding: 0 1.4rem; 709 | position: relative; 710 | word-wrap: normal; 711 | } 712 | /* code highlight */ 713 | .token.comment, 714 | .token.prolog, 715 | .token.doctype, 716 | .token.cdata { 717 | color: #8e908c; 718 | } 719 | .token.namespace { 720 | opacity: 0.7; 721 | } 722 | .token.boolean, 723 | .token.number { 724 | color: #c76b29; 725 | } 726 | .token.punctuation { 727 | color: #525252; 728 | } 729 | .token.property { 730 | color: #c08b30; 731 | } 732 | .token.tag { 733 | color: #2973b7; 734 | } 735 | .token.string { 736 | color: var(--theme-color, #42b983); 737 | } 738 | .token.selector { 739 | color: #6679cc; 740 | } 741 | .token.attr-name { 742 | color: #2973b7; 743 | } 744 | .token.entity, 745 | .token.url, 746 | .language-css .token.string, 747 | .style .token.string { 748 | color: #22a2c9; 749 | } 750 | .token.attr-value, 751 | .token.control, 752 | .token.directive, 753 | .token.unit { 754 | color: var(--theme-color, #42b983); 755 | } 756 | .token.keyword, 757 | .token.function { 758 | color: #e96900; 759 | } 760 | .token.statement, 761 | .token.regex, 762 | .token.atrule { 763 | color: #22a2c9; 764 | } 765 | .token.placeholder, 766 | .token.variable { 767 | color: #3d8fd1; 768 | } 769 | .token.deleted { 770 | text-decoration: line-through; 771 | } 772 | .token.inserted { 773 | border-bottom: 1px dotted #202746; 774 | text-decoration: none; 775 | } 776 | .token.italic { 777 | font-style: italic; 778 | } 779 | .token.important, 780 | .token.bold { 781 | font-weight: bold; 782 | } 783 | .token.important { 784 | color: #c94922; 785 | } 786 | .token.entity { 787 | cursor: help; 788 | } 789 | .markdown-section pre > code { 790 | -moz-osx-font-smoothing: initial; 791 | -webkit-font-smoothing: initial; 792 | background-color: #f8f8f8; 793 | border-radius: 2px; 794 | color: #525252; 795 | display: block; 796 | font-family: 'Roboto Mono', Monaco, courier, monospace; 797 | font-size: 0.8rem; 798 | line-height: inherit; 799 | margin: 0 2px; 800 | max-width: inherit; 801 | overflow: inherit; 802 | padding: 2.2em 5px; 803 | white-space: inherit; 804 | } 805 | .markdown-section code::after, 806 | .markdown-section code::before { 807 | letter-spacing: 0.05rem; 808 | } 809 | code .token { 810 | -moz-osx-font-smoothing: initial; 811 | -webkit-font-smoothing: initial; 812 | min-height: 1.5rem; 813 | position: relative; 814 | left: auto; 815 | } 816 | pre::after { 817 | color: #ccc; 818 | content: attr(data-lang); 819 | font-size: 0.6rem; 820 | font-weight: 600; 821 | height: 15px; 822 | line-height: 15px; 823 | padding: 5px 10px 0; 824 | position: absolute; 825 | right: 0; 826 | text-align: right; 827 | top: 0; 828 | } 829 | -------------------------------------------------------------------------------- /public/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | OpenApi - XY笔记 - 开源API 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 34 |
35 |
36 |

XY笔记 - 开源API测试平台

37 | 38 |

39 | Github 40 | Get Started 41 |

42 |
43 | 44 |
45 |
46 |

XY笔记 - 开源API测试平台

47 |
48 |
测试
49 |
50 |
51 | 52 | 53 | -------------------------------------------------------------------------------- /public/user/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | XY登录中心 8 | 9 | 10 | 11 | 12 | 101 | 102 | 103 | 104 | 105 |
106 |
107 |

MIX

108 |
109 |
110 |
111 |
112 | 114 |
115 |
116 | 118 |
119 |
120 | 121 |
122 |
123 |
124 |
125 | 126 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /public/user/reg.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | XY注册中心 8 | 9 | 10 | 11 | 100 | 101 | 102 | 103 | 104 |
105 |
106 |

MIX

107 |
108 |
109 |
110 |
111 | 113 |
114 |
115 | 117 |
118 |
119 | 121 |
122 |
123 | 124 |
125 |
126 |
127 |
128 | 129 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /public/user/user.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | XY用户中心 8 | 9 | 10 | 11 | 12 | 101 | 102 | 103 | 104 | 105 |
106 |
107 |

MIX

108 |
109 |
110 |
111 |
112 | 113 |
114 |
115 | 116 |
117 |
118 |
119 | 120 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /test.php: -------------------------------------------------------------------------------- 1 | $item){ 13 | $device['os'][$key]=trim($item); 14 | } 15 | 16 | echo json_encode($device); --------------------------------------------------------------------------------