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 }