Skip to content

Commit

Permalink
write all logic
Browse files Browse the repository at this point in the history
  • Loading branch information
logica0419 committed Sep 9, 2024
1 parent 6b438c6 commit 0e14c5c
Show file tree
Hide file tree
Showing 3 changed files with 238 additions and 4 deletions.
10 changes: 9 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@ module github.com/nekko-lab/kakko
go 1.23.1

require (
github.com/go-sql-driver/mysql v1.8.1
github.com/gofiber/fiber/v2 v2.52.5
github.com/gofiber/template/django/v3 v3.1.12
github.com/google/uuid v1.5.0
github.com/sivchari/gotwtr v1.2.1
gorm.io/driver/mysql v1.5.7
gorm.io/gorm v1.25.12
)

require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/flosch/pongo2/v6 v6.0.0 // indirect
github.com/gofiber/template v1.8.3 // indirect
github.com/gofiber/utils v1.1.0 // indirect
github.com/google/uuid v1.5.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.17.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
Expand All @@ -22,4 +29,5 @@ require (
github.com/valyala/fasthttp v1.51.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
)
20 changes: 20 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/flosch/pongo2/v6 v6.0.0 h1:lsGru8IAzHgIAw6H2m4PCyleO58I40ow6apih0WprMU=
github.com/flosch/pongo2/v6 v6.0.0/go.mod h1:CuDpFm47R0uGGE7z13/tTlt1Y6zdxvr2RLT5LJhsHEU=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo=
github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc=
Expand All @@ -12,8 +17,14 @@ github.com/gofiber/template/django/v3 v3.1.12 h1:w2jxm9bJajhvrroXqEmUmakbvDSlzjp
github.com/gofiber/template/django/v3 v3.1.12/go.mod h1:4YNpM+LJ/el+cjUpdulp8lOH6dxZ2jaQmrF4E2/KGAk=
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
Expand All @@ -31,6 +42,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/sivchari/gotwtr v1.2.1 h1:03oaLGJTrG1XRADbO1/3lvDzs66VfU1AZGilHrxr5VM=
github.com/sivchari/gotwtr v1.2.1/go.mod h1:RvanNbGfdV6kWRa1BhUo3KF9IYFGmd+zTpiZC5bJJV4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
Expand All @@ -43,7 +56,14 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
212 changes: 209 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,38 +1,244 @@
package main

import (
"bytes"
"embed"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"strconv"
"time"

driverMysql "github.com/go-sql-driver/mysql"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/template/django/v3"
"github.com/google/uuid"
"github.com/sivchari/gotwtr"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)

func init() {
const location = "Asia/Tokyo"

loc, err := time.LoadLocation(location)
if err != nil {
loc = time.FixedZone(location, 9*60*60)
}

time.Local = loc
}

var db *gorm.DB

type DBConfig struct {
Username string
Password string
Host string
Port int
Database string
}

func InitDB(c *DBConfig) (err error) {
db, err = gorm.Open(mysql.New(mysql.Config{
DSNConfig: &driverMysql.Config{
User: c.Username,
Passwd: c.Password,
Net: "tcp",
Addr: fmt.Sprintf("%s:%d", c.Host, c.Port),
DBName: c.Database,
Collation: "utf8mb4_general_ci",
ParseTime: true,
AllowNativePasswords: true,
},
}))
if err != nil {
return
}

db.Logger = db.Logger.LogMode(logger.Info)

return db.AutoMigrate(&PostRequest{})
}

type PostRequest struct {
ID uuid.UUID `gorm:"type:char(36);not null;primaryKey"`
Content string `gorm:"type:text;not null"`
CreatedAt time.Time `gorm:"type:datetime;not null;default:CURRENT_TIMESTAMP"`
}

func (pr *PostRequest) TableName() string {
return "post_requests"
}

func getenv(key, fallback string) string {
value := os.Getenv(key)
if len(value) == 0 {
return fallback
}

return value
}

//go:embed pages
var pages embed.FS

var (
confirmPassword = getenv("CONFIRM_PASSWORD", "password")
webhookURL = getenv("WEBHOOK_URL", "")
xKey = getenv("X_KEY", "")
dev = getenv("DEV", "true") == "true"
)

func main() {
port, err := strconv.Atoi(getenv("DB_PORT", "3306"))
if err != nil {
log.Panic(err)
}

c := &DBConfig{
Username: getenv("DB_USERNAME", "root"),
Password: getenv("DB_PASSWORD", "password"),
Host: getenv("DB_HOST", "localhost"),
Port: port,
Database: getenv("DB_DATABASE", "kakko"),
}
err = InitDB(c)
if err != nil {
log.Panic(err)
}

engine := django.NewPathForwardingFileSystem(http.FS(pages), "/pages", ".django")

app := fiber.New(fiber.Config{
Views: engine,
})

app.Get("/", renderPostPage)
app.Get("/", getPost)
app.Post("/", postPost)
app.Get("/reviews/:id", getReview)
app.Post("/reviews/:id", postReview)

log.Panic(app.Listen(":9000"))
}

func renderPostPage(c *fiber.Ctx) error {
func getPost(c *fiber.Ctx) error {
return c.Render("post", fiber.Map{}, "layout")
}

func postPost(c *fiber.Ctx) error {
content := c.FormValue("content")

return c.Render("confirm", fiber.Map{
id, err := uuid.NewV7()
if err != nil {
return c.Status(http.StatusInternalServerError).SendString(err.Error())
}

pr := &PostRequest{
ID: id,
Content: content,
CreatedAt: time.Now(),
}

err = db.Create(pr).Error
if err != nil {
return c.Status(http.StatusInternalServerError).SendString(err.Error())
}

contentJson, err := json.Marshal(struct {
Content string `json:"content"`
}{
Content: `## 新しいポストリクエストが作成されました
ポストリクエストを承認してください。
http://localhost:9000/reviews/` + pr.ID.String(),
})
if err != nil {
return c.Status(http.StatusInternalServerError).SendString(err.Error())
}

_, err = http.Post(
webhookURL,
"application/json",
bytes.NewBuffer(contentJson),
)
if err != nil {
return c.Status(http.StatusInternalServerError).SendString(err.Error())
}

return c.Render("post_confirm", fiber.Map{
"ID": pr.ID,
"Content": content,
}, "layout")
}

func getReview(c *fiber.Ctx) error {
id := c.Params("id")

var pr PostRequest
err := db.Where("id = ?", id).First(&pr).Error
if err != nil {
return c.Status(http.StatusInternalServerError).SendString(err.Error())
}

return c.Render("review", fiber.Map{
"ID": pr.ID,
"Content": pr.Content,
}, "layout")
}

func postReview(c *fiber.Ctx) error {
password := c.FormValue("password")
if password != confirmPassword {
return c.Status(http.StatusUnauthorized).SendString("Unauthorized")
}

id := c.Params("id")

var pr PostRequest
err := db.Where("id = ?", id).First(&pr).Error
if err != nil {
return c.Status(http.StatusInternalServerError).SendString(err.Error())
}

if dev {
contentJson, err := json.Marshal(struct {
Content string `json:"content"`
}{
Content: "## ポスト送信テスト\n\n```\n" + pr.Content + "\n```",
})
if err != nil {
return c.Status(http.StatusInternalServerError).SendString(err.Error())
}

_, err = http.Post(
webhookURL,
"application/json",
bytes.NewBuffer(contentJson),
)
if err != nil {
return c.Status(http.StatusInternalServerError).SendString(err.Error())
}
} else {
client := gotwtr.New(xKey)
_, err := client.PostTweet(c.Context(), &gotwtr.PostTweetOption{
Text: pr.Content,
})
if err != nil {
return c.Status(http.StatusInternalServerError).SendString(err.Error())
}
}

err = db.Delete(&pr).Error
if err != nil {
return c.Status(http.StatusInternalServerError).SendString(err.Error())
}

return c.Render("review_confirm", fiber.Map{
"ID": pr.ID,
"Content": pr.Content,
}, "layout")
}

0 comments on commit 0e14c5c

Please sign in to comment.