diff --git a/.gitignore b/.gitignore index a059d759..20423f3b 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ upload_to_PyPi.py .project .pydevproject .settings/ +.idea/ \ No newline at end of file diff --git a/MANIFEST b/MANIFEST index 71e9f48e..5a720487 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,9 +1,8 @@ -# file GENERATED by distutils, do NOT edit -setup.py -jconfig\__init__.py -jconfig\jconfig.py -test\test.py -vk_api\__init__.py -vk_api\vk_api.py -vk_api\upload\__init__.py -vk_api\upload\vk_upload.py +# file GENERATED by distutils, do NOT edit +setup.py +jconfig\__init__.py +jconfig\jconfig.py +test\test.py +vk_api\__init__.py +vk_api\vk_api.py +vk_api\vk_upload.py diff --git a/README.md b/README.md index 8c430eff..1f94466a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ vk_api **vk_api** - модуль для использования API сайта ВКонтакте (vk.com). Пример смотрите в файле [example.py](https://github.com/python273/vk_api/blob/master/example.py) -Тестовая поддержка **Python 3**! +Python 2 / 3 С вопросами или советами можете [написать автору в ВК](https://vk.com/im?sel=183433824). diff --git a/example.py b/example.py index c7cc5ef6..74244589 100644 --- a/example.py +++ b/example.py @@ -1,32 +1,36 @@ -''' -@author: Kirill Python -@contact: http://vk.com/python273 -@license Apache License, Version 2.0, see LICENSE file - -Copyright (C) 2013 -''' - -# -*- coding: utf-8 -*- -import vk_api - - -def main(): - u""" Пример получения последнего сообщения со стены """ - - login = u'python@vk.com' - password = u'mypassword' - - try: - vk = vk_api.VkApi(login, password) # Авторизируемся - except vk_api.authorization_error as error_msg: - print(error_msg) # В случае ошибки выведем сообщение - return # и выйдем - - values = { - 'count': 1 # Получаем только одно сообщение - } - response = vk.method('wall.get', values) # Используем метод wall.get - print(response[1]['text']) # Печатаем текст последнего поста со стены - -if __name__ == '__main__': - main() +# -*- coding: utf-8 -*- + +''' +@author: Kirill Python +@contact: http://vk.com/python273 +@license Apache License, Version 2.0, see LICENSE file + +Copyright (C) 2013 +''' + +import vk_api + + +def main(): + u""" Пример получения последнего сообщения со стены """ + + login = u'python@vk.com' + password = u'mypassword' + + try: + vk = vk_api.VkApi(login, password) # Авторизируемся + except vk_api.AuthorizationError as error_msg: + print(error_msg) # В случае ошибки выведем сообщение + return # и выйдем + + values = { + 'count': 1 # Получаем только один пост + } + response = vk.method('wall.get', values) # Используем метод wall.get + + if response['items']: + # Печатаем текст последнего поста со стены + print(response['items'][0]['text']) + +if __name__ == '__main__': + main() diff --git a/jconfig/__init__.py b/jconfig/__init__.py index e68b8eb1..7914d79f 100644 --- a/jconfig/__init__.py +++ b/jconfig/__init__.py @@ -1,19 +1,21 @@ -''' -@author: Kirill Python -@contact: http://vk.com/python273 -@license Apache License, Version 2.0, see LICENSE file - -Copyright (C) 2013 -''' - -__author__ = "Kirill Python" -__version__ = "1.1" -__email__ = "mikeking568@gmail.com" -__contact__ = "https://vk.com/python273" - - -import sys -if sys.version_info[0] == 2: - from jconfig import * -else: - from .jconfig import * +# -*- coding: utf-8 -*- + +''' +@author: Kirill Python +@contact: http://vk.com/python273 +@license Apache License, Version 2.0, see LICENSE file + +Copyright (C) 2013 +''' + +__author__ = "Kirill Python" +__version__ = "1.1" +__email__ = "mikeking568@gmail.com" +__contact__ = "https://vk.com/python273" + + +import sys +if sys.version_info[0] == 2: + from jconfig import * +else: + from .jconfig import * diff --git a/jconfig/jconfig.py b/jconfig/jconfig.py index 60d957f9..8b433b05 100644 --- a/jconfig/jconfig.py +++ b/jconfig/jconfig.py @@ -1,42 +1,43 @@ -''' -@author: Kirill Python -@contact: http://vk.com/python273 -@license Apache License, Version 2.0, see LICENSE file - -Copyright (C) 2013 -''' - -# -*- coding: utf-8 -*- -import os -import json - - -class config: - def __init__(self, section, filename='config'): - self.section = section # Секция настроек - self.filename = filename # Файл с настройками - self.all = self.parse() # Все настройки - self.settings = self.all.get(section, {}) # Настройки секции - - def __getitem__(self, item): - return self.settings.get(item, {}) - - def __setitem__(self, key, value): - self.settings.update({key: value}) - self.all.update({self.section: self.settings}) - self.update(self.all) - - def parse(self): - fileis = os.path.exists(self.filename) - if fileis: - settings = json.load(open(self.filename, 'r')) - return settings - else: - self.update() - return {} - - def update(self, settings=None): - if not settings: - settings = {} - - json.dump(settings, open(self.filename, 'w')) +# -*- coding: utf-8 -*- + +''' +@author: Kirill Python +@contact: http://vk.com/python273 +@license Apache License, Version 2.0, see LICENSE file + +Copyright (C) 2013 +''' + +import os +import json + + +class Config(object): + def __init__(self, section, filename='config'): + self.section = section # Секция настроек + self.filename = filename # Файл с настройками + self.all = self.parse() # Все настройки + self.settings = self.all.get(section, {}) # Настройки секции + + def __getitem__(self, item): + return self.settings.get(item, {}) + + def __setitem__(self, key, value): + self.settings.update({key: value}) + self.all.update({self.section: self.settings}) + self.update(self.all) + + def parse(self): + fileis = os.path.exists(self.filename) + if fileis: + settings = json.load(open(self.filename, 'r')) + return settings + else: + self.update() + return {} + + def update(self, settings=None): + if not settings: + settings = {} + + json.dump(settings, open(self.filename, 'w')) diff --git a/setup.py b/setup.py index fab486d2..895ca33d 100644 --- a/setup.py +++ b/setup.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + ''' @author: Kirill Python @contact: http://vk.com/python273 @@ -6,13 +9,10 @@ Copyright (C) 2013 ''' -#!/usr/bin/env python -""" Setup file for vk_api package """ - from distutils.core import setup setup(name='vk_api', - version='4.6', - description='Module to use API VKontakte vk.com', + version='4.7', + description='Module to use API vk.com', author='Kirill Python', author_email='mikeking568@gmail.com', url='https://github.com/python273/vk_api', diff --git a/vk_api/__init__.py b/vk_api/__init__.py index 1f10ef6b..52432289 100644 --- a/vk_api/__init__.py +++ b/vk_api/__init__.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + ''' @author: Kirill Python @contact: http://vk.com/python273 @@ -7,7 +9,7 @@ ''' __author__ = "Kirill Python" -__version__ = "4.6" +__version__ = "4.6.6" __email__ = "mikeking568@gmail.com" __contact__ = "https://vk.com/python273" @@ -16,6 +18,8 @@ if sys.version_info[0] == 2: from vk_api import * from vk_upload import * + from vk_tools import * else: from .vk_api import * from .vk_upload import * + from .vk_tools import * diff --git a/vk_api/vk_api.py b/vk_api/vk_api.py index bb209496..3b6a58d1 100644 --- a/vk_api/vk_api.py +++ b/vk_api/vk_api.py @@ -1,230 +1,380 @@ -''' -@author: Kirill Python -@contact: http://vk.com/python273 -@license Apache License, Version 2.0, see LICENSE file - -Copyright (C) 2013 -''' - -# -*- coding: utf-8 -*- -import jconfig -import re -import requests -import time - - -class VkApi(): - def __init__(self, - login=None, password=None, number=None, - sid=None, token=None, - proxies=None, - version='5.0', app_id=2895443, scope=2097151): - ''' - :param login: Логин ВКонтакте - :param password: Пароль ВКонтакте - :param number: Номер при проверке безопасности - Номер: +7 12345678 90 - number = 12345678 - :param sid: cookie remixsid - :param token: access_token - :param proxies: proxy server - {'http': 'http://127.0.0.1:8888/', - 'https' : 'https://127.0.0.1:8888/'} - :param version: Версия API (default: '5.0') - :param app_id: Standalone-приложение (default: 2895443) - :param scope: Запрашиваемые права (default: 2097151) - ''' - - self.login = login - self.password = password - self.number = number - - self.sid = sid - self.token = {'access_token': token} - - self.version = version - self.app_id = app_id - self.scope = scope - - self.settings = jconfig.config(login) - - self.http = requests.Session() - self.http.proxies = proxies # Ставим прокси - self.http.headers = { # Притворимся браузером - 'User-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) ' \ - 'Gecko/20100101 Firefox/20.0' - } - self.http.verify = False - - if login and password: - self.sid = self.settings['remixsid'] - self.token = self.settings['access_token'] - - if not self.check_sid(): - self.vk_login() - - if not self.check_token(): - self.api_login() - - def vk_login(self, captcha_sid=None, captcha_key=None): - ''' Авторизцаия ВКонтакте с получением cookies remixsid ''' - - url = 'https://login.vk.com/' - values = { - 'act': 'login', - 'utf8': '1', - 'email': self.login, - 'pass': self.password - } - - if captcha_sid and captcha_key: - values.update({ - 'captcha_sid': captcha_sid, - 'captcha_key': captcha_key - }) - - self.http.cookies.clear() - response = self.http.post(url, values) - - if 'remixsid' in self.http.cookies: - remixsid = self.http.cookies['remixsid'] - self.settings['remixsid'] = remixsid - - # Нужно для авторизации в API - self.settings['forapilogin'] = { - 'p': self.http.cookies['p'], - 'l': self.http.cookies['l'] - } - - self.sid = remixsid - - elif 'sid=' in response.url: - raise authorization_error('Authorization error (capcha)') - else: - raise authorization_error('Authorization error (bad password)') - - if 'security_check' in response.url: - if self.number: - number_hash = regexp(r'security_check.*?hash: \'(.*?)\'\};', - response.text)[0] - - values = { - 'act': 'security_check', - 'al': '1', - 'al_page': '3', - 'code': self.number, - 'hash': number_hash, - 'to': '' - } - - response = self.http.post('https://vk.com/login.php', values) - - if response.text.split('')[4] == '4': - return - - raise authorization_error('Authorization error (enter number)') - - def check_sid(self): - ''' Прверка Cookies remixsid на валидность ''' - - if self.sid: - url = 'https://vk.com/feed2.php' - self.http.cookies.update({ - 'remixsid': self.sid, - 'remixlang': '0', - 'remixsslsid': '1' - }) - - response = self.http.get(url).json() - - if response['user']['id'] != -1: - return response - - def api_login(self): - ''' Получение токена через Desktop приложение ''' - - url = 'https://oauth.vk.com/authorize' - values = { - 'client_id': self.app_id, - 'scope': self.scope, - 'response_type': 'token', - } - - self.http.cookies.update(self.settings['forapilogin']) - self.http.cookies.update({'remixsid': self.sid}) - - response = self.http.post(url, values) - - if not 'access_token' in response.url: - url = regexp(r'location\.href = "(.*?)"\+addr;', response.text)[0] - response = self.http.get(url) - - if 'access_token' in response.url: - params = response.url.split('#')[1].split('&') - - token = {} - for i in params: - x = i.split('=') - token.update({x[0]: x[1]}) - - self.settings['access_token'] = token - self.token = token - else: - raise authorization_error('Authorization error (api)') - - def check_token(self): - ''' Прверка access_token на валидность ''' - - if self.token.get('access_token'): - try: - self.method('isAppUser') - except api_error: - return False - - return True - - def method(self, method, values=None): - ''' Использование методов API - - method - название метода - 'users.get' - - values - параметры - {'uids': 1} - ''' - - url = 'https://api.vk.com/method/%s' % method - - if not values: - values = {} - - values.update({'v': self.version}) - - if self.token: - values.update({'access_token': self.token['access_token']}) - - response = self.http.post(url, values).json() - if 'error' in response: - raise api_error(response['error']) - else: - return response['response'] - - -def regexp(reg, string): - ''' Поиск по регулярке ''' - - reg = re.compile(reg, re.IGNORECASE | re.DOTALL) - reg = reg.findall(string) - return reg - - -class vk_api_error(Exception): - pass - - -class authorization_error(vk_api_error): - pass - - -class api_error(vk_api_error): - pass +# -*- coding: utf-8 -*- + +''' +@author: Kirill Python +@contact: http://vk.com/python273 +@license Apache License, Version 2.0, see LICENSE file + +Copyright (C) 2013 +''' + +import jconfig +import re +import requests +import time + +DELAY = 1.0 / 3 # 3 requests per second +CAPTCHA_ERROR_CODE = 14 +NEED_VALIDATION_CODE = 17 + + +class VkApi(object): + def __init__(self, login=None, password=None, number=None, token=None, + proxies=None, captcha_handler=None, + api_version='5.21', app_id=2895443, scope=2097151): + ''' + :param login: Логин ВКонтакте + :param password: Пароль ВКонтакте + :param number: Номер для проверке безопасности (указывать, если + в качестве логина используется не номер) + + :param token: access_token + :param proxies: proxy server + {'http': 'http://127.0.0.1:8888/', + 'https': 'https://127.0.0.1:8888/'} + :param api_version: Версия API (default: '5.21') + :param app_id: Standalone-приложение (default: 2895443) + :param scope: Запрашиваемые права (default: 2097151) + ''' + + self.login = login + self.password = password + self.number = number + + self.sid = None + self.token = {'access_token': token} + + self.api_version = api_version + self.app_id = app_id + self.scope = scope + + self.settings = jconfig.Config(login) + + self.http = requests.Session() + self.http.proxies = proxies # Ставим прокси + self.http.headers = { # Притворимся браузером + 'User-agent': 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:28.0) ' \ + 'Gecko/20100101 Firefox/28.0' + } + self.http.verify = False + + self.last_request = 0.0 + + self.error_handlers = { + NEED_VALIDATION_CODE: self.need_validation_handler, + CAPTCHA_ERROR_CODE: captcha_handler or self.captcha_handler + } + + if login and password: + self.sid = self.settings['remixsid'] + self.token = self.settings['access_token'] + + if not self.check_sid(): + self.vk_login() + else: + self.security_check('http://vk.com') + + if not self.check_token(): + self.api_login() + + def vk_login(self, captcha_sid=None, captcha_key=None): + ''' Авторизцаия ВКонтакте с получением cookies remixsid ''' + + url = 'https://login.vk.com/' + values = { + 'act': 'login', + 'utf8': '1', + 'email': self.login, + 'pass': self.password + } + + if captcha_sid and captcha_key: + values.update({ + 'captcha_sid': captcha_sid, + 'captcha_key': captcha_key + }) + + self.http.cookies.clear() + response = self.http.post(url, values) + + if 'remixsid' in self.http.cookies: + remixsid = self.http.cookies['remixsid'] + self.settings['remixsid'] = remixsid + + # Нужно для авторизации в API + self.settings['forapilogin'] = { + 'p': self.http.cookies['p'], + 'l': self.http.cookies['l'] + } + + self.sid = remixsid + + elif 'sid=' in response.url: + captcha_sid = regexp(r'sid=(\d+)', response.url)[0] + captcha = Captcha(self, captcha_sid, self.vk_login) + + if self.error_handlers[CAPTCHA_ERROR_CODE]: + self.error_handlers[CAPTCHA_ERROR_CODE](captcha) + else: + raise AuthorizationError('Authorization error (capcha)') + else: + raise BadPassword('Bad password') + + if 'security_check' in response.url: + self.security_check(response=response) + + def security_check(self, url=None, response=None): + if url: + response = self.http.get(url) + if not 'security_check' in response.url: + return + + phone_prefix = regexp(r'label ta_r">(.*?)<', + response.text) + phone_prefix = phone_prefix[0].strip() + + phone_postfix = regexp(r'phone_postfix">(.*?)<', + response.text) + phone_postfix = phone_postfix[0].strip() + + if self.number: + code = code_from_number(phone_prefix, phone_postfix, self.number) + else: + code = code_from_number(phone_prefix, phone_postfix, self.login) + + if code: + number_hash = regexp(r'security_check.*?hash: \'(.*?)\'\};', + response.text)[0] + + values = { + 'act': 'security_check', + 'al': '1', + 'al_page': '3', + 'code': code, + 'hash': number_hash, + 'to': '' + } + + response = self.http.post('https://vk.com/login.php', values) + + if response.text.split('')[4] == '4': + return True + + raise SecurityCheck('Enter number') + + def check_sid(self): + ''' Прверка Cookies remixsid на валидность ''' + + if self.sid: + url = 'https://vk.com/feed2.php' + self.http.cookies.update({ + 'remixsid': self.sid, + 'remixlang': '0', + 'remixsslsid': '1' + }) + + response = self.http.get(url).json() + + if response['user']['id'] != -1: + return response + + def api_login(self): + ''' Получение токена через Desktop приложение ''' + + url = 'https://oauth.vk.com/authorize' + values = { + 'client_id': self.app_id, + 'scope': self.scope, + 'response_type': 'token', + } + + self.http.cookies.update(self.settings['forapilogin']) + self.http.cookies.update({'remixsid': self.sid}) + + response = self.http.post(url, values) + + if not 'access_token' in response.url: + url = regexp(r'location\.href = "(.*?)"\+addr;', response.text)[0] + response = self.http.get(url) + + if 'access_token' in response.url: + params = response.url.split('#')[1].split('&') + + token = {} + for i in params: + x = i.split('=') + token.update({x[0]: x[1]}) + + self.settings['access_token'] = token + self.token = token + else: + raise AuthorizationError('Authorization error (api)') + + def check_token(self): + ''' Прверка access_token на валидность ''' + + if self.token: + try: + self.method('isAppUser') + except ApiError: + return False + + return True + + def captcha_handler(self, captcha): + ''' http://vk.com/dev/captcha_error ''' + pass + + def need_validation_handler(self, error): + ''' http://vk.com/dev/need_validation ''' + # TODO: write me + pass + + def method(self, method, values=None, captcha_sid=None, captcha_key=None): + ''' + Использование методов API + + :param method: метод + :param values: параметры + :param captcha_sid: + :param captcha_key: + ''' + + url = 'https://api.vk.com/method/%s' % method + + if values: + values = values.copy() + else: + values = {} + + if not 'v' in values: + values.update({'v': self.api_version}) + + if self.token: + values.update({'access_token': self.token['access_token']}) + + if captcha_sid and captcha_key: + values.update({ + 'captcha_sid': captcha_sid, + 'captcha_key': captcha_key + }) + + # Ограничение 3 запроса в секунду + delay = DELAY - (time.time() - self.last_request) + + if delay > 0: + time.sleep(delay) + + response = self.http.post(url, values).json() + self.last_request = time.time() + + if 'error' in response: + error = ApiError(self, method, values, response['error']) + error_code = error.code + + if error_code in self.error_handlers: + if error_code == CAPTCHA_ERROR_CODE: + # TODO: wtf + error = Captcha( + self, + error.error['captcha_sid'], + self.method, + (method,), + {'values': values}, + error.error['captcha_img'] + ) + + response = self.error_handlers[error_code](error) + + if response is not None: + return response + + raise error + else: + return response['response'] + + +def regexp(reg, string): + ''' Поиск по регулярке ''' + + reg = re.compile(reg, re.IGNORECASE | re.DOTALL) + reg = reg.findall(string) + return reg + + +def code_from_number(phone_prefix, phone_postfix, number): + prefix_len = len(phone_prefix) + postfix_len = len(phone_postfix) + + if (prefix_len + postfix_len) > len(number): + return + + # Сравниваем начало номера + if not number[:prefix_len] == phone_prefix: + return + + # Сравниваем конец номера + if not number[-postfix_len:] == phone_postfix: + return + + return number[prefix_len:-postfix_len] + + +class AuthorizationError(Exception): + pass + + +class BadPassword(AuthorizationError): + pass + + +class SecurityCheck(AuthorizationError): + pass + + +class ApiError(Exception): + def __init__(self, vk, method, values, error): + self.vk = vk + self.method = method + self.values = values + self.code = error['error_code'] + self.error = error + + def try_method(self): + return self.vk.method(self.method, self.values) + + def __str__(self): + return '[{}] {}'.format(self.error['error_code'], + self.error['error_msg']) + + +class Captcha(Exception): + def __init__(self, vk, captcha_sid, + func, args=None, kwargs=None, url=None): + self.vk = vk + self.sid = captcha_sid + self.func = func + self.args = args or () + self.kwargs = kwargs or {} + + self.key = None + self.url = url + + def get_url(self): + if not self.url: + self.url = 'http://api.vk.com/captcha.php?sid={}'.format(self.sid) + + return self.url + + def try_again(self, key): + self.key = key + + self.kwargs.update({ + 'captcha_sid': self.sid, + 'captcha_key': self.key + }) + + return self.func(*self.args, **self.kwargs) + + def __str__(self): + return 'Captcha needed' diff --git a/vk_api/vk_tools.py b/vk_api/vk_tools.py new file mode 100644 index 00000000..507e68f8 --- /dev/null +++ b/vk_api/vk_tools.py @@ -0,0 +1,83 @@ +# encoding: utf-8 +import json +import sys + +if sys.version_info[0] == 3: + xrange = range + + +class VkTools(object): + def __init__(self, vk): + self.vk = vk + + def get_all(self, method, values=None, max_count=200, key='items'): + ''' Получить все элементы + Работает в методах, где в ответе есть items или users + За один запрос получает max_count * 25 элементов + + :param method: метод + :param values: параметры + :param max_count: максимальное количество элементов, + которое можно получить за один раз + :param key: ключ элементов, которые нужно получить + ''' + + if values: + values = values.copy() + else: + values = {} + + items = [] + offset = 0 + + while True: + run_code = code_get_all_items % ( + max_count, offset, json.dumps(values), + key, method, method + ) + + response = self.vk.method('execute', {'code': run_code}) + + items += response['items'] + + if response['end']: + break + + offset = response['offset'] + + return {'count': len(items), key: items} + + def get_all_slow(self, method, values=None, max_count=200, key='items'): + ''' Получить все элементы + Работает в методах, где в ответе есть count и items или users + + :param method: метод + :param values: параметры + :param max_count: максимальное количество элементов, + которое можно получить за один раз + :param key: ключ элементов, которые нужно получить + ''' + + if not values: + values = {} + else: + values = values.copy() + + values.update({'count': max_count}) + + response = self.vk.method(method, values) + count = response['count'] + items = response[key] + + for i in xrange(max_count, count + 1, max_count): + values.update({ + 'offset': i + }) + + response = self.vk.method(method, values) + items += response[key] + + return {'count': len(items), key: items} + +# Полный код в файле vk_procedures +code_get_all_items = 'var z=%s,x=%s,y=%s,k="%s",p={"count":z}+y,r=API.%s(p),c=r["count"],j=r[k],o=0,i=1;while(i<25&&o=c};' diff --git a/vk_api/vk_upload.py b/vk_api/vk_upload.py index 898f2b1a..52ebb0a6 100644 --- a/vk_api/vk_upload.py +++ b/vk_api/vk_upload.py @@ -1,101 +1,101 @@ -''' -@author: Kirill Python -@contact: http://vk.com/python273 -@license Apache License, Version 2.0, see LICENSE file - -Copyright (C) 2013 -''' - -# -*- coding: utf-8 -*- - - -class VkUpload(): - def __init__(self, vk): - self.vk = vk - # https://vk.com/dev/upload_files - - def photo(self, photos, album_id=None, group_id=None): - ''' Загрузка изображений в альбом пользователя - - photos = ['photo1.jpg', 'img.png'] - = 'screen.png' - Максимум 5 фотографий - - album_id - ''' - - if not (album_id and photos): - return False - - if type(photos) == str: # upload.photo('photo.jpg', ...) - photos = [photos] - - values = { - 'album_id': album_id - } - if group_id: # Если загружаем в группу - values.update({'group_id': group_id}) - - # Получаем ссылку для загрузки - url = self.vk.method('photos.getUploadServer', values)['upload_url'] - - # Загружаем - photos_files = openPhotos(photos) - response = self.vk.http.post(url, files=photos_files).json() - closePhotos(photos_files) - - # Олег Илларионов: - # это не могу к сожалению просто пофиксить - if not 'album_id' in response: - response['album_id'] = response['aid'] - - # Сохраняем фото в альбоме - response = self.vk.method('photos.save', response) - - return response - - def photoMessages(self, photos, group_id=None): - ''' Загрузка изображений в сообщения - - photos = ['photo1.jpg', 'img.png'] - = 'screen.png' - Максимум 7(?) фотографий - ''' - - if not photos: - return False - - if type(photos) == str: # upload.photo('photo.jpg', ...) - photos = [photos] - - values = {} - if group_id: - values.update({'group_id': group_id}) - - # Получаем ссылку для загрузки - url = self.vk.method('photos.getMessagesUploadServer', values)['upload_url'] - - # Загружаем - photos_files = openPhotos(photos) - response = self.vk.http.post(url, files=photos_files) - closePhotos(photos_files) - - # Сохраняем фото в альбоме - response = self.vk.method('photos.saveMessagesPhoto', response.json()) - - return response - - -def openPhotos(photos_paths): - photos = {} - - for x, filename in enumerate(photos_paths): # Открываем файлы - photos.update( - {'file%s' % x: open(filename, 'rb')} - ) - - return photos - -def closePhotos(photos): - for i in photos: - photos[i].close() +# -*- coding: utf-8 -*- + +''' +@author: Kirill Python +@contact: http://vk.com/python273 +@license Apache License, Version 2.0, see LICENSE file + +Copyright (C) 2013 +''' + + +class VkUpload(object): + def __init__(self, vk): + self.vk = vk + # https://vk.com/dev/upload_files + + def photo(self, photos, album_id=None, group_id=None): + ''' Загрузка изображений в альбом пользователя + + photos = ['photo1.jpg', 'img.png'] + = 'screen.png' + Максимум 5 фотографий + + album_id + ''' + + if not (album_id and photos): + return False + + if type(photos) == str: # upload.photo('photo.jpg', ...) + photos = [photos] + + values = { + 'album_id': album_id + } + if group_id: # Если загружаем в группу + values.update({'group_id': group_id}) + + # Получаем ссылку для загрузки + url = self.vk.method('photos.getUploadServer', values)['upload_url'] + + # Загружаем + photos_files = openPhotos(photos) + response = self.vk.http.post(url, files=photos_files).json() + closePhotos(photos_files) + + # Олег Илларионов: + # это не могу к сожалению просто пофиксить + if not 'album_id' in response: + response['album_id'] = response['aid'] + + # Сохраняем фото в альбоме + response = self.vk.method('photos.save', response) + + return response + + def photoMessages(self, photos, group_id=None): + ''' Загрузка изображений в сообщения + + photos = ['photo1.jpg', 'img.png'] + = 'screen.png' + Максимум 7(?) фотографий + ''' + + if not photos: + return False + + if type(photos) == str: # upload.photo('photo.jpg', ...) + photos = [photos] + + values = {} + if group_id: + values.update({'group_id': group_id}) + + # Получаем ссылку для загрузки + url = self.vk.method('photos.getMessagesUploadServer', values)['upload_url'] + + # Загружаем + photos_files = openPhotos(photos) + response = self.vk.http.post(url, files=photos_files) + closePhotos(photos_files) + + # Сохраняем фото в альбоме + response = self.vk.method('photos.saveMessagesPhoto', response.json()) + + return response + + +def openPhotos(photos_paths): + photos = {} + + for x, filename in enumerate(photos_paths): # Открываем файлы + photos.update( + {'file%s' % x: open(filename, 'rb')} + ) + + return photos + +def closePhotos(photos): + for i in photos: + photos[i].close() diff --git a/vk_procedures b/vk_procedures new file mode 100644 index 00000000..09771108 --- /dev/null +++ b/vk_procedures @@ -0,0 +1,31 @@ +========== +CODE: get items x25 +INPUT: max_count, start_offset, params:in_JSON, key, method, method +---------- +var max_count = %s; +var start_offset = %s; +var my_params = %s; +var key = %s; + +var params = {"count": max_count} + my_params; + +var res = API.%s(params); +var count = res["count"]; +var items = res[key]; + +var offset = 0; + +var i = 1; +while(i < 25 && offset < count) { + offset = i * max_count + start_offset; + params = {"count": max_count, "offset": offset}; + params = params + my_params; + + res = API.%s(params); + items = items + res[key]; + + i = i + 1; +} + +return {"count": count, "items": items, "offset": offset, "end": offset >= count}; +========== \ No newline at end of file