-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathhandler.go
More file actions
102 lines (89 loc) · 3.42 KB
/
Copy pathhandler.go
File metadata and controls
102 lines (89 loc) · 3.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package handlers
import (
"context"
"errors"
"fmt"
"net/http"
"strings"
"github.com/rs/zerolog"
"maunium.net/go/mautrix/bridgev2"
"maunium.net/go/mautrix/event"
"github.com/highesttt/matrix-line-messenger/pkg/line"
)
// Handler provides dependencies needed by content type conversion functions.
type Handler struct {
Log zerolog.Logger
HTTPClient *http.Client
// RecoverToken attempts to restore a valid session by refreshing or re-logging in.
RecoverToken func(ctx context.Context) error
ShouldRecover func(ctx context.Context, err error) bool
IsRefreshRequired func(err error) bool
IsLoggedOut func(err error) bool
HandleLoggedOut func(ctx context.Context, err error)
// NewClient creates a new LINE API client with the current access token.
NewClient func() *line.Client
// DownloadOBSResource overrides non-talk OBS downloads in tests.
DownloadOBSResource func(ctx context.Context, client *line.Client, service, sid, oid string) ([]byte, error)
// DownloadAlbumPreview overrides album thumbnail downloads in tests.
DownloadAlbumPreview func(ctx context.Context, client *line.Client, oid, chatID, albumID string) ([]byte, error)
// DecryptMedia decrypts E2EE encrypted media data using the given key material.
DecryptMedia func(data []byte, keyMaterial string) ([]byte, error)
}
func (h *Handler) downloadAlbumPreview(ctx context.Context, client *line.Client, oid, chatID, albumID string) ([]byte, error) {
if h.DownloadAlbumPreview != nil {
return h.DownloadAlbumPreview(ctx, client, oid, chatID, albumID)
}
return client.DownloadAlbumPreview(ctx, oid, chatID, albumID)
}
func obsTalkMetaMessageID(messageID string, isPlainMedia bool) string {
if isPlainMedia {
return ""
}
return messageID
}
func mediaDownloadFailure(kind string, err error, relatesTo *event.RelatesTo) (*bridgev2.ConvertedMessage, error) {
if !errors.Is(err, line.ErrOBSObjectNotFound) {
// Keep ambiguous OBS failures retryable. Returning ErrIgnoringRemoteEvent
// prevents bridgev2 from posting a generic error notice, while omitting a
// converted message means the remote event isn't stored as successfully
// bridged and can be retried by a later backfill.
return nil, fmt.Errorf("%w: failed to download %s from LINE OBS: %w", bridgev2.ErrIgnoringRemoteEvent, strings.ToLower(kind), err)
}
return &bridgev2.ConvertedMessage{
Parts: []*bridgev2.ConvertedMessagePart{
{
Type: event.EventMessage,
Content: &event.MessageEventContent{
MsgType: event.MsgNotice,
Body: fmt.Sprintf("[%s unavailable — LINE media expired before it could be bridged]", kind),
RelatesTo: relatesTo,
},
},
},
}, nil
}
// tryRecoverClient attempts token recovery on auth errors and returns a fresh client.
// Returns (newClient, true) on success, (nil, false) if recovery was not needed or failed.
func (h *Handler) tryRecoverClient(ctx context.Context, err error) (*line.Client, bool) {
if err == nil {
return nil, false
}
if h.IsLoggedOut(err) {
if h.HandleLoggedOut != nil {
h.HandleLoggedOut(ctx, err)
}
return nil, false
}
if h.ShouldRecover != nil {
if !h.ShouldRecover(ctx, err) {
return nil, false
}
} else if !line.IsUnauthorizedStatus(err) && !h.IsRefreshRequired(err) {
return nil, false
}
if errRecover := h.RecoverToken(ctx); errRecover != nil {
h.Log.Warn().Err(errRecover).Msg("Failed to recover token for media download")
return nil, false
}
return h.NewClient(), true
}