Skip to content

xgfone/go-msgnotice

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

42 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

A Common Message Notice Library

GoDoc License Minimum Go Version Latest SemVer

Example

package main

import (
	"context"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"net/http"
	"os"
	"time"

	// Load and register the drivers.
	_ "github.com/xgfone/go-msgnotice/driver/drivers/email"
	_ "github.com/xgfone/go-msgnotice/driver/drivers/feishu"

	"github.com/xgfone/go-msgnotice/channel"
	"github.com/xgfone/go-msgnotice/channel/manager"
	"github.com/xgfone/go-msgnotice/driver"
	"github.com/xgfone/go-msgnotice/driver/builder"
	"github.com/xgfone/go-msgnotice/driver/middleware"
	"github.com/xgfone/go-msgnotice/driver/middleware/logger"
	"github.com/xgfone/go-msgnotice/driver/middleware/timeout"
)

var (
	listenaddr   = flag.String("listenaddr", "127.0.0.1:80", "The address to listen on.")
	channelsfile = flag.String("channelsfile", "channels.json", "The file path storing the channels.")
)

func _loadFromFile(filepath string, dst any, cb func() error) (err error) {
	data, err := os.ReadFile(filepath)
	if err != nil {
		if os.IsNotExist(err) {
			err = nil
		}
		return
	} else if len(data) == 0 {
		return
	}

	if err = json.Unmarshal(data, dst); err != nil {
		return
	}

	return cb()
}

func initChannels() {
	type Channel struct {
		ChannelName string
		DriverName  string
		DriverConf  map[string]any
	}

	var channels []Channel
	var _channels []channel.Channel
	err := _loadFromFile(*channelsfile, &channels, func() (err error) {
		for _, c := range channels {
			if c.ChannelName == "" || c.DriverName == "" {
				return errors.New("missing the channel or driver name")
			}

			driver, err := builder.Build(c.DriverName, c.DriverConf)
			if err != nil {
				return err
			}

			_channels = append(_channels, channel.New(c.ChannelName, driver))
		}
		return
	})

	if err != nil {
		fmt.Println(err)
		return
	}

	manager.Default.UpsertChannels(_channels...)
}

func initMiddlewares() {
	middleware.DefaultManager.Use(timeout.New(100, time.Second*10, nil))
	middleware.DefaultManager.Use(logger.New(90, nil))
}

func httpHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		w.Header().Set("Allow", http.MethodPost)
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}

	var req struct {
		Content  any
		Channel  string
		Receiver string
		Metadata map[string]any
	}
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	if req.Content == nil || req.Channel == "" || req.Receiver == "" {
		http.Error(w, "missing the required arguments", 400)
		return
	}

	msg := driver.NewMessage(req.Channel, "", req.Receiver, req.Content, req.Metadata)
	err := channel.Send(context.Background(), msg)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func main() {
	flag.Parse()

	initMiddlewares()
	initChannels()

	http.HandleFunc("/message", httpHandler)
	_ = http.ListenAndServe(*listenaddr, nil)
}
// Channels configuration file: channels.json
[
  {
    "ChannelName": "email",
    "DriverName": "email",
    "DriverConf": {
      "addr": "smtp.example.com",
      "from": "username@example.com",
      "username": "username@example.com",
      "password": "password",
      "forcetls": true
    }
  },
  {
    "ChannelName": "feishu.webhook",
    "DriverName": "feishu.webhook"
  }
]
# Run the message notice process.
$ msgnotice &

# Client sends the message.

## Send the message by the email
$ curl http://localhost/message -X POST -H 'content-type: application/json' \
-d '{"Content": {"Subject": "subject", "Content": "test"}, "Channel": "email", "Receiver": "xiegaofeng@bimoai.com"}'

## Send the general text message to feishu by webhook.
$ curl http://localhost/message -X POST -H 'content-type: application/json' \
-d '{"Channel": "feishu.webhook", "Receiver": "9c473cb6-1234-5678-bbf1-147b5e83ab8e", "Content": "<at user_id=\"all\">All</at>"}'

## Send the rich text message to feishu by webhook.
$ curl http://localhost/message -X POST -H 'content-type: application/json' -d '{
    "Channel": "feishu.webhook",
    "Receiver": "9c473cb6-1234-5678-bbf1-147b5e83ab8e",
    "Metadata": {"MsgType": "post"},
    "Content": {
        "zh_cn": {
            "title": "test",
            "content": [
                [
                    {"tag": "text", "text": "first paragraph"},
                    {"tag": "at", "user_id": "all"},
                    {"tag": "a", "text": "URL", "href": "https://www.example.com"}
                ],
                [
                    {"tag": "text", "text": "second paragraph"}
                ]
            ]
        }
    }
}'

About

A common message notice library

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages