97 lines
4.2 KiB
Go
97 lines
4.2 KiB
Go
package cli
|
|
|
|
import (
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/openclaw/discrawl/internal/config"
|
|
"github.com/openclaw/discrawl/internal/store"
|
|
"github.com/vincentkoc/crawlkit/control"
|
|
)
|
|
|
|
func (r *runtime) runMetadata(args []string) error {
|
|
fs := flag.NewFlagSet("metadata", flag.ContinueOnError)
|
|
fs.SetOutput(io.Discard)
|
|
jsonOut := fs.Bool("json", false, "")
|
|
if err := fs.Parse(args); err != nil {
|
|
return usageErr(err)
|
|
}
|
|
if fs.NArg() != 0 {
|
|
return usageErr(errors.New("metadata takes flags only"))
|
|
}
|
|
if *jsonOut {
|
|
r.json = true
|
|
}
|
|
cfg := config.Default()
|
|
manifest := control.NewManifest("discrawl", "Discord Crawl", "discrawl")
|
|
manifest.Description = "Local-first Discord archive crawler."
|
|
manifest.Branding = control.Branding{SymbolName: "bubble.left.and.bubble.right.fill", AccentColor: "#5865f2", BundleIdentifier: "com.hnc.Discord"}
|
|
manifest.Paths = control.Paths{
|
|
DefaultConfig: config.ResolvePath(""),
|
|
ConfigEnv: config.DefaultConfigEnv,
|
|
DefaultDatabase: cfg.DBPath,
|
|
DefaultCache: cfg.CacheDir,
|
|
DefaultLogs: cfg.LogDir,
|
|
DefaultShare: cfg.Share.RepoPath,
|
|
}
|
|
manifest.Capabilities = []string{"metadata", "status", "doctor", "sync", "tap", "tui", "git-share", "sql", "embeddings"}
|
|
manifest.Privacy = control.Privacy{ContainsPrivateMessages: true, ExportsSecrets: false, LocalOnlyScopes: []string{"discord", "desktop-cache", "sqlite", "git-share"}}
|
|
manifest.Commands = map[string]control.Command{
|
|
"status": {Title: "Status", Argv: []string{"discrawl", "status", "--json"}, JSON: true},
|
|
"doctor": {Title: "Doctor", Argv: []string{"discrawl", "doctor", "--json"}, JSON: true},
|
|
"sync": {Title: "Sync", Argv: []string{"discrawl", "--json", "sync"}, JSON: true, Mutates: true},
|
|
"tap": {Title: "Import desktop cache", Argv: []string{"discrawl", "--json", "tap"}, JSON: true, Mutates: true},
|
|
"cache-import": {Title: "Import desktop cache", Argv: []string{"discrawl", "--json", "cache-import"}, JSON: true, Mutates: true},
|
|
"wiretap": {Title: "Legacy desktop cache import", Argv: []string{"discrawl", "--json", "wiretap"}, JSON: true, Mutates: true, Legacy: true, Deprecated: true},
|
|
"tui": {Title: "Terminal browser", Argv: []string{"discrawl", "tui"}},
|
|
"tui-json": {Title: "Terminal browser rows", Argv: []string{"discrawl", "tui", "--json"}, JSON: true},
|
|
"publish": {Title: "Publish share", Argv: []string{"discrawl", "--json", "publish"}, JSON: true, Mutates: true},
|
|
"subscribe": {Title: "Subscribe share", Argv: []string{"discrawl", "--json", "subscribe"}, JSON: true, Mutates: true},
|
|
"update": {Title: "Update share", Argv: []string{"discrawl", "--json", "update"}, JSON: true, Mutates: true},
|
|
}
|
|
return r.print(manifest)
|
|
}
|
|
|
|
func controlStatus(configPath string, cfg config.Config, status store.Status, shareNeedsUpdate bool) control.Status {
|
|
counts := []control.Count{
|
|
control.NewCount("guilds", "Guilds", int64(status.GuildCount)),
|
|
control.NewCount("channels", "Channels", int64(status.ChannelCount)),
|
|
control.NewCount("threads", "Threads", int64(status.ThreadCount)),
|
|
control.NewCount("messages", "Messages", int64(status.MessageCount)),
|
|
control.NewCount("members", "Members", int64(status.MemberCount)),
|
|
control.NewCount("embedding_backlog", "Embedding backlog", int64(status.EmbeddingBacklog)),
|
|
}
|
|
out := control.NewStatus("discrawl", fmt.Sprintf("%d messages across %d channels", status.MessageCount, status.ChannelCount))
|
|
out.State = "current"
|
|
out.ConfigPath = configPath
|
|
out.DatabasePath = status.DBPath
|
|
out.Counts = counts
|
|
if !status.LastSyncAt.IsZero() {
|
|
out.LastSyncAt = status.LastSyncAt.UTC().Format(time.RFC3339)
|
|
}
|
|
db := control.SQLiteDatabase("primary", "Discord archive", "archive", status.DBPath, true, counts)
|
|
out.DatabaseBytes = db.Bytes
|
|
out.WALBytes = fileSize(status.DBPath + "-wal")
|
|
out.Databases = []control.Database{db}
|
|
out.Share = &control.Share{
|
|
Enabled: cfg.ShareEnabled(),
|
|
RepoPath: cfg.Share.RepoPath,
|
|
Remote: cfg.Share.Remote,
|
|
Branch: cfg.Share.Branch,
|
|
NeedsUpdate: shareNeedsUpdate,
|
|
}
|
|
return out
|
|
}
|
|
|
|
func fileSize(path string) int64 {
|
|
info, err := os.Stat(path)
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return info.Size()
|
|
}
|