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  }