worker/answerwc/to_client.go

370 lines
9.8 KiB
Go
Raw Normal View History

2024-02-19 18:20:09 +00:00
package answerwc
import (
"context"
_ "embed"
"encoding/json"
"fmt"
2024-03-13 16:36:23 +00:00
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/dal"
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/model"
2024-02-19 18:20:09 +00:00
"penahub.gitlab.yandexcloud.net/backend/quiz/worker.git/clients/mailclient"
"penahub.gitlab.yandexcloud.net/backend/quiz/worker.git/wctools"
"penahub.gitlab.yandexcloud.net/pena-services/customer/pkg/customer_clients"
2024-03-13 16:36:23 +00:00
2024-02-19 18:20:09 +00:00
"time"
"github.com/go-redis/redis/v8"
)
type DepsSendToClient struct {
Redis *redis.Client
Dal *dal.DAL
MailClient *mailclient.Client
CustomerService *customer_clients.CustomersClient
2024-02-19 18:20:09 +00:00
}
type SendToClient struct {
redis *redis.Client
dal *dal.DAL
mailClient *mailclient.Client
customerService *customer_clients.CustomersClient
errChan chan<- error
2024-02-19 18:20:09 +00:00
}
type PendingTasks struct {
Count int64
QuizConfig model.QuizConfig
}
//go:embed mail/to_client.tmpl
var toClientTemplate string
//go:embed mail/reminder.tmpl
var reminderTemplate string
func NewSendToClient(deps DepsSendToClient, errChan chan<- error) *SendToClient {
2024-02-19 18:20:09 +00:00
return &SendToClient{
redis: deps.Redis,
dal: deps.Dal,
mailClient: deps.MailClient,
customerService: deps.CustomerService,
errChan: errChan,
2024-02-19 18:20:09 +00:00
}
}
func (w *SendToClient) Start(ctx context.Context) {
answerTicker := time.NewTicker(30 * time.Second)
defer answerTicker.Stop()
for {
select {
case <-answerTicker.C:
w.processPendingAnswer(ctx)
case <-ctx.Done():
return
}
}
}
func (w *SendToClient) processPendingAnswer(ctx context.Context) {
pendingAnswers, err := w.redis.Keys(ctx, "answer:*").Result()
2024-02-19 18:20:09 +00:00
if err != nil {
fmt.Println("Error getting keys from redis")
w.errChan <- err
return
}
fmt.Println("ANS")
for _, key := range pendingAnswers {
func() {
fmt.Println("ANS1", key)
answerJSON, err := w.redis.GetDel(ctx, key).Result()
2024-02-19 18:20:09 +00:00
if err == redis.Nil {
return
} else if err != nil {
w.reportError(err, "Error getting and deleting data from redis")
return
}
defer func() {
if r := recover(); r != nil {
w.reportError(nil, fmt.Sprintf("recovering from panic or error setting redis value %v", r))
fmt.Println("ANS1ERRR", r)
_ = w.redis.Set(ctx, key, answerJSON, 0).Err()
2024-02-19 18:20:09 +00:00
}
}()
var answer model.Answer
err = json.Unmarshal([]byte(answerJSON), &answer)
fmt.Println("ANS2", err)
if err != nil {
w.reportError(err, "Error unmarshal answer")
return
}
answerContent, err := wctools.ProcessAnswer(answer.Content)
fmt.Println("ANS3", err)
if err != nil {
w.reportError(err, "Error unmarshal answer content")
return
}
allAnswers, err := w.dal.AnswerRepo.GetAllAnswersByQuizID(ctx, answer.Session)
2024-02-19 18:20:09 +00:00
fmt.Println("ANS4", err)
if err != nil {
w.reportError(err, "Error getting all answers by quizID")
return
}
questionsMap, sortedallAnswers, err := w.dal.QuestionRepo.GetMapQuestions(ctx, allAnswers)
2024-02-19 18:20:09 +00:00
fmt.Println("ANS5", err)
if err != nil {
w.reportError(err, "Error getting questionsMap")
return
}
if answer.QuizId == 0 {
return
}
quizConfig, accountId, err := w.dal.QuizRepo.GetQuizConfig(ctx, answer.QuizId)
2024-02-19 18:20:09 +00:00
fmt.Println("ANS6", err)
if err != nil {
w.reportError(err, "Error getting quiz config")
return
}
quiz, err := w.dal.QuizRepo.GetQuizById(ctx, accountId, answer.QuizId)
2024-02-19 18:20:09 +00:00
fmt.Println("ANS60", err, accountId, answer.QuizId)
if err != nil {
w.reportError(err, "Error getting quiz")
return
}
quizConfig.Mailing.Reply = quiz.Name
if quizConfig.Mailing.Theme == "" {
quizConfig.Mailing.Theme = quiz.Name
}
account, privileges, err := w.dal.AccountRepo.GetAccAndPrivilegeByEmail(ctx, accountId)
2024-02-19 18:20:09 +00:00
fmt.Println("ANS7", err)
if err != nil {
w.reportError(err, "Error getting account and privileges by email")
return
}
result, err := w.processAnswerWithPrivileges(ctx, quiz.Name, quizConfig, questionsMap, privileges, account, sortedallAnswers, answerContent, answer.CreatedAt)
2024-02-19 18:20:09 +00:00
fmt.Println("ANS8", err, result, privileges)
if err != nil {
w.reportError(err, "Error process answer with privileges")
return
}
if !result {
err = w.redis.Set(ctx, fmt.Sprintf("%s:%s", account.ID, key), answerJSON, 0).Err()
2024-02-19 18:20:09 +00:00
if err != nil {
w.reportError(err, "Error setting redis value")
return
}
}
}()
}
}
func (w *SendToClient) processAnswerWithPrivileges(ctx context.Context, quizName string, quizConfig model.QuizConfig,
questionsMap map[uint64]string, privileges []model.ShortPrivilege, account model.Account, allAnswers []model.ResultAnswer,
answerContent model.ResultContent, answerTime time.Time) (bool, error) {
err := w.notificationCustomer(ctx, account, privileges)
2024-02-19 18:20:09 +00:00
fmt.Println("ANS81", err)
if err != nil {
return false, err
}
if wctools.HasUnlimitedPrivilege(privileges) {
err := w.ProcessMessageToClient(quizConfig, questionsMap, account, allAnswers, answerContent, answerTime)
if err != nil {
return false, err
}
return true, nil
}
privilege := wctools.HasQuizCntPrivilege(privileges)
if privilege != nil {
err := w.ProcessMessageToClient(quizConfig, questionsMap, account, allAnswers, answerContent, answerTime)
fmt.Println("PMC", err)
if err != nil {
return true, err
}
privilege.Amount--
err = w.dal.AccountRepo.UpdatePrivilegeAmount(ctx, privilege.ID, privilege.Amount)
2024-02-19 18:20:09 +00:00
if err != nil {
return false, err
}
return true, nil
} else {
w.checkAndSendTaskReminders(sendTaskRemindersDeps{
2024-02-19 18:20:09 +00:00
email: account.Email,
theme: quizName,
config: model.QuizConfig{
Mailing: model.ResultInfo{
When: "email",
Theme: fmt.Sprintf("не удалось отправить заявку по опросу\"%s\"", quizName),
Reply: "noreply@pena.digital",
ReplName: "Reminder",
},
},
})
return false, nil
}
}
func (w *SendToClient) recordPendingTasks(ctx context.Context, Email string, quizConfig model.QuizConfig) error {
key := fmt.Sprintf("pending_tasks:%s", Email)
var pendingTasks PendingTasks
val, err := w.redis.HGet(ctx, key, "data").Result()
2024-02-19 18:20:09 +00:00
if err == nil {
err := json.Unmarshal([]byte(val), &pendingTasks)
if err != nil {
return err
}
pendingTasks.Count++
} else {
pendingTasks = PendingTasks{
Count: 1,
QuizConfig: quizConfig,
}
}
pendingTasksJSON, err := json.Marshal(pendingTasks)
if err != nil {
return err
}
err = w.redis.HSet(ctx, key, "data", string(pendingTasksJSON)).Err()
2024-02-19 18:20:09 +00:00
if err != nil {
return err
}
return nil
}
type sendTaskRemindersDeps struct {
email, theme string
config model.QuizConfig
}
func (w *SendToClient) checkAndSendTaskReminders(deps sendTaskRemindersDeps) {
2024-02-19 18:20:09 +00:00
err := w.processReminderToClient(deps.email, deps.config)
fmt.Println("PMC1", err)
if err != nil {
w.reportError(err, "Error sending tasks reminder email")
}
}
func (w *SendToClient) notificationCustomer(ctx context.Context, account model.Account, privileges []model.ShortPrivilege) error {
2024-02-19 18:20:09 +00:00
for _, privilege := range privileges {
fmt.Println("NOTIFIC", privilege.PrivilegeID, privilege.Amount, !wctools.IsPrivilegeExpired(privilege))
if privilege.PrivilegeID == "quizUnlimTime" && !wctools.IsPrivilegeExpired(privilege) {
historyData := customer_clients.InsertHistoryDeps{
UserID: account.UserID,
Comment: fmt.Sprintf("%s privilege has expired, it was created at %d", privilege.PrivilegeID, privilege.CreatedAt.Unix()),
Key: "end",
2024-02-19 18:20:09 +00:00
}
err := w.customerService.InsertHistory(ctx, historyData)
2024-02-19 18:20:09 +00:00
if err != nil {
return err
}
}
if privilege.PrivilegeID == "quizCnt" && privilege.Amount == 0 {
historyData := customer_clients.InsertHistoryDeps{
UserID: account.UserID,
Comment: fmt.Sprintf("%s privilege has expired, it was created at %d", privilege.PrivilegeID, privilege.CreatedAt.Unix()),
Key: "end",
2024-02-19 18:20:09 +00:00
}
err := w.customerService.InsertHistory(ctx, historyData)
2024-02-19 18:20:09 +00:00
if err != nil {
return err
}
}
}
return nil
}
// сделал экспортируемым для теста
func (w *SendToClient) ProcessMessageToClient(quizConfig model.QuizConfig, questionsMap map[uint64]string, account model.Account, allAnswers []model.ResultAnswer, answerContent model.ResultContent, answerTime time.Time) error {
theme := quizConfig.Mailing.Theme
quizConfig.Mailing.Theme = quizConfig.Mailing.Reply
data := mailclient.EmailTemplateData{
QuizConfig: quizConfig.Mailing,
AnswerContent: answerContent,
AllAnswers: allAnswers,
QuestionsMap: questionsMap,
}
dayOfWeek := wctools.DaysOfWeek[answerTime.Format("Monday")]
monthOfYear := wctools.MonthsOfYear[answerTime.Format("January")]
formattedTime := fmt.Sprintf("%s, %d %s %d г., %02d:%02d (UTC%s)",
dayOfWeek,
answerTime.Day(),
monthOfYear,
answerTime.Year(),
answerTime.Hour(),
answerTime.Minute(),
answerTime.Format("-07:00"),
)
data.AnswerTime = formattedTime
fmt.Println("SUBJECT", theme, account.Email)
err := w.mailClient.SendMailWithAttachment(account.Email, theme, toClientTemplate, data, nil)
2024-02-19 18:20:09 +00:00
if err != nil {
return err
}
return nil
}
func (w *SendToClient) processReminderToClient(email string, quizConfig model.QuizConfig) error {
data := mailclient.EmailTemplateData{
QuizConfig: model.ResultInfo{
When: quizConfig.Mailing.When,
Theme: quizConfig.Mailing.Theme,
Reply: email,
ReplName: quizConfig.Mailing.ReplName,
},
AnswerContent: model.ResultContent{},
AllAnswers: []model.ResultAnswer{},
QuestionsMap: nil,
}
fmt.Println("PRTC", data, email, quizConfig)
err := w.mailClient.SendMailWithAttachment(email, quizConfig.Mailing.Theme, reminderTemplate, data, nil)
2024-02-19 18:20:09 +00:00
if err != nil {
return err
}
return nil
}
func (w *SendToClient) reportError(err error, message string) {
if err != nil {
fmt.Println(message + ": " + err.Error())
w.errChan <- err
}
}