diff --git a/rt.py b/rt.py index f0e799e0b01196388b05332b172cfbb4555d57d6..b406011dc5c815f046e9a344fbb1e56b06ba9a94 100755 --- a/rt.py +++ b/rt.py @@ -23,15 +23,11 @@ class RT(Plugin): api: str login: dict headers = {'User-agent': 'maubot-rt'} - regex_number = re.compile(r'[0-9]+') + regex_id = re.compile(r'[0-9]+') regex_properties = re.compile(r'([a-zA-z]+): (.+)') regex_history = re.compile(r'([0-9]+): (.+)') regex_entry = re.compile(r'([a-zA-z]+): (.+(?:\n {8}.*)*)', re.MULTILINE) - interesting = [ - 'Ticket created', - 'Correspondence added', - 'Comments added', - ] + interesting = ['Ticket created', 'Correspondence added', 'Comments added'] async def start(self) -> None: self.on_external_config_update() @@ -51,17 +47,17 @@ class RT(Plugin): def get_config_class(cls) -> Type[BaseProxyConfig]: return Config - def is_valid_number(self, number: str) -> bool: - return True if self.regex_number.match(number) else False + def is_valid_id(self, id: str) -> bool: + return True if self.regex_id.match(id) else False def filter_dict(self, raw: dict, keys: Set) -> dict: return {k: v for k, v in raw.items() if k in keys} - def markdown_link(self, number: str) -> str: - return f'[rt#{number}]({self.display}?id={number})' + def markdown_link(self, id: str) -> str: + return f'[rt#{id}]({self.display}?id={id})' - def html_link(self, number: str) -> str: - return f'<a href="{self.display}?id={number}">rt#{number}</a>' + def html_link(self, id: str) -> str: + return f'<a href="{self.display}?id={id}">rt#{id}</a>' async def can_manage(self, evt: MessageEvent) -> bool: if evt.sender in self.whitelist: @@ -83,36 +79,36 @@ class RT(Plugin): event = await self.client.get_state_event(room_id, EventType.ROOM_MEMBER, user_id) return event.displayname - async def _properties(self, number: str) -> dict: + async def _properties(self, id: str) -> dict: await self.http.post(self.rest, data=self.login, headers=self.headers) - rest = f'{self.rest}ticket/{number}/show' + rest = f'{self.rest}ticket/{id}/show' async with self.http.get(rest, headers=self.headers) as response: content = await response.text() raw = dict(self.regex_properties.findall(content)) return self.filter_dict(raw, self.filter_properties) - async def _edit(self, number: str, properties: dict) -> None: - rest = f'{self.rest}ticket/{number}/edit' + async def _edit(self, id: str, properties: dict) -> None: + rest = f'{self.rest}ticket/{id}/edit' content = {'content': '\n'.join([f'{k}: {v}' for k, v in properties.items()])} data = {**self.login, **content} await self.http.post(rest, data=data, headers=self.headers) - async def _comment(self, number: str, comment: str) -> None: - rest = f'{self.rest}ticket/{number}/comment' - content = {'content': f'id: {number}\nAction: comment\nText: {comment}'} + async def _comment(self, id: str, comment: str) -> None: + rest = f'{self.rest}ticket/{id}/comment' + content = {'content': f'id: {id}\nAction: comment\nText: {comment}'} data = {**self.login, **content} await self.http.post(rest, data=data, headers=self.headers) - async def _history(self, number: str) -> dict: + async def _history(self, id: str) -> dict: await self.http.post(self.rest, data=self.login, headers=self.headers) - rest = f'{self.rest}ticket/{number}/history' + rest = f'{self.rest}ticket/{id}/history' async with self.http.get(rest, headers=self.headers) as response: content = await response.text() return dict(self.regex_history.findall(content)) - async def _entry(self, number: str, entry: str) -> dict: + async def _entry(self, id: str, entry: str) -> dict: await self.http.post(self.rest, data=self.login, headers=self.headers) - rest = f'{self.rest}ticket/{number}/history/id/{entry}' + rest = f'{self.rest}ticket/{id}/history/id/{entry}' async with self.http.get(rest, headers=self.headers) as response: content = await response.text() raw = dict(self.regex_entry.findall(content)) @@ -128,13 +124,13 @@ class RT(Plugin): msg_lines = [] await self.http.post(self.rest, data=self.login, headers=self.headers) for sub in subs: - number = sub[4] - rest = f'{self.rest}ticket/{number}/show' + id = sub[4] + rest = f'{self.rest}ticket/{id}/show' async with self.http.get(rest, headers=self.headers) as response: content = await response.text() ticket = dict(self.regex_properties.findall(content)) markdown = '{} is **{}** in **{}** from {} \n{}'.format( - self.markdown_link(number), + self.markdown_link(id), ticket['Status'], ticket['Queue'], ticket['Creator'], @@ -151,50 +147,50 @@ class RT(Plugin): pass @rt.subcommand('properties', aliases=('p', 'prop'), help='Show all ticket properties.') - @command.argument('number', 'ticket number', parser=str) - async def properties(self, evt: MessageEvent, number: str) -> None: - if not await self.can_manage(evt) or not self.is_valid_number(number): + @command.argument('id', 'ticket id', parser=str) + async def properties(self, evt: MessageEvent, id: str) -> None: + if not await self.can_manage(evt) or not self.is_valid_id(id): return await evt.mark_read() - properties_dict = await self._properties(number) + properties_dict = await self._properties(id) properties = ' \n'.join([f'{k}: {v}' for k, v in properties_dict.items()]) - await evt.respond(f'{self.markdown_link(number)} properties: \n{properties}') + await evt.respond(f'{self.markdown_link(id)} properties: \n{properties}') @rt.subcommand('resolve', aliases=('r', 'res'), help='Mark the ticket as resolved.') - @command.argument('number', 'ticket number', parser=str) - async def resolve(self, evt: MessageEvent, number: str) -> None: - if not await self.can_manage(evt) or not self.is_valid_number(number): + @command.argument('id', 'ticket id', parser=str) + async def resolve(self, evt: MessageEvent, id: str) -> None: + if not await self.can_manage(evt) or not self.is_valid_id(id): return await evt.mark_read() - await self._edit(number, {'Status': 'resolved'}) - await evt.respond(f'{self.markdown_link(number)} resolved 😃') + await self._edit(id, {'Status': 'resolved'}) + await evt.respond(f'{self.markdown_link(id)} resolved 😃') @rt.subcommand('open', aliases=('o', 'op'), help='Mark the ticket as open.') - @command.argument('number', 'ticket number', parser=str) - async def open(self, evt: MessageEvent, number: str) -> None: - if not await self.can_manage(evt) or not self.is_valid_number(number): + @command.argument('id', 'ticket id', parser=str) + async def open(self, evt: MessageEvent, id: str) -> None: + if not await self.can_manage(evt) or not self.is_valid_id(id): return await evt.mark_read() - await self._edit(number, {'Status': 'open'}) - await evt.respond(f'{self.markdown_link(number)} opened ðŸ˜ï¸') + await self._edit(id, {'Status': 'open'}) + await evt.respond(f'{self.markdown_link(id)} opened ðŸ˜ï¸') @rt.subcommand('stall', aliases=('st', 'sta'), help='Mark the ticket as stalled.') - @command.argument('number', 'ticket number', parser=str) - async def stall(self, evt: MessageEvent, number: str) -> None: - if not await self.can_manage(evt) or not self.is_valid_number(number): + @command.argument('id', 'ticket id', parser=str) + async def stall(self, evt: MessageEvent, id: str) -> None: + if not await self.can_manage(evt) or not self.is_valid_id(id): return await evt.mark_read() - await self._edit(number, {'Status': 'stalled'}) - await evt.respond(f'{self.markdown_link(number)} stalled 😴') + await self._edit(id, {'Status': 'stalled'}) + await evt.respond(f'{self.markdown_link(id)} stalled 😴') @rt.subcommand('delete', aliases=('d', 'del'), help='Mark the ticket as deleted.') - @command.argument('number', 'ticket number', parser=str) - async def delete(self, evt: MessageEvent, number: str) -> None: - if not await self.can_manage(evt) or not self.is_valid_number(number): + @command.argument('id', 'ticket id', parser=str) + async def delete(self, evt: MessageEvent, id: str) -> None: + if not await self.can_manage(evt) or not self.is_valid_id(id): return await evt.mark_read() - await self._edit(number, {'Status': 'deleted'}) - await evt.respond(f'{self.markdown_link(number)} deleted 🤬') + await self._edit(id, {'Status': 'deleted'}) + await evt.respond(f'{self.markdown_link(id)} deleted 🤬') @rt.subcommand('autoresolve', help='Ask the bot to automatically answer and resolve tickets.') async def autoresolve(self, evt: MessageEvent) -> None: @@ -204,89 +200,89 @@ class RT(Plugin): await evt.react('😂🤣🦄🌈') @rt.subcommand('comment', aliases=('c', 'com'), help='Add a comment.') - @command.argument('number', 'ticket number', parser=str) + @command.argument('id', 'ticket id', parser=str) @command.argument('comment', 'comment text', pass_raw=True) - async def comment(self, evt: MessageEvent, number: str, comment: str) -> None: - if not await self.can_manage(evt) or not self.is_valid_number(number): + async def comment(self, evt: MessageEvent, id: str, comment: str) -> None: + if not await self.can_manage(evt) or not self.is_valid_id(id): return await evt.mark_read() - await self._comment(number, comment) - await evt.respond(f'{self.markdown_link(number)} comment added 🤓') + await self._comment(id, comment) + await evt.respond(f'{self.markdown_link(id)} comment added 🤓') @rt.subcommand('history', aliases=('h', 'hist'), help='Get a list of all history entries.') - @command.argument('number', 'ticket number', parser=str) - async def history(self, evt: MessageEvent, number: str) -> None: - if not await self.can_manage(evt) or not self.is_valid_number(number): + @command.argument('id', 'ticket id', parser=str) + async def history(self, evt: MessageEvent, id: str) -> None: + if not await self.can_manage(evt) or not self.is_valid_id(id): return await evt.mark_read() - history_dict = await self._history(number) + history_dict = await self._history(id) history = ' \n'.join([f'{k}: {v}' for k, v in history_dict.items()]) - await evt.respond(f'{self.markdown_link(number)} history entries: \n{history}') + await evt.respond(f'{self.markdown_link(id)} history entries: \n{history}') @rt.subcommand('entry', aliases=('e', 'ent'), help='Gets a single history entry.') - @command.argument('number', 'ticket number', parser=str) - @command.argument('entryid', 'history entry number', parser=str) - async def entry(self, evt: MessageEvent, number: str, entryid: str) -> None: - if not await self.can_manage(evt) or not self.is_valid_number(number): + @command.argument('id', 'ticket id', parser=str) + @command.argument('entryid', 'history entry id', parser=str) + async def entry(self, evt: MessageEvent, id: str, entryid: str) -> None: + if not await self.can_manage(evt) or not self.is_valid_id(id): return await evt.mark_read() - entry_dict = await self._entry(number, entryid) + entry_dict = await self._entry(id, entryid) entry = ' \n'.join([f'{k}: {v}' for k, v in entry_dict.items()]) - await evt.respond(f'{self.markdown_link(number)} history entry {entryid}: \n{entry}') + await evt.respond(f'{self.markdown_link(id)} history entry {entryid}: \n{entry}') @rt.subcommand('last', aliases=('l', 'la'), help='Gets the last entry.') - @command.argument('number', 'ticket number', parser=str) - async def last(self, evt: MessageEvent, number: str) -> None: - if not await self.can_manage(evt) or not self.is_valid_number(number): + @command.argument('id', 'ticket id', parser=str) + async def last(self, evt: MessageEvent, id: str) -> None: + if not await self.can_manage(evt) or not self.is_valid_id(id): return await evt.mark_read() - history = await self._history(number) + history = await self._history(id) mails = {k: v for k, v in history.items() if any(i in v for i in self.interesting)} entryid = max(mails, key=int) - entry_dict = await self._entry(number, entryid) + entry_dict = await self._entry(id, entryid) entry = ' \n'.join([f'{k}: {v}' for k, v in entry_dict.items()]) - await evt.respond(f'{self.markdown_link(number)} history entry {entryid}: \n{entry}') + await evt.respond(f'{self.markdown_link(id)} history entry {entryid}: \n{entry}') @rt.subcommand('show', aliases=('s', 'sh'), help='Show all information about the ticket.') - @command.argument('number', 'ticket number', parser=str) - async def show(self, evt: MessageEvent, number: str) -> None: - if not await self.can_manage(evt) or not self.is_valid_number(number): + @command.argument('id', 'ticket id', parser=str) + async def show(self, evt: MessageEvent, id: str) -> None: + if not await self.can_manage(evt) or not self.is_valid_id(id): return await evt.mark_read() - prop_dict = await self._properties(number) + prop_dict = await self._properties(id) props = ' \n'.join([f'{k}: {v}' for k, v in prop_dict.items()]) - await evt.respond(f'{self.markdown_link(number)} properties: \n{props}') - history = await self._history(number) + await evt.respond(f'{self.markdown_link(id)} properties: \n{props}') + history = await self._history(id) for entryid, entry_text in history.items(): if any(i in entry_text for i in self.interesting + ['Requestor']): if 'Requestor' in entry_text: await evt.respond(f'history entry {entryid}: {entry_text}') continue - entry_dict = await self._entry(number, entryid) + entry_dict = await self._entry(id, entryid) entry = ' \n'.join([f'{k}: {v}' for k, v in entry_dict.items()]) await evt.respond(f'history entry {entryid}: \n{entry}') @rt.subcommand('take', aliases=('t', 'ta', 'steal'), help='Take or steal the ticket.') - @command.argument('number', 'ticket number', parser=str) - async def take(self, evt: MessageEvent, number: str) -> None: - if not await self.can_manage(evt) or not self.is_valid_number(number): + @command.argument('id', 'ticket id', parser=str) + async def take(self, evt: MessageEvent, id: str) -> None: + if not await self.can_manage(evt) or not self.is_valid_id(id): return await evt.mark_read() username = await self._username(evt) displayname = await self._displayname(evt.room_id, evt.sender) - await self._edit(number, {'Owner': username}) + await self._edit(id, {'Owner': username}) content = TextMessageEventContent( msgtype=MessageType.NOTICE, format=Format.HTML, - body=f'{displayname} took rt#{number} ðŸ‘ï¸', + body=f'{displayname} took rt#{id} ðŸ‘ï¸', formatted_body=f'<a href="https://matrix.to/#/{evt.sender}">{evt.sender}</a> ' - f'took {self.html_link(number)} ðŸ‘ï¸') + f'took {self.html_link(id)} ðŸ‘ï¸') await evt.respond(content) @rt.subcommand('give', aliases=('g', 'gi', 'assign'), help='Give the ticket to somebody.') - @command.argument('number', 'ticket number', parser=str) + @command.argument('id', 'ticket id', parser=str) @command.argument('user', 'matrix user', parser=str) - async def give(self, evt: MessageEvent, number: str, user: str) -> None: - if not await self.can_manage(evt) or not self.is_valid_number(number): + async def give(self, evt: MessageEvent, id: str, user: str) -> None: + if not await self.can_manage(evt) or not self.is_valid_id(id): return await evt.mark_read() member_mxids = await self._member_mxids(evt.room_id) @@ -301,11 +297,11 @@ class RT(Plugin): displayname = await self._displayname(evt.room_id, evt.sender) target_mxid = member_mxids[user] target_username = target_mxid[1:].split(':')[0] - await self._edit(number, {'Owner': target_username}) + await self._edit(id, {'Owner': target_username}) content = TextMessageEventContent( msgtype=MessageType.NOTICE, format=Format.HTML, - body=f'{displayname} assigned rt#{number} to {user} 😜', + body=f'{displayname} assigned rt#{id} to {user} 😜', formatted_body=f'<a href="https://matrix.to/#/{evt.sender}">{evt.sender}</a> ' - f'assigned {self.html_link(number)} to ' + f'assigned {self.html_link(id)} to ' f'<a href="https://matrix.to/#/{target_mxid}">{target_mxid}</a> 😜') await evt.respond(content)