refactor: rewrite api and view
This commit is contained in:
parent
6fa8fcfe8c
commit
62801fd487
14 changed files with 147 additions and 147 deletions
11
Makefile
11
Makefile
|
|
@ -2,8 +2,7 @@ CGO_ENABLED = 0
|
|||
GO_ARCH_AMD = amd64
|
||||
GO_OS_LINUX = linux
|
||||
|
||||
EXECUTABLE_SERVER = budget-go
|
||||
EXECUTABLE_CMD = budget-go-client
|
||||
EXECUTABLE_SERVER = owncast-webhook
|
||||
|
||||
CC = go build
|
||||
CFLAGS = -trimpath
|
||||
|
|
@ -11,9 +10,7 @@ LDFLAGS = -d -s -w -extldflags=-static
|
|||
GCFLAGS = all=
|
||||
ASMFLAGS = all=
|
||||
|
||||
|
||||
all: build
|
||||
#docker
|
||||
|
||||
.PHONY:
|
||||
rice:
|
||||
|
|
@ -23,16 +20,12 @@ rice:
|
|||
front:
|
||||
NODE_ENV=prod ./node_modules/.bin/webpack
|
||||
|
||||
.PHONY:
|
||||
tpl:
|
||||
TEMPL_EXPERIMENT=rawgo templ generate
|
||||
|
||||
lint:
|
||||
npm run lint || true
|
||||
npm run format
|
||||
|
||||
.PHONY:
|
||||
build: tpl front rice
|
||||
build: front rice
|
||||
CGO_ENABLED=$(CGO_ENABLED) \
|
||||
GOARCH=$(GO_ARCH_AMD) \
|
||||
GOOS=$(GO_OS_LINUX) \
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
package chat
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/owncast-webhook/backend/store"
|
||||
"gitnet.fr/deblan/owncast-webhook/backend/view"
|
||||
tpl "gitnet.fr/deblan/owncast-webhook/backend/view/template/chat"
|
||||
"gitnet.fr/deblan/owncast-webhook/backend/webhook"
|
||||
. "maragu.dev/gomponents"
|
||||
. "maragu.dev/gomponents/components"
|
||||
. "maragu.dev/gomponents/html"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
|
|
@ -18,8 +22,57 @@ func New(e *echo.Echo) *Controller {
|
|||
return &c
|
||||
}
|
||||
|
||||
var messages []webhook.Message
|
||||
|
||||
func (ctrl *Controller) Messages(c echo.Context) error {
|
||||
return view.Render(c, 200, tpl.Messages("Chat - Messages", messages))
|
||||
page := HTML5(HTML5Props{
|
||||
Title: "Chat",
|
||||
Language: "fr",
|
||||
Head: []Node{
|
||||
Group(view.EntrypointCss("main")),
|
||||
Link(Rel("icon"), Type("image/x-icon"), Href(view.Asset("static/img/favicon.png"))),
|
||||
},
|
||||
Body: []Node{
|
||||
ID("chat"),
|
||||
Div(
|
||||
Class("messages"),
|
||||
Map(store.GetMessageStore().All(), func(message store.MessageInterface) Node {
|
||||
var containerStyle Node
|
||||
var userStyle Node
|
||||
|
||||
if message.Origin() == store.MessageOriginOwncast {
|
||||
msg := message.(store.OwncastMessage)
|
||||
|
||||
containerStyle = StyleAttr(fmt.Sprintf(
|
||||
"border-color: var(--theme-color-users-%d)",
|
||||
msg.WebhookMessage.User.DisplayColor,
|
||||
))
|
||||
|
||||
userStyle = StyleAttr(fmt.Sprintf(
|
||||
"color: var(--theme-color-users-%d)",
|
||||
msg.WebhookMessage.User.DisplayColor,
|
||||
))
|
||||
}
|
||||
|
||||
return Div(
|
||||
Class("message"),
|
||||
ID(message.ID()),
|
||||
containerStyle,
|
||||
Div(
|
||||
Class("message-user"),
|
||||
userStyle,
|
||||
Text(message.Author()),
|
||||
),
|
||||
Div(
|
||||
Class("message-body"),
|
||||
Raw(message.Content()),
|
||||
),
|
||||
)
|
||||
}),
|
||||
),
|
||||
Group(view.EntrypointJs("main")),
|
||||
},
|
||||
})
|
||||
|
||||
page.Render(c.Response().Writer)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package owncast
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/owncast-webhook/backend/store"
|
||||
"gitnet.fr/deblan/owncast-webhook/backend/view"
|
||||
tpl "gitnet.fr/deblan/owncast-webhook/backend/view/template/chat"
|
||||
"gitnet.fr/deblan/owncast-webhook/backend/webhook"
|
||||
)
|
||||
|
||||
|
|
@ -19,24 +19,16 @@ func New(e *echo.Echo) *Controller {
|
|||
return &c
|
||||
}
|
||||
|
||||
var messages []webhook.Message
|
||||
|
||||
func (ctrl *Controller) Messages(c echo.Context) error {
|
||||
return view.Render(c, 200, tpl.Messages("Chat - Messages", messages))
|
||||
}
|
||||
|
||||
func (ctrl *Controller) ChatMessage(c echo.Context) error {
|
||||
value := new(webhook.WebhookNewMessage)
|
||||
|
||||
if err := c.Bind(value); err != nil {
|
||||
return c.JSON(400, nil)
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"status": "ko"})
|
||||
}
|
||||
|
||||
store.GetMessageStore().Add(store.OwncastMessage{
|
||||
WebhookMessage: value.EventData,
|
||||
})
|
||||
|
||||
messages = append(messages, value.EventData)
|
||||
|
||||
return c.JSON(200, nil)
|
||||
return c.JSON(http.StatusCreated, map[string]string{"status": "ok"})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ package router
|
|||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitnet.fr/deblan/owncast-webhook/backend/controller/chat"
|
||||
"gitnet.fr/deblan/owncast-webhook/backend/controller/webhook/owncast"
|
||||
)
|
||||
|
||||
func RegisterControllers(e *echo.Echo) {
|
||||
chat.New(e)
|
||||
owncast.New(e)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package store
|
||||
|
||||
import "gitnet.fr/deblan/owncast-webhook/backend/webhook"
|
||||
|
||||
type MessageOrigin int
|
||||
|
||||
var messageStore *MessageStore
|
||||
|
|
@ -32,28 +30,9 @@ func GetMessageStore() *MessageStore {
|
|||
}
|
||||
|
||||
type MessageInterface interface {
|
||||
IsVisible() bool
|
||||
GetOrigin() MessageOrigin
|
||||
GetAuthor() string
|
||||
GetContent() string
|
||||
}
|
||||
|
||||
type OwncastMessage struct {
|
||||
WebhookMessage webhook.Message
|
||||
}
|
||||
|
||||
func (o *OwncastMessage) IsVisible() bool {
|
||||
return o.WebhookMessage.Visible
|
||||
}
|
||||
|
||||
func (o *OwncastMessage) GetOrigin() MessageOrigin {
|
||||
return MessageOriginTwitch
|
||||
}
|
||||
|
||||
func (o *OwncastMessage) GetAuthor() string {
|
||||
return o.WebhookMessage.User.DisplayName
|
||||
}
|
||||
|
||||
func (o *OwncastMessage) GetContent() string {
|
||||
return o.WebhookMessage.GetBody()
|
||||
ID() string
|
||||
Visible() bool
|
||||
Origin() MessageOrigin
|
||||
Author() string
|
||||
Content() string
|
||||
}
|
||||
|
|
|
|||
39
backend/store/owncast_message.go
Normal file
39
backend/store/owncast_message.go
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package store
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gitnet.fr/deblan/owncast-webhook/backend/webhook"
|
||||
"gitnet.fr/deblan/owncast-webhook/config"
|
||||
)
|
||||
|
||||
type OwncastMessage struct {
|
||||
WebhookMessage webhook.Message
|
||||
}
|
||||
|
||||
func (o OwncastMessage) ID() string {
|
||||
return o.WebhookMessage.Id
|
||||
}
|
||||
|
||||
func (o OwncastMessage) Visible() bool {
|
||||
return o.WebhookMessage.Visible
|
||||
}
|
||||
|
||||
func (o OwncastMessage) Origin() MessageOrigin {
|
||||
return MessageOriginOwncast
|
||||
}
|
||||
|
||||
func (o OwncastMessage) Author() string {
|
||||
return o.WebhookMessage.User.DisplayName
|
||||
}
|
||||
|
||||
func (o OwncastMessage) Content() string {
|
||||
content := strings.ReplaceAll(
|
||||
o.WebhookMessage.Body,
|
||||
`<img src="`,
|
||||
fmt.Sprintf(`<img src="%s`, config.Get().Owncast.BaseUrl),
|
||||
)
|
||||
|
||||
return content
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
package template
|
||||
|
||||
import "gitnet.fr/deblan/owncast-webhook/backend/view"
|
||||
|
||||
templ Fav(url string) {
|
||||
<link rel="icon" type="image/x-icon" href={ url }>
|
||||
}
|
||||
|
||||
templ Head(title string) {
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
@Fav(view.Asset("static/img/favicon.png"))
|
||||
<title>{ title }</title>
|
||||
@templ.Raw(view.EntrypointCss("main"))
|
||||
</head>
|
||||
}
|
||||
|
||||
templ JS() {
|
||||
@templ.Raw(view.EntrypointJs("main"))
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
package chat
|
||||
|
||||
import (
|
||||
"gitnet.fr/deblan/owncast-webhook/backend/view/template"
|
||||
"gitnet.fr/deblan/owncast-webhook/backend/webhook"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func getMessageUserStyle(message webhook.Message) templ.Attributes {
|
||||
return templ.Attributes{
|
||||
"style": fmt.Sprintf("color: var(--theme-color-users-%d)", message.User.DisplayColor),
|
||||
}
|
||||
}
|
||||
|
||||
func getMessageStyle(message webhook.Message) templ.Attributes {
|
||||
return templ.Attributes{
|
||||
"style": fmt.Sprintf("border-color: var(--theme-color-users-%d)", message.User.DisplayColor),
|
||||
}
|
||||
}
|
||||
|
||||
templ Message(message webhook.Message) {
|
||||
<div class="message" id={ message.Id } { getMessageStyle(message)... }>
|
||||
<div class="message-user" { getMessageUserStyle(message)... }>
|
||||
{ message.User.DisplayName } $
|
||||
</div>
|
||||
<div class="message-body">
|
||||
@templ.Raw(message.GetBody())
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
templ Messages(title string, messages []webhook.Message) {
|
||||
<!doctype html>
|
||||
<html id="chat">
|
||||
@template.Head(title)
|
||||
<body>
|
||||
<div class="messages">
|
||||
for _, message := range messages {
|
||||
if message.Visible {
|
||||
@Message(message)
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
@template.JS()
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
|
|
@ -3,11 +3,11 @@ package view
|
|||
import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/a-h/templ"
|
||||
"github.com/labstack/echo/v4"
|
||||
. "maragu.dev/gomponents"
|
||||
. "maragu.dev/gomponents/html"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -64,24 +64,30 @@ func entrypointFiles(app, category string) []string {
|
|||
return files
|
||||
}
|
||||
|
||||
func EntrypointJs(app string) string {
|
||||
func EntrypointJs(app string) []Node {
|
||||
files := entrypointFiles(app, "js")
|
||||
results := []string{}
|
||||
var results []Node
|
||||
|
||||
for _, file := range files {
|
||||
results = append(results, fmt.Sprintf(`<script src="%s"></script>`, file))
|
||||
results = append(
|
||||
results,
|
||||
Script(Src(file)),
|
||||
)
|
||||
}
|
||||
|
||||
return strings.Join(results, "")
|
||||
return results
|
||||
}
|
||||
|
||||
func EntrypointCss(app string) string {
|
||||
func EntrypointCss(app string) []Node {
|
||||
files := entrypointFiles(app, "css")
|
||||
results := []string{}
|
||||
var results []Node
|
||||
|
||||
for _, file := range files {
|
||||
results = append(results, fmt.Sprintf(`<link rel="stylesheet" href="%s" />`, file))
|
||||
results = append(
|
||||
results,
|
||||
Link(Rel("stylesheet"), Href(file)),
|
||||
)
|
||||
}
|
||||
|
||||
return strings.Join(results, "")
|
||||
return results
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package webhook
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
|
@ -26,12 +25,6 @@ type Message struct {
|
|||
User MessageUser `json:"user"`
|
||||
}
|
||||
|
||||
func (m *Message) GetBody() string {
|
||||
m.Body = strings.ReplaceAll(m.Body, `<img src="`, `<img src="https://deblan.tv`)
|
||||
|
||||
return m.Body
|
||||
}
|
||||
|
||||
// {
|
||||
// "type": "CHAT",
|
||||
// "eventData": {
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@ export TEMPL_EXPERIMENT=rawgo
|
|||
while true; do
|
||||
rm -f cmd/server/rice-box.go
|
||||
./node_modules/.bin/webpack
|
||||
make tpl
|
||||
screen -S budget -d -m go run ./cmd/server
|
||||
notify-send "Budget" "Ready!"
|
||||
screen -S owncastwh -d -m go run ./cmd/server
|
||||
notify-send "Owncast Webhook" "Ready!"
|
||||
inotifywait -r . -e close_write
|
||||
screen -X -S budget quit
|
||||
done
|
||||
|
|
|
|||
|
|
@ -12,6 +12,15 @@ type Config struct {
|
|||
Address string
|
||||
Port int
|
||||
}
|
||||
Owncast struct {
|
||||
BaseUrl string
|
||||
}
|
||||
Twitch struct {
|
||||
ClientId string
|
||||
ClientSecret string
|
||||
WebhookUrl string
|
||||
WebhookSecret string
|
||||
}
|
||||
}
|
||||
|
||||
var config *Config
|
||||
|
|
@ -34,4 +43,11 @@ func (c *Config) Load(file string) {
|
|||
config.Server.Address = cfg.Section("server").Key("address").String()
|
||||
config.Server.Port, _ = cfg.Section("server").Key("port").Int()
|
||||
config.Server.BaseUrl = cfg.Section("server").Key("base_url").String()
|
||||
|
||||
config.Owncast.BaseUrl = cfg.Section("owncast").Key("base_url").String()
|
||||
|
||||
config.Twitch.ClientId = cfg.Section("twitch").Key("client_id").String()
|
||||
config.Twitch.ClientSecret = cfg.Section("twitch").Key("client_secret").String()
|
||||
config.Twitch.WebhookSecret = cfg.Section("twitch").Key("webhook_secret").String()
|
||||
config.Twitch.WebhookUrl = cfg.Section("twitch").Key("webhook_url").String()
|
||||
}
|
||||
|
|
|
|||
3
go.mod
3
go.mod
|
|
@ -5,14 +5,13 @@ go 1.23.0
|
|||
require (
|
||||
github.com/GeertJohan/go.rice v1.0.3
|
||||
github.com/a-h/templ v0.2.778
|
||||
github.com/gabriel-vasile/mimetype v1.4.5
|
||||
github.com/go-playground/validator v9.31.0+incompatible
|
||||
github.com/labstack/echo/v4 v4.12.0
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
maragu.dev/gomponents v1.2.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/LinneB/twitchwh v0.1.0 // indirect
|
||||
github.com/daaku/go.zipexe v1.0.2 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
|
|
|
|||
6
go.sum
6
go.sum
|
|
@ -1,8 +1,6 @@
|
|||
github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
|
||||
github.com/GeertJohan/go.rice v1.0.3 h1:k5viR+xGtIhF61125vCE1cmJ5957RQGXG6dmbaWZSmI=
|
||||
github.com/GeertJohan/go.rice v1.0.3/go.mod h1:XVdrU4pW00M4ikZed5q56tPf1v2KwnIKeIdc9CBYNt4=
|
||||
github.com/LinneB/twitchwh v0.1.0 h1:c9zdl3tGksINmxn5DzbjpWmGvSVmBsux9kE/hQURE5I=
|
||||
github.com/LinneB/twitchwh v0.1.0/go.mod h1:w+6OI4wgFtrZmZ9yZN28tZMiVq5b4iXDXk6T9XNshTI=
|
||||
github.com/a-h/templ v0.2.778 h1:VzhOuvWECrwOec4790lcLlZpP4Iptt5Q4K9aFxQmtaM=
|
||||
github.com/a-h/templ v0.2.778/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w=
|
||||
github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
|
||||
|
|
@ -10,8 +8,6 @@ github.com/daaku/go.zipexe v1.0.2 h1:Zg55YLYTr7M9wjKn8SY/WcpuuEi+kR2u4E8RhvpyXmk
|
|||
github.com/daaku/go.zipexe v1.0.2/go.mod h1:5xWogtqlYnfBXkSB1o9xysukNP9GTvaNkqzUZbt3Bw8=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
|
|
@ -62,3 +58,5 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
|||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
maragu.dev/gomponents v1.2.0 h1:H7/N5htz1GCnhu0HB1GasluWeU2rJZOYztVEyN61iTc=
|
||||
maragu.dev/gomponents v1.2.0/go.mod h1:oEDahza2gZoXDoDHhw8jBNgH+3UR5ni7Ur648HORydM=
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue