feat(core): Add slash command /spend
for ticket and ticket comments
ref: #284 closes #286
This commit is contained in:
37
app/core/lib/slash_commands/__init__.py
Normal file
37
app/core/lib/slash_commands/__init__.py
Normal file
@ -0,0 +1,37 @@
|
||||
import re
|
||||
|
||||
from core.lib.slash_commands.duration import Duration
|
||||
|
||||
|
||||
class SlashCommands(
|
||||
Duration
|
||||
):
|
||||
"""Slash Commands Base Class
|
||||
|
||||
This class in intended to be included in the following models:
|
||||
|
||||
- Ticket
|
||||
|
||||
- TicketComment
|
||||
"""
|
||||
|
||||
|
||||
def slash_command(self, markdown:str) -> str:
|
||||
""" Slash Commands Processor
|
||||
|
||||
Markdown text that contains a slash command is passed to this function and on the processing
|
||||
of any valid slash command, the slash command will be removed from the markdown.
|
||||
|
||||
If any error occurs when attempting to process the slash command, it will not be removed from
|
||||
the markdown. This is by design so that the "errored" slash command can be inspected.
|
||||
|
||||
Args:
|
||||
markdown (str): un-processed Markdown
|
||||
|
||||
Returns:
|
||||
str: Markdown without the slash command text.
|
||||
"""
|
||||
|
||||
markdown = re.sub(self.time_spent, self.command_duration, markdown)
|
||||
|
||||
return markdown
|
91
app/core/lib/slash_commands/duration.py
Normal file
91
app/core/lib/slash_commands/duration.py
Normal file
@ -0,0 +1,91 @@
|
||||
import re
|
||||
|
||||
|
||||
class Duration:
|
||||
"""Duration Slash Command
|
||||
|
||||
The command keyword is `spend` and you can also use `spent`. The formatting for the time
|
||||
after the command, is <digit> then either `h`, `m`, `s` for hours, minutes and seconds respectively.
|
||||
|
||||
Valid commands are as follows:
|
||||
|
||||
- /spend 1h1ms
|
||||
|
||||
- /spend 1h 1m 1s
|
||||
|
||||
For this command to process the following conditions must be met:
|
||||
|
||||
- There is either a `<new line>` (`\n`) or a `<space>` char immediatly before the slash `/`
|
||||
|
||||
- There is a `<space>` char after the command keyword, i.e. `/spend<space>1h`
|
||||
|
||||
- _Optional_ `<space>` char between the time blocks.
|
||||
"""
|
||||
|
||||
|
||||
time_spent: str = r'[\s|\n]\/(?P<command>[spend|spent]+)\s(?P<time>(?P<hours>\d+h)?\s?(?P<minutes>[\d]{1,2}m)?\s?(?P<seconds>\d+[s])?)[\s|\n]?'
|
||||
|
||||
|
||||
def command_duration(self, match) -> str:
|
||||
"""/spend, /spent processor
|
||||
|
||||
Slash command usage within a ticket description will add an action comment with the
|
||||
time spent. For a ticket comment, it's duration field is set to the duration valuee calculated.
|
||||
|
||||
Args:
|
||||
match (re.Match): Grouped matches
|
||||
|
||||
Returns:
|
||||
str: The matched string if the duration calculation is `0`
|
||||
None: On successfully processing the command
|
||||
"""
|
||||
|
||||
a = 'a'
|
||||
|
||||
command = match.group('command')
|
||||
time:str = str(match.group('time')).replace(' ', '')
|
||||
hours = match.group('hours')
|
||||
minutes = match.group('minutes')
|
||||
seconds = match.group('seconds')
|
||||
|
||||
duration: int = 0
|
||||
|
||||
if hours is not None:
|
||||
|
||||
duration += int(hours[:-1])*60*60
|
||||
|
||||
if minutes is not None:
|
||||
|
||||
duration += int(minutes[:-1])*60
|
||||
|
||||
if seconds is not None:
|
||||
|
||||
duration += int(seconds[:-1])
|
||||
|
||||
if duration > 0:
|
||||
|
||||
if str(self._meta.verbose_name).lower() == 'ticket':
|
||||
|
||||
from core.models.ticket.ticket_comment import TicketComment
|
||||
|
||||
comment_text = f'added {time} of time spent'
|
||||
|
||||
TicketComment.objects.create(
|
||||
ticket = self,
|
||||
comment_type = TicketComment.CommentType.ACTION,
|
||||
body = comment_text,
|
||||
duration = duration,
|
||||
user = self.opened_by,
|
||||
)
|
||||
|
||||
if str(self._meta.verbose_name).lower() == 'comment':
|
||||
|
||||
self.duration = duration
|
||||
|
||||
else:
|
||||
|
||||
#ToDo: Add logging that the slash command could not be processed.
|
||||
|
||||
return str(match.string[match.start():match.end()])
|
||||
|
||||
return None
|
Reference in New Issue
Block a user