Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/app/core/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ async def get_current_user(authorization: str = Header(None)) -> UUID:
try:
supabase = get_supabase_client()
# Verify the token and get user
user_response = supabase.auth.get_user(token)
user_response = await supabase.auth.get_user(token)

if not user_response or not user_response.user:
raise HTTPException(
Expand Down
6 changes: 5 additions & 1 deletion backend/integrations/discord/cogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ def __init__(self, bot: DiscordBot, queue_manager: AsyncQueueManager):

def cog_load(self):
"""Called when the cog is loaded"""
# Start the cleanup task - it will wait for the bot to be ready via before_loop
self.cleanup_expired_tokens.start()

def cog_unload(self):
self.cleanup_expired_tokens.cancel()
if self.cleanup_expired_tokens.is_running():
self.cleanup_expired_tokens.cancel()

@tasks.loop(minutes=5)
async def cleanup_expired_tokens(self):
Expand All @@ -47,7 +49,9 @@ async def cleanup_expired_tokens(self):
@cleanup_expired_tokens.before_loop
async def before_cleanup(self):
"""Wait until the bot is ready before starting cleanup"""
print("--> Waiting for bot to be ready before starting cleanup task...")
await self.bot.wait_until_ready()
print("--> Bot is ready, starting cleanup task...")

@app_commands.command(name="reset", description="Reset your DevRel thread and memory.")
async def reset_thread(self, interaction: discord.Interaction):
Expand Down
2 changes: 2 additions & 0 deletions backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from app.database.weaviate.client import get_weaviate_client
from integrations.discord.bot import DiscordBot
from discord.ext import commands
from routes import router as legacy_router
# DevRel commands are now loaded dynamically (commented out below)
# from integrations.discord.cogs import DevRelCommands

Expand Down Expand Up @@ -124,6 +125,7 @@ async def favicon():
return Response(status_code=204)

api.include_router(api_router)
api.include_router(legacy_router, prefix="/api", tags=["Legacy"])


if __name__ == "__main__":
Expand Down
92 changes: 92 additions & 0 deletions backend/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from app.core.events.base import BaseEvent
from app.core.handler.handler_registry import HandlerRegistry
from pydantic import BaseModel
from app.core.config import settings
import httpx

router = APIRouter()

Expand Down Expand Up @@ -35,6 +37,96 @@ def register_event_handlers():
event_bus.register_handler(EventType.PR_COMMENTED, sample_handler, PlatformType.GITHUB)
event_bus.register_handler(EventType.PR_MERGED, sample_handler, PlatformType.GITHUB)

@router.post("/repo-stats")
async def get_repo_stats(request: RepoRequest):
"""
Get repository statistics from GitHub
"""
try:
# Parse repo URL to extract owner and repo name
repo_url = request.repo_url.strip()

# Handle SSH format ([email protected]:owner/repo.git)
if repo_url.startswith("git@"):
# Split on ':' to get the path part
if ":" in repo_url:
path = repo_url.split(":", 1)[1]
else:
raise HTTPException(status_code=400, detail="Invalid GitHub repository URL")
else:
# Ensure scheme is present
if not repo_url.startswith(("http://", "https://")):
repo_url = "https://" + repo_url

# Extract path from URL
try:
# Parse URL to get path component
if "github.com/" in repo_url:
path = repo_url.split("github.com/", 1)[1]
else:
raise HTTPException(status_code=400, detail="Invalid GitHub repository URL")
except (IndexError, ValueError) as e:
raise HTTPException(status_code=400, detail="Invalid GitHub repository URL") from e

# Strip leading/trailing slashes and .git suffix
path = path.strip("/").removesuffix(".git")

# Split into segments and validate
segments = path.split("/")
if len(segments) < 2:
raise HTTPException(status_code=400, detail="Invalid GitHub repository URL")

owner, repo = segments[0], segments[1]
# Validate GitHub token is configured
if not settings.github_token:
raise HTTPException(
status_code=500,
detail="GitHub token not configured in environment variables. Please set GITHUB_TOKEN."
)
# Fetch repository stats from GitHub API
headers = {
"Authorization": f"token {settings.github_token}",
"Accept": "application/vnd.github.v3+json"
}

async with httpx.AsyncClient() as client:
response = await client.get(
f"https://api.github.com/repos/{owner}/{repo}",
headers=headers,
timeout=10.0
)

if response.status_code != 200:
logging.error(f"GitHub API error: {response.status_code} - {response.text}")
raise HTTPException(
status_code=response.status_code,
detail=f"GitHub API returned status {response.status_code}"
)

repo_data = response.json()

return {
"name": repo_data.get("name"),
"full_name": repo_data.get("full_name"),
"description": repo_data.get("description"),
"stars": repo_data.get("stargazers_count", 0),
"forks": repo_data.get("forks_count", 0),
"open_issues": repo_data.get("open_issues_count", 0),
"language": repo_data.get("language"),
"created_at": repo_data.get("created_at"),
"updated_at": repo_data.get("updated_at"),
"url": repo_data.get("html_url"),
"owner": {
"login": repo_data.get("owner", {}).get("login"),
"avatar_url": repo_data.get("owner", {}).get("avatar_url"),
}
}
except HTTPException:
raise
except Exception as e:
logging.exception("Error fetching repo stats")
raise HTTPException(status_code=500, detail="Internal server error") from e

@router.post("/github/webhook")
async def github_webhook(request: Request):
payload = await request.json()
Expand Down
6 changes: 3 additions & 3 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading