Browse Source

inital

master
Alexeev Nickolay 6 years ago
commit
f4646d4303
  1. 21
      LICENSE
  2. 60
      README.md
  3. 16
      setup.py
  4. 4
      yandex_connect/__init__.py
  5. 203
      yandex_connect/base.py
  6. 398
      yandex_connect/directory.py

21
LICENSE

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 zt50tz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

60
README.md

@ -0,0 +1,60 @@
# yandex_connect
Библиотека python для использования API Yandex connect / Яндекс коннект.
В настоящий момент реализованы все функции Directory, версии 6.
https://tech.yandex.ru/connect/directory/api/about-docpage/
### Установка
```bash
git clone https://github.com/zt50tz/yandex-connect
sudo python setup.py install
```
### Пример
```python
from yandex_connect import YandexConnectDirectory
app = YandexConnectDirectory('<OAuth TOKEN>', org_id=None) # создание
app.user_add('test', 'test234test') # добавление сотрудника
app.user_list_full() # просмотр всех сотрудников
```
Методы
------
##### Сотрудники
- ```user_info``` — Получение информации о сотруднике
- ```user_list``` - Получение списка сотрудников
- ```user_list_full``` - Получение полного списка сотрудников, без страниц
- ```user_add``` - Добавление сотрудника
- ```user_upd``` - Изменение сотрудника
- ```user_alias_add``` - Добавление алиаса для сотрудника
##### Отделы
- ```department_list``` - Получение списка отделов
- ```department_list_full``` - Получение полного списка отделов
- ```department_info``` - Получение информации об отделе
- ```department_add``` - Добавление отдела
- ```department_upd``` - Изменение отдела
- ```department_del``` - Удаление отдела
##### Команды
- ```group_list``` - Список команд
- ```group_list_full``` - Полный список команд
- ```group_info``` - Получение информации о команде
- ```group_add``` - Добавление команды
- ```group_upd``` - Изменение команды
- ```group_member_list``` - Участники команды
- ```group_member_add``` - Добавить участника команды
- ```group_member_del``` - Удалить участника команды
- ```group_member_update``` - Изменение участников команды
##### Домены
- ```domain_list``` - Получение списка доменов
- ```domain_add``` - Добавить домен
- ```domain_del``` - Удалить домен
##### Организации
- ```organization_list``` - Список организаций

16
setup.py

@ -0,0 +1,16 @@
# coding: utf8
from setuptools import setup
setup(name='yandex_connect',
version='0.01b',
description='API Yandex Connect',
url='http://github.com/zt50tz/yandex-connect',
author='Alexeev Nick',
author_email='n@akolka.ru',
license='MIT',
packages=['yandex_connect'],
install_requires=[
'requests',
],
zip_safe=False)

4
yandex_connect/__init__.py

@ -0,0 +1,4 @@
# coding: utf8
from .base import *
from .directory import *

203
yandex_connect/base.py

@ -0,0 +1,203 @@
# coding: utf8
"""
Yandex.Connect Base API module
:author: Alexeev Nick
:email: n@akolka.ru
:version: 0.01b
"""
import json
import requests
import datetime
import inspect
def json_prepare_dump(obj):
"""
Подготовка к json.dumps
:param obj: объект
:return: подготовленный объект
"""
if isinstance(obj, list):
for i, item in enumerate(obj):
obj[i] = json_prepare_dump(item)
elif isinstance(obj, dict):
for key in obj:
obj[key] = json_prepare_dump(obj[key])
elif type(obj) is datetime.date:
return obj.isoformat()
elif isinstance(obj, datetime.datetime):
return obj.isoformat()
return obj
def inspect_args_func(frame):
"""
Inspect current def arguments
:param frame: inspect.currentframe()
:return: dict
"""
args, _, _, values = inspect.getargvalues(frame)
return {key: values[key] for key in args if key != 'self'}
class YandexConnectException(Exception):
"""
Exception of module
"""
pass
class YandexConnectExceptionY(Exception):
"""
Exception by yandex request
"""
pass
class YandexConnectRequest(object):
""" Yandex Connect request API object """
_version = None # API version
_oauth_token = None # OAuth Token
_org_id = None # Org ID
_domain = None # Domain
def __init__(self, domain, oauth_token, org_id=None, version=6):
"""
Init
:param domain: yandex domain
:param oauth_token: OAuth Token https://oauth.yandex.ru/
:param org_id: Organization id
:param version: API version
"""
self._domain = domain
self._oauth_token = oauth_token
self._org_id = org_id
if version:
self._version = version
def __call__(self, name, data=None, method='post'):
"""
Base request method
:param name: url path
:param data: data / args of request
:param method: request method - get/post
:raise YandexConnectException: bad request, jsonify failed
:raise YandexConnectExceptionY: yandex exception
:return: dict
"""
url = '%(domain)s/v%(version)s/%(name)s' % {
'domain': self._domain,
'version': self._version,
'name': name
}
if not url.endswith('/'):
url = '%s/' % url
if data:
for key in data.keys():
if data[key] is None or (isinstance(data[key], dict) and not data[key]):
del data[key]
continue
method = method.lower()
if method not in ['get', 'post', 'patch', 'delete']:
raise ValueError('Not right method')
kwargs = {
'headers': {
'Authorization': 'OAuth %s' % self._oauth_token,
'X-Org-ID': self._org_id if self._org_id else None
}
}
if method in ['post', 'patch']:
if data:
module = name.split('/')[0]
if module.endswith('s'):
module = module[:-1]
key_id = '%s_id' % module
if key_id in data:
del data[key_id]
kwargs['data'] = json.dumps(json_prepare_dump(data))
kwargs['headers']['Content-Type'] = 'application/json'
else:
kwargs['params'] = data
if not kwargs['headers']['X-Org-ID']:
del kwargs['headers']['X-Org-ID']
try:
r = getattr(requests, method)(url, **kwargs)
except Exception:
raise YandexConnectException(u'Request error: send', name, data)
if r.status_code > 299:
try:
msg = r.json()
except Exception:
msg = r.text
raise YandexConnectExceptionY(r.status_code, msg)
if method == 'delete':
return True
try:
ret = r.json()
except Exception:
return True
return ret
class YandexConnectBase(object):
""" Yandex connect API base class"""
DOMAIN = None # Request Domain
request = None # Request object
def __init__(self, oauth_token, org_id=None, version=6):
"""
:param oauth_token: OAuth token
:param org_id: ID org
:param version: API version
"""
self.request = YandexConnectRequest(self.DOMAIN, oauth_token, org_id=org_id, version=version)
@staticmethod
def prepare_fields(fields, title_field, only_title_field=False):
"""
Prepare fields data key
:param fields: obj
:param title_field: second field
:param only_title_field: return only title field
:return:
"""
if not fields:
if not only_title_field:
fields = ['id', title_field]
else:
fields = [title_field]
if isinstance(fields, list):
fields = u','.join(fields)
return fields
def list_full(self, callback, default_field, **kwargs):
"""
List full
:param callback: callback function
:param default_field: default field
:param kwargs: params
:return: list
"""
kwargs['fields'] = self.prepare_fields(kwargs['fields'], default_field)
kwargs['per_page'] = 100
pages = None
page = 1
ret = []
while True:
kwargs['page'] = page
r = callback(**kwargs)
if pages is None:
pages = r['pages']
ret += r['result']
if page >= pages:
break
page += 1
return ret

398
yandex_connect/directory.py

@ -0,0 +1,398 @@
# coding: utf8
"""
Yandex.Connect Directory API module
:author: Alexeev Nick
:email: n@akolka.ru
:version: 0.01b
"""
from .base import *
from inspect import currentframe
class YandexConnectDirectory(YandexConnectBase):
""" Yandex connect directory API base class """
DOMAIN = u'https://api.directory.yandex.net' # Request Domain
# ------------------------------------------------------------------------------------------------------------------
# Helper functions
# ------------------------------------------------------------------------------------------------------------------
@staticmethod
def prepare_contacts(contacts):
"""
Convert contacts list of tuple to yandex data structure
:param contacts: list[('type', 'value')]
:return: list
"""
if not contacts:
return None
ret = []
if contacts:
for i in range(len(contacts)):
if type(contacts[i]) is tuple:
item = {
"type": contacts[i][0],
"value": contacts[i][1]
}
else:
item = contacts[i]
ret.append(item)
return ret
@staticmethod
def prepare_name(data):
"""
Prepare kwargs name words to yandex data structure
:param data: kwargs of request
:return: None
"""
data['name'] = {
'first': data['name'],
'last': data['secname'],
'middle': data['sername']
}
for key in data['name'].keys():
if not data['name'][key]:
del data['name'][key]
for key in ['secname', 'sername']:
del data[key]
# ------------------------------------------------------------------------------------------------------------------
# User
# ------------------------------------------------------------------------------------------------------------------
def user_info(self, user_id, fields=None):
"""
Получение информации о сотруднике
:param user_id: ID
:param fields: поля, по умолчанию: id, nickname
:url man: https://tech.yandex.ru/connect/directory/api/concepts/users/read-user-docpage/
:return: yandex request dict информация о сотруднике
"""
data = inspect_args_func(currentframe())
data['fields'] = self.prepare_fields(data['fields'], 'nickname')
return self.request('users/%s' % user_id, data, method='get')
def user_list(self, fields=None, id=None, nickname=None, department_id=None, recursive_department_id=None, group_id=None, recursive_group_id=None, is_dismissed=None, page=None, per_page=None):
"""
Получение списка сотрудников
:param fields: поля, по умолчанию id, nickname
:param id: фильтр
:param nickname: фильтр
:param department_id: фильтр
:param recursive_department_id: фильтр
:param group_id: фильтр
:param recursive_group_id: фильтр
:param is_dismissed: фильтр
:param page: страница
:param per_page: на странице
:url man: https://tech.yandex.ru/connect/directory/api/concepts/users/read-users-list-docpage/
:return: yandex request dict список сотрудников
"""
data = inspect_args_func(currentframe())
data['fields'] = self.prepare_fields(data['fields'], 'nickname')
return self.request('users', data, method='get')
def user_list_full(self, fields=None, id=None, nickname=None, department_id=None, recursive_department_id=None, group_id=None, recursive_group_id=None, is_dismissed=None):
"""
Получение полного списка сотрудников, без страниц
:param fields: поля, по умолчанию id, nickname
:param id: фильтр
:param nickname: фильтр
:param department_id: фильтр
:param recursive_department_id: фильтр
:param group_id: фильтр
:param recursive_group_id: фильтр
:param is_dismissed: фильтр
:url man: https://tech.yandex.ru/connect/directory/api/concepts/users/read-users-list-docpage/
:return: yandex request list - список сотрудников
"""
return self.list_full(self.user_list, 'nickname', **inspect_args_func(currentframe()))
def user_add(self, nickname, password, about=None, aliases=None, birthday=None, contacts=None, department_id=1, gender='male', is_admin=None, is_dismissed=None, name=None, secname=None, sername=None, position=None):
"""
Добавление сотрудника
:param nickname: логин
:param password: пароль
:param about: описание
:param aliases: list, ['псевдоним1', ...]
:param birthday: datetime.date, день рождения
:param contacts: list, Контакты в типах яндекса, либо [tuple('type', 'value'), ...]
:param department_id: ID отдела, 1
:param gender: Пол male|female
:param is_admin: bool, Администор
:param is_dismissed: bool, Увольнение
:param name: Имя
:param secname: Фамилия
:param sername: Отчество
:param position: Должность
:url man: https://tech.yandex.ru/connect/directory/api/concepts/users/add-user-docpage/
:return: yandex request dict созданный сотрудник
"""
data = inspect_args_func(currentframe())
self.prepare_name(data)
data['contacts'] = self.prepare_contacts(data['contacts'])
return self.request('users', data, method='post')
def user_upd(self, user_id, nickname=None, password=None, about=None, birthday=None, contacts=None, department_id=None, gender=None, is_admin=None, is_dismissed=None, name=None, secname=None, sername=None, position=None):
"""
Изменение сотрудника
:param user_id: ID сотрудника
:param nickname: логин
:param password: пароль
:param about: описание
:param aliases: list, ['псевдоним1', ...]
:param birthday: datetime.date, день рождения
:param contacts: list, Контакты в типах яндекса, либо [tuple('type', 'value'), ...]
:param department_id: ID отдела, 1
:param gender: Пол male|female
:param is_admin: bool, Администор
:param is_dismissed: bool, Увольнение
:param name: Имя
:param secname: Фамилия
:param sername: Отчество
:param position: Должность
:url man: https://tech.yandex.ru/connect/directory/api/concepts/users/edit-user-docpage/
:return: yandex request dict измененный сотрудник
"""
data = inspect_args_func(currentframe())
self.prepare_name(data)
data['contacts'] = self.prepare_contacts(data['contacts'])
return self.request('users/%s' % user_id, data, method='patch')
def user_alias_add(self, user_id, name):
"""
Добавление алиаса для сотрудника
:param user_id: ID сотрудника
:param name: алиас
:url man: https://tech.yandex.ru/connect/directory/api/concepts/users/add-user-aliases-docpage/
:return: yandex request dict
"""
return self.request('users/%s/aliases' % user_id, inspect_args_func(currentframe()), method='post')
# ------------------------------------------------------------------------------------------------------------------
# Department
# ------------------------------------------------------------------------------------------------------------------
def department_list(self, fields=None, page=None, per_page=None):
"""
Получение списка отделов
:param fields: поля, по умолчанию - id, name
:param page: страница
:param per_page: количество элементов на странице
:url man: https://tech.yandex.ru/connect/directory/api/concepts/departments/read-departments-list-docpage/
:return: yandex request list - список отделов
"""
data = inspect_args_func(currentframe())
data['fields'] = self.prepare_fields(data['fields'], 'name')
return self.request('departments', data, method='get')
def department_list_full(self, fields=None):
"""
Получение полного списка отделов
:param fields: поля, по умолчанию - id, name
:url man: https://tech.yandex.ru/connect/directory/api/concepts/departments/read-departments-list-docpage/
:return: yandex request list - список отделов
"""
return self.list_full(self.department_list, 'name', **inspect_args_func(currentframe()))
def department_info(self, department_id):
"""
Получение информации об отделе
:param department_id: ID
:return: yandex request dict
"""
return self.request('departments/%s' % department_id, method='get')
def department_add(self, name, label, description=None, head_id=None, parent_id=1):
"""
Добавление отдела
:param name: название
:param label: рассылка
:param description: описание
:param head_id: id руководителя отдела
:param parent_id: id родительского отдела, 1
:url man: https://tech.yandex.ru/connect/directory/api/concepts/departments/create-department-docpage/
:return: yandex request dict - созданный отдел
"""
return self.request('departments', inspect_args_func(currentframe()), method='post')
def department_upd(self, department_id, name=None, description=None, head_id=None, label=None, parent_id=None):
"""
Изменение отдела
:param department_id: ID
:param name: название
:param label: рассылка
:param description: описание
:param head_id: id руководителя отдела
:param parent_id: id родительского отдела
:url man: https://tech.yandex.ru/connect/directory/api/concepts/departments/edit-department-docpage/
:return: yandex request dict - созданный отдел
"""
return self.request('departments/%s' % department_id, inspect_args_func(currentframe()), method='patch')
def department_del(self, department_id):
"""
Удаление отдела
:param department_id: ID
:url man: https://tech.yandex.ru/connect/directory/api/concepts/departments/delete-department-docpage/
:return: bool
"""
return self.request('departments/%s' % department_id, method='delete')
# ------------------------------------------------------------------------------------------------------------------
# Group
# ------------------------------------------------------------------------------------------------------------------
def group_list(self, fields=None, page=None, per_page=None):
"""
Список команд
:param fields: поля, по умолчанию id, name
:param page: страница
:param per_page: на странице
:url man: https://tech.yandex.ru/connect/directory/api/concepts/groups/read-groups-list-docpage/
:return: yandex request list - список команд
"""
data = inspect_args_func(currentframe())
data['fields'] = self.prepare_fields(data['fields'], 'name')
return self.request('groups', data, method='get')
def group_list_full(self, fields=None):
"""
Полный список команд
:param fields: поля, по умолчанию id, name
:url man: https://tech.yandex.ru/connect/directory/api/concepts/groups/read-groups-list-docpage/
:return: yandex request list - список команд
"""
return self.list_full(self.group_list, 'name', **inspect_args_func(currentframe()))
def group_info(self, group_id, fields=None):
"""
Получение информации о команде
:param group_id: ID
:param fields: поля, по умолчанию id, name
:url man: https://tech.yandex.ru/connect/directory/api/concepts/groups/read-group-docpage/
:return: yandex request dict - команда
"""
data = inspect_args_func(currentframe())
data['fields'] = self.prepare_fields(data['fields'], 'name')
return self.request('groups/%s' % group_id, data, method='get')
def group_add(self, name, label, admins=None, description=None, members=None, type=None):
"""
Добавление команды
:param name: название команды
:param label: название рассылки
:param admins: [{"id": <идентификатор администратора>, "type": "user"},...]
:param description: описание
:param members: list [{"type": "<user|group|department>", "id": <идентификатор>},...]
:param type: тип - generic|organization_admin|robots|department_head
:url man: https://tech.yandex.ru/connect/directory/api/concepts/groups/create-group-docpage/
:return: yandex request dict - созданная команда
"""
return self.request('groups', inspect_args_func(currentframe()), method='post')
def group_upd(self, group_id, name=None, label=None, admins=None, description=None, members=None, type=None):
"""
Изменение команды
:param group_id: ID
:param name: название команды
:param label: название рассылки
:param admins: [{"id": <идентификатор администратора>, "type": "user"},...]
:param description: описание
:param members: list [{"type": "<user|group|department>", "id": <идентификатор>},...]
:param type: тип - generic|organization_admin|robots|department_head
:url man: https://tech.yandex.ru/connect/directory/api/concepts/groups/edit-group-docpage/
:return: yandex request dict - измененная команда
"""
return self.request('groups/%s' % group_id, inspect_args_func(currentframe()), method='patch')
def group_member_list(self, group_id):
"""
Участники команды
:param group_id: ID
:url man: https://tech.yandex.ru/connect/directory/api/concepts/groups/read-group-members-list-docpage/
:return: yandex request list - участники команды
"""
return self.request('groups/%s/members', method='get')
def group_member_add(self, group_id, type, id):
"""
Добавить участника команды
:param group_id: ID
:param type: Тип - user|group|department
:param id: User ID
:url man: https://tech.yandex.ru/connect/directory/api/concepts/groups/add-group-member-docpage/
:return: yandex request dict
"""
return self.request('groups/%s/members' % group_id, inspect_args_func(currentframe()), method='post')
def group_member_del(self, group_id, user_id):
"""
Удалить участника команды
:param group_id: ID
:param user_id: User ID
:url man: https://tech.yandex.ru/connect/directory/api/concepts/groups/bulk-add-group-member-docpage/
:return: True
"""
return self.group_member_update(group_id, [{'operation_type': 'remove', 'value': {'id': user_id}}])
def group_member_update(self, group_id, actions):
"""
Изменение участников команды
:param group_id: ID
:param actions: list, [{"operation_type": "<add|remove>", "value": {"type": "<user|group|department>", "id": ID User}},..]
:url man: https://tech.yandex.ru/connect/directory/api/concepts/groups/bulk-add-group-member-docpage/
:return: True
"""
return self.request('groups/%s/members/bulk-update' % group_id, data=actions, method='post')
# ------------------------------------------------------------------------------------------------------------------
# Domain
# ------------------------------------------------------------------------------------------------------------------
def domain_list(self, fields=None):
"""
Получение списка доменов
:param fields: поля, по умолчанию name
:url man: https://tech.yandex.ru/connect/directory/api/concepts/domains/read-domains-list-docpage/
:return: yandex request list
"""
data = inspect_args_func(currentframe())
data['fields'] = self.prepare_fields(data['fields'], 'name', only_title_field=True)
return self.request('domains', data, method='get')
def domain_add(self, name):
"""
Добавить домен
:param name: домен
:url man: https://tech.yandex.ru/connect/directory/api/concepts/domains/add-domain-docpage/
:return: bool
"""
return self.request('domains', inspect_args_func(currentframe()), method='post')
def domain_del(self, name):
"""
Удалить домен
:param name: домен
:url man: https://tech.yandex.ru/connect/directory/api/concepts/domains/delete-domain-docpage/
:return: bool
"""
return self.request('domains/%s' % name, method='delete')
# ------------------------------------------------------------------------------------------------------------------
# Organization
# ------------------------------------------------------------------------------------------------------------------
def organization_list(self, fields=None):
"""
Список организаций
:param fields: поля, по умолчанию id, name
:return: yandex request list
"""
data = inspect_args_func(currentframe())
data['fields'] = self.prepare_fields(data['fields'], 'name')
return self.request('organizations', data, method='get')['result']
Loading…
Cancel
Save