- implemented discord /repo command

This commit is contained in:
naudachu 2023-11-01 20:33:44 +05:00
parent a496c1998d
commit 59d9fc567f
22 changed files with 306 additions and 470 deletions

View File

@ -8,212 +8,94 @@ import (
"os/signal"
"syscall"
"ticket-pimp/bot/handler"
"ticket-pimp/internal/controller"
"ticket-pimp/internal/domain"
"ticket-pimp/internal/services"
discordbot "ticket-pimp/discord-bot"
configDB "ticket-pimp/internal/storage/db/config"
"ticket-pimp/discord"
"ticket-pimp/telegram"
ticketDB "ticket-pimp/internal/storage/db/tickets"
"github.com/jackc/pgx/v5"
"github.com/joho/godotenv"
"github.com/mr-linch/go-tg"
"github.com/mr-linch/go-tg/tgb"
)
func main() {
log.Print("started")
config := env("develop.env")
// run(config)
test(config)
config := domain.InitConfig("develop.env")
run(config)
// test(config)
}
func test(conf domain.Config) {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill, syscall.SIGTERM)
defer cancel()
conn, err := pgx.Connect(
ctx,
fmt.Sprintf(
"postgresql://%s:%s@%s:%s/%s",
conf.DB.User,
conf.DB.Pass,
conf.DB.Host,
conf.DB.Port,
conf.DB.Name,
))
if err != nil {
log.Fatalf("DB connection failed: %v", err)
}
// func test(conf domain.Config) {
// ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill, syscall.SIGTERM)
// defer cancel()
q := configDB.New(conn)
// appconfig, err := q.GetConfig(ctx)
// conn, err := pgxpool.New(ctx, fmt.Sprintf(
// "postgresql://%s:%s@%s:%s/%s",
// conf.DB.User,
// conf.DB.Pass,
// conf.DB.Host,
// conf.DB.Port,
// conf.DB.Name,
// ))
// appconfigNew, err := q.SetNewConfig(ctx)
// if err != nil {
// log.Fatalf("DB connection failed: %v", err)
// }
// _ = appconfig
// _ = appconfigNew
// q := configDB.New(conn)
appController := controller.NewAppConfig(q)
ticketConfig, err := appController.NewKey(ctx)
_ = ticketConfig
// appController := controller.NewAppConfig(q)
// ticketConfig, err := appController.NewKey(ctx)
// _ = ticketConfig
}
// }
func run(conf domain.Config) {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill, syscall.SIGTERM)
defer cancel()
// -- DB connection init -- START
conn, err := pgx.Connect(
ctx,
fmt.Sprintf(
"postgresql://%s:%s@%s:%s/%s",
conf.DB.User,
conf.DB.Pass,
conf.DB.Host,
conf.DB.Port,
conf.DB.Name,
conf.DB.User, conf.DB.Pass, conf.DB.Host, conf.DB.Port, conf.DB.Name,
))
if err != nil {
log.Fatalf("DB connection failed: %v", err)
}
defer conn.Close(ctx)
// -- DB connection init -- END
opts := TelegramOptions{
ticketsRepo: ticketDB.New(conn),
gitService: services.NewGit(conf.Git),
cloudService: services.NewCloud(conf.Cloud),
coda: services.NewCodaClient(conf.Coda),
appConfig: &conf,
}
ticketsRepo := ticketDB.New(conn)
gitService := services.NewGit(conf.Git)
cloudService := services.NewCloud(conf.Cloud)
codeService := services.NewCodaClient(conf.Coda)
go func() {
if err := runDiscrodBot(conf); err != nil {
opts := discord.DiscordOptions{
TicketsRepo: ticketsRepo,
GitService: gitService,
CloudService: cloudService,
Coda: codeService,
AppConfig: &conf,
}
if err := discord.Run(conf, opts); err != nil {
log.Fatalf("discord bot cannot be runned: %v", err)
}
}()
if err := runTgBot(ctx, opts); err != nil {
opts := telegram.TelegramOptions{
TicketsRepo: ticketsRepo,
GitService: gitService,
CloudService: cloudService,
Coda: codeService,
AppConfig: &conf,
}
if err := telegram.Run(ctx, opts); err != nil {
log.Fatalf("telegram bot cannot be runned: %v", err)
defer os.Exit(1)
}
}
// env
// env function reads provided file and setup envirmental variables;
func env(envFilePath string) domain.Config {
err := godotenv.Load(envFilePath)
if err != nil {
log.Fatal("Error while loading env file")
}
return domain.Config{
Git: domain.GitConfig{
BaseUrl: os.Getenv("GIT_BASE_URL"),
Token: os.Getenv("GIT_TOKEN"),
User: os.Getenv("GIT_USER"),
},
Cloud: domain.CloudConfig{
BaseUrl: os.Getenv("CLOUD_BASE_URL"),
User: os.Getenv("CLOUD_USER"),
Pass: os.Getenv("CLOUD_PASS"),
RootDir: os.Getenv("ROOTDIR"),
},
Coda: domain.CodaConfig{
Farm: os.Getenv("CODA_TOKEN1"),
Develop: os.Getenv("CODA_TOKEN2"),
},
DB: domain.DBConfig{
Host: os.Getenv("DB_HOST"),
Port: os.Getenv("DB_PORT"),
Name: os.Getenv("DB_NAME"),
User: os.Getenv("DB_USER"),
Pass: os.Getenv("DB_PASS"),
SslMode: os.Getenv("SSLMODE"),
},
Telegram: domain.TelegramConfig{
Token: os.Getenv("TG_API"),
},
Discord: domain.DiscordConfig{
Token: os.Getenv("DISCORD_TOKEN"),
},
}
}
func runDiscrodBot(conf domain.Config) error {
token := conf.Discord.Token
dbot, err := discordbot.NewDiscordBot(token)
if err != nil {
return err
}
createRepoHandler := discordbot.CreateRepoHandler(3)
dbot.Session.AddHandler(createRepoHandler.Handler)
if err := dbot.Session.Open(); err != nil {
return fmt.Errorf("cannot open the session: %v", err)
}
log.Println("Adding commands...")
cmd, err := dbot.Session.ApplicationCommandCreate(dbot.Session.State.User.ID, "", &createRepoHandler.Command)
if err != nil {
log.Panicf("Cannot create '%v' command: %v", createRepoHandler.Command.Name, err)
}
defer dbot.Session.Close()
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
<-stop
log.Println("Graceful shutdown")
log.Println("Removing commands...")
err = dbot.Session.ApplicationCommandDelete(dbot.Session.State.User.ID, "", cmd.ID)
if err != nil {
log.Panicf("Cannot delete '%v' command: %v", cmd.Name, err)
}
return nil
}
type TelegramOptions struct {
ticketsRepo *ticketDB.Queries
gitService *services.Git
cloudService *services.Cloud
coda *services.Coda
appConfig *domain.Config
}
// runTgBot ...
// ..function creates new Telegram BOT instance
// ..throw env variables through bot's handlers
// ..setup tg bot router;
// and finally returns tgb.Poller
func runTgBot(ctx context.Context, opts TelegramOptions) error {
log.Print("Start telegram bot init..")
client := tg.New(opts.appConfig.Telegram.Token)
h := handler.NewHandler(
opts.gitService,
opts.cloudService,
opts.coda,
opts.ticketsRepo,
)
router := tgb.NewRouter().
Message(h.Init, tgb.Command("init")).
Message(h.PingHandler, tgb.Command("ping")).
Message(h.DevelopmentTaskHandler, tgb.TextHasPrefix("/new")).
Message(h.NewRepoHandler, tgb.TextHasPrefix("/repo")).
Message(h.NewFolderHandler, tgb.TextHasPrefix("/folder")).
Message(h.FarmTaskHandler, tgb.TextHasPrefix("/task"))
return tgb.NewPoller(
router,
client,
).Run(ctx)
}

78
discord/discord.go Normal file
View File

@ -0,0 +1,78 @@
package discord
import (
"fmt"
"log"
"os"
"os/signal"
"ticket-pimp/discord/handler"
"ticket-pimp/internal/domain"
"ticket-pimp/internal/services"
tickets "ticket-pimp/internal/storage/db/tickets"
"github.com/bwmarrin/discordgo"
)
func initBotWith(token string) (*discordgo.Session, error) {
discord, err := discordgo.New("Bot " + token)
if err != nil {
return nil, err
}
return discord, nil
}
type DiscordOptions struct {
TicketsRepo *tickets.Queries
GitService *services.Git
CloudService *services.Cloud
Coda *services.Coda
AppConfig *domain.Config
}
func Run(conf domain.Config, opts DiscordOptions) error {
token := conf.Discord.Token
session, err := initBotWith(token)
if err != nil {
return err
}
router := handler.InitRouter(opts.GitService)
for _, h := range router.Routes {
session.AddHandler(h.Handler)
}
if err := session.Open(); err != nil {
return fmt.Errorf("cannot open the session: %v", err)
}
log.Println("Adding commands...")
var cmds []*discordgo.ApplicationCommand
for _, h := range router.Routes {
cmd, err := session.ApplicationCommandCreate(session.State.User.ID, "", &h.Command)
if err != nil {
log.Panicf("Cannot create '%v' command: %v", h.Command.Name, err)
}
cmds = append(cmds, cmd)
}
log.Println("Following commands added:")
log.Println(cmds)
defer session.Close()
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
<-stop
log.Println("Graceful shutdown")
log.Println("Removing commands...")
for _, h := range cmds {
err = session.ApplicationCommandDelete(session.State.User.ID, "", h.ID)
if err != nil {
log.Panicf("Cannot delete '%v' command: %v", h.Name, err)
}
}
return nil
}

View File

@ -1,32 +1,46 @@
package discordbot
package handler
import (
"fmt"
"log"
"ticket-pimp/internal/domain"
"ticket-pimp/internal/services"
"github.com/bwmarrin/discordgo"
)
type DiscordBot struct {
Session *discordgo.Session
type router struct {
Routes []route
git services.IGit
}
func NewDiscordBot(token string) (*DiscordBot, error) {
discord, err := discordgo.New("Bot " + token)
if err != nil {
return nil, err
}
return &DiscordBot{
Session: discord,
}, nil
// Подключение роутов к Discord боту
func InitRouter(gitService services.IGit) *router {
var r router
r.Routes = append(
r.Routes,
r.CreateRepoHandler(3),
// r.CreateTicketHandler(3),
)
r.git = gitService
return &r
}
type CommandHandler struct {
type route struct {
Command discordgo.ApplicationCommand
Handler func(s *discordgo.Session, i *discordgo.InteractionCreate)
}
func CreateRepoHandler(repoNameMinLength int) CommandHandler {
return CommandHandler{
func (h *router) CreateRepoHandler(repoNameMinLength int) route {
const (
projectRepo = "project_repo"
buildRepo = "build_repo"
)
return route{
Command: discordgo.ApplicationCommand{
Name: "repo",
Description: "Command for repository creation",
@ -39,11 +53,11 @@ func CreateRepoHandler(repoNameMinLength int) CommandHandler {
Choices: []*discordgo.ApplicationCommandOptionChoice{
{
Name: "Unity project repo",
Value: "project_repo",
Value: projectRepo,
},
{
Name: "XCode build repo",
Value: "build_repo",
Value: buildRepo,
},
},
},
@ -66,41 +80,44 @@ func CreateRepoHandler(repoNameMinLength int) CommandHandler {
optionMap[opt.Name] = opt
}
// This example stores the provided arguments in an []interface{}
// which will be used to format the bot's response
margs := make([]interface{}, 0, len(options))
msgformat := "You learned how to use command options! " +
"Take a look at the value(s) you entered:\n"
var str string = ""
if option, ok := optionMap["repo_type"]; ok {
// Option values must be type asserted from interface{}.
// Discordgo provides utility functions to make this simple.
margs = append(margs, option.StringValue())
msgformat += "> string-option: %s\n"
}
if option, ok := optionMap["repo_name"]; ok {
// Option values must be type asserted from interface{}.
// Discordgo provides utility functions to make this simple.
margs = append(margs, option.StringValue())
msgformat += "> string-option: %s\n"
str = option.StringValue()
if option, ok := optionMap["repo_type"]; ok {
switch option.Value {
case projectRepo:
case buildRepo:
str += "-build"
}
}
}
s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
var g *domain.Git
var result string
g, err := h.git.CreateRepo(str)
if err != nil {
result = fmt.Sprintf("error while repo creation: %v", err)
} else {
result = "🚀 " + g.HtmlUrl + " was created"
}
discerr := s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
// Ignore type for now, they will be discussed in "responses"
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
Content: fmt.Sprintf(
msgformat,
margs...,
),
Content: result,
},
})
log.Println(discerr)
},
}
}
func CreateTicketHandler(repoNameMinLength int) CommandHandler {
return CommandHandler{
func (h *router) CreateTicketHandler(repoNameMinLength int) route {
return route{
Command: discordgo.ApplicationCommand{
Name: "new",
Description: "Create new development ticket",
@ -130,13 +147,7 @@ func CreateTicketHandler(repoNameMinLength int) CommandHandler {
msgformat := "You learned how to use command options! " +
"Take a look at the value(s) you entered:\n"
if option, ok := optionMap["repo_type"]; ok {
// Option values must be type asserted from interface{}.
// Discordgo provides utility functions to make this simple.
margs = append(margs, option.StringValue())
msgformat += "> string-option: %s\n"
}
if option, ok := optionMap["repo_name"]; ok {
if option, ok := optionMap["project_name"]; ok {
// Option values must be type asserted from interface{}.
// Discordgo provides utility functions to make this simple.
margs = append(margs, option.StringValue())

View File

@ -1,28 +0,0 @@
FROM adoptopenjdk/openjdk11-openj9
ARG GITBUCKET_HOME
# create home
RUN mkdir -p $GITBUCKET_HOME
# mark volumes
VOLUME $GITBUCKET_HOME/repositories
VOLUME $GITBUCKET_HOME/data
VOLUME $GITBUCKET_HOME/gist
VOLUME $GITBUCKET_HOME/plugins
# Port for web page and Port for SSH access to git repository (Optional)
EXPOSE 8080 8443 29418
COPY server-WIN-DOMAIN-CA.cer /
COPY SSLPoke.java /
# ADD https://github.com/gitbucket/gitbucket/releases/download/4.38.4/gitbucket.war $GITBUCKET_HOME/gitbucket.war
COPY gitbucket.war $GITBUCKET_HOME
RUN keytool -importcert -file /server-WIN-DOMAIN-CA.cer -alias "server-WIN-DOMAIN-CA" -cacerts -storepass changeit -noprompt
# set environment
WORKDIR $GITBUCKET_HOME
CMD ["sh", "-c", "java $JAVA_OPTS -jar $GITBUCKET_HOME/gitbucket.war"]

View File

@ -1,40 +0,0 @@
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
/** Establish a SSL connection to a host and port, writes a byte and
* prints the response. See
* http://confluence.atlassian.com/display/JIRA/Connecting+to+SSL+services
*/
public class SSLPoke {
public static void main(String[] args) {
if (args.length != 2) {
System.out.println("Usage: "+SSLPoke.class.getName()+" <host> <port>");
System.exit(1);
}
try {
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(args[0], Integer.parseInt(args[1]));
SSLParameters sslparams = new SSLParameters();
sslparams.setEndpointIdentificationAlgorithm("HTTPS");
sslsocket.setSSLParameters(sslparams);
InputStream in = sslsocket.getInputStream();
OutputStream out = sslsocket.getOutputStream();
// Write a test byte to get a reaction :)
out.write(1);
while (in.available() > 0) {
System.out.print(in.read());
}
System.out.println("Successfully connected");
} catch (Exception exception) {
exception.printStackTrace();
System.exit(1);
}
}
}

View File

@ -1,68 +0,0 @@
version: "3"
volumes:
mysql:
driver: local
services:
gitbucket:
build:
context: .
dockerfile: Dockerfile
args:
GITBUCKET_HOME: /mnt/gitbucket
container_name: gitbucket_server
restart: always
ports:
- ${HTTP_PORT}:8080
- ${HTTPS_PORT}:8443
# Optional for SSH:
- ${SSH_PORT}:29418
depends_on:
mariadb:
condition: service_healthy
environment:
- JAVA_OPTS=-Dcom.sun.net.ssl.checkRevocation=false -Dcom.sun.security.enableAIAcaIssuers=true -Docsp.enable=fase -Dtrust_all_cert=true -Djdk.tls.client.protocols=TLSv1.2 -Dcom.sun.net.ssl.enableECC=false
- GITBUCKET_HOME=/mnt/gitbucket
- GITBUCKET_CONNECTORS=http
- GITBUCKET_HOST=0.0.0.0
- GITBUCKET_PORT=8080
- GITBUCKET_SECUREPORT=8443
- GITBUCKET_REDIRECTHTTPS=false
- GITBUCKET_PREFIX=/
- GITBUCKET_MAXFILESIZE=4294967296
- GITBUCKET_UPLOADTIMEOUT=120000
- GITBUCKET_JETTYIDLETIMEOUT=600000
- GITBUCKET_DB_URL=jdbc:mariadb://mariadb/gitbucket?useUnicode=true&characterEncoding=utf8
- GITBUCKET_DB_USER=gitbucket
- GITBUCKET_DB_PASSWORD=gitbucket
healthcheck:
test: ["CMD", "/usr/bin/healthcheck"]
interval: 30s
timeout: 10s
retries: 5
volumes:
- ../disks/disk1/gitbucket_data/repositories/:/mnt/gitbucket/repositories/
- ../disks/disk1/gitbucket_data/data/:/mnt/gitbucket/data/
- ../disks/disk1/gitbucket_data/gist/:/mnt/gitbucket/gist/
- ../disks/disk1/gitbucket_data/plugins/:/mnt/gitbucket/plugins/
mariadb:
image: mariadb:10.6
container_name: gitbucket_mariadb
restart: always
ports:
- ${DB_PORT}:3306
environment:
- MYSQL_ROOT_PASSWORD=gitbucket
- MYSQL_USER=gitbucket
- MYSQL_PASSWORD=gitbucket
- MYSQL_DATABASE=gitbucket
command: ["--max-allowed-packet=128M", "--innodb-log-file-size=64M"]
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-u", "root", "--password=gitbucket"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- mysql:/var/lib/mysql

Binary file not shown.

View File

@ -1,22 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDuTCCAqGgAwIBAgIQcZXcA798CYtB1LtewpzPijANBgkqhkiG9w0BAQsFADBu
MRUwEwYKCZImiZPyLGQBGRYFbG9jYWwxHjAcBgoJkiaJk/IsZAEZFg5tYXJsZXJp
bm9ncm91cDEWMBQGCgmSJomT8ixkARkWBnNlcnZlcjEdMBsGA1UEAxMUc2VydmVy
LVdJTi1ET01BSU4tQ0EwIBcNMjIwODE1MTI1NTM3WhgPMjEyMjA4MTUxMzA1Mzda
MG4xFTATBgoJkiaJk/IsZAEZFgVsb2NhbDEeMBwGCgmSJomT8ixkARkWDm1hcmxl
cmlub2dyb3VwMRYwFAYKCZImiZPyLGQBGRYGc2VydmVyMR0wGwYDVQQDExRzZXJ2
ZXItV0lOLURPTUFJTi1DQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AMBJwWymu7Csp+y8EMiPNo5drsQE58+enNCk13OIemQON5LZwY++BnvIrHvnaCof
Cdb9U2QyWV+Iehv/lNXcBkT6dJCTxUVmn6rXMmwNnBJmGuy0D6APIEPVBO3S7+/R
E4az8ikpVezbqAw/LiSyVMEQFaAEK8RlleBScLw9gpXmcWKljCrO/z+2wO1EGI3z
a1+qFLynQLeyusRj6rvo0U4RTyXdKaA++Ojhx3DV1NopHoSJ7CqXR728ubWK0fvY
0JGMg2ijS1cle7yC96+9ZSjdtktI/9M+8SG/tbpXcpW1bzGM0wCWOos1hLehks7V
c1pBEuVGSKSdtyF/FK2C7YUCAwEAAaNRME8wCwYDVR0PBAQDAgGGMA8GA1UdEwEB
/wQFMAMBAf8wHQYDVR0OBBYEFL+/yzfaRM/Rcrc9oYEzZf3STypqMBAGCSsGAQQB
gjcVAQQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQA7j2n9ZeKDwbmWCM2P1F9+6EZ8
+RZ+PEdxqs3aDo6S0Ckr/iopHA9PoexKGVEQN6bzaYxb0XTEbpJ89oI299weJF+W
63zID/lpEzsaSlTWpuj8KBudVoKsJmwJK2akQ2T3MmSiz7drtFOyh5wl9vhoi2cv
H3xhpqOYgh6iRwfwXMLo2YyS4vG6UZtq1GnU/drwVb1gHCoMdz7sFIdxlaw85Ub+
dlicykBNu60dbvM/iI0qSG25PerjEoOWZAglrPWpsQ0Zy+ChV0lWSp6FIYHjT3Rj
3TUo18LwIUKyorRErOTO4vgYHpqaA/RkAfl0C3cUujMw9eAp1fyd9FH0UcDo
-----END CERTIFICATE-----

View File

@ -1,72 +0,0 @@
version: "3"
volumes:
mysql:
driver: local
redis:
driver: local
services:
owncloud:
image: owncloud/server:${OWNCLOUD_VERSION}
container_name: owncloud_server
restart: always
ports:
- ${HTTP_PORT}:8080
depends_on:
- mariadb
- redis
environment:
- OWNCLOUD_DOMAIN=${OWNCLOUD_DOMAIN}
- OWNCLOUD_TRUSTED_DOMAINS=${OWNCLOUD_TRUSTED_DOMAINS}
- OWNCLOUD_DB_TYPE=mysql
- OWNCLOUD_DB_NAME=owncloud
- OWNCLOUD_DB_USERNAME=owncloud
- OWNCLOUD_DB_PASSWORD=owncloud
- OWNCLOUD_DB_HOST=mariadb
- OWNCLOUD_ADMIN_USERNAME=${ADMIN_USERNAME}
- OWNCLOUD_ADMIN_PASSWORD=${ADMIN_PASSWORD}
- OWNCLOUD_MYSQL_UTF8MB4=true
- OWNCLOUD_REDIS_ENABLED=true
- OWNCLOUD_REDIS_HOST=redis
healthcheck:
test: ["CMD", "/usr/bin/healthcheck"]
interval: 30s
timeout: 10s
retries: 5
volumes:
- ../disks/disk1/owncloud_data/:/mnt/data
- ../disks/:/mnt/disks
mariadb:
image: mariadb:10.6 # minimum required ownCloud version is 10.9
container_name: owncloud_mariadb
restart: always
ports:
- ${DB_PORT}:3306
environment:
- MYSQL_ROOT_PASSWORD=owncloud
- MYSQL_USER=owncloud
- MYSQL_PASSWORD=owncloud
- MYSQL_DATABASE=owncloud
command: ["--max-allowed-packet=128M", "--innodb-log-file-size=64M"]
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-u", "root", "--password=owncloud"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- mysql:/var/lib/mysql
redis:
image: redis:6
container_name: owncloud_redis
restart: always
command: ["--databases", "1"]
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- redis:/data

5
go.mod
View File

@ -5,7 +5,6 @@ go 1.20
require (
github.com/bwmarrin/discordgo v0.27.1
github.com/imroc/req/v3 v3.35.2
github.com/jackc/pgx v3.6.2+incompatible
github.com/jackc/pgx/v5 v5.4.3
github.com/joho/godotenv v1.5.1
github.com/mr-linch/go-tg v0.9.1
@ -20,9 +19,8 @@ require (
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/lib/pq v1.10.9 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/onsi/ginkgo/v2 v2.10.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
@ -33,6 +31,7 @@ require (
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/net v0.11.0 // indirect
golang.org/x/sync v0.2.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/text v0.10.0 // indirect
golang.org/x/tools v0.9.3 // indirect

12
go.sum
View File

@ -27,21 +27,17 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx v3.6.2+incompatible h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o=
github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mr-linch/go-tg v0.9.1 h1:4KNe7zwFG6svgM9w6pIcH3R7QWa6hIK8tCisQiFRCpU=
github.com/mr-linch/go-tg v0.9.1/go.mod h1:276w69YW4pEo3ZYta+LQe4v/ut2w2h1ksP4ziBWkK98=
github.com/onsi/ginkgo/v2 v2.10.0 h1:sfUl4qgLdvkChZrWCYndY2EAu9BRIw1YphNAzy1VNWs=
github.com/onsi/ginkgo/v2 v2.10.0/go.mod h1:UDQOh5wbQUlMnkLfVaIUMtQ1Vus92oM+P2JX1aulgcE=
github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
@ -54,7 +50,6 @@ github.com/quic-go/quic-go v0.35.1 h1:b0kzj6b/cQAf05cT0CkQubHM31wiA+xH3IBkxP62po
github.com/quic-go/quic-go v0.35.1/go.mod h1:+4CVgVppm0FNjpG3UcX8Joi/frKOH7/ciD5yGcwOO1g=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@ -81,6 +76,8 @@ golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -108,4 +105,3 @@ google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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=

View File

@ -1,5 +1,12 @@
package domain
import (
"log"
"os"
"github.com/joho/godotenv"
)
type Config struct {
Git GitConfig
Cloud CloudConfig
@ -48,3 +55,44 @@ type ApplicationConfig struct {
Key string
ID int
}
// InitConfig
// InitConfig function reads provided file and setup envirmental variables;
func InitConfig(envFilePath string) Config {
err := godotenv.Load(envFilePath)
if err != nil {
log.Fatal("Error while loading env file")
}
return Config{
Git: GitConfig{
BaseUrl: os.Getenv("GIT_BASE_URL"),
Token: os.Getenv("GIT_TOKEN"),
User: os.Getenv("GIT_USER"),
},
Cloud: CloudConfig{
BaseUrl: os.Getenv("CLOUD_BASE_URL"),
User: os.Getenv("CLOUD_USER"),
Pass: os.Getenv("CLOUD_PASS"),
RootDir: os.Getenv("ROOTDIR"),
},
Coda: CodaConfig{
Farm: os.Getenv("CODA_TOKEN1"),
Develop: os.Getenv("CODA_TOKEN2"),
},
DB: DBConfig{
Host: os.Getenv("DB_HOST"),
Port: os.Getenv("DB_PORT"),
Name: os.Getenv("DB_NAME"),
User: os.Getenv("DB_USER"),
Pass: os.Getenv("DB_PASS"),
SslMode: os.Getenv("SSLMODE"),
},
Telegram: TelegramConfig{
Token: os.Getenv("TG_API"),
},
Discord: DiscordConfig{
Token: os.Getenv("DISCORD_TOKEN"),
},
}
}

View File

@ -49,19 +49,15 @@ func (gb *Git) CreateRepo(name string) (*domain.Git, error) {
return repo, nil
}
type request struct {
type gitCreateRequest struct {
Name string `json:"name"`
Private bool `json:"private"`
}
type permissionRequest struct {
Perm string `json:"permission"`
}
func (gb *Git) newRepo(name string) (*domain.Git, error) {
name = helpers.GitNaming(name)
payload := request{
payload := gitCreateRequest{
Name: name,
Private: true,
}
@ -81,13 +77,16 @@ func (gb *Git) newRepo(name string) (*domain.Git, error) {
return &git, nil
}
type gitSetPermissionRequest struct {
Perm string `json:"permission"`
}
func (gb *Git) defaultGroupAsCollaborator(git *domain.Git) (*domain.Git, error) {
payload := permissionRequest{
payload := gitSetPermissionRequest{
Perm: "push",
}
///orgs/manurlerino/teams/devs/repos/manurlerino/x
respURL := "/orgs/mobilerino/teams/devs/repos/mobilerino/" + git.Name
resp, _ := gb.R().

View File

@ -19,12 +19,12 @@ type git struct {
ssh string
}
func newGit(domain *domain.Git) *git {
func newGit(g *domain.Git) *git {
return &git{
name: domain.Name,
url: domain.HtmlUrl,
git: domain.CloneUrl,
ssh: fmt.Sprintf("ssh://%s/%s.git", domain.SshUrl, domain.FullName),
name: g.Name,
url: g.HtmlUrl,
git: g.CloneUrl,
ssh: fmt.Sprintf("ssh://%s/%s.git", g.SshUrl, g.FullName),
}
}

View File

@ -1,9 +1,9 @@
package handler
import (
"ticket-pimp/bot/controller"
"ticket-pimp/internal/controller"
"ticket-pimp/internal/services"
db "ticket-pimp/internal/storage/db/tickets"
tickets "ticket-pimp/internal/storage/db/tickets"
)
type Handler struct {
@ -13,14 +13,14 @@ type Handler struct {
coda services.ICoda
key string
id string
db *db.Queries
db *tickets.Queries
}
func NewHandler(
git services.IGit,
cloud services.ICloud,
coda services.ICoda,
db *db.Queries,
db *tickets.Queries,
) *Handler {
return &Handler{

53
telegram/telegram.go Normal file
View File

@ -0,0 +1,53 @@
package telegram
import (
"context"
"log"
"ticket-pimp/internal/domain"
"ticket-pimp/internal/services"
"ticket-pimp/telegram/handler"
"github.com/mr-linch/go-tg"
"github.com/mr-linch/go-tg/tgb"
tickets "ticket-pimp/internal/storage/db/tickets"
)
type TelegramOptions struct {
TicketsRepo *tickets.Queries
GitService *services.Git
CloudService *services.Cloud
Coda *services.Coda
AppConfig *domain.Config
}
// runTgBot ...
// ..function creates new Telegram BOT instance
// ..throw env variables through bot's handlers
// ..setup tg bot router;
// and finally returns tgb.Poller
func Run(ctx context.Context, opts TelegramOptions) error {
log.Print("Start telegram bot init..")
client := tg.New(opts.AppConfig.Telegram.Token)
h := handler.NewHandler(
opts.GitService,
opts.CloudService,
opts.Coda,
opts.TicketsRepo,
)
router := tgb.NewRouter().
Message(h.Init, tgb.Command("init")).
Message(h.PingHandler, tgb.Command("ping")).
Message(h.DevelopmentTaskHandler, tgb.TextHasPrefix("/new")).
Message(h.NewRepoHandler, tgb.TextHasPrefix("/repo")).
Message(h.NewFolderHandler, tgb.TextHasPrefix("/folder")).
Message(h.FarmTaskHandler, tgb.TextHasPrefix("/task"))
return tgb.NewPoller(
router,
client,
).Run(ctx)
}