main
Raw Download raw file
  1package cmd
  2
  3import (
  4	"context"
  5	"fmt"
  6	"mysh/pkg/cache"
  7	"mysh/pkg/mythic"
  8	"time"
  9
 10	"github.com/spf13/cobra"
 11)
 12
 13var cacheCmd = &cobra.Command{
 14	Use:   "cache",
 15	Short: "Show cache information",
 16	Long:  "Display information about the task result cache including location, size, and number of cached tasks.",
 17	RunE:  runCacheInfo,
 18}
 19
 20var cacheFlushCmd = &cobra.Command{
 21	Use:   "flush",
 22	Short: "Flush all cached task results",
 23	Long:  "Remove all cached task results from the cache directory.",
 24	RunE:  runCacheFlush,
 25}
 26
 27var cacheUpdateCmd = &cobra.Command{
 28	Use:   "update",
 29	Short: "Update cache with latest task results",
 30	Long:  "Fetch all tasks from the server and update the local cache with completed task results.",
 31	RunE:  runCacheUpdate,
 32}
 33
 34func init() {
 35	rootCmd.AddCommand(cacheCmd)
 36	cacheCmd.AddCommand(cacheFlushCmd)
 37	cacheCmd.AddCommand(cacheUpdateCmd)
 38}
 39
 40func runCacheInfo(cmd *cobra.Command, args []string) error {
 41	if err := validateConfig(); err != nil {
 42		return err
 43	}
 44
 45	taskCache, err := cache.New(mythicURL)
 46	if err != nil {
 47		return fmt.Errorf("failed to initialize cache: %w", err)
 48	}
 49
 50	cacheDir, fileCount, totalSize, err := taskCache.GetCacheInfo()
 51	if err != nil {
 52		return fmt.Errorf("failed to get cache info: %w", err)
 53	}
 54
 55	fmt.Printf("Cache Information:\n")
 56	fmt.Printf("Location:     %s\n", cacheDir)
 57	fmt.Printf("Cached tasks: %d\n", fileCount)
 58	fmt.Printf("Total size:   %s\n", formatBytes(totalSize))
 59
 60	return nil
 61}
 62
 63func runCacheFlush(cmd *cobra.Command, args []string) error {
 64	if err := validateConfig(); err != nil {
 65		return err
 66	}
 67
 68	taskCache, err := cache.New(mythicURL)
 69	if err != nil {
 70		return fmt.Errorf("failed to initialize cache: %w", err)
 71	}
 72
 73	if err := taskCache.ClearCache(); err != nil {
 74		return fmt.Errorf("failed to flush cache: %w", err)
 75	}
 76
 77	fmt.Println("Cache flushed successfully")
 78	return nil
 79}
 80
 81func runCacheUpdate(cmd *cobra.Command, args []string) error {
 82	if err := validateConfig(); err != nil {
 83		return err
 84	}
 85
 86	client := mythic.NewClient(mythicURL, token, insecure, socksProxy)
 87	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
 88	defer cancel()
 89
 90	// Initialize cache
 91	taskCache, err := cache.New(mythicURL)
 92	if err != nil {
 93		return fmt.Errorf("failed to initialize cache: %w", err)
 94	}
 95
 96	fmt.Println("Fetching all tasks from server...")
 97
 98	// Get all tasks (lightweight metadata first)
 99	tasks, err := client.GetAllTasks(ctx, 0) // 0 = no limit
100	if err != nil {
101		return fmt.Errorf("failed to get tasks: %w", err)
102	}
103
104	if len(tasks) == 0 {
105		fmt.Println("No tasks found on server")
106		return nil
107	}
108
109	fmt.Printf("Found %d tasks, updating cache...\n", len(tasks))
110
111	// Use the same logic as grep to populate task responses and update cache
112	updatedTasks := populateTaskResponses(ctx, client, tasks, taskCache)
113
114	fmt.Printf("Cache update completed. Processed %d tasks.\n", len(updatedTasks))
115	return nil
116}
117
118// formatBytes formats byte count as human-readable string
119func formatBytes(bytes int64) string {
120	const unit = 1024
121	if bytes < unit {
122		return fmt.Sprintf("%d B", bytes)
123	}
124	div, exp := int64(unit), 0
125	for n := bytes / unit; n >= unit; n /= unit {
126		div *= unit
127		exp++
128	}
129	return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
130}