mirror of
https://github.com/System-End/nephthys.git
synced 2026-04-19 18:35:14 +00:00
add stale closing
This commit is contained in:
parent
56f184718a
commit
36b488d9d3
4 changed files with 99 additions and 2 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import asyncio
|
||||
import contextlib
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
import uvicorn
|
||||
from aiohttp import ClientSession
|
||||
|
|
@ -8,6 +9,7 @@ from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
|||
from dotenv import load_dotenv
|
||||
from starlette.applications import Starlette
|
||||
|
||||
from nephthys.tasks.close_stale import close_stale_tickets
|
||||
from nephthys.tasks.daily_stats import send_daily_stats
|
||||
from nephthys.tasks.update_helpers import update_helpers
|
||||
from nephthys.utils.delete_thread import process_queue
|
||||
|
|
@ -35,6 +37,13 @@ async def main(_app: Starlette):
|
|||
|
||||
scheduler = AsyncIOScheduler(timezone="Europe/London")
|
||||
scheduler.add_job(send_daily_stats, "cron", hour=0, minute=0)
|
||||
scheduler.add_job(
|
||||
close_stale_tickets,
|
||||
"interval",
|
||||
hours=1,
|
||||
max_instances=1,
|
||||
next_run_time=datetime.now(),
|
||||
)
|
||||
scheduler.start()
|
||||
|
||||
delete_msg_task = asyncio.create_task(process_queue())
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from nephthys.utils.permissions import can_resolve
|
|||
from prisma.enums import TicketStatus
|
||||
|
||||
|
||||
async def resolve(ts: str, resolver: str, client: AsyncWebClient):
|
||||
async def resolve(ts: str, resolver: str, client: AsyncWebClient, stale: bool = False):
|
||||
resolving_user = await env.db.user.find_unique(where={"slackId": resolver})
|
||||
if not resolving_user:
|
||||
await send_heartbeat(
|
||||
|
|
@ -57,7 +57,9 @@ async def resolve(ts: str, resolver: str, client: AsyncWebClient):
|
|||
|
||||
await client.chat_postMessage(
|
||||
channel=env.slack_help_channel,
|
||||
text=env.transcript.ticket_resolve.format(user_id=resolver),
|
||||
text=env.transcript.ticket_resolve.format(user_id=resolver)
|
||||
if not stale
|
||||
else env.transcript.ticket_resolve_stale.format(user_id=resolver),
|
||||
thread_ts=ts,
|
||||
)
|
||||
|
||||
|
|
|
|||
77
nephthys/tasks/close_stale.py
Normal file
77
nephthys/tasks/close_stale.py
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import asyncio
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
from datetime import timezone
|
||||
|
||||
from slack_sdk.errors import SlackApiError
|
||||
|
||||
from nephthys.actions.resolve import resolve
|
||||
from nephthys.utils.env import env
|
||||
from nephthys.utils.logging import send_heartbeat
|
||||
from prisma.enums import TicketStatus
|
||||
|
||||
|
||||
async def get_is_stale(ts: str) -> bool:
|
||||
try:
|
||||
replies = await env.slack_client.conversations_replies(
|
||||
channel=env.slack_help_channel, ts=ts, limit=1000
|
||||
)
|
||||
last_reply = (
|
||||
replies.get("messages", [])[-1] if replies.get("messages") else None
|
||||
)
|
||||
if not last_reply:
|
||||
logging.error("No replies found - this should never happen")
|
||||
await send_heartbeat(f"No replies found for ticket {ts}")
|
||||
return False
|
||||
return (
|
||||
datetime.now(tz=timezone.utc)
|
||||
- datetime.fromtimestamp(float(ts), tz=timezone.utc)
|
||||
) > timedelta(days=3)
|
||||
except SlackApiError as e:
|
||||
if e.response["error"] == "ratelimited":
|
||||
retry_after = int(e.response.headers.get("Retry-After", 1))
|
||||
logging.warning(
|
||||
f"Rate limited while fetching replies for ticket {ts}. Retrying after {retry_after} seconds."
|
||||
)
|
||||
await asyncio.sleep(retry_after)
|
||||
return await get_is_stale(ts)
|
||||
else:
|
||||
logging.error(
|
||||
f"Error fetching replies for ticket {ts}: {e.response['error']}"
|
||||
)
|
||||
await send_heartbeat(
|
||||
f"Error fetching replies for ticket {ts}: {e.response['error']}"
|
||||
)
|
||||
return False
|
||||
|
||||
|
||||
async def close_stale_tickets():
|
||||
"""
|
||||
Closes tickets that have been open for more than 7 days.
|
||||
This task is intended to be run periodically.
|
||||
"""
|
||||
|
||||
logging.info("Closing stale tickets...")
|
||||
await send_heartbeat("Closing stale tickets...")
|
||||
|
||||
try:
|
||||
tickets = await env.db.ticket.find_many(
|
||||
where={"NOT": [{"status": TicketStatus.CLOSED}]},
|
||||
include={
|
||||
"openedBy": True,
|
||||
},
|
||||
)
|
||||
stale_tickets = [
|
||||
ticket for ticket in tickets if await get_is_stale(ticket.msgTs)
|
||||
]
|
||||
|
||||
for ticket in stale_tickets:
|
||||
await resolve(ticket.msgTs, ticket.openedBy.slackId, env.slack_client) # type: ignore (this is valid - see include above)
|
||||
|
||||
await send_heartbeat(f"Closed {len(stale_tickets)} stale tickets.")
|
||||
|
||||
logging.info(f"Closed {len(stale_tickets)} stale tickets.")
|
||||
except Exception as e:
|
||||
logging.error(f"Error closing stale tickets: {e}")
|
||||
await send_heartbeat(f"Error closing stale tickets: {e}")
|
||||
|
|
@ -59,6 +59,11 @@ class Transcript(BaseModel):
|
|||
default="", description="Message when ticket is resolved"
|
||||
)
|
||||
|
||||
ticket_resolve_stale: str = Field(
|
||||
default="",
|
||||
description="Message when ticket is resolved due to being stale",
|
||||
)
|
||||
|
||||
thread_broadcast_delete: str = Field(
|
||||
default="hey! please keep your messages *all in one thread* to make it easier to read! i've gone ahead and removed that message from the channel for ya :D",
|
||||
)
|
||||
|
|
@ -116,6 +121,10 @@ if your question has been answered, please hit the button below to mark it as re
|
|||
self.ticket_resolve = f"""oh, oh! it looks like this post has been marked as resolved by <@{{user_id}}>! if you have any more questions, please make a new post in <#{self.help_channel}> and someone'll be happy to help you out! not me though, i'm just a silly racoon ^-^
|
||||
"""
|
||||
|
||||
if not self.ticket_resolve_stale:
|
||||
self.ticket_resolve_stale = f""":rac_nooo: it looks like this post is a bit old! if you still need help, please make a new post in <#{self.help_channel}> and someone'll be happy to help you out! ^~^
|
||||
"""
|
||||
|
||||
if not self.home_unknown_user_text:
|
||||
self.home_unknown_user_text = f"heyyyy, heidi here! it looks like i'm not allowed to show ya this. sorry! if you think this is a mistake, please reach out to <@{self.program_owner}> and she'll lmk what to do!"
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue