Helpdesk
helpdesk
¶
Functionality around the HelpDesk / LiveChat API
__all__ = ['HelpDeskClient', 'Mail', 'MailClient', 'Recipient']
module-attribute
¶
HelpDeskClient(config: Optional[Config] = None)
¶
Source code in src/pytanis/helpdesk/client.py
def __init__(self, config: Optional[Config] = None):
if config is None:
config = get_cfg()
self._config = config
# Important: Always use a custom User-Agent, never a generic one.
# Generic User-Agents are filtered by helpdesk to reduce spam.
self._headers = {"User-Agent": "Pytanis"}
self._get_throttled = self._get
self._post_throttled = self._post
self.set_throttling(2, 1) # we are nice by default
create_ticket(ticket: NewTicket)
¶
Source code in src/pytanis/helpdesk/client.py
def create_ticket(self, ticket: NewTicket):
return self.post("tickets", data=ticket.dict())
get(endpoint: str, params: Optional[Dict[str, str]] = None) -> JSON
¶
Retrieve data via throttled GET request and return the JSON
Source code in src/pytanis/helpdesk/client.py
def get(self, endpoint: str, params: Optional[Dict[str, str]] = None) -> JSON:
"""Retrieve data via throttled GET request and return the JSON"""
resp = self._get_throttled(endpoint, params)
resp.raise_for_status()
return resp.json()
list_agents() -> List[Agent]
¶
Source code in src/pytanis/helpdesk/client.py
def list_agents(self) -> List[Agent]:
agents = self.get("agents")
assert isinstance(agents, List)
return [Agent.parse_obj(dct) for dct in agents]
list_teams() -> List[Team]
¶
Source code in src/pytanis/helpdesk/client.py
def list_teams(self) -> List[Team]:
teams = self.get("teams")
assert isinstance(teams, List)
return [Team.parse_obj(dct) for dct in teams]
post(endpoint: str, data: Dict[str, Any], params: Optional[Dict[str, str]] = None) -> JSON
¶
Source code in src/pytanis/helpdesk/client.py
def post(self, endpoint: str, data: Dict[str, Any], params: Optional[Dict[str, str]] = None) -> JSON:
resp = self._post_throttled(endpoint, data, params)
resp.raise_for_status()
return resp.json()
set_throttling(calls: int, seconds: int)
¶
Throttle the number of calls per seconds to the Pretalx API
Source code in src/pytanis/helpdesk/client.py
def set_throttling(self, calls: int, seconds: int):
"""Throttle the number of calls per seconds to the Pretalx API"""
_logger.debug("throttling", calls=calls, seconds=seconds)
self._get_throttled = throttle(calls, seconds)(self._get)
self._post_throttled = throttle(calls, seconds)(self._post)
Mail
¶
Mail template
Use the data
field to store additional information
You can use the typical Format String Syntax and the objects recipient
and mail
to access metadata to complement the template, e.g.:
Hello {recipient.address_as},
We hope it's ok to address you your first name rather than using your full name being {recipient.name}.
Have you read the email's subject '{mail.subject}'? How is your work right now at {recipient.data.company}?
Cheers!
MailClient(helpdesk_client: Optional[HelpDeskClient] = None)
¶
Mail client for mass mails over HelpDesk
Source code in src/pytanis/helpdesk/mail.py
def __init__(self, helpdesk_client: Optional[HelpDeskClient] = None):
if helpdesk_client is None:
helpdesk_client = HelpDeskClient()
self._helpdesk_client = helpdesk_client
self.dry_run: Callable[[NewTicket], None] = self.print_new_ticket
dry_run: Callable[[NewTicket], None] = self.print_new_ticket
instance-attribute
¶
print_new_ticket(ticket: NewTicket)
staticmethod
¶
Default action in a dry-run. Mainly for making sure you sent what you mean!
Overwrite it by assigning to self.dry_run another function
ToDo: Make this function nice, maybe use the rich
library even
Source code in src/pytanis/helpdesk/mail.py
@staticmethod
def print_new_ticket(ticket: NewTicket):
"""Default action in a dry-run. Mainly for making sure you sent what you mean!
Overwrite it by assigning to self.dry_run another function
ToDo: Make this function nice, maybe use the `rich` library even
"""
print("#" * 40)
print(f"Recipient: {ticket.requester.name} <{ticket.requester.email}>")
print(f"Subject: {ticket.subject}")
print(f"{ticket.message.text}")
send(mail: Mail, dry_run: bool = True) -> Tuple[List[Tuple[Recipient, Optional[Ticket]]], List[Tuple[Recipient, Exception]]]
¶
Send a mail to all recipients using HelpDesk
Source code in src/pytanis/helpdesk/mail.py
def send(
self, mail: Mail, dry_run: bool = True
) -> Tuple[List[Tuple[Recipient, Optional[Ticket]]], List[Tuple[Recipient, Exception]]]:
"""Send a mail to all recipients using HelpDesk"""
errors = []
tickets = []
for recipient in tqdm(mail.recipients):
recip_mail = mail.copy()
try:
recip_mail.subject = mail.subject.format(recipient=recipient, mail=mail)
# be aware here that the body might reference to subject line, so it must be filled already
recip_mail.text = recip_mail.text.format(recipient=recipient, mail=recip_mail)
ticket = self._create_ticket(recip_mail, recipient)
if dry_run:
self.print_new_ticket(ticket)
resp_ticket = None
else:
resp = self._helpdesk_client.create_ticket(ticket)
resp_ticket = Ticket.parse_obj(resp)
except Exception as e:
errors.append((recipient, e))
else:
tickets.append((recipient, resp_ticket))
return tickets, errors
Recipient
¶
Details about the recipient
Use the data
field to store additional information
address_as: Optional[str]
class-attribute
¶
data: Optional[MetaData]
class-attribute
¶
email: str
class-attribute
¶
name: str
class-attribute
¶
fill_with_name(v, values)
classmethod
¶
Source code in src/pytanis/helpdesk/mail.py
@validator("address_as")
@classmethod
def fill_with_name(cls, v, values):
if v is None:
v = values["name"]
return v