Skip to content

Commit

Permalink
Merge branch 'prenit-coverfox-add-agent'. Closes #16.
Browse files Browse the repository at this point in the history
  • Loading branch information
sjkingo committed Jun 4, 2018
2 parents 9badc63 + 0f53d11 commit b9ff0da
Show file tree
Hide file tree
Showing 7 changed files with 343 additions and 2 deletions.
102 changes: 101 additions & 1 deletion freshdesk/v2/api.py
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):
Expand Down Expand Up @@ -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.
Expand All @@ -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'
Expand Down
22 changes: 22 additions & 0 deletions freshdesk/v2/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ def _to_timestamp(self, timestamp_str):
return dateutil.parser.parse(timestamp_str)


class TicketField(FreshdeskModel):
def __str__(self):
return self.name

def __repr__(self):
return '<TicketField \'{}\' \'{}\'>'.format(self.name, self.description)

class Ticket(FreshdeskModel):
def __str__(self):
return self.subject
Expand Down Expand Up @@ -101,3 +108,18 @@ def __str__(self):
def __repr__(self):
return '<Company \'{}\>'.format(self.name)

class Agent(FreshdeskModel):
def __str__(self):
return self.contact['name']

def __repr__(self):
return '<Agent #{} \'{}\'>'.format(self.id, self.contact['name'])


class Role(FreshdeskModel):
def __str__(self):
return self.name

def __repr__(self):
return '<Role \'{}\'>'.format(self.name)

23 changes: 23 additions & 0 deletions freshdesk/v2/sample_json_data/agent_1.json
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"
}
}
49 changes: 49 additions & 0 deletions freshdesk/v2/sample_json_data/agents.json
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"
}
}
]
11 changes: 11 additions & 0 deletions freshdesk/v2/sample_json_data/role_1.json
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"
}
24 changes: 24 additions & 0 deletions freshdesk/v2/sample_json_data/roles.json
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"
}
]
114 changes: 113 additions & 1 deletion freshdesk/v2/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)

Expand Down Expand Up @@ -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)

0 comments on commit b9ff0da

Please sign in to comment.