first commit
This commit is contained in:
13
mApi/.gitignore
vendored
Executable file
13
mApi/.gitignore
vendored
Executable file
@@ -0,0 +1,13 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
1
mApi/.pydio
Normal file
1
mApi/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
a19759e8-d650-433b-8bf3-365303d5bf79
|
||||
163
mApi/README.md
Executable file
163
mApi/README.md
Executable file
@@ -0,0 +1,163 @@
|
||||
# 1. 前言
|
||||
|
||||
---
|
||||
|
||||
为何写这个接口?其实本来不准备写的,这两天在练习 [TypeScript](https://www.tslang.cn/index.html),然后一直在用[TypeScript](https://www.tslang.cn/index.html)改造[express](http://www.expressjs.com.cn/)框架的应用生成器代码。改着改着发现有点无聊了。
|
||||
|
||||
无聊,而且没有挑战,怎么办?....Google翻墙后随意逛了下,然后无意中看到一个比较`好欺负`的 学(dongzuo)习(pian)网站,然后抄起还没最终完善好的项目代码来练练手!
|
||||
|
||||
**注意:代码本无罪,请以学习的目的来正确看待本项目!**
|
||||
|
||||
|
||||
## 2. 技术实现
|
||||
|
||||
---
|
||||
|
||||
项目基于[Node.js](http://nodejs.cn/),主要开发语言使用的是[TypeScript](https://www.tslang.cn/index.html),通过自动化构建工具[gulp](https://www.gulpjs.com.cn/)实现对`*.ts`文件的修改后的自动编译成`*.js`。
|
||||
|
||||
使用模块 [gulp-uglify](https://www.npmjs.com/package/gulp-uglify) 压缩编译成功后的js代码,然后通过模块 [gulp-babel](https://www.npmjs.com/package/gulp-babel)将编译后的`es6`转换成`es5`代码。
|
||||
|
||||
因为当我们还没写完某段ts代码,gulp在后台编译的时候就会报错,报错直接导致了gulp终止了进程也就无法对代码进行有效的实时编译。所以这里使用模块 [gulp-plumber](https://www.npmjs.com/package/gulp-plumber)在容易出错的地方写错误监听。这个插件可以阻止 gulp 插件发生错误导致进程退出并输出错误日志。
|
||||
|
||||
代码位置:`gulpfile.js` 第18行
|
||||
```js
|
||||
//编译ts文件为js
|
||||
gulp.task('build-ts',function(){
|
||||
return tsp.src()
|
||||
.pipe(plumber()) // 捕捉编译ts编译的错误,避免因为错误导致gulp进场关闭
|
||||
.pipe(tsp())
|
||||
.pipe(gulp.dest(PATHS.output));
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
|
||||
因为我们要让gulp在后台监听并实时编译ts文件,然后还想让我们的nodejs服务器同步我们ts文件编译结束能自动重启查看到效果,所以我这里安装了模块 [concurrently](https://www.npmjs.com/package/concurrently) 。主要用于同步运行gulp任何和启动nodejs网站服务器。
|
||||
|
||||
`package.json`中代码:
|
||||
|
||||
```js
|
||||
"scripts": {
|
||||
...
|
||||
"all": "concurrently \"gulp dev\" \"npm run dev\" "
|
||||
}
|
||||
```
|
||||
|
||||
所以请先全局安装 `concurrently`,命令:
|
||||
|
||||
> npm install -g concurrently
|
||||
|
||||
然后在安装你的网站依赖。
|
||||
|
||||
|
||||
**项目里有些文件和代码和此次爬虫的代码无关,只是我之前还没写完的代码留在那,懒得删除!并不影响使用...**
|
||||
|
||||
|
||||
## 3. 接口
|
||||
|
||||
---
|
||||
|
||||
> 测试阶段接口统一运行在 [http://127.0.0.1:3000](http://127.0.0.1:3000)
|
||||
|
||||
### 3.1: 获取网站主页数据
|
||||
|
||||
---
|
||||
|
||||
这个接口获取的是网站主页的数据,视频数量有限,不过是推荐的热门视频。
|
||||
|
||||
|
||||
| 接口地址 | 请求方式 | 参数 |
|
||||
| :-----------| :------- | ---------------------- |
|
||||
| /index | GET | 无 |
|
||||
|
||||
- 实例:[http://127.0.0.1:3000/index](http://127.0.0.1:3000/index)
|
||||
|
||||
- 数据返回:
|
||||
|
||||
```json
|
||||
{
|
||||
status: 200,
|
||||
length: 24,
|
||||
time: "2018-08-11 23:22:26",
|
||||
result: [
|
||||
{
|
||||
title: "SM调教最新**娘",
|
||||
href: "https://www.**.com/Html/93/5949.html",
|
||||
gif: "https://pic.**.com/Uploads/vod/2018-08-11/7.mp4.gif",
|
||||
time: "2018-08-11",
|
||||
mp4: "https://d.e**i.com/20180811/93/7/7.mp4"
|
||||
},
|
||||
{
|
||||
title: "极品**女主播96年美女赵晓晓人这么瘦却有这么一对****",
|
||||
href: "https://www.**.com/Html/91/5948.html",
|
||||
gif: "https://pic.**.com/Uploads/vod/2018-08-11/924.mp4.gif",
|
||||
time: "2018-08-11",
|
||||
mp4: "https://d.**.com/20180811/91/924/924.mp4"
|
||||
},
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2: 获取网站各栏目的视频数据
|
||||
|
||||
---
|
||||
|
||||
这个接口是用来获取各个网站分类栏目的数据,视频数量和分类更多!
|
||||
|
||||
|
||||
| 接口地址 | 请求方式 | 参数 |
|
||||
| :------------------------ | :------- | ---------- |
|
||||
| /videoClass | GET | type:具体栏目编号(参考下面的表) <br> page: 页码|
|
||||
|
||||
- 实例:[http://127.0.0.1:3000/videoClass?type=60&page=1](http://127.0.0.1:3000/videoClass?type=60&page=1)
|
||||
|
||||
|
||||
- 数据返回:
|
||||
|
||||
```json
|
||||
{
|
||||
status: 200,
|
||||
length: 12,
|
||||
time: "2018-08-11 23:35:55",
|
||||
total: "共2642部 4/221",
|
||||
result: [
|
||||
{
|
||||
title: "藝壇風雨錄-[粵語中字]",
|
||||
href: "https://www.**.com/Html/109/5865.html",
|
||||
gif: "https://pic.**.com/Uploads/vod/2018-08-06/11.mp4.jpg",
|
||||
time: "2018-08-06",
|
||||
mp4: "https://d.**.com/20180806/109/11/11.mp4"
|
||||
},
|
||||
{
|
||||
title: "正点留学妹妹**视频被**漂亮",
|
||||
href: "https://www.**.com/Html/87/5857.html",
|
||||
gif: "https://pic.**.com/Uploads/vod/2018-08-05/64.mp4.gif",
|
||||
time: "2018-08-05",
|
||||
mp4: "https://d.**.com/20180805/87/64/64.mp4"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
注意:type 字段的具体编号请看下表:
|
||||
|
||||
| 栏目名称 | 栏目编号 |
|
||||
| :--------| :------|
|
||||
| 国产精品 | 60 |
|
||||
| 中文字幕 | 94 |
|
||||
| S级女优 | 100 |
|
||||
| 欧美性爱 | 62 |
|
||||
| 成人动漫 | 101 |
|
||||
| 自拍偷拍 | 89 |
|
||||
| 夫妻同房 | 87 |
|
||||
| 开放90后 | 93 |
|
||||
| 换妻游戏 | 90 |
|
||||
| 网红主播 | 91 |
|
||||
| 手机小视频 | 88 |
|
||||
| 明星艳照门 | 92 |
|
||||
| 经典三级 | 109 |
|
||||
| 无码在线 | 110 |
|
||||
| 熟女人妻 | 111 |
|
||||
| 美颜巨乳 | 112 |
|
||||
| 颜射吃精 | 113 |
|
||||
| 丝袜制服 | 114 |
|
||||
1
mApi/api/.pydio
Normal file
1
mApi/api/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
320ef53f-50f1-4129-ae6b-50dcb9c34f8e
|
||||
127
mApi/api/api.md
Executable file
127
mApi/api/api.md
Executable file
@@ -0,0 +1,127 @@
|
||||
## API接口文档
|
||||
|
||||
---
|
||||
|
||||
> 接口统一运行在:[http://149.28.26.249:3000/](http://149.28.26.249:3000/)
|
||||
|
||||
注意:
|
||||
|
||||
- 1:接口全部使用GET方式进行数据请求
|
||||
- 2:接口参数全部采用 RSA 非对称性加密,所以需要文件里面的 `rsa_pub.pem` 公钥对接口参数进行加密
|
||||
- 3:参数需要放在http请求头部的 `token` 中进行数据传递。
|
||||
|
||||
|
||||
完整的流程:
|
||||
|
||||
举例,例如这边访问 分类接口:
|
||||
|
||||
- 1:接口URL地址如下:http://149.28.26.249:3000:3000/class
|
||||
- 2:接口参数拼接后:type=60&page=1
|
||||
- 3:使用 `rsa_pub.pem` 对 步骤2 进行加密得到密文:
|
||||
```txt
|
||||
qwe87LzOllYQYOHnLERCw0u/xIoBePAuNa36iu4e27hMdLCrOVd/YXesT+Q5qXVmB/FC0vR5H7rHrW+MmdTX78ey546ua3pTSlTieO8J4QGcwE+YERPJ1mG8QKmNyOVVffQaa9ltOWaHcNUH5EKEjUIU2wDDIBT5Xxl1/4CsZPc=
|
||||
```
|
||||
- 4:将加密后的密文放到http请求的头部`token`中,发送请求。
|
||||

|
||||
|
||||
- 5:后端Node.js将会从header中拿到`token`然后用私钥解密,等到参数 type=60&page=1,然后爬虫根据规则去爬取网站返回json数据。数据格式如下:
|
||||

|
||||
|
||||
|
||||
### 1:首页
|
||||
|
||||
这个接口获取的是网站主页的数据,视频数量有限,不过是推荐的热门视频。
|
||||
|
||||
| 接口地址 | 请求方式 | 参数 |
|
||||
| :-----------| :------- | ---------------------- |
|
||||
| /index | GET | 无 |
|
||||
|
||||
数据返回:
|
||||
```json
|
||||
{
|
||||
length: 24, // 数据长度
|
||||
status: 200, // 请求状态 200,成功
|
||||
time: "2018-08-25 15:29:24", // 请求时间
|
||||
result: [
|
||||
{
|
||||
// 视频的gif地址
|
||||
gif: "https://pic.5ppav.com/Uploads/vod/2018-08-25/7.mp4.gif",
|
||||
// 视频的详情页网址(一般前端用不上)
|
||||
href: "https://www.974sp.com/Html/93/6153.html",
|
||||
// 视频的 mp4 播放地址
|
||||
mp4: "https://d.eeoai.com/20180825/93/7/7.mp4",
|
||||
// 视频发布时间
|
||||
time: "2018-08-25",
|
||||
// 视频的标题
|
||||
title: "台南召妓全紀錄~長X女大學生"
|
||||
}
|
||||
...
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 2: 分类接口
|
||||
|
||||
这个接口是用来获取各个网站分类栏目的数据,视频数量和分类更多!
|
||||
|
||||
|
||||
| 接口地址 | 请求方式 | 参数 |
|
||||
| :------------------------ | :------- | ---------- |
|
||||
| /class | GET | type:具体栏目编号(参考下面的表) <br> page: 页码(请求第几页)|
|
||||
|
||||
|
||||
数据返回:
|
||||
```json
|
||||
{
|
||||
length: 12, // 数据长度
|
||||
status: 200, // 请求状态 200,成功
|
||||
time: "2018-08-25 15:29:24", // 请求时间
|
||||
total: {
|
||||
// 当前第几页
|
||||
currentPage: 1,
|
||||
// 该分类总计多少视频
|
||||
totalNumber: 2725,
|
||||
// 该分类总计有多少页
|
||||
totalPage: 228
|
||||
},
|
||||
result: [
|
||||
{
|
||||
// 视频的gif地址
|
||||
gif: "https://pic.5ppav.com/Uploads/vod/2018-08-25/7.mp4.gif",
|
||||
// 视频的详情页网址(一般前端用不上)
|
||||
href: "https://www.974sp.com/Html/93/6153.html",
|
||||
// 视频的 mp4 播放地址
|
||||
mp4: "https://d.eeoai.com/20180825/93/7/7.mp4",
|
||||
// 视频发布时间
|
||||
time: "2018-08-25",
|
||||
// 视频的标题
|
||||
title: "台南召妓全紀錄~長X女大學生"
|
||||
}
|
||||
...
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
注意:type 字段的具体编号请看下表:
|
||||
|
||||
| 栏目名称 | 栏目编号 |
|
||||
| :--------| :------|
|
||||
| 国产精品 | 60 |
|
||||
| 中文字幕 | 94 |
|
||||
| S级女优 | 100 |
|
||||
| 欧美性爱 | 62 |
|
||||
| 成人动漫 | 101 |
|
||||
| 自拍偷拍 | 89 |
|
||||
| 夫妻同房 | 87 |
|
||||
| 开放90后 | 93 |
|
||||
| 换妻游戏 | 90 |
|
||||
| 网红主播 | 91 |
|
||||
| 手机小视频 | 88 |
|
||||
| 明星艳照门 | 92 |
|
||||
| 经典三级 | 109 |
|
||||
| 无码在线 | 110 |
|
||||
| 熟女人妻 | 111 |
|
||||
| 美颜巨乳 | 112 |
|
||||
| 颜射吃精 | 113 |
|
||||
| 丝袜制服 | 114 |
|
||||
1
mApi/api/img/.pydio
Normal file
1
mApi/api/img/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
44d5909a-9e22-4c51-a408-fc68f3a6abac
|
||||
BIN
mApi/api/img/json.png
Executable file
BIN
mApi/api/img/json.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 144 KiB |
BIN
mApi/api/img/token.png
Executable file
BIN
mApi/api/img/token.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 113 KiB |
6
mApi/api/rsa_pub.pem
Executable file
6
mApi/api/rsa_pub.pem
Executable file
@@ -0,0 +1,6 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUbu7pfBOXprboQ4P/jBDHYAQq
|
||||
B7GTp/uzcDGiwHfdaGnjAxioNHgim9zO+/Bz/A/K9g5z7LKy/URl94QOKVpyTf1a
|
||||
c1WF6E7N0H3ALkylc0rS5Ciy5FY9MdwhyhuzlBkYoBsd7tY8/QxuDuzZ/hwFooZs
|
||||
GW9/C7DnjeEQ7RRRgQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
14
mApi/cluster.js
Executable file
14
mApi/cluster.js
Executable file
@@ -0,0 +1,14 @@
|
||||
var cluster = require('cluster');
|
||||
if (cluster.isMaster) {
|
||||
//Fork a worker to run the main program
|
||||
for (var i = 0; i < 2; i++) var worker = cluster.fork();
|
||||
} else {
|
||||
//Run main program
|
||||
require('./build/www.js');
|
||||
console.log('worker is running');
|
||||
}
|
||||
|
||||
cluster.on('death', function(worker) {
|
||||
console.log('worker ' + worker.pid + ' died. restart...');
|
||||
cluster.fork();
|
||||
});
|
||||
47
mApi/gulpfile.js
Executable file
47
mApi/gulpfile.js
Executable file
@@ -0,0 +1,47 @@
|
||||
let gulp = require('gulp');
|
||||
let ts = require('gulp-typescript');
|
||||
let uglify = require('gulp-uglify');
|
||||
let babel = require('gulp-babel');
|
||||
let plumber = require('gulp-plumber');
|
||||
let tsp = ts.createProject('tsconfig.json');
|
||||
|
||||
|
||||
//常量配置
|
||||
const PATHS = {
|
||||
scripts:['./src/**/*.ts'],
|
||||
output:'./build',
|
||||
minifyJs: './build/**/*.js'
|
||||
};
|
||||
//编译ts文件为js
|
||||
gulp.task('build-ts',function(){
|
||||
return tsp.src()
|
||||
.pipe(plumber())
|
||||
.pipe(tsp())
|
||||
.pipe(gulp.dest(PATHS.output));
|
||||
});
|
||||
|
||||
// 压缩混淆转换js代码
|
||||
gulp.task('minify-js',function(){
|
||||
gulp.src(PATHS.minifyJs)
|
||||
.pipe(babel({
|
||||
presets: ['env']
|
||||
}))
|
||||
.pipe(uglify({
|
||||
ie8: true
|
||||
}))
|
||||
.pipe(gulp.dest(PATHS.output));
|
||||
});
|
||||
|
||||
//当ts文件变化,重新编译ts文件为js
|
||||
gulp.task('watch-ts',function(){
|
||||
gulp.watch(PATHS.scripts,['build-ts'],['minify-js']);
|
||||
});
|
||||
|
||||
// 复制 RSA非对称加密的 api 接口加密文件到build文件夹
|
||||
gulp.task('copy',function(){
|
||||
gulp.src('src/rsa/*.pem')
|
||||
.pipe(gulp.dest(`${PATHS.output}/rsa`));
|
||||
});
|
||||
|
||||
//开发任务
|
||||
gulp.task('dev',['build-ts','minify-js','watch-ts','copy']);
|
||||
5099
mApi/package-lock.json
generated
Executable file
5099
mApi/package-lock.json
generated
Executable file
File diff suppressed because it is too large
Load Diff
37
mApi/package.json
Executable file
37
mApi/package.json
Executable file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "nodechat",
|
||||
"version": "1.0.0",
|
||||
"description": "本来用typescript练手重写express的应用生成器,不过到后面用这个写爬虫练手。",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "node-dev ./build/www.js",
|
||||
"build": "gulp dev",
|
||||
"all": "concurrently \"gulp dev\" \"npm run dev\" "
|
||||
},
|
||||
"keywords": [
|
||||
"chat",
|
||||
"nodejs"
|
||||
],
|
||||
"author": "bmy",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/cheerio": "^0.22.8",
|
||||
"@types/mysql": "^2.15.5",
|
||||
"@types/node": "^10.5.7",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"cheerio": "^1.0.0-rc.2",
|
||||
"concurrently": "^3.6.1",
|
||||
"express": "^4.16.3",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-babel": "^7.0.1",
|
||||
"gulp-plumber": "^1.2.0",
|
||||
"gulp-typescript": "^5.0.0-alpha.3",
|
||||
"gulp-uglify": "^3.0.1",
|
||||
"moment": "^2.22.2",
|
||||
"mysql": "^2.16.0",
|
||||
"node-jsencrypt": "^1.0.0",
|
||||
"request": "^2.88.0",
|
||||
"typescript": "^3.0.1"
|
||||
}
|
||||
}
|
||||
1
mApi/src/.pydio
Normal file
1
mApi/src/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
b13a6818-95b9-48ac-88f1-9dde569b879d
|
||||
1
mApi/src/api/.pydio
Normal file
1
mApi/src/api/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
6dab72fe-06a3-4667-bf7a-d3183fc559c8
|
||||
225
mApi/src/api/index.ts
Executable file
225
mApi/src/api/index.ts
Executable file
@@ -0,0 +1,225 @@
|
||||
import * as request from "request";
|
||||
import * as cheerio from "cheerio";
|
||||
import config from "./../config";
|
||||
class api {
|
||||
|
||||
private videoList: Array<any>;
|
||||
private imgList: Array<any>;
|
||||
private pagination: string;
|
||||
private videBaseUrl: string;
|
||||
private videoType: string;
|
||||
|
||||
constructor() {
|
||||
this.videoList = [];
|
||||
this.videBaseUrl = config.url.video
|
||||
this.videoType = '.mp4'
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送GET请求,获取网站html代码
|
||||
* @param url 网站地址
|
||||
*/
|
||||
public get(url: string) {
|
||||
let options: any = {
|
||||
url: url,
|
||||
headers: {
|
||||
'Referer': 'https://www.657xd.com/'
|
||||
}
|
||||
};
|
||||
return new Promise((resolve, reject) => {
|
||||
request(url, function (error, response, body) {
|
||||
if (error) {
|
||||
console.log(`-----请求出错----`);
|
||||
console.log(error);
|
||||
console.log(`-----请求出错----`);
|
||||
reject('error')
|
||||
} else {
|
||||
resolve(body)
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析网页代码,获取数据
|
||||
* @param html html代码
|
||||
* @param callback 回调
|
||||
*/
|
||||
public cheerios(html: string, callback: any, total?: boolean) {
|
||||
|
||||
let videoListHtml: any = this.CheerioLoad(html, '.movie2_list ul li')
|
||||
|
||||
total ? this.pagination = videoListHtml.$('.pagination').find('strong').text() : ''
|
||||
this.videoList = [];
|
||||
|
||||
(_this => {
|
||||
videoListHtml.data.each(function (item) {
|
||||
let list: any = videoListHtml.$(this);
|
||||
|
||||
|
||||
if (list.find('span').text().length != 0) {
|
||||
let mp4Url = _this.mp4URL(
|
||||
list.find('span').text(),
|
||||
list.find('a').attr('href'),
|
||||
list.html().match(/get_local\(\"([\s\S]*?).jpg/)[1]
|
||||
);
|
||||
|
||||
_this.videoList.push({
|
||||
title: list.find('h3').text(), // 视频标题
|
||||
href: `${config.url.BaseUrl()}${list.find('a').attr('href')}`, // 视频链接地址
|
||||
gif: `${config.url.video}${list.html().match(/get_local\(\"([\s\S]*?)\"\)/)[1]}`, // 视频缩略图
|
||||
time: list.find('span').text(), // 视频发布时间
|
||||
mp4: config.url.video+mp4Url,
|
||||
m3u8: _this.mp42(mp4Url)
|
||||
})
|
||||
}
|
||||
})
|
||||
})(this)
|
||||
|
||||
callback(this.videoList, this.pagination)
|
||||
}
|
||||
|
||||
/**
|
||||
* http://127.0.0.1:3000/image?type=63&page=3
|
||||
* 查看首页图片
|
||||
* @param html
|
||||
* @param callback
|
||||
* @param total
|
||||
*/
|
||||
public cheeriosIMG(html: string, callback: any, total?: boolean) {
|
||||
|
||||
let imgListHtml: any = this.CheerioLoad(html, '.box ul li')
|
||||
|
||||
total ? this.pagination = imgListHtml.$('.pagination').text() : ''
|
||||
|
||||
this.imgList = [];
|
||||
|
||||
(_this => {
|
||||
imgListHtml.data.each(function (item) {
|
||||
let list: any = imgListHtml.$(this);
|
||||
_this.imgList.push({
|
||||
title: list.find('a').text(),
|
||||
href: list.find('a').attr('href'),
|
||||
time: list.find('a').find('span').text()
|
||||
})
|
||||
})
|
||||
})(this)
|
||||
callback(this.imgList, this.pagination)
|
||||
}
|
||||
|
||||
/**
|
||||
* http://127.0.0.1:3000/imageinfo?id=/Html/63/12544.html
|
||||
* 从图片列表进入图片详情
|
||||
* @param html
|
||||
* @param callback
|
||||
*/
|
||||
public enterInfos(html: string, callback: any) {
|
||||
let list: any = this.CheerioLoad(html, '.content img')
|
||||
let title: string = list.$('.page_title h1').text()
|
||||
let imgdata: Array<any> = []
|
||||
list.data.each(function (item) {
|
||||
let img: any = list.$(this);
|
||||
imgdata.push({
|
||||
title: title,
|
||||
url: img.attr('src')
|
||||
})
|
||||
});
|
||||
|
||||
callback(imgdata)
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据规律直接分析得到视频的真实mp4地址
|
||||
* @param time 视频发布时间
|
||||
* @param href 视频链接地址
|
||||
* @param id 视频缩略图
|
||||
*/
|
||||
public mp4URL(time: string, href: string, id: string) {
|
||||
let times: string = time.replace(/-/ig, '')
|
||||
let hrefs: string = href.match(/\/(\d*)\//)[1]
|
||||
let ids: string = this.chechImgUrl(id);
|
||||
let URLS: string;
|
||||
if (ids != 'null') {
|
||||
URLS = `/${times}/${hrefs}/${ids}/${ids}${this.videoType}`
|
||||
} else {
|
||||
URLS = 'http://static.runoob.com/video/f0381j0mxd7.m701.mp4'
|
||||
}
|
||||
return URLS;
|
||||
// return this.mp42(URLS);
|
||||
}
|
||||
|
||||
//线路一 根据视频MP4地址获取m3u8播放地址
|
||||
public mp42(s) {
|
||||
var purls = [
|
||||
"https://1dbffh8.com",
|
||||
"https://1bhut8.com",
|
||||
"https://1bfsdgfht.com",
|
||||
"https://1bhyr6.com",
|
||||
"https://1bryts1.com"
|
||||
];
|
||||
var spcl_url = "https://p.043vb.com";
|
||||
|
||||
var purl = purls[Math.floor(Math.random() * purls.length)];
|
||||
var uu = purl + s + ".m3u8";
|
||||
var hour = new Date().getHours();
|
||||
var sdate = new Date().getDay();
|
||||
var x = Math.random();//0-1之间
|
||||
|
||||
if (hour >= 21 || hour < 22) {
|
||||
if (x < 0.3) {
|
||||
uu = spcl_url + s + ".m3u8";
|
||||
}
|
||||
if (sdate == 5 || sdate == 6) {
|
||||
if (x < 0.5) {
|
||||
uu = spcl_url + s + ".m3u8";
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
uu = purl + s + ".m3u8";
|
||||
}
|
||||
if (hour >= 22 || hour <= 1) {
|
||||
|
||||
if (x < 0.45) {
|
||||
uu = spcl_url + s + ".m3u8";
|
||||
}
|
||||
if (sdate == 5 || sdate == 6) {
|
||||
if (x < 0.55) {
|
||||
uu = spcl_url + s + ".m3u8";
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
uu = purl + s + ".m3u8";
|
||||
}
|
||||
|
||||
return uu;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回Cheerio数据
|
||||
* @param html html代码
|
||||
* @param dom 需要获取的dom节点
|
||||
*/
|
||||
public CheerioLoad(html: any, dom) {
|
||||
let $: any = cheerio.load(html);
|
||||
return {
|
||||
$: $,
|
||||
data: $(dom)
|
||||
};
|
||||
}
|
||||
|
||||
public chechImgUrl(url) {
|
||||
if (url.match(/\/(\d*).mp4/) == null) {
|
||||
url = 'null'
|
||||
} else {
|
||||
url = url.match(/\/(\d*).mp4/)[1]
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default api
|
||||
14
mApi/src/app.ts
Executable file
14
mApi/src/app.ts
Executable file
@@ -0,0 +1,14 @@
|
||||
import * as express from 'express';
|
||||
import * as path from 'path';
|
||||
|
||||
let app = express();
|
||||
|
||||
import indexRouter from './routes/modular/index';
|
||||
|
||||
app.use(express.static(path.join(__dirname, "public")));
|
||||
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
app.use("/", indexRouter);
|
||||
|
||||
export default app
|
||||
1
mApi/src/config/.pydio
Normal file
1
mApi/src/config/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
6bec38f6-dcf5-4ff3-95a1-23cd9c666a11
|
||||
185
mApi/src/config/index.ts
Executable file
185
mApi/src/config/index.ts
Executable file
@@ -0,0 +1,185 @@
|
||||
export default {
|
||||
address: 'http://127.0.0.1',
|
||||
port: 1314,
|
||||
rsa: {
|
||||
public: "../../rsa/rsa_pub.pem",
|
||||
private: "../../rsa/rsa_priv.pem"
|
||||
},
|
||||
mysql: {
|
||||
connectionLimit: 10,
|
||||
host: "127.0.0.1",
|
||||
user: "root",
|
||||
password: "714500",
|
||||
database: "haozhuo"
|
||||
},
|
||||
url: {
|
||||
BaseUrl: () => {
|
||||
var host = "";
|
||||
var getdz = "";
|
||||
var url = new Array();
|
||||
url.push("1b572.com");
|
||||
url.push("1b667.com");
|
||||
url.push("1b669.com");
|
||||
url.push("1b670.com");
|
||||
url.push("1b671.com");
|
||||
|
||||
url.push("11b12.com");
|
||||
url.push("11b13.com");
|
||||
url.push("11b15.com");
|
||||
url.push("11b16.com");
|
||||
url.push("11b17.com");
|
||||
url.push("11b18.com");
|
||||
url.push("11b19.com");
|
||||
url.push("11b20.com");
|
||||
url.push("11b21.com");
|
||||
url.push("11b23.com");
|
||||
url.push("11b25.com");
|
||||
url.push("11b26.com");
|
||||
url.push("11b27.com");
|
||||
url.push("11b28.com");
|
||||
url.push("11b29.com");
|
||||
url.push("11b30.com");
|
||||
url.push("11b32.com");
|
||||
url.push("22b11.com");
|
||||
url.push("22b12.com");
|
||||
url.push("22b13.com");
|
||||
url.push("22b15.com");
|
||||
url.push("22b16.com");
|
||||
url.push("22b17.com");
|
||||
url.push("22b18.com");
|
||||
url.push("22b19.com");
|
||||
url.push("22b20.com");
|
||||
url.push("22b21.com");
|
||||
url.push("22b23.com");
|
||||
url.push("22b25.com");
|
||||
url.push("22b26.com");
|
||||
url.push("22b27.com");
|
||||
url.push("22b28.com");
|
||||
url.push("22b29.com");
|
||||
url.push("22b30.com");
|
||||
url.push("22b32.com");
|
||||
url.push("33b12.com");
|
||||
url.push("33b13.com");
|
||||
url.push("33b15.com");
|
||||
url.push("33b16.com");
|
||||
url.push("33b17.com");
|
||||
url.push("33b18.com");
|
||||
url.push("33b19.com");
|
||||
url.push("33b20.com");
|
||||
url.push("33b21.com");
|
||||
url.push("33b22.com");
|
||||
url.push("33b23.com");
|
||||
url.push("33b25.com");
|
||||
url.push("33b26.com");
|
||||
url.push("33b27.com");
|
||||
url.push("33b28.com");
|
||||
|
||||
var UyoOfAKC1 = new Date("2020/12/24 18:30:00".replace(/\-/g, "/")).getTime();
|
||||
|
||||
var VK2 = 1; //VK2>=1
|
||||
var PhKNMS3 = (Math.floor((new Date().getTime() - UyoOfAKC1) / 86400000) + 1) * VK2;
|
||||
var i4 = 0;
|
||||
var cncOFZ5 = VK2 - 1;
|
||||
var MrZRcYn6 = Math.floor(Math.random() * (cncOFZ5 - i4 + 1) + i4);
|
||||
var a7 = PhKNMS3 + MrZRcYn6;
|
||||
if (a7 < 0 || a7 >= url.length) {
|
||||
a7 = url.length - (MrZRcYn6 + 1);
|
||||
PhKNMS3 = url.length - (cncOFZ5 + 1);
|
||||
}
|
||||
var D$Uja8 = true;
|
||||
for (var j = i4; j <= cncOFZ5; j++) {
|
||||
if (host.indexOf(url[PhKNMS3 + j]) >= 0) {
|
||||
D$Uja8 = false;
|
||||
break
|
||||
}
|
||||
}
|
||||
var i = a7;
|
||||
if (D$Uja8 == true) {
|
||||
var Rvq9 = url[a7];
|
||||
if (typeof (Rvq9) == "undefined") {
|
||||
Rvq9 = url[url.length - 1]
|
||||
}
|
||||
var x_ratio = Math.random();//0~1
|
||||
if (x_ratio < 0.5) {
|
||||
getdz = "https://" + escape(Rvq9);
|
||||
} else {
|
||||
getdz = "https://www." + escape(Rvq9);
|
||||
}
|
||||
|
||||
}
|
||||
return getdz;
|
||||
},
|
||||
video: 'https://1dhgjyr9.com',
|
||||
index: '/index.html',
|
||||
class: [
|
||||
{
|
||||
title: '国产精品',
|
||||
url: '/60/'
|
||||
},
|
||||
{
|
||||
title: '中文字幕',
|
||||
url: '/94/'
|
||||
},
|
||||
{
|
||||
title: 'S级女优',
|
||||
url: '/100/'
|
||||
},
|
||||
{
|
||||
title: '欧美性爱',
|
||||
url: '/62/'
|
||||
},
|
||||
{
|
||||
title: '成人动漫',
|
||||
url: '/101/'
|
||||
},
|
||||
{
|
||||
title: '自拍偷拍',
|
||||
url: '/89/'
|
||||
},
|
||||
{
|
||||
title: '夫妻同房',
|
||||
url: '/87/'
|
||||
},
|
||||
{
|
||||
title: '开放90后',
|
||||
url: '/93/'
|
||||
},
|
||||
{
|
||||
title: '换妻游戏',
|
||||
url: '/90/'
|
||||
},
|
||||
{
|
||||
title: '网红主播',
|
||||
url: '/91/'
|
||||
},
|
||||
{
|
||||
title: '手机小视频',
|
||||
url: '/88/'
|
||||
},
|
||||
{
|
||||
title: '经典三级',
|
||||
url: '/109/'
|
||||
},
|
||||
{
|
||||
title: '无码在线',
|
||||
url: '/110/'
|
||||
},
|
||||
{
|
||||
title: '熟女人妻',
|
||||
url: '/111/'
|
||||
},
|
||||
{
|
||||
title: '美颜巨乳',
|
||||
url: '/112/'
|
||||
},
|
||||
{
|
||||
title: '颜射吃精',
|
||||
url: '/113/'
|
||||
},
|
||||
{
|
||||
title: '丝袜制服',
|
||||
url: '/114/'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
1
mApi/src/mysql/.pydio
Normal file
1
mApi/src/mysql/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
aa1faf5e-b04a-4264-9ba0-745100cdd496
|
||||
38
mApi/src/mysql/index.ts
Executable file
38
mApi/src/mysql/index.ts
Executable file
@@ -0,0 +1,38 @@
|
||||
import * as mysql from "mysql";
|
||||
import config from "../config";
|
||||
|
||||
class MySql {
|
||||
private pool:any
|
||||
|
||||
constructor(){
|
||||
this.pool = mysql.createPool(config.mysql);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行数据库操作
|
||||
* @param sql sql语句
|
||||
* @param values 参数值
|
||||
*/
|
||||
query (sql:string, values?:Array<any>) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.pool.getConnection(function(err, connection) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
connection.query(sql, values, (err, rows) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
rows.length == 0 ? (rows = ["NoData..."]) : rows;
|
||||
resolve(rows);
|
||||
}
|
||||
// 结束会话
|
||||
connection.release();
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default MySql
|
||||
1
mApi/src/routes/.pydio
Normal file
1
mApi/src/routes/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
195eddce-af6f-49ce-9e1f-ddc16e30ca4a
|
||||
103
mApi/src/routes/controller.ts
Executable file
103
mApi/src/routes/controller.ts
Executable file
@@ -0,0 +1,103 @@
|
||||
import * as express from 'express'
|
||||
import utils from '../utils'
|
||||
const router = express.Router()
|
||||
|
||||
class Controller {
|
||||
public routers: any;
|
||||
public response: any;
|
||||
public request: any;
|
||||
public utils = new utils();
|
||||
|
||||
constructor () {
|
||||
router.all('*', (req, res, next) => {
|
||||
this.response = res
|
||||
this.request= req
|
||||
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
res.header("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With, token, X-Bmob-Application-Id, X-Bmob-REST-API-Key");
|
||||
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
|
||||
if(req.method == "OPTIONS") res.send(200);
|
||||
else next();
|
||||
|
||||
});
|
||||
// 暴露 router,方便其他路由使用
|
||||
this.routers = router
|
||||
}
|
||||
|
||||
/**
|
||||
* GET 请求
|
||||
* @param url 请求的地址
|
||||
* @param callback 回调
|
||||
*/
|
||||
public GetRoutes(url: string,callback: any) : void {
|
||||
router.get(url, (req, res) => {
|
||||
let params;
|
||||
switch (url) {
|
||||
case '/index':
|
||||
callback(res, req)
|
||||
break;
|
||||
case '/imageinfo':
|
||||
if(params.id != ''){
|
||||
callback(res, req, params)
|
||||
}else {
|
||||
res.json({
|
||||
status: 404,
|
||||
message: '参数缺失'
|
||||
})
|
||||
}
|
||||
break;
|
||||
case '/image':
|
||||
if(req.query.type != '' &&
|
||||
req.query.page != ''){
|
||||
callback(res, req)
|
||||
}else {
|
||||
res.json({
|
||||
status: 404,
|
||||
message: '参数缺失'
|
||||
})
|
||||
}
|
||||
case '/videoClass':
|
||||
// 判断是否存在必要参数key,和值
|
||||
console.log(req.query);
|
||||
|
||||
if(req.query.type != '' &&
|
||||
req.query.page != '') {
|
||||
callback(res, req)
|
||||
}else {
|
||||
res.json({
|
||||
status: 404,
|
||||
message: '参数缺失'
|
||||
})
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* POST 请求
|
||||
* @param url 请求的地址
|
||||
* @param callback 回调
|
||||
*/
|
||||
public PostRoutes(url: string, callback: any) : void {
|
||||
router.post(url, (req, res) => {
|
||||
callback(res, req)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
private useApiStyle (req,res) {
|
||||
if(req.query.hasOwnProperty("_rsa") && req.query._rsa != ''){
|
||||
res.json({
|
||||
status: "SRA接口等待实现..."
|
||||
})
|
||||
}else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Controller
|
||||
1
mApi/src/routes/modular/.pydio
Normal file
1
mApi/src/routes/modular/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
5ada070d-70e8-4b4f-80f2-ada2d255cf95
|
||||
138
mApi/src/routes/modular/index.ts
Executable file
138
mApi/src/routes/modular/index.ts
Executable file
@@ -0,0 +1,138 @@
|
||||
import Controller from "../controller";
|
||||
// import mysql from "./../../mysql";
|
||||
import utils from "./../../utils";
|
||||
import api from "./../../api";
|
||||
import config from "./../../config";
|
||||
|
||||
class index extends Controller{
|
||||
public utils = new utils();
|
||||
// public db = new mysql();
|
||||
public api = new api();
|
||||
|
||||
constructor () {
|
||||
super();
|
||||
this.indexRouter()
|
||||
this.otherClass()
|
||||
this.imageRouter()
|
||||
this.enterInfo()
|
||||
}
|
||||
|
||||
/**
|
||||
* 网站首页api
|
||||
* 接口地址:http://127.0.0.1:3000/index
|
||||
*/
|
||||
private indexRouter(): void {
|
||||
this.GetRoutes('/index',async (res, req) => {
|
||||
let data:any = await this.api.get(config.url.BaseUrl())
|
||||
this.api.cheerios(data, (result)=>{
|
||||
return res.json({
|
||||
status: 200,
|
||||
length: result.length,
|
||||
time: this.utils.GetTime(),
|
||||
result: result
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 网站分类页面api
|
||||
* 接口地址:http://127.0.0.1:3000/videoClass?type=60&page=1
|
||||
* @param type 网站栏目id
|
||||
* @param page 想要获取第几页的数据
|
||||
*/
|
||||
private otherClass(): void {
|
||||
this.GetRoutes('/videoClass', async (res,req) => {
|
||||
let type: string = req.query.type
|
||||
let page: string = req.query.page
|
||||
|
||||
let data: any = await this.api.get(this.returnURL(type, page))
|
||||
this.api.cheerios(data, (result, pagination)=>{
|
||||
return res.json({
|
||||
status: 200,
|
||||
length: result.length,
|
||||
time: this.utils.GetTime(),
|
||||
resultList: {
|
||||
total: this.returnPage(pagination),
|
||||
video: result
|
||||
}
|
||||
})
|
||||
}, true)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图片列表
|
||||
*/
|
||||
private imageRouter(): void {
|
||||
this.GetRoutes('/image', async (res,req) => {
|
||||
let type: string = req.query.type
|
||||
let page: string = req.query.page
|
||||
let data:any = await this.api.get(this.returnURL(type,page))
|
||||
this.api.cheeriosIMG(data, (result, pagination)=>{
|
||||
|
||||
return res.json({
|
||||
status: 200,
|
||||
length: result.length,
|
||||
time: this.utils.GetTime(),
|
||||
total: this.returnPage(pagination.substring(0,22), true),
|
||||
result: result
|
||||
})
|
||||
},true)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 进入图片详情
|
||||
*/
|
||||
private enterInfo() {
|
||||
this.GetRoutes('/imageinfo', async (res,req,params) => {
|
||||
let id: string = params.id
|
||||
let data:any = await this.api.get(`${config.url.BaseUrl()}${id}`)
|
||||
this.api.enterInfos(data,(result) =>{
|
||||
return res.json({
|
||||
status: 200,
|
||||
length: result.length,
|
||||
time: this.utils.GetTime(),
|
||||
result: result
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 因为这里第一个URL地址和其他之后每一个的地址不一样,所以这里做下简单判断
|
||||
* @param type
|
||||
* @param page
|
||||
*/
|
||||
private returnURL(type:string, page:string): any {
|
||||
let URL:string;
|
||||
page === '1' ? URL = `${config.url.BaseUrl()}/Html/${type}/` : URL = `${config.url.BaseUrl()}/Html/${type}/index-${page}.html`
|
||||
return URL
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回总视频数,当前页,总页数
|
||||
* @param page
|
||||
*/
|
||||
private returnPage(page:string, action?:boolean):any {
|
||||
let pages:any;
|
||||
if(action) {
|
||||
pages = {
|
||||
totalNumber: page.match(/共(\S*)篇/)[1],
|
||||
currentPage: page.match(/:(\S*)\//)[1],
|
||||
totalPage: page.match(/\/(\S*)页/)[1]
|
||||
}
|
||||
}else {
|
||||
pages = {
|
||||
totalNumber: page.match(/共(\S*)部/)[1],
|
||||
currentPage: page.match(/\s+(\S*)\//)[1],
|
||||
totalPage: page.match(/\/(\S*)/)[1]
|
||||
}
|
||||
}
|
||||
|
||||
return pages
|
||||
}
|
||||
}
|
||||
|
||||
export default new index().routers
|
||||
1
mApi/src/rsa/.pydio
Normal file
1
mApi/src/rsa/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
e91c2418-1979-4c6b-83c4-c5d6a1ea9a0b
|
||||
5
mApi/src/rsa/help.md
Executable file
5
mApi/src/rsa/help.md
Executable file
@@ -0,0 +1,5 @@
|
||||
RSA 非对称性加密在api接口中的使用
|
||||
|
||||
rsa_pub.pem: 公钥发给前端,前端ajax请求用公钥加密参数
|
||||
|
||||
rsa_priv.pem:私钥留在服务器上,用来解密前端ajax参数
|
||||
15
mApi/src/rsa/rsa_priv.pem
Executable file
15
mApi/src/rsa/rsa_priv.pem
Executable file
@@ -0,0 +1,15 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXQIBAAKBgQDUbu7pfBOXprboQ4P/jBDHYAQqB7GTp/uzcDGiwHfdaGnjAxio
|
||||
NHgim9zO+/Bz/A/K9g5z7LKy/URl94QOKVpyTf1ac1WF6E7N0H3ALkylc0rS5Ciy
|
||||
5FY9MdwhyhuzlBkYoBsd7tY8/QxuDuzZ/hwFooZsGW9/C7DnjeEQ7RRRgQIDAQAB
|
||||
AoGBALp9LHWCfDysmXOrGaz0jCJLEzzGhkjGtnsfKiPjbRbMu/ATXskDTterFpwK
|
||||
pltb041sluGD0Ji7KBmPwbkg6olFB8EUCu5U281+8vNXaynzwCYF/tdaRoRUcIVf
|
||||
VZS1y48LwH1JdPCtQvNldIAho5Nop7dWgz0qT2dCUezu7ab1AkEA/twQt1vnRpbk
|
||||
vp3donKkux6hI8gwV58X7jtZjIOstVWlbGUBI90nln71lEUUmkuWK6YCyJy6fhAo
|
||||
+gZ1OlltzwJBANViRRFJoGmZZLL9Jhgmeg52syVSWYcxquihKUdP4Wg6lbiETaHT
|
||||
iqNnIBTG/c5W462zJ4JfKMB1NPKUwcYy768CQQDdVZle5H3SnDFEKi3VauMNbuha
|
||||
/vyc3BoYV4rJsYFIan0jygRXdTVwSgpVHjlqVsKwXZiFSTfdS4OKwBkG96uZAkAL
|
||||
YfqdOXg9KdmdUrO9hg/sxZg43XO5KoUbc71n+HLlxHpIJYaeo1I59T5Y3WScpTXw
|
||||
BiaNZdYeriHs7tKHaCAxAkB548KLYhkxrl1SjLdmW8OcvenVORTim03dmsgUDg57
|
||||
RRenq8VNgEvEdl/5N2k8evrr3bciMAxnk0oAGUYCsbDI
|
||||
-----END RSA PRIVATE KEY-----
|
||||
6
mApi/src/rsa/rsa_pub.pem
Executable file
6
mApi/src/rsa/rsa_pub.pem
Executable file
@@ -0,0 +1,6 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDUbu7pfBOXprboQ4P/jBDHYAQq
|
||||
B7GTp/uzcDGiwHfdaGnjAxioNHgim9zO+/Bz/A/K9g5z7LKy/URl94QOKVpyTf1a
|
||||
c1WF6E7N0H3ALkylc0rS5Ciy5FY9MdwhyhuzlBkYoBsd7tY8/QxuDuzZ/hwFooZs
|
||||
GW9/C7DnjeEQ7RRRgQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
1
mApi/src/utils/.pydio
Normal file
1
mApi/src/utils/.pydio
Normal file
@@ -0,0 +1 @@
|
||||
1ce2a739-84af-4587-a927-daf5d4118598
|
||||
48
mApi/src/utils/index.ts
Executable file
48
mApi/src/utils/index.ts
Executable file
@@ -0,0 +1,48 @@
|
||||
import * as moment from "moment";
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import config from "./../config";
|
||||
import * as JsEncrypt from "node-jsencrypt";
|
||||
import * as querystring from "querystring";
|
||||
|
||||
class Utils {
|
||||
private publicKey;
|
||||
private privateKey;
|
||||
private RsaEncrypt = new JsEncrypt()
|
||||
constructor () {
|
||||
// 公钥
|
||||
this.publicKey = fs.readFileSync(path.join(__filename,config.rsa.public), "utf8")
|
||||
// 私钥
|
||||
this.privateKey = fs.readFileSync(path.join(__filename,config.rsa.private), "utf8")
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回指定的时间
|
||||
* @param timer 时间的格式
|
||||
*/
|
||||
public GetTime (timer?:string) {
|
||||
timer = timer || 'YYYY-MM-DD HH:mm:ss'
|
||||
return moment().format(timer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用公钥( rsa_pub.pem )对接口参数进行加密
|
||||
* @param ciphertext 需要加密的数据
|
||||
*/
|
||||
// public Encryption (ciphertext: string) {
|
||||
// let encrypted = crypto.publicEncrypt(this.publicKey, Buffer.from(ciphertext))
|
||||
// return encrypted.toString('base64')
|
||||
// }
|
||||
|
||||
/**
|
||||
* 使用私钥( rsa_priv.pem ) 对接口参数 token 进行解密
|
||||
* 解密后在使用 querystring 进行序列化
|
||||
* @param ciphertext 需要解密的参数
|
||||
*/
|
||||
public Decrypt(ciphertext: string) {
|
||||
this.RsaEncrypt.setPrivateKey(this.privateKey)
|
||||
return this.RsaEncrypt.decrypt(ciphertext)
|
||||
}
|
||||
}
|
||||
|
||||
export default Utils
|
||||
50
mApi/src/www.ts
Executable file
50
mApi/src/www.ts
Executable file
@@ -0,0 +1,50 @@
|
||||
import app from './app';
|
||||
import config from "./config";
|
||||
import * as http from 'http';
|
||||
|
||||
class service {
|
||||
port: number;
|
||||
server: any;
|
||||
constructor () {
|
||||
this.port = config.port
|
||||
this.init()
|
||||
}
|
||||
|
||||
private init (): void {
|
||||
this.server = http.createServer(app)
|
||||
this.start()
|
||||
}
|
||||
|
||||
private start (): void {
|
||||
this.server.listen(this.port);
|
||||
this.server.on('error', this.error);
|
||||
this.server.on('listening', this.onListening);
|
||||
}
|
||||
|
||||
private error (error:any): void {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
var bind = this.port;
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
console.error(`端口:${bind} 需要提升权限..`);
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
console.error(`端口:${bind} 被占用...`);
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private onListening(): void {
|
||||
console.log(`App is run: ${config.address}:${config.port}`)
|
||||
}
|
||||
}
|
||||
|
||||
new service()
|
||||
|
||||
|
||||
3
mApi/test.rest
Executable file
3
mApi/test.rest
Executable file
@@ -0,0 +1,3 @@
|
||||
GET http://127.0.0.1:3000/class?type=60&page=2 HTTP/1.1
|
||||
content-type: application/json
|
||||
token: 'wwwww'
|
||||
19
mApi/tsconfig.json
Executable file
19
mApi/tsconfig.json
Executable file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib":["es6"],
|
||||
"module": "commonjs", //指定生成哪个模块系统代码
|
||||
"target": "es5", //目标代码类型
|
||||
"noImplicitAny": false, //在表达式和声明上有隐含的'any'类型时报错。
|
||||
"sourceMap": false, //用于debug
|
||||
"rootDir":"./src", //仅用来控制输出的目录结构--outDir。
|
||||
"outDir":"./build", //重定向输出目录。
|
||||
"watch":false //在监视模式下运行编译器。会监视输出文件,在它们改变时重新编译。
|
||||
},
|
||||
"include":[
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude":[
|
||||
"views",
|
||||
"static"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user