func (b *Bot) EditDeadline(event tgbotapi.Update) (string, error) {
	isAdmin, err := b.senderIsAdminInChannel(event.Message.From.UserName, event.Message.Chat.ID)
	if err != nil {
		return "", err
	}
	if !isAdmin {
		return "", fmt.Errorf("user not admin")
	}
	deadline := event.Message.CommandArguments()
	group, err := b.db.FindGroup(event.Message.Chat.ID)
	if err != nil {
		return "", err
	}
	localizer := i18n.NewLocalizer(b.bundle, group.Language)
	if strings.TrimSpace(deadline) == "" {
		group.StandupDeadline = ""
		gr, err := b.db.UpdateGroup(group)
		if err != nil {
			return localizer.Localize(&i18n.LocalizeConfig{
				DefaultMessage: &i18n.Message{
					ID:    "failedRemoveStandupDeadline",
					Other: "Could not remove standup deadline",
				},
			})
		}
		for _, v := range b.teams {
			if v.Group.ID == gr.ID {
				v.Group.StandupDeadline = gr.StandupDeadline
			}
		}
		return localizer.Localize(&i18n.LocalizeConfig{
			DefaultMessage: &i18n.Message{
				ID:    "removeStandupDeadline",
				Other: "Standup deadline removed",
			},
		})
	}
	group.StandupDeadline = deadline
	gr, err := b.db.UpdateGroup(group)
	if err != nil {
		return localizer.Localize(&i18n.LocalizeConfig{
			DefaultMessage: &i18n.Message{
				ID:    "failedUpdateStandupDeadline",
				Other: "Could not edit standup deadline",
			},
		})
	}
	for _, v := range b.teams {
		if v.Group.ID == gr.ID {
			v.Group.StandupDeadline = gr.StandupDeadline
		}
	}
	return localizer.Localize(&i18n.LocalizeConfig{
		DefaultMessage: &i18n.Message{
			ID:    "updateStandupDeadline",
			Other: "Edited standup deadline, new deadline is {{.Deadline}}",
		},
		TemplateData: map[string]interface{}{
			"Deadline": deadline,
		},
	})
}
EditDeadline modifies standup time
package bot
import (
	"fmt"
	"strings"
	"time"
	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
	"github.com/maddevsio/mad-telegram-standup-bot/model"
	"github.com/nicksnyder/go-i18n/v2/i18n"
	log "github.com/sirupsen/logrus"
)
type internInfo struct {
	internName       string
	timeSinceAdded   string
	missedStandups   string
	daysOnInternship int
}
var Test bool
func (b *Bot) HandleCommand(event tgbotapi.Update) (err error) {
	if event.Message == nil {
		event.Message = event.EditedMessage
	}
	var message string
	switch event.Message.Command() {
	case "help":
		message, err = b.Help(event)
		if err != nil {
			log.WithFields(log.Fields{"error": err, "event": event}).Error("Help failed")
		}
	case "join":
		message, err = b.JoinStandupers(event)
		if err != nil {
			log.WithFields(log.Fields{"error": err, "event": event}).Error("JoinStandupers failed")
		}
	case "show":
		message, err = b.Show(event)
		if err != nil {
			log.WithFields(log.Fields{"error": err, "event": event}).Error("Show failed")
		}
	case "leave":
		message, err = b.LeaveStandupers(event)
		if err != nil {
			log.WithFields(log.Fields{"error": err, "event": event}).Error("LeaveStandupers failed")
		}
	case "edit_deadline":
		message, err = b.EditDeadline(event)
		if err != nil {
			log.WithFields(log.Fields{"error": err, "event": event}).Error("EditDeadline failed")
		}
	case "update_onbording_message":
		message, err = b.UpdateOnbordingMessage(event)
		if err != nil {
			log.WithFields(log.Fields{"error": err, "event": event}).Error("UpdateOnbordingMessage failed")
		}
	case "update_group_language":
		message, err = b.UpdateGroupLanguage(event)
		if err != nil {
			log.WithFields(log.Fields{"error": err, "event": event}).Error("UpdateGroupLanguage failed")
		}
	case "change_submission_days":
		message, err = b.ChangeSubmissionDays(event)
		if err != nil {
			log.WithFields(log.Fields{"error": err, "event": event}).Error("ChangeSubmissionDays failed")
		}
	case "group_tz":
		message, err = b.ChangeGroupTimeZone(event)
		if err != nil {
			log.WithFields(log.Fields{"error": err, "event": event}).Error("ChangeGroupTimeZone failed")
		}
	case "tz":
		message, err = b.ChangeUserTimeZone(event)
		if err != nil {
			log.WithFields(log.Fields{"error": err, "event": event}).Error("ChangeUserTimeZone failed")
		}
	default:
		message = "I do not know this command..."
		log.WithFields(log.Fields{"event": event}).Warning("Unrecognized command")
	}
	if err != nil {
		return err
	}
	msg := tgbotapi.NewMessage(event.Message.Chat.ID, message)
	_, err = b.tgAPI.Send(msg)
	return err
}
func (b *Bot) Help(event tgbotapi.Update) (string, error) {
	group, err := b.db.FindGroup(event.Message.Chat.ID)
	if err != nil {
		return "", err
	}
	localizer := i18n.NewLocalizer(b.bundle, group.Language)
	helpText, err := localizer.Localize(&i18n.LocalizeConfig{
		DefaultMessage: &i18n.Message{
			ID:    "helpText",
			Other: `In order to submit a standup, tag me and write a message with keywords. Direct message me to see the list of keywords needed. Loking forward for your standups! Message @anatoliyfedorenko in case of any unexpected behaviour, submit issues to https: 
		},
	})
	return helpText, err
}
func (b *Bot) JoinStandupers(event tgbotapi.Update) (string, error) {
	group, err := b.db.FindGroup(event.Message.Chat.ID)
	if err != nil {
		return "", err
	}
	localizer := i18n.NewLocalizer(b.bundle, group.Language)
	standuper, err := b.db.FindStanduper(event.Message.From.ID, event.Message.Chat.ID)  
	if err == nil {
		switch standuper.Status {
		case "active":
			return localizer.Localize(&i18n.LocalizeConfig{
				DefaultMessage: &i18n.Message{
					ID:    "youAlreadyStandup",
					Other: "You already a part of standup team",
				},
			})
		case "paused", "deleted":
			standuper.Status = "active"
			_, err := b.db.UpdateStanduper(standuper)
			if err != nil {
				return "", err
			}
			return localizer.Localize(&i18n.LocalizeConfig{
				DefaultMessage: &i18n.Message{
					ID:    "welcomeBack",
					Other: "Welcome back! Glad to see you again, and looking forward to your standups",
				},
			})
		}
	}
	_, err = b.db.CreateStanduper(&model.Standuper{
		Created:      time.Now(),
		Status:       "active",
		UserID:       event.Message.From.ID,
		Username:     event.Message.From.UserName,
		ChatID:       event.Message.Chat.ID,
		LanguageCode: event.Message.From.LanguageCode,
		TZ:           "Asia/Bishkek",  
	})
	if err != nil {
		log.Error("CreateStanduper failed: ", err)
		return localizer.Localize(&i18n.LocalizeConfig{
			DefaultMessage: &i18n.Message{
				ID:    "createStanduperFailed",
				Other: "Could not add you to standup team",
			},
		})
	}
	if group.StandupDeadline == "" {
		return localizer.Localize(&i18n.LocalizeConfig{
			DefaultMessage: &i18n.Message{
				ID:    "welcomeNoDedline",
				Other: "Welcome to the standup team, no standup deadline has been setup yet",
			},
		})
	}
	return localizer.Localize(&i18n.LocalizeConfig{
		DefaultMessage: &i18n.Message{
			ID:    "welcomeWithDedline",
			Other: "Welcome to the standup team, please, submit your standups no later than {{.Deadline}}",
		},
		TemplateData: map[string]interface{}{
			"Deadline": group.StandupDeadline,
		},
	})
}
func (b *Bot) Show(event tgbotapi.Update) (string, error) {
	standupers, err := b.db.ListChatStandupers(event.Message.Chat.ID)
	if err != nil {
		return "", err
	}
	group, err := b.db.FindGroup(event.Message.Chat.ID)
	if err != nil {
		return "", err
	}
	message := b.prepareShowMessage(standupers, group)
	return message, nil
}
func (b *Bot) prepareShowMessage(standupers []model.Standuper, group *model.Group) string {
	localizer := i18n.NewLocalizer(b.bundle, group.Language)
	var internsInfo string
	var interns []internInfo
	for _, standuper := range standupers {
		var info internInfo
		info.internName = "@" + standuper.Username + ", "
		if standuper.Username == "" {
			info.internName = fmt.Sprintf("[stranger](tg://user?id=%v)", standuper.UserID)
		}
		daysOnInternship := time.Now().UTC().Sub(standuper.Created).Hours() / 24
		if int(daysOnInternship) == 0 {
			daysOnInternship = 1.0
		}
		internshipDuration, err := localizer.Localize(&i18n.LocalizeConfig{
			DefaultMessage: &i18n.Message{
				ID:    "presenceDuration",
				One:   "{{.Days}} day in the project, ",
				Two:   "{{.Days}} days in the project, ",
				Few:   "{{.Days}} days in the project, ",
				Many:  "{{.Days}} days in the project, ",
				Other: "{{.Days}} days in the project, ",
			},
			PluralCount: int(daysOnInternship),
			TemplateData: map[string]interface{}{
				"Days": int(daysOnInternship),
			},
		})
		if err != nil {
			log.Error(err)
		}
		info.timeSinceAdded = internshipDuration
		info.daysOnInternship = int(daysOnInternship)
		interns = append(interns, info)
	}
	interns = sortInterns(interns)
	for _, info := range interns {
		internsInfo += info.internName + info.timeSinceAdded + "\n"
	}
	showStandupers, err := localizer.Localize(&i18n.LocalizeConfig{
		DefaultMessage: &i18n.Message{
			ID:    "showStandupers",
			Other: "Standupers:",
		},
	})
	if err != nil {
		log.Error(err)
	}
	if len(internsInfo) == 0 {
		showStandupers, err = localizer.Localize(&i18n.LocalizeConfig{
			DefaultMessage: &i18n.Message{
				ID:    "showNoStandupers",
				Other: "No standupers in the team, /join to start standuping",
			},
		})
		if err != nil {
			log.Error(err)
		}
	}
	standupersInfo := showStandupers + "\n" + internsInfo
	var standupDeadlineInfo string
	if group.StandupDeadline == "" {
		noStandupDeadline, err := localizer.Localize(&i18n.LocalizeConfig{
			DefaultMessage: &i18n.Message{
				ID:    "noStandupDeadline",
				Other: "Standup deadline is not set",
			},
		})
		if err != nil {
			log.Error(err)
		}
		standupDeadlineInfo = noStandupDeadline
	} else {
		standupDeadline, err := localizer.Localize(&i18n.LocalizeConfig{
			DefaultMessage: &i18n.Message{
				ID:    "standupDeadline",
				Other: "Standup deadline set at {{.Deadline}} on {{.Weekdays}}",
			},
			TemplateData: map[string]interface{}{
				"Deadline": group.StandupDeadline,
				"Weekdays": group.SubmissionDays,
			},
		})
		if err != nil {
			log.Error(err)
		}
		standupDeadlineInfo = standupDeadline
	}
	return standupersInfo + "\n" + standupDeadlineInfo
}
func sortInterns(entries []internInfo) []internInfo {
	var members []internInfo
	for i := 0; i < len(entries); i++ {
		if !sweep(entries, i) {
			break
		}
	}
	for _, item := range entries {
		members = append(members, item)
	}
	return members
}
func sweep(entries []internInfo, prevPasses int) bool {
	var N = len(entries)
	var didSwap = false
	var firstIndex = 0
	var secondIndex = 1
	for secondIndex < (N - prevPasses) {
		var firstItem = entries[firstIndex]
		var secondItem = entries[secondIndex]
		if entries[firstIndex].daysOnInternship < entries[secondIndex].daysOnInternship {
			entries[firstIndex] = secondItem
			entries[secondIndex] = firstItem
			didSwap = true
		}
		firstIndex++
		secondIndex++
	}
	return didSwap
}
func (b *Bot) LeaveStandupers(event tgbotapi.Update) (string, error) {
	group, err := b.db.FindGroup(event.Message.Chat.ID)
	if err != nil {
		return "", err
	}
	localizer := i18n.NewLocalizer(b.bundle, group.Language)
	standuper, err := b.db.FindStanduper(event.Message.From.ID, event.Message.Chat.ID)  
	if err != nil {
		return localizer.Localize(&i18n.LocalizeConfig{
			DefaultMessage: &i18n.Message{
				ID:    "notStanduper",
				Other: "You do not standup yet",
			},
		})
	}
	standuper.Status = "paused"
	_, err = b.db.UpdateStanduper(standuper)
	if err != nil {
		return localizer.Localize(&i18n.LocalizeConfig{
			DefaultMessage: &i18n.Message{
				ID:    "failedLeaveStanupers",
				Other: "Could not remove you from standup team",
			},
		})
	}
	threads, err := b.db.ListNotificationsThread(event.Message.Chat.ID)
	if err != nil {
		log.Error("ListNotificationsThread failed: ", err)
	}
	for _, thr := range threads {
		if thr.Username != standuper.Username {
			continue
		}
		if err := b.db.DeleteNotificationThread(thr.ID); err != nil {
			log.Error("DeleteNotificationThread failed: ", err)
		}
	}
	return localizer.Localize(&i18n.LocalizeConfig{
		DefaultMessage: &i18n.Message{
			ID:    "leaveStanupers",
			Other: "You no longer have to submit standups, thanks for all your standups and messages",
		},
	})
}