Compare commits
No commits in common. "f35ec00a169017f85b2d10ca693db85b8eb443c6" and "35489361fe2d76311ee404f5ea90ddfbffc3b452" have entirely different histories.
f35ec00a16
...
35489361fe
73
chat.go
73
chat.go
|
@ -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
|
||||||
|
|
||||||
|
|
16
client.go
16
client.go
|
@ -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
4
go.mod
|
@ -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
4
go.sum
|
@ -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
6
vendor/modules.txt
vendored
|
@ -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
|
|
||||||
|
|
Loading…
Reference in a new issue