Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ban from Telegram when authorise/monitor multiple accounts with TDLib on Java #1197

Closed
ashvydkyi opened this issue Sep 17, 2020 · 1 comment

Comments

@ashvydkyi
Copy link

ashvydkyi commented Sep 17, 2020

hey guys,

Based on this comment, to authorize multiple accounts with TDLib, we can create as many TDLib clients as I need and initialize them with different database folders.
Bellow plain client to authorize multiple accounts based on this example

import java.io.FileNotFoundException;
import java.io.IOError;
import java.io.IOException;
import java.util.Arrays;
import org.drinkless.tdlib.TdApi;
import org.drinkless.tdlib.TdApi.AuthorizationState;
import org.drinkless.tdlib.TdApi.AuthorizationStateClosed;
import org.drinkless.tdlib.TdApi.AuthorizationStateClosing;
import org.drinkless.tdlib.TdApi.AuthorizationStateLoggingOut;
import org.drinkless.tdlib.TdApi.AuthorizationStateReady;
import org.drinkless.tdlib.TdApi.AuthorizationStateWaitEncryptionKey;
import org.drinkless.tdlib.TdApi.AuthorizationStateWaitOtherDeviceConfirmation;
import org.drinkless.tdlib.TdApi.AuthorizationStateWaitPhoneNumber;
import org.drinkless.tdlib.TdApi.AuthorizationStateWaitTdlibParameters;
import org.drinkless.tdlib.TdApi.CheckDatabaseEncryptionKey;
import org.drinkless.tdlib.TdApi.Function;
import org.drinkless.tdlib.TdApi.Object;
import org.drinkless.tdlib.TdApi.RequestQrCodeAuthentication;
import org.drinkless.tdlib.TdApi.SetTdlibParameters;
import org.drinkless.tdlib.TdApi.TdlibParameters;
import org.drinkless.tdlib.TdApi.UpdateAuthorizationState;
import org.drinkless.tdlib.TdApi.UpdateNewMessage;
import org.springframework.util.ResourceUtils;

public final class Client implements Runnable {

    static {
        try {
            System.load(ResourceUtils.getFile("classpath:libs/mac/amd64/tdjni.dylib").getAbsolutePath());
            nativeClientExecute(new TdApi.SetLogVerbosityLevel(0));
            if (nativeClientExecute(new TdApi.SetLogStream(new TdApi.LogStreamFile("logs/tdlib.log", 1 << 27))) instanceof TdApi.Error) {
                throw new IOError(new IOException("Write access to the current directory is required"));
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException("Unable to execute static initialization");
        }
    }

    private static native long createNativeClient();

    private static native void nativeClientSend(long nativeClientId, long eventId, TdApi.Function function);

    private static native int nativeClientReceive(long nativeClientId, long[] eventIds, TdApi.Object[] events, double timeout);

    private static native TdApi.Object nativeClientExecute(TdApi.Function function);

    private static native void destroyNativeClient(long nativeClientId);

    private final long nativeClientId;
    private final long databaseId;

    public Client(long databaseId) {
        this.nativeClientId = createNativeClient();
        this.databaseId = databaseId;
    }

    public void poll() {
        Arrays.stream(receive()).forEach(response -> {
            if (response == null || response.getObject() == null) {
                return;
            }
            if (response.getObject() instanceof UpdateAuthorizationState) {
                UpdateAuthorizationState updateAuthorizationState = (UpdateAuthorizationState) response.getObject();
                handleAuthorizationState(updateAuthorizationState.authorizationState);
            } else if (response.getObject() instanceof UpdateNewMessage) {
                UpdateNewMessage updateNewMessage = (UpdateNewMessage) response.getObject();
                System.out.println(updateNewMessage.message.content.toString());
            }
        });
    }

    @Override
    public void run() {
        while (true) {
            poll();
        }
    }

    private void handleAuthorizationState(AuthorizationState authorizationState) {
        switch (authorizationState.getConstructor()) {
            case AuthorizationStateWaitTdlibParameters.CONSTRUCTOR: {
                TdlibParameters parameters = new TdlibParameters();
                parameters.databaseDirectory = "database/" + databaseId;
                parameters.useMessageDatabase = true;
                parameters.useSecretChats = true;
                parameters.apiId = 1503950;
                parameters.apiHash = "86a6e7681d15ae34089b2bf9b3014188";
                parameters.systemLanguageCode = "en";
                parameters.deviceModel = "MacOS";
                parameters.systemVersion = "10.15.6";
                parameters.applicationVersion = "1.0.1";
                parameters.enableStorageOptimizer = true;
                send(new Request(2L, new SetTdlibParameters(parameters)));
                break;
            }
            case AuthorizationStateWaitEncryptionKey.CONSTRUCTOR: {
                send(new Request(3L, new CheckDatabaseEncryptionKey()));
                break;
            }
            case AuthorizationStateWaitPhoneNumber.CONSTRUCTOR: {
                send(new Request(4L, new RequestQrCodeAuthentication()));
                break;
            }
            case AuthorizationStateWaitOtherDeviceConfirmation.CONSTRUCTOR: {
                String link = ((AuthorizationStateWaitOtherDeviceConfirmation) authorizationState).link;
                System.out.println("Please confirm this login link '" + link + "' on another device; id='" + databaseId + "' ");
                break;
            }

            case AuthorizationStateReady.CONSTRUCTOR: {
                System.out.println("Authorised; id='" + databaseId + "' ");
                break;
            }
            case AuthorizationStateLoggingOut.CONSTRUCTOR: {
                System.out.println("Logging out; id='" + databaseId + "' ");
                break;
            }
            case AuthorizationStateClosing.CONSTRUCTOR: {
                System.out.println("Closing; id='" + databaseId + "' ");
                break;
            }
            case AuthorizationStateClosed.CONSTRUCTOR: {
                System.out.println("Closed; id='" + databaseId + "' ");
                break;
            }
            default: {
                System.out.println("Unsupported authorization state=" + authorizationState);
                break;
            }
        }
    }

    private Response[] receive() {
        long[] eventIds = new long[1000];
        Object[] events = new Object[1000];
        int resultSize = nativeClientReceive(nativeClientId, eventIds, events, 300.0);
        Response[] responses = new Response[resultSize];

        for (int i = 0; i < resultSize; ++i) {
            responses[i] = new Response(eventIds[i], events[i]);
        }
        return responses;
    }

    private void send(Request request) {
        nativeClientSend(nativeClientId, request.getId(), request.getFunction());
    }

    private static class Response {

        private long id;
        private Object object;

        public Response(long id, Object object) {
            this.id = id;
            this.object = object;
        }

        public long getId() {
            return this.id;
        }

        public Object getObject() {
            return this.object;
        }
    }

    private static class Request {

        private long id;
        private Function function;

        public Request(long id, Function function) {
            this.id = id;
            this.function = function;
        }

        public long getId() {
            return this.id;
        }

        public Function getFunction() {
            return this.function;
        }
    }
}

and usage

    public static void main(String[] args) {
        new Thread(new Client(1234567890)).start();
        new Thread(new Client(987654321)).start();
    }

and the parameters to change the database folder

parameters.databaseDirectory = "database/" + databaseId;

During testing, I authorized two accounts (AuthorizationStateReady was retreived) with different telephone numbers. I post a couple of messages and retrieved them successfully, but in a while, both accounts/telephone numbers were banned by telegram with the following message:

Your account was suspended for suspicious activity. If you think that this is a mistake, please write to recover@telegram.org your phone number and other details to recover the account.

any ideas about why it's happening??

@levlam
Copy link
Contributor

levlam commented Sep 17, 2020

The message contains all available information. We can't add anything besides it.

@levlam levlam closed this as completed Oct 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants