telegram-tghub-better-new
Version:
NodeJS/Browser MTProto API Telegram client library,
905 lines (904 loc) • 40.2 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CustomError = exports.AnalyzeTData = exports.clearEmptyBy = exports.oldTelegram = exports.defaultConfig = exports.cFingerpting = exports.saveStringSession = exports.getInitConnection = exports.formatInitParams = exports.StoreSession = exports.defaultDc = void 0;
exports.formatInputString = formatInputString;
exports.formatProxyTemplate = formatProxyTemplate;
exports.formatProxy = formatProxy;
exports.identifyTheDirectory = identifyTheDirectory;
exports.clearEmpty = clearEmpty;
exports.isValidInternationalPhoneNumber = isValidInternationalPhoneNumber;
exports.getCountryByPhone = getCountryByPhone;
exports.getLangCode = getLangCode;
exports.getDefaultJson = getDefaultJson;
exports.formatJsonAndSession = formatJsonAndSession;
exports.checkImportData = checkImportData;
exports.getFileName = getFileName;
exports.formatErrorMessage = formatErrorMessage;
exports.getError = getError;
exports.clientDestroy = clientDestroy;
exports.returnSingleSimpleClient = returnSingleSimpleClient;
exports.createSingleSimpleClient = createSingleSimpleClient;
// @ts-nocheck
const lodash_1 = __importDefault(require("lodash"));
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
const dayjs_1 = __importDefault(require("dayjs"));
const moment_timezone_1 = __importDefault(require("moment-timezone"));
const path_1 = __importDefault(require("path"));
const adm_zip_1 = __importDefault(require("adm-zip"));
const iconv_lite_1 = __importDefault(require("iconv-lite"));
const crypto = __importStar(require("crypto"));
const string_template_1 = __importDefault(require("string-template"));
const iso_lang_codes_1 = __importDefault(require("iso-lang-codes"));
const libphonenumber_js_1 = require("libphonenumber-js");
const __1 = require("../");
const IGE_1 = require("../crypto/IGE");
const model_js_1 = __importDefault(require("./model.js"));
const { asleep } = __1.helpers;
const { StringSession } = __1.sessions;
const { BinaryReader } = __1.extensions;
exports.defaultDc = {
id: 1,
ip: "149.154.175.57",
ipAddress: "149.154.175.57",
port: 443,
ipv6: false,
};
class StoreSession extends StringSession {
constructor() {
super();
this.sessionInfo = {};
}
async init() {
const isAlive = ["authKey", "dcId", "port", "serverAddress"].every((i) => !!this.sessionInfo[i]);
if (isAlive) {
const { authKey, dcId, port, serverAddress } = this.sessionInfo;
this._dcId = dcId;
this._port = port;
this._serverAddress = serverAddress;
this._key = authKey;
}
else {
this.setDC(exports.defaultDc.id, exports.defaultDc.ip, exports.defaultDc.port);
}
}
}
exports.StoreSession = StoreSession;
const formatInitParams = (list) => {
const params = list.map((item) => {
switch (item._) {
case "jsonString":
return new __1.Api.JsonObjectValue({
key: item.key,
value: new __1.Api.JsonString({
value: item.value,
}),
});
case "jsonNumber":
return new __1.Api.JsonObjectValue({
key: item.key,
value: new __1.Api.JsonNumber({
value: item.value,
}),
});
case "jsonObject":
return new __1.Api.JsonObjectValue({
key: item.key,
value: new __1.Api.JsonObject({
value: (0, exports.formatInitParams)(item.value),
}),
});
default:
break;
}
});
return params;
};
exports.formatInitParams = formatInitParams;
const getInitConnection = (sessionInfo) => {
const { deviceToken, cFingerpting, installer, packageId, tzOffset, apiHash, apiId, langPack, appVersion, systemVersion, deviceModel, langCode, systemLangCode, perfCat, } = sessionInfo;
const defaultInitConnectionParams = [
{
_: "jsonString",
key: "device_token",
value: deviceToken || "",
},
{
_: "jsonString",
key: "data",
value: cFingerpting || tg4cFingerpting,
},
{
_: "jsonString",
key: "installer",
value: installer || "",
},
{
_: "jsonString",
key: "package_id",
value: packageId || "org.telegram.messenger",
},
{
_: "jsonNumber",
key: "tz_offset",
value: Number(tzOffset || 0),
},
{
_: "jsonNumber",
key: "perf_cat",
value: perfCat || lodash_1.default.random(1, 2),
},
];
const params = (0, exports.formatInitParams)(defaultInitConnectionParams);
const initRequest = {
apiId,
apiHash,
langPack,
langCode,
systemLangCode,
appVersion,
systemVersion,
deviceModel,
params: new __1.Api.JsonObject({
value: params,
}),
};
return initRequest;
};
exports.getInitConnection = getInitConnection;
function serializeGramjsSession(session) {
const authKey = Buffer.from(session.authKey);
if (authKey.length !== 256) {
throw new Error("authKey must be 256 bytes long");
}
const ipEncoded = Buffer.from(session.ipAddress, "utf-8");
const u8 = Buffer.alloc(261 + ipEncoded.length);
let pos = 0;
pos = u8.writeUInt8(session.dcId, pos);
pos = u8.writeUInt16BE(ipEncoded.length, pos);
ipEncoded.copy(u8, pos);
pos += ipEncoded.length;
pos = u8.writeUInt16BE(session.port, pos);
authKey.copy(u8, pos);
return `1${u8.toString("base64")}`;
}
const saveStringSession = (data) => {
const stringSession = serializeGramjsSession(lodash_1.default.assign({}, lodash_1.default.pick(data, ["dcId", "port", "ipAddress", "authKey"]), {
ipv6: false,
}));
return stringSession;
};
exports.saveStringSession = saveStringSession;
exports.cFingerpting = "49C1522548EBACD46CE322B6FD47F6092BB745D0F88082145CAF35E14DCC38E1";
exports.defaultConfig = {
cFingerpting: exports.cFingerpting,
enablePushConnection: false,
configPath: "/data/user/0/org.telegram.messenger/files",
langCode: "en",
};
function formatInputString(inputString) {
var _a;
let counter = 0;
let list = [];
const replacedString = (_a = inputString === null || inputString === void 0 ? void 0 : inputString.replace) === null || _a === void 0 ? void 0 : _a.call(inputString, /\{([^}]+)\}/g, () => {
const result = "{" + counter + "}";
counter++;
return result;
});
const matches = inputString.match(/\{([^}]+)\}/g);
if (matches) {
// 提取匹配到的文本,去除花括号
const extractedTexts = matches.map((match) => match.substring(1, match.length - 1));
// 将数字根据非数字字符拆分成长度为2的数组
list = extractedTexts.flatMap((text) => {
const numbers = text.split(/[^0-9]+/).filter(Boolean); // 匹配非数字字符并拆分
const result = [];
for (let i = 0; i < numbers.length; i += 2) {
result.push(numbers.slice(i, i + 2));
}
return result;
});
}
return (0, string_template_1.default)(replacedString, list.map((rests) => lodash_1.default.random(...rests)));
}
function formatProxyTemplate(proxy = {}) {
const formatProxyData = lodash_1.default.forOwn(lodash_1.default.cloneDeep(proxy), (value, key, obj) => {
obj[key] = formatInputString(String(value || ""));
});
return lodash_1.default.assign({}, formatProxyData, {
password: String(lodash_1.default.get(formatProxyData, "password", "")),
port: Number(lodash_1.default.get(formatProxyData, "port", 0)),
});
}
function formatProxy(proxy = {}) {
return lodash_1.default.assign({}, formatProxyTemplate(proxy), {
socksType: 5,
timeout: 10,
});
}
const getModel = () => {
return model_js_1.default[lodash_1.default.random(0, model_js_1.default.length - 1)];
};
const oldTelegram = () => {
const { deviceBrand, deviceModel, model } = getModel();
const conf = Object.assign(Object.assign({}, exports.defaultConfig), { deviceBrand,
deviceModel,
model, apiHash: "014b35b6184100b085b0d0572f9b5103", apiId: 4, langPack: "android", appVersion: "10.13.2 (48509)", cFingerpting: exports.cFingerpting, systemVersion: `SDK ${lodash_1.default.random(28, 34)}`, installer: "com.google.android.packageinstaller", packageId: "org.telegram.messenger.web", deviceToken: "__FIREBASE_FAILED__" });
return conf;
};
exports.oldTelegram = oldTelegram;
function identifyTheDirectory(path) {
const parts = lodash_1.default.split(path, "/");
const directories = [];
// Build each level of the path
for (let i = 0; i < parts.length - 1; i++) {
const dirPath = lodash_1.default.slice(parts, 0, i + 1).join("/") + "/";
directories.push(dirPath);
}
return directories;
}
const clearEmptyBy = (value) => {
// 排除 null、undefined 和空字符串
if (lodash_1.default.isNil(value) || value === "") {
return false;
}
// 对于对象和数组,进一步检查是否为空
if (lodash_1.default.isObject(value) && lodash_1.default.isEmpty(value)) {
return false;
}
// 其他情况保留
return true;
};
exports.clearEmptyBy = clearEmptyBy;
function clearEmpty(obj) {
return lodash_1.default.pickBy(obj, exports.clearEmptyBy);
}
function isValidInternationalPhoneNumber(phoneNumber) {
// 正则表达式匹配以加号开头,随后是一个或多个数字的字符串
return /^\+\d+$/.test(phoneNumber) && (0, libphonenumber_js_1.isValidPhoneNumber)(phoneNumber);
}
function getCountryByPhone(phone) {
if (isValidInternationalPhoneNumber(phone)) {
const parsedNumber = (0, libphonenumber_js_1.parsePhoneNumber)(phone);
return lodash_1.default.get(parsedNumber, "country");
}
}
function getLangCode(props) {
var _a, _b;
const phone = lodash_1.default.get(props, "phone");
const country = getCountryByPhone(phone);
if (country) {
const systemLangCodes = iso_lang_codes_1.default.findCountryLocales(country);
if (!lodash_1.default.isEmpty(systemLangCodes)) {
const index = lodash_1.default.random(0, systemLangCodes.length - 1);
const systemLangCode = ((_b = (_a = systemLangCodes === null || systemLangCodes === void 0 ? void 0 : systemLangCodes[index]) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase) === null || _b === void 0 ? void 0 : _b.call(_a)) || "en-us";
const langCodes = iso_lang_codes_1.default.findCountryLanguages(country);
const langCode = (langCodes === null || langCodes === void 0 ? void 0 : langCodes[index]) || "en";
const [timezone] = moment_timezone_1.default.tz.zonesForCountry(country, true);
const offset = lodash_1.default.get(timezone, "offset");
const option = {
country,
systemLangCode,
systemLangPack: systemLangCode,
langCode,
tzOffset: offset ? offset * 60 : 10800,
};
return option;
}
}
return {
country,
langCode: "en",
systemLangCode: "en-us",
systemLangPack: "en-us",
tzOffset: 10800,
};
}
class AnalyzeTData {
constructor(props) {
const { buffers, phone, sessionInfo } = props;
this.buffers = buffers;
this.phone = phone;
this.sessionInfo = sessionInfo;
}
run() {
this.getTwoFa();
const old_session_key = "data";
const tDataList = lodash_1.default.filter(this.buffers, (item) => lodash_1.default.get(item, "originalname", "").includes("tdata"));
const tDataItem = lodash_1.default.minBy(tDataList, (item) => lodash_1.default.size(item.originalname));
const tDataPath = lodash_1.default.get(tDataItem, "originalname", "");
const partOneMd5 = this.tdesktopMd5(old_session_key).slice(0, 16);
const tdesktopUserBasePath = tDataPath + partOneMd5;
const pathKey = "key_" + old_session_key;
const openPath = tDataPath + pathKey;
const data = this.openTDesktopBuffer(openPath);
const salt = this.tdesktopReadBuffer(data);
if (salt.length !== 32) {
throw new Error("Length of salt is wrong!");
}
const encryptedKey = this.tdesktopReadBuffer(data);
const encryptedInfo = this.tdesktopReadBuffer(data);
const hash = crypto
.createHash("sha512")
.update(salt)
.update("")
.update(salt)
.digest();
const passKey = crypto.pbkdf2Sync(hash, salt, 1, 256, "sha512");
const key = this.tdesktopReadBuffer(this.tdesktopDecrypt(new BinaryReader(encryptedKey), passKey));
const info = this.tdesktopReadBuffer(this.tdesktopDecrypt(new BinaryReader(encryptedInfo), key));
const count = info.readUInt32BE();
if (count !== 1) {
throw new Error("Currently only supporting one account at a time");
}
const main = this.tdesktopOpenEncrypted(tdesktopUserBasePath, key);
const magic = main.read(4).reverse().readUInt32LE();
if (magic !== 75) {
throw new Error("Unsupported magic version");
}
const final = new BinaryReader(this.tdesktopReadBuffer(main));
final.read(12);
final.read(4).reverse().readUInt32LE();
const mainDc = final.read(4).reverse().readUInt32LE();
const length = final.read(4).reverse().readUInt32LE();
for (let i = 0; i < length; i++) {
const dc = final.read(4).reverse().readUInt32LE();
const authKey = final.read(256);
if (dc === mainDc) {
this.sessionInfo.dcId = mainDc;
this.sessionInfo.authKey = authKey;
this.sessionInfo.serverAddress = this.getServerAddress(mainDc);
this.sessionInfo.port = 443;
this.getDefaultParams();
}
}
}
openTDesktopBuffer(name) {
const filesToTry = [];
for (const i of ["0", "1", "s"]) {
const existsItem = lodash_1.default.find(this.buffers, (item) => lodash_1.default.get(item, "originalname", "").includes(name + i));
if (!lodash_1.default.isEmpty(existsItem)) {
const buffer = lodash_1.default.get(existsItem, "buffer");
filesToTry.push(new BinaryReader(buffer));
}
}
return this.tdesktopOpenAfter(filesToTry);
}
tdesktopOpenAfter(filesToTry) {
for (const fileToTry of filesToTry) {
const magic = fileToTry.read(4).toString("utf-8");
if (magic !== "TDF$") {
console.error("WRONG MAGIC");
continue;
}
const versionBytes = fileToTry.read(4);
let data = fileToTry.read();
const md5 = data.slice(-16).toString("hex");
data = data.slice(0, -16);
const length = Buffer.alloc(4);
length.writeInt32LE(data.length, 0);
const toCompare = Buffer.concat([
data,
length,
versionBytes,
Buffer.from("TDF$", "utf-8"),
]);
const hash = crypto
.createHash("md5")
.update(toCompare)
.digest("hex");
if (hash !== md5) {
throw new Error("Wrong MD5");
}
const result = new BinaryReader(data);
return result;
}
}
tdesktopReadBuffer(buffer) {
const length = buffer.read(4).reverse().readInt32LE();
const result = length > 0 ? buffer.read(length, false) : Buffer.alloc(0);
return result;
}
tdesktopDecrypt(data, auth_key) {
const message_key = data.read(16);
const encrypted_data = data.read();
const [aes_key, aes_iv] = this.calcKey(auth_key, message_key, false);
const ige = new IGE_1.IGE(aes_key, aes_iv);
const decrypted_data = ige.decryptIge(encrypted_data);
if (message_key.toString("hex") !==
this.sha1(decrypted_data).slice(0, 16).toString("hex")) {
throw new Error("msg_key mismatch");
}
return new BinaryReader(decrypted_data);
}
calcKey(authKey, msgKey, client) {
const x = client ? 0 : 8;
const sha1_a = this.sha1(Buffer.concat([msgKey, authKey.slice(x, x + 32)]));
const sha1_b = this.sha1(Buffer.concat([
authKey.slice(32 + x, 32 + x + 16),
msgKey,
authKey.slice(48 + x, 48 + x + 16),
]));
const sha1_c = this.sha1(Buffer.concat([authKey.slice(64 + x, 64 + x + 32), msgKey]));
const sha1_d = this.sha1(Buffer.concat([msgKey, authKey.slice(96 + x, 96 + x + 32)]));
const aes_key = Buffer.concat([
sha1_a.slice(0, 8),
sha1_b.slice(8, 8 + 12),
sha1_c.slice(4, 4 + 12),
]);
const aes_iv = Buffer.concat([
sha1_a.slice(8, 8 + 12),
sha1_b.slice(0, 8),
sha1_c.slice(16, 16 + 4),
sha1_d.slice(0, 8),
]);
return [aes_key, aes_iv];
}
tdesktopOpenEncrypted(fileName, tdesktopKey) {
const f = this.openTDesktopBuffer(fileName);
const data = this.tdesktopReadBuffer(f);
const res = this.tdesktopDecrypt(new BinaryReader(data), tdesktopKey);
const length = res.readInt(false);
if (length > res.getBuffer().length || length < 4) {
throw new Error("Wrong length");
}
return res;
}
tdesktopMd5(data) {
let result = "";
const hash = crypto.createHash("md5").update(data).digest("hex");
for (let i = 0; i < hash.length; i += 2) {
result += hash[i + 1] + hash[i];
}
return result.toUpperCase();
}
getServerAddress(dcId) {
switch (dcId) {
case 1:
return "149.154.175.50";
case 2:
return "95.161.76.100";
case 3:
return "149.154.175.100";
case 4:
return "149.154.167.91";
case 5:
return "149.154.171.5";
default:
throw new Error("Invalid DC");
}
}
sha1(buf) {
return crypto.createHash("sha1").update(buf).digest();
}
getDefaultParams() {
var _a, _b;
const phone = (_b = (_a = this === null || this === void 0 ? void 0 : this.phone) === null || _a === void 0 ? void 0 : _a.replace) === null || _b === void 0 ? void 0 : _b.call(_a, /^(\+)?(\d+)/, "+$2");
this.sessionInfo = lodash_1.default.assign({}, this.sessionInfo, getLangCode({ phone }), {
apiHash: "b18441a1ff607e10a989891a5462e627",
apiId: 2040,
langPack: "tdesktop",
deviceToken: "__FIREBASE_FAILED__",
systemVersion: "Windows 11",
appVersion: "5.2.3 x64",
deviceModel: "Desktop",
langCode: "en",
systemLangCode: "en-US",
tzOffset: 28800,
phone,
});
}
getTwoFa() {
var _a, _b, _c, _d;
const passwordTwoFA = lodash_1.default.find(this.buffers, (item) => ["password", "fa", "pwd"].some((name) => lodash_1.default.get(item, "originalname", "").toLowerCase().includes(name)) && lodash_1.default.get(item, "originalname", "").includes("txt"));
this.sessionInfo.password =
((_d = (_c = (_b = (_a = lodash_1.default.get(passwordTwoFA, "buffer")) === null || _a === void 0 ? void 0 : _a.toString) === null || _b === void 0 ? void 0 : _b.call(_a, "utf8")) === null || _c === void 0 ? void 0 : _c.replace) === null || _d === void 0 ? void 0 : _d.call(_c, /[\b\f\n\r\t\v]/g, "")) || null;
}
}
exports.AnalyzeTData = AnalyzeTData;
function getDefaultJson(phoneNumber = "") {
var _a;
const phone = (_a = phoneNumber === null || phoneNumber === void 0 ? void 0 : phoneNumber.replace) === null || _a === void 0 ? void 0 : _a.call(phoneNumber, /^(\+)?(\d+)/, "+$2");
const defaultJsonObject = lodash_1.default.assign({}, (0, exports.oldTelegram)(), getLangCode({ phone }));
return defaultJsonObject;
}
function formatJsonAndSession(props = {}) {
let { session, json, remark } = props;
if (!lodash_1.default.isEmpty(json) && Array.isArray(json)) {
json = lodash_1.default.map(lodash_1.default.filter(json, Boolean), (item) => {
var _a, _b;
let jsonObject = {};
const originalname = iconv_lite_1.default.decode(Buffer.from(lodash_1.default.get(item, "originalname", ""), "binary"), "utf-8");
const extname = path_1.default.extname(originalname);
const sessionFile = path_1.default.basename(originalname, extname);
try {
jsonObject = lodash_1.default.mapKeys(JSON.parse(lodash_1.default.get(item, "buffer", []).toString()), (value, key) => lodash_1.default.camelCase(key));
}
catch (error) {
return {};
}
const phone = (_b = (_a = lodash_1.default.get(jsonObject, "phone", "")) === null || _a === void 0 ? void 0 : _a.replace) === null || _b === void 0 ? void 0 : _b.call(_a, /^(\+)?(\d+)/, "+$2");
const defaultJsonObject = getDefaultJson(phone);
const { appId: apiId, appHash: apiHash, device: deviceModel, systemLangPack: systemLangCode, twoFa, sdk: systemVersion, deviceToken, langPack, tzOffset, appVersion, langCode, cFingerpting, installer, packageId, email, userId, password, password2Fa, } = jsonObject;
let jsonBetterData = {
sessionFile,
phone: sessionFile || phone,
apiId,
apiHash,
deviceModel,
systemLangCode,
deviceToken,
langPack,
tzOffset,
appVersion,
systemVersion,
password: twoFa || password || password2Fa,
langCode,
cFingerpting,
installer,
packageId,
email,
userId,
};
jsonBetterData = lodash_1.default.mapValues(jsonBetterData, (value, key) => {
return value || defaultJsonObject[key];
});
jsonBetterData.isUseProxy = 2;
jsonBetterData.proxy = {};
const sessionLength = Object.values(jsonBetterData).length;
const nextSessionLength = lodash_1.default.filter(Object.values(jsonBetterData), exports.clearEmptyBy).length;
if (sessionLength - nextSessionLength >= 5) {
return {};
}
return jsonBetterData;
});
}
if (!lodash_1.default.isEmpty(session) && Array.isArray(session)) {
session = lodash_1.default.map(lodash_1.default.filter(session, Boolean), (item) => {
const originalname = iconv_lite_1.default.decode(Buffer.from(lodash_1.default.get(item, "originalname", ""), "binary"), "utf-8");
const extname = path_1.default.extname(originalname);
const sessionFile = path_1.default.basename(originalname, extname);
try {
const buffer = lodash_1.default.get(item, "buffer", []);
const db = new better_sqlite3_1.default(buffer);
let result = db.prepare("SELECT * FROM sessions").get();
db.close();
const currentTime = (0, dayjs_1.default)(new Date()).format("YYYY-MM-DD HH:mm:ss");
result = lodash_1.default.mapKeys(result, (value, key) => lodash_1.default.camelCase(key));
const { authKey, port, dcId, serverAddress } = result;
const sessionObject = {
sessionFile,
authKey,
port,
dcId,
serverAddress,
remark: remark || `${currentTime}-导入`,
accountStatus: 2,
};
if (lodash_1.default.isNil(authKey) || lodash_1.default.isNil(dcId)) {
return {};
}
// if (!serverAddress || !port) {
// const { ipAddress, port } = _.keyBy(androidDcList, 'id')[dcId] || {};
// sessionObject.serverAddress = ipAddress;
// sessionObject.port = port;
// }
const sessionLength = Object.values(sessionObject).length;
const nextSessionLength = lodash_1.default.filter(Object.values(sessionObject), exports.clearEmptyBy).length;
if (sessionLength - nextSessionLength >= 1) {
return {};
}
return sessionObject;
}
catch (error) {
return {};
}
});
}
const sessions = lodash_1.default.values(lodash_1.default.merge(lodash_1.default.keyBy(session, "sessionFile"), lodash_1.default.keyBy(json, "sessionFile")));
const result = lodash_1.default.reduce(sessions, (result, item) => {
var _a, _b;
if (!lodash_1.default.isEmpty(item) && !lodash_1.default.isNil(lodash_1.default.get(item, "authKey"))) {
const defaultJsonObject = getDefaultJson(item.phone);
const phone = (_b = (_a = lodash_1.default.get(item, "phone", lodash_1.default.get(item, "sessionFile"))) === null || _a === void 0 ? void 0 : _a.replace) === null || _b === void 0 ? void 0 : _b.call(_a, /^(\+)?(\d+)/, "+$2");
result.push(lodash_1.default.assign(defaultJsonObject, item, {
phone,
country: getCountryByPhone(phone) || "未知",
remark,
}));
}
return result;
}, []);
return result;
}
function checkImportData(props = {}) {
var _a;
let { json = [], session = [], zip = [], tdata = [], remark } = props;
const fileList = [...json, ...session, ...zip, ...tdata];
//校验格式是否正确
const isHaveCanResolve = (_a = ["session", "zip"]) === null || _a === void 0 ? void 0 : _a.some((field) => fileList === null || fileList === void 0 ? void 0 : fileList.some((item) => { var _a, _b; return (_b = (_a = ((item === null || item === void 0 ? void 0 : item.originalname) || "")) === null || _a === void 0 ? void 0 : _a.endsWith) === null || _b === void 0 ? void 0 : _b.call(_a, field); }));
if (!isHaveCanResolve) {
return {
code: 403,
msg: "请正确上传会话文件",
info: {},
};
}
if (!lodash_1.default.isEmpty(zip) && Array.isArray(zip)) {
zip = lodash_1.default.flattenDeep(lodash_1.default.map(zip, (item) => {
const buffer = lodash_1.default.get(item, "buffer", []);
const zip = new adm_zip_1.default(buffer);
const zipEntries = zip.getEntries();
const zipFiles = lodash_1.default.map(zipEntries, (zipEntry) => {
const originalname = iconv_lite_1.default.decode(Buffer.from(lodash_1.default.get(zipEntry, "entryName", ""), "binary"), "utf-8");
const ext = path_1.default.extname(originalname);
const sessionFile = path_1.default.basename(originalname, ext);
const buffer = zipEntry.getData();
return {
sessionFile,
buffer,
originalname,
size: buffer.length,
ext,
};
});
const groups = lodash_1.default.map(lodash_1.default.groupBy(zipFiles, (item) => item.sessionFile), (list) => {
return lodash_1.default.reduce(list, (pre, cur) => {
if (lodash_1.default.get(cur, "ext", "").endsWith("json")) {
return lodash_1.default.assign({}, pre, {
json: cur,
});
}
if (lodash_1.default.get(cur, "ext", "").endsWith("session")) {
return lodash_1.default.assign({}, pre, {
session: cur,
});
}
return pre;
}, {});
});
return formatJsonAndSession({
json: lodash_1.default.map(groups, "json", []),
session: lodash_1.default.map(groups, "session", []),
remark,
});
}));
}
if (!lodash_1.default.isEmpty(tdata) && Array.isArray(tdata)) {
tdata = lodash_1.default.flattenDeep(lodash_1.default.map(tdata, (item) => {
const buffer = lodash_1.default.get(item, "buffer", []);
const zip = new adm_zip_1.default(buffer);
const zipEntries = zip.getEntries();
const zipFiles = lodash_1.default.map(zipEntries, (zipEntry) => {
var _a;
let originalname = iconv_lite_1.default.decode(Buffer.from(lodash_1.default.get(zipEntry, "entryName", ""), "binary"), "utf-8");
originalname = (_a = originalname === null || originalname === void 0 ? void 0 : originalname.replace) === null || _a === void 0 ? void 0 : _a.call(originalname, /\/{2,}/g, "/");
const ext = path_1.default.extname(originalname);
const sessionFile = path_1.default.basename(originalname, ext);
const buffer = zipEntry.getData();
return {
sessionFile,
buffer,
originalname,
size: buffer.length,
ext,
isDirectory: zipEntry.isDirectory,
};
});
let rootList = lodash_1.default.filter(zipFiles, (item) => !!item.isDirectory);
if (lodash_1.default.isEmpty(rootList)) {
zipFiles.push(...lodash_1.default.map(lodash_1.default.compact([
...new Set(lodash_1.default.flattenDeep(lodash_1.default.map(zipFiles, (item) => identifyTheDirectory(lodash_1.default.get(item, "originalname", ""))))),
]), (originalname) => {
return {
originalname,
sessionFile: lodash_1.default.last(lodash_1.default.compact(lodash_1.default.split(originalname, "/"))),
isDirectory: true,
};
}));
rootList = lodash_1.default.filter(zipFiles, (item) => !!item.isDirectory);
}
const tdataMaps = rootList.reduce((result, curItem) => {
var _a;
const phone = lodash_1.default.get(curItem, "sessionFile", "");
const phoneNumber = (_a = phone === null || phone === void 0 ? void 0 : phone.replace) === null || _a === void 0 ? void 0 : _a.call(phone, /^(\+)?(\d+)/, "+$2");
if (isValidInternationalPhoneNumber(phoneNumber)) {
result[phone] = lodash_1.default.filter(zipFiles, (item) => lodash_1.default.get(item, "originalname", "").includes(phone));
}
return result;
}, {});
const results = lodash_1.default.reduce(lodash_1.default.entries(tdataMaps), (all, [phone, buffers]) => {
try {
const newTData = new AnalyzeTData({
phone,
buffers,
sessionInfo: {
remark,
sessionFile: phone,
},
});
newTData.run();
all.push(lodash_1.default.get(newTData, "sessionInfo", {}));
}
catch (error) { }
return all;
}, []);
return results;
}));
}
const sessions = lodash_1.default.uniqBy(lodash_1.default.merge(formatJsonAndSession({
session,
json,
remark,
}), zip, tdata), "sessionFile");
return sessions;
}
function getFileName(props = {}) {
let { json = [], session = [], zip = [], tdata = [] } = props;
const fileList = [...json, ...session, ...zip, ...tdata];
let params = {
sessionFile: "",
extName: [],
};
lodash_1.default.forEach(fileList, (item) => {
let originalname = lodash_1.default.get(item, "originalname", "");
originalname = iconv_lite_1.default.decode(Buffer.from(originalname, "utf8"), // 直接使用正确的编码方式
"utf-8");
const extName = path_1.default.extname(originalname);
const sessionFile = path_1.default.basename(originalname, extName);
params.sessionFile = sessionFile;
params.extName.push(extName);
});
params.extName = params.extName.join("|");
return params;
}
function formatErrorMessage(message) {
return lodash_1.default.reduce(Object.entries(errorMsgMaps), (msg, [key, val]) => {
var _a, _b;
return ((_b = (_a = message === null || message === void 0 ? void 0 : message.toLocaleLowerCase()) === null || _a === void 0 ? void 0 : _a.indexOf) === null || _b === void 0 ? void 0 : _b.call(_a, key.toLocaleLowerCase())) !==
-1
? `${val}${message}`
: msg;
}, message);
}
function getError(error) {
const propertyNames = Object.getOwnPropertyNames(error);
return lodash_1.default.reduce(propertyNames, (err, key) => lodash_1.default.assign({}, err, { [key]: error[key] }), {});
}
class CustomError extends Error {
constructor(props) {
const { msg } = props;
super(msg); // 调用父类的constructor,设置错误消息
lodash_1.default.assign(this, props);
}
}
exports.CustomError = CustomError;
async function clientDestroy(client) {
var _a, _b;
try {
await ((_a = client === null || client === void 0 ? void 0 : client.disconnect) === null || _a === void 0 ? void 0 : _a.call(client));
await ((_b = client === null || client === void 0 ? void 0 : client.destroy) === null || _b === void 0 ? void 0 : _b.call(client));
if (!!(client === null || client === void 0 ? void 0 : client.disconnect) && !(client === null || client === void 0 ? void 0 : client.disconnected)) {
return await clientDestroy(client);
}
}
catch (error) {
if (!!(client === null || client === void 0 ? void 0 : client.disconnect) && !(client === null || client === void 0 ? void 0 : client.disconnected)) {
return await clientDestroy(client);
}
}
}
async function returnSingleSimpleClient(props) {
let { sessionInfo = {} } = lodash_1.default.cloneDeep(props);
let { phone, proxy } = sessionInfo;
sessionInfo.phone = phone.replace(/^(\+)?(\d+)/, "+$2");
const session = new StoreSession();
sessionInfo = lodash_1.default.assign({}, (0, exports.oldTelegram)(), getLangCode({ phone }), sessionInfo, {
phone,
proxy,
});
if (!lodash_1.default.isEmpty(proxy)) {
sessionInfo.proxy = formatProxy(proxy);
}
else {
sessionInfo = lodash_1.default.omit(sessionInfo, ["proxy"]);
}
session.sessionInfo = sessionInfo;
await session.init();
const { apiHash, apiId } = sessionInfo;
const client = new __1.TelegramClient(session, apiId, apiHash, Object.assign(Object.assign({}, sessionInfo), { floodSleepThreshold: 5, connectionRetries: 1, requestRetries: 5, retryDelay: 0, useWSS: true }));
client.sessionInfo = sessionInfo;
client.setLogLevel("none");
const initRequest = (0, exports.getInitConnection)(sessionInfo);
client._initRequest = new __1.Api.InitConnection(initRequest);
try {
const preConnect = Date.now();
const result = await Promise.race([client.connect(), asleep(50000)]);
const curConnect = Math.ceil((Date.now() - preConnect) / 1000);
console.log(`${phone}---使用${curConnect}秒连接客户端-${!!result}`);
return client;
}
catch (error) {
await clientDestroy(client);
throw new CustomError(lodash_1.default.assign({}, getError(error), {
phone,
}));
}
}
async function createSingleSimpleClient(props) {
let { sessionInfo = {}, callback } = lodash_1.default.cloneDeep(props);
let { phone, proxy } = sessionInfo;
sessionInfo.phone = phone.replace(/^(\+)?(\d+)/, "+$2");
const session = new StoreSession();
sessionInfo = lodash_1.default.assign({}, (0, exports.oldTelegram)(), getLangCode({ phone }), sessionInfo, {
phone,
proxy,
});
if (!lodash_1.default.isEmpty(proxy)) {
sessionInfo.proxy = formatProxy(proxy);
}
else {
sessionInfo = lodash_1.default.omit(sessionInfo, ["proxy"]);
}
session.sessionInfo = sessionInfo;
await session.init();
const { apiHash, apiId } = sessionInfo;
const client = new __1.TelegramClient(session, apiId, apiHash, Object.assign(Object.assign({}, sessionInfo), { floodSleepThreshold: 5, connectionRetries: 1, requestRetries: 5, retryDelay: 0, useWSS: true }));
client.sessionInfo = sessionInfo;
client.setLogLevel("none");
const initRequest = (0, exports.getInitConnection)(sessionInfo);
client._initRequest = new __1.Api.InitConnection(initRequest);
try {
const preConnect = Date.now();
const connectResult = await Promise.race([
client.connect(),
asleep(60000),
]);
const curConnect = Math.ceil((Date.now() - preConnect) / 1000);
console.log(`${phone}---使用${curConnect}秒连接客户端-${!!connectResult}`);
const result = await Promise.race([callback(client), asleep(140000)]);
await clientDestroy(client);
if (lodash_1.default.isNull(result)) {
throw new CustomError({
code: 504,
msg: "TG呆滞时间过久",
info: {},
phone,
});
}
return lodash_1.default.assign({}, result, {
phone,
});
}
catch (error) {
await clientDestroy(client);
throw new CustomError(lodash_1.default.assign({}, getError(error), {
phone,
}));
}
}