Compare commits

..

No commits in common. "f35ec00a169017f85b2d10ca693db85b8eb443c6" and "35489361fe2d76311ee404f5ea90ddfbffc3b452" have entirely different histories.

7 changed files with 43 additions and 76 deletions

73
chat.go
View file

@ -13,23 +13,9 @@ import (
"time" "time"
"github.com/r3labs/sse/v2" "github.com/r3labs/sse/v2"
"github.com/tylertravisty/go-utils/random"
"golang.org/x/net/html" "golang.org/x/net/html"
"gopkg.in/cenkalti/backoff.v1" "gopkg.in/cenkalti/backoff.v1"
"travisty.io/tyler/go-utils/random"
)
const (
ChatBadgeRecurringSubscription = "recurring_subscription"
ChatBadgeLocalsSupporter = "locals_supporter"
ChatTypeInit = "init"
ChatTypeMessages = "messages"
ChatTypeMuteUsers = "mute_users"
ChatTypeDeleteMessages = "delete_messages"
ChatTypeSubscriber = "locals_supporter"
ChatTypeRaiding = "raid_confirmed"
ChatTypePinMessage = "pin_message"
ChatTypeUnpinMessage = "unpin_message"
) )
type ChatInfo struct { type ChatInfo struct {
@ -79,6 +65,24 @@ func (c *Client) getChatInfo() (*ChatInfo, error) {
lineS, err := r.ReadString('\n') lineS, err := r.ReadString('\n')
for err == nil { for err == nil {
if strings.Contains(lineS, "RumbleChat(") { if strings.Contains(lineS, "RumbleChat(") {
//start := strings.Index(lineS, "RumbleChat(") + len("RumbleChat(")
//if start == -1 {
// return nil, fmt.Errorf("error finding chat function in webpage")
//}
//end := strings.Index(lineS[start:], ");")
//if end == -1 {
// return nil, fmt.Errorf("error finding end of chat function in webpage")
//}
//argsS := strings.ReplaceAll(lineS[start:start+end], ", ", ",")
//argsS = strings.Replace(argsS, "[", "\"[", 1)
//n := strings.LastIndex(argsS, "]")
//argsS = argsS[:n] + "]\"" + argsS[n+1:]
//c := csv.NewReader(strings.NewReader(argsS))
//args, err := c.ReadAll()
//if err != nil {
// return nil, fmt.Errorf("error parsing csv: %v", err)
//}
//info := args[0]
start := strings.Index(lineS, "RumbleChat(") + len("RumbleChat(") start := strings.Index(lineS, "RumbleChat(") + len("RumbleChat(")
if start == -1 { if start == -1 {
return nil, fmt.Errorf("error finding chat function in webpage") return nil, fmt.Errorf("error finding chat function in webpage")
@ -88,11 +92,11 @@ func (c *Client) getChatInfo() (*ChatInfo, error) {
return nil, fmt.Errorf("error finding end of chat function in webpage") return nil, fmt.Errorf("error finding end of chat function in webpage")
} }
args := parseRumbleChatArgs(lineS[start : start+end]) args := parseRumbleChatArgs(lineS[start : start+end])
channelID, err := strconv.Atoi(args[6]) channelID, err := strconv.Atoi(args[5])
if err != nil { if err != nil {
return nil, fmt.Errorf("error converting channel ID argument string to int: %v", err) return nil, fmt.Errorf("error converting channel ID argument string to int: %v", err)
} }
chatInfo = &ChatInfo{ChannelID: channelID, ChatID: args[2], UrlPrefix: args[0]} chatInfo = &ChatInfo{ChannelID: channelID, ChatID: args[1], UrlPrefix: args[0]}
} else if strings.Contains(lineS, "media-by--a") && strings.Contains(lineS, "author") { } else if strings.Contains(lineS, "media-by--a") && strings.Contains(lineS, "author") {
r := strings.NewReader(lineS) r := strings.NewReader(lineS)
node, err := html.Parse(r) node, err := html.Parse(r)
@ -128,7 +132,7 @@ func parseRumbleChatArgs(argsS string) []string {
arg := []rune{} arg := []rune{}
for _, c := range argsS { for _, c := range argsS {
if c == ',' && open == 0 { if c == ',' && open == 0 {
args = append(args, trimRumbleChatArg(string(arg))) args = append(args, string(arg))
arg = []rune{} arg = []rune{}
} else { } else {
if c == '[' { if c == '[' {
@ -142,16 +146,12 @@ func parseRumbleChatArgs(argsS string) []string {
} }
} }
if len(arg) > 0 { if len(arg) > 0 {
args = append(args, trimRumbleChatArg(string(arg))) args = append(args, string(arg))
} }
return args return args
} }
func trimRumbleChatArg(arg string) string {
return strings.Trim(strings.TrimSpace(arg), "\"")
}
type ChatMessage struct { type ChatMessage struct {
Text string `json:"text"` Text string `json:"text"`
} }
@ -258,15 +258,6 @@ type ChatEventBlock struct {
Type string `json:"type"` Type string `json:"type"`
} }
type ChatEventNotification struct {
Badge string `json:"badge"`
Text string `json:"text"`
}
type ChatEventRaidNotification struct {
StartTs int64 `json:"start_ts"`
}
type ChatEventRant struct { type ChatEventRant struct {
Duration int `json:"duration"` Duration int `json:"duration"`
ExpiresOn string `json:"expires_on"` ExpiresOn string `json:"expires_on"`
@ -277,8 +268,6 @@ type ChatEventMessage struct {
Blocks []ChatEventBlock `json:"blocks"` Blocks []ChatEventBlock `json:"blocks"`
ChannelID *int64 `json:"channel_id"` ChannelID *int64 `json:"channel_id"`
ID string `json:"id"` ID string `json:"id"`
Notification *ChatEventNotification `json:"notification"`
RaidNotification *ChatEventRaidNotification `json:"raid_notification"`
Rant *ChatEventRant `json:"rant"` Rant *ChatEventRant `json:"rant"`
Text string `json:"text"` Text string `json:"text"`
Time string `json:"time"` Time string `json:"time"`
@ -403,11 +392,8 @@ type ChatView struct {
ImageUrl string ImageUrl string
Init bool Init bool
IsFollower bool IsFollower bool
Raid bool
Rant int Rant int
Sub bool
Text string Text string
Time time.Time
Type string Type string
Username string Username string
} }
@ -469,23 +455,10 @@ func parseMessages(eventType string, messages []ChatEventMessage, users map[stri
view.Color = user.Color view.Color = user.Color
view.ImageUrl = user.Image1 view.ImageUrl = user.Image1
view.IsFollower = user.IsFollower view.IsFollower = user.IsFollower
if message.RaidNotification != nil {
view.Raid = true
}
if message.Rant != nil { if message.Rant != nil {
view.Rant = message.Rant.PriceCents view.Rant = message.Rant.PriceCents
} }
if message.Notification != nil {
if message.Notification.Badge == ChatBadgeRecurringSubscription {
view.Sub = true
}
}
view.Text = message.Text view.Text = message.Text
t, err := time.Parse(time.RFC3339, message.Time)
if err != nil {
return nil, fmt.Errorf("error parsing message time: %v", err)
}
view.Time = t
view.Type = eventType view.Type = eventType
view.Username = user.Username view.Username = user.Username

View file

@ -273,37 +273,31 @@ func (c *Client) userLogout() error {
return nil return nil
} }
type LoggedInResponseData struct {
Username string `json:"username"`
}
type LoggedInResponseUser struct { type LoggedInResponseUser struct {
ID string `json:"id"`
LoggedIn bool `json:"logged_in"` LoggedIn bool `json:"logged_in"`
} }
type LoggedInResponse struct { type LoggedInResponse struct {
Data LoggedInResponseData `json:"data"`
User LoggedInResponseUser `json:"user"` User LoggedInResponseUser `json:"user"`
} }
func (c *Client) LoggedIn() (*LoggedInResponse, error) { func (c *Client) LoggedIn() (bool, error) {
resp, err := c.httpClient.Get(urlUserLogin) resp, err := c.httpClient.Get(urlUserLogin)
if err != nil { if err != nil {
return nil, pkgErr("error getting login service", err) return false, pkgErr("error getting login service", err)
} }
defer resp.Body.Close() defer resp.Body.Close()
bodyB, err := io.ReadAll(resp.Body) bodyB, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
return nil, pkgErr("error reading body bytes", err) return false, pkgErr("error reading body bytes", err)
} }
var lir LoggedInResponse var lir LoggedInResponse
err = json.NewDecoder(strings.NewReader(string(bodyB))).Decode(&lir) err = json.NewDecoder(strings.NewReader(string(bodyB))).Decode(&lir)
if err != nil { if err != nil {
return nil, pkgErr("error un-marshaling response body", err) return false, pkgErr("error un-marshaling response body", err)
} }
return &lir, nil return lir.User.LoggedIn, nil
} }

4
go.mod
View file

@ -1,13 +1,13 @@
module travisty.io/tyler/rumble-livestream-lib-go module github.com/tylertravisty/rumble-livestream-lib-go
go 1.19 go 1.19
require ( require (
github.com/r3labs/sse/v2 v2.10.0 github.com/r3labs/sse/v2 v2.10.0
github.com/robertkrimen/otto v0.2.1 github.com/robertkrimen/otto v0.2.1
github.com/tylertravisty/go-utils v0.0.0-20230524204414-6893ae548909
golang.org/x/net v0.24.0 golang.org/x/net v0.24.0
gopkg.in/cenkalti/backoff.v1 v1.1.0 gopkg.in/cenkalti/backoff.v1 v1.1.0
travisty.io/tyler/go-utils v0.0.0-20240614172648-00b0b1a557b4
) )
require ( require (

4
go.sum
View file

@ -9,6 +9,8 @@ github.com/robertkrimen/otto v0.2.1/go.mod h1:UPwtJ1Xu7JrLcZjNWN8orJaM5n5YEtqL//
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/tylertravisty/go-utils v0.0.0-20230524204414-6893ae548909 h1:xrjIFqzGQXlCrCdMPpW6+SodGFSlrQ3ZNUCr3f5tF1g=
github.com/tylertravisty/go-utils v0.0.0-20230524204414-6893ae548909/go.mod h1:2W31Jhs9YSy7y500wsCOW0bcamGi9foQV1CKrfvfTxk=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
@ -24,5 +26,3 @@ gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
travisty.io/tyler/go-utils v0.0.0-20240614172648-00b0b1a557b4 h1:/InkkmR3O6lh63ckLJe14k1DRB6RuOZJv5TpfxGVRKQ=
travisty.io/tyler/go-utils v0.0.0-20240614172648-00b0b1a557b4/go.mod h1:2inG89XtlVnppctG2WnKir4mWWN0zbF/PB9m1HXdTYI=

6
vendor/modules.txt vendored
View file

@ -10,6 +10,9 @@ github.com/robertkrimen/otto/file
github.com/robertkrimen/otto/parser github.com/robertkrimen/otto/parser
github.com/robertkrimen/otto/registry github.com/robertkrimen/otto/registry
github.com/robertkrimen/otto/token github.com/robertkrimen/otto/token
# github.com/tylertravisty/go-utils v0.0.0-20230524204414-6893ae548909
## explicit; go 1.16
github.com/tylertravisty/go-utils/random
# golang.org/x/net v0.24.0 # golang.org/x/net v0.24.0
## explicit; go 1.18 ## explicit; go 1.18
golang.org/x/net/context golang.org/x/net/context
@ -37,6 +40,3 @@ gopkg.in/cenkalti/backoff.v1
## explicit ## explicit
gopkg.in/sourcemap.v1 gopkg.in/sourcemap.v1
gopkg.in/sourcemap.v1/base64vlq gopkg.in/sourcemap.v1/base64vlq
# travisty.io/tyler/go-utils v0.0.0-20240614172648-00b0b1a557b4
## explicit; go 1.16
travisty.io/tyler/go-utils/random