技术文档

This commit is contained in:
userA
2023-05-19 01:29:47 +08:00
parent 093416e896
commit 643e145275
71 changed files with 10273 additions and 3 deletions

3
.gitignore vendored
View File

@@ -1,2 +1,3 @@
# Project exclude paths
/console/target/
/console/target/
/doc/docs/.vuepress/dist/

2
.idea/compiler.xml generated
View File

@@ -15,6 +15,7 @@
<module name="SectionWorkModule" />
<module name="PublishModule" />
<module name="VideoSectionModule" />
<module name="doc" />
<module name="SectionModule" />
<module name="BarrageModule" />
<module name="HotModule" />
@@ -38,6 +39,7 @@
<module name="VideoSectionModule" options="-parameters" />
<module name="common" options="-parameters" />
<module name="console" options="-parameters" />
<module name="doc" options="-parameters" />
</option>
</component>
</project>

1
.idea/encodings.xml generated
View File

@@ -15,6 +15,7 @@
<file url="file://$PROJECT_DIR$/VideoSectionModule/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/common/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/console/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/doc/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
<file url="PROJECT" charset="UTF-8" />

View File

@@ -0,0 +1,46 @@
package org.example.pojo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import lombok.Data;
import java.util.List;
/**
* 弹幕通用类
* @author 燧枫
* @date 2023/4/23 15:28
*/
@Data
public class Barrage {
// 弹幕唯一id
private String mid;
// 真实时间戳
private Long timeReal;
// 相对于视频的时间戳
private Long timeIndex;
// 弹幕内容
private String content;
public Barrage(){
}
public Barrage(String mid, Long timeReal, Long timeIndex, String content) {
this.mid = mid;
this.timeReal = timeReal;
this.timeIndex = timeIndex;
this.content = content;
}
/**
* @description: use to set BarrageProperty
*/
public static List<Barrage> copyProperty(JSONArray BarrageList){
return JSON.parseArray(BarrageList.toJSONString(), Barrage.class);
}
}

View File

@@ -0,0 +1,11 @@
package org.example.coreTest;
import org.junit.jupiter.api.Test;
/**
* @author Genius
* @date 2023/05/18 21:13
**/
public class moduleTest {
}

1
FileModule/README.md Normal file
View File

@@ -0,0 +1 @@
# FileModule

View File

@@ -117,6 +117,7 @@ public class FileCacheTest {
@Test
public void TestAddCache() throws FileCacheException, InterruptedException {
FileCacheManagerInstance.getInstance().start();
for(int i=0;i<10;i++){
Student student = new Student(Integer.toString(i),i,"jsu"+i,"major"+i,null,null);
cache.writeKeys(student,"-1");

View File

@@ -58,7 +58,7 @@ public class JsonFileUtilTest {
@Test
public void readJsonFile() {
Map maps = JsonFileUtil.readJsonFile("E:\\Project\\ChopperBot\\FileModule\\src\\main\\resources\\", "test.json");
Map maps = JsonFileUtil.readJsonFile("../config/", "moduleConfig.json");
Object test = maps.get("module");
System.out.println(test);
System.out.println(maps);

View File

@@ -0,0 +1,65 @@
{
"data":[
{
"age":0,
"major":"major0",
"name":"0",
"school":"jsu0"
},
{
"age":1,
"major":"major1",
"name":"1",
"school":"jsu1"
},
{
"age":2,
"major":"major2",
"name":"2",
"school":"jsu2"
},
{
"age":3,
"major":"major3",
"name":"3",
"school":"jsu3"
},
{
"age":4,
"major":"major4",
"name":"4",
"school":"jsu4"
},
{
"age":5,
"major":"major5",
"name":"5",
"school":"jsu5"
},
{
"age":6,
"major":"major6",
"name":"6",
"school":"jsu6"
},
{
"age":7,
"major":"major7",
"name":"7",
"school":"jsu7"
},
{
"age":8,
"major":"major8",
"name":"8",
"school":"jsu8"
},
{
"age":9,
"major":"major9",
"name":"9",
"school":"jsu9"
}
],
"updateTime":"2023-04-26 00:24:47"
}

View File

@@ -1,7 +1,8 @@
# ChopperBot项目框架
👉[项目文档]👈()
👉[更新日志](https://gitee.com/sbg-genius/ChopperBot/blob/master/CHANGELOG.md)👈
## 项目介绍
@@ -10,6 +11,8 @@
## 模块介绍
![image](https://mynoteimages.oss-cn-hangzhou.aliyuncs.com/20230419223557838.png)
## 开发技术文档
### 爬虫引擎 [CreeperModule]:
介绍:支持多直播网站的爬虫引擎,多线程高效爬取,支持弹幕爬取,支持视频

View File

@@ -0,0 +1,16 @@
{
platForm:[
{
name:douyu,
moduleFilter:['跳舞','唱歌'],
AnchorFilter:[
{
name:'大司马',
autoVideo:false,
autoBarrage:false
}
]
FollowTheTrendMode:false
}
]
}

35
doc/.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
name: CI
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x]
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Build project
env:
CODING_USER: ${{ secrets.CODING_USER }}
CODING_TOKEN: ${{ secrets.CODING_TOKEN }}
run: yarn --frozen-lockfile && yarn run deploy
- name: Upload COS
uses: zkqiang/tencent-cos-action@v0.1.0
with:
args: list / -ar && delete -r -f / && upload -r ./docs/.vuepress/dist/ /
secret_id: ${{ secrets.TENCENT_CLOUD_SECRET_ID }}
secret_key: ${{ secrets.TENCENT_CLOUD_SECRET_KEY }}
bucket: ${{ secrets.TENCENT_CLOUD_BUCKET }}
region: ap-beijing

30
doc/.gitignore vendored Normal file
View File

@@ -0,0 +1,30 @@
# IntelliJ project files
.idea/
*.iml
*.ipr
*.iws
out
gem
# Fleet project files
.fleet/
# VS Code project files
.vscode/
# MacOS files
.DS_Store
Thumbs.db
# NPM
package-lock.json
node_modules
# YARN
# yarn.lock
# VuePress
docs/.vuepress/dist
# Baidu Push
urls.txt

8
doc/.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

9
doc/.idea/Assistant-Doc.iml generated Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
doc/.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
doc/.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Assistant-Doc.iml" filepath="$PROJECT_DIR$/.idea/Assistant-Doc.iml" />
</modules>
</component>
</project>

7
doc/.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

27
doc/deploy.sh Normal file
View File

@@ -0,0 +1,27 @@
#!/usr/bin/env sh
# 确保脚本抛出遇到的错误
set -e
# 生成文档
yarn run build
# 进入生成的文件夹
cd docs/.vuepress/dist
# 输出 CNAME 文件
echo "baomidou.com" > CNAME
echo "www.baomidou.com" >> CNAME
echo "google.com, pub-4147143076931995, DIRECT, f08c47fec0942fa0" > ads.txt
# msg="来自Github Actions的自动部署更新于$(TZ=UTC-8 date "+%Y-%m-%d %H:%M:%S")"
# codingUrl=https://${CODING_USER}:${CODING_TOKEN}@e.coding.net/yangyang0507/mybatis-plus-doc.git
# git config --global user.name "D.Yang"
# git config --global user.email "koyangslash@gmail.com"
# git init
# git remote add origin $codingUrl
# git add -A
# git commit -m "${msg}"
# git push -f origin master

View File

@@ -0,0 +1,16 @@
const head = require('./config/head.js');
const plugins = require('./config/plugins.js');
const themeConfig = require('./config/themeConfig.js');
module.exports = {
theme: "vdoing",
title: "ChopperBot",
description: 'ChopperBot 官方文档',
base: "/ChopperBot-Doc/",
markdown: {
lineNumbers: true
},
head,
themeConfig,
plugins
}

View File

@@ -0,0 +1,68 @@
// Head Config
module.exports = [
["link", { rel: "icon", href: "/img/favicon.ico" }],
[
"meta",
{
name: "keywords",
content:
"ChopperBot,Assistant,Tml,framework,toolkit"
}
],
["meta", { name: "theme-color", content: "#ef6d48" }],
[
"script",
{
crossorigin: "anonymous",
async: true,
src: "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4147143076931995"
}
],
["script", { async: true, src: "https://cdn.wwads.cn/js/makemoney.js" }],
['script', {}, `
// 万维广告“禁止”广告拦截
// function called if wwads is blocked
// https://github.com/bytegravity/whitelist-wwads
function ABDetected() {
var adBlockDetected_div = document.createElement("div");
adBlockDetected_div.style.cssText = "position: absolute; top: 0; left: 0; width: 100%; background: #fc6600; color: #fff; z-index: 9999999999; font-size: 14px; text-align: center; line-height: 1.5; font-weight: bold; padding-top: 6px; padding-bottom: 6px;";
adBlockDetected_div.innerHTML = "我们的广告服务商 <a style='color:#fff;text-decoration:underline' target='_blank' href='https://wwads.cn/page/end-user-privacy'>并不跟踪您的隐私</a>,为了支持本站的长期运营,请将我们的网站 <a style='color: #fff;text-decoration:underline' target='_blank' href='https://wwads.cn/page/whitelist-wwads'>加入广告拦截器的白名单</a>。";
document.getElementsByTagName("body")[0].appendChild(adBlockDetected_div);
// add a close button to the right side of the div
var adBlockDetected_close = document.createElement("div");
adBlockDetected_close.style.cssText = "position: absolute; top: 0; right: 10px; width: 30px; height: 30px; background: #fc6600; color: #fff; z-index: 9999999999; line-height: 30px; cursor: pointer;";
adBlockDetected_close.innerHTML = "×";
adBlockDetected_div.appendChild(adBlockDetected_close);
// add a click event to the close button
adBlockDetected_close.onclick = function() {
this.parentNode.parentNode.removeChild(this.parentNode);
};
}
function vote() {
var voteDetected_div = document.createElement("div");
voteDetected_div.style.cssText = "position: absolute; top: 0; left: 0; width: 100%; background: #7bbfea; color: #fff; z-index: 9999999999; font-size: 14px; text-align: center; line-height: 1.5; font-weight: bold; padding-top: 6px; padding-bottom: 6px;";
voteDetected_div.innerHTML = "<a style='color:#fff;text-decoration:underline' target='_blank' href='https://www.oschina.net/project/top_cn_2021?id=36'>MyBatis-Plus 正在参与“2021年度 OSC 中国开源项目”评选,请为我们投上宝贵的一票,谢谢!</a>";
document.getElementsByTagName("body")[0].appendChild(voteDetected_div);
voteDetected_div.onclick = function() {
this.remove();
};
}
function docReady(t) {
"complete" === document.readyState ||
"interactive" === document.readyState
? setTimeout(t, 1)
: document.addEventListener("DOMContentLoaded", t);
}
//check if wwads' fire function was blocked after document is ready with 3s timeout (waiting the ad loading)
docReady(function () {
setTimeout(function () {
if( window._AdBlockInit === undefined ){
ABDetected();
}
}, 3000);
});
`]
];

View File

@@ -0,0 +1,94 @@
/** 插入自定义html模块 (可用于插入广告模块等)
* {
* homeSidebarB: htmlString, 首页侧边栏底部
*
* sidebarT: htmlString, 全局左侧边栏顶部
* sidebarB: htmlString, 全局左侧边栏底部
*
* pageT: htmlString, 全局页面顶部
* pageB: htmlString, 全局页面底部
* pageTshowMode: string, 页面顶部-显示方式:未配置默认全局;'article' => 仅文章页①; 'custom' => 仅自定义页①
* pageBshowMode: string, 页面底部-显示方式:未配置默认全局;'article' => 仅文章页①; 'custom' => 仅自定义页①
*
* windowLB: htmlString, 全局左下角②
* windowRB: htmlString, 全局右下角②
* }
*
* ①注:在.md文件front matter配置`article: false`的页面是自定义页,未配置的默认是文章页(首页除外)。
* ②注windowLB 和 windowRB1.展示区块宽高最大是200*200px。2.请给自定义元素定一个不超过200px的固定宽高。3.在屏宽小于960px时无论如何都不会显示。
*/
// Adsense
// module.exports = {
// sidebarB: `<!-- 正方形 -->
// <ins class="adsbygoogle"
// style="display:block"
// data-ad-client="ca-pub-4147143076931995"
// data-ad-slot="1866407052"
// data-ad-format="auto"
// data-full-width-responsive="true"></ins>
// <script>
// (adsbygoogle = window.adsbygoogle || []).push({});
// </script>`,
// pageB: `<!-- 横向自适应 -->
// <ins class="adsbygoogle"
// style="display:block"
// data-ad-client="ca-pub-4147143076931995"
// data-ad-slot="1866407052"
// data-ad-format="auto"
// data-full-width-responsive="true"></ins>
// <script>
// (adsbygoogle = window.adsbygoogle || []).push({});
// </script>`,
// windowRB: `<!-- 固定160*160px -->
// <ins class="adsbygoogle"
// style="display:inline-block;width:160px;height:160px"
// data-ad-client="ca-pub-4147143076931995"
// data-ad-slot="1866407052"></ins>
// <script>
// (adsbygoogle = window.adsbygoogle || []).push({});
// </script>
// `
// };
// 万维
// module.exports = {
// sidebarT: `
//
// `,
// pageT: `
// <div class="wwads-cn wwads-horizontal page-wwads" data-id="135"></div>
// <style>
// .page-wwads{
// width:100%!important;
// min-height: 0;
// margin: 0;
// }
// .page-wwads .wwads-img img{
// width:80px!important;
// }
// .page-wwads .wwads-poweredby{
// width: 40px;
// position: absolute;
// right: 25px;
// bottom: 3px;
// }
// .wwads-content .wwads-text, .page-wwads .wwads-text{
// height: 100%;
// padding-top: 5px;
// display: block;
// }
// </style>
// `,
// windowRB: `
// <ins class="adsbygoogle"
// style="display:block"
// data-ad-client="ca-pub-4147143076931995"
// data-ad-slot="1866407052"
// data-ad-format="auto"
// data-full-width-responsive="true"></ins>
// <script>
// (adsbygoogle = window.adsbygoogle || []).push({});
// </script>
// `
// };

View File

@@ -0,0 +1,26 @@
module.exports = [
{ text: "首页", link: "/" },
{
text: "指南",
link: "/pages/24112f/",
items: [
{ text: "快速入门", link: "/pages/24112f/" },
{ text: "技术文档", link: "/pages/779a6e/" },
]
},
{
text: "配置",
link: "/pages/3b5af0/",
items: [
{ text: "使用配置", link: "/pages/56bac0/" },
]
},
{ text: "生态", link: "/pages/24ae02/" },
{ text: "问答", link: "/pages/f84a74/" },
{ text: "💖支持", link: "/pages/4fedc2/" },
{
text: "🚀起飞诶~~起飞",
link: "/pages/1fedc1/",
},
{ text: "更新日志", link: "https://github.com/969025903/ChopperBot/blob/master/CHANGELOG.md" },
];

View File

@@ -0,0 +1,90 @@
const loveMe = require("./../plugins/love-me");
// Plugin Config
module.exports = [
// 鼠标点击爱心特效
[
loveMe,
{
color: "#11a8cd",
excludeClassName: "theme-vdoing-content"
}
],
// 搜索框第三方搜索
[
"thirdparty-search",
{
thirdparty: [
{
title: "在GitHub中搜索",
frontUrl: "https://github.com/search?q=",
behindUrl: ""
},
{
title: "在Google中搜索",
frontUrl: "https://www.google.com/search?q="
},
{
title: "在Baidu中搜索",
frontUrl: "https://www.baidu.com/s?wd="
}
]
}
],
// 百度统计
[
"vuepress-plugin-baidu-tongji",
{
hm: "577e65b88c06c034335c395caa4b6205"
}
],
// 百度 SEO 优化
["vuepress-plugin-baidu-autopush", {}],
// 代码块复制
[
("one-click-copy",
{
copySelector: [
'div[class*="language-"] pre',
'div[class*="aside-code"] aside'
],
copyMessage: "复制成功",
duration: 1000,
showInMobile: false
})
],
// 图片缩放
[
"vuepress-plugin-zooming",
{
selector: ".theme-vdoing-content img:not(.no-zoom)",
options: {
bgColor: "rgba(0,0,0,0.6)"
}
}
],
// "上次更新"时间格式
[
"@vuepress/last-updated",
{
transformer: (timestamp, lang) => {
const dayjs = require("dayjs"); // https://day.js.org/
return dayjs(timestamp).format("YYYY/MM/DD, HH:mm:ss");
}
}
],
// 谷歌统计
[
"@vuepress/google-analytics",
{
ga: "UA-85414008-1"
}
],
// 网站地图
[
"sitemap",
{
hostname: 'https://baomidou.com',
},
],
];

View File

@@ -0,0 +1,70 @@
const nav = require("./nav.js");
const htmlModules = require("./htmlModules.js");
// Theme Config
module.exports = {
nav,
sidebarDepth: 2,
logo: "/img/logo.svg",
repo: "969025903/ChopperBot",
searchMaxSuggestions: 10,
lastUpdated: "上次更新",
docsRepo: "/twj666/Chopper-Doc",
docsDir: "docs",
docsBranch: "master",
editLinks: true,
editLinkText: "帮助我们改善此页面!",
// Vdoing Theme Config
sidebar: { mode: "structuring", collapsable: false },
updateBar: {
showToArticle: false
},
category: false,
tag: false,
archive: true,
author: {
name: "Genius",
href: "https://github.com/969025903"
},
social: {
icons: [
{
iconClass: "icon-github",
title: "GitHub",
link: "https://github.com/969025903"
},
{
iconClass: "icon-gitee",
title: "Gitee",
link: "https://gitee.com/sbg-genius"
},
{
iconClass: "icon-youjian",
title: "发邮件",
link: "mailto:geniusssbg@gmail.com"
}
]
},
footer: {
createYear: 2016,
copyrightInfo: [
'<a href="https://969025903.github.io/" target="_blank" style="font-weight:bold">TimeMachine Lab</a>',
' | ',
'Sponsored by <a href="https://www.jetbrains.com" target="_blank" style="font-weight:bold">JetBrains</a>',
' | ',
'<a href="http://beian.miit.gov.cn/" target=_blank>渝ICP备2021000141号-1</a>',
'<p>友情链接:',
'<a href="https://969025903.github.io/" target="_blank" style="font-weight:bold">GeniusBlog</a>',
'</p>'
].join('')
},
htmlModules
};

View File

@@ -0,0 +1,98 @@
// import vue from 'vue/dist/vue.esm.browser'
let sidebarArray = [
`<a href="https://www.diboot.com/?from=mp" target="_blank">
<img class="no-zoom" style="width:100%;" src="https://www.diboot.com/diboot_slogon.png">
</a>`,
`<a href="https://www.developers.pub/?from=mp" target="_blank">
<img class="no-zoom" style="width:100%;" src="https://static.developers.pub/86feb94f2aaf474882697919020749c1.png">
</a>`,
`<a href="http://aizuda.com?from=mp" target="_blank">
<img class="no-zoom" style="width:100%;" src="/img/aizuda.png">
</a>`,
`<a href="http://github.crmeb.net/u/MyBatis-Plus" target="_blank">
<img class="no-zoom" style="width:100%;" src="/img/crmeb3.gif">
</a>`
];
export default ({
Vue, // VuePress 正在使用的 Vue 构造函数
options, // 附加到根实例的一些选项
router, // 当前应用的路由实例
siteData, // 站点元数据
isServer // 当前应用配置是处于 服务端渲染 还是 客户端
}) => {
// window.Vue = vue // 使页面中可以使用Vue构造函数 使页面中的vue demo生效
// 用于监控在路由变化时检查广告拦截器 (to主题使用者你可以去掉本文件的所有代码)
if (!isServer) {
router.afterEach(() => {
//check if wwads' fire function was blocked after document is ready with 3s timeout (waiting the ad loading)
docReady(function () {
setTimeout(function () {
if (window._AdBlockInit === undefined) {
ABDetected();
}
}, 3000);
});
setTimeout(() => {
function shuffle(arr) {
var l = arr.length;
var index, temp;
while (l > 0) {
index = Math.floor(Math.random() * l);
temp = arr[l - 1];
arr[l - 1] = arr[index];
arr[index] = temp;
l--;
}
return arr;
}
const sidebarTop = document.querySelector(".sidebar-slot-top");
if (!sidebarTop) return;
sidebarArray = shuffle(sidebarArray);
let _html = `<div style="width:230px;margin:0 auto">
${sidebarArray.slice(0, 4).join("")}
<br/>
<span style='color: gray;font-size: smaller;'>广告采用随机方式显示</span>
<span style='color: #E01E5A;font-size: smaller;font-weight: bolder;float: right'>❤️<a href='/pages/4fedc2/'>成为赞助商</a></span>
</div>`;
sidebarTop.innerHTML = _html;
}, 200);
// 删除事件改为隐藏事件
setTimeout(() => {
const pageAD = document.querySelector(".page-ad");
if (!pageAD) return;
const btnEl = pageAD.querySelector(".wwads-hide");
if (btnEl) {
btnEl.onclick = () => {
pageAD.style.display = "none";
};
}
// 显示广告模块
if (pageAD.style.display === "none") {
pageAD.style.display = "flex";
}
}, 900);
});
}
};
function ABDetected() {
const h = "<style>.wwads-horizontal,.wwads-vertical{background-color:#f4f8fa;padding:5px;min-height:120px;margin-top:20px;box-sizing:border-box;border-radius:3px;font-family:sans-serif;display:flex;min-width:150px;position:relative;overflow:hidden;}.wwads-horizontal{flex-wrap:wrap;justify-content:center}.wwads-vertical{flex-direction:column;align-items:center;padding-bottom:32px}.wwads-horizontal a,.wwads-vertical a{text-decoration:none}.wwads-horizontal .wwads-img,.wwads-vertical .wwads-img{margin:5px}.wwads-horizontal .wwads-content,.wwads-vertical .wwads-content{margin:5px}.wwads-horizontal .wwads-content{flex:130px}.wwads-vertical .wwads-content{margin-top:10px}.wwads-horizontal .wwads-text,.wwads-content .wwads-text{font-size:14px;line-height:1.4;color:#0e1011;-webkit-font-smoothing:antialiased}.wwads-horizontal .wwads-poweredby,.wwads-vertical .wwads-poweredby{display:block;font-size:11px;color:#a6b7bf;margin-top:1em}.wwads-vertical .wwads-poweredby{position:absolute;left:10px;bottom:10px}.wwads-horizontal .wwads-poweredby span,.wwads-vertical .wwads-poweredby span{transition:all 0.2s ease-in-out;margin-left:-1em}.wwads-horizontal .wwads-poweredby span:first-child,.wwads-vertical .wwads-poweredby span:first-child{opacity:0}.wwads-horizontal:hover .wwads-poweredby span,.wwads-vertical:hover .wwads-poweredby span{opacity:1;margin-left:0}.wwads-horizontal .wwads-hide,.wwads-vertical .wwads-hide{position:absolute;right:-23px;bottom:-23px;width:46px;height:46px;border-radius:23px;transition:all 0.3s ease-in-out;cursor:pointer;}.wwads-horizontal .wwads-hide:hover,.wwads-vertical .wwads-hide:hover{background:rgb(0 0 0 /0.05)}.wwads-horizontal .wwads-hide svg,.wwads-vertical .wwads-hide svg{position:absolute;left:10px;top:10px;fill:#a6b7bf}.wwads-horizontal .wwads-hide:hover svg,.wwads-vertical .wwads-hide:hover svg{fill:#3E4546}</style><a href='https://wwads.cn/page/whitelist-wwads' class='wwads-img' target='_blank' rel='nofollow'><img src='https://cdn.jsdelivr.net/gh/xugaoyi/image_store@master/blog/wwads.2a3pidhlh4ys.webp' width='130'></a><div class='wwads-content'><a href='https://wwads.cn/page/whitelist-wwads' class='wwads-text' target='_blank' rel='nofollow'>为了本站的长期运营,请将我们的网站加入广告拦截器的白名单,感谢您的支持!<span style='color: #11a8cd'>如何添加白名单?</span></a><a href='https://wwads.cn/page/end-user-privacy' class='wwads-poweredby' title='万维广告 让广告更优雅,且有用' target='_blank'><span>万维</span><span>广告</span></a></div><a class='wwads-hide' onclick='parentNode.remove()' title='隐藏广告'><svg xmlns='http://www.w3.org/2000/svg' width='6' height='7'><path d='M.879.672L3 2.793 5.121.672a.5.5 0 11.707.707L3.708 3.5l2.12 2.121a.5.5 0 11-.707.707l-2.12-2.12-2.122 2.12a.5.5 0 11-.707-.707l2.121-2.12L.172 1.378A.5.5 0 01.879.672z'></path></svg></a>";
const wwadsEl = document.getElementsByClassName("wwads-cn");
const wwadsContentEl = document.querySelector('.wwads-content');
if (wwadsEl[0] && !wwadsContentEl) {
wwadsEl[0].innerHTML = h;
}
};
//check document ready
function docReady(t) {
"complete" === document.readyState ||
"interactive" === document.readyState
? setTimeout(t, 1)
: document.addEventListener("DOMContentLoaded", t);
}

View File

@@ -0,0 +1,12 @@
const path= require('path');
const LoveMyPlugin = (options={}) => ({
define () {
const COLOR = options.color || "rgb(" + ~~ (255 * Math.random()) + "," + ~~ (255 * Math.random()) + "," + ~~ (255 * Math.random()) + ")"
const EXCLUDECLASS = options.excludeClassName || ''
return {COLOR, EXCLUDECLASS}
},
enhanceAppFiles: [
path.resolve(__dirname, 'love-me.js')
]
});
module.exports = LoveMyPlugin;

View File

@@ -0,0 +1,62 @@
export default () => {
if (typeof window !== "undefined") {
(function(e, t, a) {
function r() {
for (var e = 0; e < s.length; e++) s[e].alpha <= 0 ? (t.body.removeChild(s[e].el), s.splice(e, 1)) : (s[e].y--, s[e].scale += .004, s[e].alpha -= .013, s[e].el.style.cssText = "left:" + s[e].x + "px;top:" + s[e].y + "px;opacity:" + s[e].alpha + ";transform:scale(" + s[e].scale + "," + s[e].scale + ") rotate(45deg);background:" + s[e].color + ";z-index:99999");
requestAnimationFrame(r)
}
function n() {
var t = "function" == typeof e.onclick && e.onclick;
e.onclick = function(e) {
// 过滤指定元素
let mark = true;
EXCLUDECLASS && e.path && e.path.forEach((item) =>{
if(item.nodeType === 1) {
typeof item.className === 'string' && item.className.indexOf(EXCLUDECLASS) > -1 ? mark = false : ''
}
})
if(mark) {
t && t(),
o(e)
}
}
}
function o(e) {
var a = t.createElement("div");
a.className = "heart",
s.push({
el: a,
x: e.clientX - 5,
y: e.clientY - 5,
scale: 1,
alpha: 1,
color: COLOR
}),
t.body.appendChild(a)
}
function i(e) {
var a = t.createElement("style");
a.type = "text/css";
try {
a.appendChild(t.createTextNode(e))
} catch(t) {
a.styleSheet.cssText = e
}
t.getElementsByTagName("head")[0].appendChild(a)
}
// function c() {
// return "rgb(" + ~~ (255 * Math.random()) + "," + ~~ (255 * Math.random()) + "," + ~~ (255 * Math.random()) + ")"
// }
var s = [];
e.requestAnimationFrame = e.requestAnimationFrame || e.webkitRequestAnimationFrame || e.mozRequestAnimationFrame || e.oRequestAnimationFrame || e.msRequestAnimationFrame ||
function(e) {
setTimeout(e, 1e3 / 60)
},
i(".heart{width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: fixed;}.heart:after{top: -5px;}.heart:before{left: -5px;}"),
n(),
r()
})(window, document)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1011 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 60 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

View File

@@ -0,0 +1,79 @@
.home-wrapper .banner .banner-conent .hero h1{
font-size 2.8rem!important
}
//
table
width auto
.page >*:not(.footer),.card-box
box-shadow: none!important
.page
@media (min-width $contentWidth + 80)
padding-top $navbarHeight!important
.home-wrapper .banner .banner-conent
padding 0 2.9rem
box-sizing border-box
.home-wrapper .banner .slide-banner .slide-banner-wrapper .slide-item a
h2
margin-top 2rem
font-size 1.2rem!important
p
padding 0 1rem
//
.gt-container
.gt-ico-tip
&::after
content: '( Win + . ) or ( + + ) open Emoji'
color: #999
.gt-meta
border-color var(--borderColor)!important
.gt-comments-null
color var(--textColor)
opacity .5
.gt-header-textarea
color var(--textColor)
background rgba(180,180,180,0.1)!important
.gt-btn
border-color $accentColor!important
background-color $accentColor!important
.gt-btn-preview
background-color rgba(255,255,255,0)!important
color $accentColor!important
a
color $accentColor!important
.gt-svg svg
fill $accentColor!important
.gt-comment-content,.gt-comment-admin .gt-comment-content
background-color rgba(150,150,150,0.1)!important
&:hover
box-shadow 0 0 25px rgba(150,150,150,.5)!important
.gt-comment-body
color var(--textColor)!important
// qq
.qq
position: relative;
.qq::after
content: "";
background: $accentColor;
color:#fff;
padding: 0 5px;
border-radius: 10px;
font-size:12px;
position: absolute;
top: -4px;
right: -35px;
transform:scale(0.85);
// demo
body .vuepress-plugin-demo-block__wrapper
&,.vuepress-plugin-demo-block__display
border-color rgba(160,160,160,.3)
.vuepress-plugin-demo-block__footer:hover
.vuepress-plugin-demo-block__expand::before
border-top-color: $accentColor !important;
border-bottom-color: $accentColor !important;
svg
fill: $accentColor !important;

View File

@@ -0,0 +1,62 @@
// vdoing使
//***vdoing-***//
// //
// $bannerTextColor = #fff // 首页banner区()
// $accentColor = #11A8CD
// $arrowBgColor = #ccc
// $badgeTipColor = #42b983
// $badgeWarningColor = darken(#ffe564, 35%)
// $badgeErrorColor = #DA5961
// //
// $navbarHeight = 3.6rem
// $sidebarWidth = 18rem
// $contentWidth = 860px
// $homePageWidth = 1100px
// $rightMenuWidth = 230px //
// //
// $lineNumbersWrapperWidth = 2.5rem
//
.theme-mode-light
--bodyBg: rgba(255,255,255,1)
--mainBg: rgba(255,255,255,1)
--sidebarBg: rgba(255,255,255,.8)
--blurBg: rgba(255,255,255,.9)
--textColor: #004050
--textLightenColor: #ef6d48
--borderColor: rgba(0,0,0,.15)
--codeBg: #f6f6f6
--codeColor: #525252
codeThemeLight()
//
.theme-mode-dark
--bodyBg: rgba(30,30,34,1)
--mainBg: rgba(30,30,34,1)
--sidebarBg: rgba(30,30,34,.8)
--blurBg: rgba(30,30,34,.8)
--textColor: rgb(140,140,150)
--textLightenColor: #ef6d48
--borderColor: #2C2C3A
--codeBg: #252526
--codeColor: #fff
codeThemeDark()
//
.theme-mode-read
--bodyBg: rgba(245,245,213,1)
--mainBg: rgba(245,245,213,1)
--sidebarBg: rgba(245,245,213,.8)
--blurBg: rgba(245,245,213,.9)
--textColor: #004050
--textLightenColor: #ef6d48
--borderColor: rgba(0,0,0,.15)
--codeBg: #282c34
--codeColor: #fff
codeThemeDark()

View File

@@ -0,0 +1,39 @@
---
title: 简介
date: 2021-12-14 17:10:38
permalink: /pages/24112f/
article: false
---
[ChopperBot](https://github.com/969025903/ChopperBot) 一款全自动的主播切片机器人,支持模块热度分析, 主播热度分析,智能爬取,弹幕视频爬取,弹幕分析, 自动切片,切片分类,自动标题,自动封面,账号打造,账号管理, 多平台上传等功能
::: tip 愿景
ChopperBot 留下每个主播的精彩片段
:::
<style>
.demo{
padding: 1rem 1.5rem;
border: 1px solid #ddd;
border-radius: 4px;
}
</style>
## 特性
- **跨平台服务**目前支持Douyuhuyab站抖音twitch等热门直播平台
- **热门分析**ChopperBot为您自动分析时下流行元素热门爆火主播紧跟当前热点获取最新直播内容
- **全自动工作**直播爬取自动切片封面生成标题选取内容上传账号管理电脑不用动ChopperBot全自动
- **个性化账号打造**不管是搞笑博主还是精彩集锦ChopperBot为每个账号打造不同的个性化内容生成
- **可视化管理**: 提供可视化管理界面,让您的使用体验更方便。
## 代码托管
> **[Gitee](https://gitee.com/sbg-genius/ChopperBot)** | **[Github](https://github.com/969025903/ChopperBot)**
## 参与贡献
欢迎各路大佬一起来参与完善 Assistant捏我们期待你的 PR
- 贡献代码:代码地址 [ChopperBot](https://github.com/969025903/ChopperBot) ,欢迎提交 Issue 或者 Pull Requests
- 维护文档:文档地址 [ChopperBot-Doc](https://github.com/969025903/ChopperBot-Doc) ,欢迎参与翻译和修订

View File

@@ -0,0 +1,15 @@
---
title: 快速开始
date: 2021-12-14 18:06:39
permalink: /pages/226c21/
article: false
---
正在开发中.....
- console为后端启动模块
- console-ui为前端启动模块

View File

@@ -0,0 +1,80 @@
---
title: FileModule目录
date: 2021-12-14 18:15:59
permalink: /pages/779a6e/
article: false
---
[👉 源码](https://github.com/969025903/ChopperBot)
[[toc]]
## FileCache
::: tip 说明
由于ChopperBot中使用了大量的Json文件来保存配置或数据而有些Json文件可能会被频繁的操作
而FileCache就是用来解决文件的频繁写入造成的IO问题FileCache具备了简单的文件操作功能文件缓存池文件刷入文件定时刷入文件版本对照功能
方便开发人员对文件的操作与管理。
:::
更多详情请移步至 [FileCache](/pages/779a6c/) 查看。
## FileUtil
::: tip 说明
文件的操作工具类
:::
| 方法名称 | 方法说明 | 参数描述 | 返回内容 |
| :-: | :-: | :-: | :-: |
| isFileExist| 判断文件是否存在 | dir(String) 文件路径 | boolean |
| copyFile | 复制文件 | srcPath(String) 源文件路径,destPath(String) 目标文件路径 | File |
| deleteFile | 删除文件 | path(String) 文件根路径, filename(String) 文件名称 | boolean|
| deleteFile | 删除文件 | path(String) 文件路径| boolean |
| deleteDirectory | 删除文件夹,包括文件夹内容<br/> (排除root文件和C:) | path(String) 文件路径 | boolean |
| deleteDirectory | 删除文件夹,包括文件夹内容 | path(String) 文件路径<br/> visit 访问文件时触发该方法<br/> preVisit 访问子目录前触发该方法<br/> postVisit 访问目录之后触发该方法<br/> | boolean |
```java
public void testDelete() throws IOException {
FileUtil.deleteDirectory("E:\\Project\\ChopperBot\\FileModule\\src\\main\\resources\\trash");
}
```
- `更多例子可查看test包下面的samples`
- [FileUtilTest](https://github.com/969025903/ChopperBot/blob/master/FileModule/src/test/java/org/example/util/FileUtilTest.java)
## JsonFileUtil
::: tip 说明
Json文件的操作工具类
:::
| 方法名称 | 方法说明 | 参数描述 | 返回内容 |
| :-: | :-: | :-: | :-: |
| readJsonFile | 读取json文件 | filePath(String) 文件根路径</br> fileName(String) 文件名</br>| Map |
| readJsonFile | 读取json文件 | fullPath(String) 全文件路径</br> | Map |
| readJsonFileToJSONObject | 读取json文件并返回json对象 | filePath(String) 文件根路径</br> fileName(String) 文件名</br>| JsonObject |
| readJsonFileToJSONObject | 读取json文件并返回json对象 | fullPath(String) 全文件路径</br>| JsonObject |
| readJsonFileToObject | 读取json文件并返回对象 | fullPath(String) 全文件路径</br> clazz(Class) 返回类型| T泛型 |
| writeJsonFile | 写入json文件不存在则自动创建 | filePath(String) 文件路径</br> fileName(String) 文件名</br> data(Map) 内容| File |
| writeJsonFile | 写入json文件不存在则自动创建 | fullPath(String) 全文件路径</br> data(Map) 内容 | File |
| writeJsonFileIsExist | 写入json文件,不存在则返回null | filePath(String) 文件路径</br> fileName(String) 文件名</br> data(Map) 内容| File |
| writeJsonFileIsExist | 写入json文件,不存在则返回null | fullPath(String) 全文件路径</br> data(Map) 内容 | File |
| writeBigJsonFile | 写入大json文件 | fullPath(String) 全文件路径</br> data(Map) 内容 | File |
| writeBigJsonFile | 写入大json文件 | fullPath(String) 全文件路径</br> Objs(List) 内容 | File |
```java
public void writeClassInJsonFile() {
Student student = new Student(
"Genius",
18,
"HUST",
"CS",
List.of("Coding", "Reading", "Playing"),
Map.of("QQ", "123456789", "WeChat", "987654321")
);
JsonFileUtil.writeJsonFile("E:\\Project\\ChopperBot\\FileModule\\src\\main\\resources\\", "student.json", student);
JsonFileUtil.writeBigJsonFile("E:\\Project\\ChopperBot\\FileModule\\src\\main\\resources\\student2.json", List.of(student));
JsonFileUtil.writeJsonFileIsExist("E:\\Project\\ChopperBot\\FileModule\\src\\main\\resources\\student3.json", student);
System.out.println(JsonFileUtil.readJsonFileToObject("E:\\Project\\ChopperBot\\FileModule\\src\\main\\resources\\student.json", Student.class));
System.out.println(JsonFileUtil.readJsonFileToObject("E:\\Project\\ChopperBot\\FileModule\\src\\main\\resources\\student2.json",List.class));
}
```
- `更多例子可查看test包下面的samples`
- [JsonFileUtilTest](https://github.com/969025903/ChopperBot/blob/master/FileModule/src/test/java/org/example/util/JsonFileUtilTest.java)

View File

@@ -0,0 +1,131 @@
---
title: FileCache
date: 2021-12-14 18:15:59
permalink: /pages/779a6c/
article: false
---
## FileCache说明
![image](https://mynoteimages.oss-cn-hangzhou.aliyuncs.com/20230519003421323.png)
::: tip 说明
由于ChopperBot中使用了大量的Json文件来保存配置或数据
而有些Json文件可能会被频繁的操作而FileCache就是用来解决文件的频繁写入造成的IO问题FileCache具备了简单的文件操作功能文件缓存池文件刷入文件定时刷入文件版本对照功能
方便开发人员对文件的操作与管理。
:::
- 文件缓冲池写入内容快速写入缓存无需等待IO
- 多种文件sync机制达到缓冲池上限触发sync定时监控进行sync
- 快速的文件操作:快速的查看,修改文件内容
- 文件版本对照机制:比对新老文件版本,减少无意义的刷入
## 使用
### 进行文件缓存
1. 先创建一个类继承ConfigFile类
2. 创建一个FileCache类并将ConfigFile放入Cache中即可
```java
ModuleSrcConfigFile moduleSrcConfigFile = new ModuleSrcConfigFile();
FileCache fileCache = new FileCache(moduleSrcConfigFile);
```
| 构造方法参数 | 说明 |
| :-: | :-: |
| configFile | 要缓存的配置文件 |
| autoSyncTime | 定时刷入文件时间如果为0则不进行定时刷入|
| maxWriteBufferLimit | 当写入的内容大小超过该值时会进行一次文件刷入 |
### 文件缓存操作
| 方法名称 | 描述 |
| :-: | :-: |
| [get](/pages/779a6c/#get-string-keys) | 获取文件缓存内容|
| [writeKeys](/pages/779a6c/#writekeys) | 写入文件缓存内容 |
| [append](/pages/779a6c/#writekeys) | 追加文件缓存内容 |
```json
{
"updateTime": "2023-05-06 04:05:20",
"data": {
"account": {
"src": "./config/account",
"list": [1,2,3,4,5]
}
}
}
```
#### get(String...keys)
##### 方法说明
- keys代表嵌套查询例如上述json文件想获取data下的src只需使用方法```get("account","src")```,注意无需再获取"data"方法中已经包含data的自动获取,
- 如果想获取数组的元素,只需使用方法```get("account","list","0")``` 选择下标即可之后的keys同理
```java
fileCache.get("account","src");
fileCache.get("account","list","2");
```
#### writeKeys(Object data,String...keys)
##### 方法说明
- data: 写入文件的内容写入的内容大小会被FileCache计入
- keys: 和get的参数keys一致只不过要进行数组写入的话比如追加数组内容则采用```writeKeys("account","list",-1)```
```java
fileCache.writeKeys(data,"account","src"); //更改文件内容
fileCache.writeKeys(data,"account","list","0"); //更改数组内容
fileCache.writeKeys(data,"account","list","-1"); //追加数组内容
```
#### append(Object data,String...keys)
##### 方法说明
- data: 追加文件的内容追加的内容大小会被FileCache计入
- keys: 与writeKeys同理
```java
fileCache.append(i,"sectionwork","src","0"); //追加数组的某个元素
fileCache.append(i,"sectionwork","src","-1"); //追加数组
fileCache.append(i,"barrage","src"); //追加类中的元素
```
### 启用文件缓存定时监控
当你文件写入的内容可能不足以填充满缓存池触发写入机制,但你又想自动进行持久化,这个时候你可以将该文件加入到`FileCacheManager`FileCacheManager是专门负责文件定时刷入监控的管理类他负责监听所有加入进来的文件缓存类并进行定时刷入
如果你想要加入你的fileCache你只需按照下述方法加入即可
```java
FileCacheManagerInstance.getInstance().addFileCache(你的文件缓存);
```
如果你想手动刷入缓存可以使用fileCache的`forceSync`方法
```java
fileCache.forceSync()
```
### 全局FileCache
如果你想将FileCache变为全局的且在启动时加入到文件监控管理中你可以在`GlobalFileCache`中写入你的FileCache
```java
public class GlobalFileCache {
public static FileCache ModuleSrcConfigFile;
//写入你的FileCache
static {
try {
//在此初始化
ModuleSrcConfigFile = new FileCache(new ModuleSrcConfigFile());
} catch (FileCacheException e) {
throw new RuntimeException(e);
}
}
//再此添加到文件监控管理队列中
public static List<FileCache> fileCaches
= List.of(ModuleSrcConfigFile);
}
```
## 核心类描述
### FileCache
::: tip 简述
ConfigFile的文件缓存池负责文件内容的缓存与刷入
:::
### FileCacheManager
### FileCacheManagerInstance
### GlobalFileCache
- `更多例子可查看test包下面的samples`
- [FileCacheTest](https://github.com/969025903/ChopperBot/blob/master/FileModule/src/test/java/org/example/cache/FileCacheTest.java)

View File

@@ -0,0 +1,22 @@
---
title: 生态
description: 企业级开源低代码应用开发平台_程序一站式开发管理平台
permalink: /pages/24ae02/
date: 2021-12-14 16:22:37
sidebar: false
article: false
---
## TML研究所其余作品
- [UltimateCache](https://gitee.com/welsir/ultimate-cache) - 致力于开发一个能够用于实际生产的redis注解缓存(开发中)。
- [Assistant](https://gitee.com/969025903/Assistant) - 致力于开发一个后端开发的百宝箱。
## 更多优秀开源作品
[RocketMQ](https://github.com/apache/rocketmq) 查看。
## 团队荣耀
虚空奖杯 🏆🏆🏆🏆🏆

View File

@@ -0,0 +1,15 @@
---
title: 问答
permalink: /pages/f84a74/
date: 2022-11-17 19:01:07
sidebar: false
article: false
---
[[toc]]
## 如何启动ChopperBot
1. console-ui为ChopperBot的前端
2. console为ChopperBot的后端
3. 分别启动前后端即可

View File

@@ -0,0 +1,43 @@
---
title: 支持这个项目
permalink: /pages/4fedc2/
date: 2019-11-16 14:07:31
sidebar: false
article: false
editLink: false
---
## 用爱发电
如果您正在使用这个项目并感觉良好,或者是想支持我们继续开发,您可以通过如下`任意`方式支持我们:
1. Star 并向您的朋友推荐或分享 [ChopperBot](https://github.com/969025903/ChopperBot) 🚀
2. 轻轻点击一次页面右下角(ad) 🙃
3. 通过以下二维码进行一次性捐款,请我喝一杯可乐 🥤
非常感谢! ❤️
::: center
<img align="center" height="400px" src="/img/donate2.png"/>
:::
### 加入ChopperBot开发点击一个小星星
将您的品牌 LOGO 及标语同时展示在:
- GitHub 仓库主页顶部
- 文档官网首页顶部
- 文档官网所有文档页左侧边栏顶部
相关联系方式(添加烦请注明来意):
- QQ[969025903](tencent://message/?uin=969025903&Site=&Menu=yes)
- QQ[燧枫](tencent://message/?uin=369202865&Site=&Menu=yes)
- QQ[Weisir](tencent://message/?uin=1824379011&Site=&Menu=yes)
- QQ[脑洞大开](tencent://message/?uin=647831033&Site=&Menu=yes)
- 邮件:[geniusssbg@gmail.com](mailto:geniusssbg@gmail.com)
- Github[https://github.com/969025903/ChopperBot](https://github.com/969025903/ChopperBot)
## 致谢
感谢给予支持的朋友,您的支持是我们前进的动力 🎉

View File

@@ -0,0 +1,6 @@
---
archivesPage: true
title: 归档
permalink: /blog/
article: false
---

66
doc/docs/index.md Normal file
View File

@@ -0,0 +1,66 @@
---
home: true
heroImage: /img/logo.svg
heroText: ChopperBot
tagline: 🤖自动化切片机器人
actionText: 快速开始 →
actionLink: /pages/24112f/
bannerBg: none
features: # 可选的
- title: 跨平台服务
details: 目前支持Douyuhuyab站抖音twitch等热门直播平台。
- title: 全自动工作
details: 直播爬取自动切片封面生成标题选取内容上传账号管理电脑不用动ChopperBot全自动。
- title: 时下热门分析
details: ChopperBot为您自动分析时下流行元素热门爆火主播紧跟当前热点获取最新直播内容。
postList: none
---
<p align="center">
<a class="become-sponsor" href="/pages/4fedc2">支持这个项目</a>
</p>
<p align="center">
<a class="become-sponsor" href="https://github.com/969025903/ChopperBot">这个项目还在开发中,请加入我们一起开发</a>
</p>
<style>
.become-sponsor{
padding: 8px 20px;
display: inline-block;
color: #ef6d48;
border-radius: 30px;
box-sizing: border-box;
border: 1px solid #ef6d48;
}
</style>
<br/>
### 🤡开发人员
[Genius🤡](https://github.com/969025903)
[twj666🤡](https://github.com/tmlgenius)
[welsir🤡](https://github.com/tmlgenius)
[masteryf🤡](https://github.com/masteryf)
### TML生态圈
- [ChopperBot](https://github.com/969025903/ChopperBot) - 一款后端开发小助手,快速生成代码,快速完成业务。
- [Assistant](https://github.com/969025903/Assistant) - 一款后端开发小助手,快速生成代码,快速完成业务。
### 代码托管
> **[Gitee](https://gitee.com/sbg-genius/ChopperBot)** | **[Github](https://github.com/969025903/ChopperBot)**
### 参与贡献
欢迎各路好汉一起来参与完善 Assistant我们期待你的 PR
- 贡献代码:代码地址 [ChopperBot](https://github.com/969025903/ChopperBot) ,欢迎提交 Issue 或者 Pull Requests
- 维护文档:文档地址 [ChopperBot-Doc](https://github.com/twj666/Chopper-Doc) ,欢迎参与翻译和修订
### 友情链接
- [genius blog](https://969025903.github.io/)

26
doc/package.json Normal file
View File

@@ -0,0 +1,26 @@
{
"name": "mybatis-plus-doc",
"version": "1.0.0",
"scripts": {
"dev": "vuepress dev docs",
"build": "vuepress build docs",
"deploy": "bash deploy.sh",
"updateTheme": "npm uninstall vuepress-theme-vdoing && rm -rf node_modules && npm i && npm i vuepress-theme-vdoing -D",
"editFm": "node utils/editFrontmatter.js"
},
"devDependencies": {
"@vuepress/plugin-google-analytics": "^1.8.2",
"dayjs": "^1.9.7",
"inquirer": "^7.1.0",
"json2yaml": "^1.1.0",
"vuepress": "^1.9.5",
"vuepress-plugin-baidu-tongji": "^1.0.1",
"vuepress-plugin-demo-block": "^0.7.2",
"vuepress-plugin-one-click-copy": "^1.0.2",
"vuepress-plugin-sitemap": "^2.3.1",
"vuepress-plugin-thirdparty-search": "^1.0.2",
"vuepress-plugin-zooming": "^1.1.7",
"vuepress-theme-vdoing": "^1.12.8",
"yamljs": "^0.3.0"
}
}

14
doc/utils/config.yml Normal file
View File

@@ -0,0 +1,14 @@
#批量添加和修改、删除front matter配置文件
# 需要批量处理的路径docs文件夹内的文件夹 (数组。映射路径docs/arr[0]/arr[1] ... )
path:
- docs # 第一个成员必须是docs
# 要删除的字段 (数组)
delete:
# - test
# - tags
# 要添加、修改front matter的数据 front matter中没有的数据则添加已有的数据则覆盖
data:
article: false

View File

@@ -0,0 +1,92 @@
/**
* 批量添加和修改front matter ,需要配置 ./config.yml 文件。
*/
const fs = require('fs'); // 文件模块
const path = require('path'); // 路径模块
const matter = require('gray-matter'); // front matter解析器 https://github.com/jonschlinkert/gray-matter
const jsonToYaml = require('json2yaml')
const yamlToJs = require('yamljs')
const inquirer = require('inquirer') // 命令行操作
const chalk = require('chalk') // 命令行打印美化
const readFileList = require('./modules/readFileList');
const { type, repairDate} = require('./modules/fn');
const log = console.log
const configPath = path.join(__dirname, 'config.yml') // 配置文件的路径
main();
/**
* 主体函数
*/
async function main() {
const promptList = [{
type: "confirm",
message: chalk.yellow('批量操作frontmatter有修改数据的风险确定要继续吗'),
name: "edit",
}];
let edit = true;
await inquirer.prompt(promptList).then(answers => {
edit = answers.edit
})
if(!edit) { // 退出操作
return
}
const config = yamlToJs.load(configPath) // 解析配置文件的数据转为js对象
if (type(config.path) !== 'array') {
log(chalk.red('路径配置有误path字段应该是一个数组'))
return
}
if (config.path[0] !== 'docs') {
log(chalk.red("路径配置有误path数组的第一个成员必须是'docs'"))
return
}
const filePath = path.join(__dirname, '..', ...config.path); // 要批量修改的文件路径
const files = readFileList(filePath); // 读取所有md文件数据
files.forEach(file => {
let dataStr = fs.readFileSync(file.filePath, 'utf8');// 读取每个md文件的内容
const fileMatterObj = matter(dataStr) // 解析md文件的front Matter。 fileMatterObj => {content:'剔除frontmatter后的文件内容字符串', data:{<frontmatter对象>}, ...}
let matterData = fileMatterObj.data; // 得到md文件的front Matter
let mark = false
// 删除操作
if (config.delete) {
if( type(config.delete) !== 'array' ) {
log(chalk.yellow('未能完成删除操作delete字段的值应该是一个数组'))
} else {
config.delete.forEach(item => {
if (matterData[item]) {
delete matterData[item]
mark = true
}
})
}
}
// 添加、修改操作
if (type(config.data) === 'object') {
Object.assign(matterData, config.data) // 将配置数据合并到front Matter对象
mark = true
}
// 有操作时才继续
if (mark) {
if(matterData.date && type(matterData.date) === 'date') {
matterData.date = repairDate(matterData.date) // 修复时间格式
}
const newData = jsonToYaml.stringify(matterData).replace(/\n\s{2}/g,"\n").replace(/"/g,"") + '---\r\n' + fileMatterObj.content;
fs.writeFileSync(file.filePath, newData); // 写入
log(chalk.green(`update frontmatter${file.filePath} `))
}
})
}

21
doc/utils/modules/fn.js Normal file
View File

@@ -0,0 +1,21 @@
// 类型判断
exports.type = function (o){
var s = Object.prototype.toString.call(o)
return s.match(/\[object (.*?)\]/)[1].toLowerCase()
}
// 修复date时区格式的问题
exports.repairDate = function (date) {
date = new Date(date);
return `${date.getUTCFullYear()}-${zero(date.getUTCMonth()+1)}-${zero(date.getUTCDate())} ${zero(date.getUTCHours())}:${zero(date.getUTCMinutes())}:${zero(date.getUTCSeconds())}`;
}
// 日期的格式
exports.dateFormat = function (date) {
return `${date.getFullYear()}-${zero(date.getMonth()+1)}-${zero(date.getDate())} ${zero(date.getHours())}:${zero(date.getMinutes())}:${zero(date.getSeconds())}`
}
// 小于10补0
function zero(d){
return d.toString().padStart(2,'0')
}

View File

@@ -0,0 +1,43 @@
/**
* 读取所有md文件数据
*/
const fs = require('fs'); // 文件模块
const path = require('path'); // 路径模块
const docsRoot = path.join(__dirname, '..', '..', 'docs'); // docs文件路径
function readFileList(dir = docsRoot, filesList = []) {
const files = fs.readdirSync(dir);
files.forEach( (item, index) => {
let filePath = path.join(dir, item);
const stat = fs.statSync(filePath);
if (stat.isDirectory() && item !== '.vuepress') {
readFileList(path.join(dir, item), filesList); //递归读取文件
} else {
if(path.basename(dir) !== 'docs'){ // 过滤docs目录级下的文件
const fileNameArr = path.basename(filePath).split('.')
let name = null, type = null;
if (fileNameArr.length === 2) { // 没有序号的文件
name = fileNameArr[0]
type = fileNameArr[1]
} else if (fileNameArr.length === 3) { // 有序号的文件
name = fileNameArr[1]
type = fileNameArr[2]
} else { // 超过两个‘.’的
log(chalk.yellow(`warning: 该文件 "${filePath}" 没有按照约定命名,将忽略生成相应数据。`))
return
}
if(type === 'md'){ // 过滤非md文件
filesList.push({
name,
filePath
});
}
}
}
});
return filesList;
}
module.exports = readFileList;

8686
doc/yarn.lock Normal file

File diff suppressed because it is too large Load Diff