Coder Social home page Coder Social logo

veops / messenger Goto Github PK

View Code? Open in Web Editor NEW
52.0 6.0 18.0 1.17 MB

一个简单轻量的消息发送服务

Home Page: https://veops.cn

License: Apache License 2.0

Dockerfile 1.35% Shell 0.06% Go 78.79% Makefile 0.35% HTML 4.92% CSS 0.29% JavaScript 14.25%
golang messenger gin

messenger's Introduction

Messenger

Apache License 2.0 go>=1.18 API

messenger是一个简单轻量的消息发送服务,支持邮件、微信、飞书、钉钉,同时支持配置动态修改,使用简单灵活

安装

源码

cd messenger
sh build.sh
cp conf/confTemplate.yaml conf/conf.yaml # edit your config
./messenger

docker

# 源码构建
cd messenger
cp conf/confTemplate.yaml conf/conf.yaml # edit your config
docker build --tag messenger .
docker run -d --name messenger -p 8888:8888 -v $(pwd)/conf:/messenger/conf --restart=always messenger

# 镜像
docker pull registry.cn-hangzhou.aliyuncs.com/veops/messenger:latest

API

您也可以通过访问 http://127.0.0.1:8888/swagger/index.html 查看swagger api文档

发送消息

请求方式:POST

请求地址:http://127.0.0.1:8888/v1/message

参数说明:

参数 是否必须 类型 说明
sender string sender名称:发送消息具体sender的名称,对应conf中的name
msgtype string 消息内容类型:每种消息发送方式支持多种消息内容类型,各发送方式支持的消息内容类型参考如下
wechatBot: 微信机器人      wechatApp:微信应用
feishuBot:飞书机器人      feishuApp:飞书应用
dingdingBot:钉钉机器人    dingdingApp:钉钉应用
email (邮件): text/plain text/html
aliSms (阿里云短信): sms
content string 消息内容:IM(微信、飞书、钉钉)消息内容本身具有结构,传入其JSON序列化之后的字符串,如微信应用的文本消息填写{"content":"my content"}序列化后字符;邮件可直接填写内容字符串;阿里云短信填写模板变量JSON序列化后字符串如:{"name":"张三","number":"1390000****"} 序列化后字符串
title string 消息标题:仅用于 email 类型
tos []string 接收人列表:发送邮件、应用消息时需要填写
ccs []string 抄送人列表:仅用于 email 类型
extra string 额外参数:通常情况下您只需要关注消息内容类型和其内容发送人,但是当您需要传递一些额外参数时,比如微信应用开启重复检查和检查时间间隔,可以将extra设置为{"enable_duplicate_check":1, "duplicate_check_interval": 1800}序列化后字符串
sync bool 同步发送:默认情况下,发送请求接受成功即返回200,消息会异步发送,若sync为true则会同步等待消息发送结果并返回
simple bool 简单内容:默认情况下,消息内容是json字符串(参考content参数),对于简单的消息类型text和markdown可设置simple=true,此时content仅填写内容字符串本身即可,如my content
支持的消息类型(msgtype)
text: wechatBot wechatApp feishuBot feishuApp dingdingBot dingdingApp
markdown: wechatBot wechatApp dingdingBot dingdingApp
ats []string @列表: 使用@all代表@所有人; 支持wechatBot(text, markdown(无法@all)), feishuBot(text), dingdingBot (text, markdown)
at_mobiles []string @列表: 同ats参数,但使用手机号而非user id; 支持wechatBot(text), dingdingBot(text, markdown)

返回结果:

// 正常 httpStatusCode==200
{
  "msg": "ok"
}

// 异常 httpStatusCode!=200
{
  "msg": "xxxx"
}

请求示例:

curl

curl  -X POST \
  'http://localhost:8888/v1/message' \
  --header 'Content-Type: application/json' \
  --data-raw '{
  "sender": "yourSenderName",
  "msgtype": "text",
  "content": "{\"content\":\"一行文本内容\"}"
}'

python

import json
import requests

reqUrl = "http://localhost:8888/v1/message"

response = requests.post(reqUrl, json={
    "sender": "yourSenderName",
    "msgtype": "text",
    "content": json.dumps({
        "content": "一行文本内容1"
    })
})

print(response.status_code)

golang

package main

import (
	"fmt"

	"github.com/go-resty/resty/v2"
)

func main() {
	reqUrl := "http://localhost:8888/v1/message"

	content, _ := json.Marshal(map[string]any{
		"content": "一行文本内容2",
	})
	resp, err := resty.New().R().
		SetBody(map[string]any{
			"sender":  "yourSenderName",
			"msgtype": "text",
			"content": string(content),
		}).Post(reqUrl)

	fmt.Println(err, resp.StatusCode())
}

更新配置

请求方式:POST PUT DELETE

请求地址:http://127.0.0.1:8888/v1/senders

参数说明:

参数(请求体) 是否必须 类型 说明
body json 请求body为您的sender配置,如{"wechatBot": [{"name": "yourSenderName", "url": "https://xxx"}]}
POST:同类型配置会被全部覆盖
PUT:同类型同名称的配置会被更新,新配置将被添加
DELETE:同类型同名称配置将被删除

返回结果:

// 正常 httpStatusCode==200
{
  "msg": "ok"
}

// 异常 httpStatusCode!=200
{
  "msg": "xxxx"
}

查询用户ID

请求方式:POST

请求地址:http://127.0.0.1:8888/v1/uid/getbyphone

参数说明:

参数 是否必须 类型 说明
sender string 查询用户id时使用的sender名称
phone string 手机号

返回结果:

// 正常 httpStatusCode==200
{
  "uid": "xxxxxxxxxxxxx",
  "msg": "ok"
}

// 异常 httpStatusCode!=200
{
  "msg": "xxxx"
}

查询消息历史

请求方式:GET

请求地址:http://127.0.0.1:8888/v1/histories

参数说明:

参数 是否必须 类型 说明
page_index int 分页序号,从1开始
page_size int 分页每页数量
start int64 起始时间unix时间戳
end int64 结束时间unix时间戳
sender string 发送方式名称
content string 消息内容

返回结果:

// 正常 httpStatusCode==200
{
  "count": 1,
  "list": [
    {
      "CreatedAt": 1705911411,
      "Err": "",
      "Id": 1,
      "Message": "json string of message",
      "ReceivedAt": 1705911410,
      "Req": "curl command of request",
      "Resp": "json string of response body and http code",
      "Status": true
    }
  ],
  "msg": "ok"
}

// 异常 httpStatusCode!=200
{
  "msg": "xxxx"
}

鉴权

当配置文件中开启auths鉴权配置后,请求需要加入鉴权信息,目前支持三种鉴权方式.

IP

发送请求的客户端ip需匹配pattern

token

发送请求中需要添加请求头 X-Token = token in your yaml config

sign

签名鉴权需要添加请求头 X-TS = 当前unix秒数时间戳 X-Nonce = 随机内容 X-Sign = 根据签名算法生成的签名

签名算法步骤为

  1. 将ts和nonce信息加入body中 body["ts"] = X-TS, body["nonce"] = X-Nonce
  2. 将body中的键值对按键排序后拼接
  3. 使用配置文件中的secret计算sha256的值,并将结果进行base64编码,如 secret=666时,步骤二中结果为
  4. 设置请求头中的 X-Sign = 步骤三结果
// golang 签名示例
secret := "666"
body := map[string]any{
"sender":  "wechatBot",
"msgtype": "text",
"content": "{\"content\":\"一行文本内容\"}",
}
body["ts"] = "1695005697" // cast.ToString(time.Now().Unix())
body["nonce"] = "123"
keys := lo.Keys(body)
sort.Strings(keys)

// content{"content":"一行文本内容"}msgtypetextnonce123senderwechatBotts1695005697
kvStr := strings.Join(lo.Map(keys, func(k string, _ int) string { return fmt.Sprintf("%s%s", k, body[k]) }), "")

mac := hmac.New(sha256.New, []byte(secret))
_, _ = mac.Write([]byte(kvStr))

// nAW4/1vz8EjdJEVXqTevmX7yBOzQtUti1Z2TIgAxogc=
sign := base64.StdEncoding.EncodeToString(mac.Sum(nil))

配置说明

yaml配置文件定义了

  1. app 服务配置ip的、端口
  2. auths 鉴权方式。多种鉴权方式同时配置时,按配置先后进行检查,满足任意一种方式即通过鉴权。支持的鉴权方式为
    • ip
    • token
    • sign签名
  3. senders 具体发送方式。senders支持动态增删,即在服务已经启动的情况下可以直接修改senders列表,服务会持续读取最新的改动。支持的发送方式类型
    • email
    • wechatBot
    • wechatApp
    • feishuBot
    • feishuApp
    • dingdingBot
    • dingdingApp
    • aliSms
app:
  ip:
  port: 8888

auths:
  # - type: ip
  #   pattern: 192.168.*.*

  # - type: token
  #   token: your token

  # - type: sign
  #   secret: your secret

senders:
  email:
    # - name: yourSenderName1
    #   host: mail.xxx.com
    #   port: 25
    #   account: [email protected]
    #   password: #无密码时留空即可
    #   tls: "false"
  wechatBot:
    # - name: yourSenderName2
    #   url: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxx
  wechatApp:
    # - name: yourSenderName3
    #   corpid: xxxx
    #   agentid: xxxx
    #   corpsecret: xxxx
  feishuBot:
    # - name: yourSenderName4
    #   url: https://open.feishu.cn/open-apis/bot/v2/hook/xxxxxx
  feishuApp:
    # - name: yourSenderName5
    #   app_id: cli_xxxx
    #   app_secret: xxxx
  dingdingBot:
    # - name: yourSenderName6
    #   url: https://oapi.dingding.com/robot/send?access_token=xxxx
    #   token: xxxx #仅加密方式为加签时填写
  dingdingApp:
    # - name: yourSenderName7
    #   appKey: xxxx
    #   appSecret: xxxx
    #   robotCode: xxxx
  aliSms:
    # - name: yourSenderName8
    #   accessKey: xxxx
    #   accessSecret: xxxx
    #   templateCode: SMS_123456789
    #   signName: xxxx

自定义发送

通常情况下,以上7中方式能满足大部分需求,但是如果你想要定制自己的sender,可以按如下步骤进行开发

  1. 在send目录下创建你的sender文件,如mysender.go
  2. 定义mysender结构体并实现sender接口
    type sender interface {
        send(*message) error
        getConf() map[string]string
    }
  3. 新增init方法将你的sender注册到后台goroutine中,registered的key mysender即为你的sender的类型,可以在配置文件中使用。通常建议将文件名、结构体名、类型名保持一直
    func init() {
        registered["mysender"] = func(conf config) sender {
            return &wechatBot{conf: conf}
        }
    }

Web

http://127.0.0.1:8888/web

messenger's People

Contributors

ttktatakai avatar pycook avatar ronething avatar ivongwy avatar

Stargazers

soulc avatar idclab avatar Hualaosi avatar 杨凯彬 avatar  avatar 墨 avatar  avatar stitch cula avatar  avatar 晨枫 avatar  avatar  avatar  avatar osmen avatar Willem avatar YangEver avatar Andrus Basile avatar YIN JIA YI avatar  avatar 枫桥 avatar hejie avatar JohnAi avatar ydjm avatar  avatar  avatar maskkid avatar  avatar Jin avatar wwhai avatar tianmac avatar Lzlarkin avatar  avatar  avatar XieZhi Company avatar iuu avatar  avatar  avatar Kerry avatar  avatar  avatar  avatar  avatar tars-GG avatar leo avatar hk avatar  avatar Simple4H avatar Loki29 avatar Tony Joseph avatar rocketzhang avatar  avatar duliang123 avatar

Watchers

Thomas Copper avatar  avatar loveiwei avatar  avatar  avatar  avatar

messenger's Issues

[help wanted]: conf.yaml problem

Contact Details

[email protected]

What is your question?

i have a question!
auths:

  • type: ip
    pattern: 192.168.*.*

If I have more IPs in different domains, for example: 10.10.*.* and 175.0.*.* and so on. How to write the conf/conf.yaml

Version

newest

feat: openapi

Contact Details

No response

feature is related to UI or API aspects?

No response

What is your advice?

maybe we can use openapi yaml file to view api.

Version

none

About the atUserIds parameter of dingdingBot

Dingding Normal group: The atUserIds parameter is not supported (only for Internal group of enterprises).
So I had to modify the atUserIds parameter to: atMobiles.
Then @Someone works!

at["isAtAll"] = lo.Contains(msg.Ats, "@all") at["atMobiles"] = lo.Without(msg.Ats, "@all")

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.