mirror of
https://gitcode.com/JianFeeeee/homeagent-sdk.git
synced 2026-09-20 08:58:03 +00:00
1335 lines
45 KiB
Go
1335 lines
45 KiB
Go
package main
|
||
|
||
import (
|
||
"bytes"
|
||
"encoding/json"
|
||
"fmt"
|
||
"io"
|
||
"log"
|
||
"mime/multipart"
|
||
"net/http"
|
||
"os"
|
||
"strings"
|
||
"time"
|
||
|
||
sdk "gitcode.com/JianFeeeee/homeagent-sdk/sdk"
|
||
)
|
||
|
||
type Plugin struct {
|
||
name string
|
||
sdk *sdk.PluginSDK
|
||
http *http.Client
|
||
baseURL string
|
||
token string
|
||
resetToken string
|
||
}
|
||
|
||
func NewPlugin(name string, config map[string]interface{}) (sdk.Plugin, error) {
|
||
return &Plugin{name: name}, nil
|
||
}
|
||
|
||
func NewPluginFactory(name string, config map[string]interface{}) (sdk.Plugin, error) {
|
||
return &Plugin{name: name}, nil
|
||
}
|
||
|
||
func (p *Plugin) Name() string { return p.name }
|
||
|
||
func getSetting(s sdk.SettingsAPI, key string, fallback string) string {
|
||
v, err := s.Get(key)
|
||
if err != nil || v == nil {
|
||
return fallback
|
||
}
|
||
if sv, ok := v.(string); ok {
|
||
return sv
|
||
}
|
||
return fallback
|
||
}
|
||
|
||
func readArg(args map[string]interface{}, key string) string {
|
||
if v, ok := args[key]; ok && v != nil {
|
||
if s, ok := v.(string); ok {
|
||
return s
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func readArgInt(args map[string]interface{}, key string, fallback int) int {
|
||
if v, ok := args[key]; ok && v != nil {
|
||
switch n := v.(type) {
|
||
case float64:
|
||
return int(n)
|
||
case int64:
|
||
return int(n)
|
||
}
|
||
}
|
||
return fallback
|
||
}
|
||
|
||
func readArgBool(args map[string]interface{}, key string) *bool {
|
||
if v, ok := args[key]; ok {
|
||
if b, ok := v.(bool); ok {
|
||
return &b
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func errResult(msg string) map[string]interface{} {
|
||
return map[string]interface{}{"isError": true, "content": msg}
|
||
}
|
||
|
||
func (p *Plugin) Start(s *sdk.PluginSDK) error {
|
||
p.sdk = s
|
||
s.SetAutoRestart(true)
|
||
|
||
s.Settings().RegisterDef(sdk.ConfigDef{
|
||
Key: "url", Default: "https://blog.jianfgit.xyz", Type: "string",
|
||
DisplayName: "VanBlog URL", Description: "VanBlog 站点基地址",
|
||
Category: "vanblog",
|
||
})
|
||
s.Settings().RegisterDef(sdk.ConfigDef{
|
||
Key: "token", Default: "", Type: "password",
|
||
DisplayName: "API Token", Description: "管理员 API Token(长期令牌,从后台 Token 管理创建)",
|
||
Category: "vanblog",
|
||
})
|
||
s.Settings().RegisterDef(sdk.ConfigDef{
|
||
Key: "reset_token", Default: "", Type: "password",
|
||
DisplayName: "重置密码 Token", Description: "用于 auth/restore 重置管理员密码的特殊 Token",
|
||
Category: "vanblog",
|
||
})
|
||
|
||
p.http = &http.Client{Timeout: 30 * time.Second}
|
||
p.baseURL = strings.TrimRight(getSetting(s.Settings(), "url", "https://blog.jianfgit.xyz"), "/")
|
||
p.token = getSetting(s.Settings(), "token", "")
|
||
p.resetToken = getSetting(s.Settings(), "reset_token", "")
|
||
|
||
if p.token == "" {
|
||
if coreVal, err := s.Settings().GetCore("plugin.vanblog.token"); err == nil && coreVal != nil {
|
||
if sv, ok := coreVal.(string); ok && sv != "" {
|
||
p.token = sv
|
||
s.Settings().Set("token", sv)
|
||
s.Settings().SetCore("plugin.vanblog.token", nil)
|
||
log.Printf("[vanblog] migrated token from core config to plugin config")
|
||
}
|
||
}
|
||
}
|
||
|
||
tp := p.name + "_"
|
||
|
||
s.RegisterTool(tp+"list_articles", sdk.ToolDef{
|
||
Name: tp + "list_articles", Description: "列出 VanBlog 文章,支持分页和搜索",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"page": map[string]interface{}{"type": "integer", "description": "页码从1开始", "default": 1},
|
||
"pageSize": map[string]interface{}{"type": "integer", "description": "每页条数", "default": 50},
|
||
"keyword": map[string]interface{}{"type": "string", "description": "搜索关键词"},
|
||
"category": map[string]interface{}{"type": "string", "description": "按分类筛选"},
|
||
"tag": map[string]interface{}{"type": "string", "description": "按标签筛选"},
|
||
"sort": map[string]interface{}{"type": "string", "description": "排序: newest|oldest"},
|
||
},
|
||
},
|
||
}, p.handleListArticles)
|
||
|
||
s.RegisterTool(tp+"get_article", sdk.ToolDef{
|
||
Name: tp + "get_article", Description: "获取单篇文章完整内容",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"id": map[string]interface{}{"type": "string", "description": "文章 ID 或 pathname"},
|
||
}, "required": []string{"id"},
|
||
},
|
||
}, p.handleGetArticle)
|
||
|
||
s.RegisterTool(tp+"create_article", sdk.ToolDef{
|
||
Name: tp + "create_article", Description: "新建文章,title 和 category 必填",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"title": map[string]interface{}{"type": "string", "description": "标题"},
|
||
"content": map[string]interface{}{"type": "string", "description": "Markdown 正文"},
|
||
"category": map[string]interface{}{"type": "string", "description": "分类"},
|
||
"tags": map[string]interface{}{"type": "string", "description": "标签逗号分隔"},
|
||
"pinned": map[string]interface{}{"type": "boolean", "description": "置顶"},
|
||
}, "required": []string{"title", "category"},
|
||
},
|
||
}, p.handleCreateArticle)
|
||
|
||
s.RegisterTool(tp+"update_article", sdk.ToolDef{
|
||
Name: tp + "update_article", Description: "更新文章,只传需改字段",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"id": map[string]interface{}{"type": "string", "description": "文章 ID"},
|
||
"title": map[string]interface{}{"type": "string", "description": "新标题"},
|
||
"content": map[string]interface{}{"type": "string", "description": "新正文"},
|
||
"category": map[string]interface{}{"type": "string", "description": "新分类"},
|
||
"tags": map[string]interface{}{"type": "string", "description": "新标签逗号分隔"},
|
||
"pinned": map[string]interface{}{"type": "boolean", "description": "置顶"},
|
||
}, "required": []string{"id"},
|
||
},
|
||
}, p.handleUpdateArticle)
|
||
|
||
s.RegisterTool(tp+"delete_article", sdk.ToolDef{
|
||
Name: tp + "delete_article", Description: "删除文章(软删除)",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"id": map[string]interface{}{"type": "string", "description": "文章 ID"},
|
||
}, "required": []string{"id"},
|
||
},
|
||
}, p.handleDeleteArticle)
|
||
|
||
s.RegisterTool(tp+"search_articles", sdk.ToolDef{
|
||
Name: tp + "search_articles", Description: "按链接搜索文章",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"link": map[string]interface{}{"type": "string", "description": "文章链接"},
|
||
}, "required": []string{"link"},
|
||
},
|
||
}, p.handleSearchArticles)
|
||
|
||
s.RegisterTool(tp+"manage_drafts", sdk.ToolDef{
|
||
Name: tp + "manage_drafts",
|
||
Description: "管理草稿。命令: list|get|create|update|delete|publish",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "list|get|create|update|delete|publish"},
|
||
"id": map[string]interface{}{"type": "string", "description": "草稿ID(get/update/delete/publish需要)"},
|
||
"title": map[string]interface{}{"type": "string", "description": "标题(create/update)"},
|
||
"content": map[string]interface{}{"type": "string", "description": "正文(create/update)"},
|
||
"category": map[string]interface{}{"type": "string", "description": "分类(create/update)"},
|
||
"tags": map[string]interface{}{"type": "string", "description": "标签逗号分隔(create/update)"},
|
||
"page": map[string]interface{}{"type": "integer", "description": "页码(list)"},
|
||
"pageSize": map[string]interface{}{"type": "integer", "description": "每页条数(list)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageDrafts)
|
||
|
||
s.RegisterTool(tp+"manage_categories", sdk.ToolDef{
|
||
Name: tp + "manage_categories",
|
||
Description: "管理分类。命令: list|get|create|update|delete",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "list|get|create|update|delete"},
|
||
"name": map[string]interface{}{"type": "string", "description": "分类名(get/create/update/delete需要)"},
|
||
"newName": map[string]interface{}{"type": "string", "description": "新名称(update)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageCategories)
|
||
|
||
s.RegisterTool(tp+"manage_tags", sdk.ToolDef{
|
||
Name: tp + "manage_tags",
|
||
Description: "管理标签。命令: list|get|rename|delete",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "list|get|rename|delete"},
|
||
"name": map[string]interface{}{"type": "string", "description": "标签名"},
|
||
"newName": map[string]interface{}{"type": "string", "description": "新名称(rename)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageTags)
|
||
|
||
s.RegisterTool(tp+"manage_images", sdk.ToolDef{
|
||
Name: tp + "manage_images",
|
||
Description: "管理图床图片。命令: list|all|upload|scan|export|delete|delete_all",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "list|all|upload|scan|export|delete|delete_all"},
|
||
"page": map[string]interface{}{"type": "integer", "description": "页码(list)"},
|
||
"pageSize": map[string]interface{}{"type": "integer", "description": "每页条数(list)"},
|
||
"file": map[string]interface{}{"type": "string", "description": "本地文件路径(upload)"},
|
||
"sign": map[string]interface{}{"type": "string", "description": "图片签名(delete)"},
|
||
"type": map[string]interface{}{"type": "string", "description": "图片类型(upload: favicon/watermark/空)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageImages)
|
||
|
||
s.RegisterTool(tp+"manage_links", sdk.ToolDef{
|
||
Name: tp + "manage_links",
|
||
Description: "管理友情链接。命令: list|create|update|delete",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "list|create|update|delete"},
|
||
"data": map[string]interface{}{"type": "string", "description": "JSON数据(create/update)"},
|
||
"name": map[string]interface{}{"type": "string", "description": "链接名(delete)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageLinks)
|
||
|
||
s.RegisterTool(tp+"manage_social", sdk.ToolDef{
|
||
Name: tp + "manage_social",
|
||
Description: "管理社交链接。命令: list|types|create|update|delete",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "list|types|create|update|delete"},
|
||
"data": map[string]interface{}{"type": "string", "description": "JSON数据(create/update)"},
|
||
"stype": map[string]interface{}{"type": "string", "description": "社交类型(delete)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageSocial)
|
||
|
||
s.RegisterTool(tp+"manage_rewards", sdk.ToolDef{
|
||
Name: tp + "manage_rewards",
|
||
Description: "管理打赏设置。命令: list|create|update|delete",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "list|create|update|delete"},
|
||
"data": map[string]interface{}{"type": "string", "description": "JSON数据(create/update)"},
|
||
"name": map[string]interface{}{"type": "string", "description": "打赏项名(delete)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageRewards)
|
||
|
||
s.RegisterTool(tp+"manage_pages", sdk.ToolDef{
|
||
Name: tp + "manage_pages",
|
||
Description: "管理自定义页面。命令: list|get|create|update|delete|folder|file|upload|create_file|create_folder|update_file",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "list|get|create|update|delete|folder|file|upload|create_file|create_folder|update_file"},
|
||
"path": map[string]interface{}{"type": "string", "description": "页面路径"},
|
||
"data": map[string]interface{}{"type": "string", "description": "JSON数据(create/update)"},
|
||
"folder": map[string]interface{}{"type": "string", "description": "文件夹路径(folder/file相关)"},
|
||
"file": map[string]interface{}{"type": "string", "description": "文件路径(file/upload相关)"},
|
||
"content": map[string]interface{}{"type": "string", "description": "文件内容(create_file/update_file)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManagePages)
|
||
|
||
s.RegisterTool(tp+"manage_settings", sdk.ToolDef{
|
||
Name: tp + "manage_settings",
|
||
Description: "管理站点设置。命令: get_static|set_static|get_waline|set_waline|get_layout|set_layout|get_login|set_login",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "get_static|set_static|get_waline|set_waline|get_layout|set_layout|get_login|set_login"},
|
||
"data": map[string]interface{}{"type": "string", "description": "JSON设置数据(set_*命令)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageSettings)
|
||
|
||
s.RegisterTool(tp+"manage_about", sdk.ToolDef{
|
||
Name: tp + "manage_about",
|
||
Description: "管理关于页。命令: get|update",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "get|update"},
|
||
"content": map[string]interface{}{"type": "string", "description": "关于页内容(update)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageAbout)
|
||
|
||
s.RegisterTool(tp+"manage_site", sdk.ToolDef{
|
||
Name: tp + "manage_site",
|
||
Description: "管理站点信息。命令: get|update",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "get|update"},
|
||
"data": map[string]interface{}{"type": "string", "description": "JSON站点数据(update)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageSite)
|
||
|
||
s.RegisterTool(tp+"manage_menu", sdk.ToolDef{
|
||
Name: tp + "manage_menu",
|
||
Description: "管理导航菜单。命令: get|update",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "get|update"},
|
||
"data": map[string]interface{}{"type": "string", "description": "JSON菜单数据(update)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageMenu)
|
||
|
||
s.RegisterTool(tp+"get_analysis", sdk.ToolDef{
|
||
Name: tp + "get_analysis", Description: "获取访问统计数据",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"tab": map[string]interface{}{"type": "string", "description": "overview|viewer|article", "default": "overview"},
|
||
},
|
||
},
|
||
}, p.handleGetAnalysis)
|
||
|
||
s.RegisterTool(tp+"get_logs", sdk.ToolDef{
|
||
Name: tp + "get_logs", Description: "获取系统日志",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"page": map[string]interface{}{"type": "integer", "description": "页码"},
|
||
"pageSize": map[string]interface{}{"type": "integer", "description": "每页条数"},
|
||
"event": map[string]interface{}{"type": "string", "description": "按事件类型筛选"},
|
||
},
|
||
},
|
||
}, p.handleGetLogs)
|
||
|
||
s.RegisterTool(tp+"manage_backup", sdk.ToolDef{
|
||
Name: tp + "manage_backup",
|
||
Description: "备份管理。命令: export|import",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "export|import"},
|
||
"file": map[string]interface{}{"type": "string", "description": "备份JSON文件路径(import)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageBackup)
|
||
|
||
s.RegisterTool(tp+"manage_caddy", sdk.ToolDef{
|
||
Name: tp + "manage_caddy",
|
||
Description: "管理Caddy配置。命令: get_https|set_https|get_log|clear_log|get_config",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "get_https|set_https|get_log|clear_log|get_config"},
|
||
"data": map[string]interface{}{"type": "string", "description": "JSON数据(set_https)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageCaddy)
|
||
|
||
s.RegisterTool(tp+"manage_isr", sdk.ToolDef{
|
||
Name: tp + "manage_isr",
|
||
Description: "ISR增量渲染。命令: get|trigger|update",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "get|trigger|update"},
|
||
"data": map[string]interface{}{"type": "string", "description": "JSON数据(update)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageISR)
|
||
|
||
s.RegisterTool(tp+"manage_pipelines", sdk.ToolDef{
|
||
Name: tp + "manage_pipelines",
|
||
Description: "管理流水线。命令: list|get|config|create|trigger|update|delete",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "list|get|config|create|trigger|update|delete"},
|
||
"id": map[string]interface{}{"type": "string", "description": "流水线ID(get/trigger/update/delete)"},
|
||
"data": map[string]interface{}{"type": "string", "description": "JSON数据(create/update)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManagePipelines)
|
||
|
||
s.RegisterTool(tp+"manage_collaborators", sdk.ToolDef{
|
||
Name: tp + "manage_collaborators",
|
||
Description: "管理协作者。命令: list|list_all|create|update|delete",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "list|list_all|create|update|delete"},
|
||
"data": map[string]interface{}{"type": "string", "description": "JSON数据(create/update)"},
|
||
"id": map[string]interface{}{"type": "string", "description": "协作者ID(delete)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageCollaborators)
|
||
|
||
s.RegisterTool(tp+"manage_tokens", sdk.ToolDef{
|
||
Name: tp + "manage_tokens",
|
||
Description: "管理API Token。命令: list|create|delete",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "list|create|delete"},
|
||
"id": map[string]interface{}{"type": "string", "description": "Token ID(delete)"},
|
||
"expiresIn": map[string]interface{}{"type": "integer", "description": "有效期毫秒(create,默认1年)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleManageTokens)
|
||
|
||
s.RegisterTool(tp+"auth", sdk.ToolDef{
|
||
Name: tp + "auth",
|
||
Description: "VanBlog认证。命令: login|logout|restore|update",
|
||
Parameters: map[string]interface{}{
|
||
"type": "object", "properties": map[string]interface{}{
|
||
"command": map[string]interface{}{"type": "string", "description": "login|logout|restore|update"},
|
||
"username": map[string]interface{}{"type": "string", "description": "用户名(login)"},
|
||
"password": map[string]interface{}{"type": "string", "description": "密码(login/restore/update)"},
|
||
"newName": map[string]interface{}{"type": "string", "description": "新用户名(update)"},
|
||
"newPassword": map[string]interface{}{"type": "string", "description": "新密码(update)"},
|
||
}, "required": []string{"command"},
|
||
},
|
||
}, p.handleAuth)
|
||
|
||
s.RegisterTool(tp+"get_meta", sdk.ToolDef{
|
||
Name: tp + "get_meta", Description: "获取VanBlog元信息(版本、站点等)",
|
||
Parameters: map[string]interface{}{"type": "object", "properties": map[string]interface{}{}},
|
||
}, p.handleGetMeta)
|
||
|
||
log.Printf("[vanblog] started: %s (url=%s, token=%t)", p.name, p.baseURL, p.token != "")
|
||
return nil
|
||
}
|
||
|
||
func (p *Plugin) Stop() error { return nil }
|
||
|
||
func (p *Plugin) do(method, path string, body interface{}) (interface{}, error) {
|
||
return p.doRaw(method, path, body, nil)
|
||
}
|
||
|
||
func (p *Plugin) doRaw(method, path string, body interface{}, headers map[string]string) (interface{}, error) {
|
||
url := p.baseURL + path
|
||
var reqBody io.Reader
|
||
if body != nil {
|
||
b, _ := json.Marshal(body)
|
||
reqBody = bytes.NewReader(b)
|
||
}
|
||
req, err := http.NewRequest(method, url, reqBody)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("请求失败: %w", err)
|
||
}
|
||
if p.token != "" {
|
||
req.Header.Set("token", p.token)
|
||
}
|
||
if body != nil {
|
||
req.Header.Set("Content-Type", "application/json")
|
||
}
|
||
for k, v := range headers {
|
||
req.Header.Set(k, v)
|
||
}
|
||
resp, err := p.http.Do(req)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("请求失败: %w", err)
|
||
}
|
||
defer resp.Body.Close()
|
||
raw, _ := io.ReadAll(resp.Body)
|
||
if resp.StatusCode >= 400 {
|
||
return nil, fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(raw))
|
||
}
|
||
var result interface{}
|
||
if err := json.Unmarshal(raw, &result); err != nil {
|
||
return string(raw), nil
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
func jsonArg(args map[string]interface{}, key string) (map[string]interface{}, bool) {
|
||
s := readArg(args, key)
|
||
if s == "" {
|
||
return nil, false
|
||
}
|
||
var m map[string]interface{}
|
||
if json.Unmarshal([]byte(s), &m) != nil {
|
||
return nil, false
|
||
}
|
||
return m, true
|
||
}
|
||
|
||
// ======== Article Handlers ========
|
||
|
||
func (p *Plugin) handleListArticles(args map[string]interface{}) (interface{}, error) {
|
||
page := readArgInt(args, "page", 1)
|
||
pageSize := readArgInt(args, "pageSize", 50)
|
||
path := fmt.Sprintf("/api/admin/article?page=%d&pageSize=%d", page, pageSize)
|
||
if v := readArg(args, "keyword"); v != "" {
|
||
path += "&keyword=" + v
|
||
}
|
||
if v := readArg(args, "category"); v != "" {
|
||
path += "&category=" + v
|
||
}
|
||
if v := readArg(args, "tag"); v != "" {
|
||
path += "&tag=" + v
|
||
}
|
||
if v := readArg(args, "sort"); v != "" {
|
||
path += "&sort=" + v
|
||
}
|
||
return p.do("GET", path, nil)
|
||
}
|
||
|
||
func (p *Plugin) handleGetArticle(args map[string]interface{}) (interface{}, error) {
|
||
id := readArg(args, "id")
|
||
if id == "" {
|
||
return errResult("id 不能为空"), nil
|
||
}
|
||
return p.do("GET", "/api/admin/article/"+id, nil)
|
||
}
|
||
|
||
func (p *Plugin) handleCreateArticle(args map[string]interface{}) (interface{}, error) {
|
||
title := readArg(args, "title")
|
||
category := readArg(args, "category")
|
||
if title == "" || category == "" {
|
||
return errResult("title 和 category 不能为空"), nil
|
||
}
|
||
body := map[string]interface{}{"title": title, "category": category}
|
||
if v := readArg(args, "content"); v != "" {
|
||
body["content"] = v
|
||
}
|
||
if v := readArg(args, "tags"); v != "" {
|
||
body["tags"] = strings.Split(v, ",")
|
||
}
|
||
if v := readArgBool(args, "pinned"); v != nil {
|
||
body["pinned"] = *v
|
||
}
|
||
return p.do("POST", "/api/admin/article", body)
|
||
}
|
||
|
||
func (p *Plugin) handleUpdateArticle(args map[string]interface{}) (interface{}, error) {
|
||
id := readArg(args, "id")
|
||
if id == "" {
|
||
return errResult("id 不能为空"), nil
|
||
}
|
||
body := map[string]interface{}{}
|
||
if v := readArg(args, "title"); v != "" {
|
||
body["title"] = v
|
||
}
|
||
if v := readArg(args, "content"); v != "" {
|
||
body["content"] = v
|
||
}
|
||
if v := readArg(args, "category"); v != "" {
|
||
body["category"] = v
|
||
}
|
||
if v := readArg(args, "tags"); v != "" {
|
||
body["tags"] = strings.Split(v, ",")
|
||
}
|
||
if v := readArgBool(args, "pinned"); v != nil {
|
||
body["pinned"] = *v
|
||
}
|
||
return p.do("PUT", "/api/admin/article/"+id, body)
|
||
}
|
||
|
||
func (p *Plugin) handleDeleteArticle(args map[string]interface{}) (interface{}, error) {
|
||
id := readArg(args, "id")
|
||
if id == "" {
|
||
return errResult("id 不能为空"), nil
|
||
}
|
||
return p.do("DELETE", "/api/admin/article/"+id, nil)
|
||
}
|
||
|
||
func (p *Plugin) handleSearchArticles(args map[string]interface{}) (interface{}, error) {
|
||
link := readArg(args, "link")
|
||
if link == "" {
|
||
return errResult("link 不能为空"), nil
|
||
}
|
||
return p.do("POST", "/api/admin/article/searchByLink", map[string]interface{}{"link": link})
|
||
}
|
||
|
||
// ======== Draft ========
|
||
|
||
func (p *Plugin) handleManageDrafts(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "list":
|
||
page := readArgInt(args, "page", 1)
|
||
pageSize := readArgInt(args, "pageSize", 50)
|
||
return p.do("GET", fmt.Sprintf("/api/admin/draft?page=%d&pageSize=%d", page, pageSize), nil)
|
||
case "get":
|
||
id := readArg(args, "id")
|
||
if id == "" {
|
||
return errResult("id 不能为空"), nil
|
||
}
|
||
return p.do("GET", "/api/admin/draft/"+id, nil)
|
||
case "create":
|
||
body := map[string]interface{}{}
|
||
if v := readArg(args, "title"); v != "" {
|
||
body["title"] = v
|
||
}
|
||
if v := readArg(args, "content"); v != "" {
|
||
body["content"] = v
|
||
}
|
||
if v := readArg(args, "category"); v != "" {
|
||
body["category"] = v
|
||
}
|
||
if v := readArg(args, "tags"); v != "" {
|
||
body["tags"] = strings.Split(v, ",")
|
||
}
|
||
return p.do("POST", "/api/admin/draft", body)
|
||
case "update":
|
||
id := readArg(args, "id")
|
||
if id == "" {
|
||
return errResult("id 不能为空"), nil
|
||
}
|
||
body := map[string]interface{}{}
|
||
if v := readArg(args, "title"); v != "" {
|
||
body["title"] = v
|
||
}
|
||
if v := readArg(args, "content"); v != "" {
|
||
body["content"] = v
|
||
}
|
||
if v := readArg(args, "category"); v != "" {
|
||
body["category"] = v
|
||
}
|
||
if v := readArg(args, "tags"); v != "" {
|
||
body["tags"] = strings.Split(v, ",")
|
||
}
|
||
return p.do("PUT", "/api/admin/draft/"+id, body)
|
||
case "delete":
|
||
id := readArg(args, "id")
|
||
if id == "" {
|
||
return errResult("id 不能为空"), nil
|
||
}
|
||
return p.do("DELETE", "/api/admin/draft/"+id, nil)
|
||
case "publish":
|
||
id := readArg(args, "id")
|
||
if id == "" {
|
||
return errResult("id 不能为空"), nil
|
||
}
|
||
return p.do("POST", "/api/admin/draft/publish", map[string]interface{}{"id": id})
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Category ========
|
||
|
||
func (p *Plugin) handleManageCategories(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "list":
|
||
return p.do("GET", "/api/admin/category/all", nil)
|
||
case "get":
|
||
name := readArg(args, "name")
|
||
if name == "" {
|
||
return errResult("name 不能为空"), nil
|
||
}
|
||
return p.do("GET", "/api/admin/category/"+name, nil)
|
||
case "create":
|
||
name := readArg(args, "name")
|
||
if name == "" {
|
||
return errResult("name 不能为空"), nil
|
||
}
|
||
return p.do("POST", "/api/admin/category", map[string]interface{}{"name": name})
|
||
case "update":
|
||
name := readArg(args, "name")
|
||
if name == "" {
|
||
return errResult("name 不能为空"), nil
|
||
}
|
||
newName := readArg(args, "newName")
|
||
return p.do("PUT", "/api/admin/category/"+name, map[string]interface{}{"name": newName})
|
||
case "delete":
|
||
name := readArg(args, "name")
|
||
if name == "" {
|
||
return errResult("name 不能为空"), nil
|
||
}
|
||
return p.do("DELETE", "/api/admin/category/"+name, nil)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Tag ========
|
||
|
||
func (p *Plugin) handleManageTags(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "list":
|
||
return p.do("GET", "/api/admin/tag/all", nil)
|
||
case "get":
|
||
name := readArg(args, "name")
|
||
if name == "" {
|
||
return errResult("name 不能为空"), nil
|
||
}
|
||
return p.do("GET", "/api/admin/tag/"+name, nil)
|
||
case "rename":
|
||
name := readArg(args, "name")
|
||
newName := readArg(args, "newName")
|
||
if name == "" || newName == "" {
|
||
return errResult("name 和 newName 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/tag/"+name, map[string]interface{}{"name": newName})
|
||
case "delete":
|
||
name := readArg(args, "name")
|
||
if name == "" {
|
||
return errResult("name 不能为空"), nil
|
||
}
|
||
return p.do("DELETE", "/api/admin/tag/"+name, nil)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Image ========
|
||
|
||
func (p *Plugin) handleManageImages(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "list":
|
||
page := readArgInt(args, "page", 1)
|
||
pageSize := readArgInt(args, "pageSize", 50)
|
||
return p.do("GET", fmt.Sprintf("/api/admin/img?page=%d&pageSize=%d", page, pageSize), nil)
|
||
case "all":
|
||
return p.do("GET", "/api/admin/img/all", nil)
|
||
case "upload":
|
||
filePath := readArg(args, "file")
|
||
if filePath == "" {
|
||
return errResult("file 路径不能为空"), nil
|
||
}
|
||
imgType := readArg(args, "type")
|
||
return p.uploadImage(filePath, imgType)
|
||
case "scan":
|
||
return p.do("POST", "/api/admin/img/scan", nil)
|
||
case "export":
|
||
return p.do("POST", "/api/admin/img/export", nil)
|
||
case "delete":
|
||
sign := readArg(args, "sign")
|
||
if sign == "" {
|
||
return errResult("sign 不能为空"), nil
|
||
}
|
||
return p.do("DELETE", "/api/admin/img/"+sign, nil)
|
||
case "delete_all":
|
||
return p.do("DELETE", "/api/admin/img/all/delete", nil)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
func (p *Plugin) uploadImage(filePath, imgType string) (interface{}, error) {
|
||
f, err := os.Open(filePath)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("打开文件失败: %w", err)
|
||
}
|
||
defer f.Close()
|
||
|
||
var buf bytes.Buffer
|
||
w := multipart.NewWriter(&buf)
|
||
part, err := w.CreateFormFile("image", filePath)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("创建表单失败: %w", err)
|
||
}
|
||
if _, err := io.Copy(part, f); err != nil {
|
||
return nil, fmt.Errorf("写入文件失败: %w", err)
|
||
}
|
||
if imgType != "" {
|
||
w.WriteField("type", imgType)
|
||
}
|
||
w.Close()
|
||
|
||
req, err := http.NewRequest("POST", p.baseURL+"/api/admin/img/upload", &buf)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("创建请求失败: %w", err)
|
||
}
|
||
req.Header.Set("token", p.token)
|
||
req.Header.Set("Content-Type", w.FormDataContentType())
|
||
|
||
resp, err := p.http.Do(req)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("上传失败: %w", err)
|
||
}
|
||
defer resp.Body.Close()
|
||
raw, _ := io.ReadAll(resp.Body)
|
||
if resp.StatusCode >= 400 {
|
||
return nil, fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(raw))
|
||
}
|
||
var result interface{}
|
||
if json.Unmarshal(raw, &result) != nil {
|
||
return string(raw), nil
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
// ======== Link ========
|
||
|
||
func (p *Plugin) handleManageLinks(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "list":
|
||
return p.do("GET", "/api/admin/meta/link", nil)
|
||
case "create":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("POST", "/api/admin/meta/link", data)
|
||
case "update":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/meta/link", data)
|
||
case "delete":
|
||
name := readArg(args, "name")
|
||
if name == "" {
|
||
return errResult("name 不能为空"), nil
|
||
}
|
||
return p.do("DELETE", "/api/admin/meta/link/"+name, nil)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Social ========
|
||
|
||
func (p *Plugin) handleManageSocial(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "list":
|
||
return p.do("GET", "/api/admin/meta/social", nil)
|
||
case "types":
|
||
return p.do("GET", "/api/admin/meta/social/types", nil)
|
||
case "create":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("POST", "/api/admin/meta/social", data)
|
||
case "update":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/meta/social", data)
|
||
case "delete":
|
||
stype := readArg(args, "stype")
|
||
if stype == "" {
|
||
return errResult("stype 不能为空"), nil
|
||
}
|
||
return p.do("DELETE", "/api/admin/meta/social/"+stype, nil)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Reward ========
|
||
|
||
func (p *Plugin) handleManageRewards(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "list":
|
||
return p.do("GET", "/api/admin/meta/reward", nil)
|
||
case "create":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("POST", "/api/admin/meta/reward", data)
|
||
case "update":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/meta/reward", data)
|
||
case "delete":
|
||
name := readArg(args, "name")
|
||
if name == "" {
|
||
return errResult("name 不能为空"), nil
|
||
}
|
||
return p.do("DELETE", "/api/admin/meta/reward/"+name, nil)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Custom Page ========
|
||
|
||
func (p *Plugin) handleManagePages(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "list":
|
||
return p.do("GET", "/api/admin/customPage/all", nil)
|
||
case "get":
|
||
path := readArg(args, "path")
|
||
if path == "" {
|
||
return p.do("GET", "/api/admin/customPage", nil)
|
||
}
|
||
return p.do("GET", "/api/admin/customPage?path="+path, nil)
|
||
case "create":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("POST", "/api/admin/customPage", data)
|
||
case "update":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/customPage", data)
|
||
case "delete":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("DELETE", "/api/admin/customPage", data)
|
||
case "folder":
|
||
folder := readArg(args, "folder")
|
||
return p.do("GET", "/api/admin/customPage/folder?folder="+folder, nil)
|
||
case "file":
|
||
file := readArg(args, "file")
|
||
return p.do("GET", "/api/admin/customPage/file?file="+file, nil)
|
||
case "upload":
|
||
filePath := readArg(args, "file")
|
||
if filePath == "" {
|
||
return errResult("file 路径不能为空"), nil
|
||
}
|
||
return p.uploadCustomPageFile(filePath)
|
||
case "create_file":
|
||
file := readArg(args, "file")
|
||
content := readArg(args, "content")
|
||
return p.do("POST", "/api/admin/customPage/file", map[string]interface{}{"file": file, "content": content})
|
||
case "create_folder":
|
||
folder := readArg(args, "folder")
|
||
return p.do("POST", "/api/admin/customPage/folder", map[string]interface{}{"folder": folder})
|
||
case "update_file":
|
||
file := readArg(args, "file")
|
||
content := readArg(args, "content")
|
||
return p.do("PUT", "/api/admin/customPage/file", map[string]interface{}{"file": file, "content": content})
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
func (p *Plugin) uploadCustomPageFile(filePath string) (interface{}, error) {
|
||
f, err := os.Open(filePath)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("打开文件失败: %w", err)
|
||
}
|
||
defer f.Close()
|
||
|
||
var buf bytes.Buffer
|
||
w := multipart.NewWriter(&buf)
|
||
part, err := w.CreateFormFile("file", filePath)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("创建表单失败: %w", err)
|
||
}
|
||
if _, err := io.Copy(part, f); err != nil {
|
||
return nil, fmt.Errorf("写入文件失败: %w", err)
|
||
}
|
||
w.Close()
|
||
|
||
req, err := http.NewRequest("POST", p.baseURL+"/api/admin/customPage/upload", &buf)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("创建请求失败: %w", err)
|
||
}
|
||
req.Header.Set("token", p.token)
|
||
req.Header.Set("Content-Type", w.FormDataContentType())
|
||
|
||
resp, err := p.http.Do(req)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("上传失败: %w", err)
|
||
}
|
||
defer resp.Body.Close()
|
||
raw, _ := io.ReadAll(resp.Body)
|
||
if resp.StatusCode >= 400 {
|
||
return nil, fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(raw))
|
||
}
|
||
var result interface{}
|
||
if json.Unmarshal(raw, &result) != nil {
|
||
return string(raw), nil
|
||
}
|
||
return result, nil
|
||
}
|
||
|
||
// ======== Settings ========
|
||
|
||
func (p *Plugin) handleManageSettings(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "get_static":
|
||
return p.do("GET", "/api/admin/setting/static", nil)
|
||
case "set_static":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/setting/static", data)
|
||
case "get_waline":
|
||
return p.do("GET", "/api/admin/setting/waline", nil)
|
||
case "set_waline":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/setting/waline", data)
|
||
case "get_layout":
|
||
return p.do("GET", "/api/admin/setting/layout", nil)
|
||
case "set_layout":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/setting/layout", data)
|
||
case "get_login":
|
||
return p.do("GET", "/api/admin/setting/login", nil)
|
||
case "set_login":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/setting/login", data)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== About ========
|
||
|
||
func (p *Plugin) handleManageAbout(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "get":
|
||
return p.do("GET", "/api/admin/meta/about", nil)
|
||
case "update":
|
||
content := readArg(args, "content")
|
||
return p.do("PUT", "/api/admin/meta/about", map[string]interface{}{"content": content})
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Site ========
|
||
|
||
func (p *Plugin) handleManageSite(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "get":
|
||
return p.do("GET", "/api/admin/meta/site", nil)
|
||
case "update":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/meta/site", data)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Menu ========
|
||
|
||
func (p *Plugin) handleManageMenu(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "get":
|
||
return p.do("GET", "/api/admin/meta/menu", nil)
|
||
case "update":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/meta/menu", data)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Analysis ========
|
||
|
||
func (p *Plugin) handleGetAnalysis(args map[string]interface{}) (interface{}, error) {
|
||
tab := readArg(args, "tab")
|
||
if tab == "" {
|
||
tab = "overview"
|
||
}
|
||
return p.do("GET", "/api/admin/analysis?tab="+tab, nil)
|
||
}
|
||
|
||
// ======== Log ========
|
||
|
||
func (p *Plugin) handleGetLogs(args map[string]interface{}) (interface{}, error) {
|
||
page := readArgInt(args, "page", 1)
|
||
pageSize := readArgInt(args, "pageSize", 50)
|
||
path := fmt.Sprintf("/api/admin/log?page=%d&pageSize=%d", page, pageSize)
|
||
if v := readArg(args, "event"); v != "" {
|
||
path += "&event=" + v
|
||
}
|
||
return p.do("GET", path, nil)
|
||
}
|
||
|
||
// ======== Backup ========
|
||
|
||
func (p *Plugin) handleManageBackup(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "export":
|
||
return p.do("GET", "/api/admin/backup/export", nil)
|
||
case "import":
|
||
filePath := readArg(args, "file")
|
||
if filePath == "" {
|
||
return errResult("file 路径不能为空"), nil
|
||
}
|
||
data, err := os.ReadFile(filePath)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("读取备份文件失败: %w", err)
|
||
}
|
||
var body interface{}
|
||
if json.Unmarshal(data, &body) != nil {
|
||
return errResult("无效的备份JSON"), nil
|
||
}
|
||
return p.do("POST", "/api/admin/backup/import", body)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Caddy ========
|
||
|
||
func (p *Plugin) handleManageCaddy(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "get_https":
|
||
return p.do("GET", "/api/admin/caddy/https", nil)
|
||
case "set_https":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/caddy/https", data)
|
||
case "get_log":
|
||
return p.do("GET", "/api/admin/caddy/log", nil)
|
||
case "clear_log":
|
||
return p.do("DELETE", "/api/admin/caddy/log", nil)
|
||
case "get_config":
|
||
return p.do("GET", "/api/admin/caddy/config", nil)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== ISR ========
|
||
|
||
func (p *Plugin) handleManageISR(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "get":
|
||
return p.do("GET", "/api/admin/isr", nil)
|
||
case "trigger":
|
||
return p.do("POST", "/api/admin/isr", nil)
|
||
case "update":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/isr", data)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Pipeline ========
|
||
|
||
func (p *Plugin) handleManagePipelines(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "list":
|
||
return p.do("GET", "/api/admin/pipeline", nil)
|
||
case "config":
|
||
return p.do("GET", "/api/admin/pipeline/config", nil)
|
||
case "get":
|
||
id := readArg(args, "id")
|
||
if id == "" {
|
||
return errResult("id 不能为空"), nil
|
||
}
|
||
return p.do("GET", "/api/admin/pipeline/"+id, nil)
|
||
case "create":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("POST", "/api/admin/pipeline", data)
|
||
case "trigger":
|
||
id := readArg(args, "id")
|
||
if id == "" {
|
||
return errResult("id 不能为空"), nil
|
||
}
|
||
return p.do("POST", "/api/admin/pipeline/trigger/"+id, nil)
|
||
case "update":
|
||
id := readArg(args, "id")
|
||
if id == "" {
|
||
return errResult("id 不能为空"), nil
|
||
}
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/pipeline/"+id, data)
|
||
case "delete":
|
||
id := readArg(args, "id")
|
||
if id == "" {
|
||
return errResult("id 不能为空"), nil
|
||
}
|
||
return p.do("DELETE", "/api/admin/pipeline/"+id, nil)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Collaborator ========
|
||
|
||
func (p *Plugin) handleManageCollaborators(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "list":
|
||
return p.do("GET", "/api/admin/collaborator", nil)
|
||
case "list_all":
|
||
return p.do("GET", "/api/admin/collaborator/list", nil)
|
||
case "create":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("POST", "/api/admin/collaborator", data)
|
||
case "update":
|
||
data, ok := jsonArg(args, "data")
|
||
if !ok {
|
||
return errResult("data JSON 不能为空"), nil
|
||
}
|
||
return p.do("PUT", "/api/admin/collaborator", data)
|
||
case "delete":
|
||
id := readArg(args, "id")
|
||
if id == "" {
|
||
return errResult("id 不能为空"), nil
|
||
}
|
||
return p.do("DELETE", "/api/admin/collaborator/"+id, nil)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Token ========
|
||
|
||
func (p *Plugin) handleManageTokens(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "list":
|
||
return p.do("GET", "/api/admin/token", nil)
|
||
case "create":
|
||
expiresIn := readArgInt(args, "expiresIn", 3153600000)
|
||
return p.do("POST", "/api/admin/token", map[string]interface{}{"expiresIn": expiresIn})
|
||
case "delete":
|
||
id := readArg(args, "id")
|
||
if id == "" {
|
||
return errResult("id 不能为空"), nil
|
||
}
|
||
return p.do("DELETE", "/api/admin/token/"+id, nil)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Auth ========
|
||
|
||
func (p *Plugin) handleAuth(args map[string]interface{}) (interface{}, error) {
|
||
cmd := readArg(args, "command")
|
||
switch cmd {
|
||
case "login":
|
||
username := readArg(args, "username")
|
||
password := readArg(args, "password")
|
||
if username == "" || password == "" {
|
||
return errResult("username 和 password 不能为空"), nil
|
||
}
|
||
result, err := p.do("POST", "/api/admin/auth/login", map[string]interface{}{"username": username, "password": password})
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if m, ok := result.(map[string]interface{}); ok {
|
||
if data, ok := m["data"].(map[string]interface{}); ok {
|
||
if token, ok := data["token"].(string); ok && token != "" {
|
||
p.token = token
|
||
p.sdk.Settings().Set("token", token)
|
||
}
|
||
}
|
||
}
|
||
return result, nil
|
||
case "logout":
|
||
return p.do("POST", "/api/admin/auth/logout", nil)
|
||
case "restore":
|
||
password := readArg(args, "password")
|
||
if password == "" {
|
||
return errResult("password 不能为空"), nil
|
||
}
|
||
return p.doRaw("POST", "/api/admin/auth/restore", map[string]interface{}{"password": password}, map[string]string{"token": p.resetToken})
|
||
case "update":
|
||
body := map[string]interface{}{}
|
||
if v := readArg(args, "newName"); v != "" {
|
||
body["name"] = v
|
||
}
|
||
if v := readArg(args, "newPassword"); v != "" {
|
||
body["password"] = v
|
||
}
|
||
return p.do("PUT", "/api/admin/auth", body)
|
||
default:
|
||
return errResult("未知命令: " + cmd), nil
|
||
}
|
||
}
|
||
|
||
// ======== Meta ========
|
||
|
||
func (p *Plugin) handleGetMeta(args map[string]interface{}) (interface{}, error) {
|
||
return p.do("GET", "/api/admin/meta", nil)
|
||
}
|