Skip to content

Commit

Permalink
Implement Discord Authorization Bot
Browse files Browse the repository at this point in the history
  • Loading branch information
Beniamiiin committed Nov 12, 2023
1 parent 0be57c5 commit 36b5b30
Show file tree
Hide file tree
Showing 23 changed files with 271 additions and 64 deletions.
3 changes: 2 additions & 1 deletion .env-example
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ TELEGRAM_VOTE_BOT_TOKEN=replace-me

TELEGRAM_AUTHORIZATION_BOT_TOKEN=replace-me
DISCORD_AUTHORIZATION_BOT_TOKEN=replace-me
DISCORD_AUTHORIZATION_CHANNEL_ID=replace-me
DISCORD_SERVER_ID=replace-me
DISCORD_MEMBER_ROLE_ID=replace-me

VOTE_API_URL=replace-me

Expand Down
20 changes: 17 additions & 3 deletions .github/workflows/docker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
push: true
tags: ghcr.io/beniamiiin/access-governance-system:pss

- name: Build and push AuthorizationBot
- name: Build and push TelegramAuthorizationBot
uses: docker/build-push-action@v4
with:
context: .
Expand All @@ -70,6 +70,20 @@ jobs:
DB_URL=${{ secrets.DB_URL }}
TELEGRAM_AUTHORIZATION_BOT_TOKEN=${{ secrets.TELEGRAM_AUTHORIZATION_BOT_TOKEN }}
DISCORD_AUTHORIZATION_BOT_TOKEN=${{ secrets.DISCORD_AUTHORIZATION_BOT_TOKEN }}
DISCORD_AUTHORIZATION_CHANNEL_ID=${{ secrets.DISCORD_AUTHORIZATION_CHANNEL_ID }}
DISCORD_SERVER_ID=${{ secrets.DISCORD_SERVER_ID }}
DISCORD_MEMBER_ROLE_ID=${{ secrets.DISCORD_MEMBER_ROLE_ID }}
push: true
tags: ghcr.io/beniamiiin/access-governance-system:ab
tags: ghcr.io/beniamiiin/access-governance-system:tab

- name: Build and push DiscordAuthorizationBot
uses: docker/build-push-action@v4
with:
context: .
file: ./deployments/authorization_bot/Dockerfile
build-args: |
ENVIRONMENT=${{ vars.ENVIRONMENT }}
COMMUNITY_NAME=${{ vars.COMMUNITY_NAME }}
LOKI_URL=${{ secrets.LOKI_URL }}
DISCORD_AUTHORIZATION_BOT_TOKEN=${{ secrets.DISCORD_AUTHORIZATION_BOT_TOKEN }}
push: true
tags: ghcr.io/beniamiiin/access-governance-system:dab
27 changes: 18 additions & 9 deletions Taskfile.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,18 +138,27 @@ tasks:
deps:
- install-docker-plugins
vars:
URL: ghcr.io/beniamiiin/access-governance-system:ab
SERVICE_NAME: authorization-bot
TELEGRAM_BOT_URL: ghcr.io/beniamiiin/access-governance-system:tab
TELEGRAM_SERVICE_NAME: authorization-bot-telegram
DISCORD_BOT_URL: ghcr.io/beniamiiin/access-governance-system:dab
DISCORD_SERVICE_NAME: authorization-bot-discord
cmds:
- docker pull {{.URL}}
- docker image tag {{.URL}} {{.SERVICE_NAME}}
- docker rmi {{.URL}}
- docker run --detach --interactive --tty --net {{.NETWORK_NAME}} --name {{.SERVICE_NAME}} {{.SERVICE_NAME}}
- docker pull {{.TELEGRAM_BOT_URL}}
- docker image tag {{.TELEGRAM_BOT_URL}} {{.TELEGRAM_SERVICE_NAME}}
- docker rmi {{.TELEGRAM_BOT_URL}}
- docker run --detach --interactive --tty --net {{.NETWORK_NAME}} --name {{.TELEGRAM_SERVICE_NAME}} {{.TELEGRAM_SERVICE_NAME}}
- docker pull {{.DISCORD_BOT_URL}}
- docker image tag {{.DISCORD_BOT_URL}} {{.DISCORD_SERVICE_NAME}}
- docker rmi {{.DISCORD_BOT_URL}}
- docker run --detach --interactive --tty --net {{.NETWORK_NAME}} --name {{.DISCORD_SERVICE_NAME}} {{.DISCORD_SERVICE_NAME}}

authorization-bot-down:
desc: Stop authorization bot
vars:
SERVICE_NAME: authorization-bot
TELEGRAM_SERVICE_NAME: authorization-bot-telegram
DISCORD_SERVICE_NAME: authorization-bot-discord
cmds:
- docker rm -f {{.SERVICE_NAME}}
- docker rmi -f {{.SERVICE_NAME}}
- docker rm -f {{.TELEGRAM_SERVICE_NAME}}
- docker rmi -f {{.TELEGRAM_SERVICE_NAME}}
- docker rm -f {{.DISCORD_SERVICE_NAME}}
- docker rmi -f {{.DISCORD_SERVICE_NAME}}
14 changes: 10 additions & 4 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,20 @@ tasks:
up
--detach
--build
authorization-bot
authorization-bot-telegram

authorization-bot-down:
desc: Stop authorization bot
cmds:
- docker-compose
--env-file .env
--file ./deployments/docker-compose.yml
--project-name authorization-bot
down
authorization-bot
authorization-bot-telegram
- docker-compose
--file ./deployments/docker-compose.yml
down
authorization-bot-discord
- docker-compose
--file ./deployments/docker-compose.yml
down
database
111 changes: 111 additions & 0 deletions cmd/authorization_bot/discord/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package main

import (
"access_governance_system/configs"
"access_governance_system/internal/di"
"context"
"errors"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"

"github.com/bwmarrin/discordgo"
"go.uber.org/zap"
)

var (
config configs.DiscordAuthrozationBotConfig
logger *zap.SugaredLogger
)

func main() {
config, err := configs.LoadDiscordAuthrozationBotConfig()
logger := di.NewLogger(config.Logger.AppName, config.App.Environment, config.Logger.URL)

if err != nil {
logger.Fatalw("failed to load config", "error", err)
}
logger.Info("config loaded")

go func() {
logger.Info("setting up health check server")
settingUpHealthCheckServer(logger)
}()

logger.Info("starting bot")

discord, err := discordgo.New("Bot " + config.AuthrozationBot.Token)
if err != nil {
logger.Fatalw("failed to create discord session", "error", err)
}

discord.AddHandler(authorization)

discord.Identify.Intents = discordgo.IntentsGuildMessages

err = discord.Open()
if err != nil {
logger.Fatalw("error opening connection", "error", err)
return
}

stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
<-stop

discord.Close()
}

func authorization(s *discordgo.Session, m *discordgo.MessageCreate) {
if m.Author.ID == s.State.User.ID {
return
}

if m.Content == "!authorize" {
tgBotLink := fmt.Sprintf("https://t.me/S16AuthorizationBot?start=%s", m.Author.ID)
message := fmt.Sprintf("Привет, для авторизации в сообществе %s перейди по ссылке %s", config.App.CommunityName, tgBotLink)

channel, err := s.UserChannelCreate(m.Author.ID)
if err != nil {
fmt.Println("failed to create author channel", "error", err)
}

_, err = s.ChannelMessageSend(channel.ID, message)
if err != nil {
fmt.Println("failed to send message", "error", err)
}
}
}

func settingUpHealthCheckServer(logger *zap.SugaredLogger) {
mux := http.NewServeMux()
mux.HandleFunc("/authorization-bot-discord/healthcheck", healthCheckHandler)

server := &http.Server{Addr: ":8080", Handler: mux}

if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
logger.Errorw("failed to start http server", "error", err)
}

stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
<-stop

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

err := server.Shutdown(ctx)
if err != nil {
logger.Errorw("failed to shutdown http server", "error", err)
return
}

logger.Info("shutting down")
}

func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte("I'm alive"))
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
)

func main() {
config, err := configs.LoadAuthrozationBotConfig()
config, err := configs.LoadTelegramAuthrozationBotConfig()
logger := di.NewLogger(config.Logger.AppName, config.App.Environment, config.Logger.URL)

if err != nil {
Expand Down Expand Up @@ -55,7 +55,7 @@ func main() {

func settingUpHealthCheckServer(logger *zap.SugaredLogger) {
mux := http.NewServeMux()
mux.HandleFunc("/authorization-bot/healthcheck", healthCheckHandler)
mux.HandleFunc("/authorization-bot-telegram/healthcheck", healthCheckHandler)

server := &http.Server{Addr: ":8080", Handler: mux}

Expand Down
4 changes: 0 additions & 4 deletions configs/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,3 @@ type App struct {
InitialSeeders []string `env:"INITIAL_SEEDERS" envSeparator:","`
MembersChatID int64 `env:"MEMBERS_CHAT_ID,notEmpty"`
}

func (c App) IsDevEnvironment() bool {
return c.Environment == "development"
}
2 changes: 1 addition & 1 deletion configs/telegram.go → configs/bot.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package configs

type Telegram struct {
type Bot struct {
Token string
}
37 changes: 28 additions & 9 deletions configs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ type AccessGovernanceBotConfig struct {
App App
DB DB
Logger Logger
AccessGovernanceBot Telegram
VoteBot Telegram
AccessGovernanceBot Bot
VoteBot Bot
VoteAPI VoteAPI
}

Expand All @@ -34,7 +34,7 @@ type ProposalStateServiceConfig struct {
App App
DB DB
Logger Logger
AccessGovernanceBot Telegram
AccessGovernanceBot Bot
VoteAPI VoteAPI

Quorum float64 `env:"QUORUM"` // 30% initial parameter for quorum
Expand All @@ -55,23 +55,42 @@ func LoadProposalStateServiceConfig() (ProposalStateServiceConfig, error) {
return config, nil
}

type AuthrozationBotConfig struct {
type TelegramAuthrozationBotConfig struct {
App App
DB DB
Logger Logger
DiscordAuthrozationBot Discord
TelegramAuthrozationBot Telegram
TelegramAuthrozationBot Bot
}

func LoadAuthrozationBotConfig() (AuthrozationBotConfig, error) {
var config AuthrozationBotConfig
func LoadTelegramAuthrozationBotConfig() (TelegramAuthrozationBotConfig, error) {
var config TelegramAuthrozationBotConfig

if err := env.Parse(&config); err != nil {
return AuthrozationBotConfig{}, fmt.Errorf("failed to parse config: %w", err)
return TelegramAuthrozationBotConfig{}, fmt.Errorf("failed to parse config: %w", err)
}

config.TelegramAuthrozationBot.Token = os.Getenv("TELEGRAM_AUTHORIZATION_BOT_TOKEN")
config.Logger.AppName = "authorization-bot"
config.Logger.AppName = "authorization-bot-telegram"

return config, nil
}

type DiscordAuthrozationBotConfig struct {
App App
Logger Logger
AuthrozationBot Bot
}

func LoadDiscordAuthrozationBotConfig() (DiscordAuthrozationBotConfig, error) {
var config DiscordAuthrozationBotConfig

if err := env.Parse(&config); err != nil {
return DiscordAuthrozationBotConfig{}, fmt.Errorf("failed to parse config: %w", err)
}

config.AuthrozationBot.Token = os.Getenv("DISCORD_AUTHORIZATION_BOT_TOKEN")
config.Logger.AppName = "authorization-bot-discord"

return config, nil
}
5 changes: 3 additions & 2 deletions configs/discord.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package configs

type Discord struct {
Token string `env:"DISCORD_AUTHORIZATION_BOT_TOKEN,notEmpty"`
AuthorizationChannelID string `env:"DISCORD_AUTHORIZATION_CHANNEL_ID,notEmpty"`
Token string `env:"DISCORD_AUTHORIZATION_BOT_TOKEN"`
ChannelID string `env:"DISCORD_SERVER_ID"`
MemberRoleID string `env:"DISCORD_MEMBER_ROLE_ID"`
}
28 changes: 28 additions & 0 deletions deployments/authorization_bot/discord/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
FROM golang:1.21

ARG ENVIRONMENT
ENV ENVIRONMENT=$ENVIRONMENT

ARG LOKI_URL
ENV LOKI_URL=$LOKI_URL

ARG DISCORD_AUTHORIZATION_BOT_TOKEN
ENV DISCORD_AUTHORIZATION_BOT_TOKEN=$DISCORD_AUTHORIZATION_BOT_TOKEN

ARG DISCORD_SERVER_ID
ENV DISCORD_SERVER_ID=$DISCORD_SERVER_ID

ARG DISCORD_MEMBER_ROLE_ID
ENV DISCORD_MEMBER_ROLE_ID=$DISCORD_MEMBER_ROLE_ID

WORKDIR /opt/src

COPY ./go.mod .
COPY ./go.sum .
RUN go mod download

ADD . .

RUN go build -o /go/bin/app ./cmd/authorization_bot/discord

CMD ["/go/bin/app"]
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ ENV TELEGRAM_AUTHORIZATION_BOT_TOKEN=$TELEGRAM_AUTHORIZATION_BOT_TOKEN
ARG DISCORD_AUTHORIZATION_BOT_TOKEN
ENV DISCORD_AUTHORIZATION_BOT_TOKEN=$DISCORD_AUTHORIZATION_BOT_TOKEN

ARG DISCORD_AUTHORIZATION_CHANNEL_ID
ENV DISCORD_AUTHORIZATION_CHANNEL_ID=$DISCORD_AUTHORIZATION_CHANNEL_ID

WORKDIR /opt/src

COPY ./go.mod .
Expand All @@ -29,6 +26,6 @@ RUN go mod download

ADD . .

RUN go build -o /go/bin/app ./cmd/authorization_bot/
RUN go build -o /go/bin/app ./cmd/authorization_bot/telegram

CMD ["/go/bin/app"]
Loading

0 comments on commit 36b5b30

Please sign in to comment.