Compare commits
12 Commits
76649e81ff
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 211c72556d | |||
| fefd921817 | |||
| 2da7168b78 | |||
| 0899cc6741 | |||
| c2ffd25130 | |||
| a0274810aa | |||
| 1503b68886 | |||
| b286c85da2 | |||
| d7a2c0b750 | |||
| f48b8d3dd5 | |||
| cac85ae744 | |||
| 9c3da74078 |
@@ -0,0 +1,4 @@
|
|||||||
|
.git
|
||||||
|
.gitea
|
||||||
|
.env
|
||||||
|
*.log
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# Discord Bot Token
|
||||||
|
# Zu finden unter https://discord.com/developers/applications → Bot → Token
|
||||||
|
DISCORD_TOKEN=dein_token_hier
|
||||||
|
TARGET_CHANNEL_NAME=mein-channel
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: node:20
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version-file: go.mod
|
||||||
|
cache: false
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: go build ./...
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
name: Publish Docker Image
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: node:20-alpine
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Docker CLI + Buildx
|
||||||
|
shell: sh
|
||||||
|
run: |
|
||||||
|
apk add --no-cache docker-cli docker-cli-buildx
|
||||||
|
|
||||||
|
- name: Build image metadata
|
||||||
|
id: meta
|
||||||
|
shell: sh
|
||||||
|
run: |
|
||||||
|
SERVER_URL="${GITHUB_SERVER_URL:-${GITEA_SERVER_URL:-}}"
|
||||||
|
if [ -z "$SERVER_URL" ]; then
|
||||||
|
echo "Neither GITHUB_SERVER_URL nor GITEA_SERVER_URL is set."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
REGISTRY_HOST="${SERVER_URL#http://}"
|
||||||
|
REGISTRY_HOST="${REGISTRY_HOST#https://}"
|
||||||
|
IMAGE_REPO="$(echo "$GITHUB_REPOSITORY" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
|
||||||
|
echo "registry_host=$REGISTRY_HOST" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "image=$REGISTRY_HOST/$IMAGE_REPO" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Log in to Gitea Container Registry
|
||||||
|
shell: sh
|
||||||
|
env:
|
||||||
|
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
||||||
|
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
LEGACY_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
ACTOR_USERNAME: ${{ github.actor }}
|
||||||
|
run: |
|
||||||
|
USERNAME="$REGISTRY_USERNAME"
|
||||||
|
TOKEN="$REGISTRY_TOKEN"
|
||||||
|
|
||||||
|
if [ -z "$USERNAME" ]; then
|
||||||
|
USERNAME="$ACTOR_USERNAME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$TOKEN" ]; then
|
||||||
|
TOKEN="$LEGACY_TOKEN"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$USERNAME" ] || [ -z "$TOKEN" ]; then
|
||||||
|
echo "Registry login failed: set REGISTRY_USERNAME and REGISTRY_TOKEN (or fallback GITEA_TOKEN)."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$TOKEN" | docker login "${{ steps.meta.outputs.registry_host }}" -u "$USERNAME" --password-stdin
|
||||||
|
|
||||||
|
- name: Build and push image
|
||||||
|
shell: sh
|
||||||
|
run: |
|
||||||
|
IMAGE="${{ steps.meta.outputs.image }}"
|
||||||
|
SHA_TAG="${GITHUB_SHA}"
|
||||||
|
REF_TYPE="${GITHUB_REF_TYPE}"
|
||||||
|
REF_NAME="${GITHUB_REF_NAME}"
|
||||||
|
|
||||||
|
TAG_ARGS="--tag $IMAGE:$SHA_TAG"
|
||||||
|
|
||||||
|
# latest only for pushes to main
|
||||||
|
if [ "$REF_TYPE" = "branch" ] && [ "$REF_NAME" = "main" ]; then
|
||||||
|
TAG_ARGS="$TAG_ARGS --tag $IMAGE:latest"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# semver tags for refs like v1.2.3 -> v1.2.3, v1.2, v1
|
||||||
|
if [ "$REF_TYPE" = "tag" ]; then
|
||||||
|
case "$REF_NAME" in
|
||||||
|
v[0-9]*.[0-9]*.[0-9]*)
|
||||||
|
MAJOR="$(echo "$REF_NAME" | cut -d. -f1)"
|
||||||
|
MINOR="$(echo "$REF_NAME" | cut -d. -f2)"
|
||||||
|
TAG_ARGS="$TAG_ARGS --tag $IMAGE:$REF_NAME --tag $IMAGE:$MAJOR.$MINOR --tag $IMAGE:$MAJOR"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
TAG_ARGS="$TAG_ARGS --tag $IMAGE:$REF_NAME"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker buildx version
|
||||||
|
docker buildx build --push $TAG_ARGS .
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
FROM golang:1.23-alpine AS builder
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
|
||||||
|
COPY go.mod go.sum ./
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o /out/discord-thread-bot .
|
||||||
|
|
||||||
|
FROM gcr.io/distroless/static-debian12:nonroot
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /out/discord-thread-bot /app/discord-thread-bot
|
||||||
|
|
||||||
|
ENTRYPOINT ["/app/discord-thread-bot"]
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
module discord-thread-bot
|
||||||
|
|
||||||
|
go 1.23.0
|
||||||
|
|
||||||
|
require github.com/bwmarrin/discordgo v0.29.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
|
github.com/joho/godotenv v1.5.1 // indirect
|
||||||
|
golang.org/x/crypto v0.38.0 // indirect
|
||||||
|
golang.org/x/sys v0.33.0 // indirect
|
||||||
|
)
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
github.com/bwmarrin/discordgo v0.29.0 h1:FmWeXFaKUwrcL3Cx65c20bTRW+vOb6k8AnaP+EgjDno=
|
||||||
|
github.com/bwmarrin/discordgo v0.29.0/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY=
|
||||||
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
|
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
|
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||||
|
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||||
|
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
|
"github.com/joho/godotenv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := godotenv.Load(); err != nil && !os.IsNotExist(err) {
|
||||||
|
log.Println("Warnung: .env-Datei konnte nicht geladen werden:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
token := os.Getenv("DISCORD_TOKEN")
|
||||||
|
if token == "" {
|
||||||
|
log.Fatal("Umgebungsvariable DISCORD_TOKEN ist nicht gesetzt")
|
||||||
|
}
|
||||||
|
|
||||||
|
dg, err := discordgo.New("Bot " + token)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Fehler beim Erstellen der Discord-Session:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
targetChannelName := os.Getenv("TARGET_CHANNEL_NAME")
|
||||||
|
if targetChannelName == "" {
|
||||||
|
targetChannelName = "threads-und-diskussionen"
|
||||||
|
}
|
||||||
|
|
||||||
|
dg.AddHandler(func(s *discordgo.Session, t *discordgo.ThreadCreate) {
|
||||||
|
onThreadCreate(s, t, targetChannelName)
|
||||||
|
})
|
||||||
|
|
||||||
|
// GUILDS-Intent enthält THREAD_CREATE-Events
|
||||||
|
dg.Identify.Intents = discordgo.IntentsGuilds
|
||||||
|
|
||||||
|
if err = dg.Open(); err != nil {
|
||||||
|
log.Fatal("Fehler beim Öffnen der Verbindung:", err)
|
||||||
|
}
|
||||||
|
defer dg.Close()
|
||||||
|
|
||||||
|
fmt.Println("Bot läuft. CTRL+C zum Beenden.")
|
||||||
|
|
||||||
|
sc := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
|
||||||
|
<-sc
|
||||||
|
}
|
||||||
|
|
||||||
|
func onThreadCreate(s *discordgo.Session, t *discordgo.ThreadCreate, targetChannelName string) {
|
||||||
|
// Neu erstellte Threads haben NewlyCreated == true.
|
||||||
|
// Ohne diese Prüfung feuert das Event auch beim Bot-Start für bestehende Threads.
|
||||||
|
if !t.NewlyCreated {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
channels, err := s.GuildChannels(t.GuildID)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Fehler beim Abrufen der Channels:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var targetChannelID string
|
||||||
|
for _, ch := range channels {
|
||||||
|
if ch.Name == targetChannelName {
|
||||||
|
targetChannelID = ch.ID
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if targetChannelID == "" {
|
||||||
|
log.Printf("Channel #%s nicht gefunden\n", targetChannelName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
threadLink := fmt.Sprintf("https://discord.com/channels/%s/%s", t.GuildID, t.ID)
|
||||||
|
message := fmt.Sprintf("Neuer Thread: **%s**\n%s", t.Name, threadLink)
|
||||||
|
|
||||||
|
if _, err = s.ChannelMessageSend(targetChannelID, message); err != nil {
|
||||||
|
log.Println("Fehler beim Senden der Nachricht:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user