Skip to content

Commit

Permalink
feat: add custom decoder/encoder for value content
Browse files Browse the repository at this point in the history
  • Loading branch information
tiny-craft committed Feb 3, 2024
1 parent 7faca87 commit 450e451
Show file tree
Hide file tree
Showing 18 changed files with 783 additions and 63 deletions.
46 changes: 26 additions & 20 deletions backend/services/browser_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,8 @@ func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JS
}
}

decoder := Preferences().GetDecoder()

switch data.KeyType {
case "string":
var str string
Expand Down Expand Up @@ -782,7 +784,7 @@ func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JS
Value: val,
})
if doConvert {
if dv, _, _ := convutil.ConvertTo(val, param.Decode, param.Format); dv != val {
if dv, _, _ := convutil.ConvertTo(val, param.Decode, param.Format, decoder); dv != val {
items[len(items)-1].DisplayValue = dv
}
}
Expand Down Expand Up @@ -829,7 +831,7 @@ func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JS
Value: strutil.EncodeRedisKey(loadedVal[i+1]),
})
if doConvert {
if dv, _, _ := convutil.ConvertTo(loadedVal[i+1], param.Decode, param.Format); dv != loadedVal[i+1] {
if dv, _, _ := convutil.ConvertTo(loadedVal[i+1], param.Decode, param.Format, decoder); dv != loadedVal[i+1] {
items[len(items)-1].DisplayValue = dv
}
}
Expand All @@ -854,7 +856,7 @@ func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JS
items[i/2].Key = loadedVal[i]
items[i/2].Value = strutil.EncodeRedisKey(loadedVal[i+1])
if doConvert {
if dv, _, _ := convutil.ConvertTo(loadedVal[i+1], param.Decode, param.Format); dv != loadedVal[i+1] {
if dv, _, _ := convutil.ConvertTo(loadedVal[i+1], param.Decode, param.Format, decoder); dv != loadedVal[i+1] {
items[i/2].DisplayValue = dv
}
}
Expand Down Expand Up @@ -899,7 +901,7 @@ func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JS
Value: val,
})
if doConvert {
if dv, _, _ := convutil.ConvertTo(val, param.Decode, param.Format); dv != val {
if dv, _, _ := convutil.ConvertTo(val, param.Decode, param.Format, decoder); dv != val {
items[len(items)-1].DisplayValue = dv
}
}
Expand All @@ -919,7 +921,7 @@ func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JS
for i, val := range loadedKey {
items[i].Value = val
if doConvert {
if dv, _, _ := convutil.ConvertTo(val, param.Decode, param.Format); dv != val {
if dv, _, _ := convutil.ConvertTo(val, param.Decode, param.Format, decoder); dv != val {
items[i].DisplayValue = dv
}
}
Expand Down Expand Up @@ -967,7 +969,7 @@ func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JS
Score: score,
})
if doConvert {
if dv, _, _ := convutil.ConvertTo(loadedVal[i], param.Decode, param.Format); dv != loadedVal[i] {
if dv, _, _ := convutil.ConvertTo(loadedVal[i], param.Decode, param.Format, decoder); dv != loadedVal[i] {
items[len(items)-1].DisplayValue = dv
}
}
Expand Down Expand Up @@ -1001,7 +1003,7 @@ func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JS
Value: val,
})
if doConvert {
if dv, _, _ := convutil.ConvertTo(val, param.Decode, param.Format); dv != val {
if dv, _, _ := convutil.ConvertTo(val, param.Decode, param.Format, decoder); dv != val {
items[len(items)-1].DisplayValue = dv
}
}
Expand Down Expand Up @@ -1062,7 +1064,7 @@ func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JS
if vb, merr := json.Marshal(msg.Values); merr != nil {
it.DisplayValue = "{}"
} else {
it.DisplayValue, _, _ = convutil.ConvertTo(string(vb), types.DECODE_NONE, types.FORMAT_JSON)
it.DisplayValue, _, _ = convutil.ConvertTo(string(vb), types.DECODE_NONE, types.FORMAT_JSON, decoder)
}
if doFilter && !strings.Contains(it.DisplayValue, param.MatchPattern) {
continue
Expand Down Expand Up @@ -1096,7 +1098,7 @@ func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JS
// blank format indicate auto format
func (b *browserService) ConvertValue(value any, decode, format string) (resp types.JSResp) {
str := strutil.DecodeRedisKey(value)
value, decode, format = convutil.ConvertTo(str, decode, format)
value, decode, format = convutil.ConvertTo(str, decode, format, Preferences().GetDecoder())
resp.Success = true
resp.Data = map[string]any{
"value": value,
Expand Down Expand Up @@ -1139,7 +1141,7 @@ func (b *browserService) SetKeyValue(param types.SetKeyParam) (resp types.JSResp
return
} else {
var saveStr string
if saveStr, err = convutil.SaveAs(str, param.Format, param.Decode); err != nil {
if saveStr, err = convutil.SaveAs(str, param.Format, param.Decode, Preferences().GetDecoder()); err != nil {
resp.Msg = fmt.Sprintf(`save to type "%s" fail: %s`, param.Format, err.Error())
return
}
Expand Down Expand Up @@ -1250,12 +1252,13 @@ func (b *browserService) SetHashValue(param types.SetHashParam) (resp types.JSRe
key := strutil.DecodeRedisKey(param.Key)
str := strutil.DecodeRedisKey(param.Value)
var saveStr, displayStr string
if saveStr, err = convutil.SaveAs(str, param.Format, param.Decode); err != nil {
decoder := Preferences().GetDecoder()
if saveStr, err = convutil.SaveAs(str, param.Format, param.Decode, decoder); err != nil {
resp.Msg = fmt.Sprintf(`save to type "%s" fail: %s`, param.Format, err.Error())
return
}
if len(param.RetDecode) > 0 && len(param.RetFormat) > 0 {
displayStr, _, _ = convutil.ConvertTo(saveStr, param.RetDecode, param.RetFormat)
displayStr, _, _ = convutil.ConvertTo(saveStr, param.RetDecode, param.RetFormat, decoder)
}
var updated, added, removed []types.HashEntryItem
var replaced []types.HashReplaceItem
Expand Down Expand Up @@ -1473,7 +1476,8 @@ func (b *browserService) SetListItem(param types.SetListParam) (resp types.JSRes
} else {
// replace index value
var saveStr string
if saveStr, err = convutil.SaveAs(str, param.Format, param.Decode); err != nil {
decoder := Preferences().GetDecoder()
if saveStr, err = convutil.SaveAs(str, param.Format, param.Decode, decoder); err != nil {
resp.Msg = fmt.Sprintf(`save to type "%s" fail: %s`, param.Format, err.Error())
return
}
Expand All @@ -1484,7 +1488,7 @@ func (b *browserService) SetListItem(param types.SetListParam) (resp types.JSRes
}
var displayStr string
if len(param.RetDecode) > 0 && len(param.RetFormat) > 0 {
displayStr, _, _ = convutil.ConvertTo(saveStr, param.RetDecode, param.RetFormat)
displayStr, _, _ = convutil.ConvertTo(saveStr, param.RetDecode, param.RetFormat, decoder)
}
replaced = append(replaced, types.ListReplaceItem{
Index: param.Index,
Expand Down Expand Up @@ -1574,16 +1578,17 @@ func (b *browserService) UpdateSetItem(param types.SetSetParam) (resp types.JSRe

// insert new value
str = strutil.DecodeRedisKey(param.NewValue)
decoder := Preferences().GetDecoder()
var saveStr string
if saveStr, err = convutil.SaveAs(str, param.Format, param.Decode); err != nil {
if saveStr, err = convutil.SaveAs(str, param.Format, param.Decode, decoder); err != nil {
resp.Msg = fmt.Sprintf(`save to type "%s" fail: %s`, param.Format, err.Error())
return
}
if affect, _ = client.SAdd(ctx, key, saveStr).Result(); affect > 0 {
// add new item
var displayStr string
if len(param.RetDecode) > 0 && len(param.RetFormat) > 0 {
displayStr, _, _ = convutil.ConvertTo(saveStr, param.RetDecode, param.RetFormat)
displayStr, _, _ = convutil.ConvertTo(saveStr, param.RetDecode, param.RetFormat, decoder)
}
added = append(added, types.SetEntryItem{
Value: saveStr,
Expand Down Expand Up @@ -1620,6 +1625,7 @@ func (b *browserService) UpdateZSetValue(param types.SetZSetParam) (resp types.J
var added, updated, removed []types.ZSetEntryItem
var replaced []types.ZSetReplaceItem
var affect int64
decoder := Preferences().GetDecoder()
if len(newVal) <= 0 {
// no new value, delete value
if affect, err = client.ZRem(ctx, key, val).Result(); affect > 0 {
Expand All @@ -1630,7 +1636,7 @@ func (b *browserService) UpdateZSetValue(param types.SetZSetParam) (resp types.J
}
} else {
var saveVal string
if saveVal, err = convutil.SaveAs(newVal, param.Format, param.Decode); err != nil {
if saveVal, err = convutil.SaveAs(newVal, param.Format, param.Decode, decoder); err != nil {
resp.Msg = fmt.Sprintf(`save to type "%s" fail: %s`, param.Format, err.Error())
return
}
Expand All @@ -1640,7 +1646,7 @@ func (b *browserService) UpdateZSetValue(param types.SetZSetParam) (resp types.J
Score: param.Score,
Member: saveVal,
}).Result()
displayValue, _, _ := convutil.ConvertTo(val, param.RetDecode, param.RetFormat)
displayValue, _, _ := convutil.ConvertTo(val, param.RetDecode, param.RetFormat, decoder)
if affect > 0 {
// add new item
added = append(added, types.ZSetEntryItem{
Expand Down Expand Up @@ -1668,7 +1674,7 @@ func (b *browserService) UpdateZSetValue(param types.SetZSetParam) (resp types.J
Score: param.Score,
Member: saveVal,
}).Result()
displayValue, _, _ := convutil.ConvertTo(saveVal, param.RetDecode, param.RetFormat)
displayValue, _, _ := convutil.ConvertTo(saveVal, param.RetDecode, param.RetFormat, decoder)
if affect <= 0 {
// no new value added, just update exists item
removed = append(removed, types.ZSetEntryItem{
Expand Down Expand Up @@ -1794,7 +1800,7 @@ func (b *browserService) AddStreamValue(server string, db int, k any, ID string,
updateValues[fieldItems[i].(string)] = fieldItems[i+1]
}
vb, _ := json.Marshal(updateValues)
displayValue, _, _ := convutil.ConvertTo(string(vb), types.DECODE_NONE, types.FORMAT_JSON)
displayValue, _, _ := convutil.ConvertTo(string(vb), types.DECODE_NONE, types.FORMAT_JSON, Preferences().GetDecoder())

resp.Success = true
resp.Data = struct {
Expand Down
20 changes: 20 additions & 0 deletions backend/services/preferences_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ import (
storage2 "tinyrdm/backend/storage"
"tinyrdm/backend/types"
"tinyrdm/backend/utils/coll"
convutil "tinyrdm/backend/utils/convert"
sliceutil "tinyrdm/backend/utils/slice"
)

type preferencesService struct {
pref *storage2.PreferencesStorage
clientVersion string
customDecoder []convutil.CmdConvert
}

var preferences *preferencesService
Expand Down Expand Up @@ -182,6 +185,23 @@ func (p *preferencesService) GetScanSize() int {
return size
}

func (p *preferencesService) GetDecoder() []convutil.CmdConvert {
data := p.pref.GetPreferences()
return sliceutil.FilterMap(data.Decoder, func(i int) (convutil.CmdConvert, bool) {
//if !data.Decoder[i].Enable {
// return convutil.CmdConvert{}, false
//}
return convutil.CmdConvert{
Name: data.Decoder[i].Name,
Auto: data.Decoder[i].Auto,
DecodePath: data.Decoder[i].DecodePath,
DecodeArgs: data.Decoder[i].DecodeArgs,
EncodePath: data.Decoder[i].EncodePath,
EncodeArgs: data.Decoder[i].EncodeArgs,
}, true
})
}

type latestRelease struct {
Name string `json:"name"`
TagName string `json:"tag_name"`
Expand Down
20 changes: 16 additions & 4 deletions backend/types/preferences.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package types
import "tinyrdm/backend/consts"

type Preferences struct {
Behavior PreferencesBehavior `json:"behavior" yaml:"behavior"`
General PreferencesGeneral `json:"general" yaml:"general"`
Editor PreferencesEditor `json:"editor" yaml:"editor"`
Cli PreferencesCli `json:"cli" yaml:"cli"`
Behavior PreferencesBehavior `json:"behavior" yaml:"behavior"`
General PreferencesGeneral `json:"general" yaml:"general"`
Editor PreferencesEditor `json:"editor" yaml:"editor"`
Cli PreferencesCli `json:"cli" yaml:"cli"`
Decoder []PreferencesDecoder `json:"decoder" yaml:"decoder,omitempty"`
}

func NewPreferences() Preferences {
Expand All @@ -33,6 +34,7 @@ func NewPreferences() Preferences {
FontSize: consts.DEFAULT_FONT_SIZE,
CursorStyle: "block",
},
Decoder: []PreferencesDecoder{},
}
}

Expand Down Expand Up @@ -72,3 +74,13 @@ type PreferencesCli struct {
FontSize int `json:"fontSize" yaml:"font_size"`
CursorStyle string `json:"cursorStyle" yaml:"cursor_style,omitempty"`
}

type PreferencesDecoder struct {
Name string `json:"name" yaml:"name"`
Enable bool `json:"enable" yaml:"enable"`
Auto bool `json:"auto" yaml:"auto"`
DecodePath string `json:"decodePath" yaml:"decode_path"`
DecodeArgs []string `json:"decodeArgs" yaml:"decode_args,omitempty"`
EncodePath string `json:"encodePath" yaml:"encode_path"`
EncodeArgs []string `json:"encodeArgs" yaml:"encode_args,omitempty"`
}
75 changes: 75 additions & 0 deletions backend/utils/convert/cmd_convert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package convutil

import (
"encoding/base64"
"os/exec"
"strings"
sliceutil "tinyrdm/backend/utils/slice"
)

type CmdConvert struct {
Name string
Auto bool
DecodePath string
DecodeArgs []string
EncodePath string
EncodeArgs []string
}

const replaceholder = "{VALUE}"

func (c CmdConvert) Encode(str string) (string, bool) {
base64Content := base64.StdEncoding.EncodeToString([]byte(str))
var containHolder bool
args := sliceutil.Map(c.EncodeArgs, func(i int) string {
arg := strings.TrimSpace(c.EncodeArgs[i])
if strings.Contains(arg, replaceholder) {
arg = strings.ReplaceAll(arg, replaceholder, base64Content)
containHolder = true
}
return arg
})
if len(args) <= 0 || !containHolder {
args = append(args, base64Content)
}
cmd := exec.Command(c.EncodePath, args...)
output, err := cmd.Output()
if err != nil || len(output) <= 0 || string(output) == "[RDM-ERROR]" {
return str, false
}

outputContent := make([]byte, base64.StdEncoding.DecodedLen(len(output)))
n, err := base64.StdEncoding.Decode(outputContent, output)
if err != nil {
return str, false
}
return string(outputContent[:n]), true
}

func (c CmdConvert) Decode(str string) (string, bool) {
base64Content := base64.StdEncoding.EncodeToString([]byte(str))
var containHolder bool
args := sliceutil.Map(c.DecodeArgs, func(i int) string {
arg := strings.TrimSpace(c.DecodeArgs[i])
if strings.Contains(arg, replaceholder) {
arg = strings.ReplaceAll(arg, replaceholder, base64Content)
containHolder = true
}
return arg
})
if len(args) <= 0 || !containHolder {
args = append(args, base64Content)
}
cmd := exec.Command(c.DecodePath, args...)
output, err := cmd.Output()
if err != nil || len(output) <= 0 || string(output) == "[RDM-ERROR]" {
return str, false
}

outputContent := make([]byte, base64.StdEncoding.DecodedLen(len(output)))
n, err := base64.StdEncoding.Decode(outputContent, output)
if err != nil {
return str, false
}
return string(outputContent[:n]), true
}
Loading

0 comments on commit 450e451

Please sign in to comment.