133 lines
4.2 KiB
Go
133 lines
4.2 KiB
Go
package linkpearl
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
|
|
"maunium.net/go/mautrix"
|
|
"maunium.net/go/mautrix/event"
|
|
"maunium.net/go/mautrix/format"
|
|
"maunium.net/go/mautrix/id"
|
|
)
|
|
|
|
const (
|
|
// MaxRetries is the maximum number of retries for sending a message
|
|
MaxRetries = 5
|
|
// DefaultTypingTimeout is the step delay for sending message retries
|
|
RetryDelay = 5 * time.Second
|
|
)
|
|
|
|
// SendMessageEvent sends a message event to the roomID and automatically retries if the server returns a 502 or 404 error
|
|
func (l *Linkpearl) SendMessageEvent(ctx context.Context, roomID id.RoomID, eventType event.Type, contentJSON any, currentAttempt ...int) (resp *mautrix.RespSendEvent, err error) {
|
|
attempt := 1
|
|
if len(currentAttempt) > 0 {
|
|
attempt = currentAttempt[0]
|
|
}
|
|
|
|
resp, err = l.api.SendMessageEvent(ctx, roomID, eventType, contentJSON)
|
|
if err == nil {
|
|
return resp, nil
|
|
}
|
|
err = UnwrapError(err)
|
|
if (strings.Contains(err.Error(), "HTTP 502") || strings.Contains(err.Error(), "HTTP 404")) && attempt <= MaxRetries {
|
|
l.log.Warn().
|
|
Err(err).
|
|
Str("roomID", roomID.String()).
|
|
Int("attempt", attempt).
|
|
Int("of", MaxRetries).
|
|
Msg("cannot send event, sleeping and retrying")
|
|
time.Sleep(RetryDelay * time.Duration(attempt))
|
|
return l.SendMessageEvent(ctx, roomID, eventType, contentJSON, attempt+1)
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
// Send a message to the roomID and automatically try to encrypt it, if the destination room is encrypted
|
|
//
|
|
//nolint:unparam // it's public interface
|
|
func (l *Linkpearl) Send(ctx context.Context, roomID id.RoomID, content any) (id.EventID, error) {
|
|
l.log.Debug().Str("roomID", roomID.String()).Any("content", content).Msg("sending event")
|
|
resp, err := l.SendMessageEvent(ctx, roomID, event.EventMessage, content)
|
|
if err != nil {
|
|
return "", UnwrapError(err)
|
|
}
|
|
return resp.EventID, nil
|
|
}
|
|
|
|
// SendTyping notification
|
|
func (l *Linkpearl) SendTyping(ctx context.Context, roomID id.RoomID, typing bool, timeout ...int) {
|
|
ttl := DefaultTypingTimeout
|
|
if len(timeout) > 0 {
|
|
ttl = timeout[0]
|
|
}
|
|
_, err := l.api.UserTyping(ctx, roomID, typing, time.Duration(ttl)*time.Second)
|
|
if err != nil {
|
|
l.log.Warn().Err(err).Bool("typing", typing).Msg("cannot set typing")
|
|
}
|
|
}
|
|
|
|
// SendNotice to a room with optional relations, markdown supported
|
|
func (l *Linkpearl) SendNotice(ctx context.Context, roomID id.RoomID, message string, relates ...*event.RelatesTo) {
|
|
var withRelatesTo bool
|
|
content := format.RenderMarkdown(message, true, true)
|
|
content.MsgType = event.MsgNotice
|
|
if len(relates) > 0 {
|
|
withRelatesTo = true
|
|
content.RelatesTo = relates[0]
|
|
}
|
|
|
|
_, err := l.Send(ctx, roomID, &content)
|
|
if err != nil {
|
|
l.log.Error().Err(UnwrapError(err)).Str("roomID", roomID.String()).Str("retries", "1/2").Msg("cannot send a notice into the room")
|
|
if withRelatesTo {
|
|
content.RelatesTo = nil
|
|
_, err = l.Send(ctx, roomID, &content)
|
|
if err != nil {
|
|
l.log.Error().Err(UnwrapError(err)).Str("roomID", roomID.String()).Str("retries", "2/2").Msg("cannot send a notice into the room even without relations")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// SendFile to a matrix room
|
|
func (l *Linkpearl) SendFile(ctx context.Context, roomID id.RoomID, req *mautrix.ReqUploadMedia, msgtype event.MessageType, relates ...*event.RelatesTo) error {
|
|
var relation *event.RelatesTo
|
|
if len(relates) > 0 {
|
|
relation = relates[0]
|
|
}
|
|
|
|
resp, err := l.GetClient().UploadMedia(ctx, *req)
|
|
if err != nil {
|
|
err = UnwrapError(err)
|
|
l.log.Error().Err(err).Str("file", req.FileName).Msg("cannot upload file")
|
|
return err
|
|
}
|
|
content := &event.MessageEventContent{
|
|
MsgType: msgtype,
|
|
Body: req.FileName,
|
|
FileName: req.FileName,
|
|
Info: &event.FileInfo{
|
|
Size: int(req.ContentLength),
|
|
MimeType: req.ContentType,
|
|
},
|
|
URL: resp.ContentURI.CUString(),
|
|
RelatesTo: relation,
|
|
}
|
|
|
|
_, err = l.Send(ctx, roomID, content)
|
|
err = UnwrapError(err)
|
|
if err != nil {
|
|
l.log.Error().Err(err).Str("roomID", roomID.String()).Str("retries", "1/2").Msg("cannot send file into the room")
|
|
if relation != nil {
|
|
content.RelatesTo = nil
|
|
_, err = l.Send(ctx, roomID, &content)
|
|
err = UnwrapError(err)
|
|
if err != nil {
|
|
l.log.Error().Err(UnwrapError(err)).Str("roomID", roomID.String()).Str("retries", "2/2").Msg("cannot send file into the room even without relations")
|
|
}
|
|
}
|
|
}
|
|
|
|
return err
|
|
}
|