Skip to content

Commit

Permalink
feat: implement scan for more information and optimize output
Browse files Browse the repository at this point in the history
  • Loading branch information
wux1an committed May 26, 2023
1 parent 77fc612 commit b712209
Show file tree
Hide file tree
Showing 7 changed files with 432 additions and 16 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

**Todo:**

- [ ] scan more information
- [x] scan more information (need networking)
- [x] json beautify
- [ ] javascript beautify
- [ ] html beautify
Expand Down
180 changes: 180 additions & 0 deletions cmd/scan-tui.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
package cmd

import (
"fmt"
"github.com/charmbracelet/bubbles/help"
"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/progress"
"github.com/charmbracelet/bubbles/table"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/fatih/color"
"regexp"
"strconv"
"strings"
"wxapkg/util"
)

var baseStyle = lipgloss.NewStyle().
BorderStyle(lipgloss.ThickBorder()).
BorderForeground(lipgloss.Color("240"))

type scanTui struct {
table table.Model
raw []util.WxidInfo
selected *util.WxidInfo
progress progress.Model
}

func newScanTui(wxidInfo []util.WxidInfo) *scanTui {
var prog = progress.New(progress.WithScaledGradient("#FF7CCB", "#FDFF8C"))

var rows = make([]table.Row, 0, len(wxidInfo))
for _, info := range wxidInfo {
rows = append(rows, []string{
info.Nickname,
info.PrincipalName,
info.Description,
})
}

var title = color.New(color.FgMagenta, color.Bold).Sprint
columns := []table.Column{
{Title: title("Name"), Width: 20},
{Title: title("Developer"), Width: 30},
{Title: title("Description"), Width: 40},
}
prog.Width = 0
for _, c := range columns {
prog.Width += c.Width
}
prog.Width += len(columns) * 2

var height = 10
if len(rows) < height {
height = len(rows)
}
t := table.New(
table.WithColumns(columns),
table.WithRows(rows),
table.WithFocused(true),
table.WithHeight(height),
)
t.Rows()

s := table.DefaultStyles()
s.Header = s.Header.
BorderStyle(lipgloss.NormalBorder()).
BorderForeground(lipgloss.Color("240")).
BorderBottom(true).
Bold(false)
s.Selected = s.Selected.
Foreground(lipgloss.Color("229")).
Background(lipgloss.Color("57")).
Bold(false)
t.SetStyles(s)

return &scanTui{
table: t,
raw: wxidInfo,
progress: prog,
}
}

func (s *scanTui) Init() tea.Cmd {
return nil
}

func (s *scanTui) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmd tea.Cmd
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "esc":
if s.table.Focused() {
s.table.Blur()
} else {
s.table.Focus()
}
case "q", "ctrl+c":
return s, tea.Quit
case "enter":
s.selected = &s.raw[s.table.Cursor()]
return s, tea.Quit
}
}
s.table, cmd = s.table.Update(msg)
return s, cmd
}

func (s *scanTui) renderProgress() string {
var prog = s.progress.ViewAs(float64(s.table.Cursor()+1) / float64(len(s.raw)))
var p = regexp.MustCompile(`\d{1,3}%`).FindString(prog)
format := "%" + strconv.Itoa(len(p)) + "s"
newStr := fmt.Sprintf(format, fmt.Sprintf("%d/%d", s.table.Cursor()+1, len(s.raw)))
prog = strings.Replace(prog, p, newStr, 1)

return prog
}

func (s *scanTui) renderDetail() string {
var result = ""

var info = s.raw[s.table.Cursor()]

var link = color.New(color.Italic, color.Underline).Sprint
var title = color.New(color.FgMagenta, color.Bold).Sprint
var content = color.CyanString

if info.Error != "" {
result += title(" error: ") + color.RedString(info.Error) + "\n"
}

if info.Error == "" {
result += title(" wxid: ") + content(info.Wxid) + "\n"
result += title(" Name: ") + content(info.Nickname) + "\n"
result += title(" Developer: ") + content(info.PrincipalName) + "\n"
result += title(" Description: ") + content(info.Description) + "\n"
}

result += title(" Location: ") + content(link(info.Location)) + "\n"

if info.Error == "" {
result += title(" Avatar: ") + content(link(info.Avatar)) + "\n"
}

result += title(" All information see '") + content(".\\"+util.CachePath) + title("'")

return result
}

func (s *scanTui) renderHelp() string {
return help.New().ShortHelpView([]key.Binding{
key.NewBinding(
key.WithKeys("enter"),
key.WithHelp("enter", "unpack"),
),
key.NewBinding(
key.WithKeys("up", "k"),
key.WithHelp("↑/k", "move up"),
),
key.NewBinding(
key.WithKeys("down", "j"),
key.WithHelp("↓/j", "move down"),
),
key.NewBinding(
key.WithKeys("q", "ctrl+c"),
key.WithHelp("q", "exit"),
),
})
}

func (s *scanTui) View() string {
var result = ""
result += "" + s.renderProgress() + "\n"
result += baseStyle.Render(s.table.View()) + "\n"
result += s.renderDetail() + "\n"
result += "\n " + s.renderHelp() + "\n"

return result
}
31 changes: 29 additions & 2 deletions cmd/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package cmd

import (
"fmt"
tea "github.com/charmbracelet/bubbletea"
"github.com/fatih/color"
"github.com/spf13/cobra"
"os"
"path/filepath"
"regexp"
"wxapkg/util"
)

var scanCmd = &cobra.Command{
Expand All @@ -27,14 +29,39 @@ var scanCmd = &cobra.Command{
return
}

var wxidInfos = make([]util.WxidInfo, 0, len(files))
for _, file := range files {
if !file.IsDir() || !regAppId.MatchString(file.Name()) {
continue
}

var id = regAppId.FindStringSubmatch(file.Name())[1]
fmt.Printf("%s %s\n", color.GreenString(id), color.CyanString(filepath.Join(root, file.Name()))) // todo scan file
var wxid = regAppId.FindStringSubmatch(file.Name())[1]
info, err := util.WxidQuery.Query(wxid)
info.Location = filepath.Join(root, file.Name())
info.Wxid = wxid
if err != nil {
info.Error = fmt.Sprintf("%v", err)
}

wxidInfos = append(wxidInfos, info)
}

var tui = newScanTui(wxidInfos)
if _, err := tea.NewProgram(tui, tea.WithAltScreen()).Run(); err != nil {
color.Red("Error running program: %v", err)
os.Exit(1)
}

if tui.selected == nil {
return
}

output := tui.selected.Wxid
_ = unpackCmd.Flags().Set("root", tui.selected.Location)
_ = unpackCmd.Flags().Set("output", output)
detailFilePath := filepath.Join(output, "detail.json")
unpackCmd.Run(unpackCmd, []string{"detailFilePath", detailFilePath})
_ = os.WriteFile(detailFilePath, []byte(tui.selected.Json()), 0600)
},
}

Expand Down
33 changes: 25 additions & 8 deletions cmd/unpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ import (
"os"
"path/filepath"
"regexp"
"sort"
"sync"
"wxapkg/util"
)

var logger = color.New()
var programName = filepath.Base(os.Args[0])
var unpackCmd = &cobra.Command{
Use: "unpack",
Expand All @@ -38,6 +38,8 @@ var unpackCmd = &cobra.Command{
dirs, err := os.ReadDir(root)
util.Fatal(err)

color.Cyan("[+] unpack root '%s' with %d threads\n", root, thread)

var allFileCount = 0
for _, subDir := range dirs {
subOutput := filepath.Join(output, subDir.Name())
Expand All @@ -51,14 +53,29 @@ var unpackCmd = &cobra.Command{
util.Fatal(err)
allFileCount += fileCount

logger.Println(color.YellowString("\r[+] unpacked %5d files from '%s'", fileCount, file))
rel, _ := filepath.Rel(filepath.Dir(root), file)
color.Yellow("\r[+] unpacked %5d files from '%s'", fileCount, rel)
}
}

logger.Println(color.CyanString("[+] all %d files saved to '%s'", allFileCount, output))
logger.Println(color.CyanString("[+] statistics:"))
color.Cyan("[+] all %d files saved to '%s'\n", allFileCount, output)
if len(args) == 2 && "detailFilePath" == args[0] {
color.Cyan("[+] mini program detail info saved to '%s'\n", args[1])
}

color.Cyan("[+] extension statistics:\n")

var keys [][]interface{}
for k, v := range exts {
logger.Println(color.CyanString(" - %5d %-5s files", v, k))
keys = append(keys, []interface{}{k, v})
}

sort.Slice(keys, func(i, j int) bool {
return keys[i][1].(int) > keys[j][1].(int)
})

for _, kk := range keys {
color.Cyan(" - %-5s %5d\n", kk[0], kk[1])
}
},
}
Expand Down Expand Up @@ -128,6 +145,7 @@ func unpack(decryptedData []byte, unpackRoot string, thread int) (int, error) {
wg.Add(thread)
var locker = sync.Mutex{}
var count = 0
var colorPrint = color.New()
for i := 0; i < thread; i++ {
go func() {
defer wg.Done()
Expand All @@ -146,10 +164,9 @@ func unpack(decryptedData []byte, unpackRoot string, thread int) (int, error) {
err = os.WriteFile(outputFilePath, beautify, 0600)
util.Fatal(err)

//color.Green("(%d/%d) saved '%s'", i+1, fileCount, outputFilePath)
locker.Lock()
count++
logger.Printf(color.GreenString("\runpack %d/%d", count, fileCount))
_, _ = colorPrint.Print(color.GreenString("\runpack %d/%d", count, fileCount))
locker.Unlock()
}
}()
Expand Down Expand Up @@ -192,7 +209,7 @@ func fileBeautify(name string, data []byte) (result []byte) {
func parseWxid(root string) (string, error) {
var regAppId = regexp.MustCompile(`(wx[0-9a-f]{16})`)
if !regAppId.MatchString(filepath.Base(root)) {
return "", errors.New("the path is not a mimi program path")
return "", errors.New("the path is not a mini program path")
}

return regAppId.FindStringSubmatch(filepath.Base(root))[1], nil
Expand Down
22 changes: 20 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,34 @@ module wxapkg
go 1.19

require (
github.com/charmbracelet/bubbles v0.15.0
github.com/charmbracelet/bubbletea v0.24.1
github.com/charmbracelet/lipgloss v0.7.1
github.com/fatih/color v1.15.0
github.com/spf13/cobra v1.7.0
github.com/tidwall/pretty v1.2.1
github.com/wux1an/fake-useragent v1.1.0
golang.org/x/crypto v0.7.0
)

require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/harmonica v0.2.0 // indirect
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.1 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/sync v0.2.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/term v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
)
Loading

0 comments on commit b712209

Please sign in to comment.