package notificationimp import ( "context" "github.com/tech/sendico/notification/interface/api" "github.com/tech/sendico/notification/internal/appversion" mmail "github.com/tech/sendico/notification/internal/server/notificationimp/mail" "github.com/tech/sendico/notification/internal/server/notificationimp/telegram" "github.com/tech/sendico/pkg/discovery" "github.com/tech/sendico/pkg/domainprovider" "github.com/tech/sendico/pkg/merrors" na "github.com/tech/sendico/pkg/messaging/notifications/account" confirmations "github.com/tech/sendico/pkg/messaging/notifications/confirmations" cnotifications "github.com/tech/sendico/pkg/messaging/notifications/confirmation" ni "github.com/tech/sendico/pkg/messaging/notifications/invitation" snotifications "github.com/tech/sendico/pkg/messaging/notifications/site" "github.com/tech/sendico/pkg/mlogger" "github.com/tech/sendico/pkg/model" "github.com/tech/sendico/pkg/mservice" "go.uber.org/zap" ) type NotificationAPI struct { logger mlogger.Logger client mmail.Client dp domainprovider.DomainProvider tg telegram.Client announcer *discovery.Announcer confirm *confirmationManager } func (a *NotificationAPI) Name() mservice.Type { return mservice.Notifications } func (a *NotificationAPI) Finish(_ context.Context) error { if a.announcer != nil { a.announcer.Stop() } if a.confirm != nil { a.confirm.Stop() } return nil } func CreateAPI(a api.API) (*NotificationAPI, error) { p := &NotificationAPI{ dp: a.DomainProvider(), } p.logger = a.Logger().Named(p.Name()) if a.Config().Notification == nil { return nil, merrors.InvalidArgument("notification configuration is missing", "config.notification") } if a.Config().Notification.Telegram == nil { return nil, merrors.InvalidArgument("telegram configuration is missing", "config.notification.telegram") } var err error if p.client, err = mmail.CreateMailClient(p.logger.Named("mailer"), p.Name(), a.Register().Producer(), a.Localizer(), a.DomainProvider(), a.Config().Notification); err != nil { p.logger.Error("Failed to create mail connection", zap.Error(err), zap.String("driver", a.Config().Notification.Driver)) return nil, err } if p.tg, err = telegram.NewClient(p.logger.Named("telegram"), a.Config().Notification.Telegram); err != nil { p.logger.Error("Failed to create telegram client", zap.Error(err)) return nil, err } p.confirm = newConfirmationManager(p.logger, p.tg, a.Register().Producer()) db, err := a.DBFactory().NewAccountDB() if err != nil { p.logger.Error("Failed to create account db connection", zap.Error(err)) return nil, err } if err := a.Register().Consumer(na.NewAccountCreatedMessageProcessor(p.logger, db, p.onAccount)); err != nil { p.logger.Error("Failed to create account creation handler", zap.Error(err)) return nil, err } if err := a.Register().Consumer(na.NewPasswordResetRequestedMessageProcessor(p.logger, db, p.onPasswordReset)); err != nil { p.logger.Error("Failed to create password reset handler", zap.Error(err)) return nil, err } if err := a.Register().Consumer(cnotifications.NewConfirmationCodeProcessor(p.logger, db, p.onConfirmationCode)); err != nil { p.logger.Error("Failed to create confirmation code handler", zap.Error(err)) return nil, err } if err := a.Register().Consumer(confirmations.NewConfirmationRequestProcessor(p.logger, p.onConfirmationRequest)); err != nil { p.logger.Error("Failed to register confirmation request handler", zap.Error(err)) return nil, err } idb, err := a.DBFactory().NewInvitationsDB() if err != nil { p.logger.Error("Failed to create invitation db connection", zap.Error(err)) return nil, err } if err := a.Register().Consumer(ni.NewInvitationCreatedProcessor(p.logger, p.onInvitation, idb, db)); err != nil { p.logger.Error("Failed to create invitation creation handler", zap.Error(err)) return nil, err } if err := a.Register().Consumer(snotifications.NewSiteRequestProcessor(p.logger, p.onDemoRequest, p.onContactRequest, p.onCallRequest)); err != nil { p.logger.Error("Failed to register site request handler", zap.Error(err)) return nil, err } if router := a.Router(); router != nil { router.Post("/telegram/webhook", p.handleTelegramWebhook) } announce := discovery.Announcement{ Service: "NOTIFICATIONS", Operations: []string{"notify.send"}, Version: appversion.Create().Short(), } p.announcer = discovery.NewAnnouncer(p.logger, a.Register().Producer(), string(mservice.Notifications), announce) p.announcer.Start() return p, nil } func (a *NotificationAPI) onDemoRequest(ctx context.Context, request *model.DemoRequest) error { if a.tg == nil { return merrors.Internal("telegram client is not configured") } if err := a.tg.SendDemoRequest(ctx, request); err != nil { a.logger.Warn("Failed to send demo request via telegram", zap.Error(err)) return err } a.logger.Info("Demo request sent via Telegram", zap.String("name", request.Name), zap.String("organization", request.OrganizationName)) return nil } func (a *NotificationAPI) onContactRequest(ctx context.Context, request *model.ContactRequest) error { if a.tg == nil { return merrors.Internal("telegram client is not configured") } if err := a.tg.SendContactRequest(ctx, request); err != nil { a.logger.Warn("Failed to send contact request via telegram", zap.Error(err)) return err } a.logger.Info("Contact request sent via Telegram", zap.String("name", request.Name), zap.String("topic", request.Topic)) return nil } func (a *NotificationAPI) onCallRequest(ctx context.Context, request *model.CallRequest) error { if a.tg == nil { return merrors.Internal("telegram client is not configured") } if err := a.tg.SendCallRequest(ctx, request); err != nil { a.logger.Warn("Failed to send call request via telegram", zap.Error(err)) return err } a.logger.Info("Call request sent via Telegram", zap.String("phone", request.Phone)) return nil } func (a *NotificationAPI) onConfirmationRequest(ctx context.Context, request *model.ConfirmationRequest) error { if a.confirm == nil { return merrors.Internal("confirmation manager is not configured") } return a.confirm.HandleRequest(ctx, request) }