github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/app/slashcommands/command_custom_status.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package slashcommands
     5  
     6  import (
     7  	"regexp"
     8  	"strings"
     9  	"unicode/utf8"
    10  
    11  	"github.com/masterhung0112/hk_server/v5/app"
    12  	"github.com/masterhung0112/hk_server/v5/app/request"
    13  	"github.com/masterhung0112/hk_server/v5/model"
    14  	"github.com/masterhung0112/hk_server/v5/shared/i18n"
    15  	"github.com/masterhung0112/hk_server/v5/shared/mlog"
    16  )
    17  
    18  type CustomStatusProvider struct {
    19  }
    20  
    21  const (
    22  	CmdCustomStatus      = app.CmdCustomStatusTrigger
    23  	CmdCustomStatusClear = "clear"
    24  )
    25  
    26  func init() {
    27  	app.RegisterCommandProvider(&CustomStatusProvider{})
    28  }
    29  
    30  func (*CustomStatusProvider) GetTrigger() string {
    31  	return CmdCustomStatus
    32  }
    33  
    34  func (*CustomStatusProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Command {
    35  	return &model.Command{
    36  		Trigger:          CmdCustomStatus,
    37  		AutoComplete:     true,
    38  		AutoCompleteDesc: T("api.command_custom_status.desc"),
    39  		AutoCompleteHint: T("api.command_custom_status.hint"),
    40  		DisplayName:      T("api.command_custom_status.name"),
    41  	}
    42  }
    43  
    44  func (*CustomStatusProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
    45  	if !*a.Config().TeamSettings.EnableCustomUserStatuses {
    46  		return nil
    47  	}
    48  
    49  	message = strings.TrimSpace(message)
    50  	if message == CmdCustomStatusClear {
    51  		if err := a.RemoveCustomStatus(args.UserId); err != nil {
    52  			mlog.Debug(err.Error())
    53  			return &model.CommandResponse{Text: args.T("api.command_custom_status.clear.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
    54  		}
    55  
    56  		return &model.CommandResponse{
    57  			ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL,
    58  			Text:         args.T("api.command_custom_status.clear.success"),
    59  		}
    60  	}
    61  
    62  	customStatus := GetCustomStatus(message)
    63  	customStatus.PreSave()
    64  	if err := a.SetCustomStatus(args.UserId, customStatus); err != nil {
    65  		mlog.Debug(err.Error())
    66  		return &model.CommandResponse{Text: args.T("api.command_custom_status.app_error"), ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL}
    67  	}
    68  
    69  	return &model.CommandResponse{
    70  		ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL,
    71  		Text: args.T("api.command_custom_status.success", map[string]interface{}{
    72  			"EmojiName":     ":" + customStatus.Emoji + ":",
    73  			"StatusMessage": customStatus.Text,
    74  		}),
    75  	}
    76  }
    77  
    78  func GetCustomStatus(message string) *model.CustomStatus {
    79  	customStatus := &model.CustomStatus{
    80  		Emoji: model.DefaultCustomStatusEmoji,
    81  		Text:  message,
    82  	}
    83  
    84  	firstEmojiLocations := model.EMOJI_PATTERN.FindIndex([]byte(message))
    85  	if len(firstEmojiLocations) > 0 && firstEmojiLocations[0] == 0 {
    86  		// emoji found at starting index
    87  		customStatus.Emoji = message[firstEmojiLocations[0]+1 : firstEmojiLocations[1]-1]
    88  		customStatus.Text = strings.TrimSpace(message[firstEmojiLocations[1]:])
    89  		return customStatus
    90  	}
    91  
    92  	if message == "" {
    93  		return customStatus
    94  	}
    95  
    96  	spaceSeparatedMessage := strings.Fields(message)
    97  	if len(spaceSeparatedMessage) == 0 {
    98  		return customStatus
    99  	}
   100  
   101  	emojiString := spaceSeparatedMessage[0]
   102  	var unicode []string
   103  	for utf8.RuneCountInString(emojiString) >= 1 {
   104  		codepoint, size := utf8.DecodeRuneInString(emojiString)
   105  		code := model.RuneToHexadecimalString(codepoint)
   106  		unicode = append(unicode, code)
   107  		emojiString = emojiString[size:]
   108  	}
   109  
   110  	unicodeString := removeUnicodeSkinTone(strings.Join(unicode, "-"))
   111  	emoji, count := model.GetEmojiNameFromUnicode(unicodeString)
   112  	if count > 0 {
   113  		customStatus.Emoji = emoji
   114  		textString := strings.Join(spaceSeparatedMessage[1:], " ")
   115  		customStatus.Text = strings.TrimSpace(textString)
   116  	}
   117  
   118  	return customStatus
   119  }
   120  
   121  func removeUnicodeSkinTone(unicodeString string) string {
   122  	skinToneDetectorRegex := regexp.MustCompile("-(1f3fb|1f3fc|1f3fd|1f3fe|1f3ff)")
   123  	skinToneLocations := skinToneDetectorRegex.FindIndex([]byte(unicodeString))
   124  
   125  	if len(skinToneLocations) == 0 {
   126  		return unicodeString
   127  	}
   128  	if _, count := model.GetEmojiNameFromUnicode(unicodeString); count > 0 {
   129  		return unicodeString
   130  	}
   131  	unicodeWithRemovedSkinTone := unicodeString[:skinToneLocations[0]] + unicodeString[skinToneLocations[1]:]
   132  	unicodeWithVariationSelector := unicodeString[:skinToneLocations[0]] + "-fe0f" + unicodeString[skinToneLocations[1]:]
   133  	if _, count := model.GetEmojiNameFromUnicode(unicodeWithRemovedSkinTone); count > 0 {
   134  		unicodeString = unicodeWithRemovedSkinTone
   135  	} else if _, count := model.GetEmojiNameFromUnicode(unicodeWithVariationSelector); count > 0 {
   136  		unicodeString = unicodeWithVariationSelector
   137  	}
   138  
   139  	return unicodeString
   140  }