Advertisement
stuppid_bot

Untitled

Jan 20th, 2016
271
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.60 KB | None | 0 0
  1. from .access_token import AccessToken
  2. import logging
  3. import re
  4. import urllib.parse
  5.  
  6.  
  7. AUTH_BASE = "https://oauth.vk.com"
  8. REDIRECT_URI = AUTH_BASE + "/blank.html"
  9.  
  10.  
  11. class AuthMixin:
  12.     def get_auth_url(self, params):
  13.         return "{}?{}".format(
  14.             urllib.parse.urljoin(AUTH_BASE, self.auth_path),
  15.             urllib.parse.urlencode(params)
  16.         )
  17.  
  18.  
  19. class DirectAuth(AuthMixin):
  20.     """Осуществляет прямую авторизацию <https://vk.com/dev/auth_direct>"""
  21.     auth_path = 'token'
  22.  
  23.     def __init__(self,
  24.                  client,
  25.                  client_id,
  26.                  client_secret,
  27.                  scope=None,
  28.                  username=None,
  29.                  password=None,
  30.                  test_redirect_uri=None):
  31.         self.logger = logging.getLogger(
  32.             ".".join([self.__class__.__module__, self.__class__.__name__]))
  33.         self.client = client
  34.         self.client_id = client_id
  35.         self.client_secret = client_secret
  36.         self.scope = scope
  37.         self.username = username
  38.         self.password = password
  39.         self.test_redirect_uri = test_redirect_uri
  40.  
  41.     def authorize(self,
  42.                   username=None,
  43.                   password=None,
  44.                   captcha_key=None,
  45.                   captcha_sid=None):
  46.         self.username = username or self.username
  47.         self.password = password or self.password
  48.         if not self.username or not self.password:
  49.             raise AuthError("Username and password are required")
  50.         params = self.get_auth_params()
  51.         if captcha_key:
  52.             assert captcha_sid is not None
  53.             params['captcha_key'] = captcha_key
  54.             params['captcha_sid'] = captcha_sid
  55.         url = self.get_auth_url(params)
  56.         self.logger.debug("Url: %s", url)
  57.         response = self.client.get(url)
  58.         if 'error' in response:
  59.             raise OAuthError(response)
  60.         self.client.access_token = AccessToken(
  61.             key=response.access_token,
  62.             user_id=response.user_id,
  63.             expires_in=response.expires_in,
  64.             secret=response.get('secret')
  65.         )
  66.         self.logger.info("Successfully authorized")
  67.  
  68.     def get_auth_params(self):
  69.         params = dict(
  70.             grant_type='password',
  71.             client_id=self.client_id,
  72.             client_secret=self.client_secret,
  73.             username=self.username,
  74.             password=self.password,
  75.             v=self.client.api_version
  76.         )
  77.         if self.scope:
  78.             params['scope'] = self.scope
  79.         if self.test_redirect_uri:
  80.             params['test_redirect_uri']
  81.         return params
  82.  
  83.  
  84. class ClientAuth(AuthMixin):
  85.     """Осуществляет авторизацию Standalone приложения
  86.    <https://vk.com/dev/auth_mobile>"""
  87.     auth_path = 'authorize'
  88.  
  89.     def __init__(self,
  90.                  client,
  91.                  client_id,
  92.                  scope=None,
  93.                  username=None,
  94.                  password=None,
  95.                  display=None,
  96.                  redirect_uri=REDIRECT_URI):
  97.         self.logger = logging.getLogger(
  98.             ".".join([self.__class__.__module__, self.__class__.__name__]))
  99.         self.client = client
  100.         self.client_id = client_id
  101.         self.scope = scope
  102.         self.username = username
  103.         self.password = password
  104.         self.redirect_uri = redirect_uri
  105.         self.display = display
  106.  
  107.     def authorize(self, username=None, password=None):
  108.         self.username = username or self.username
  109.         self.password = password or self.password
  110.         if not self.username or not self.password:
  111.             raise AuthError("Username and password are required")
  112.         params = self.get_auth_params()
  113.         r = self.client.session.get(self.get_auth_url(params))
  114.         action = self.get_form_action(r.text)
  115.         params = self.get_login_form_params(r.text)
  116.         self.submit_login_form(action, params)
  117.  
  118.     def submit_login_form(self, action, params):
  119.         params['email'] = self.username
  120.         params['pass'] = self.password
  121.         r = self.client.session.post(action, params)
  122.         self.logger.debug("Current URL: %s", r.url)
  123.         if r.url.find('#'):
  124.             # Копипаст
  125.             h = r.url.split("#")[1]
  126.             res = dict(urllib.parse.parse_qsl(h))
  127.             assert 'access_token' in res
  128.             self.client.access_token = AccessToken(
  129.                 res['access_token'],
  130.                 int(res['user_id']),
  131.                 int(res['expires_in']),
  132.                 res.get('secret')
  133.             )
  134.             return
  135.         ga_match = re.search(
  136.             'https://login\.vk\.com/\?act=grant_access([^"]+)', r.text)
  137.         # Страница с подтверждением, где кнопочку Allow нужно нажать
  138.         if ga_match:
  139.             ga_url = ga_match.group(0)
  140.             r = self.client.session.get(ga_url)
  141.             h = r.url.split("#")[1]
  142.             res = dict(urllib.parse.parse_qsl(h))
  143.             if 'error' in res:
  144.                 raise AuthError(res.get('error_description') or res['error'])
  145.             assert 'access_token' in res
  146.             self.client.access_token = AccessToken(
  147.                 res['access_token'],
  148.                 int(res['user_id']),
  149.                 int(res['expires_in']),
  150.                 res.get('secret')
  151.             )
  152.             return
  153.         captcha_match = re.search(
  154.             '([^"]+/captcha\.php\?sid=(\d+)[^"]+)', r.text)
  155.         if captcha_match:
  156.             captcha_url, captcha_sid = captcha_match.groups()
  157.             try:
  158.                 captcha_key = self.get_captcha_key(captcha_url)
  159.             except NotImplementedError:
  160.                 raise AuthError("Captcha required")
  161.             params['captcha_sid'] = captcha_sid
  162.             params['captcha_key'] = captcha_key
  163.             # Хз можно, наверное, закомментировать. Все хеши к сессии привязаны
  164.             params = self.get_login_form_params(r.text)
  165.             self.submit_login_form(action, params)
  166.             return
  167.         error_match = re.search(
  168.             '(warning|error)">([^<]+)', r.text)
  169.         if error_match:
  170.             raise AuthError(error_match.group(2))
  171.         raise AuthError("WTF?")
  172.  
  173.     def get_captcha_key(self, url):
  174.         raise NotImplementedError
  175.  
  176.     def get_form_action(self, content):
  177.         match = re.search('action="([^"]+)', content)
  178.         return match.group(1)
  179.  
  180.     def get_login_form_params(self, content):
  181.         matches = re.findall(
  182.             '(_origin|ip_h|lg_h|to|expire)" value="([^"]+)', content)
  183.         return dict(matches)
  184.  
  185.     def get_auth_params(self):
  186.         params = dict(
  187.             client_id=self.client_id,
  188.             redirect_uri=self.redirect_uri,
  189.             v=self.client.api_version,
  190.             response_type='token'
  191.         )
  192.         if self.scope:
  193.             params['scope'] = self.scope
  194.         if self.display:
  195.             params['display'] = self.display
  196.         return params
  197.  
  198.  
  199. class AuthError(Exception):
  200.     pass
  201.  
  202.  
  203. class OAuthError(AuthError):
  204.     def __init__(self, response):
  205.         self.error_type = response['error']
  206.         self.error_description = response.get('error_description')
  207.         self.captcha_img = response.get('captcha_img')
  208.         self.captcha_sid = response.get('captcha_sid')
  209.         self.redirect_uri = response.get('redirect_uri')
  210.  
  211.     def __str__(self):
  212.         if self.error_description:
  213.             return ": ".join([self.error_type, self.error_description])
  214.         return self.error_type
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement