<commit_before>package http

import (
	"encoding/json"
	"fmt"
	"log"
	"regexp"

	"github.com/VagabondDataNinjas/gizlinebot/domain"

	"github.com/labstack/echo"

	"github.com/VagabondDataNinjas/gizlinebot/storage"
	"github.com/VagabondDataNinjas/gizlinebot/survey"
	"github.com/line/line-bot-sdk-go/linebot"
)

func LineWebhookHandlerBuilder(surv *survey.Survey, s storage.Storage, bot *linebot.Client, globalVars *domain.GlobalTplVars) func(c echo.Context) error {
	return func(c echo.Context) error {
		events, err := bot.ParseRequest(c.Request())
		if err != nil {
			if err == linebot.ErrInvalidSignature {
				c.JSON(400, map[string]string{"status": "error", "err": err.Error()})
				// w.WriteHeader(400)
			} else {
				// @TODO log error
				c.JSON(500, map[string]string{"status": "error"})
			}
		}
		for _, event := range events {
			userId := event.Source.UserID
			questionTplVars := &survey.QuestionTemplateVars{
				UserId:   userId,
				Hostname: globalVars.Hostname,
			}

			eventString, err := json.Marshal(event)
			if err != nil {
				log.Printf("[err] Could not marshal event: %+v; err: %s", event, err)
			} else {
				err = s.AddRawLineEvent(string(event.Type), string(eventString))
				if err != nil {
					log.Printf("[err] Could not store event: %+v; err: %s", event, err)
				}
			}

			if event.Type == linebot.EventTypeFollow {
				log.Printf("User %s follow event", userId)
				userProfileResp, err := bot.GetProfile(userId).Do()
				if err != nil {
					log.Print(err)
					continue
				}

				err = s.AddUserProfile(userProfileResp.UserID, userProfileResp.DisplayName)
				if err != nil {
					fmt.Printf("AddUserProfile err: %s\n", err)
					continue
				}

				hasAnswers, err := s.UserHasAnswers(userId)
				if err != nil {
					log.Print(err)
					continue
				}

				if hasAnswers {
					question, err := surv.GetNextQuestion(userId, questionTplVars)
					if err != nil {
						log.Print(err)
						continue
					}
					if _, err = bot.PushMessage(userId, linebot.NewTextMessage(question.Text)).Do(); err != nil {
						log.Print(err)
						continue
					}
				} else {
					welcomeTplVars := &storage.WelcomeMsgTplVars{
						UserId:   userId,
						Hostname: globalVars.Hostname,
					}
					welcomeMsgs, err := s.GetWelcomeMsgs(welcomeTplVars)
					if err != nil {
						log.Print(err)
						continue
					}
					log.Printf("User %s: sending welcome messages", userId)
					for _, welcomeMsg := range welcomeMsgs {
						// check if the message is a video one
						isVideoMsg, _ := regexp.MatchString(".*.mp4", welcomeMsg)
						if isVideoMsg {
							vidMsgRegex := regexp.MustCompile("\\|")
							vidAndPreview := vidMsgRegex.Split(welcomeMsg, -1)
							if len(vidAndPreview) != 2 {
								log.Printf("Unexpected video message format. Got: \"%s\"", welcomeMsg)
								continue
							}
							if _, err := bot.PushMessage(userId, linebot.NewVideoMessage(vidAndPreview[0], vidAndPreview[1])).Do(); err != nil {
								log.Print(err)
								continue
							}
						} else {
							if _, err = bot.PushMessage(userId, linebot.NewTextMessage(welcomeMsg)).Do(); err != nil {
								log.Print(err)
								continue
							}
						}
					}
				}
			}

			if event.Type == linebot.EventTypeMessage {
				switch message := event.Message.(type) {
				case *linebot.LocationMessage:
					err = surv.RecordGpsAnswer(userId, message.Latitude, message.Longitude, message.Address, "line")
					if err != nil {
						log.Print(err)
						break
					}
				case *linebot.TextMessage:
					answer, err := surv.RecordAnswer(userId, message.Text, "line")
					if err != nil {
						log.Print(err)
						break
					}

					if answer.QuestionId == "price" {
						err = sendPriceList(bot, s, userId)
						if err != nil {
							log.Print(err)
						}
					}

					question, err := surv.GetNextQuestion(userId, questionTplVars)
					if err != nil {
						log.Print(err)
						break
					}

					if _, err = bot.PushMessage(userId, linebot.NewTextMessage(question.Text)).Do(); err != nil {
						log.Print(err)
					}
				}
			}
		}
		return nil
	}
}<commit_msg>Send welcome messages in its own function<commit_after>package http

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"regexp"

	"github.com/VagabondDataNinjas/gizlinebot/domain"

	"github.com/labstack/echo"

	"github.com/VagabondDataNinjas/gizlinebot/storage"
	"github.com/VagabondDataNinjas/gizlinebot/survey"
	"github.com/line/line-bot-sdk-go/linebot"
)

func LineWebhookHandlerBuilder(surv *survey.Survey, s storage.Storage, bot *linebot.Client, globalVars *domain.GlobalTplVars) func(c echo.Context) error {
	return func(c echo.Context) error {
		events, err := bot.ParseRequest(c.Request())
		if err != nil {
			if err == linebot.ErrInvalidSignature {
				c.JSON(400, map[string]string{"status": "error", "err": err.Error()})
				// w.WriteHeader(400)
			} else {
				// @TODO log error
				c.JSON(500, map[string]string{"status": "error"})
			}
		}
		for _, event := range events {
			userId := event.Source.UserID
			questionTplVars := &survey.QuestionTemplateVars{
				UserId:   userId,
				Hostname: globalVars.Hostname,
			}

			eventString, err := json.Marshal(event)
			if err != nil {
				log.Printf("[err] Could not marshal event: %+v; err: %s", event, err)
			} else {
				err = s.AddRawLineEvent(string(event.Type), string(eventString))
				if err != nil {
					log.Printf("[err] Could not store event: %+v; err: %s", event, err)
				}
			}

			if event.Type == linebot.EventTypeFollow {
				log.Printf("User %s follow event", userId)
				userProfileResp, err := bot.GetProfile(userId).Do()
				if err != nil {
					log.Print(err)
					continue
				}

				err = s.AddUserProfile(userProfileResp.UserID, userProfileResp.DisplayName)
				if err != nil {
					fmt.Printf("AddUserProfile err: %s\n", err)
					continue
				}

				hasAnswers, err := s.UserHasAnswers(userId)
				if err != nil {
					log.Print(err)
					continue
				}

				if hasAnswers {
					question, err := surv.GetNextQuestion(userId, questionTplVars)
					if err != nil {
						log.Print(err)
						continue
					}
					if _, err = bot.PushMessage(userId, linebot.NewTextMessage(question.Text)).Do(); err != nil {
						log.Print(err)
						continue
					}
				} else {
					log.Printf("User %s: sending welcome messages", userId)
					welcomeTplVars := &storage.WelcomeMsgTplVars{
						UserId:   userId,
						Hostname: globalVars.Hostname,
					}
					welcomeMsgs, err := s.GetWelcomeMsgs(welcomeTplVars)
					if err != nil {
						log.Print(err)
						continue
					}
					err = sendWelcomeMsgs(welcomeMsgs, userId, bot)
					if err != nil {
						log.Print(err)
						continue
					}
				}
			}

			if event.Type == linebot.EventTypeMessage {
				switch message := event.Message.(type) {
				case *linebot.LocationMessage:
					err = surv.RecordGpsAnswer(userId, message.Latitude, message.Longitude, message.Address, "line")
					if err != nil {
						log.Print(err)
						break
					}

				case *linebot.TextMessage:
					answer, err := surv.RecordAnswer(userId, message.Text, "line")
					if err != nil {
						log.Print(err)
						break
					}

					if answer.QuestionId == "price" {
						err = sendPriceList(bot, s, userId)
						if err != nil {
							log.Print(err)
						}
					}

					question, err := surv.GetNextQuestion(userId, questionTplVars)
					if err != nil {
						log.Print(err)
						break
					}

					if _, err = bot.PushMessage(userId, linebot.NewTextMessage(question.Text)).Do(); err != nil {
						log.Print(err)
					}
				}
			}
		}
		return nil
	}
}

func sendWelcomeMsgs(welcomeMsgs []string, userId string, bot *linebot.Client) error {
	for _, welcomeMsg := range welcomeMsgs {
		// check if the message is a video one
		isVideoMsg, _ := regexp.MatchString(".*.mp4", welcomeMsg)
		if isVideoMsg {
			vidMsgRegex := regexp.MustCompile("\\|")
			vidAndPreview := vidMsgRegex.Split(welcomeMsg, -1)
			if len(vidAndPreview) != 2 {
				return errors.New(fmt.Sprintf("Unexpected video message format. Got: \"%s\"", welcomeMsg))
			}
			if _, err := bot.PushMessage(userId, linebot.NewVideoMessage(vidAndPreview[0], vidAndPreview[1])).Do(); err != nil {
				return err
			}
		} else {
			if _, err := bot.PushMessage(userId, linebot.NewTextMessage(welcomeMsg)).Do(); err != nil {
				return err
			}
		}
	}
	return nil
}
{'fraction_non_alphanumeric': 0.1359923113887554, 'fraction_numerical': 0.003363767419509851, 'mean_word_length': 2.741573033707865, 'pattern_counts': {'":': 6, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '893127', 'n_tokens_mistral': 3688, 'n_tokens_neox': 2851, 'n_words': 588}