-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'prenit-coverfox-add-agent'. Closes #16.
- Loading branch information
Showing
7 changed files
with
343 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
import requests | ||
from requests.exceptions import HTTPError | ||
import json | ||
from freshdesk.v2.models import Ticket, Comment, Customer, Contact, Group, Company | ||
from freshdesk.v2.models import Ticket, Comment, Customer, Contact, Group, Company, Agent, Role, TicketField | ||
|
||
|
||
class TicketAPI(object): | ||
|
@@ -175,6 +175,103 @@ def get_company(self, company_id): | |
url = 'companies/%s' % company_id | ||
return Company(**self._api._get(url)) | ||
|
||
|
||
class RoleAPI(object): | ||
def __init__(self, api): | ||
self._api = api | ||
|
||
def list_roles(self): | ||
url = 'roles' | ||
roles = [] | ||
for r in self._api._get(url): | ||
roles.append(Role(**r)) | ||
return roles | ||
|
||
def get_role(self, role_id): | ||
url = 'roles/%s' % role_id | ||
return Role(**self._api._get(url)) | ||
|
||
|
||
class TicketFieldAPI(object): | ||
def __init__(self, api): | ||
self._api = api | ||
|
||
def list_ticket_fields(self, **kwargs): | ||
url = 'ticket_fields' | ||
ticket_fields = [] | ||
|
||
if kwargs.has_key('type'): | ||
url = "{}?type={}".format(url, kwargs['type']) | ||
|
||
for tf in self._api._get(url): | ||
ticket_fields.append(TicketField(**tf)) | ||
return ticket_fields | ||
|
||
|
||
class AgentAPI(object): | ||
def __init__(self, api): | ||
self._api = api | ||
|
||
def list_agents(self, **kwargs): | ||
"""List all agents, optionally filtered by a view. Specify filters as | ||
keyword arguments, such as: | ||
{ | ||
email='[email protected]', | ||
phone=873902, | ||
mobile=56523, | ||
state='fulltime' | ||
} | ||
Passing None means that no named filter will be passed to | ||
Freshdesk, which returns list of all agents | ||
Multiple filters are AND'd together. | ||
""" | ||
|
||
url = 'agents?' | ||
if kwargs: | ||
for filter_name, filter_value in kwargs.items(): | ||
url = url + "{}={}&".format(filter_name, filter_value) | ||
del kwargs[filter_name] | ||
|
||
page = 1 | ||
per_page = 100 | ||
agents = [] | ||
|
||
# Skip pagination by looping over each page and adding tickets | ||
while True: | ||
this_page = self._api._get(url + 'page=%d&per_page=%d' | ||
% (page, per_page), kwargs) | ||
agents += this_page | ||
if len(this_page) < per_page: | ||
break | ||
page += 1 | ||
|
||
return [Agent(**a) for a in agents] | ||
|
||
def get_agent(self, agent_id): | ||
"""Fetches the agent for the given agent ID""" | ||
url = 'agents/%s' % agent_id | ||
return Agent(**self._api._get(url)) | ||
|
||
def update_agent(self, agent_id, **kwargs): | ||
"""Updates an agent""" | ||
url = 'agents/%s' % agent_id | ||
agent = self._api._put(url, data=json.dumps(kwargs)) | ||
return Agent(**agent) | ||
|
||
def delete_agent(self, agent_id): | ||
"""Delete the agent for the given agent ID""" | ||
url = 'agents/%d' % agent_id | ||
self._api._delete(url) | ||
|
||
def currently_authenticated_agent(self): | ||
"""Fetches currently logged in agent""" | ||
url = 'agents/me' | ||
return Agent(**self._api._get(url)) | ||
|
||
|
||
class API(object): | ||
def __init__(self, domain, api_key): | ||
"""Creates a wrapper to perform API actions. | ||
|
@@ -198,6 +295,9 @@ def __init__(self, domain, api_key): | |
self.companies = CompanyAPI(self) | ||
self.groups = GroupAPI(self) | ||
self.customers = CustomerAPI(self) | ||
self.agents = AgentAPI(self) | ||
self.roles = RoleAPI(self) | ||
self.ticket_fields = TicketFieldAPI(self) | ||
|
||
if domain.find('freshdesk.com') < 0: | ||
raise AttributeError('Freshdesk v2 API works only via Freshdesk' | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"available":true, | ||
"occasional":false, | ||
"signature":null, | ||
"id":1, | ||
"ticket_scope":1, | ||
"created_at":"2015-08-18T16:18:05Z", | ||
"updated_at":"2015-08-18T16:18:05Z", | ||
"available_since":null, | ||
"contact":{ | ||
"active":true, | ||
"email":"[email protected]", | ||
"job_title":null, | ||
"language":"en", | ||
"last_login_at":"2015-08-21T14:54:46+05:30", | ||
"mobile":1234, | ||
"name":"Support", | ||
"phone":5678, | ||
"time_zone":"Chennai", | ||
"created_at":"2015-08-18T16:18:05Z", | ||
"updated_at":"2015-08-25T08:50:20Z" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
[ | ||
{ | ||
"available":true, | ||
"occasional":false, | ||
"signature":null, | ||
"id":1, | ||
"ticket_scope":1, | ||
"created_at":"2015-08-18T16:18:05Z", | ||
"updated_at":"2015-08-18T16:18:05Z", | ||
"available_since":null, | ||
"contact":{ | ||
"active":true, | ||
"email":"[email protected]", | ||
"job_title":null, | ||
"language":"en", | ||
"last_login_at":"2015-08-21T14:54:46+05:30", | ||
"mobile":1234, | ||
"name":"Support", | ||
"phone":5678, | ||
"time_zone":"Chennai", | ||
"created_at":"2015-08-18T16:18:05Z", | ||
"updated_at":"2015-08-25T08:50:20Z" | ||
} | ||
}, | ||
{ | ||
"available":true, | ||
"occasional":false, | ||
"signature":null, | ||
"signature":null, | ||
"id":432, | ||
"ticket_scope":1, | ||
"created_at":"2015-08-28T11:47:58Z", | ||
"updated_at":"2015-08-28T11:47:58Z", | ||
"available_since":null, | ||
"contact":{ | ||
"active":false, | ||
"email":"[email protected]", | ||
"job_title":"Journalist", | ||
"language":"en", | ||
"last_login_at":null, | ||
"mobile":null, | ||
"name":"Clark Kent", | ||
"phone":null, | ||
"time_zone":"Chennai", | ||
"created_at":"2015-08-28T09:08:16Z", | ||
"updated_at":"2015-08-28T11:47:58Z" | ||
} | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"id": 1, | ||
"name": "Agent", | ||
"description": "Can log, view, reply, update and resolve tickets and manage contacts.", | ||
"business_hour_id": null, | ||
"escalate_to": 1, | ||
"unassigned_for": "30m", | ||
"auto_ticket_assign": true, | ||
"created_at": "2014-01-08T07:53:41+05:30", | ||
"updated_at": "2014-01-08T07:53:41+05:30" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
[ | ||
{ | ||
"id": 1, | ||
"name": "Agent", | ||
"description": "Can log, view, reply, update and resolve tickets and manage contacts.", | ||
"business_hour_id": null, | ||
"escalate_to": 1, | ||
"unassigned_for": "30m", | ||
"auto_ticket_assign": true, | ||
"created_at": "2014-01-08T07:53:41+05:30", | ||
"updated_at": "2014-01-08T07:53:41+05:30" | ||
}, | ||
{ | ||
"id": 2, | ||
"name": "Administrator", | ||
"description": "Can configure all features through the Admin tab, but is restricted from viewing Account or Billing related information.", | ||
"business_hour_id": null, | ||
"escalate_to": 1, | ||
"unassigned_for": "30m", | ||
"auto_ticket_assign": true, | ||
"created_at": "2014-01-08T07:53:41+05:30", | ||
"updated_at": "2014-01-08T07:53:41+05:30" | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ | |
from unittest import TestCase | ||
|
||
from freshdesk.v2.api import API | ||
from freshdesk.v2.models import Ticket, Comment, Contact, Customer, Group | ||
from freshdesk.v2.models import Ticket, Comment, Contact, Customer, Group, Agent, Role | ||
|
||
""" | ||
Test suite for python-freshdesk. | ||
|
@@ -33,6 +33,14 @@ def __init__(self, *args): | |
re.compile(r'customers/1$'): self.read_test_file('customer.json'), | ||
re.compile(r'groups$'): self.read_test_file('groups.json'), | ||
re.compile(r'groups/1$'): self.read_test_file('group_1.json'), | ||
re.compile(r'roles$'): self.read_test_file('roles.json'), | ||
re.compile(r'roles/1$'): self.read_test_file('role_1.json'), | ||
re.compile(r'agents\[email protected]&page=1&per_page=100'): self.read_test_file('agent_1.json'), | ||
re.compile(r'agents\?mobile=1234&page=1&per_page=100'): self.read_test_file('agent_1.json'), | ||
re.compile(r'agents\?phone=5678&page=1&per_page=100'): self.read_test_file('agent_1.json'), | ||
re.compile(r'agents\?state=fulltime&page=1&per_page=100'): self.read_test_file('agent_1.json'), | ||
re.compile(r'agents\?page=1&per_page=100'): self.read_test_file('agents.json'), | ||
re.compile(r'agents/1$'): self.read_test_file('agent_1.json'), | ||
} | ||
super(MockedAPI, self).__init__(*args) | ||
|
||
|
@@ -359,3 +367,107 @@ def test_group_datetime(self): | |
|
||
def test_group_repr(self): | ||
self.assertEqual(repr(self.group), '<Group \'Entertainers\'>') | ||
|
||
class TestRole(TestCase): | ||
@classmethod | ||
def setUpClass(cls): | ||
cls.api = MockedAPI(DOMAIN, API_KEY) | ||
cls.role = cls.api.roles.get_role(1) | ||
|
||
def test_list_roles(self): | ||
roles = self.api.roles.list_roles() | ||
self.assertIsInstance(roles, list) | ||
self.assertEqual(len(roles), 2) | ||
self.assertEqual(roles[0].id, self.role.id) | ||
|
||
def test_role(self): | ||
self.assertIsInstance(self.role, Role) | ||
self.assertEqual(self.role.name, 'Agent') | ||
self.assertEqual(self.role.description, 'Can log, view, reply, update and resolve tickets and manage contacts.') | ||
|
||
def test_group_datetime(self): | ||
self.assertIsInstance(self.role.created_at, datetime.datetime) | ||
self.assertIsInstance(self.role.updated_at, datetime.datetime) | ||
|
||
def test_group_repr(self): | ||
self.assertEqual(repr(self.role), '<Role \'Agent\'>') | ||
|
||
|
||
class TestAgent(TestCase): | ||
|
||
@classmethod | ||
def setUpClass(cls): | ||
cls.api = MockedAPI(DOMAIN, API_KEY) | ||
cls.agent = cls.api.agents.get_agent(1) | ||
cls.agent_json = json.loads(open(os.path.join(os.path.dirname(__file__), | ||
'sample_json_data', | ||
'agent_1.json')).read()) | ||
|
||
def test_str(self): | ||
self.assertEqual(str(self.agent), 'Support') | ||
|
||
def test_repr(self): | ||
self.assertEqual(repr(self.agent), '<Agent #1 \'Support\'>') | ||
|
||
def test_get_agent(self): | ||
self.assertIsInstance(self.agent, Agent) | ||
self.assertEqual(self.agent.id, 1) | ||
self.assertEqual(self.agent.contact['name'], 'Support') | ||
self.assertEqual(self.agent.contact['email'], '[email protected]') | ||
self.assertEqual(self.agent.contact['mobile'], 1234) | ||
self.assertEqual(self.agent.contact['phone'], 5678) | ||
self.assertEqual(self.agent.occasional, False) | ||
|
||
@responses.activate | ||
def test_update_agent(self): | ||
a = self.agent_json.copy() | ||
|
||
responses.add(responses.GET, | ||
'https://{}/api/v2/agents/1'.format(DOMAIN), | ||
status=200, content_type='application/json', json=a) | ||
|
||
values = { | ||
'occasional': True, | ||
'contact': { | ||
'name': 'Updated Name' | ||
} | ||
} | ||
|
||
b = a.copy() | ||
b.update(values) | ||
|
||
responses.add(responses.PUT, | ||
'https://{}/api/v2/agents/1'.format(DOMAIN), | ||
status=200, content_type='application/json', json=b) | ||
|
||
agent = self.api.agents.update_agent(a['id'], **values) | ||
|
||
self.assertEqual(agent.occasional, True) | ||
self.assertEqual(agent.contact['name'], 'Updated Name') | ||
|
||
@responses.activate | ||
def test_delete_agent(self): | ||
responses.add(responses.DELETE, | ||
'https://{}/api/v2/agents/1'.format(DOMAIN), | ||
status=204) | ||
self.api.agents.delete_agent(1) | ||
|
||
def test_agent_name(self): | ||
self.assertEqual(self.agent.contact['name'], 'Support') | ||
|
||
def test_agent_mobile(self): | ||
self.assertEqual(self.agent.contact['mobile'], 1234) | ||
|
||
def test_agent_state(self): | ||
self.assertEqual(self.agent.available, True) | ||
self.assertEqual(self.agent.occasional, False) | ||
|
||
def test_agent_datetime(self): | ||
self.assertIsInstance(self.agent.created_at, datetime.datetime) | ||
self.assertIsInstance(self.agent.updated_at, datetime.datetime) | ||
|
||
def test_none_filter_name(self): | ||
agents = self.api.agents.list_agents() | ||
self.assertIsInstance(agents, list) | ||
self.assertEqual(len(agents), 2) | ||
self.assertEqual(agents[0].id, self.agent.id) |