Compare commits
No commits in common. "daceefe5481eb08035c0a73ef7febf6262c0ef3d" and "562b90ebf777f74c733b54f97b92f9889a1678af" have entirely different histories.
daceefe548
...
562b90ebf7
52
NOTES.md
52
NOTES.md
|
@ -1,60 +1,21 @@
|
|||
# Roadmap
|
||||
|
||||
Rum Goggles App:
|
||||
|
||||
v1-beta:
|
||||
- Chat bot rule triggers on stream events
|
||||
- On: follow, subscribe, rant, raid
|
||||
- Chat polls
|
||||
- Stream statistics
|
||||
|
||||
v1.N:
|
||||
- Download subscriber data, track re-subs, trigger rules on re-subs
|
||||
- Stream moderator bot
|
||||
- OBS integration
|
||||
|
||||
Rum Goggles Service:
|
||||
- Chat polls
|
||||
- Monitor all live stream chats
|
||||
- Channel points
|
||||
- Spam/Troll tracking
|
||||
|
||||
# Bugs
|
||||
|
||||
Chat bot rule menu back button does not work in macOS
|
||||
|
||||
If connection to chat stream breaks, gracefully handle error
|
||||
- try to reconnect
|
||||
- let the chat rules know, etc.
|
||||
- test with VPN
|
||||
|
||||
# Doing
|
||||
|
||||
Add bypass to commands for:
|
||||
- Host, admin, mod, etc.
|
||||
|
||||
Monitor how many handlers are listening to a producer.
|
||||
- If producer.Stop is called, subtract from count.
|
||||
- If count == 0, stop producer
|
||||
|
||||
Change API producer to monitor changes and only send new events, one at a time, to app, instead of the entire response; create datatype for single API event
|
||||
- update chatbot and page handlers to use single API events
|
||||
- page details should add to activity list one at a time
|
||||
- store page list in Go, send entire list to frontend on updates
|
||||
- list can be updated by any producer
|
||||
|
||||
Add timeouts to event triggers to prevent rate limit?
|
||||
|
||||
Don't stop rule if chat error is 429 Too Many Requests
|
||||
|
||||
Check if sender is logged in before running rule. If not, return rule error.
|
||||
|
||||
Add max rant amount for commands
|
||||
|
||||
Button to export log file -> user selects folder
|
||||
|
||||
Style scroll bars on Windows
|
||||
- WebView2 issue
|
||||
|
||||
Indicator in chatbot that producer is running
|
||||
Before v1-alpha release:
|
||||
- stop all running rules when chat bot is deleted
|
||||
- indicator in chatbot that producer is running
|
||||
- this can be in many different places as needed
|
||||
|
||||
Custom stream moderator rules
|
||||
|
@ -121,6 +82,3 @@ User settings:
|
|||
- API query timer (default: 2s)
|
||||
|
||||
# To Do
|
||||
|
||||
Currently relies on Rumble to manage account username case-sensitivity.
|
||||
- Change database table to use UNIQUE COLLATE NOCASE on account username
|
81
v1/app.go
81
v1/app.go
|
@ -12,12 +12,12 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/tylertravisty/rum-goggles/v1/internal/chatbot"
|
||||
"github.com/tylertravisty/rum-goggles/v1/internal/config"
|
||||
"github.com/tylertravisty/rum-goggles/v1/internal/events"
|
||||
"github.com/tylertravisty/rum-goggles/v1/internal/models"
|
||||
rumblelivestreamlib "github.com/tylertravisty/rumble-livestream-lib-go"
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
"travisty.io/tyler/rum-goggles/v1/internal/chatbot"
|
||||
"travisty.io/tyler/rum-goggles/v1/internal/config"
|
||||
"travisty.io/tyler/rum-goggles/v1/internal/events"
|
||||
"travisty.io/tyler/rum-goggles/v1/internal/models"
|
||||
rumblelivestreamlib "travisty.io/tyler/rumble-livestream-lib-go"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
@ -835,6 +835,10 @@ func (a *App) activatePage(pi PageInfo) error {
|
|||
if name == nil {
|
||||
return fmt.Errorf("page name is nil")
|
||||
}
|
||||
url := pi.KeyUrl()
|
||||
if url == nil {
|
||||
return fmt.Errorf("page key url is nil")
|
||||
}
|
||||
|
||||
a.pagesMu.Lock()
|
||||
page, exists := a.pages[*name]
|
||||
|
@ -869,11 +873,6 @@ func (a *App) activatePage(pi PageInfo) error {
|
|||
}
|
||||
page.active = true
|
||||
|
||||
url := pi.KeyUrl()
|
||||
if url == nil {
|
||||
return fmt.Errorf("page key url is nil")
|
||||
}
|
||||
|
||||
err := a.producers.ApiP.Start(*name, *url, 10*time.Second)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error starting api: %v", err)
|
||||
|
@ -889,43 +888,6 @@ func (a *App) activatePage(pi PageInfo) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (a *App) deletePage(pi PageInfo) error {
|
||||
name := pi.String()
|
||||
if name == nil {
|
||||
return fmt.Errorf("page name is nil")
|
||||
}
|
||||
|
||||
a.pagesMu.Lock()
|
||||
defer a.pagesMu.Unlock()
|
||||
page, exists := a.pages[*name]
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
|
||||
page.activeMu.Lock()
|
||||
defer page.activeMu.Unlock()
|
||||
if page.active {
|
||||
if a.producers.ApiP.Active(*name) {
|
||||
err := a.producers.ApiP.Stop(*name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error stopping api: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
page.displayingMu.Lock()
|
||||
if page.displaying {
|
||||
runtime.EventsEmit(a.wails, "PageActive", false)
|
||||
}
|
||||
page.displayingMu.Unlock()
|
||||
|
||||
page.active = false
|
||||
}
|
||||
|
||||
delete(a.pages, *name)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) DeleteAccount(id int64) error {
|
||||
acct, err := a.services.AccountS.ByID(id)
|
||||
if err != nil {
|
||||
|
@ -951,11 +913,13 @@ func (a *App) DeleteAccount(id int64) error {
|
|||
return fmt.Errorf("Error deleting account. Try again.")
|
||||
}
|
||||
|
||||
err = a.deletePage(acct)
|
||||
if a.producers.ApiP.Active(*name) {
|
||||
err := a.producers.ApiP.Stop(*name)
|
||||
if err != nil {
|
||||
a.logError.Println("error deleting page:", err)
|
||||
a.logError.Println("error stopping api:", err)
|
||||
return fmt.Errorf("Error deleting account. Try again.")
|
||||
}
|
||||
}
|
||||
|
||||
err = a.services.AccountS.Delete(acct)
|
||||
if err != nil {
|
||||
|
@ -991,11 +955,13 @@ func (a *App) DeleteChannel(id int64) error {
|
|||
return fmt.Errorf("Error deleting channel. Try again.")
|
||||
}
|
||||
|
||||
err = a.deletePage(channel)
|
||||
if a.producers.ApiP.Active(*name) {
|
||||
err := a.producers.ApiP.Stop(*name)
|
||||
if err != nil {
|
||||
a.logError.Println("error deleting page:", err)
|
||||
a.logError.Println("error stopping api:", err)
|
||||
return fmt.Errorf("Error deleting channel. Try again.")
|
||||
}
|
||||
}
|
||||
|
||||
err = a.services.ChannelS.Delete(channel)
|
||||
if err != nil {
|
||||
|
@ -1309,13 +1275,12 @@ func (a *App) UpdateChatbot(chatbot *models.Chatbot) error {
|
|||
return fmt.Errorf("Error updating chatbot. Try again.")
|
||||
}
|
||||
|
||||
// list, err := a.chatbotList()
|
||||
// if err != nil {
|
||||
// a.logError.Println("error getting chatbot list:", err)
|
||||
// return fmt.Errorf("Error updating chatbot. Try again.")
|
||||
// }
|
||||
runtime.EventsEmit(a.wails, "ChatbotInfo", chatbot)
|
||||
// runtime.EventsEmit(a.wails, "ChatbotList", list)
|
||||
list, err := a.chatbotList()
|
||||
if err != nil {
|
||||
a.logError.Println("error getting chatbot list:", err)
|
||||
return fmt.Errorf("Error updating chatbot. Try again.")
|
||||
}
|
||||
runtime.EventsEmit(a.wails, "ChatbotList", list)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -42,19 +42,8 @@ function ChatBot(props) {
|
|||
const [openNewRule, setOpenNewRule] = useState(false);
|
||||
const [chatbotRules, setChatbotRules] = useState([]);
|
||||
const [chatbotSettings, setChatbotSettings] = useState(true);
|
||||
const [refresh, setRefresh] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
EventsOff('ChatbotInfo');
|
||||
EventsOn('ChatbotInfo', (event) => {
|
||||
if (openChatbot !== null && openChatbot.id === event.id) {
|
||||
openChatbot.name = event.name;
|
||||
openChatbot.url = event.url;
|
||||
setRefresh(!refresh);
|
||||
}
|
||||
});
|
||||
|
||||
EventsOff('ChatbotList');
|
||||
EventsOn('ChatbotList', (event) => {
|
||||
setChatbots(event);
|
||||
if (openChatbot !== null) {
|
||||
|
@ -65,9 +54,7 @@ function ChatBot(props) {
|
|||
}
|
||||
}
|
||||
});
|
||||
}, [openChatbot]);
|
||||
|
||||
useEffect(() => {
|
||||
EventsOn('ChatbotRules', (event) => {
|
||||
setChatbotRules(event);
|
||||
});
|
||||
|
@ -1146,10 +1133,6 @@ function ModalRuleTriggerEvent(props) {
|
|||
let from_account = {};
|
||||
switch (event) {
|
||||
case 'Follow':
|
||||
if (options.page === undefined || options.page === '') {
|
||||
setValidOptions(false);
|
||||
return;
|
||||
}
|
||||
from_account.name = options.page;
|
||||
from_account.on_follow = {};
|
||||
break;
|
||||
|
@ -1175,10 +1158,6 @@ function ModalRuleTriggerEvent(props) {
|
|||
let from_channel = {};
|
||||
switch (event) {
|
||||
case 'Follow':
|
||||
if (options.page === undefined || options.page === '') {
|
||||
setValidOptions(false);
|
||||
return;
|
||||
}
|
||||
from_channel.name = options.page;
|
||||
from_channel.on_follow = {};
|
||||
break;
|
||||
|
@ -1435,7 +1414,7 @@ function EventOptionsRant(props) {
|
|||
setValidMaxAmount(true);
|
||||
}
|
||||
|
||||
setMinAmount(amount);
|
||||
setMinAmount(event.target.value);
|
||||
props.setOptions({ min_amount: amount, max_amount: maxAmount });
|
||||
};
|
||||
const [maxAmount, setMaxAmount] = useState(
|
||||
|
|
|
@ -344,7 +344,7 @@ function PageDetails(props) {
|
|||
onSubmit={() => setError('')}
|
||||
/>
|
||||
)}
|
||||
{openDelete && details !== null && (
|
||||
{openDelete && (
|
||||
<Modal
|
||||
backgroundClose={true}
|
||||
cancelButton={'Cancel'}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module travisty.io/tyler/rum-goggles/v1
|
||||
module github.com/tylertravisty/rum-goggles/v1
|
||||
|
||||
go 1.21
|
||||
|
||||
|
@ -6,8 +6,8 @@ toolchain go1.22.0
|
|||
|
||||
require (
|
||||
github.com/mattn/go-sqlite3 v1.14.22
|
||||
github.com/tylertravisty/rumble-livestream-lib-go v0.9.0
|
||||
github.com/wailsapp/wails/v2 v2.8.1
|
||||
travisty.io/tyler/rumble-livestream-lib-go v0.0.0-20240614172924-f35ec00a1690
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -31,6 +31,7 @@ require (
|
|||
github.com/robertkrimen/otto v0.3.0 // indirect
|
||||
github.com/samber/lo v1.38.1 // indirect
|
||||
github.com/tkrajina/go-reflector v0.5.6 // indirect
|
||||
github.com/tylertravisty/go-utils v0.0.0-20230524204414-6893ae548909 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
github.com/wailsapp/go-webview2 v1.0.10 // indirect
|
||||
|
@ -42,7 +43,6 @@ require (
|
|||
golang.org/x/text v0.14.0 // indirect
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
|
||||
gopkg.in/sourcemap.v1 v1.0.5 // indirect
|
||||
travisty.io/tyler/go-utils v0.0.0-20240614172648-00b0b1a557b4 // indirect
|
||||
)
|
||||
|
||||
// replace github.com/wailsapp/wails/v2 v2.8.0 => /home/tyler/dev/go/pkg/mod
|
||||
|
|
|
@ -58,6 +58,10 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
|
|||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQSepKdE=
|
||||
github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4=
|
||||
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=
|
||||
github.com/tylertravisty/rumble-livestream-lib-go v0.9.0 h1:G1b/uac43dq7BG7NzcLeRLPOfOu8GyjViE9s48qhwhw=
|
||||
github.com/tylertravisty/rumble-livestream-lib-go v0.9.0/go.mod h1:Odkqvsn+2eoWV3ePcj257Ga0bdOqV4JBTfOJcQ+Sqf8=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
|
@ -106,7 +110,3 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
|||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
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=
|
||||
travisty.io/tyler/rumble-livestream-lib-go v0.0.0-20240614172924-f35ec00a1690 h1:j6qZCouGr8+eDKnK4T5qGfwqbwfq8G06gTv25zbKfgY=
|
||||
travisty.io/tyler/rumble-livestream-lib-go v0.0.0-20240614172924-f35ec00a1690/go.mod h1:kawNZvHMCKVQ18Qt3jayiUGsHfH2tlovr65GXzVXVA0=
|
||||
|
|
|
@ -10,10 +10,10 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/tylertravisty/rum-goggles/v1/internal/events"
|
||||
"github.com/tylertravisty/rum-goggles/v1/internal/models"
|
||||
rumblelivestreamlib "github.com/tylertravisty/rumble-livestream-lib-go"
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
"travisty.io/tyler/rum-goggles/v1/internal/events"
|
||||
"travisty.io/tyler/rum-goggles/v1/internal/models"
|
||||
rumblelivestreamlib "travisty.io/tyler/rumble-livestream-lib-go"
|
||||
)
|
||||
|
||||
type user struct {
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"travisty.io/tyler/rum-goggles/v1/internal/models"
|
||||
"github.com/tylertravisty/rum-goggles/v1/internal/models"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -8,9 +8,9 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/tylertravisty/rum-goggles/v1/internal/events"
|
||||
rumblelivestreamlib "github.com/tylertravisty/rumble-livestream-lib-go"
|
||||
"github.com/wailsapp/wails/v2/pkg/runtime"
|
||||
"travisty.io/tyler/rum-goggles/v1/internal/events"
|
||||
rumblelivestreamlib "travisty.io/tyler/rumble-livestream-lib-go"
|
||||
)
|
||||
|
||||
type Runner struct {
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
rumblelivestreamlib "travisty.io/tyler/rumble-livestream-lib-go"
|
||||
rumblelivestreamlib "github.com/tylertravisty/rumble-livestream-lib-go"
|
||||
)
|
||||
|
||||
type Api struct {
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
rumblelivestreamlib "travisty.io/tyler/rumble-livestream-lib-go"
|
||||
rumblelivestreamlib "github.com/tylertravisty/rumble-livestream-lib-go"
|
||||
)
|
||||
|
||||
type Chat struct {
|
||||
|
|
|
@ -5,10 +5,10 @@ import (
|
|||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/tylertravisty/rum-goggles/v1/internal/config"
|
||||
"github.com/wailsapp/wails/v2"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
"travisty.io/tyler/rum-goggles/v1/internal/config"
|
||||
)
|
||||
|
||||
//go:embed all:frontend/dist
|
||||
|
|
|
@ -13,9 +13,9 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/r3labs/sse/v2"
|
||||
"github.com/tylertravisty/go-utils/random"
|
||||
"golang.org/x/net/html"
|
||||
"gopkg.in/cenkalti/backoff.v1"
|
||||
"travisty.io/tyler/go-utils/random"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -88,11 +88,11 @@ func (c *Client) getChatInfo() (*ChatInfo, error) {
|
|||
return nil, fmt.Errorf("error finding end of chat function in webpage")
|
||||
}
|
||||
args := parseRumbleChatArgs(lineS[start : start+end])
|
||||
channelID, err := strconv.Atoi(args[6])
|
||||
channelID, err := strconv.Atoi(args[5])
|
||||
if err != nil {
|
||||
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") {
|
||||
r := strings.NewReader(lineS)
|
||||
node, err := html.Parse(r)
|
12
v1/vendor/modules.txt
vendored
12
v1/vendor/modules.txt
vendored
|
@ -74,6 +74,12 @@ github.com/samber/lo
|
|||
# github.com/tkrajina/go-reflector v0.5.6
|
||||
## explicit; go 1.17
|
||||
github.com/tkrajina/go-reflector/reflector
|
||||
# github.com/tylertravisty/go-utils v0.0.0-20230524204414-6893ae548909
|
||||
## explicit; go 1.16
|
||||
github.com/tylertravisty/go-utils/random
|
||||
# github.com/tylertravisty/rumble-livestream-lib-go v0.9.0
|
||||
## explicit; go 1.19
|
||||
github.com/tylertravisty/rumble-livestream-lib-go
|
||||
# github.com/valyala/bytebufferpool v1.0.0
|
||||
## explicit
|
||||
github.com/valyala/bytebufferpool
|
||||
|
@ -183,9 +189,3 @@ gopkg.in/cenkalti/backoff.v1
|
|||
## explicit
|
||||
gopkg.in/sourcemap.v1
|
||||
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
|
||||
# travisty.io/tyler/rumble-livestream-lib-go v0.0.0-20240614172924-f35ec00a1690
|
||||
## explicit; go 1.19
|
||||
travisty.io/tyler/rumble-livestream-lib-go
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
"frontend:dev:serverUrl": "auto",
|
||||
"author": {
|
||||
"name": "tyler",
|
||||
"email": "tyler@noreply.travisty.io"
|
||||
"email": "tylertravisty@users.noreply.github.com"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue