Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beta9 #9

Merged
merged 12 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# botgo specific
config.yml
config.json
*.db
*.db.lock
*.ini
Expand All @@ -20,4 +21,5 @@ log/
webui/dist/

#ignore data
data/
data/

146 changes: 146 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package config

import (
"encoding/json"
"fmt"
"log"
"os"
"reflect"
)

// 配置文件路径
const configFile = "config.json"

type Config struct {
Account string `json:"account"` // 登入用户名
Password string `json:"password"` // 登入密码
Title string `json:"title"` // 自定义标题
Port string `json:"port"` // WebUI端口
UseHttps bool `json:"useHttps"` // 使用 https
Cert string `json:"cert"` // 证书
Key string `json:"key"` // 密钥
}

type BotInfo struct {
BotID string `json:"botId"` // 机器人的唯一标识
BotNickname string `json:"botNickname"` // 机器人的昵称
BotHead string `json:"botHead"` // 机器人的头像链接
}

type Apis struct {
APIPaths string `json:"apiPaths"` // API地址 检测存活
APINames string `json:"apiNames"` // API名称 一一对应
}

// 默认配置
var defaultConfig = Config{
UseHttps: false,
Cert: "",
Key: "",
Account: "admin",
Password: "admin",
Title: "",
Port: "60123",
}

// readConfig 尝试读取配置文件,如果失败则创建并自动配置默认配置
func ReadConfig() Config {
var config Config

data, err := os.ReadFile(configFile)
if err != nil {
fmt.Println("无法读取配置文件, 正在创建默认配置...")
config = createDefaultConfig()
} else {
err = json.Unmarshal(data, &config)
if err != nil {
fmt.Println("配置解析失败, 正在使用默认配置...")
config = defaultConfig
}
}

// 检查并设置默认值
if checkAndSetDefaults(&config) {
// 如果配置被修改,写回文件
WriteConfigToFile(config)
}

return config
}

// checkAndSetDefaults 检查并设置默认值,返回是否做了修改
func checkAndSetDefaults(config *Config) bool {
// 通过反射获取Config的类型和值
val := reflect.ValueOf(config).Elem()
typ := val.Type()

// 记录是否进行了修改
var modified bool

// 遍历所有字段
for i := 0; i < val.NumField(); i++ {
field := val.Field(i)
defaultField := reflect.ValueOf(defaultConfig).Field(i)
fieldType := field.Type()

// 跳过布尔类型的字段
if fieldType.Kind() == reflect.Bool {
continue
}

fieldName := typ.Field(i).Name

// 特殊处理RestartInterval字段
if fieldName == "RestartInterval" || fieldName == "WhiteCheckTime" || fieldName == "MemoryCleanupInterval" || fieldName == "BackupInterval" || fieldName == "MemoryCheckInterval" {
continue
}

// 如果字段是零值,设置为默认值
if isZeroOfUnderlyingType(field.Interface()) {
field.Set(defaultField)
modified = true
}
}

return modified
}

// isZeroOfUnderlyingType 检查一个值是否为其类型的零值
func isZeroOfUnderlyingType(x interface{}) bool {
return reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
}

// WriteConfigToFile 将配置写回文件
func WriteConfigToFile(config Config) {
configJSON, err := json.MarshalIndent(config, "", " ")
if err != nil {
log.Fatalf("无法序列化配置: %v", err)
}

err = os.WriteFile(configFile, configJSON, 0644)
if err != nil {
log.Fatalf("无法写入配置文件: %v", err)
}
}

// createDefaultConfig 创建一个带有默认值的配置文件,并返回这个配置
func createDefaultConfig() Config {
// 序列化默认配置
data, err := json.MarshalIndent(defaultConfig, "", " ")
if err != nil {
fmt.Println("无法创建默认配置文件:", err)
os.Exit(1)
}

// 将默认配置写入文件
err = os.WriteFile(configFile, data, 0666)
if err != nil {
fmt.Println("无法写入默认配置文件:", err)
os.Exit(1)
}

fmt.Println("默认配置文件已创建:", configFile)

// 返回默认配置
return defaultConfig
}
124 changes: 124 additions & 0 deletions docs/api文档.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# API 调用文档

## 概述
该API接口允许用户通过HTTP请求触发程序,根据传入的参数执行不同的功能。以下是可用的参数列表及其详细说明。

请确保在实际应用中,对所有参数值进行urlencode以避免URL解析错误。

请求需要携带cookie,可从浏览器f12获取.token有效期1个月.文末有cookie获取和设置教程.

如果不提供cookie参数,将会得到{"error":"Unauthorized: Cookie not provided"}报错.

## 参数

### `-a` (HTTP API 的地址)
- **字段名**: `a`
- **类型**: `string`
- **描述**: 指定后端服务的HTTP API地址,用于网络请求。

### `-p` (群列表的文件名)
- **字段名**: `p`
- **类型**: `string`
- **描述**: 指定要读取的群列表txt文件的文件名(不包含.txt后缀)。

### `-w` (要发送的信息)
- **字段名**: `w`
- **类型**: `string`
- **描述**: 指定要发送的消息内容。如果内容包含`.txt`后缀,则尝试从对应的txt文件中读取内容。

### `-d` (每条信息推送时间的间隔)
- **字段名**: `d`
- **类型**: `int`
- **默认值**: `10`
- **描述**: 设置每条消息的推送时间间隔(单位:秒)。

### `-c` (每个群推送的概率)
- **字段名**: `c`
- **类型**: `int`
- **默认值**: `100`
- **描述**: 每个群组推送消息的概率(单位:百分比%)。

### `-h` (显示帮助信息)
- **字段名**: `h`
- **类型**: `bool`
- **默认值**: `false`
- **描述**: 当此参数被设置时,程序将输出帮助信息并退出。

### `-s` (读取-save文件路径)
- **字段名**: `s`
- **类型**: `string`
- **描述**: 指定用于断点续传的-save文件的路径。

### `-g` (gensokyo过滤子频道)
- **字段名**: `g`
- **类型**: `bool`
- **默认值**: `false`
- **描述**: 是否启用gensokyo子频道的过滤。

### `-f` (私聊模式)
- **字段名**: `f`
- **类型**: `bool`
- **默认值**: `false`
- **描述**: 如果设置为true,则模式限定为私聊,不发送群广播信息。

### `-t` (access_token)
- **字段名**: `t`
- **类型**: `string`
- **描述**: 如果设置了HTTP的密钥,则需要此参数来进行验证。

### `-r` (打乱群/好友列表顺序)
- **字段名**: `r`
- **类型**: `bool`
- **默认值**: `false`
- **描述**: 是否打乱群组和好友列表的顺序。

## 示例调用

通过curl发送带参数的请求示例:

```bash
curl "http://localhost:60123/run?p=group_list&w=这是一条消息&d=15&a=http://example.com&c=80&s=savepath&g=true&f=true&t=your_token&r=true"
```

### 获取Cookie

1. 打开浏览器,导航到您的网站。
2. 使用F12键打开开发者工具。
3. 切换到“网络(Network)”标签页。
4. 在网站上触发一个请求(比如登录或加载页面)。
5. 查看网络请求列表,找到任一已发送的请求,点击它。
6. 在请求详情中找到“请求头(Request Headers)”部分,复制`Cookie`字段的内容。

### Python API调用示例

这个示例展示了如何使用Python `requests`库发送一个带有cookie的HTTP GET请求:

```python
import requests

# API的URL
url = 'https://example.com/api/run'

# 需要发送的参数
params = {
'a': 'http://127.0.0.1:42001',
'p': '1716208337-5月20日babyq2',
'w': 'baby.txt',
'd': '10',
'c': '100',
's': '5月20日babyq2',
'g': 'true',
't': 'xyy520499'
}

# 从浏览器获取的cookie字符串
cookies = {
'session_token': 'your_copied_cookie_here' # 替换成从浏览器复制的cookie值
}

# 发送请求
response = requests.get(url, params=params, cookies=cookies)

# 输出响应内容
print(response.text)
```
9 changes: 9 additions & 0 deletions front/gsk-bd-front/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
8 changes: 8 additions & 0 deletions front/gsk-bd-front/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/dist
/src-capacitor
/src-cordova
/.quasar
/node_modules
.eslintrc.js
/src-ssr
/quasar.config.*.temporary.compiled*
90 changes: 90 additions & 0 deletions front/gsk-bd-front/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
module.exports = {
// https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy
// This option interrupts the configuration hierarchy at this file
// Remove this if you have an higher level ESLint config file (it usually happens into a monorepos)
root: true,

// https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser
// Must use parserOptions instead of "parser" to allow vue-eslint-parser to keep working
// `parser: 'vue-eslint-parser'` is already included with any 'plugin:vue/**' config and should be omitted
parserOptions: {
parser: require.resolve('@typescript-eslint/parser'),
extraFileExtensions: [ '.vue' ]
},

env: {
browser: true,
es2021: true,
node: true,
'vue/setup-compiler-macros': true
},

// Rules order is important, please avoid shuffling them
extends: [
// Base ESLint recommended rules
// 'eslint:recommended',

// https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#usage
// ESLint typescript rules
'plugin:@typescript-eslint/recommended',

// Uncomment any of the lines below to choose desired strictness,
// but leave only one uncommented!
// See https://eslint.vuejs.org/rules/#available-rules
'plugin:vue/vue3-essential', // Priority A: Essential (Error Prevention)
// 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability)
// 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead)

// https://github.com/prettier/eslint-config-prettier#installation
// usage with Prettier, provided by 'eslint-config-prettier'.
'prettier'
],

plugins: [
// required to apply rules which need type information
'@typescript-eslint',

// https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-files
// required to lint *.vue files
'vue'

// https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509292674
// Prettier has not been included as plugin to avoid performance impact
// add it as an extension for your IDE

],

globals: {
ga: 'readonly', // Google Analytics
cordova: 'readonly',
__statics: 'readonly',
__QUASAR_SSR__: 'readonly',
__QUASAR_SSR_SERVER__: 'readonly',
__QUASAR_SSR_CLIENT__: 'readonly',
__QUASAR_SSR_PWA__: 'readonly',
process: 'readonly',
Capacitor: 'readonly',
chrome: 'readonly'
},

// add your custom rules here
rules: {

'prefer-promise-reject-errors': 'off',

quotes: ['warn', 'single', { avoidEscape: true }],

// this rule, if on, would require explicit return type on the `render` function
'@typescript-eslint/explicit-function-return-type': 'off',

// in plain CommonJS modules, you can't use `import foo = require('foo')` to pass this rule, so it has to be disabled
'@typescript-eslint/no-var-requires': 'off',

// The core 'no-unused-vars' rules (in the eslint:recommended ruleset)
// does not work with type definitions
'no-unused-vars': 'off',

// allow debugger during development only
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
}
}
Loading
Loading