Skip to content

Commit 3c05c83

Browse files
committed
Attempting to fix Kick and YouTube chats
1 parent 3f9002b commit 3c05c83

33 files changed

Lines changed: 4102 additions & 2221 deletions

Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ checkconfig-android:
168168
streampanel-android-arm64-in-docker: build-streampanel-android-arm64-in-docker check-streampanel-android-arm64-static-cgo
169169

170170
build-streampanel-android-arm64-in-docker: checkconfig-android-in-docker builddir $(GOPATH)/bin/pkg-config-wrapper
171-
go mod tidy
172171
git config --global --add safe.directory /project
173172
$(eval ANDROID_NDK_HOME=$(shell ls -d /home/builder/lib/android-ndk-* | tail -1))
174173
cd cmd/streampanel && \

cmd/streampanel/FyneApp.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ Website = "https://github.com/xaionaro/streamctl"
55
Name = "streampanel"
66
ID = "center.dx.streampanel"
77
Version = "0.1.0"
8-
Build = 437
8+
Build = 438

go.mod

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ replace github.com/joeyak/go-twitch-eventsub/v3 => github.com/xaionaro-go/go-twi
3333

3434
replace github.com/scorfly/gokick => github.com/xaionaro-go/gokick v0.0.0-20250713175656-f538d6396851
3535

36-
replace github.com/abhinavxd/youtube-live-chat-downloader/v2 => github.com/xaionaro-go/youtube-live-chat-downloader/v2 v2.0.0-20250726224735-811554015ae8
37-
3836
replace github.com/Danny-Dasilva/CycleTLS => github.com/xaionaro-go/CycleTLS v0.0.0-20250923213111-aed0022ae7b5
3937

4038
replace github.com/dexterlb/mpvipc => github.com/xaionaro-go/mpvipc v0.0.0-20251019230357-e0f534e5dde4
4139

4240
replace github.com/RomainMichau/cloudscraper_go => github.com/xaionaro-go/cloudscraper v0.0.0-20251019213127-d3687042cb55
4341

42+
replace github.com/abhinavxd/youtube-live-chat-downloader/v2 => github.com/xaionaro-go/youtube-live-chat-downloader/v2 v2.0.0-20251025201126-e815a074fd2c
43+
4444
require (
4545
github.com/facebookincubator/go-belt v0.0.0-20250308011339-62fb7027b11f
4646
github.com/go-git/go-billy/v5 v5.6.2
@@ -214,7 +214,7 @@ require (
214214
github.com/prometheus/common v0.62.0 // indirect
215215
github.com/prometheus/procfs v0.15.1 // indirect
216216
github.com/quic-go/qpack v0.5.1 // indirect
217-
github.com/quic-go/quic-go v0.54.0 // indirect
217+
github.com/quic-go/quic-go v0.55.0 // indirect
218218
github.com/refraction-networking/uquic v0.0.6 // indirect
219219
github.com/refraction-networking/utls v1.8.0 // indirect
220220
github.com/rubenv/sql-migrate v1.7.0 // indirect
@@ -259,7 +259,7 @@ require (
259259
go.opentelemetry.io/otel v1.36.0 // indirect
260260
go.opentelemetry.io/otel/metric v1.36.0 // indirect
261261
go.opentelemetry.io/otel/trace v1.36.0 // indirect
262-
go.uber.org/mock v0.5.0 // indirect
262+
go.uber.org/mock v0.5.2 // indirect
263263
go.uber.org/multierr v1.11.0 // indirect
264264
go.uber.org/zap v1.27.0 // indirect
265265
gocv.io/x/gocv v0.41.0 // indirect
@@ -329,7 +329,7 @@ require (
329329
github.com/xaionaro-go/go-rtmp v0.0.0-20241009130244-1e3160f27f42
330330
github.com/xaionaro-go/grpcproxy v0.0.0-20241103205849-a8fef42e72f9
331331
github.com/xaionaro-go/iterate v0.0.0-20250406123757-7802d56b52ce
332-
github.com/xaionaro-go/kickcom v0.0.0-20251020001342-56d643f3dccf
332+
github.com/xaionaro-go/kickcom v0.0.0-20251025201043-15900e6712af
333333
github.com/xaionaro-go/lockmap v0.0.0-20240901172806-e17aea364748
334334
github.com/xaionaro-go/logwriter v0.0.0-20250111154941-c3f7a1a2d567
335335
github.com/xaionaro-go/mediamtx v0.0.0-20250406132618-79ecbc3e138f

go.sum

100755100644
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -953,8 +953,8 @@ github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
953953
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
954954
github.com/quic-go/qtls-go1-20 v0.3.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
955955
github.com/quic-go/quic-go v0.37.4/go.mod h1:YsbH1r4mSHPJcLF4k4zruUkLBqctEMBDR6VPvcYjIsU=
956-
github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg=
957-
github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
956+
github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=
957+
github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U=
958958
github.com/refraction-networking/uquic v0.0.6 h1:9ol1oOaOpHDeeDlBY7u228jK+T5oic35QrFimHVaCMM=
959959
github.com/refraction-networking/uquic v0.0.6/go.mod h1:TFgTmV/yqVCMEXVwP7z7PMAhzye02rFHLV6cRAg59jc=
960960
github.com/refraction-networking/utls v1.5.4/go.mod h1:SPuDbBmgLGp8s+HLNc83FuavwZCFoMmExj+ltUHiHUw=
@@ -1141,8 +1141,8 @@ github.com/xaionaro-go/helix/v2 v2.0.0-20250309182928-f54c9d4c8a29 h1:k7WLDHIK0A
11411141
github.com/xaionaro-go/helix/v2 v2.0.0-20250309182928-f54c9d4c8a29/go.mod h1:e1GsZq4NDk9sQlPJ0Nr3+14R9cizqg09VAk7/IonpOU=
11421142
github.com/xaionaro-go/iterate v0.0.0-20250406123757-7802d56b52ce h1:4a0vM4EOq7cU15TTmJHX66vX2cXA7RgVX3bWyj4ZVw4=
11431143
github.com/xaionaro-go/iterate v0.0.0-20250406123757-7802d56b52ce/go.mod h1:Dx52o1WH1xUoV8jjpiIVTRZ/rNoPNPcnLdMrQ5D2FH0=
1144-
github.com/xaionaro-go/kickcom v0.0.0-20251020001342-56d643f3dccf h1:bIRQa7SWL1GXIwyQtCqKUP7R2y3DJEzI5E+PJz7dYl0=
1145-
github.com/xaionaro-go/kickcom v0.0.0-20251020001342-56d643f3dccf/go.mod h1:dxsKxBKOTkPeeXejFkmmIuSpHVSJo8X1rv2O7iPZKj0=
1144+
github.com/xaionaro-go/kickcom v0.0.0-20251025201043-15900e6712af h1:j9qN7/Ph/CgdLFDpC5p1UdETs+NeC8sQhhov5mjBCxQ=
1145+
github.com/xaionaro-go/kickcom v0.0.0-20251025201043-15900e6712af/go.mod h1:rpsgYYdyrXwVAspMU0Nh3V8FBl5ILIgQWhZiR727KRY=
11461146
github.com/xaionaro-go/libsrt v0.0.0-20250505013920-61d894a3b7e9 h1:z5K1pa9cJZ2oqFNWyyxrxO/50Hv4Gn+1kkfXTHkoKNM=
11471147
github.com/xaionaro-go/libsrt v0.0.0-20250505013920-61d894a3b7e9/go.mod h1:yH5w7hdIyhbR4p0WfABH9fLIIK2ZwPd5CKk2K2ND/vo=
11481148
github.com/xaionaro-go/lockmap v0.0.0-20240901172806-e17aea364748 h1:SlB3zLAuLgRxdOo250gMUG/7hSiEU2NzEUNYbJDuI2A=
@@ -1198,8 +1198,8 @@ github.com/xaionaro-go/xpath v0.0.0-20250111145115-55f5728f643f h1:ofxY1akRlVdJ/
11981198
github.com/xaionaro-go/xpath v0.0.0-20250111145115-55f5728f643f/go.mod h1:f0DVcqddOy1RALOgXJHwpQnkp1u1yeBX/+A2+Bf4EGc=
11991199
github.com/xaionaro-go/xsync v0.0.0-20250928140805-f801683b71ba h1:eRxxULTIaR7PSHMrj4yRDZd1trSZSDl4hcxRxzd+AJg=
12001200
github.com/xaionaro-go/xsync v0.0.0-20250928140805-f801683b71ba/go.mod h1:FCpywNAl4a4hgzE8j7Z+TpdhBQi5WHxnI35jOrFpoQw=
1201-
github.com/xaionaro-go/youtube-live-chat-downloader/v2 v2.0.0-20250726224735-811554015ae8 h1:iRcIRlIryjDkgFoKJZQQWra/zv783CnKtXnpq9z7VTQ=
1202-
github.com/xaionaro-go/youtube-live-chat-downloader/v2 v2.0.0-20250726224735-811554015ae8/go.mod h1:TrUogg8mrebgMD/JU094CmSXn3yKrt+CZjiDL3YtmMw=
1201+
github.com/xaionaro-go/youtube-live-chat-downloader/v2 v2.0.0-20251025201126-e815a074fd2c h1:ycVt/n/TMGQM26QEUELOlHQjTq7M2k9wFr4T2/3OoRY=
1202+
github.com/xaionaro-go/youtube-live-chat-downloader/v2 v2.0.0-20251025201126-e815a074fd2c/go.mod h1:skCvdVw1Gf9sVvlsPlE2xieWVQD8e+4GdGz/V9oSLVg=
12031203
github.com/xaionaro-go/zerolog2belt v0.0.0-20241103164018-a3bc1ea487e5 h1:jAy7VLg8y8XE1R8jBte4PRDJzOaAE+sUfmttfB9ZcAY=
12041204
github.com/xaionaro-go/zerolog2belt v0.0.0-20241103164018-a3bc1ea487e5/go.mod h1:KJuX7yl27vU+KV6CpsWOe5ZMY4zSg70hvEhwoYdr17w=
12051205
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
@@ -1257,8 +1257,8 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
12571257
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
12581258
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
12591259
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
1260-
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
1261-
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
1260+
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
1261+
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
12621262
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
12631263
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
12641264
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=

pkg/streamcontrol/kick/chat_handler_obsolete.go

Lines changed: 6 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -2,170 +2,22 @@ package kick
22

33
import (
44
"context"
5-
"fmt"
6-
"slices"
7-
"strconv"
8-
"time"
95

10-
"github.com/facebookincubator/go-belt/tool/logger"
11-
"github.com/xaionaro-go/kickcom"
12-
"github.com/xaionaro-go/observability"
13-
"github.com/xaionaro-go/streamctl/pkg/streamcontrol"
6+
"github.com/xaionaro-go/streamctl/pkg/streamcontrol/kick/chathandlerobsolete"
147
)
158

16-
type ChatClientOBSOLETE interface {
17-
GetChatMessagesV2(
18-
ctx context.Context,
19-
channelID uint64,
20-
cursor uint64,
21-
) (*kickcom.ChatMessagesV2Reply, error)
22-
}
23-
24-
type ChatHandlerOBSOLETE struct {
25-
currentCursor uint64
26-
channelID uint64
27-
lastMessageID string
28-
client ChatClientOBSOLETE
29-
cancelFunc context.CancelFunc
30-
messagesOutChan chan streamcontrol.ChatMessage
31-
onClose func(context.Context, *ChatHandlerOBSOLETE)
32-
}
9+
type ChatHandlerOBSOLETE = chathandlerobsolete.ChatHandlerOBSOLETE
3310

3411
func (k *Kick) newChatHandlerOBSOLETE(
3512
ctx context.Context,
3613
channelSlug string,
37-
onClose func(context.Context, *ChatHandlerOBSOLETE),
3814
) (*ChatHandlerOBSOLETE, error) {
39-
reverseEngClient, err := kickcom.New()
40-
if err != nil {
41-
return nil, fmt.Errorf("unable to initialize a client to Kick: %w", err)
42-
}
43-
44-
var resp *kickcom.ChannelV1
45-
{
46-
ctx, cancelFn := context.WithTimeout(ctx, time.Minute)
47-
resp, err = reverseEngClient.GetChannelV1(ctx, channelSlug)
48-
cancelFn()
49-
if err != nil {
50-
return nil, fmt.Errorf("unable to get channel '%s' info: %w", channelSlug, err)
51-
}
52-
}
53-
return NewChatHandlerOBSOLETE(ctx, reverseEngClient, resp.ID, onClose)
15+
return NewChatHandlerOBSOLETE(ctx, channelSlug)
5416
}
5517

5618
func NewChatHandlerOBSOLETE(
5719
ctx context.Context,
58-
chatClient ChatClientOBSOLETE,
59-
channelID uint64,
60-
onClose func(context.Context, *ChatHandlerOBSOLETE),
61-
) (_ret *ChatHandlerOBSOLETE, _err error) {
62-
logger.Debugf(ctx, "NewChatHandlerOBSOLETE(ctx, client, %d, %p)", channelID, onClose)
63-
defer func() {
64-
logger.Debugf(ctx, "/NewChatHandlerOBSOLETE(ctx, client, %d, %p): %#+v %v", channelID, onClose, _ret, _err)
65-
}()
66-
67-
ctx, cancelFn := context.WithCancel(ctx)
68-
h := &ChatHandlerOBSOLETE{
69-
currentCursor: 0,
70-
client: chatClient,
71-
channelID: channelID,
72-
cancelFunc: cancelFn,
73-
onClose: onClose,
74-
}
75-
h.init(ctx)
76-
return h, nil
77-
}
78-
79-
func (h *ChatHandlerOBSOLETE) init(ctx context.Context) {
80-
h.messagesOutChan = make(chan streamcontrol.ChatMessage, 100)
81-
observability.Go(ctx, func(ctx context.Context) {
82-
if h.onClose != nil {
83-
defer h.onClose(ctx, h)
84-
}
85-
defer close(h.messagesOutChan)
86-
h.loop(ctx)
87-
})
88-
}
89-
90-
func (h *ChatHandlerOBSOLETE) loop(ctx context.Context) {
91-
err := h.iterate(ctx)
92-
if err != nil {
93-
logger.Errorf(ctx, "unable to perform an iteration: %v", err)
94-
return
95-
}
96-
97-
t := time.NewTicker(time.Second)
98-
defer t.Stop()
99-
for {
100-
select {
101-
case <-ctx.Done():
102-
return
103-
case <-t.C:
104-
}
105-
err := h.iterate(ctx)
106-
if err != nil {
107-
logger.Errorf(ctx, "unable to perform an iteration: %v", err)
108-
return
109-
}
110-
}
111-
}
112-
113-
func (h *ChatHandlerOBSOLETE) iterate(ctx context.Context) error {
114-
startTS := time.Now()
115-
reply, err := h.client.GetChatMessagesV2(ctx, uint64(h.channelID), 0)
116-
if err != nil {
117-
return fmt.Errorf("unable to get the chat messages of channel with ID %d: %w", h.channelID, err)
118-
}
119-
rtt := time.Since(startTS)
120-
logger.Tracef(ctx, "round trip time == %v (messages count: %d)", rtt, len(reply.Data.Messages))
121-
122-
// TODO: use the cursor instead of message ID to avoid duplicates
123-
if reply.Data.Cursor != "" {
124-
cursor, err := strconv.ParseUint(reply.Data.Cursor, 10, 64)
125-
if err != nil {
126-
return fmt.Errorf("unable to parse the cursor value '%s': %w", reply.Data.Cursor, err)
127-
}
128-
h.currentCursor = cursor
129-
} else {
130-
h.currentCursor = 0
131-
}
132-
133-
// assuming reply.Data is already sorted by CreatedAt DESC
134-
135-
slices.Reverse(reply.Data.Messages)
136-
137-
// skipping everything we already notified about
138-
var firstNewIdx int
139-
for idx, msg := range reply.Data.Messages {
140-
if msg.ID == h.lastMessageID {
141-
firstNewIdx = idx + 1
142-
break
143-
}
144-
}
145-
146-
for _, msg := range reply.Data.Messages[firstNewIdx:] {
147-
h.sendMessage(msg)
148-
}
149-
return nil
150-
}
151-
152-
func (h *ChatHandlerOBSOLETE) sendMessage(
153-
msg kickcom.ChatMessageV2,
154-
) {
155-
h.lastMessageID = msg.ID
156-
select {
157-
case h.messagesOutChan <- streamcontrol.ChatMessage{
158-
CreatedAt: msg.CreatedAt,
159-
EventType: streamcontrol.EventTypeChatMessage,
160-
UserID: streamcontrol.ChatUserID(fmt.Sprintf("%d", msg.UserID)),
161-
Username: msg.Sender.Slug,
162-
MessageID: streamcontrol.ChatMessageID(msg.ID),
163-
Message: msg.Content,
164-
MessageFormatType: streamcontrol.TextFormatTypePlain,
165-
}:
166-
default:
167-
}
168-
}
169-
func (h *ChatHandlerOBSOLETE) MessagesChan() <-chan streamcontrol.ChatMessage {
170-
return h.messagesOutChan
20+
channelSlug string,
21+
) (*ChatHandlerOBSOLETE, error) {
22+
return chathandlerobsolete.New(ctx, channelSlug)
17123
}

0 commit comments

Comments
 (0)