Skip to content

Commit

Permalink
[Backend] No redis to check bad words
Browse files Browse the repository at this point in the history
  • Loading branch information
Alfex4936 committed Mar 13, 2024
1 parent dd89202 commit 5165dd7
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 143 deletions.
14 changes: 9 additions & 5 deletions backend/dto/marker_dto.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package dto

import "chulbong-kr/models"
import (
"chulbong-kr/models"
"time"
)

type MarkerRequest struct {
MarkerID int `json:"markerId,omitempty"`
Expand Down Expand Up @@ -47,8 +50,9 @@ type MarkerSimple struct {
}

type MarkerSimpleWithDescrption struct {
MarkerID int `json:"markerId" db:"MarkerID"`
Latitude float64 `json:"latitude" db:"Latitude"`
Longitude float64 `json:"longitude" db:"Longitude"`
Description string `json:"description" db:"Description"`
MarkerID int `json:"markerId" db:"MarkerID"`
Latitude float64 `json:"latitude" db:"Latitude"`
Longitude float64 `json:"longitude" db:"Longitude"`
Description string `json:"description" db:"Description"`
CreatedAt time.Time `json:"-" db:"CreatedAt"`
}
3 changes: 2 additions & 1 deletion backend/handlers/comment_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package handlers
import (
"chulbong-kr/dto"
"chulbong-kr/services"
"chulbong-kr/utils"
"strconv"

"github.com/gofiber/fiber/v2"
Expand All @@ -16,7 +17,7 @@ func PostCommentHandler(c *fiber.Ctx) error {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid request body"})
}

containsBadWord, _ := services.CheckForBadWords(req.CommentText)
containsBadWord, _ := utils.CheckForBadWords(req.CommentText)
if containsBadWord {
return c.Status(fiber.StatusBadRequest).SendString("Comment contains inappropriate content.")
}
Expand Down
28 changes: 20 additions & 8 deletions backend/handlers/marker_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func CreateMarkerWithPhotosHandler(c *fiber.Ctx) error {
description = descValues[0]
}

containsBadWord, _ := services.CheckForBadWords(description)
containsBadWord, _ := utils.CheckForBadWords(description)
if containsBadWord {
return c.Status(fiber.StatusBadRequest).SendString("Comment contains inappropriate content.")
}
Expand Down Expand Up @@ -163,18 +163,30 @@ func DeleteMarkerHandler(c *fiber.Ctx) error {

// UploadMarkerPhotoToS3Handler to upload a file to S3
func UploadMarkerPhotoToS3Handler(c *fiber.Ctx) error {
file, err := c.FormFile("file")
// Parse the multipart form
form, err := c.MultipartForm()
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Could not get uploaded file"})
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Failed to parse form"})
}

fileURL, err := services.UploadFileToS3(file)
markerIDstr, markerIDExists := form.Value["markerId"]
if !markerIDExists {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Failed to parse form"})
}

markerID, err := strconv.Atoi(markerIDstr[0])
if err != nil {
// Interpret the error message to set the appropriate HTTP status code
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Failed to parse form"})
}

files := form.File["photos"]

urls, err := services.UploadMarkerPhotoToS3(markerID, files)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to upload photos"})
}

return c.JSON(fiber.Map{"url": fileURL})
return c.JSON(fiber.Map{"urls": urls})
}

// DeleteObjectFromS3Handler handles requests to delete objects from S3.
Expand Down Expand Up @@ -261,7 +273,7 @@ func GetUserMarkersHandler(c *fiber.Ctx) error {

markersWithPhotos, total, err := services.GetAllMarkersByUserWithPagination(userID, page, pageSize)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "check if you have added markers"})
}

totalPages := int(math.Ceil(float64(total) / float64(pageSize)))
Expand Down
56 changes: 8 additions & 48 deletions backend/main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

import (
"bufio"
"chulbong-kr/database"
"chulbong-kr/handlers"
"chulbong-kr/middlewares"
Expand Down Expand Up @@ -66,8 +65,9 @@ func main() {
})
services.RedisStore = store

services.ResetCache("badwords")
loadBadWordsIntoRedis("badwords.txt")
if err := utils.LoadBadWords("badwords.txt"); err != nil {
log.Fatalf("Failed to load bad words: %v", err)
}

// Initialize global variables
setTokenExpirationTime()
Expand Down Expand Up @@ -142,10 +142,10 @@ func main() {

// Enable CORS for all routes
app.Use(cors.New(cors.Config{
AllowOrigins: "http://localhost:5173,https://chulbong-kr.vercel.app", // List allowed origins
AllowMethods: "GET,POST,PUT,DELETE,OPTIONS", // Explicitly list allowed methods
AllowHeaders: "*", // TODO: Allow specific headers
ExposeHeaders: "Accept, Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Accept-Encoding",
AllowOrigins: "http://localhost:5173,https://chulbong-kr.vercel.app", // List allowed origins
AllowMethods: "GET,POST,PUT,DELETE,OPTIONS", // Explicitly list allowed methods
AllowHeaders: "*", // TODO: Allow specific headers
// ExposeHeaders: "Accept",
AllowCredentials: true,
}))

Expand Down Expand Up @@ -193,6 +193,7 @@ func main() {
}), handlers.GetAllMarkersHandler)
api.Get("/markers/:markerId/details", middlewares.AuthSoftMiddleware, handlers.GetMarker)
api.Get("/markers/close", handlers.FindCloseMarkersHandler)
api.Post("/markers/upload", middlewares.AdminOnly, handlers.UploadMarkerPhotoToS3Handler)

markerGroup := api.Group("/markers")
{
Expand All @@ -203,7 +204,6 @@ func main() {
// markerGroup.Get("/:markerId", handlers.GetMarker)

markerGroup.Post("/new", handlers.CreateMarkerWithPhotosHandler)
markerGroup.Post("/upload", handlers.UploadMarkerPhotoToS3Handler)
markerGroup.Post("/:markerID/dislike", handlers.LeaveDislikeHandler)
markerGroup.Post("/:markerID/favorites", handlers.AddFavoriteHandler)

Expand Down Expand Up @@ -259,43 +259,3 @@ func setTokenExpirationTime() {
// Assign the converted duration to the global variable
services.TOKEN_DURATION = time.Duration(durationInt) * time.Hour
}

func loadBadWordsIntoRedis(filePath string) {
const batchSize = 500

file, err := os.Open(filePath)
if err != nil {
panic(err)
}
defer file.Close()

scanner := bufio.NewScanner(file)
batch := make([]string, 0, batchSize)

for scanner.Scan() {
word := scanner.Text()
batch = append(batch, word)

// Once we've collected enough words, insert them in a batch.
if len(batch) >= batchSize {
err := services.AddBadWords(batch)
if err != nil {
fmt.Printf("Failed to insert batch: %v\n", err)
}
// Reset the batch slice for the next group of words
batch = batch[:0]
}
}

// Don't forget to insert any words left in the batch after finishing the loop
if len(batch) > 0 {
err := services.AddBadWords(batch)
if err != nil {
fmt.Printf("Failed to insert final batch: %v\n", err)
}
}

if err := scanner.Err(); err != nil {
panic(err)
}
}
99 changes: 44 additions & 55 deletions backend/services/marker_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"chulbong-kr/database"
"chulbong-kr/dto"
"chulbong-kr/models"

"github.com/jmoiron/sqlx"
)

func CreateMarkerWithPhotos(markerDto *dto.MarkerRequest, userID int, form *multipart.Form) (*dto.MarkerResponse, error) {
Expand Down Expand Up @@ -89,77 +87,32 @@ func GetAllMarkers() ([]dto.MarkerSimple, error) {
return markers, nil
}

func GetAllMarkersByUserWithPagination(userID, page, pageSize int) ([]models.MarkerWithPhotos, int, error) {
func GetAllMarkersByUserWithPagination(userID, page, pageSize int) ([]dto.MarkerSimpleWithDescrption, int, error) {
offset := (page - 1) * pageSize

// Query to select markers created by a specific user with LIMIT and OFFSET for pagination
markerQuery := `
SELECT
M.MarkerID,
M.UserID,
M.MarkerID,
ST_X(M.Location) AS Latitude,
ST_Y(M.Location) AS Longitude,
M.Description,
U.Username,
M.CreatedAt,
M.UpdatedAt,
IFNULL(D.DislikeCount, 0) AS DislikeCount
M.Description,
M.CreatedAt
FROM
Markers M
INNER JOIN
Users U ON M.UserID = U.UserID
LEFT JOIN
(
SELECT
MarkerID,
COUNT(DislikeID) AS DislikeCount
FROM
MarkerDislikes
GROUP BY
MarkerID
) D ON M.MarkerID = D.MarkerID
WHERE
M.UserID = ?
ORDER BY
M.CreatedAt DESC
LIMIT ? OFFSET ?
`

var markersWithUsernames []dto.MarkerWithDislike
err := database.DB.Select(&markersWithUsernames, markerQuery, userID, pageSize, offset)
markersWithDescription := make([]dto.MarkerSimpleWithDescrption, 0)
err := database.DB.Select(&markersWithDescription, markerQuery, userID, pageSize, offset)
if err != nil {
return nil, 0, err
}

// Fetch all photos at once
photoQuery := `SELECT * FROM Photos WHERE MarkerID IN (?)`
query, args, err := sqlx.In(photoQuery, getMarkerIDs(markersWithUsernames))
if err != nil {
return nil, 0, err
}
var allPhotos []models.Photo
err = database.DB.Select(&allPhotos, database.DB.Rebind(query), args...)
if err != nil {
return nil, 0, err
}

// Map photos to their markers
photoMap := make(map[int][]models.Photo) // markerID to photos
for _, photo := range allPhotos {
photoMap[photo.MarkerID] = append(photoMap[photo.MarkerID], photo)
}

// Assemble the final structure
markersWithPhotos := make([]models.MarkerWithPhotos, 0)
for _, marker := range markersWithUsernames {
markersWithPhotos = append(markersWithPhotos, models.MarkerWithPhotos{
Marker: marker.Marker,
Photos: photoMap[marker.MarkerID],
Username: marker.Username,
DislikeCount: marker.DislikeCount,
})
}

// Query to get the total count of markers for the user
countQuery := `SELECT COUNT(DISTINCT Markers.MarkerID) FROM Markers WHERE Markers.UserID = ?`
var total int
Expand All @@ -168,7 +121,7 @@ LIMIT ? OFFSET ?
return nil, 0, err
}

return markersWithPhotos, total, nil
return markersWithDescription, total, nil
}

// GetMarker retrieves a single marker and its associated photo by the marker's ID
Expand Down Expand Up @@ -227,7 +180,7 @@ WHERE M.MarkerID = ?`
DislikeCount: markersWithUsernames.DislikeCount,
}

PublishMarkerUpdate(fmt.Sprintf("user: %s", markersWithPhotos.Username))
// PublishMarkerUpdate(fmt.Sprintf("user: %s", markersWithPhotos.Username))

return &markersWithPhotos, nil
}
Expand Down Expand Up @@ -455,6 +408,42 @@ func RemoveFavorite(userID, markerID int) error {
return nil
}

func UploadMarkerPhotoToS3(markerID int, files []*multipart.FileHeader) ([]string, error) {
// Begin a transaction for database operations
tx, err := database.DB.Beginx()
if err != nil {
return nil, err
}

defer tx.Rollback()

picUrls := make([]string, 0)
// Process file uploads from the multipart form
for _, file := range files {
fileURL, err := UploadFileToS3(file)
if err != nil {
fmt.Printf("Failed to upload file to S3: %v\n", err)
continue // Skip this file and continue with the next
}
picUrls = append(picUrls, fileURL)
// Associate each photo with the marker in the database
if _, err := tx.Exec("INSERT INTO Photos (MarkerID, PhotoURL, UploadedAt) VALUES (?, ?, NOW())", markerID, fileURL); err != nil {
// Attempt to delete the uploaded file from S3
if delErr := DeleteDataFromS3(fileURL); delErr != nil {
fmt.Printf("Also failed to delete the file from S3: %v\n", delErr)
}
return nil, err
}
}

// If no errors, commit the transaction
if err := tx.Commit(); err != nil {
return nil, err
}

return picUrls, nil
}

// Helper function to extract marker IDs
func getMarkerIDs(markers []dto.MarkerWithDislike) []interface{} {
ids := make([]interface{}, len(markers))
Expand Down
Loading

0 comments on commit 5165dd7

Please sign in to comment.