diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 79ab906..3948c4d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -57,6 +57,7 @@ jobs: - name: Git File Restore run: git checkout . + working-directory: web/ # More assembly might be required: Docker logins, GPG, etc. It all depends # on your needs. diff --git a/.goreleaser.yaml b/.goreleaser.yaml index bc94295..bea96ae 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -13,9 +13,6 @@ builds: - linux - windows - darwin - goarch: - - amd64 - - arm64 id: "{{ .Env.CUSTOM_PROJ_NAME }}" binary: "{{ .Env.CUSTOM_PROJ_NAME }}" diff --git a/Dockerfile b/Dockerfile index e1aa2d2..c022d40 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,5 @@ -FROM ubuntu:latest +FROM debian:stable +ENV TZ=Asia/Shanghai COPY ./ /app/ diff --git a/README.md b/README.md index cbe3ced..55cf75f 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ Message Nest 是一个灵活而强大的消息推送整合平台,旨在简化 - 🎨 **自定义性:** 可以根据需求定制消息推送策略,满足不同场景的个性化需求。 - 🛠 **开放性:** 易于扩展和集成新的消息通知服务,以适应未来的变化。 - ## 进度 🔨 项目还在不断更新中,欢迎大家提出各种建议。 @@ -22,17 +21,21 @@ Message Nest 是一个灵活而强大的消息推送整合平台,旨在简化 关于日志,考虑到目前多数服务以收集控制台输出为主,暂时不支持写出日志文件。 2024.01.24 + - [x] 支持数据统计展示 ----- -- 2024.01.20 + +2024.01.20 + - [x] 添加日志查看自动刷新 ----- + 2024.01.07 + - [x] 支持站点信息自定义 ----- + 2024.01.03 + - [x] 支持企业微信 ----- + - [x] 单应用打包,直接运行,不用部署前端页面 - [x] 支持邮件发送 @@ -49,22 +52,60 @@ Message Nest 是一个灵活而强大的消息推送整合平台,旨在简化 - [ ] .... ## 项目来由 💡 + 自己常常写一些脚本需要消息推送,经常需要接入不同的消息发送,很不方便,于是就有了这个项目。 ## 效果图 📺 -![image](https://raw.githubusercontent.com/engigu/resources/images/2024/01/25/fe21b48b69ed0672911adf63ca5ff511.gif) + +![image](https://raw.githubusercontent.com/engigu/resources/images/2024/01/26/593a06ac4d1db666acb8a9fb8719e734.gif) ## 使用方法 🚀 +
+ 1. 直接运行最新的release打包的可执行文件(推荐,不用部署前端页面) + 1. 下载最新的系统版本对应的release, 解压 2. 新建一个数据库 3. 重命名conf/app.example.ini为conf/app.ini 4. 修改app.ini对应的配置 -5. 启动项目会自动创建表和账号 +5. 将配置中`EmbedHtml = disable`, 进行注释,以单应用方式运行,完整配置参考如下: + +```ini +[app] +JwtSecret = message-nest +LogLevel = INFO + +; 第一次运行务必打开,初始化数据 +InitData = enable + +[server] +RunMode = release +HttpPort = 8000 +ReadTimeout = 60 +WriteTimeout = 60 +; 注释EmbedHtml,启用单应用模式 +; EmbedHtml = disable + +[database] +; 关闭SQL打印 +; SqlDebug = enable + +Type = mysql +User = root +Password = Aa123456 +Host = vm.server +Port = 3308 +Name = yourDbName +TablePrefix = message_ + +``` + +6. 启动项目会自动创建表和账号 + ```shell # 第一次运行将app.ini中的app.InitData设置为enable,会自动进行表数据的初始化 # 后续不需要开启这个配置 -# INFO登录启动回出现如下日志 +# INFO日志级别启动回出现如下日志 [2024-01-13 13:40:09.075] INFO [migrate.go:70 Setup] [Init Data]: Migrate table: message_auth [2024-01-13 13:40:11.778] INFO [migrate.go:70 Setup] [Init Data]: Migrate table: message_send_tasks @@ -76,10 +117,200 @@ Message Nest 是一个灵活而强大的消息推送整合平台,旨在简化 [2024-01-13 13:40:46.751] INFO [migrate.go:77 Setup] [Init Data]: All table data init done. ``` -6. 启动项目,访问8000端口,初始账号为admin,密码为123456 + +7. 启动项目,访问8000端口,初始账号为admin,密码为123456 + +
+ + +
+ 2. 前后端分离部署(待更新) +
+ + +[//]: # (1. 前端项目构建) + +[//]: # (```shell) + +[//]: # (cd web && npm i && npm run build) + +[//]: # (```) + +[//]: # (2. 配置配置文件,参考上面,需要注意将配置中`EmbedHtml = disable`取消注释) + +[//]: # (3. 启动go服务) + +[//]: # (```shell) + +[//]: # (go mod tidy) + +[//]: # (CGO_ENABLED=0 go build -o Message-Nest) + +[//]: # (./Message-Nest) + +[//]: # (```) + +[//]: # (4. 配置Nginx,将静态文件) + +[//]: # (5. 配置Nginx,将后端接口转发) + +
+ 3. 开发调试运行 + +1. 重命名conf/app.example.ini为conf/app.ini, 关键配置如下 + +```ini +[app] +JwtSecret = message-nest +LogLevel = INFO + +; 第一次运行务必打开,初始化数据 +InitData = enable + +[server] +; RunMode务必设置成debug,会自动添加跨域 +RunMode = debug +HttpPort = 8000 +ReadTimeout = 60 +WriteTimeout = 60 +; 取消EmbedHtml的注释(启用前后端分离),然后到web目录下面,npm run dev启动前端页面 +EmbedHtml = disable + +[database] +; 开启SQL打印 +SqlDebug = enable + +Type = mysql +User = root +Password = Aa123456 +Host = vm.server +Port = 3308 +Name = yourDbName +TablePrefix = message_ + +``` + +2. 运行main.go,服务启动后会运行在8000端口 + +```shell +go mod tidy +go run main.go +``` + +3. 启动前端页面,页面启动后会提示访问url,一般是`http://127.0.0.1:5173` + +```shell +cd web +npm i +npm run dev +``` + +4. 访问`http://127.0.0.1:5173`,进行调试开发,接口会自动转发到go服务`http://localhost:8000` + +
+ +
+ 4. docker/docker-compose部署 + +docker部署 + +1. 新建一个数据库,准备一个conf文件夹 +2. 新增conf/app.ini +3. 修改app.ini对应的配置 +4. 将配置中`EmbedHtml = disable`, 进行注释,以单应用方式运行,完整配置参考如下: + +```ini +[app] +JwtSecret = message-nest +LogLevel = INFO + +; 第一次运行务必打开,初始化数据 +InitData = enable + +[server] +RunMode = release +; docker模式下端口配置文件中只能为8000 +HttpPort = 8000 +ReadTimeout = 60 +WriteTimeout = 60 +; 注释EmbedHtml,启用单应用模式 +; EmbedHtml = disable + +[database] +; 关闭SQL打印 +; SqlDebug = enable + +Type = mysql +User = root +Password = Aa123456 +Host = vm.server +Port = 3308 +Name = yourDbName +TablePrefix = message_ + +``` +6. 使用使用命令启动,端口使用`-p`自定义 +```shell +docker pull engigu/message-nest:latest +# 测试运行 +docker run --rm -ti -p 8000:8000 -v /your/path/conf:/app/conf engigu/message-nest:latest +# 正式运行 +docker run -d -p 8000:8000 -v /your/path/conf:/app/conf engigu/message-nest:latest +``` +7. 启动项目,访问8000端口,初始账号为admin,密码为123456 + +docker-compose部署 +1. 准备app.ini,文件内容如上docker部署 +2. 准备docker-compose.yml,内容如下: +```yml +version: "3.7" +services: + + message-nest: + image: engigu/message-nest:latest + container_name: message-nest + restart: always + volumes: + - ./conf:/app/conf + ports: + - "8000:8000" +``` +3. 文件结构 +```shell +. +├── conf +│ └── app.ini +├── docker-compose.yml + +``` +4. 启动项目 +```shell +# 测试运行 +docker-compose up +# 正式运行 +docker-compose up -d +``` + +
+ +#### 关于EmbedHtml配置的说明 + +> 这个配置可以理解为单应用模式(或者前后端分离)的开关 +> 1. 取消这个配置的注释,表示前后端分离,表示go服务启动的时候只会有api服务,需要到web目录下,npm run + dev启动前端项目。然后访问前端项目提示的端口服务,一般是127.0.0.1:5173。 + 或者使用npm run build,用Nginx部署前端。 +> +> +> 2. 注释这个配置,表示单应用,启动go服务,会把web/dist目录下文件作为前端静态资源。 + 如果目录下没有静态资源文件,需要到web目录下,npm run build构建生成。 +> +> 两种方式各有优缺点,综合考虑下来,推荐直接使用release的打包执行文件,其中已经内置了页面静态资源,只用运行一个服务。 ## 完整配置说明 ⚙️ +
+ 点击展开 + ```ini [app] JwtSecret = message-nest @@ -89,6 +320,7 @@ LogLevel = INFO ; init table data, first run set enable ; 首次运行打开这个,会自动初始化表和数据 +; 项目升级需要打开这个进行检测新增表字段创建 InitData = enable [server] @@ -99,7 +331,8 @@ ReadTimeout = 60 WriteTimeout = 60 ; use embed html static file ; 是否使用embed打包的静态资源 -; 如果运行release打包后的应用,请注释这个设置。如果取消这个注释,只会单独运行api服务,前端服务需要到web目录手动npm run dev, 进行启动 +; 如果运行release打包后的应用,请注释这个设置。 +; 如果取消这个注释,只会单独运行api服务,前端页面需要到web目录手动npm run dev, 运行前端服务 ; EmbedHtml = disable [database] @@ -115,13 +348,67 @@ TablePrefix = message_ ; SqlDebug = enable ``` +
+ +## 页面操作指引 🎞️ + +关于消息的添加,发送的整个步骤,是以顶部菜单栏从右向左进行操作。 + +
+ 1. 新增发信渠道(添加消息的具体渠道) + +![image](screenshots/1-add-message-ways.png) + +参考各个渠道tab的说明进行设置保存 + +注意现在的自定义webhook形式,只支持`POST`请求,采用的是替换配置的消息体中的占位符`TEXT`,进行发送消息 + +
+ +
+ 2. 新增发信任务 + +![image](screenshots/2-add-message-task.png) + +1. 点击渠道输入框会弹出所有渠道选项 +2. 选择一个渠道会出现渠道的明细信息,并选择一种消息类型,进行暂存成为实例,点击确定才会进行最终的保存 +3. 添加任务的页面实际上,会分别添加任务,以及任务关联的渠道实例 +4. 关于任务与实例的说明: + +> 一个任务可以关联创建多个实例 +> +> 选择不同的渠道,填写的实例信息也不一样 +> +> 一个任务可以绑定一个实例,也可以绑定多个实例,多个实例意味着一个消息可以推送给多个消息渠道 + +5. 关于实例的消息类型说明: + +> 消息的类型大体上可以分为text、html、markdown三种类型。每种渠道消息现在支持的类型有不同的限制。 +> +> 在实际发送的时候,会优先选择发送api中传过来对应类型的消息,如果api中没有对应的类型,会直接取api中text消息。 +> +> api中text消息在发送的时候必须要传 + +
+ +
+ 3. 消息发送 + +![image](screenshots/3-send-message.png) + +参考各种语言的接口进行调用 + +
## 贡献 🤝 + 欢迎通过提交问题和提出改进建议。 ## 致谢 🙏 + 该项目汲取了[go-gin-example](https://github.com/eddycjy/go-gin-example)项目的灵感,展示了 Go 和 Gin 在实际应用中的强大和多才多艺。 ## 许可证 📝 + [LICENSE](LICENSE) diff --git a/main.go b/main.go index 59eb139..7bfd06b 100644 --- a/main.go +++ b/main.go @@ -45,9 +45,16 @@ func main() { MaxHeaderBytes: maxHeaderBytes, } + startInfo := "" + if setting.ServerSetting.RunMode == "debug" { + startInfo = fmt.Sprintf("run mode: %s, start message server @ http://localhost%s", setting.ServerSetting.RunMode, endPoint) + } else { + startInfo = fmt.Sprintf("run mode: %s, start message server @ http://0.0.0.0%s", setting.ServerSetting.RunMode, endPoint) + } + logrus.WithFields(logrus.Fields{ "prefix": fmt.Sprintf("[PID:%d]", os.Getpid()), - }).Infof("start message server @ http://0.0.0.0%s", endPoint) + }).Infof(startInfo) err := server.ListenAndServe() if err != nil { diff --git a/models/send_tasks_logs.go b/models/send_tasks_logs.go index 94347b4..fc91bd7 100644 --- a/models/send_tasks_logs.go +++ b/models/send_tasks_logs.go @@ -153,10 +153,11 @@ func GetStatisticData() (StatisticData, error) { query := db. Table(logt). Select(` -COUNT(*) AS today_total_num, -SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS today_succ_num, -SUM(CASE WHEN status != 1 or status is null THEN 1 ELSE 0 END) AS today_failed_num`). + COUNT(*) AS today_total_num, + SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS today_succ_num, + SUM(CASE WHEN status != 1 or status is null THEN 1 ELSE 0 END) AS today_failed_num`). Where("DATE(created_on) = ?", currDay) + query.First(&statistic) // 最近30天数据 @@ -164,13 +165,14 @@ SUM(CASE WHEN status != 1 or status is null THEN 1 ELSE 0 END) AS today_failed_n queryData := db. Table(logt). Select(` - CAST(DATE(created_on) AS CHAR) AS day, + CAST(DATE(created_on) AS CHAR) AS day, SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS day_succ_num, SUM(CASE WHEN status != 1 or status is null THEN 1 ELSE 0 END) AS day_failed_num, - COUNT(*) AS num`). + COUNT(*) AS num`). Where(" created_on >= DATE(?) - INTERVAL ? DAY", currDay, days). - Group("DATE(created_on)"). - Order("created_on") + Group("day"). + Order("day") + queryData.Scan(&latestData) // 消息实例分类数目 diff --git a/screenshots/1-add-message-ways.png b/screenshots/1-add-message-ways.png new file mode 100644 index 0000000..711d5e4 Binary files /dev/null and b/screenshots/1-add-message-ways.png differ diff --git a/screenshots/2-add-message-task.png b/screenshots/2-add-message-task.png new file mode 100644 index 0000000..e088297 Binary files /dev/null and b/screenshots/2-add-message-task.png differ diff --git a/screenshots/3-send-message.png b/screenshots/3-send-message.png new file mode 100644 index 0000000..906dd33 Binary files /dev/null and b/screenshots/3-send-message.png differ diff --git a/web/README.md b/web/README.md index d81e1fb..20c8cb5 100644 --- a/web/README.md +++ b/web/README.md @@ -21,3 +21,4 @@ npm run dev ```sh npm run build ``` +[README.md](..%2FREADME.md) \ No newline at end of file