Страницы

Поиск по вопросам

среда, 22 января 2020 г.

Сохранение сессии Telegram API

#java #telegram_api


Приветствую.

Возник вопрос по поводу Telegram API (не Bot API). Не могу понять, как сохранить
данные пользователя после его первой аутентификации в приложении. В данный момент при
каждом входе идет запрос кода. 

После первого удачного входа пробовал сохранять phoneCodeHash, номер телефона и phoneCode.
В принципе, это работает до истечения срока кода аутентификации.

Возможно, сейчас я путаю, потому что использую представление данного API на Java
с библиотекой Kotlogram. Реализация аутентификации в сэмпле:

ApiStorage.java

public static class ApiStorage implements TelegramApiStorage {

//Create File variable for auth.key and dc.save
public static final File AUTH_KEY_FILE = new File("Properties/auth.key");
public static final File NEAREST_DC_FILE = new File("Properties/dc.save");

@Override
public void saveAuthKey(@NotNull AuthKey authKey) {
    try {
        FileUtils.writeByteArrayToFile(AUTH_KEY_FILE, authKey.getKey());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Nullable
@Override
public AuthKey loadAuthKey() {
    try {
        return new AuthKey(FileUtils.readFileToByteArray(AUTH_KEY_FILE));
    } catch (IOException e) {
        if (!(e instanceof FileNotFoundException))
            e.printStackTrace();
    }

    return null;
}

@Override
public void saveDc(@NotNull DataCenter dataCenter) {
    try {
        FileUtils.write(NEAREST_DC_FILE, dataCenter.toString());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Nullable
@Override
public DataCenter loadDc() {
    try {
        String[] infos = FileUtils.readFileToString(NEAREST_DC_FILE).split(":");
        return new DataCenter(infos[0], Integer.parseInt(infos[1]));
    } catch (IOException e) {
        if (!(e instanceof FileNotFoundException))
            e.printStackTrace();
    }

    return null;
}

@Override
public void deleteAuthKey() {
    try {
        FileUtils.forceDelete(AUTH_KEY_FILE);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void deleteDc() {
    try {
        FileUtils.forceDelete(NEAREST_DC_FILE);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void saveSession(@Nullable MTSession session) {

}

@Nullable
@Override
public MTSession loadSession() {
    return null;
}
}


Сама аутентификация в Java Console.

public class Main {
// Get them from Telegram's console
public static final int API_ID = api id;
public static final String API_HASH = api hash;

// What you want to appear in the "all sessions" screen
public static final String APP_VERSION = "AppVersion";
public static final String MODEL = "Model";
public static final String SYSTEM_VERSION = "SysVer";
public static final String LANG_CODE = "en";

public static TelegramApp application = new TelegramApp(API_ID, API_HASH, MODEL,
SYSTEM_VERSION, APP_VERSION, LANG_CODE);
public static final String PHONE_NUMBER = "тут был телефон"; // International format

public static void main(String[] args) {
    TelegramClient client = Kotlogram.getDefaultClient(application, new ApiStorage());

    try {
        TLSentCode sentCode = client.authSendCode(false, PHONE_NUMBER, true);
        System.out.println("Authentication code: ");
        String code = new Scanner(System.in).nextLine();

        TLAuthorization authorization = client.authSignIn(PHONE_NUMBER, sentCode.getPhoneCodeHash(),
code);
        TLUser self = authorization.getUser().getAsUser();
        System.out.println("You are now signed in as " + self.getFirstName() + "
" + self.getLastName() + " @" + self.getUsername());
    } catch (RpcErrorException | IOException e) {
        e.printStackTrace();
    } finally {
        client.close(); // Important, do not forget this, or your process won't finish
    }
}
}


Данную реализацию я использую в Android приложении. Конечно, все раскидано по асинхронным
потокам. Но каждый раз при входе в приложение идет проверка кода авторизации. Из-за
этого я за сегодня заблокировал 3 разных аккаунта на день по причине флуда авторизации.

В качестве обходного варианта я использовал подстановку значений в данном методе,
запоминая их при удачной авторизации. 

client.authSignIn(phoneNumber, phoneCodeHash, phoneCode);


Это работает только до того момента, пока код не истечет.
Возможно, кто-то знает как это решается на уровне самого API, а не библиотеки, или
сможет предложить вариант использования других подходов для работы с Telegram API:
стандартный API, TDlib или какое-либо другое решение для авторизации пользователей
в приложении через Telegram на Java.

Честно, не смог ни с чем другим разобраться. 
Заранее благодарю за ответы.
    


Ответы

Ответ 1



Нашел решение методом научного тыка. Я был действительно не прав, т.к. данная библиотека сама умеет отрабатывать сессии. Просто делает это (на мой взгляд) очень неочевидно. Прикладываю ниже рабочее решение в виде консольного приложения на Java. Это же решение работает и для Android приложения. public class Main { // Get them from Telegram's console private static final int API_ID = /*put api id here*/; private static final String API_HASH = "put hash here"; // What you want to appear in the "all sessions" screen private static final String APP_VERSION = "AppVersion"; private static final String MODEL = "Model"; private static final String SYSTEM_VERSION = "SysVer"; private static final String LANG_CODE = "en"; private static TelegramApp application = new TelegramApp(API_ID, API_HASH, MODEL, SYSTEM_VERSION, APP_VERSION, LANG_CODE); private static final String PHONE_NUMBER = "put a phone number here"; // International format public static void main(String[] args) { TelegramClient client = Kotlogram.getDefaultClient(application, new ApiStorage()); try { TLUserFull userFull = client.usersGetFullUser(new TLInputUserSelf()); TLUser self = userFull.getUser().getAsUser(); showUserInfo(self); } catch (RpcErrorException e) { if (e.getTag().equals("AUTH_KEY_UNREGISTERED")) signInUser(client); else e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { client.close(); } } private static void signInUser(TelegramClient client) { try { // Send code to account TLSentCode sentCode = client.authSendCode(false, PHONE_NUMBER, true); System.out.println("Authentication code: "); String code = new Scanner(System.in).nextLine(); TLAuthorization authorization = client.authSignIn(PHONE_NUMBER, sentCode.getPhoneCodeHash(), code); TLUser self = authorization.getUser().getAsUser(); showUserInfo(self); } catch (Exception e) { e.printStackTrace(); } } private static void showUserInfo(TLUser user) { System.out.println("You are now signed in as " + user.getFirstName() + " " + user.getLastName() + " @" + user.getUsername()); } } Не знаю, кто плюсовал данный вопрос, но, надеюсь, что оно кому-нибудь поможет. Спасибо.

Комментариев нет:

Отправить комментарий