Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save s3rgeym/eee96bbf91b04f7eb46b7449f8884a00 to your computer and use it in GitHub Desktop.
Save s3rgeym/eee96bbf91b04f7eb46b7449f8884a00 to your computer and use it in GitHub Desktop.

У HH есть API. Но к сожалению любой желающий приложение создать не сможет и нужно проходить премодерацию... либо воспользоваться данными от офиц приложения.

Сначала зайдем в Google Market с телефона, найдем приложение:

image

Поделимся ссылкой самим с собой:

image

Через любой из этих сайтов скачиваем:

И декомпилируем APK через этот сайт.

image

Grep'ом мне не удалось найти CLIENT_ID и CLIENT_SECRET, пришлось ставить Java и запускать VS Code. ИЧСХ, Java сожрала всю память, но я отыскал нужное:

private final Scope m33076w() {
    C24801c cVar = new C24801c("head_hunter_applicant", false, "release", R.mipmap.ic_launcher);
    C24799a aVar = new C24799a("HIOMIAS39CA9DICTA7JIO64LQKQJF5AGIK74G9ITJKLNEDAOH5FHS5G1JI7FOEGD", "V9M870DE342BGHFRUJ5FTCGCUA1482AN0DI8C5TFI9ULMA89H10N60NOP8I4JMVS", "hhandroid://oauthresponse", "https://api.hh.ru/");
    C11249DI.m33576b();
    C11249DI.m33575a().mo50911g(this, cVar, aVar);
    return C11249DI.m33575a().mo50912h();
}

// Первое значение CLIENT_ID, второе — CLIENT_SECRET
public C24799a(String str, String str2, String str3, String str4) {
    Intrinsics.checkNotNullParameter(str, "CLIENT_ID");
    Intrinsics.checkNotNullParameter(str2, "CLIENT_SECRET");
    Intrinsics.checkNotNullParameter(str3, "REDIRECT_URI");
    Intrinsics.checkNotNullParameter(str4, "URL_BASE_API");
    this.f46656a = str;
    this.f46657b = str2;
    this.f46658c = str3;
    this.f46659d = str4;
}

Прямая авторизация к сожалению больше не работает:

// Получение токена напрямую
public OAuthRequest createAccessTokenPasswordGrantRequest(String str, String str2) {
    // POST https://hh.ru/oauth/token
    OAuthRequest oAuthRequest = new OAuthRequest(this.api.getAccessTokenVerb(), this.api.getAccessTokenEndpoint());
    OAuthConfig config = getConfig();
    oAuthRequest.addParameter("username", str);
    oAuthRequest.addParameter("password", str2);
    String scope = config.getScope();
    if (scope != null) {
        oAuthRequest.addParameter(OAuthConstants.SCOPE, scope);
    }
    oAuthRequest.addParameter(OAuthConstants.GRANT_TYPE, "password");
    String apiKey = config.getApiKey();
    String apiSecret = config.getApiSecret();
    if (!(apiKey == null || apiSecret == null)) {
        // Authorization
        oAuthRequest.addHeader(OAuthConstants.HEADER, "Basic " + Base64Encoder.getInstance().encode(String.format("%s:%s", new Object[]{apiKey, apiSecret}).getBytes(Charset.forName("UTF-8"))));
    }
    return oAuthRequest;
}
>>> http_client.post('https://hh.ru/oauth/token', {'username': 'user', 'password': 'pswd', 'scope': '', 'grant_type': 'password'}, auth=(CLIENT_ID, CLIENT_SECRET)).json()
{'error': 'unsupported_grant_type', 'error_description': 'unsupported grant_type'}

Работает только авторизация через сайт:

https://hh.ru/oauth/authorize?response_type=code&client_id=HIOMIAS39CA9DICTA7JIO64LQKQJF5AGIK74G9ITJKLNEDAOH5FHS5G1JI7FOEGD&state=state&redirect_uri=

image

image

Приложение использует протокол hhandroid для обработки кода авторизации, указание какого-то другого значения в redirect_uri приводит к ошибке. Для регистрации обработчика пришлось извратиться:

$ cat ~/.local/share/applications/hhandroid.desktop
[Desktop Entry]
Type=Application
Name=HHAndroid Handler
Exec=open-hhandroid.sh %u
StartupNotify=false
MimeType=x-scheme-handler/hhandroid;

$ micro ~/bin/open-hhandroid.sh                      

$ chmod +x ~/bin/open-hhandroid.sh

$ cat ~/bin/open-hhandroid.sh
#!/usr/bin/env bash
xdg-open "http://localhost:12345/?q=$1"

$ xdg-mime default hhandroid-opener.desktop x-scheme-handler/hhandroid

Работат:

image

Я пытался еще расширение сделать, но protocol_handlers работают только в Firefox, а фуррифокс говно. Еще есть Navigator.registerProtocolHandler(), но...

Теперь нужно из кода авторизации получить access_token:

Python 3.10.9 (main, Dec 19 2022, 17:35:49) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import requests
>>> requests.post('https://hh.ru/oauth/token', {'grant_type': 'authorization_code', 'client_id': "HIOMIAS39CA9DICTA7JIO64LQKQJF5AGIK74G9ITJKLNEDAOH5FHS5G1JI7FOEGD", 'client_secret': "V9M870DE342BGHFRUJ5FTCGCUA1482AN0DI8C5TFI9ULMA89H10N60NOP8I4JMVS", 'code': '<CODE>'}).json()
{'access_token': '<ACCESS_TOKEN>', 'token_type': 'bearer', 'refresh_token': '<REFRESH_TOKEN>', 'expires_in': 1209599}

Для запросов к API используется этот User-Agent?

String format = String.format(Locale.ENGLISH, "%s/%s.%d, Device: %s, Android OS: %s (UUID: %s)", Arrays.copyOf(new Object[]{this.f45885a.mo99828c(), this.f45885a.mo99826a(), Integer.valueOf(this.f45885a.mo99827b()), Build.MODEL, Build.VERSION.RELEASE, this.f45886b.mo99833c()}, 6));
@s3rgeym
Copy link
Author

s3rgeym commented Mar 4, 2023

UUID.randomUUID().toString() => 51c5b94a-da4f-4c43-8c62-94b0a584e73f

@s3rgeym
Copy link
Author

s3rgeym commented Mar 4, 2023

первое packageName

    public static String m37235c(String str) {
        String str2;
        StringBuilder sb = new StringBuilder();
        sb.append(str);
        sb.append("/");
        sb.append("5.0.1");
        sb.append(".");
        sb.append("45001730");
        sb.append(" (");
        String str3 = Build.MODEL;
        String str4 = Build.MANUFACTURER;
        if (str3.startsWith(str4)) {
            str2 = C14166O2.m38267a(str3);
        } else {
            str2 = C14166O2.m38267a(str4) + " " + str3;
        }
        sb.append(str2);
        sb.append("; Android ");
        sb.append(Build.VERSION.RELEASE);
        sb.append(")");
        return sb.toString();
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment