Skip to content

Commit

Permalink
feat: adding outline for games (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipebrsk authored Oct 9, 2024
1 parent 25a555f commit 0c0b692
Show file tree
Hide file tree
Showing 133 changed files with 13,878 additions and 5 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Upload results to Codecov
if: github.event.pull_request.draft == false
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
Expand Down
31 changes: 31 additions & 0 deletions DONE.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,36 @@
- [x] Create tags table
- [x] Create genres table
- [x] Create platforms table
- [x] Create languages table
- [x] Adding outline for games
- [x] Associating games with platforms
- [x] Associating games with categories
- [x] Associating games with tags
- [x] Associating games with genres
- [x] Associating games with languages
- [x] Create association for games or DLCs
- [x] Create torrent websites (such as firgitl, skidrow etc)
- [x] Create the kind of protections (such as Denuvo, Steam, GOG etc)
- [x] Create game developers (such as Game Science)
- [x] Create game publishers (such as Game Science)
- [x] Create requirement types
- [x] A requirement type should have a potential column, that should be enum, with minimum, maximum or recommended
- [x] A requirement type should have a type column, that should be enum, with windows, mac or linux
- [x] Create requirements and associate with requirement types
- [x] Create game outline system
- [x] Add game DLCs
- [x] Add game critics
- [x] Add game torrents
- [x] Add game crack
- [x] Add game reviews
- [x] Add game galleries
- [x] Add game publishers
- [x] Add game developers
- [x] Add game requirements
- [x] Add game comments (for torrents section)
- [x] Add game support
- [x] Add game hearts
- [x] Add game views
- [x] Add game stores

### Post MVP
9 changes: 9 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
- [ ] Review the action keys for missions and titles
- [ ] Planning all missions and titles type
- [ ] Planning all daily/weekly/monthly missions
- [x] Create viewable structure
- [x] Add game views count
- [ ] Add post views count
- [ ] Create heartable structure
- [x] Add game hearts count
- [ ] Add post hearts count
- [x] Add comment hearts count

### Post-MVP

Expand Down Expand Up @@ -72,13 +79,15 @@
- [ ] AWS
- [ ] SNS
- [ ] Lambda
- [ ] Make user friend requests
- [ ] Create a chat between users
- [ ] User can be able to chat another users
- [ ] User can be able to create a group and chat them
- [ ] User can be able to change the group name and avatar
- [ ] User can be able to add and remove members (creator or admin)
- [ ] User can be able to add admins on groups (owner only)
- [ ] Chat should use realtime
- [ ] User can chat only friends - check if possibility will be only to that ones that accepts the friend request
- [ ] Create quizz that could reward with some coins and experience, maybe titles
- [ ] Award with coins and experience on comment, heart a game, or something else
- [ ] Heart a game;
Expand Down
2 changes: 2 additions & 0 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func main() {
transactionService,
notificationService,
missionService,
gameService,
db := di.InitDependencies()

// Setup routes with dependency injection
Expand All @@ -39,6 +40,7 @@ func main() {
transactionService,
notificationService,
missionService,
gameService,
)

c := cron.New()
Expand Down
6 changes: 5 additions & 1 deletion cmd/server/routes/init_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func InitHandlers(
transactionService *usecases.TransactionService,
notificationService *usecases.NotificationService,
missionService *usecases.MissionService,
gameService *usecases.GameService,
) (
authHandler *api.AuthHandler,
passwordResetHandler *api.PasswordResetHandler,
Expand All @@ -27,6 +28,7 @@ func InitHandlers(
transactionHandler *api.TransactionHandler,
notificationHandler *api.NotificationHandler,
missionHandler *api.MissionHandler,
gameHandler *api.GameHandler,
) {
userHandler = api.NewUserHandler(userService)
authHandler = api.NewAuthHandler(authService, userService)
Expand All @@ -37,6 +39,7 @@ func InitHandlers(
transactionHandler = api.NewTransactionHandler(transactionService, userService)
notificationHandler = api.NewNotificationHandler(notificationService, userService)
missionHandler = api.NewMissionHandler(missionService, userService)
gameHandler = api.NewGameHandler(gameService, userService)

return authHandler,
passwordResetHandler,
Expand All @@ -46,5 +49,6 @@ func InitHandlers(
titleHandler,
transactionHandler,
notificationHandler,
missionHandler
missionHandler,
gameHandler
}
7 changes: 6 additions & 1 deletion cmd/server/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ func SetupRouter(
transactionService *usecases.TransactionService,
notificationService *usecases.NotificationService,
missionService *usecases.MissionService,
gameService *usecases.GameService,
) *gin.Engine {
r := gin.Default()
env := config.LoadConfig()
Expand Down Expand Up @@ -51,7 +52,8 @@ func SetupRouter(
titleHandler,
transactionHandler,
notificationHandler,
missionHandler := InitHandlers(
missionHandler,
gameHandler := InitHandlers(
authService,
userService,
passwordResetService,
Expand All @@ -63,6 +65,7 @@ func SetupRouter(
transactionService,
notificationService,
missionService,
gameService,
)

// Define the middlewares
Expand Down Expand Up @@ -108,6 +111,8 @@ func SetupRouter(

protected.GET("/missions", missionHandler.GetAllForUser)
protected.POST("/missions/:id/complete", missionHandler.CompleteMission)

protected.GET("/games/:slug", gameHandler.FindBySlug)
}

// Common routes
Expand Down
5 changes: 4 additions & 1 deletion di/di.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func InitDependencies() (
*usecases.TransactionService,
*usecases.NotificationService,
*usecases.MissionService,
*usecases.GameService,
*gorm.DB,
) {
cfg := config.LoadConfig()
Expand All @@ -50,7 +51,8 @@ func InitDependencies() (
walletService,
transactionService,
notificationService,
missionService := Setup(dbConn)
missionService,
gameService := Setup(dbConn)

// Setup clients for non-test environment
if cfg.ENV != "testing" {
Expand Down Expand Up @@ -84,5 +86,6 @@ func InitDependencies() (
transactionService,
notificationService,
missionService,
gameService,
dbConn
}
32 changes: 31 additions & 1 deletion di/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

func MigrateModels(dbConn *gorm.DB) {
models := []interface{}{
models := []any{
&domain.Reward{},
&domain.Level{},
&domain.Wallet{},
Expand All @@ -31,6 +31,36 @@ func MigrateModels(dbConn *gorm.DB) {
&domain.Tag{},
&domain.Platform{},
&domain.Category{},
&domain.Categoriable{},
&domain.Genreable{},
&domain.Taggable{},
&domain.Platformable{},
&domain.Language{},
&domain.GameLanguage{},
&domain.RequirementType{},
&domain.Requirement{},
&domain.Protection{},
&domain.Cracker{},
&domain.Crack{},
&domain.TorrentProvider{},
&domain.Torrent{},
&domain.Publisher{},
&domain.GamePublisher{},
&domain.Developer{},
&domain.GameDeveloper{},
&domain.GameSupport{},
&domain.Reviewable{},
&domain.Viewable{},
&domain.Heartable{},
&domain.Critic{},
&domain.Criticable{},
&domain.Store{},
&domain.GameStore{},
&domain.Commentable{},
&domain.Galleriable{},
&domain.DLC{},
&domain.DLCStore{},
&domain.Game{},
}

for _, model := range models {
Expand Down
6 changes: 5 additions & 1 deletion di/setup_dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func Setup(dbConn *gorm.DB) (
*usecases.TransactionService,
*usecases.NotificationService,
*usecases.MissionService,
*usecases.GameService,
) {
// Create repository instances
userRepo := db.NewUserRepositoryMySQL(dbConn)
Expand All @@ -31,6 +32,7 @@ func Setup(dbConn *gorm.DB) (
transactionRepo := db.NewTransactionRepositoryMySQL(dbConn)
notificationRepo := db.NewNotificationRepositoryMySQL(dbConn)
missionRepo := db.NewMissionRepositoryMySQL(dbConn)
gameRepo := db.NewGameRepositoryMySQL(dbConn)

// Create service instances
userService := usecases.NewUserService(userRepo)
Expand All @@ -44,6 +46,7 @@ func Setup(dbConn *gorm.DB) (
transactionService := usecases.NewTransactionService(transactionRepo)
notificationService := usecases.NewNotificationService(notificationRepo)
missionService := usecases.NewMissionService(missionRepo)
gameService := usecases.NewGameService(gameRepo)

return userService,
authService,
Expand All @@ -55,5 +58,6 @@ func Setup(dbConn *gorm.DB) (
walletService,
transactionService,
notificationService,
missionService
missionService,
gameService
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ require (

require github.com/aws/aws-sdk-go-v2/service/sqs v1.35.3

require github.com/shopspring/decimal v1.4.0 // direct

require (
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.5 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.35 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
Expand Down
49 changes: 49 additions & 0 deletions internal/adapters/api/game_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package api

import (
"gcstatus/internal/resources"
"gcstatus/internal/usecases"
"gcstatus/pkg/s3"
"gcstatus/pkg/utils"
"net/http"

"github.com/gin-gonic/gin"
)

type GameHandler struct {
gameService *usecases.GameService
userService *usecases.UserService
}

func NewGameHandler(
gameService *usecases.GameService,
userService *usecases.UserService,
) *GameHandler {
return &GameHandler{
gameService: gameService,
userService: userService,
}
}

func (h *GameHandler) FindBySlug(c *gin.Context) {
slug := c.Param("slug")
user, err := utils.Auth(c, h.userService.GetUserByID)
if err != nil {
RespondWithError(c, http.StatusUnauthorized, "Unauthorized: "+err.Error())
return
}

game, err := h.gameService.FindBySlug(slug, user.ID)
if err != nil {
RespondWithError(c, http.StatusInternalServerError, "Failed to fetch game: "+err.Error())
return
}

transformedGame := resources.TransformGame(game, s3.GlobalS3Client)

response := resources.Response{
Data: transformedGame,
}

c.JSON(http.StatusOK, response)
}
69 changes: 69 additions & 0 deletions internal/adapters/db/game_repository_mysql.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package db

import (
"errors"
"gcstatus/internal/domain"
"gcstatus/internal/ports"

"gorm.io/gorm"
)

type GameRepositoryMySQL struct {
db *gorm.DB
}

func NewGameRepositoryMySQL(db *gorm.DB) ports.GameRepository {
return &GameRepositoryMySQL{db: db}
}

func (h *GameRepositoryMySQL) FindBySlug(slug string, userID uint) (domain.Game, error) {
var game domain.Game
if err := h.db.Preload("Categories.Category").
Preload("Genres.Genre").
Preload("Tags.Tag").
Preload("Platforms.Platform").
Preload("Languages.Language").
Preload("Requirements.RequirementType").
Preload("Crack.Cracker").
Preload("Crack.Protection").
Preload("Torrents.TorrentProvider").
Preload("Publishers.Publisher").
Preload("Developers.Developer").
Preload("Reviews.User.Profile").
Preload("Critics.Critic").
Preload("Stores.Store").
Preload("Galleries").
Preload("DLCs.Galleries").
Preload("DLCs.Platforms.Platform").
Preload("DLCs.Stores.Store").
Preload("Comments", "parent_id IS NULL").
Preload("Comments.Hearts").
Preload("Comments.User").
Preload("Comments.Replies.User").
Preload("Support").
Preload("Views").
Preload("Hearts").
Where("slug = ?", slug).
First(&game).
Error; err != nil {
return game, err
}

var view domain.Viewable
if err := h.db.Where("viewable_id = ? AND viewable_type = ? AND user_id = ?", game.ID, "games", userID).First(&view).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
view = domain.Viewable{
ViewableID: game.ID,
ViewableType: "games",
UserID: userID,
}
if err := h.db.Create(&view).Error; err != nil {
return game, err
}
} else {
return game, err
}
}

return game, nil
}
Loading

0 comments on commit 0c0b692

Please sign in to comment.