Skip to content

Commit

Permalink
Trying to reorg things to work better for my brain
Browse files Browse the repository at this point in the history
  • Loading branch information
bsquidwrd committed May 5, 2024
1 parent 1f63934 commit bb31d25
Show file tree
Hide file tree
Showing 50 changed files with 276 additions and 195 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
name: Create and publish Discord Notifier Docker image
name: Create and publish Twitch Discord Notifier Docker image

# Configures this workflow to run every time a change is pushed to the branch called `release`.
on:
Expand All @@ -9,8 +9,8 @@ on:
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}-discordnotifier
FILE_NAME: Dockerfile.discord_notifier
IMAGE_NAME: twitch-discord-notifier
FILE_NAME: .\twitch_discord_notifier\Dockerfile

# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
jobs:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
name: Create and publish a Reciever Docker image
name: Create and publish a Twitch Reciever Docker image

# Configures this workflow to run every time a change is pushed to the branch called `release`.
on:
Expand All @@ -9,8 +9,8 @@ on:
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}-receiver
FILE_NAME: Dockerfile.receiver
IMAGE_NAME: twitch-receiver
FILE_NAME: .\twitch_receiver\Dockerfile

# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
jobs:
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ This repository aims to represent how I will be handling EventSub notifications

- Rename `sample.env` to `.env` and edit values as needed
- Run docker containers with `docker compose up`
- Run the package with `go run cmd/receiver/main.go`
- Run the package with `go run twitch_receiver/cmd/main.go`


## [Goose Documentation](https://github.com/pressly/goose?tab=readme-ov-file#install)

```shell
EXPORT GOOSE_DRIVER="postgres"
EXPORT GOOSE_DBSTRING="postgres://test:password@localhost:5432/test"
EXPORT GOOSE_MIGRATION_DIR="internal/database/migrations/"
EXPORT GOOSE_MIGRATION_DIR="shared/database/migrations/"
go install github.com/pressly/goose/v3/cmd/goose@latest
goose up
```

```powershell
$env:"GOOSE_DRIVER" = "postgres"
$env:"GOOSE_DBSTRING" = "postgres://test:password@localhost:5432/test"
$env:"GOOSE_MIGRATION_DIR" = "internal/database/migrations/"
$env:"GOOSE_MIGRATION_DIR" = "shared/database/migrations/"
go install github.com/pressly/goose/v3/cmd/goose@latest
goose up
```
8 changes: 4 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ services:
retries: 5
start_period: 5s

webhook_handler:
image: 'ghcr.io/bsquidwrd/twitcheventsubhandler-receiver:main'
twitch_receiver:
image: 'ghcr.io/bsquidwrd/twitch-receiver:main'
restart: unless-stopped
expose:
- '${PORT}'
Expand All @@ -66,8 +66,8 @@ services:
condition: service_healthy
restart: true

discord_notifier:
image: 'ghcr.io/bsquidwrd/twitcheventsubhandler-discordnotifier:main'
twitch_discord_notifier:
image: 'ghcr.io/bsquidwrd/twitch-discord-notifier:main'
restart: unless-stopped
expose:
- '${PORT}'
Expand Down
File renamed without changes.
24 changes: 12 additions & 12 deletions internal/database/cache.go → shared/database/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import (
"github.com/redis/go-redis/v9"
)

type cacheService struct {
type CacheService struct {
db *redis.Client
}

func newCacheService() *cacheService {
func NewCacheService() *CacheService {
cacheUrl := os.Getenv("CACHE_URL")
opt, err := redis.ParseURL(cacheUrl)
if err != nil {
Expand All @@ -28,24 +28,24 @@ func newCacheService() *cacheService {
panic(err)
}

return &cacheService{
return &CacheService{
db: client,
}
}

func (c *cacheService) cleanup() {
func (c *CacheService) Cleanup() {
defer c.db.Close()
}

func (c *cacheService) Ping() error {
func (c *CacheService) Ping() error {
err := c.db.Echo(context.Background(), "OK").Err()
if err != nil {
return err
}
return nil
}

func (c *cacheService) TakeLock(key string, value string, expiration time.Duration) bool {
func (c *CacheService) TakeLock(key string, value string, expiration time.Duration) bool {
lockKey := fmt.Sprintf("lock:%s", key)
// Have a reasonable default a lock can be taken for
if expiration > (1 * time.Minute) {
Expand All @@ -58,7 +58,7 @@ func (c *cacheService) TakeLock(key string, value string, expiration time.Durati
return result
}

func (c *cacheService) ReleaseLock(key string, value string) bool {
func (c *CacheService) ReleaseLock(key string, value string) bool {
lockKey := fmt.Sprintf("lock:%s", key)
existingValue := c.GetString(lockKey)
if value == existingValue {
Expand All @@ -67,15 +67,15 @@ func (c *cacheService) ReleaseLock(key string, value string) bool {
return false
}

func (c *cacheService) Delete(key string) bool {
func (c *CacheService) Delete(key string) bool {
err := c.db.Del(context.Background(), key).Err()
if err != nil {
slog.Error("Error setting key in Cache", err)
}
return err != nil
}

func (c *cacheService) GetString(key string) string {
func (c *CacheService) GetString(key string) string {
value, err := c.db.Get(context.Background(), key).Result()
switch {
case err == redis.Nil:
Expand All @@ -86,15 +86,15 @@ func (c *cacheService) GetString(key string) string {
return value
}

func (c *cacheService) SetString(key string, value string, expiration time.Duration) bool {
func (c *CacheService) SetString(key string, value string, expiration time.Duration) bool {
err := c.db.Set(context.Background(), key, value, expiration).Err()
if err != nil {
slog.Error("Error setting key in Cache", err)
}
return err != nil
}

func (c *cacheService) GetBool(key string) bool {
func (c *CacheService) GetBool(key string) bool {
value, err := c.db.Get(context.Background(), key).Bool()
switch {
case err == redis.Nil:
Expand All @@ -105,7 +105,7 @@ func (c *cacheService) GetBool(key string) bool {
return value
}

func (c *cacheService) SetBool(key string, value bool, expiration time.Duration) bool {
func (c *CacheService) SetBool(key string, value bool, expiration time.Duration) bool {
err := c.db.Set(context.Background(), key, value, expiration).Err()
if err != nil {
slog.Error("Error setting key in Cache", err)
Expand Down
2 changes: 1 addition & 1 deletion internal/database/db.go → shared/database/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
//go:embed migrations/*.sql
var embedMigrations embed.FS

func newDatabaseService() *pgxpool.Pool {
func NewDatabaseService() *pgxpool.Pool {
poolConfig, err := pgxpool.ParseConfig(os.Getenv("DATABASE_URL"))
if err != nil {
panic(err)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package twitch
package database

import (
"database/sql"
"time"
)

type DatabaseUser struct {
type TwitchUser struct {
Id string `json:"id"`
Name string `json:"name"`
Login string `json:"login"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,17 @@ WORKDIR $GOPATH/src/
COPY go.mod .
COPY go.sum .

COPY cmd ./cmd
COPY internal ./internal
COPY pkg ./pkg
COPY . .

RUN go get -d -v ./cmd/discord_notifier/
RUN GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o /go/bin/discord_notifier ./cmd/discord_notifier/
RUN GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o /go/bin/healthcheck ./cmd/healthcheck/
RUN go get -d -v ./twitch_discord_notifier/cmd/notifier/
RUN GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o /go/bin/notifier ./twitch_discord_notifier/cmd/notifier/
RUN GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o /go/bin/healthcheck ./healthcheck/cmd/healthcheck/


FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /go/bin/discord_notifier /go/bin/discord_notifier
COPY --from=builder /go/bin/notifier /go/bin/notifier
COPY --from=builder /go/bin/healthcheck /go/bin/healthcheck

HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 CMD [ "/go/bin/healthcheck" ]
CMD ["/go/bin/discord_notifier"]
CMD ["/go/bin/notifier"]
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (
"os"
"time"

"github.com/bsquidwrd/TwitchEventSubHandler/cmd/discord_notifier/routes"
"github.com/bsquidwrd/TwitchEventSubHandler/internal/database"
discordnotifierhandlers "github.com/bsquidwrd/TwitchEventSubHandler/internal/discord_notifier_handlers"
"github.com/bsquidwrd/TwitchEventSubHandler/twitch_discord_notifier/cmd/notifier/routes"
"github.com/bsquidwrd/TwitchEventSubHandler/twitch_discord_notifier/internal/handlers"
"github.com/bsquidwrd/TwitchEventSubHandler/twitch_discord_notifier/internal/service"
amqp "github.com/rabbitmq/amqp091-go"
)

Expand All @@ -36,7 +36,7 @@ func main() {
port = "8080"
}

dbServices := database.NewDiscordNotifierService()
dbServices := service.NewDiscordNotifierService()
defer dbServices.Cleanup()

topics := []string{
Expand All @@ -47,7 +47,7 @@ func main() {
}

dbServices.Queue.StartConsuming(queueName, topics, func(msg amqp.Delivery) {
discordnotifierhandlers.ProcessMessage(dbServices, msg)
handlers.ProcessMessage(dbServices, msg)
})

http.HandleFunc("/", routes.HandleRoot)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"fmt"
"net/http"

"github.com/bsquidwrd/TwitchEventSubHandler/internal/database"
"github.com/bsquidwrd/TwitchEventSubHandler/twitch_discord_notifier/internal/service"
)

func HandleHealthCheck(dbServices *database.ReceiverService) func(http.ResponseWriter, *http.Request) {
func HandleHealthCheck(dbServices *service.DiscordNotifierService) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
err := dbServices.HealthCheck()
if err != nil {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package discordnotifierhandlers
package handlers

import (
"bytes"
Expand All @@ -9,25 +9,25 @@ import (
"net/http"
"time"

"github.com/bsquidwrd/TwitchEventSubHandler/pkg/models/discord"
"github.com/bsquidwrd/TwitchEventSubHandler/twitch_discord_notifier/pkg/models"
)

// Returned values are Request Status Code, Response Body, Error
func executeWebhook(url string, method string, body discord.WebhookBody) (int, discord.WebhookBody, error) {
func executeWebhook(url string, method string, body models.WebhookBody) (int, models.WebhookBody, error) {
if method != http.MethodPost && method != http.MethodPatch {
return 0, discord.WebhookBody{}, errors.New("only POST or PATCH are valid methods to use")
return 0, models.WebhookBody{}, errors.New("only POST or PATCH are valid methods to use")
}

data, err := json.Marshal(body)
if err != nil {
slog.Warn("Could not marshal body", err)
return 0, discord.WebhookBody{}, err
return 0, models.WebhookBody{}, err
}

request, err := http.NewRequest(method, url, bytes.NewReader(data))
if err != nil {
slog.Warn("Could not assemble request", err)
return 0, discord.WebhookBody{}, err
return 0, models.WebhookBody{}, err
}

request.Header.Add("Accept", "application/json")
Expand All @@ -48,21 +48,21 @@ func executeWebhook(url string, method string, body discord.WebhookBody) (int, d
}
if err != nil {
slog.Error("Error sending webhook", err)
return response.StatusCode, discord.WebhookBody{}, err
return response.StatusCode, models.WebhookBody{}, err
}
defer response.Body.Close()

responseBody, err := io.ReadAll(response.Body)
if err != nil {
slog.Error("Unable to parse body from response", err)
return 0, discord.WebhookBody{}, err
return 0, models.WebhookBody{}, err
}

var discordResponse discord.WebhookBody
var discordResponse models.WebhookBody
err = json.Unmarshal(responseBody, &discordResponse)
if err != nil {
slog.Error("Could not unmarshal response body")
return 0, discord.WebhookBody{}, err
return 0, models.WebhookBody{}, err
}

return response.StatusCode, discordResponse, nil
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package discordnotifierhandlers
package handlers

import (
"fmt"
"strings"
"time"

"github.com/bsquidwrd/TwitchEventSubHandler/pkg/models/discord"
"github.com/bsquidwrd/TwitchEventSubHandler/pkg/models/twitch"
dbModels "github.com/bsquidwrd/TwitchEventSubHandler/shared/models/database"
"github.com/bsquidwrd/TwitchEventSubHandler/twitch_discord_notifier/pkg/models"
)

func escapeMarkdown(input string) string {
Expand All @@ -31,7 +31,7 @@ func getRelativeTimestamp(timestamp time.Time) string {
return fmt.Sprintf("<t:%d:R>", timestamp.Unix())
}

func getNotificationPayload(user twitch.DatabaseUser, subscription discord.Subscription) discord.WebhookBody {
func getNotificationPayload(user dbModels.TwitchUser, subscription models.Subscription) models.WebhookBody {
profileUrl := fmt.Sprintf("https://twitch.tv/%s", user.Login)

message := subscription.Message
Expand Down Expand Up @@ -70,7 +70,7 @@ func getNotificationPayload(user twitch.DatabaseUser, subscription discord.Subsc
formattedMessage = fmt.Sprintf("%s\n%s", offlinePrefix, formattedMessage)
}

embed := discord.NewEmbed(
embed := models.NewEmbed(
"",
escapeMarkdown(user.Title),
profileUrl,
Expand All @@ -89,7 +89,7 @@ func getNotificationPayload(user twitch.DatabaseUser, subscription discord.Subsc
embed.Timestamp = ""
}

body := discord.WebhookBody{
body := models.WebhookBody{
Content: formattedMessage,
}
body.AddEmbed(embed)
Expand Down
Loading

0 comments on commit bb31d25

Please sign in to comment.