mirror of
https://github.com/Tyrrrz/DiscordChatExporter.git
synced 2026-09-30 13:10:10 -05:00
fix(scrape): auth discovery, skip forbidden channels, mount host script
Discover Discord tokens from env, token files, GUI Settings.dat, and desktop leveldb; bind-mount the host scrape script so container preflight uses partition/--after cursors; skip inaccessible channels without aborting targets; fix set -e and busybox mktemp for incremental exports under ~/Documents. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
107
scripts/tools/ReadDceGuiToken/Program.cs
Normal file
107
scripts/tools/ReadDceGuiToken/Program.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
static string? TryGetMachineId()
|
||||
{
|
||||
foreach (var path in new[] { "/etc/machine-id", "/var/lib/dbus/machine-id" })
|
||||
{
|
||||
try
|
||||
{
|
||||
var id = File.ReadAllText(path).Trim();
|
||||
if (!string.IsNullOrWhiteSpace(id))
|
||||
return id;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return Environment.MachineName;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static string? DecryptToken(string? value, string encryptionSalt)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return null;
|
||||
|
||||
const string prefix = "enc:";
|
||||
if (!value.StartsWith(prefix, StringComparison.Ordinal))
|
||||
return value;
|
||||
|
||||
try
|
||||
{
|
||||
var encryptedData = Convert.FromHexString(value[prefix.Length..]);
|
||||
var machineId = TryGetMachineId() ?? string.Empty;
|
||||
var key = Rfc2898DeriveBytes.Pbkdf2(
|
||||
Encoding.UTF8.GetBytes(machineId),
|
||||
Encoding.UTF8.GetBytes(encryptionSalt),
|
||||
600_000,
|
||||
HashAlgorithmName.SHA256,
|
||||
16
|
||||
);
|
||||
|
||||
var tokenData = new byte[encryptedData.AsSpan(28).Length];
|
||||
using var aes = new AesGcm(key, 16);
|
||||
aes.Decrypt(
|
||||
encryptedData.AsSpan(0, 12),
|
||||
encryptedData.AsSpan(28),
|
||||
encryptedData.AsSpan(12, 16),
|
||||
tokenData
|
||||
);
|
||||
|
||||
return Encoding.UTF8.GetString(tokenData);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static string ResolveSettingsPath(string[] args)
|
||||
{
|
||||
if (args.Length > 0 && !string.IsNullOrWhiteSpace(args[0]))
|
||||
return args[0];
|
||||
|
||||
var envPath = Environment.GetEnvironmentVariable("DISCORDCHATEXPORTER_SETTINGS_PATH");
|
||||
if (!string.IsNullOrWhiteSpace(envPath))
|
||||
{
|
||||
if (envPath.EndsWith(Path.DirectorySeparatorChar) || Directory.Exists(envPath))
|
||||
return Path.Combine(envPath, "Settings.dat");
|
||||
|
||||
return envPath;
|
||||
}
|
||||
|
||||
throw new FileNotFoundException(
|
||||
"Settings path not provided. Pass Settings.dat path or set DISCORDCHATEXPORTER_SETTINGS_PATH."
|
||||
);
|
||||
}
|
||||
|
||||
var settingsPath = ResolveSettingsPath(args);
|
||||
if (!File.Exists(settingsPath))
|
||||
throw new FileNotFoundException($"Settings file not found: {settingsPath}");
|
||||
|
||||
using var document = JsonDocument.Parse(File.ReadAllText(settingsPath));
|
||||
if (
|
||||
!document.RootElement.TryGetProperty("LastToken", out var lastTokenElement)
|
||||
|| lastTokenElement.ValueKind != JsonValueKind.String
|
||||
)
|
||||
{
|
||||
Environment.Exit(2);
|
||||
}
|
||||
|
||||
var salt =
|
||||
Environment.GetEnvironmentVariable("DCE_ENCRYPTION_SALT") ?? "HimalayanPinkSalt";
|
||||
var token = DecryptToken(lastTokenElement.GetString(), salt);
|
||||
if (string.IsNullOrWhiteSpace(token))
|
||||
Environment.Exit(3);
|
||||
|
||||
Console.Write(token);
|
||||
9
scripts/tools/ReadDceGuiToken/ReadDceGuiToken.csproj
Normal file
9
scripts/tools/ReadDceGuiToken/ReadDceGuiToken.csproj
Normal file
@@ -0,0 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>ReadDceGuiToken</RootNamespace>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user