nephthys/nephthys/__main__.py
Obay M. Rashad 367dd5a2a1
AI-powered tickets categorization and a daily fulfillment reminder for open tickets (#153)
* Add ai-based ticket categorization and you can add tags in the bot homepage

* made the CategoryTag model and refactored the code to support it

* Implemented the fulfillment reminder to send all open tickets in the past 24h for amber to check them :)

* removed the ability to manage categories from the UI/fixed stuff

* Fix type error

* removed question tags

* Re-add question tags to DB schema

This is only because we don't have migrations rn so we can't actually delete stuff from the DB

---------

Co-authored-by: MMK21Hub <50421330+MMK21Hub@users.noreply.github.com>
2026-02-10 23:30:22 +00:00

107 lines
3.2 KiB
Python

import asyncio
import contextlib
import logging
from datetime import datetime
import uvicorn
from aiohttp import ClientSession
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.fulfillment_reminder import send_fulfillment_reminder
from nephthys.tasks.update_helpers import update_helpers
from nephthys.utils.delete_thread import process_queue
from nephthys.utils.env import env
from nephthys.utils.logging import parse_level_name
from nephthys.utils.logging import send_heartbeat
from nephthys.utils.logging import setup_otel_logging
load_dotenv()
try:
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
except ImportError:
pass
logging.basicConfig(level=logging.NOTSET)
stderr_logger = logging.StreamHandler()
stderr_logger.setLevel(parse_level_name(env.log_level_stderr))
stderr_logger.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
logging.getLogger().handlers = [stderr_logger]
if env.otel_logs_url:
setup_otel_logging()
@contextlib.asynccontextmanager
async def main(_app: Starlette):
await send_heartbeat(":neodog_nom_verified: Bot is online!")
async with ClientSession() as session:
env.session = session
await env.db.connect()
scheduler = AsyncIOScheduler(timezone="Europe/London")
if env.daily_summary:
scheduler.add_job(send_daily_stats, "cron", hour=0, minute=0)
scheduler.add_job(
send_fulfillment_reminder,
"cron",
hour=14,
minute=0,
timezone="Europe/London",
)
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())
await update_helpers()
handler = None
if env.slack_app_token:
if env.environment == "production":
logging.warning(
"You are currently running Socket mode in production. This is NOT RECOMMENDED - you should set up a proper HTTP server with a request URL."
)
from slack_bolt.adapter.socket_mode.async_handler import (
AsyncSocketModeHandler,
)
from nephthys.utils.slack import app as slack_app
handler = AsyncSocketModeHandler(slack_app, env.slack_app_token)
logging.info("Starting Socket Mode handler")
await handler.connect_async()
logging.info(f"Starting Uvicorn on port {env.port}")
yield
scheduler.shutdown()
delete_msg_task.cancel()
if handler:
logging.info("Stopping Socket Mode handler")
await handler.close_async()
def start():
uvicorn.run(
"nephthys.utils.starlette:app",
host="0.0.0.0",
port=env.port,
log_level="info" if env.environment != "production" else "warning",
reload=env.environment == "development",
)
if __name__ == "__main__":
start()