From ea10302b122627599e42689fe5ddeb1d43338be3 Mon Sep 17 00:00:00 2001 From: DO885 Date: Sun, 30 Jun 2024 16:26:25 +0900 Subject: [PATCH 01/10] =?UTF-8?q?=E2=9C=A8=20implement=20bot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + compose.yml | 5 +---- go.mod | 2 ++ go.sum | 4 ++++ infra/bot/bot.go | 5 +++++ main.go | 14 ++++++++++++++ 6 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 infra/bot/bot.go diff --git a/.gitignore b/.gitignore index dd9b185d..e60c2a35 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ debug # for development _development/* +.env \ No newline at end of file diff --git a/compose.yml b/compose.yml index ec1953d3..6646730e 100755 --- a/compose.yml +++ b/compose.yml @@ -23,6 +23,7 @@ services: ACTIVITY_CHANNEL_ID: ${ACTIVITY_CHANNEL_ID} TOKEN_KEY: ${TOKEN_KEY:-random32wordsXXXXXXXXXXXXXXXXXXX} KNOQ_VERSION: ${KNOQ_VERSION:-dev} + TRAQ_BOT_TOKEN: ${TRAQ_BOT_TOKEN} DEVELOPMENT: true GORM_LOG_LEVEL: info ports: @@ -30,10 +31,6 @@ services: depends_on: db: condition: service_healthy - develop: - watch: - - action: rebuild - path: ./ db: image: mariadb:10.6.4 diff --git a/go.mod b/go.mod index 097fef45..8de6aad6 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/robfig/cron/v3 v3.0.1 github.com/stretchr/testify v1.9.0 github.com/traPtitech/go-traq v0.0.0-20240509050113-9343acbeec35 + github.com/traPtitech/traq-ws-bot v1.1.3 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 golang.org/x/oauth2 v0.20.0 @@ -54,6 +55,7 @@ require ( github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/gorilla/context v1.1.2 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect diff --git a/go.sum b/go.sum index bca8f621..251d3ecd 100644 --- a/go.sum +++ b/go.sum @@ -102,6 +102,8 @@ github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kX github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= @@ -172,6 +174,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/traPtitech/go-traq v0.0.0-20240509050113-9343acbeec35 h1:NoEvHqFhmtyy7ELLp1chwM4R1vhXw2zKeEotkmKvSJw= github.com/traPtitech/go-traq v0.0.0-20240509050113-9343acbeec35/go.mod h1:7yJs1m/ddCG39XF78GA8FrXqyc4fNPfHp8BSLjMVMY8= +github.com/traPtitech/traq-ws-bot v1.1.3 h1:Cehz+ORmz/j2HexJHtm6yS/lmAq99REpojfwj0vjjBY= +github.com/traPtitech/traq-ws-bot v1.1.3/go.mod h1:mnUHbZiFLydoUxS2q8kzR1E+1RMRXrmEpUdSAxh0jvo= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= diff --git a/infra/bot/bot.go b/infra/bot/bot.go new file mode 100644 index 00000000..cbec7894 --- /dev/null +++ b/infra/bot/bot.go @@ -0,0 +1,5 @@ +package bot + +import traqwsbot "github.com/traPtitech/traq-ws-bot" + +var Bot *traqwsbot.Bot diff --git a/main.go b/main.go index 0e722c0a..99edead8 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,7 @@ import ( "time" "github.com/traPtitech/knoQ/domain" + "github.com/traPtitech/knoQ/infra/bot" "github.com/traPtitech/knoQ/infra/db" "github.com/traPtitech/knoQ/infra/traq" "github.com/traPtitech/knoQ/repository" @@ -21,6 +22,8 @@ import ( "github.com/gorilla/sessions" "github.com/robfig/cron/v3" "go.uber.org/zap" + + traqwsbot "github.com/traPtitech/traq-ws-bot" ) var ( @@ -109,6 +112,17 @@ func main() { } c.Start() + // bot + bot.Bot, err = traqwsbot.NewBot(&traqwsbot.Options{ + AccessToken: os.Getenv("TRAQ_BOT_TOKEN"), + }) + if err != nil { + panic(err) + } + if err := bot.Bot.Start(); err != nil { + panic(err) + } + // サーバースタート go func() { if err := e.Start(":3000"); err != nil { From 18cce41b7507f8d5a0507f62bed41b1c3f3cd8ba Mon Sep 17 00:00:00 2001 From: DO885 Date: Sun, 30 Jun 2024 16:56:54 +0900 Subject: [PATCH 02/10] =?UTF-8?q?=E2=9C=A8=20post=20by=20bot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.go | 16 ++++++++-------- router/middleware.go | 2 +- utils/api.go | 39 +++++++++++---------------------------- utils/cron.go | 6 +++--- 4 files changed, 23 insertions(+), 40 deletions(-) diff --git a/main.go b/main.go index 99edead8..bb436efb 100644 --- a/main.go +++ b/main.go @@ -101,9 +101,7 @@ func main() { "0 8 * * *", utils.InitPostEventToTraQ( &repo.GormRepo, - handler.WebhookSecret, handler.DailyChannelId, - handler.WebhookID, handler.Origin, ), ) @@ -112,6 +110,13 @@ func main() { } c.Start() + // サーバースタート + go func() { + if err := e.Start(":3000"); err != nil { + e.Logger.Info("shutting down the server") + } + }() + // bot bot.Bot, err = traqwsbot.NewBot(&traqwsbot.Options{ AccessToken: os.Getenv("TRAQ_BOT_TOKEN"), @@ -123,16 +128,11 @@ func main() { panic(err) } - // サーバースタート - go func() { - if err := e.Start(":3000"); err != nil { - e.Logger.Info("shutting down the server") - } - }() quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) <-quit ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() if err := e.Shutdown(ctx); err != nil { e.Logger.Fatal(err) diff --git a/router/middleware.go b/router/middleware.go index 77feb07d..29189662 100644 --- a/router/middleware.go +++ b/router/middleware.go @@ -222,7 +222,7 @@ func (h *Handlers) WebhookEventHandler(c echo.Context, reqBody, resBody []byte) content := presentation.GenerateEventWebhookContent(c.Request().Method, e, notificationTargets, h.Origin, !domain.DEVELOPMENT) - _ = utils.RequestWebhook(content, h.WebhookSecret, h.ActivityChannelID, h.WebhookID, 1) + _ = utils.RequestBotPost(content, h.ActivityChannelID) } // getRequestUserID sessionからuserを返します diff --git a/utils/api.go b/utils/api.go index 1932e508..8b827c9e 100644 --- a/utils/api.go +++ b/utils/api.go @@ -2,36 +2,19 @@ package utils import ( "context" - "crypto/hmac" - "crypto/sha1" - "encoding/hex" - "errors" - "net/http" "github.com/traPtitech/go-traq" + "github.com/traPtitech/knoQ/infra/bot" ) -// RequestWebhook q.trap/jp にメッセージを送信します。 -func RequestWebhook(message, secret, channelID, webhookID string, embed int) error { - configuration := traq.NewConfiguration() - apiClient := traq.NewAPIClient(configuration) - - xTRAQSignature := calcSignature(message, secret) - res, err := apiClient.WebhookApi.PostWebhook(context.TODO(), webhookID). - XTRAQChannelId(channelID).XTRAQSignature(xTRAQSignature). - Embed(int32(embed)).Body(message).Execute() - if err != nil { - return err - } - if res.StatusCode >= 400 { - return errors.New(http.StatusText(res.StatusCode)) - } - - return nil -} - -func calcSignature(message, secret string) string { - mac := hmac.New(sha1.New, []byte(secret)) - mac.Write([]byte(message)) - return hex.EncodeToString(mac.Sum(nil)) +// RequestBotPost q.trap/jp にメッセージを送信します。 +func RequestBotPost(message, channelID string) error { + _, _, err := bot.Bot.API(). + MessageApi. + PostMessage(context.Background(), channelID). + PostMessageRequest(traq.PostMessageRequest{ + Content: message, + }). + Execute() + return err } diff --git a/utils/cron.go b/utils/cron.go index 545f6644..0ae4db7e 100644 --- a/utils/cron.go +++ b/utils/cron.go @@ -20,8 +20,8 @@ type timeTable struct { } // InitPostEventToTraQ 現在(job実行)から24時間以内に始まるイベントを取得し、 -// webhookでtraQに送るjobを作成。 -func InitPostEventToTraQ(repo *db.GormRepository, secret, channelID, webhookID, origin string) func() { +// botでtraQに送るjobを作成。 +func InitPostEventToTraQ(repo *db.GormRepository, channelID, origin string) func() { job := func() { now := setTimeFromString(time.Now().In(tz.JST), "06:00:00") tomorrow := now.AddDate(0, 0, 1) @@ -29,7 +29,7 @@ func InitPostEventToTraQ(repo *db.GormRepository, secret, channelID, webhookID, rooms, _ := repo.GetAllRooms(now, tomorrow, uuid.Nil) events, _ := repo.GetAllEvents(filter.FilterTime(now, tomorrow)) message := createMessage(now, rooms, events, origin) - err := RequestWebhook(message, secret, channelID, webhookID, 1) + err := RequestBotPost(message, channelID) if err != nil { fmt.Println(err) } From 945b428793baf39bbfbae49029b27d98f4ccdc7e Mon Sep 17 00:00:00 2001 From: DO885 Date: Sun, 30 Jun 2024 16:59:51 +0900 Subject: [PATCH 03/10] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20rename=20webhook=20t?= =?UTF-8?q?o=20bot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- router/middleware.go | 2 +- router/presentation/event.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/router/middleware.go b/router/middleware.go index 29189662..4b894af6 100644 --- a/router/middleware.go +++ b/router/middleware.go @@ -220,7 +220,7 @@ func (h *Handlers) WebhookEventHandler(c echo.Context, reqBody, resBody []byte) } } - content := presentation.GenerateEventWebhookContent(c.Request().Method, e, notificationTargets, h.Origin, !domain.DEVELOPMENT) + content := presentation.GenerateEventBotContent(c.Request().Method, e, notificationTargets, h.Origin, !domain.DEVELOPMENT) _ = utils.RequestBotPost(content, h.ActivityChannelID) } diff --git a/router/presentation/event.go b/router/presentation/event.go index 04d55127..9c6c2347 100644 --- a/router/presentation/event.go +++ b/router/presentation/event.go @@ -162,7 +162,7 @@ func ICalFormat(events []*domain.Event, host string, userMap map[uuid.UUID]*doma return cal } -func GenerateEventWebhookContent(method string, e *EventDetailRes, nofiticationTargets []string, origin string, isMention bool) string { +func GenerateEventBotContent(method string, e *EventDetailRes, nofiticationTargets []string, origin string, isMention bool) string { timeFormat := "01/02(Mon) 15:04" var content string switch method { From 5414bd99249ae9fe2de8b93908a61b02599a2db4 Mon Sep 17 00:00:00 2001 From: DO885 Date: Wed, 3 Jul 2024 22:44:07 +0900 Subject: [PATCH 04/10] =?UTF-8?q?=E2=9C=A8=20implement=20post=20struct?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- domain/post.go | 13 +++++++++++++ infra/db/converter.go | 7 +++++++ infra/db/model.go | 6 ++++++ infra/db/post.go | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 domain/post.go create mode 100644 infra/db/post.go diff --git a/domain/post.go b/domain/post.go new file mode 100644 index 00000000..9be9a965 --- /dev/null +++ b/domain/post.go @@ -0,0 +1,13 @@ +package domain + +import "github.com/gofrs/uuid" + +type Post struct { + MessageID uuid.UUID + EventID uuid.UUID +} + +type WritePostParams struct { + MessageID uuid.UUID + EventID uuid.UUID +} diff --git a/infra/db/converter.go b/infra/db/converter.go index 59b142ed..973a8214 100644 --- a/infra/db/converter.go +++ b/infra/db/converter.go @@ -261,6 +261,13 @@ func ConvWriteGroupParamsToGroup(src WriteGroupParams) (dst Group) { } return } + +func ConvWritePostParamsToPost(src WritePostParams) (dst Post) { + dst.MessageID = src.MessageID + dst.EventID = src.EventID + return +} + func ConvdomainEventTagParamsToEventTag(src domain.EventTagParams) (dst EventTag) { dst.Tag.Name = src.Name dst.Locked = src.Locked diff --git a/infra/db/model.go b/infra/db/model.go index d46c13ad..79464fbc 100644 --- a/infra/db/model.go +++ b/infra/db/model.go @@ -21,6 +21,7 @@ var tables = []interface{}{ EventTag{}, // Eventより下にないと、overrideされる EventAdmin{}, EventAttendee{}, + Post{}, } type Model struct { @@ -167,6 +168,11 @@ type EventAttendee struct { Schedule int } +type Post struct { + MessageID uuid.UUID `gorm:"type:char(36); primaryKey"` + EventID uuid.UUID `gorm:"type:char(36); not null"` +} + // Event is event for gorm // //go:generate go run github.com/fuji8/gotypeconverter/cmd/gotypeconverter@latest -s Event -d domain.Event -o converter.go . diff --git a/infra/db/post.go b/infra/db/post.go new file mode 100644 index 00000000..1fb886fd --- /dev/null +++ b/infra/db/post.go @@ -0,0 +1,36 @@ +package db + +import ( + "github.com/gofrs/uuid" + "github.com/traPtitech/knoQ/domain" + "gorm.io/gorm" +) + +type WritePostParams struct { + domain.WritePostParams +} + +func (repo *GormRepository) CreatePost(params WritePostParams) (*Post, error) { + p, err := createPost(repo.db, params) + return p, defaultErrorHandling(err) +} + +func (repo *GormRepository) GetPost(MessageID uuid.UUID) (*Post, error) { + post, err := getPost(repo.db, MessageID) + return post, defaultErrorHandling(err) +} + +func createPost(db *gorm.DB, params WritePostParams) (*Post, error) { + post := ConvWritePostParamsToPost(params) + err := db.Create(&post).Error + if err != nil { + return nil, err + } + return &post, nil +} + +func getPost(db *gorm.DB, messageID uuid.UUID) (*Post, error) { + post := Post{} + err := db.Take(&post, messageID).Error + return &post, err +} From 2814672c8754895d76b5896cd61e3bc93e3a5b80 Mon Sep 17 00:00:00 2001 From: DO885 Date: Wed, 3 Jul 2024 22:44:42 +0900 Subject: [PATCH 05/10] =?UTF-8?q?=E2=9C=A8=20implement=20stamps=20updated?= =?UTF-8?q?=20handler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/bot/bot.go | 35 ++++++++++++++++++++++++++++++++++- main.go | 5 +++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/infra/bot/bot.go b/infra/bot/bot.go index cbec7894..dca1e4f7 100644 --- a/infra/bot/bot.go +++ b/infra/bot/bot.go @@ -1,5 +1,38 @@ package bot -import traqwsbot "github.com/traPtitech/traq-ws-bot" +import ( + "fmt" + + "github.com/gofrs/uuid" + "github.com/traPtitech/knoQ/domain" + "github.com/traPtitech/knoQ/infra/db" + traqwsbot "github.com/traPtitech/traq-ws-bot" + "github.com/traPtitech/traq-ws-bot/payload" +) var Bot *traqwsbot.Bot + +func BotMessageStampsUpdatedHandler(p *payload.BotMessageStampsUpdated, gormRepo db.GormRepository) { + post, err := gormRepo.GetPost(uuid.FromStringOrNil(p.MessageID)) + if err != nil { + fmt.Println(err) + } + for _, stamp := range p.Stamps { + var scheduleStatus domain.ScheduleStatus + switch stamp.StampID { + case "8658c060-6f8e-46f6-8ee8-3fbc63f2ed4d": + // 出席 + scheduleStatus = domain.Attendance + case "7813a8d6-77ab-446d-af1c-559db2ccab10": + // 欠席 + scheduleStatus = domain.Absent + case "0d9c5a46-61bc-4c9c-873f-99eee45757fc": + // 未定 + scheduleStatus = domain.Pending + } + err := gormRepo.UpsertEventSchedule(post.EventID, uuid.FromStringOrNil(stamp.UserID), scheduleStatus) + if err != nil { + fmt.Println(err) + } + } +} diff --git a/main.go b/main.go index bb436efb..b13dd919 100644 --- a/main.go +++ b/main.go @@ -15,6 +15,7 @@ import ( "github.com/traPtitech/knoQ/repository" "github.com/traPtitech/knoQ/utils" "github.com/traPtitech/knoQ/utils/tz" + "github.com/traPtitech/traq-ws-bot/payload" "golang.org/x/oauth2" "github.com/traPtitech/knoQ/router" @@ -124,6 +125,10 @@ func main() { if err != nil { panic(err) } + bot.Bot.OnBotMessageStampsUpdated(func(p *payload.BotMessageStampsUpdated) { + bot.BotMessageStampsUpdatedHandler(p, gormRepo) + }) + if err := bot.Bot.Start(); err != nil { panic(err) } From d3f2da1bc2f74a484fa742fd342d2ef5870d4c0b Mon Sep 17 00:00:00 2001 From: DO885 Date: Fri, 5 Jul 2024 23:43:50 +0900 Subject: [PATCH 06/10] =?UTF-8?q?=E2=9C=A8=20v13=20migration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- migration/current.go | 1 + migration/v13.go | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 migration/v13.go diff --git a/migration/current.go b/migration/current.go index b4790920..f0660043 100644 --- a/migration/current.go +++ b/migration/current.go @@ -19,5 +19,6 @@ func Migrations() []*gormigrate.Migration { v10(), v11(), v12(), + v13(), } } diff --git a/migration/v13.go b/migration/v13.go new file mode 100644 index 00000000..7b1a8915 --- /dev/null +++ b/migration/v13.go @@ -0,0 +1,25 @@ +package migration + +import ( + "github.com/go-gormigrate/gormigrate/v2" + "github.com/gofrs/uuid" + "gorm.io/gorm" +) + +type v13Post struct { + MessageID uuid.UUID `gorm:"type:char(36); primaryKey"` + EventID uuid.UUID `gorm:"type:char(36); not null"` +} + +func (*v13Post) TableName() string { + return "posts" +} + +func v13() *gormigrate.Migration { + return &gormigrate.Migration{ + ID: "13", + Migrate: func(db *gorm.DB) error { + return db.Migrator().CreateTable(&v13Post{}) + }, + } +} From 0cdce1cd227710fcc7b09fc8bb81c15c6ddba44a Mon Sep 17 00:00:00 2001 From: DO885 Date: Fri, 5 Jul 2024 23:44:31 +0900 Subject: [PATCH 07/10] =?UTF-8?q?=E2=9C=A8=20implement=20PostRepository?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- domain/domain.go | 1 + domain/post.go | 5 +++++ infra/db/converter.go | 6 ++++++ repository/post.go | 28 ++++++++++++++++++++++++++++ router/middleware.go | 7 ++++++- utils/api.go | 9 +++++---- utils/cron.go | 2 +- 7 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 repository/post.go diff --git a/domain/domain.go b/domain/domain.go index 80806cab..0421baf4 100644 --- a/domain/domain.go +++ b/domain/domain.go @@ -30,4 +30,5 @@ type Repository interface { RoomRepository TagRepository UserRepository + PostRepository } diff --git a/domain/post.go b/domain/post.go index 9be9a965..57fe8dcb 100644 --- a/domain/post.go +++ b/domain/post.go @@ -11,3 +11,8 @@ type WritePostParams struct { MessageID uuid.UUID EventID uuid.UUID } + +type PostRepository interface { + CreatePost(params WritePostParams) (*Post, error) + GetPost(MessageID uuid.UUID) (*Post, error) +} diff --git a/infra/db/converter.go b/infra/db/converter.go index 973a8214..f62cccd7 100644 --- a/infra/db/converter.go +++ b/infra/db/converter.go @@ -127,6 +127,12 @@ func ConvRoomTodomainRoom(src Room) (dst domain.Room) { return } +func ConvPostTodomainPost(src Post) (dst domain.Post) { + dst.MessageID = src.MessageID + dst.EventID = src.EventID + return +} + func ConvSEventAdminToSRoomAdmin(src []EventAdmin) (dst []RoomAdmin) { dst = make([]RoomAdmin, len(src)) for i := range src { diff --git a/repository/post.go b/repository/post.go new file mode 100644 index 00000000..ff5b4607 --- /dev/null +++ b/repository/post.go @@ -0,0 +1,28 @@ +package repository + +import ( + "github.com/gofrs/uuid" + "github.com/traPtitech/knoQ/domain" + "github.com/traPtitech/knoQ/infra/db" +) + +func (repo *Repository) CreatePost(params domain.WritePostParams) (*domain.Post, error) { + p := db.WritePostParams{ + WritePostParams: params, + } + post, err := repo.GormRepo.CreatePost(p) + if err != nil { + return nil, defaultErrorHandling(err) + } + domainPost := db.ConvPostTodomainPost(*post) + return &domainPost, nil +} + +func (repo *Repository) GetPost(MessageID uuid.UUID) (*domain.Post, error) { + post, err := repo.GormRepo.GetPost(MessageID) + if err != nil { + return nil, defaultErrorHandling(err) + } + domainPost := db.ConvPostTodomainPost(*post) + return &domainPost, nil +} diff --git a/router/middleware.go b/router/middleware.go index 4b894af6..a550b182 100644 --- a/router/middleware.go +++ b/router/middleware.go @@ -222,7 +222,12 @@ func (h *Handlers) WebhookEventHandler(c echo.Context, reqBody, resBody []byte) content := presentation.GenerateEventBotContent(c.Request().Method, e, notificationTargets, h.Origin, !domain.DEVELOPMENT) - _ = utils.RequestBotPost(content, h.ActivityChannelID) + messageID, err := utils.RequestBotPost(content, h.ActivityChannelID) + if err != nil { + h.Logger.Error("failed to request bot post", zap.Error(err)) + return + } + h.Repo.CreatePost(domain.WritePostParams{MessageID: messageID, EventID: e.ID}) } // getRequestUserID sessionからuserを返します diff --git a/utils/api.go b/utils/api.go index 8b827c9e..25251e2b 100644 --- a/utils/api.go +++ b/utils/api.go @@ -3,18 +3,19 @@ package utils import ( "context" + "github.com/gofrs/uuid" "github.com/traPtitech/go-traq" "github.com/traPtitech/knoQ/infra/bot" ) // RequestBotPost q.trap/jp にメッセージを送信します。 -func RequestBotPost(message, channelID string) error { - _, _, err := bot.Bot.API(). +func RequestBotPost(messageText, channelID string) (uuid.UUID, error) { + message, _, err := bot.Bot.API(). MessageApi. PostMessage(context.Background(), channelID). PostMessageRequest(traq.PostMessageRequest{ - Content: message, + Content: messageText, }). Execute() - return err + return uuid.FromStringOrNil(message.Id), err } diff --git a/utils/cron.go b/utils/cron.go index 0ae4db7e..ac1f9280 100644 --- a/utils/cron.go +++ b/utils/cron.go @@ -29,7 +29,7 @@ func InitPostEventToTraQ(repo *db.GormRepository, channelID, origin string) func rooms, _ := repo.GetAllRooms(now, tomorrow, uuid.Nil) events, _ := repo.GetAllEvents(filter.FilterTime(now, tomorrow)) message := createMessage(now, rooms, events, origin) - err := RequestBotPost(message, channelID) + _, err := RequestBotPost(message, channelID) if err != nil { fmt.Println(err) } From af8b5119d6af93a59fa36dd4d12c9b330b20b4a3 Mon Sep 17 00:00:00 2001 From: DO885 Date: Sun, 7 Jul 2024 21:00:31 +0900 Subject: [PATCH 08/10] =?UTF-8?q?=E2=9C=A8=20add=20status=20stamps=20to=20?= =?UTF-8?q?bot=20post?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/bot/bot.go | 12 +++++++++--- router/middleware.go | 5 +++++ utils/api.go | 13 +++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/infra/bot/bot.go b/infra/bot/bot.go index dca1e4f7..3c3d8415 100644 --- a/infra/bot/bot.go +++ b/infra/bot/bot.go @@ -12,6 +12,12 @@ import ( var Bot *traqwsbot.Bot +const ( + AttendanceStampID = "93d376c3-80c9-4bb2-909b-2bbe2fbf9e93" + AbsentStampID = "544c04db-9cc3-4c0e-935d-571d4cf103a2" + PendingStampID = "bc9a3814-f185-4b3d-ac1f-3c8f12ad7b52" +) + func BotMessageStampsUpdatedHandler(p *payload.BotMessageStampsUpdated, gormRepo db.GormRepository) { post, err := gormRepo.GetPost(uuid.FromStringOrNil(p.MessageID)) if err != nil { @@ -20,13 +26,13 @@ func BotMessageStampsUpdatedHandler(p *payload.BotMessageStampsUpdated, gormRepo for _, stamp := range p.Stamps { var scheduleStatus domain.ScheduleStatus switch stamp.StampID { - case "8658c060-6f8e-46f6-8ee8-3fbc63f2ed4d": + case AttendanceStampID: // 出席 scheduleStatus = domain.Attendance - case "7813a8d6-77ab-446d-af1c-559db2ccab10": + case AbsentStampID: // 欠席 scheduleStatus = domain.Absent - case "0d9c5a46-61bc-4c9c-873f-99eee45757fc": + case PendingStampID: // 未定 scheduleStatus = domain.Pending } diff --git a/router/middleware.go b/router/middleware.go index a550b182..1d642dd3 100644 --- a/router/middleware.go +++ b/router/middleware.go @@ -227,6 +227,11 @@ func (h *Handlers) WebhookEventHandler(c echo.Context, reqBody, resBody []byte) h.Logger.Error("failed to request bot post", zap.Error(err)) return } + err = utils.RequestBotStatusStamp(messageID) + if err != nil { + h.Logger.Error("failed to request bot status stamp", zap.Error(err)) + return + } h.Repo.CreatePost(domain.WritePostParams{MessageID: messageID, EventID: e.ID}) } diff --git a/utils/api.go b/utils/api.go index 25251e2b..4fc27736 100644 --- a/utils/api.go +++ b/utils/api.go @@ -19,3 +19,16 @@ func RequestBotPost(messageText, channelID string) (uuid.UUID, error) { Execute() return uuid.FromStringOrNil(message.Id), err } + +// RequestBotStatusStamp :white_check_mark:, :no_entry_sign:, :loading: のスタンプを送信します。 +func RequestBotStatusStamp(messageID uuid.UUID) error { + stamps := []string{bot.AttendanceStampID, bot.AbsentStampID, bot.PendingStampID} + for _, stampID := range stamps { + _, err := bot.Bot.API(). + MessageApi.AddMessageStamp(context.Background(), messageID.String(), stampID).Execute() + if err != nil { + return err + } + } + return nil +} From 81250831e01737411ac329e0ddb0bb09c4450c9f Mon Sep 17 00:00:00 2001 From: DO885 Date: Sun, 7 Jul 2024 21:15:53 +0900 Subject: [PATCH 09/10] =?UTF-8?q?=E2=9C=A8=20ignore=20old=20stamp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- infra/bot/bot.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/infra/bot/bot.go b/infra/bot/bot.go index 3c3d8415..55d7bfc8 100644 --- a/infra/bot/bot.go +++ b/infra/bot/bot.go @@ -2,6 +2,7 @@ package bot import ( "fmt" + "time" "github.com/gofrs/uuid" "github.com/traPtitech/knoQ/domain" @@ -24,6 +25,10 @@ func BotMessageStampsUpdatedHandler(p *payload.BotMessageStampsUpdated, gormRepo fmt.Println(err) } for _, stamp := range p.Stamps { + if time.Now().After(stamp.UpdatedAt.Add(3 * time.Second)) { + // 3秒以上経過したスタンプは無視 + continue + } var scheduleStatus domain.ScheduleStatus switch stamp.StampID { case AttendanceStampID: @@ -35,6 +40,8 @@ func BotMessageStampsUpdatedHandler(p *payload.BotMessageStampsUpdated, gormRepo case PendingStampID: // 未定 scheduleStatus = domain.Pending + default: + continue } err := gormRepo.UpsertEventSchedule(post.EventID, uuid.FromStringOrNil(stamp.UserID), scheduleStatus) if err != nil { From 0c3b48c9784fb81c2492da7b92921676cfcbc10e Mon Sep 17 00:00:00 2001 From: DO885 Date: Sun, 7 Jul 2024 21:43:07 +0900 Subject: [PATCH 10/10] =?UTF-8?q?=F0=9F=A7=B9=20replaced=20webhook=20to=20?= =?UTF-8?q?bot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 3 +-- README.md | 3 +-- compose.yml | 2 -- main.go | 6 +----- router/middleware.go | 4 ++-- router/router.go | 6 ++---- 6 files changed, 7 insertions(+), 17 deletions(-) diff --git a/.env.example b/.env.example index 6f9a2956..1f003b4c 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,7 @@ SESSION_KEY= TRAQ_CALENDARID= CLIENT_ID= -WEBHOOK_ID= -WEBHOOK_SECRET= +TRAQ_BOT_TOKEN= ACTIVITY_CHANNEL_ID= DAILY_CHANNEL_ID= TOKEN_KEY= diff --git a/README.md b/README.md index 482d90ee..f8bc234f 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,7 @@ knoQ の全ての機能を動作させるためには、追加の情報が必要 | SESSION_KEY | 環境変数 | `random32wordsXXXXXXXXXXXXXXXXXXX` | session を暗号化するもの | | TRAQ_CALENDARID | 環境変数 | | 進捗部屋の提供元(公開されている google calendar の id なら何でもいい) | | CLIENT_ID | 環境変数 | `d1hDlIRNfCBerXdZkH1VR8lJwCBpIuMgiv42` | 認証に必要 | -| WEBHOOK_ID | 環境変数 | | Bot 情報 | -| WEBHOOK_SECRET | 環境変数 | | Bot 情報 | +| TRAQ_BOT_TOKEN | 環境変数 | | Bot 情報 | | CHANNEL_ID | 環境変数 | | Bot の送信先チャンネル (deprecated) | | DAILY_CHANNEL_ID | 環境変数 | | Bot が毎日定時に投稿する先のチャンネル | | ACTIVITY_CHANNEL_ID | 環境変数 | | Bot が都度送信するチャンネル | diff --git a/compose.yml b/compose.yml index 6646730e..f92f64fd 100755 --- a/compose.yml +++ b/compose.yml @@ -16,8 +16,6 @@ services: SESSION_KEY: ${SESSION_KEY:-random32wordsXXXXXXXXXXXXXXXXXXX} TRAQ_CALENDARID: ${TRAQ_CALENDARID} CLIENT_ID: ${CLIENT_ID:-d1hDlIRNfCBerXdZkH1VR8lJwCBpIuMgiv42} - WEBHOOK_ID: ${WEBHOOK_ID} - WEBHOOK_SECRET: ${WEBHOOK_SECRET} CHANNEL_ID: ${CHANNEL_ID} DAILY_CHANNEL_ID: ${DAILY_CHANNEL_ID} ACTIVITY_CHANNEL_ID: ${ACTIVITY_CHANNEL_ID} diff --git a/main.go b/main.go index b13dd919..2303c19e 100644 --- a/main.go +++ b/main.go @@ -43,8 +43,6 @@ var ( clientID = getenv("CLIENT_ID", "client_id") origin = getenv("ORIGIN", "http://localhost:3000") sessionKey = getenv("SESSION_KEY", "random32wordsXXXXXXXXXXXXXXXXXXX") - webhookID = getenv("WEBHOOK_ID", "") - webhookSecret = getenv("WEBHOOK_SECRET", "") activityChannelID = getenv("ACTIVITY_CHANNEL_ID", "") dailyChannelID = getenv("DAILY_CHANNEL_ID", "") ) @@ -87,8 +85,6 @@ func main() { HttpOnly: true, SameSite: http.SameSiteLaxMode, }, - WebhookID: webhookID, - WebhookSecret: webhookSecret, ActivityChannelID: activityChannelID, DailyChannelId: dailyChannelID, Origin: origin, @@ -96,7 +92,7 @@ func main() { e := handler.SetupRoute() - // webhook + // cron c := cron.New(cron.WithLocation(tz.JST)) _, err = c.AddFunc( "0 8 * * *", diff --git a/router/middleware.go b/router/middleware.go index 1d642dd3..939c30fe 100644 --- a/router/middleware.go +++ b/router/middleware.go @@ -176,8 +176,8 @@ func (h *Handlers) RoomAdminsMiddleware(next echo.HandlerFunc) echo.HandlerFunc } } -// WebhookEventHandler is used with middleware.BodyDump -func (h *Handlers) WebhookEventHandler(c echo.Context, reqBody, resBody []byte) { +// BotEventHandler is used with middleware.BodyDump +func (h *Handlers) BotEventHandler(c echo.Context, reqBody, resBody []byte) { if c.Response().Status >= 400 { return } diff --git a/router/router.go b/router/router.go index 9855d1f1..dc87be3a 100644 --- a/router/router.go +++ b/router/router.go @@ -25,8 +25,6 @@ type Handlers struct { SessionKey []byte SessionOption sessions.Options ClientID string - WebhookID string - WebhookSecret string ActivityChannelID string DailyChannelId string Origin string @@ -90,7 +88,7 @@ func (h *Handlers) SetupRoute() *echo.Echo { eventsAPI := apiWithAuth.Group("/events") { eventsAPI.GET("", h.HandleGetEvents) - eventsAPI.POST("", h.HandlePostEvent, middleware.BodyDump(h.WebhookEventHandler)) + eventsAPI.POST("", h.HandlePostEvent, middleware.BodyDump(h.BotEventHandler)) eventsAPI.GET("/:eventid", h.HandleGetEvent) eventsAPI.PUT("/:eventid/attendees/me", h.HandleUpsertMeEventSchedule) eventsAPI.POST("/:eventid/tags", h.HandleAddEventTag) @@ -99,7 +97,7 @@ func (h *Handlers) SetupRoute() *echo.Echo { // イベント管理者権限が必要 eventsAPIWithAdminAuth := eventsAPI.Group("", h.EventAdminsMiddleware) { - eventsAPIWithAdminAuth.PUT("/:eventid", h.HandleUpdateEvent, middleware.BodyDump(h.WebhookEventHandler)) + eventsAPIWithAdminAuth.PUT("/:eventid", h.HandleUpdateEvent, middleware.BodyDump(h.BotEventHandler)) eventsAPIWithAdminAuth.DELETE("/:eventid", h.HandleDeleteEvent) } }