github.com/oinume/lekcije@v0.0.0-20231017100347-5b4c5eb6ab24/backend/cmd/follow_reminder/main.go (about) 1 package main 2 3 import ( 4 "context" 5 "flag" 6 "fmt" 7 "io" 8 "net/http" 9 "os" 10 "strings" 11 "time" 12 13 "go.uber.org/zap" 14 15 "github.com/oinume/lekcije/backend/cli" 16 "github.com/oinume/lekcije/backend/domain/config" 17 model_email "github.com/oinume/lekcije/backend/domain/model/email" 18 "github.com/oinume/lekcije/backend/infrastructure/send_grid" 19 "github.com/oinume/lekcije/backend/logger" 20 "github.com/oinume/lekcije/backend/model" 21 "github.com/oinume/lekcije/backend/model2" 22 ) 23 24 func main() { 25 m := &followReminderMain{ 26 outStream: os.Stdout, 27 errStream: os.Stderr, 28 } 29 if err := m.run(os.Args); err != nil { 30 cli.WriteError(m.errStream, err) 31 os.Exit(cli.ExitError) 32 } 33 os.Exit(cli.ExitOK) 34 } 35 36 type followReminderMain struct { 37 outStream io.Writer 38 errStream io.Writer 39 } 40 41 func (m *followReminderMain) run(args []string) error { 42 flagSet := flag.NewFlagSet("follow_reminder", flag.ContinueOnError) 43 flagSet.SetOutput(m.errStream) 44 var ( 45 dryRun = flagSet.Bool("dry-run", false, "Don't update database with fetched lessons") 46 targetDate = flagSet.String("target-date", "", "Specify registration date of users") 47 logLevel = flagSet.String("log-level", "info", "Log level") 48 ) 49 if err := flagSet.Parse(args[1:]); err != nil { 50 return err 51 } 52 53 config.MustProcessDefault() 54 startedAt := time.Now().UTC() 55 appLogger := logger.NewAppLogger(os.Stderr, logger.NewLevel(*logLevel)) 56 appLogger.Info("follow_reminder started") 57 defer func() { 58 elapsed := time.Now().UTC().Sub(startedAt) / time.Millisecond 59 appLogger.Info("follow_reminder finished", zap.Int("elapsed", int(elapsed))) 60 }() 61 62 db, err := model.OpenDB(config.DefaultVars.DBURL(), 1, config.DefaultVars.DebugSQL) 63 if err != nil { 64 return err 65 } 66 defer func() { _ = db.Close() }() 67 68 ctx := context.Background() 69 var date time.Time 70 if *targetDate == "" { 71 date = time.Now().UTC().Add(-1 * 24 * time.Hour) 72 } else { 73 date, err = time.Parse("2006-01-02", *targetDate) 74 if err != nil { 75 return fmt.Errorf("failed to parse 'target-date': %v", *targetDate) 76 } 77 } 78 users, err := model.NewUserService(db).FindAllFollowedTeacherAtIsNull(date) 79 if err != nil { 80 return err 81 } 82 83 sender := send_grid.NewEmailSender(http.DefaultClient, appLogger) 84 templateText := getEmailTemplate() 85 for _, user := range users { 86 t := model_email.NewTemplate("follow_reminder", templateText) 87 data := struct { 88 To string 89 Name string 90 }{ 91 To: user.Email, 92 Name: user.Name, 93 } 94 mail, err := model_email.NewFromTemplate(t, data) 95 if err != nil { 96 return err 97 } 98 mail.SetCustomArg("email_type", model2.EmailTypeFollowReminder) 99 mail.SetCustomArg("user_id", fmt.Sprint(user.ID)) 100 101 if !*dryRun { 102 if err := sender.Send(ctx, mail); err != nil { 103 return err 104 } 105 } 106 appLogger.Info("followReminder", zap.Uint("userID", uint(user.ID)), zap.String("email", user.Email)) 107 } 108 109 return nil 110 } 111 112 func getEmailTemplate() string { 113 return strings.TrimSpace(` 114 From: lekcije@lekcije.com 115 To: {{ .To }} 116 Subject: lekcijeでお気に入りの講師をフォローしましょう 117 Body: text/html 118 <a href="https://www.lekcije.com/">lekcije</a>をご利用いただきありがとうございます。 119 lekcijeでお気入りのDMM英会話の講師をフォローしてみましょう。 120 フォローすると、講師の空きレッスンが登録された時にメールでお知らせが届きます。 121 122 フォローの仕方がわからない場合は下記をチェック! 123 <a href="https://lekcije.amebaownd.com/posts/2044879">PC</a> 124 <a href="https://lekcije.amebaownd.com/posts/1577091">Mobile</a> 125 126 今後ともlekcijeをよろしくお願いいたします。 127 `) 128 }