Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
ef78b7467b
|
|||
0eda32b725
|
@@ -40,4 +40,6 @@ Potentially needs `export GOPRIVATE="gogs.mikescher.com"`
|
|||||||
| | | |
|
| | | |
|
||||||
| rext | Mike | Regex Wrapper, wraps regexp with a better interface |
|
| rext | Mike | Regex Wrapper, wraps regexp with a better interface |
|
||||||
| wmo | Mike | Mongo Wrapper, wraps mongodb with a better interface |
|
| wmo | Mike | Mongo Wrapper, wraps mongodb with a better interface |
|
||||||
|
| | | |
|
||||||
|
| scn | Mike | SimpleCloudNotifier |
|
||||||
| | | |
|
| | | |
|
@@ -65,7 +65,7 @@ var (
|
|||||||
TypeUnauthorized = NewType("UNAUTHORIZED", langext.Ptr(401))
|
TypeUnauthorized = NewType("UNAUTHORIZED", langext.Ptr(401))
|
||||||
TypeAuthFailed = NewType("AUTH_FAILED", langext.Ptr(401))
|
TypeAuthFailed = NewType("AUTH_FAILED", langext.Ptr(401))
|
||||||
|
|
||||||
// other values come the used package
|
// other values come from the downstream application that uses goext
|
||||||
)
|
)
|
||||||
|
|
||||||
var registeredTypes = dataext.SyncSet[string]{}
|
var registeredTypes = dataext.SyncSet[string]{}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
package goext
|
package goext
|
||||||
|
|
||||||
const GoextVersion = "0.0.351"
|
const GoextVersion = "0.0.353"
|
||||||
|
|
||||||
const GoextVersionTimestamp = "2023-12-29T19:25:36+0100"
|
const GoextVersionTimestamp = "2024-01-04T12:38:03+0100"
|
||||||
|
13
scn/scn.go
Normal file
13
scn/scn.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package scn
|
||||||
|
|
||||||
|
type Connection struct {
|
||||||
|
uid string
|
||||||
|
token string
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(userid string, token string) *Connection {
|
||||||
|
return &Connection{
|
||||||
|
uid: userid,
|
||||||
|
token: token,
|
||||||
|
}
|
||||||
|
}
|
171
scn/send.go
Normal file
171
scn/send.go
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
package scn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"gogs.mikescher.com/BlackForestBytes/goext/exerr"
|
||||||
|
json "gogs.mikescher.com/BlackForestBytes/goext/gojson"
|
||||||
|
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrAuthFailed = exerr.NewType("GOEXT_SCN_AUTHFAILED", nil)
|
||||||
|
ErrQuota = exerr.NewType("GOEXT_SCN_QUOTAEXCEEDED", nil)
|
||||||
|
ErrBadRequest = exerr.NewType("GOEXT_SCN_BADREQUEST", nil)
|
||||||
|
ErrInternalServerErr = exerr.NewType("GOEXT_SCN_INTERNALSERVER", nil)
|
||||||
|
ErrOther = exerr.NewType("GOEXT_SCN_OTHER", nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
type MessageResponse struct {
|
||||||
|
ErrHighlight int `json:"errhighlight"`
|
||||||
|
Error int `json:"error"`
|
||||||
|
IsPro bool `json:"is_pro"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Messagecount int `json:"messagecount"`
|
||||||
|
Quota int `json:"quota"`
|
||||||
|
QuotaMax int `json:"quota_max"`
|
||||||
|
SCNMessageID string `json:"scn_msg_id"`
|
||||||
|
Success bool `json:"success"`
|
||||||
|
SuppressSend bool `json:"suppress_send"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageErrResponse struct {
|
||||||
|
Errhighlight int `json:"errhighlight"`
|
||||||
|
Error int `json:"error"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
Success bool `json:"success"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageBuilder struct {
|
||||||
|
conn *Connection
|
||||||
|
title string
|
||||||
|
content *string
|
||||||
|
channel *string
|
||||||
|
time *time.Time
|
||||||
|
sendername *string
|
||||||
|
priority *int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Connection) Message(title string) *MessageBuilder {
|
||||||
|
return &MessageBuilder{conn: c, title: title}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MessageBuilder) Channel(channel string) *MessageBuilder {
|
||||||
|
c.channel = &channel
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MessageBuilder) Content(content string) *MessageBuilder {
|
||||||
|
c.content = &content
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MessageBuilder) Time(t time.Time) *MessageBuilder {
|
||||||
|
c.time = &t
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MessageBuilder) SenderName(sn string) *MessageBuilder {
|
||||||
|
c.sendername = &sn
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MessageBuilder) Priority(p int) *MessageBuilder {
|
||||||
|
c.priority = &p
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *MessageBuilder) Send(ctx context.Context) (MessageResponse, error) {
|
||||||
|
client := http.Client{Timeout: 5 * time.Second}
|
||||||
|
|
||||||
|
body := langext.H{}
|
||||||
|
|
||||||
|
body["user_id"] = c.conn.uid
|
||||||
|
body["key"] = c.conn.token
|
||||||
|
|
||||||
|
if c.channel != nil {
|
||||||
|
body["channel"] = *c.channel
|
||||||
|
}
|
||||||
|
|
||||||
|
body["title"] = c.title
|
||||||
|
|
||||||
|
if c.content != nil {
|
||||||
|
body["content"] = *c.content
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.sendername != nil {
|
||||||
|
body["content"] = *c.sendername
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.time != nil {
|
||||||
|
body["timestamp"] = c.time.Unix()
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.priority != nil {
|
||||||
|
body["priority"] = *c.priority
|
||||||
|
}
|
||||||
|
|
||||||
|
body["msg_id"] = langext.MustHexUUID()
|
||||||
|
|
||||||
|
rawbody, err := json.Marshal(body)
|
||||||
|
if err != nil {
|
||||||
|
return MessageResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(ctx, "POST", "https://simplecloudnotifier.de/", bytes.NewBuffer(rawbody))
|
||||||
|
if err != nil {
|
||||||
|
return MessageResponse{}, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return MessageResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() { _ = resp.Body.Close() }()
|
||||||
|
|
||||||
|
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
||||||
|
|
||||||
|
raw, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return MessageResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var mr MessageResponse
|
||||||
|
err = json.Unmarshal(raw, &mr)
|
||||||
|
if err != nil {
|
||||||
|
return MessageResponse{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return mr, nil
|
||||||
|
} else {
|
||||||
|
errMessage := resp.Status
|
||||||
|
|
||||||
|
if raw, err := io.ReadAll(resp.Body); err == nil {
|
||||||
|
var mr MessageErrResponse
|
||||||
|
if err = json.Unmarshal(raw, &mr); err == nil {
|
||||||
|
errMessage = mr.Message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode == 400 {
|
||||||
|
return MessageResponse{}, exerr.New(ErrBadRequest, errMessage).Build()
|
||||||
|
}
|
||||||
|
if resp.StatusCode == 401 {
|
||||||
|
return MessageResponse{}, exerr.New(ErrAuthFailed, errMessage).Build()
|
||||||
|
}
|
||||||
|
if resp.StatusCode == 403 {
|
||||||
|
return MessageResponse{}, exerr.New(ErrQuota, errMessage).Build()
|
||||||
|
}
|
||||||
|
if resp.StatusCode == 500 {
|
||||||
|
return MessageResponse{}, exerr.New(ErrInternalServerErr, errMessage).Build()
|
||||||
|
}
|
||||||
|
|
||||||
|
return MessageResponse{}, exerr.New(ErrOther, errMessage).Build()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
24
scn/send_test.go
Normal file
24
scn/send_test.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package scn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSendSCN(t *testing.T) {
|
||||||
|
t.Skip()
|
||||||
|
return
|
||||||
|
|
||||||
|
mr, err := New("TODO", "TODO").
|
||||||
|
Message("Hello Test").
|
||||||
|
Content("This is a test / goext").
|
||||||
|
Send(context.Background())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%+v\n", mr)
|
||||||
|
|
||||||
|
}
|
@@ -52,20 +52,24 @@ var ConverterRFCUnixTimeToUnixSeconds = NewDBTypeConverter[rfctime.UnixTime, int
|
|||||||
return rfctime.NewUnix(time.Unix(v, 0)), nil
|
return rfctime.NewUnix(time.Unix(v, 0)), nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// ConverterRFC339TimeToString
|
||||||
|
// Does not really use RFC339 - but sqlite does not understand timezones and the `T` delimiter
|
||||||
var ConverterRFC339TimeToString = NewDBTypeConverter[rfctime.RFC3339Time, string](func(v rfctime.RFC3339Time) (string, error) {
|
var ConverterRFC339TimeToString = NewDBTypeConverter[rfctime.RFC3339Time, string](func(v rfctime.RFC3339Time) (string, error) {
|
||||||
return v.Format(time.RFC3339), nil
|
return v.Time().In(time.UTC).Format("2006-01-02 15:04:05"), nil
|
||||||
}, func(v string) (rfctime.RFC3339Time, error) {
|
}, func(v string) (rfctime.RFC3339Time, error) {
|
||||||
t, err := time.Parse(time.RFC3339Nano, v)
|
t, err := time.Parse("2006-01-02 15:04:05", v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rfctime.RFC3339Time{}, err
|
return rfctime.RFC3339Time{}, err
|
||||||
}
|
}
|
||||||
return rfctime.NewRFC3339(t), nil
|
return rfctime.NewRFC3339(t), nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// ConverterRFC339NanoTimeToString
|
||||||
|
// Does not really use RFC339 - but sqlite does not understand timezones and the `T` delimiter
|
||||||
var ConverterRFC339NanoTimeToString = NewDBTypeConverter[rfctime.RFC3339NanoTime, string](func(v rfctime.RFC3339NanoTime) (string, error) {
|
var ConverterRFC339NanoTimeToString = NewDBTypeConverter[rfctime.RFC3339NanoTime, string](func(v rfctime.RFC3339NanoTime) (string, error) {
|
||||||
return v.Format(time.RFC3339Nano), nil
|
return v.Time().In(time.UTC).Format("2006-01-02 15:04:05.999999999"), nil
|
||||||
}, func(v string) (rfctime.RFC3339NanoTime, error) {
|
}, func(v string) (rfctime.RFC3339NanoTime, error) {
|
||||||
t, err := time.Parse(time.RFC3339Nano, v)
|
t, err := time.ParseInLocation("2006-01-02 15:04:05.999999999", v, time.UTC)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rfctime.RFC3339NanoTime{}, err
|
return rfctime.RFC3339NanoTime{}, err
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user