2018-12-17 21:55:26 -06:00
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
""" this is a patched version of vk_api to use a different user agent for authenticating against VK.
|
|
|
|
|
Everything else looks the same, the only change in the module is the new user agent, emulating a kate mobile session."""
|
2019-01-18 17:22:24 -06:00
|
|
|
|
import time
|
|
|
|
|
import hashlib
|
2018-12-17 21:55:26 -06:00
|
|
|
|
import logging
|
|
|
|
|
import vk_api
|
|
|
|
|
import threading
|
|
|
|
|
import requests
|
2019-01-02 04:42:53 +03:00
|
|
|
|
from . import jconfig_patched as jconfig
|
2018-12-17 21:55:26 -06:00
|
|
|
|
from vk_api.enums import VkUserPermissions
|
|
|
|
|
from vk_api.exceptions import *
|
|
|
|
|
|
|
|
|
|
DEFAULT_USER_SCOPE = sum(VkUserPermissions)
|
|
|
|
|
|
|
|
|
|
class VkApi(vk_api.VkApi):
|
|
|
|
|
|
2021-04-22 11:20:36 -05:00
|
|
|
|
def __init__(self, login=None, password=None, token=None,
|
2018-12-17 21:55:26 -06:00
|
|
|
|
auth_handler=None, captcha_handler=None,
|
|
|
|
|
config=jconfig.Config, config_filename='vk_config.v2.json',
|
2019-09-17 17:23:46 -05:00
|
|
|
|
api_version='5.101', app_id=2685278, scope=DEFAULT_USER_SCOPE,
|
2018-12-24 08:54:53 -06:00
|
|
|
|
client_secret='lxhD8OD7dMsqtXIm5IUY'):
|
2018-12-17 21:55:26 -06:00
|
|
|
|
|
|
|
|
|
self.login = login
|
|
|
|
|
self.password = password
|
|
|
|
|
|
|
|
|
|
self.token = {'access_token': token}
|
|
|
|
|
self.api_version = api_version
|
|
|
|
|
self.app_id = app_id
|
|
|
|
|
self.scope = scope
|
|
|
|
|
self.client_secret = client_secret
|
|
|
|
|
|
|
|
|
|
self.storage = config(self.login, filename=config_filename)
|
|
|
|
|
|
|
|
|
|
self.http = requests.Session()
|
2019-01-18 17:22:24 -06:00
|
|
|
|
self.http.headers.update({'User-agent': 'VKAndroidApp/5.23-2978 (Android 4.4.2; SDK 19; x86; unknown Android SDK built for x86; en; 320x240)'})
|
2018-12-17 21:55:26 -06:00
|
|
|
|
|
|
|
|
|
self.last_request = 0.0
|
|
|
|
|
|
|
|
|
|
self.error_handlers = {
|
|
|
|
|
NEED_VALIDATION_CODE: self.need_validation_handler,
|
|
|
|
|
CAPTCHA_ERROR_CODE: captcha_handler or self.captcha_handler,
|
|
|
|
|
TOO_MANY_RPS_CODE: self.too_many_rps_handler,
|
|
|
|
|
TWOFACTOR_CODE: auth_handler or self.auth_handler
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.lock = threading.Lock()
|
|
|
|
|
|
|
|
|
|
self.logger = logging.getLogger('vk_api_patched')
|
2019-01-18 17:22:24 -06:00
|
|
|
|
self.logger.info('Started patched VK API client...')
|
|
|
|
|
|
|
|
|
|
def method(self, method, values=None, captcha_sid=None, captcha_key=None,
|
|
|
|
|
raw=False):
|
|
|
|
|
""" Вызов метода API
|
|
|
|
|
|
|
|
|
|
:param method: название метода
|
|
|
|
|
:type method: str
|
|
|
|
|
|
|
|
|
|
:param values: параметры
|
|
|
|
|
:type values: dict
|
|
|
|
|
|
|
|
|
|
:param captcha_sid: id капчи
|
|
|
|
|
:type captcha_key: int or str
|
|
|
|
|
|
|
|
|
|
:param captcha_key: ответ капчи
|
|
|
|
|
:type captcha_key: str
|
|
|
|
|
|
|
|
|
|
:param raw: при False возвращает `response['response']`
|
|
|
|
|
при True возвращает `response`
|
|
|
|
|
(может понадобиться для метода execute для получения
|
|
|
|
|
execute_errors)
|
|
|
|
|
:type raw: bool
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
values = values.copy() if values else {}
|
|
|
|
|
|
|
|
|
|
if 'v' not in values:
|
|
|
|
|
values['v'] = self.api_version
|
|
|
|
|
|
|
|
|
|
if self.token:
|
|
|
|
|
values['access_token'] = self.token['access_token']
|
|
|
|
|
|
|
|
|
|
if captcha_sid and captcha_key:
|
|
|
|
|
values['captcha_sid'] = captcha_sid
|
|
|
|
|
values['captcha_key'] = captcha_key
|
|
|
|
|
|
|
|
|
|
with self.lock:
|
|
|
|
|
# Ограничение 3 запроса в секунду
|
|
|
|
|
delay = self.RPS_DELAY - (time.time() - self.last_request)
|
|
|
|
|
|
|
|
|
|
if delay > 0:
|
|
|
|
|
time.sleep(delay)
|
2021-04-22 11:20:36 -05:00
|
|
|
|
values.update(https=1)
|
2019-01-18 17:22:24 -06:00
|
|
|
|
response = self.http.post(
|
|
|
|
|
'https://api.vk.com/method/' + method,
|
|
|
|
|
values
|
|
|
|
|
)
|
|
|
|
|
self.last_request = time.time()
|
|
|
|
|
|
|
|
|
|
if response.ok:
|
|
|
|
|
response = response.json()
|
|
|
|
|
else:
|
|
|
|
|
error = ApiHttpError(self, method, values, raw, response)
|
|
|
|
|
response = self.http_handler(error)
|
|
|
|
|
|
|
|
|
|
if response is not None:
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
raise error
|
|
|
|
|
|
|
|
|
|
if 'error' in response:
|
|
|
|
|
error = ApiError(self, method, values, raw, response['error'])
|
|
|
|
|
|
|
|
|
|
if error.code in self.error_handlers:
|
|
|
|
|
if error.code == CAPTCHA_ERROR_CODE:
|
|
|
|
|
error = Captcha(
|
|
|
|
|
self,
|
|
|
|
|
error.error['captcha_sid'],
|
|
|
|
|
self.method,
|
|
|
|
|
(method,),
|
|
|
|
|
{'values': values, 'raw': raw},
|
|
|
|
|
error.error['captcha_img']
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
response = self.error_handlers[error.code](error)
|
|
|
|
|
|
|
|
|
|
if response is not None:
|
|
|
|
|
return response
|
|
|
|
|
|
|
|
|
|
raise error
|
|
|
|
|
|
|
|
|
|
return response if raw else response['response']
|