前言
最近在重写小霾的 DC Check 功能,打算把 DC2/3 加进去,而不是直接写成 DC1/4。
由于本人 Python 本当下手,一开始没看懂 Pyrogram 的源码,没搞明白他是怎么拿的 dc_id, 本来想找找 tdlib 能不能拿这个信息,结果我找了半天 tdlib 的文档,也没找到哪里有 dc 这一字段拿,随后在 tdlib 群中询问得知,tdlib 根本没把这部分暴露给用户···
不过据 tdlib 群的大佬说,通过头像判断的用户 DC 并不是真实 DC,这点暂且存疑
但是随后另一个大佬提醒,通过解码 file_id 就能判断出文件所存储的数据中心。
那么不多说,直接上代码。
参考代码
通过以上逻辑可得 Node.js 参考代码:
import struct from 'python-struct'
function getDC(file_id) {
let decoded_file_id_buf = rle_decode(Buffer.from(file_id, 'base64url'))
const major = parseInt(decoded_file_id_buf.slice(-1).toString('hex'), 16)
if (major < 4) {
decoded_file_id_buf = decoded_file_id_buf.slice(0, -1)
} else {
decoded_file_id_buf = decoded_file_id_buf.slice(0, -2)
}
const [, dc] = struct.unpack('<ii', decoded_file_id_buf.slice(0, 8))
return dc;
}
function rle_decode(bytes_buf) {
const result = [];
let isPreviousZero = false;
for (const item of bytes_buf) {
if (item === 0) {
isPreviousZero = true;
continue;
}
if (isPreviousZero) {
result.push(...Array(item).fill(0));
isPreviousZero = false;
} else {
result.push(item);
}
}
return Buffer.from(result);
}
console.log(getDC('AgACAgEAAxUAAWJGy2LS9jhZRw6R2qgXlZqrRo5oAAKqpzEbUr8gNO_REKKp8zC8AQADAgADYwADIwQ')) // DC1
console.log(getDC('AgACAgIAAxUAAWJGzJ9B4LKaPV5cjXOdO0xiQb-7AAI8uTEby3YxSvsJRGGMR2jcAQADAgADYwADIwQ')) // DC2
console.log(getDC('AgACAgMAAxUAAWJGza3gyRKTX-Eg5BN_n0iMHpxNAAKppzEbshEJBC3NV1bsBwi3AQADAgADYwADIwQ')) // DC3
console.log(getDC('AgACAgQAAxUAAWJGyzZFag7qs544PxHGvabVQ6wUAAIZuTEbcDIYUqVQrWEZVR2JAQADAgADYwADIwQ')) // DC4
console.log(getDC('BQACAgUAAx0CVTVl8wACQbJiRlY8fOQVb8cEg_eiBU3A3DZ6ZwACwgYAAu5bOFaKGWHnjrb_biME')) // DC5
PHP 参考代码:
<?php
function b64_decode(string $str): string
{
return base64_decode(str_replace(['-', '_'], ['+', '/'], $str));
}
function rle_decode(string $bin_str): array
{
$result = [];
$isPreviousZero = false;
foreach (str_split($bin_str) as $bin) {
$dec = hexdec(bin2hex($bin));
if ($dec === 0) {
$isPreviousZero = true;
continue;
}
if ($isPreviousZero) {
array_push($result, ...array_fill(0, $dec, 0));
$isPreviousZero = false;
} else {
$result[] = $dec;
}
}
return $result;
}
function getDC(string $file_id): int
{
$r = rle_decode(b64_decode($file_id));
return $r[4];
}
echo getDC('AgACAgEAAxUAAWJGy2LS9jhZRw6R2qgXlZqrRo5oAAKqpzEbUr8gNO_REKKp8zC8AQADAgADYwADIwQ'), PHP_EOL; // DC1
echo getDC('AgACAgIAAxUAAWJGzJ9B4LKaPV5cjXOdO0xiQb-7AAI8uTEby3YxSvsJRGGMR2jcAQADAgADYwADIwQ'), PHP_EOL; // DC2
echo getDC('AgACAgMAAxUAAWJGza3gyRKTX-Eg5BN_n0iMHpxNAAKppzEbshEJBC3NV1bsBwi3AQADAgADYwADIwQ'), PHP_EOL; // DC3
echo getDC('AgACAgQAAxUAAWJGyzZFag7qs544PxHGvabVQ6wUAAIZuTEbcDIYUqVQrWEZVR2JAQADAgADYwADIwQ'), PHP_EOL; // DC4
echo getDC('BQACAgUAAx0CVTVl8wACQbJiRlY8fOQVb8cEg_eiBU3A3DZ6ZwACwgYAAu5bOFaKGWHnjrb_biME'), PHP_EOL; // DC5