diff --git a/internal/apps/flags/handlers.go b/internal/apps/flags/handlers.go index 4ce4631..d98c534 100644 --- a/internal/apps/flags/handlers.go +++ b/internal/apps/flags/handlers.go @@ -1,311 +1,308 @@ package flags import ( - "context" - "database/sql" - "net/http" - "strconv" - "time" + "context" + "database/sql" + "net/http" + "strconv" + "time" - "git.tijl.dev/tijl/tijl.dev-core/internal/queries" - "git.tijl.dev/tijl/tijl.dev-core/internal/user" - "git.tijl.dev/tijl/tijl.dev-core/internal/utils" - "git.tijl.dev/tijl/tijl.dev-core/modules/db" - "git.tijl.dev/tijl/tijl.dev-core/modules/i18n" - "git.tijl.dev/tijl/tijl.dev-core/modules/web" - "github.com/enescakir/emoji" - "github.com/gofiber/fiber/v2" - "github.com/google/uuid" + "git.tijl.dev/tijl/tijl.dev-core/internal/queries" + "git.tijl.dev/tijl/tijl.dev-core/internal/user" + "git.tijl.dev/tijl/tijl.dev-core/internal/utils" + "git.tijl.dev/tijl/tijl.dev-core/modules/db" + "git.tijl.dev/tijl/tijl.dev-core/modules/i18n" + "git.tijl.dev/tijl/tijl.dev-core/modules/web" + "github.com/enescakir/emoji" + "github.com/gofiber/fiber/v2" + "github.com/google/uuid" ) const flagSessionCookie string = "app_flags_game_session" type NullableUUID struct { - uuid.UUID - valid bool + uuid.UUID + valid bool } type NullableString struct { - String string - valid bool + String string + valid bool } func answerHandler(c *fiber.Ctx) error { - gameId, err := uuid.Parse(c.Cookies(flagSessionCookie)) - if err != nil { - return err - } + gameId, err := uuid.Parse(c.Cookies(flagSessionCookie)) + if err != nil { + return err + } - answer := c.FormValue("answer") + answer := c.FormValue("answer") - gameSession, err := db.Queries.AppFlagsGetGame(context.TODO(), gameId) - if err != nil { - return err - } + gameSession, err := db.Queries.AppFlagsGetGame(context.TODO(), gameId) + if err != nil { + return err + } - err, countries := filterCountriesByTags(gameSession.Tags) - if err != nil { - return err - } + err, countries := filterCountriesByTags(gameSession.Tags) + if err != nil { + return err + } - shuffledCountries := shuffleSlice(countries, gameSession.GameSeed.String()) + shuffledCountries := shuffleSlice(countries, gameSession.GameSeed.String()) - correctAnswer := shuffledCountries[gameSession.QuestionCurrent-1] + correctAnswer := shuffledCountries[gameSession.QuestionCurrent-1] - if answer == correctAnswer { - db.Queries.AppFlagsUpdateGame(context.TODO(), queries.AppFlagsUpdateGameParams{ - GameID: gameId, - QuestionCurrent: gameSession.QuestionCurrent + 1, - }) - db.Queries.AppFlagsUpsertGameAnswer(context.TODO(), queries.AppFlagsUpsertGameAnswerParams{ - GameID: gameId, - Question: gameSession.QuestionCurrent, - Errors: 0, - }) - } else { - db.Queries.AppFlagsUpsertGameAnswer(context.TODO(), queries.AppFlagsUpsertGameAnswerParams{ - GameID: gameId, - Question: gameSession.QuestionCurrent, - Errors: 1, - }) - } + if answer == correctAnswer { + db.Queries.AppFlagsUpdateGame(context.TODO(), queries.AppFlagsUpdateGameParams{ + GameID: gameId, + QuestionCurrent: gameSession.QuestionCurrent + 1, + }) + db.Queries.AppFlagsUpsertGameAnswer(context.TODO(), queries.AppFlagsUpsertGameAnswerParams{ + GameID: gameId, + Question: gameSession.QuestionCurrent, + Errors: 0, + }) + } else { + db.Queries.AppFlagsUpsertGameAnswer(context.TODO(), queries.AppFlagsUpsertGameAnswerParams{ + GameID: gameId, + Question: gameSession.QuestionCurrent, + Errors: 1, + }) + } - err = db.Queries.AppFlagsUpdateQuestionCorrect(context.TODO(), gameId) - if err != nil { - return err - } + err = db.Queries.AppFlagsUpdateQuestionCorrect(context.TODO(), gameId) + if err != nil { + return err + } - if answer == correctAnswer { - return questionHandler(c, NullableUUID{}, NullableString{}) - } else { - return questionHandler(c, NullableUUID{}, NullableString{valid: true, String: answer}) - } + if answer == correctAnswer { + return questionHandler(c, NullableUUID{}, NullableString{}) + } else { + return questionHandler(c, NullableUUID{}, NullableString{valid: true, String: answer}) + } } func questionHandler(c *fiber.Ctx, newGame NullableUUID, prevError NullableString) error { - var gameId uuid.UUID - var err error - if newGame.valid { - gameId = newGame.UUID - } else { - gameId, err = uuid.Parse(c.Cookies(flagSessionCookie)) - if err != nil { - return err - } - } + var gameId uuid.UUID + var err error + if newGame.valid { + gameId = newGame.UUID + } else { + gameId, err = uuid.Parse(c.Cookies(flagSessionCookie)) + if err != nil { + return err + } + } - gameSession, err := db.Queries.AppFlagsGetGame(context.TODO(), gameId) - if err != nil { - return err - } + gameSession, err := db.Queries.AppFlagsGetGame(context.TODO(), gameId) + if err != nil { + return err + } - uid, err := user.GetSession(c) - if uid != gameSession.Uid.String { - utils.ClearCookie(c, flagSessionCookie) - return gameStartHandler(c) - } + uid, err := user.GetSession(c) + if uid != gameSession.Uid.String { + utils.ClearCookie(c, flagSessionCookie) + return gameStartHandler(c) + } - if (gameSession.QuestionAmount != 0) && (gameSession.QuestionAmount+1 == gameSession.QuestionCurrent) { - return gameEndHandler(c) - } + if (gameSession.QuestionAmount != 0) && (gameSession.QuestionAmount+1 == gameSession.QuestionCurrent) { + return gameEndHandler(c) + } - err, countries := filterCountriesByTags(gameSession.Tags) - if err != nil { - return err - } + err, countries := filterCountriesByTags(gameSession.Tags) + if err != nil { + return err + } - if int(gameSession.QuestionCurrent) == len(countries) { - return gameEndHandler(c) - } + if int(gameSession.QuestionCurrent) == len(countries) { + return gameEndHandler(c) + } - shuffledCountries := shuffleSlice(countries, gameSession.GameSeed.String()) - correctAnswer := shuffledCountries[gameSession.QuestionCurrent-1] - filteredCountries := filterSlice(countries, correctAnswer) - shuffledAnswers := shuffleSlice(filteredCountries, gameSession.GameSeed.String()+string(gameSession.QuestionCurrent)) - var correctAnswerData CountryCode - for _, country := range countryCodes { - if country.Code == correctAnswer { - correctAnswerData = country - break - } - } - var filteredAnswers []string - for _, shuffledAnswer := range shuffledAnswers { - for _, country := range countryCodes { - if shuffledAnswer == country.Code { - if hasCommonTag(correctAnswerData.Tags, country.Tags) { - filteredAnswers = append(filteredAnswers, country.Code) - } - } - } - } - shuffledAnswers = filteredAnswers - shuffledAnswers = shuffledAnswers[0:4] - shuffledAnswers = append(shuffledAnswers, correctAnswer) - shuffledAnswers = shuffleSlice(shuffledAnswers, gameSession.GameSeed.String()+string(gameSession.QuestionCurrent)) + shuffledCountries := shuffleSlice(countries, gameSession.GameSeed.String()) + correctAnswer := shuffledCountries[gameSession.QuestionCurrent-1] + filteredCountries := filterSlice(countries, correctAnswer) + shuffledAnswers := shuffleSlice(filteredCountries, gameSession.GameSeed.String()+string(gameSession.QuestionCurrent)) + var correctAnswerData CountryCode + for _, country := range countryCodes { + if country.Code == correctAnswer { + correctAnswerData = country + break + } + } + var filteredAnswers []string + for _, shuffledAnswer := range shuffledAnswers { + for _, country := range countryCodes { + if shuffledAnswer == country.Code { + if hasCommonTag(correctAnswerData.Tags, country.Tags) { + filteredAnswers = append(filteredAnswers, country.Code) + } + } + } + } + shuffledAnswers = filteredAnswers + shuffledAnswers = shuffledAnswers[0:4] + shuffledAnswers = append(shuffledAnswers, correctAnswer) + shuffledAnswers = shuffleSlice(shuffledAnswers, gameSession.GameSeed.String()+string(gameSession.QuestionCurrent)) - if gameSession.QuestionAmount != 0 && int(gameSession.QuestionAmount) < len(countries) { - shuffledCountries = shuffledCountries[0:gameSession.QuestionAmount] - } + if gameSession.QuestionAmount != 0 && int(gameSession.QuestionAmount) < len(countries) { + shuffledCountries = shuffledCountries[0:gameSession.QuestionAmount] + } - var timeleft = []string{} - if gameSession.Seconds != 0 { - timeleft = append(timeleft, strconv.Itoa(int(gameSession.Seconds)-int(time.Since(gameSession.CreatedAt).Seconds()))) - } + var timeleft = []string{} + if gameSession.Seconds != 0 { + timeleft = append(timeleft, strconv.Itoa(int(gameSession.Seconds)-int(time.Since(gameSession.CreatedAt).Seconds()))) + } - flag, err := emoji.CountryFlag(shuffledCountries[gameSession.QuestionCurrent-1]) - if err != nil { - return err - } + flag, err := emoji.CountryFlag(shuffledCountries[gameSession.QuestionCurrent-1]) + if err != nil { + return err + } - data := *web.Common(c) - data["Title"] = "tmp" - data["TimeLeft"] = timeleft - data["QuestionsLeft"] = len(shuffledCountries) - int(gameSession.QuestionCurrent) + 1 - data["Answers"] = shuffledAnswers - data["Flag"] = flag - data["Errors"] = gameSession.QuestionsErrors - data["PreviousError"] = prevError.String - data["ShortcutKeys"] = []string{"d", "f", "h", "j", "k"} - return c.Render("apps/flags/question", data, "layouts/base") + data := *web.Common(c) + data["Title"] = "tmp" + data["TimeLeft"] = timeleft + data["QuestionsLeft"] = len(shuffledCountries) - int(gameSession.QuestionCurrent) + 1 + data["Answers"] = shuffledAnswers + data["Flag"] = flag + data["Errors"] = gameSession.QuestionsErrors + data["PreviousError"] = prevError.String + data["ShortcutKeys"] = []string{"d", "f", "h", "j", "k"} + return c.Render("apps/flags/question", data, "layouts/base") } func sharedGameHandler(c *fiber.Ctx) error { - shareKey := c.FormValue("sharekey") - data, err := db.Queries.AppFlagsGetSharedData(context.TODO(), shareKey) - if err != nil { - return err - } + shareKey := c.FormValue("sharekey") + data, err := db.Queries.AppFlagsGetSharedData(context.TODO(), shareKey) + if err != nil { + return err + } - return setupGame(c, data.Tags, int(data.Questions), int(data.Seconds), NullableUUID{valid: true, UUID: data.GameSeed}) + return setupGame(c, data.Tags, int(data.Questions), int(data.Seconds), NullableUUID{valid: true, UUID: data.GameSeed}) } func startNewGameHandler(c *fiber.Ctx) error { - values := c.Request().PostArgs().PeekMulti("tags") - var selectedTags []string - for _, v := range values { - selectedTags = append(selectedTags, string(v)) - } + values := c.Request().PostArgs().PeekMulti("tags") + var selectedTags []string + for _, v := range values { + selectedTags = append(selectedTags, string(v)) + } - if len(selectedTags) < 1 { - return c.Status(http.StatusBadRequest).SendString(i18n.GetTranslations(i18n.GetLanguage(c))["select_more_countries"]) - } + if len(selectedTags) < 1 { + return c.Status(http.StatusBadRequest).SendString(i18n.GetTranslations(i18n.GetLanguage(c))["select_more_countries"]) + } - err, countries := filterCountriesByTags(selectedTags) - if err != nil { - return err - } + err, countries := filterCountriesByTags(selectedTags) + if err != nil { + return err + } - if len(countries) < 6 { - return c.Status(http.StatusBadRequest).SendString(i18n.GetTranslations(i18n.GetLanguage(c))["select_more_countries"]) - } + if len(countries) < 6 { + return c.Status(http.StatusBadRequest).SendString(i18n.GetTranslations(i18n.GetLanguage(c))["select_more_countries"]) + } - maxQuestions, err := strconv.Atoi(c.FormValue("max_questions")) - if err != nil { - return err - } + maxQuestions, err := strconv.Atoi(c.FormValue("max_questions")) + if err != nil { + return err + } - seconds, err := strconv.Atoi(c.FormValue("seconds")) - if err != nil { - return err - } + seconds, err := strconv.Atoi(c.FormValue("seconds")) + if err != nil { + return err + } - if c.FormValue("share") != "" { - return createSharedGameData(c, selectedTags, maxQuestions, seconds) - } + if c.FormValue("share") != "" { + return createSharedGameData(c, selectedTags, maxQuestions, seconds) + } - return setupGame(c, selectedTags, maxQuestions, seconds, NullableUUID{}) + return setupGame(c, selectedTags, maxQuestions, seconds, NullableUUID{}) } func createSharedGameData(c *fiber.Ctx, tags []string, maxQuestions int, seconds int) error { - uid, err := user.GetSession(c) - if err != nil { - return c.SendStatus(http.StatusUnauthorized) - } + uid, err := user.GetSession(c) + if err != nil { + return c.SendStatus(http.StatusUnauthorized) + } - shareKey := utils.RandString(4) - _, err = db.Queries.AppFlagsNewSharedData(context.TODO(), queries.AppFlagsNewSharedDataParams{ - Uid: uid, - ShareKey: shareKey, - Tags: tags, - Questions: int32(maxQuestions), - Seconds: int32(seconds), - GameSeed: uuid.New(), - }) - if err != nil { - return err - } + shareKey := utils.RandString(4) + _, err = db.Queries.AppFlagsNewSharedData(context.TODO(), queries.AppFlagsNewSharedDataParams{ + Uid: uid, + ShareKey: shareKey, + Tags: tags, + Questions: int32(maxQuestions), + Seconds: int32(seconds), + GameSeed: uuid.New(), + }) + if err != nil { + return err + } - data := *web.Common(c) - data["Title"] = "tmp" - data["ShareKey"] = shareKey - return c.Render("apps/flags/shared", data, "layouts/base") + data := *web.Common(c) + data["Title"] = "tmp" + data["ShareKey"] = shareKey + return c.Render("apps/flags/shared", data, "layouts/base") } func setupGame(c *fiber.Ctx, tags []string, maxQuestions int, seconds int, gameSeed NullableUUID) error { - var Quid = sql.NullString{} - uid, err := user.GetSession(c) - if err == nil { - Quid.Valid = true - Quid.String = uid - } + var Quid = sql.NullString{} + uid, err := user.GetSession(c) + if err == nil { + Quid.Valid = true + Quid.String = uid + } - createGameParams := queries.AppFlagsCreateGameWithSeedParams{ - Uid: Quid, - Tags: tags, - QuestionAmount: int32(maxQuestions), - Seconds: int32(seconds), - GameSeed: uuid.New(), - } + createGameParams := queries.AppFlagsCreateGameWithSeedParams{ + Uid: Quid, + Tags: tags, + QuestionAmount: int32(maxQuestions), + Seconds: int32(seconds), + GameSeed: uuid.New(), + } - if gameSeed.valid { - createGameParams.GameSeed = gameSeed.UUID - } + if gameSeed.valid { + createGameParams.GameSeed = gameSeed.UUID + } - gameID, err := db.Queries.AppFlagsCreateGameWithSeed(context.TODO(), createGameParams) - if err != nil { - return err - } + gameID, err := db.Queries.AppFlagsCreateGameWithSeed(context.TODO(), createGameParams) + if err != nil { + return err + } - c.Cookie(&fiber.Cookie{ - Name: flagSessionCookie, - Value: gameID.String(), - //Secure: true, - }) + c.Cookie(&fiber.Cookie{ + Name: flagSessionCookie, + Value: gameID.String(), + //Secure: true, + }) - return questionHandler(c, NullableUUID{valid: true, UUID: gameID}, NullableString{}) + return questionHandler(c, NullableUUID{valid: true, UUID: gameID}, NullableString{}) } func gameEndHandler(c *fiber.Ctx) error { - gameId, err := uuid.Parse(c.Cookies(flagSessionCookie)) - if err != nil { - return err - } - gameSession, err := db.Queries.AppFlagsGetGame(context.TODO(), gameId) - if err != nil { - return err - } - data := *web.Common(c) - data["Title"] = "tmp" - data["Errors"] = gameSession.QuestionsErrors - return c.Render("apps/flags/end", data, "layouts/base") + gameId, err := uuid.Parse(c.Cookies(flagSessionCookie)) + if err != nil { + return err + } + gameSession, err := db.Queries.AppFlagsGetGame(context.TODO(), gameId) + if err != nil { + return err + } + data := *web.Common(c) + data["Title"] = "tmp" + data["Errors"] = gameSession.QuestionsErrors + return c.Render("apps/flags/end", data, "layouts/base") } func stopGameHandler(c *fiber.Ctx) error { // exit game - utils.ClearCookie(c, flagSessionCookie) - return gameStartHandler(c) + utils.ClearCookie(c, flagSessionCookie) + return gameStartHandler(c) } func gameStartHandler(c *fiber.Ctx) error { - - - - data := *web.Common(c) - data["Title"] = "tmp" - data["SupportedTags"] = supportedTags - return c.Render("apps/flags/start", data, "layouts/base") + data := *web.Common(c) + data["Title"] = "Flags Game | tijl.dev" + data["SupportedTags"] = supportedTags + return c.Render("apps/flags/start", data, "layouts/base") } diff --git a/internal/apps/flags/locales/en.json b/internal/apps/flags/locales/en.json index fd320d6..0478ece 100644 --- a/internal/apps/flags/locales/en.json +++ b/internal/apps/flags/locales/en.json @@ -1,5 +1,10 @@ { + "flags": "Flags", "select_more_countries": "Too few countries", + "play": "Play", + "max_questions": "Max Questions", + "time_limit": "Time limit (seconds)", + "share_game": "Save", "Asia": "Asia", "MiddleEast": "Middle East", "SoutheastAsia": "Southeast Asia", diff --git a/internal/apps/flags/locales/nl.json b/internal/apps/flags/locales/nl.json index 29a302f..468ffc0 100644 --- a/internal/apps/flags/locales/nl.json +++ b/internal/apps/flags/locales/nl.json @@ -1,5 +1,10 @@ { + "flags": "Vlaggen", "select_more_countries": "Te weinig landen", + "play": "Play", + "time_limit": "Tijdlimit (seconden)", + "max_questions": "Maximaal aantal vragen", + "share_game": "Opslaan", "Asia": "Aziƫ", "MiddleEast": "Midden-Oosten", "SoutheastAsia": "Zuidoost-Aziƫ", diff --git a/internal/apps/flags/util.go b/internal/apps/flags/util.go index 04be727..9d59475 100644 --- a/internal/apps/flags/util.go +++ b/internal/apps/flags/util.go @@ -68,13 +68,13 @@ func filterCountriesByTags(tags []string) (error, []string) { } func filterSlice(slice []string, value string) []string { - var result []string - for _, v := range slice { - if v != value { - result = append(result, v) - } - } - return result + var result []string + for _, v := range slice { + if v != value { + result = append(result, v) + } + } + return result } func hasCommonTag(tags1, tags2 []string) bool { diff --git a/internal/handlers/routes.go b/internal/handlers/routes.go index 49d6c61..e1d4cca 100644 --- a/internal/handlers/routes.go +++ b/internal/handlers/routes.go @@ -58,6 +58,13 @@ func routes(app *fiber.App) { app.Use("/static/", filesystem.New(filesystem.Config{ Root: http.FS(static), })) + + /* + Robots + */ + app.Get("/robots.txt", func(c *fiber.Ctx) error { + return c.SendString(`User-agent: *`) + }) } // last function with low priority for 404 handler diff --git a/internal/service/main.go b/internal/service/main.go index 802db46..523738c 100644 --- a/internal/service/main.go +++ b/internal/service/main.go @@ -22,6 +22,8 @@ import ( webf "git.tijl.dev/tijl/tijl.dev-core/web" "github.com/gofiber/contrib/fiberzerolog" "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/middleware/compress" + "github.com/gofiber/fiber/v2/middleware/helmet" "github.com/gofiber/template/html/v2" ) @@ -72,6 +74,10 @@ func Listen() { app.Use(fiberzerolog.New(fiberzerolog.Config{ Logger: &log.Logger, })) + app.Use(compress.New(compress.Config{ + Level: compress.LevelBestSpeed, + })) + app.Use(helmet.New(helmet.Config{})) // Setup routes web.Setup(app) diff --git a/web/views/apps/flags/start.html b/web/views/apps/flags/start.html index 86cf705..67f5a30 100644 --- a/web/views/apps/flags/start.html +++ b/web/views/apps/flags/start.html @@ -1,40 +1,116 @@ -
-
+
+ +
+ + -
{{range .SupportedTags}} {{end}} +
+
+ + +
+ +
+ {{range .SupportedTags}} + + {{end}} +
{{if .SignedIn}} -