From 774383ec3f48717ad31d921da809aeb5a01021c8 Mon Sep 17 00:00:00 2001 From: TheSilentSage Date: Tue, 11 Jun 2024 19:26:21 +0530 Subject: [PATCH 1/4] fix: merged slot for lab while fetching timetable --- .../internal/models/timetable.go | 63 ++++++++++++------- .../internal/utils/timetableDetection.go | 6 -- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/vitty-backend-api/internal/models/timetable.go b/vitty-backend-api/internal/models/timetable.go index 62d04f1..deeb9a9 100644 --- a/vitty-backend-api/internal/models/timetable.go +++ b/vitty-backend-api/internal/models/timetable.go @@ -29,10 +29,12 @@ func (t Timetable) GetDaySlots(day time.Weekday) map[string][]Slot { resp := make(map[string][]Slot) var data []Slot daySlots := DailySlots[day.String()] + labSlot := "" var err error // Theory slots for _, slot := range t.Slots { + if slot.Type == "Theory" && slices.Contains(daySlots["Theory"], slot.Slot) { index := slices.Index(daySlots["Theory"], slot.Slot) slot.StartTime, err = time.ParseInLocation(STD_REF_TIME, TheoryTimings[index].StartTime, time.Local) @@ -51,19 +53,27 @@ func (t Timetable) GetDaySlots(day time.Weekday) map[string][]Slot { data = append(data, slot) } else if slot.Type == "Lab" && slices.Contains(daySlots["Lab"], slot.Slot) { index := slices.Index(daySlots["Lab"], slot.Slot) - slot.StartTime, err = time.ParseInLocation(STD_REF_TIME, LabTimings[index].StartTime, time.Local) - if err != nil { - log.Println("Error parsing time: ", err) - return nil - } - slot.EndTime, err = time.ParseInLocation(STD_REF_TIME, LabTimings[index].EndTime, time.Local) + if labSlot == "" { + labSlot += slot.Slot + "+" + continue + } else { + slot.StartTime, err = time.ParseInLocation(STD_REF_TIME, LabTimings[index-1].StartTime, time.Local) + if err != nil { + log.Println("Error parsing time: ", err) + return nil + } - if err != nil { - log.Println("Error parsing time: ", err) - return nil + slot.EndTime, err = time.ParseInLocation(STD_REF_TIME, LabTimings[index].EndTime, time.Local) + if err != nil { + log.Println("Error parsing time: ", err) + return nil + } + slot.Slot = labSlot + slot.Slot + labSlot = "" + data = append(data, slot) } - data = append(data, slot) + } } resp[day.String()] = data @@ -72,9 +82,11 @@ func (t Timetable) GetDaySlots(day time.Weekday) map[string][]Slot { func (t Timetable) GetDaywiseTimetable() map[string][]Slot { resp := make(map[string][]Slot) + labSlot := "" for _, slot := range t.Slots { for day, value := range DailySlots { + if slices.Contains(value["Theory"], slot.Slot) { index := slices.Index(value["Theory"], slot.Slot) var err error @@ -91,18 +103,27 @@ func (t Timetable) GetDaywiseTimetable() map[string][]Slot { resp[day] = append(resp[day], slot) } else if slices.Contains(value["Lab"], slot.Slot) { index := slices.Index(value["Lab"], slot.Slot) - var err error - slot.StartTime, err = time.ParseInLocation(STD_REF_TIME, LabTimings[index].StartTime, time.Local) - if err != nil { - log.Println("Error parsing time: ", err) - return nil - } - slot.EndTime, err = time.ParseInLocation(STD_REF_TIME, LabTimings[index].EndTime, time.Local) - if err != nil { - log.Println("Error parsing time: ", err) - return nil + + if labSlot == "" { + labSlot += slot.Slot + "+" + continue + } else { + var err error + slot.StartTime, err = time.ParseInLocation(STD_REF_TIME, LabTimings[index-1].StartTime, time.Local) + if err != nil { + log.Println("Error parsing time: ", err) + return nil + } + slot.EndTime, err = time.ParseInLocation(STD_REF_TIME, LabTimings[index].EndTime, time.Local) + if err != nil { + log.Println("Error parsing time: ", err) + return nil + } + + slot.Slot = labSlot + slot.Slot + labSlot = "" + resp[day] = append(resp[day], slot) } - resp[day] = append(resp[day], slot) } } } diff --git a/vitty-backend-api/internal/utils/timetableDetection.go b/vitty-backend-api/internal/utils/timetableDetection.go index 19ad91d..17bd513 100644 --- a/vitty-backend-api/internal/utils/timetableDetection.go +++ b/vitty-backend-api/internal/utils/timetableDetection.go @@ -48,12 +48,6 @@ func DetectTimetable(text string) ([]TimetableSlotV1, error) { } if len(Slots) == 0 { - return Slots, nil - } - - var err error - - if err != nil { return Slots, errors.New("error in detecting timetable") } From a6f4c1c874ae7b84d0b553739685db8ad433843c Mon Sep 17 00:00:00 2001 From: TheSilentSage Date: Sat, 28 Dec 2024 18:30:08 +0530 Subject: [PATCH 2/4] feat: users can add reminders --- .../api/serializers/reminders.go | 18 +++ vitty-backend-api/api/v2/initialize.go | 1 + vitty-backend-api/api/v2/reminderHandler.go | 135 ++++++++++++++++++ vitty-backend-api/cmd/root.go | 7 + vitty-backend-api/example.env/example.local | 6 +- vitty-backend-api/go.mod | 5 +- vitty-backend-api/go.sum | 10 ++ vitty-backend-api/internal/jobs/jobs.go | 45 ++++++ .../internal/models/initialize.go | 1 + .../internal/models/reminders.go | 68 +++++++++ vitty-backend-api/internal/utils/users.go | 10 ++ 11 files changed, 303 insertions(+), 3 deletions(-) create mode 100644 vitty-backend-api/api/serializers/reminders.go create mode 100644 vitty-backend-api/api/v2/reminderHandler.go create mode 100644 vitty-backend-api/internal/jobs/jobs.go create mode 100644 vitty-backend-api/internal/models/reminders.go diff --git a/vitty-backend-api/api/serializers/reminders.go b/vitty-backend-api/api/serializers/reminders.go new file mode 100644 index 0000000..2d8afa4 --- /dev/null +++ b/vitty-backend-api/api/serializers/reminders.go @@ -0,0 +1,18 @@ +package serializers + +import "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/models" + +func RemindersSerializer(reminders []models.Reminders) []map[string]interface{} { + var result []map[string]interface{} + + for _, reminder := range reminders { + out := map[string]interface{}{ + "reminder_id": reminder.ReminderId, + "reminder_name": reminder.ReminderName, + "reminder_content": reminder.ReminderContent, + "reminder_time": reminder.ReminderTime, + } + result = append(result, out) + } + return result +} diff --git a/vitty-backend-api/api/v2/initialize.go b/vitty-backend-api/api/v2/initialize.go index 256c0ab..074c65a 100644 --- a/vitty-backend-api/api/v2/initialize.go +++ b/vitty-backend-api/api/v2/initialize.go @@ -10,4 +10,5 @@ func V2Handler(api fiber.Router) { userHandler(group) timetableHandler(group) friendHandler(group) + reminderHandler(group) } diff --git a/vitty-backend-api/api/v2/reminderHandler.go b/vitty-backend-api/api/v2/reminderHandler.go new file mode 100644 index 0000000..20092fd --- /dev/null +++ b/vitty-backend-api/api/v2/reminderHandler.go @@ -0,0 +1,135 @@ +package v2 + +import ( + "strings" + + "github.com/GDGVIT/vitty-backend/vitty-backend-api/api/middleware" + "github.com/GDGVIT/vitty-backend/vitty-backend-api/api/serializers" + "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/models" + "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/utils" + "github.com/gofiber/fiber/v2" + "github.com/labstack/gommon/log" +) + +func reminderHandler(api fiber.Router) { + group := api.Group("/reminders") + group.Use(middleware.JWTAuthMiddleware) + group.Get("/", getReminders) + group.Post("/", createReminder) + group.Patch("/", updateReminder) + group.Delete("/:reminderId?", deleteReminder) +} + +func getReminders(c *fiber.Ctx) error { + var reminder models.Reminders + + username := c.Locals("user").(models.User).Username + reminder.UserName = username + + err, reminders := reminder.GetReminders() + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "detail": "Reminders not fetched", + }) + } + + if len(reminders) == 0 { + return c.Status(fiber.StatusOK).JSON(fiber.Map{ + "detail": "No reminders found", + }) + } + + return c.Status(fiber.StatusOK).JSON(fiber.Map{ + "data": serializers.RemindersSerializer(reminders), + }) +} + +func createReminder(c *fiber.Ctx) error { + var reminder models.Reminders + + if err := c.BodyParser(&reminder); err != nil { + log.Error(err) + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Invalid request body ", + }) + } + + if reminder.ReminderName == nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Reminder name is required", + }) + } + + if reminder.ReminderContent == nil { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Reminder content is required", + }) + } + + if !strings.Contains(reminder.ReminderId, "rem_") || len(reminder.ReminderId) < 32 { + reminder.ReminderId = utils.UUIDWithPrefix("rem") + } + + username := c.Locals("user").(models.User).Username + reminder.UserName = username + reminder.CreateReminder() + + return c.Status(fiber.StatusOK).JSON(fiber.Map{ + "detail": "Reminder Saved Successfully", + }) +} + +func updateReminder(c *fiber.Ctx) error { + var reminder models.Reminders + + if err := c.BodyParser(&reminder); err != nil { + log.Error(err) + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "error": "Invalid request body ", + }) + } + + if reminder.ReminderId == "" { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "detail": "Reminder id is required", + }) + } + + err := reminder.UpdateReminder() + if err != nil { + log.Error(err) + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "detail": "Reminder not updated", + }) + } + + return c.Status(fiber.StatusOK).JSON(fiber.Map{ + "detail": "Reminder Saved Successfully", + }) +} + +func deleteReminder(c *fiber.Ctx) error { + var reminder models.Reminders + + reminderId := c.Params("reminderId") + + if reminderId == "" { + return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ + "detail": "Reminder id is missing", + }) + } + + reminder.ReminderId = reminderId + username := c.Locals("user").(models.User).Username + reminder.UserName = username + + err := reminder.DeleteReminder() + + if err != nil { + log.Info(err.Error()) + return c.Status(fiber.StatusBadRequest).JSON(fiber.ErrBadRequest) + } + return c.Status(fiber.StatusOK).JSON(fiber.Map{ + "detail": "Reminder deleted successfully", + }) +} diff --git a/vitty-backend-api/cmd/root.go b/vitty-backend-api/cmd/root.go index d1410b4..d9ef056 100644 --- a/vitty-backend-api/cmd/root.go +++ b/vitty-backend-api/cmd/root.go @@ -8,6 +8,7 @@ import ( vittyCli "github.com/GDGVIT/vitty-backend/vitty-backend-api/cli" "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/auth" "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/database" + "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/jobs" "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/models" "github.com/gofiber/fiber/v2" "github.com/urfave/cli/v2" @@ -37,6 +38,9 @@ type Env struct { google_client_id string google_client_secret string google_redirect_uri string + + // Job Variable + isRunJobs string } // Method to create a new VittyApp @@ -94,6 +98,9 @@ func (v *VittyApp) init() { auth.InitializeGoogleOauth(v.env.google_client_id, v.env.google_client_secret, v.env.google_redirect_uri) auth.InitializeFirebaseApp() + // Initialize jobs + jobs.InitializeJobs(v.env.isRunJobs) + // Initialize Web app v.initWebApp() diff --git a/vitty-backend-api/example.env/example.local b/vitty-backend-api/example.env/example.local index a442b56..cfedaa3 100644 --- a/vitty-backend-api/example.env/example.local +++ b/vitty-backend-api/example.env/example.local @@ -15,4 +15,8 @@ POSTGRES_PORT=5432 # Auth Variables # --------------------------------------------------------------- OAUTH_CALLBACK_URL=http://localhost:3000/auth/callback -JWT_SECRET=secret \ No newline at end of file +JWT_SECRET=secret + +# Job Variables +# --------------------------------------------------------------- +RUN_JOBS=false \ No newline at end of file diff --git a/vitty-backend-api/go.mod b/vitty-backend-api/go.mod index 0836a17..dd0e43a 100644 --- a/vitty-backend-api/go.mod +++ b/vitty-backend-api/go.mod @@ -6,13 +6,16 @@ require ( firebase.google.com/go v3.13.0+incompatible github.com/gofiber/fiber/v2 v2.46.0 github.com/golang-jwt/jwt/v4 v4.5.0 + github.com/google/uuid v1.3.0 github.com/labstack/echo/v4 v4.11.2 + github.com/labstack/gommon v0.4.0 github.com/urfave/cli/v2 v2.25.6 golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 golang.org/x/oauth2 v0.11.0 google.golang.org/api v0.138.0 gorm.io/driver/postgres v1.5.2 gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55 + gorm.io/plugin/soft_delete v1.2.1 ) require ( @@ -30,7 +33,6 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/s2a-go v0.1.5 // indirect - github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect @@ -39,7 +41,6 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/klauspost/compress v1.16.3 // indirect - github.com/labstack/gommon v0.4.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect diff --git a/vitty-backend-api/go.sum b/vitty-backend-api/go.sum index f68de46..54112a3 100644 --- a/vitty-backend-api/go.sum +++ b/vitty-backend-api/go.sum @@ -96,6 +96,8 @@ github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU= github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= 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.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 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.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= @@ -113,6 +115,8 @@ github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APP github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.3 h1:j7a/xn1U6TKA/PHHxqZuzh64CdtRc7rU9M+AvkOl5bA= +github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= @@ -301,7 +305,13 @@ 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/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0= gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8= +gorm.io/driver/sqlite v1.1.3 h1:BYfdVuZB5He/u9dt4qDpZqiqDJ6KhPqs5QUqsr/Eeuc= +gorm.io/driver/sqlite v1.1.3/go.mod h1:AKDgRWk8lcSQSw+9kxCJnX/yySj8G3rdwYlU57cB45c= +gorm.io/gorm v1.20.1/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= +gorm.io/gorm v1.23.0/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55 h1:sC1Xj4TYrLqg1n3AN10w871An7wJM0gzgcm8jkIkECQ= gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/plugin/soft_delete v1.2.1 h1:qx9D/c4Xu6w5KT8LviX8DgLcB9hkKl6JC9f44Tj7cGU= +gorm.io/plugin/soft_delete v1.2.1/go.mod h1:Zv7vQctOJTGOsJ/bWgrN1n3od0GBAZgnLjEx+cApLGk= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/vitty-backend-api/internal/jobs/jobs.go b/vitty-backend-api/internal/jobs/jobs.go new file mode 100644 index 0000000..b6b53e7 --- /dev/null +++ b/vitty-backend-api/internal/jobs/jobs.go @@ -0,0 +1,45 @@ +package jobs + +import ( + "log" + "time" + + "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/models" +) + +func InitializeJobs(isRunJobs string) { + if isRunJobs == "true" { + startDailyJob() + startWeeklyJob() + log.Println("Jobs are running") + } else { + log.Println("Jobs disabled") + } + +} + +var reminder models.Reminders + +func startDailyJob() { + ticker := time.NewTicker(24 * time.Hour) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + reminder.SoftDeleteExpiredReminders() + } + } +} + +func startWeeklyJob() { + ticker := time.NewTicker(7 * 24 * time.Hour) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + reminder.CleanupOldReminders() + } + } +} diff --git a/vitty-backend-api/internal/models/initialize.go b/vitty-backend-api/internal/models/initialize.go index 4181fd3..d840102 100644 --- a/vitty-backend-api/internal/models/initialize.go +++ b/vitty-backend-api/internal/models/initialize.go @@ -11,6 +11,7 @@ func InitializeModels() { "User": &User{}, "Timetable": &Timetable{}, "Friend Requests": &FriendRequest{}, + "Reminders": &Reminders{}, } for name, model := range MODELS { diff --git a/vitty-backend-api/internal/models/reminders.go b/vitty-backend-api/internal/models/reminders.go new file mode 100644 index 0000000..e5b8158 --- /dev/null +++ b/vitty-backend-api/internal/models/reminders.go @@ -0,0 +1,68 @@ +package models + +import ( + "time" + + "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/database" + "gorm.io/gorm" + "gorm.io/plugin/soft_delete" +) + +type Reminders struct { + ReminderId string `json:"reminder_id,omitempty" gorm:"unique"` + ReminderName *string `json:"reminder_name" gorm:"primaryKey"` + UserName string `json:"user_name" gorm:"primaryKey;foreignKey:Username;constraint:OnDelete:CASCADE"` + ReminderContent *string `json:"reminder_content"` + ReminderTime *time.Time `json:"reminder_time,omitempty"` + User User `gorm:"foreignKey:UserName;references:Username;constraint:OnDelete:CASCADE"` + DeletedAt soft_delete.DeletedAt `json:"-,omitempty" gorm:"index"` +} + +func (r *Reminders) CreateReminder() error { + err := database.DB.Create(&r).Error + return err +} + +func (r *Reminders) GetReminders() (error, []Reminders) { + var reminders []Reminders + err := database.DB.Where(&r).Find(&reminders).Error + return err, reminders +} + +func (r *Reminders) UpdateReminder() error { + updateInteface := make(map[string]interface{}) + + if r.ReminderName != nil { + updateInteface["reminder_name"] = *r.ReminderName + } + + if r.ReminderContent != nil { + updateInteface["reminder_content"] = *r.ReminderContent + } + + if r.ReminderTime != nil { + updateInteface["reminder_time"] = *r.ReminderTime + } + + err := database.DB.Model(&Reminders{}).Where("reminder_id = ?", r.ReminderId).UpdateColumns(updateInteface).Error + + return err +} + +func (r *Reminders) DeleteReminder() error { + result := database.DB.Where("reminder_id = ? AND username like ?", r.ReminderId, r.UserName).Delete(&r) + if result.RowsAffected == 0 { + return gorm.ErrRecordNotFound + } + + return result.Error +} + +func (r *Reminders) SoftDeleteExpiredReminders() { + now := time.Now() + database.DB.Model(&Reminders{}).Where("reminder_time < ?", now).Delete(&Reminders{}) +} + +func (r *Reminders) CleanupOldReminders() { + database.DB.Unscoped().Where("deleted_at < NOW() - INTERVAL '7 days'").Delete(&Reminders{}) +} diff --git a/vitty-backend-api/internal/utils/users.go b/vitty-backend-api/internal/utils/users.go index fab413f..5cc6457 100644 --- a/vitty-backend-api/internal/utils/users.go +++ b/vitty-backend-api/internal/utils/users.go @@ -1,8 +1,11 @@ package utils import ( + "strings" + "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/database" "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/models" + "github.com/google/uuid" ) func CheckUserExists(username string) bool { @@ -58,3 +61,10 @@ func ValidateUsername(username string) (bool, string) { return true, "" } + +func UUIDWithPrefix(prefix string) string { + id := uuid.New().String() + id = prefix + "_" + id + id = strings.ReplaceAll(id, "-", "") + return id +} From 53d1e05fec1f93810e05c2e5153d9a6ef19ddc27 Mon Sep 17 00:00:00 2001 From: TheSilentSage Date: Wed, 1 Jan 2025 21:15:44 +0530 Subject: [PATCH 3/4] feat: added debug configuration for jobs --- vitty-backend-api/cmd/root.go | 9 +++++- vitty-backend-api/internal/jobs/jobs.go | 29 +++++++++++++---- vitty-backend-api/internal/utils/jobs.go | 41 ++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 vitty-backend-api/internal/utils/jobs.go diff --git a/vitty-backend-api/cmd/root.go b/vitty-backend-api/cmd/root.go index d9ef056..7ed6e65 100644 --- a/vitty-backend-api/cmd/root.go +++ b/vitty-backend-api/cmd/root.go @@ -10,6 +10,7 @@ import ( "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/database" "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/jobs" "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/models" + "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/utils" "github.com/gofiber/fiber/v2" "github.com/urfave/cli/v2" ) @@ -41,6 +42,7 @@ type Env struct { // Job Variable isRunJobs string + jobTime jobs.JobTime } // Method to create a new VittyApp @@ -59,6 +61,11 @@ func (v *VittyApp) setEnv() { v.env.google_client_id = os.Getenv("GOOGLE_CLIENT_ID") v.env.google_client_secret = os.Getenv("GOOGLE_CLIENT_SECRET") v.env.google_redirect_uri = os.Getenv("GOOGLE_REDIRECT_URI") + + //Jobs + v.env.isRunJobs = os.Getenv("RUN_JOBS") + v.env.jobTime = utils.ParseJobTimes() + } // Method to initialize CLI app @@ -99,7 +106,7 @@ func (v *VittyApp) init() { auth.InitializeFirebaseApp() // Initialize jobs - jobs.InitializeJobs(v.env.isRunJobs) + jobs.InitializeJobs(v.env.isRunJobs, v.env.debug, v.env.jobTime) // Initialize Web app v.initWebApp() diff --git a/vitty-backend-api/internal/jobs/jobs.go b/vitty-backend-api/internal/jobs/jobs.go index b6b53e7..c93c717 100644 --- a/vitty-backend-api/internal/jobs/jobs.go +++ b/vitty-backend-api/internal/jobs/jobs.go @@ -7,10 +7,25 @@ import ( "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/models" ) -func InitializeJobs(isRunJobs string) { +type JobTime struct { + DAILY_JOB_MIN int + DAILY_JOB_SEC int + WEEKLY_JOB_MIN int + WEEKLY_JOB_SEC int +} + +func InitializeJobs(isRunJobs string, debug string, jobTimes JobTime) { if isRunJobs == "true" { - startDailyJob() - startWeeklyJob() + if debug == "true" { + + timeDailyJob := time.Duration(jobTimes.DAILY_JOB_MIN)*time.Minute + time.Duration(jobTimes.DAILY_JOB_SEC)*time.Second + timeWeeklyJob := time.Duration(jobTimes.WEEKLY_JOB_MIN)*time.Minute + time.Duration(jobTimes.WEEKLY_JOB_SEC)*time.Second + go startDailyJob(timeDailyJob) + go startWeeklyJob(timeWeeklyJob) + } else { + go startDailyJob(24 * time.Hour) + go startWeeklyJob(7 * 24 * time.Hour) + } log.Println("Jobs are running") } else { log.Println("Jobs disabled") @@ -20,8 +35,8 @@ func InitializeJobs(isRunJobs string) { var reminder models.Reminders -func startDailyJob() { - ticker := time.NewTicker(24 * time.Hour) +func startDailyJob(jobTime time.Duration) { + ticker := time.NewTicker(jobTime) defer ticker.Stop() for { @@ -32,8 +47,8 @@ func startDailyJob() { } } -func startWeeklyJob() { - ticker := time.NewTicker(7 * 24 * time.Hour) +func startWeeklyJob(jobTime time.Duration) { + ticker := time.NewTicker(jobTime) defer ticker.Stop() for { diff --git a/vitty-backend-api/internal/utils/jobs.go b/vitty-backend-api/internal/utils/jobs.go new file mode 100644 index 0000000..7ddec52 --- /dev/null +++ b/vitty-backend-api/internal/utils/jobs.go @@ -0,0 +1,41 @@ +package utils + +import ( + "log" + "os" + "strconv" + + "github.com/GDGVIT/vitty-backend/vitty-backend-api/internal/jobs" +) + +func ParseJobTimes() jobs.JobTime { + var err error + var jobTime jobs.JobTime + + jobTime.DAILY_JOB_MIN, err = strconv.Atoi(os.Getenv("DAILY_JOB_MIN")) + + if err != nil { + log.Fatal(err, "JOB_DAILY_MIN_PARSE_ERR") + } + + jobTime.DAILY_JOB_SEC, err = strconv.Atoi(os.Getenv("DAILY_JOB_SEC")) + + if err != nil { + log.Fatal(err, "JOB_DAILY_SEC_PARSE_ERR") + } + + jobTime.WEEKLY_JOB_MIN, err = strconv.Atoi(os.Getenv("WEEKLY_JOB_MIN")) + + if err != nil { + log.Fatal(err, "JOB_WEEKLY_MIN_PARSE_ERR") + } + + jobTime.WEEKLY_JOB_SEC, err = strconv.Atoi(os.Getenv("WEEKLY_JOB_SEC")) + + if err != nil { + log.Fatal(err, "JOB_WEEKLY_SEC_PARSE_ERR") + } + + log.Println("Parse Done") + return jobTime +} From 1d1f50228552d499341f0291a812ae90ea9dd95a Mon Sep 17 00:00:00 2001 From: TheSilentSage Date: Wed, 1 Jan 2025 21:17:58 +0530 Subject: [PATCH 4/4] chore: updated env files --- vitty-backend-api/example.env/example.local | 7 ++++++- vitty-backend-api/example.env/example.production | 4 +++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/vitty-backend-api/example.env/example.local b/vitty-backend-api/example.env/example.local index cfedaa3..3820765 100644 --- a/vitty-backend-api/example.env/example.local +++ b/vitty-backend-api/example.env/example.local @@ -19,4 +19,9 @@ JWT_SECRET=secret # Job Variables # --------------------------------------------------------------- -RUN_JOBS=false \ No newline at end of file +RUN_JOBS=false +#Works only if debug is true +DAILY_JOB_MIN=0 +DAILY_JOB_SEC=10 +WEEKLY_JOB_MIN=0 +WEEKLY_JOB_SEC=20 \ No newline at end of file diff --git a/vitty-backend-api/example.env/example.production b/vitty-backend-api/example.env/example.production index 3a60c3a..1e832d4 100644 --- a/vitty-backend-api/example.env/example.production +++ b/vitty-backend-api/example.env/example.production @@ -15,4 +15,6 @@ POSTGRES_PORT=5432 # Auth Variables # --------------------------------------------------------------- OAUTH_CALLBACK_URL=https:///auth/callback -JWT_SECRET=secret \ No newline at end of file +JWT_SECRET=secret +# --------------------------------------------------------------- +RUN_JOBS=false \ No newline at end of file