package controllers import ( "bytes" "encoding/json" "fmt" "io/ioutil" "log" "nearle/models" "nearle/services" "net/http" "strconv" "github.com/gofiber/fiber/v2" "golang.org/x/oauth2" "golang.org/x/oauth2/google" ) type UtilsController struct { utilsService services.UtilsService } func NewUtilsController(utilsService services.UtilsService) *UtilsController { return &UtilsController{utilsService: utilsService} } const ( fcmURL = "https://fcm.googleapis.com/v1/projects/nearle-gear/messages:send" scope = "https://www.googleapis.com/auth/firebase.messaging" serviceAcc = "nearle-gear-firebase-adminsdk-l9oha-23ca3b3609.json" // Path to your service account JSON ) var client *http.Client func (ctl *UtilsController) GetAppTypes(c *fiber.Ctx) error { tag := c.Query("tag") result, err := ctl.utilsService.GetApptypes(tag) if err != nil { return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "code": http.StatusInternalServerError, "message": err.Error(), "status": false, }) } return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": result, }) } func (ctl *UtilsController) NotifyUser(c *fiber.Ctx) error { var body struct { Token string `json:"token"` Notification models.FcmNotification `json:"notification"` Data map[string]string `json:"data"` } if err := c.BodyParser(&body); err != nil { return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "code": http.StatusBadRequest, "message": fmt.Sprintf("Error parsing request body: %v", err), "status": false, }) } err := ctl.utilsService.SendNotification(body.Token, body.Notification, body.Data) if err != nil { return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ "code": http.StatusInternalServerError, "message": fmt.Sprintf("Error sending notification: %v", err), "status": false, }) } return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "FCM message sent successfully!", "status": true, }) } func (ctl *UtilsController) GetSubcategories(c *fiber.Ctx) error { mid, _ := strconv.Atoi(c.Query("moduleid")) cid, _ := strconv.Atoi(c.Query("categoryid")) result, err := ctl.utilsService.GetSubcategories(mid, cid) if err != nil { return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "code": http.StatusInternalServerError, "message": err.Error(), "status": false, }) } return c.JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": result, }) } func (ctl *UtilsController) GetApplocations(c *fiber.Ctx) error { aid, err := strconv.Atoi(c.Query("applocationid")) if err != nil { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "code": http.StatusBadRequest, "message": "Invalid applocationid", "status": false, }) } result, err := ctl.utilsService.GetApplocations(aid) if err != nil { return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "code": http.StatusInternalServerError, "message": err.Error(), "status": false, }) } return c.JSON(fiber.Map{ "status": true, "code": http.StatusOK, "message": "Successful", "details": result, }) } func (ctl *UtilsController) GetApplocationConfig(c *fiber.Ctx) error { aid, err := strconv.Atoi(c.Query("applocationid")) if err != nil { return c.Status(http.StatusBadRequest).JSON(fiber.Map{ "code": http.StatusBadRequest, "message": "Invalid applocationid", "status": false, }) } result, err := ctl.utilsService.GetApplocationConfig(aid) if err != nil { return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "code": http.StatusInternalServerError, "message": err.Error(), "status": false, }) } return c.JSON(fiber.Map{ "status": true, "code": http.StatusOK, "message": "Successful", "details": result, }) } type Notification struct { Title string `json:"title"` Body string `json:"body"` } type FCMRequestBody struct { Message struct { Notification Notification `json:"notification"` Token string `json:"token"` } `json:"message"` } func GetClientFromServiceAccount() (*http.Client, error) { data, err := ioutil.ReadFile(serviceAcc) if err != nil { return nil, fmt.Errorf("failed to read service account file: %v", err) } config, err := google.JWTConfigFromJSON(data, scope) if err != nil { return nil, fmt.Errorf("failed to parse service account JSON: %v", err) } client := config.Client(oauth2.NoContext) return client, nil } func sendFCMMessage(token, title, body string) error { if client == nil { var err error client, err = GetClientFromServiceAccount() if err != nil { return fmt.Errorf("failed to get client: %v", err) } } notification := Notification{ Title: title, Body: body, } fcmRequest := FCMRequestBody{} fcmRequest.Message.Notification = notification fcmRequest.Message.Token = token requestBody, err := json.Marshal(fcmRequest) if err != nil { return err } req, err := http.NewRequest("POST", fcmURL, bytes.NewBuffer(requestBody)) if err != nil { return err } req.Header.Set("Content-Type", "application/json") resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { bodyBytes, _ := ioutil.ReadAll(resp.Body) return fmt.Errorf("failed to send message: %s", string(bodyBytes)) } return nil } func (ctl *UtilsController) NotifyAdmin(c *fiber.Ctx) error { body := new(struct { Token []string `json:"token"` Notification struct { Title string `json:"title"` Body string `json:"body"` Sound string `json:"sound"` Type string `json:"type"` } `json:"notification"` }) if err := c.BodyParser(body); err != nil { return fiber.NewError(fiber.StatusBadRequest, "Invalid request body") } if len(body.Token) == 0 { return fiber.NewError(fiber.StatusBadRequest, "No tokens provided") } var successCount, failureCount int for _, token := range body.Token { err := sendFCMMessage(token, body.Notification.Title, body.Notification.Body) if err != nil { log.Printf("❌ Failed to send to %s: %v", token, err) failureCount++ } else { log.Printf("✅ Notification sent to %s", token) successCount++ } } return c.Status(fiber.StatusOK).JSON(fiber.Map{ "message": "Admin notifications sent", "success": successCount, "failure": failureCount, }) } func (ctl *UtilsController) GetAppConfig(c *fiber.Ctx) error { cid, _ := strconv.Atoi(c.Query("configid")) result, err := ctl.utilsService.GetAppConfig(cid) if err != nil { return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "code": 500, "message": "Failed to fetch app config", "status": false, }) } return c.Status(http.StatusOK).JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": result, }) } func (ctl *UtilsController) GetAppCategory(c *fiber.Ctx) error { result, err := ctl.utilsService.GetAppCategory() if err != nil { return c.Status(http.StatusInternalServerError).JSON(fiber.Map{ "code": 500, "message": "Failed to fetch app categories", "status": false, }) } return c.Status(http.StatusOK).JSON(fiber.Map{ "code": http.StatusOK, "message": "Success", "status": true, "details": result, }) }