hk_bot/utils.ts

231 lines
7.2 KiB
TypeScript

import Docker from "dockerode";
import logger from "./logger";
import { settings } from "./database";
// import Hero from "@ulixee/hero";
// import Miner from "@ulixee/miner";
import { sleep } from "telegram/Helpers";
import { AccountInterface } from "./interfaces/databaseInterface";
import * as telegram from "telegram";
import axios from "axios";
import cliProgress from "cli-progress";
import { isNull, isUndefined } from "lodash";
export class CaptchaError extends Error {}
export class NoNewMessagesError extends Error {}
export class DockerIsBrockenError extends Error {}
export function randomAB(a: number, b: number) {
return Math.floor(Math.random() * (b - a + 1) + a);
}
export async function isBannedByClient(
client: telegram.TelegramClient,
username: string
): Promise<boolean> {
const blockedUsers = (
await client.invoke(
new telegram.Api.contacts.GetBlocked({ limit: 2147483647 })
)
).users as telegram.Api.User[];
for (const blockedUser of blockedUsers) {
if (
blockedUser.username !== undefined &&
blockedUser.username == username.replace("@", "")
) {
return true;
}
}
return false;
}
export async function getMessagesByEntity(
client: telegram.TelegramClient,
chatEntity: telegram.Api.Chat | telegram.Api.User | string,
entity: telegram.Api.User | string,
params = {}
) {
const messages = new telegram.helpers.TotalList<telegram.Api.Message>();
if (entity instanceof telegram.Api.User) {
for (const message of await client.getMessages(chatEntity, params)) {
if (
(message.sender as telegram.Api.User).username ==
entity.username
) {
messages.push(message);
}
}
} else {
for (const message of await client.getMessages(chatEntity, params)) {
if (
isNull((message.sender as telegram.Api.User).username) !=
true &&
isUndefined((message.sender as telegram.Api.User).username) !=
true
) {
if (
(message.sender as telegram.Api.User).username!.includes(
entity.replace("@", "")
)
) {
messages.push(message);
}
}
}
}
return messages;
}
export function arrayWithoutElementAtIndex(
arr: AccountInterface[] | [],
index: number
) {
return arr.filter(function (value, arrIndex) {
return index !== arrIndex;
});
}
export async function getIP(proxyPort: number): Promise<string | null> {
// https://github.com/ulixee/unblocked/blob/main/plugins/default-browser-emulator/lib/helpers/lookupPublicIp.ts
let data: string | PromiseLike<string | null> | null;
try {
data = (
await axios.get("http://icanhazip.com/", {
proxy: {
host: "127.0.0.1",
port: proxyPort,
},
timeout: 100000,
})
).data;
} catch (err) {
logger.debug(err);
return null;
}
if ((await data) == null || (await data)!.trim() == "") {
return null;
}
return await data;
}
export async function waitNewMessages(
client: telegram.TelegramClient,
worker: AccountInterface,
chatEntity: telegram.Api.Chat | telegram.Api.User | string,
idOfLastMessage: number,
timeout = 20
): Promise<void> {
const start_time = new Date();
while (
(
await getMessagesByEntity(
client,
chatEntity,
chatEntity as telegram.Api.User | string,
{ minId: idOfLastMessage, limit: 2147483647 }
)
).length == 0
) {
if ((+new Date() - +start_time) / 1000 >= timeout) {
logger.error(
`${worker.phoneNumber} | Bot didnt answer for ${timeout}s`
);
throw new NoNewMessagesError("Is bot working?");
}
}
logger.debug(`${worker.phoneNumber} | Bot answered`);
}
export async function startNewTorDocker(
proxyPort: number,
socksPort: number,
controlPort: number,
mainProgressBar: cliProgress.MultiBar,
timeout = 200
): Promise<Docker.Container> {
timeout *= 2;
const docker = new Docker({ socketPath: "/var/run/docker.sock" });
let isPulled = false;
mainLoop: for (const image of await docker.listImages()) {
const tags = image.RepoTags;
if (tags !== undefined)
for (const repoTag of tags) {
if (repoTag.search("dperson/torproxy:latest") != -1) {
isPulled = true;
break mainLoop;
}
}
}
if (isPulled != true) {
await docker.pull("dperson/torproxy:latest");
}
// bugy shit
const options: Docker.ContainerCreateOptions = {
Image: "dperson/torproxy",
Env: ["PASSWORD=qwerty", "LOCATION=US", "TOR_NewCircuitPeriod=50"],
ExposedPorts: {},
HostConfig: {
PortBindings: {
"8118/tcp": [
{
HostPort: `${proxyPort}`,
},
],
"9050/tcp": [
{
HostPort: `${socksPort}`,
},
],
"9051/tcp": [
{
HostPort: `${controlPort}`,
},
],
},
},
Healthcheck: {
Interval: 2 * 1000000000,
Timeout: 50 * 1000000000,
StartPeriod: 50 * 1000000000,
// Test:['CMD_SHELL',`curl -sx localhost:8118 'https://check.torproject.org/' | grep -qm1 Congratulations`]
},
};
const container = await docker.createContainer(options);
await container.start();
const progressBar = mainProgressBar.create(timeout / 2, 0, {
status: `Starting docker${
settings.logLevel == "debug"
? ` ${proxyPort} ${socksPort} ${controlPort}`
: ""
}`,
});
while ((await container.inspect())!.State.Health!.Status != "healthy") {
const state = (await container.inspect())!.State.Health!.Status;
if (progressBar.getProgress() >= timeout) {
await container.kill();
progressBar.update(timeout / 2, { status: "Failed" });
progressBar.stop();
throw new DockerIsBrockenError(`Docker ${container.id} is broken`);
}
if (state == "unhealthy") {
await container.kill();
progressBar.update(timeout / 2, {
status: "Docker is unhealthy...",
});
progressBar.stop();
return await startNewTorDocker(
proxyPort,
socksPort,
controlPort,
mainProgressBar,
timeout / 2
);
}
progressBar.increment();
await sleep(2000);
}
progressBar.update(0, { status: "Started" });
progressBar.stop();
return container;
}