Implement Modrinth project tracking with commands to add, remove, and list projects. Introduce background task for update checking and enhance error handling. Update API usage for project and version retrieval.
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run
Some checks are pending
Run pre-commit / Run pre-commit (push) Waiting to run
This commit is contained in:
parent
4495e8cd63
commit
e64a1e2536
1 changed files with 123 additions and 35 deletions
|
@ -1,70 +1,158 @@
|
||||||
import discord
|
import discord
|
||||||
import aiohttp
|
import aiohttp
|
||||||
from datetime import timedelta
|
from datetime import datetime, timedelta
|
||||||
|
import asyncio
|
||||||
from redbot.core import commands, Config, checks
|
from redbot.core import commands, Config, checks
|
||||||
|
|
||||||
BASE_URL = "https://api.modrinth.com/v2/project/"
|
BASE_URL = "https://api.modrinth.com/v2"
|
||||||
|
|
||||||
class ModrinthTracker(commands.Cog):
|
class ModrinthTracker(commands.Cog):
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
self.config = Config.get_conf(self, identifier=1234567890, force_registration=True)
|
self.config = Config.get_conf(self, identifier=1234567890, force_registration=True)
|
||||||
self.config.register_guild(tracked_projects={})
|
self.config.register_guild(tracked_projects={})
|
||||||
|
self.session = None
|
||||||
|
self.bg_task = None
|
||||||
|
|
||||||
|
async def cog_load(self):
|
||||||
|
self.session = aiohttp.ClientSession()
|
||||||
|
self.bg_task = self.bot.loop.create_task(self.update_checker())
|
||||||
|
|
||||||
|
async def cog_unload(self):
|
||||||
|
if self.session:
|
||||||
|
await self.session.close()
|
||||||
|
if self.bg_task:
|
||||||
|
self.bg_task.cancel()
|
||||||
|
|
||||||
@commands.group()
|
@commands.group()
|
||||||
@checks.admin()
|
@checks.admin()
|
||||||
async def modrinth(self, ctx):
|
async def modrinth(self, ctx):
|
||||||
pass
|
"""Commands for tracking Modrinth projects"""
|
||||||
|
if ctx.invoked_subcommand is None:
|
||||||
|
await ctx.send_help()
|
||||||
|
|
||||||
@modrinth.command()
|
@modrinth.command()
|
||||||
async def add(self, ctx, project_id: str, channel: discord.TextChannel):
|
async def add(self, ctx, project_id: str, channel: discord.TextChannel):
|
||||||
tracked_projects = await self.config.guild(ctx.guild).tracked_projects()
|
"""Add a Modrinth project to track
|
||||||
if project_id in tracked_projects:
|
|
||||||
await ctx.send("This project is already being tracked.")
|
|
||||||
return
|
|
||||||
|
|
||||||
tracked_projects[project_id] = {"channel": channel.id, "latest_version": None}
|
Arguments:
|
||||||
await self.config.guild(ctx.guild).tracked_projects.set(tracked_projects)
|
project_id: The Modrinth project ID or slug
|
||||||
await ctx.send(f"Tracking project `{project_id}` in {channel.mention}.")
|
channel: The channel to send updates to
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Verify the project exists and get its info
|
||||||
|
async with self.session.get(f"{BASE_URL}/project/{project_id}") as response:
|
||||||
|
if response.status != 200:
|
||||||
|
await ctx.send(f"Error: Project `{project_id}` not found on Modrinth.")
|
||||||
|
return
|
||||||
|
project_data = await response.json()
|
||||||
|
|
||||||
|
# Get the latest version
|
||||||
|
async with self.session.get(f"{BASE_URL}/project/{project_id}/version") as response:
|
||||||
|
if response.status != 200:
|
||||||
|
await ctx.send("Error: Could not fetch version information.")
|
||||||
|
return
|
||||||
|
versions = await response.json()
|
||||||
|
latest_version = versions[0] if versions else None
|
||||||
|
|
||||||
|
tracked_projects = await self.config.guild(ctx.guild).tracked_projects()
|
||||||
|
if project_id in tracked_projects:
|
||||||
|
await ctx.send("This project is already being tracked.")
|
||||||
|
return
|
||||||
|
|
||||||
|
tracked_projects[project_id] = {
|
||||||
|
"channel": channel.id,
|
||||||
|
"latest_version": latest_version["id"] if latest_version else None,
|
||||||
|
"name": project_data["title"]
|
||||||
|
}
|
||||||
|
await self.config.guild(ctx.guild).tracked_projects.set(tracked_projects)
|
||||||
|
await ctx.send(f"Now tracking {project_data['title']} (`{project_id}`) in {channel.mention}.")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
await ctx.send(f"An error occurred while adding the project: {str(e)}")
|
||||||
|
|
||||||
@modrinth.command()
|
@modrinth.command()
|
||||||
async def remove(self, ctx, project_id: str):
|
async def remove(self, ctx, project_id: str):
|
||||||
|
"""Remove a tracked Modrinth project
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
project_id: The Modrinth project ID or slug to stop tracking
|
||||||
|
"""
|
||||||
tracked_projects = await self.config.guild(ctx.guild).tracked_projects()
|
tracked_projects = await self.config.guild(ctx.guild).tracked_projects()
|
||||||
if project_id not in tracked_projects:
|
if project_id not in tracked_projects:
|
||||||
await ctx.send("This project is not being tracked.")
|
await ctx.send("This project is not being tracked.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
project_name = tracked_projects[project_id].get("name", project_id)
|
||||||
del tracked_projects[project_id]
|
del tracked_projects[project_id]
|
||||||
await self.config.guild(ctx.guild).tracked_projects.set(tracked_projects)
|
await self.config.guild(ctx.guild).tracked_projects.set(tracked_projects)
|
||||||
await ctx.send(f"Stopped tracking project `{project_id}`.")
|
await ctx.send(f"Stopped tracking {project_name} (`{project_id}`).")
|
||||||
|
|
||||||
async def check_updates(self):
|
@modrinth.command()
|
||||||
async with aiohttp.ClientSession() as session:
|
async def list(self, ctx):
|
||||||
tracked_projects = await self.config.guild(ctx.guild).tracked_projects()
|
"""List all tracked Modrinth projects"""
|
||||||
for project_id, data in tracked_projects.items():
|
tracked_projects = await self.config.guild(ctx.guild).tracked_projects()
|
||||||
url = BASE_URL + project_id
|
if not tracked_projects:
|
||||||
async with session.get(url) as response:
|
await ctx.send("No projects are currently being tracked.")
|
||||||
if response.status != 200:
|
return
|
||||||
continue
|
|
||||||
|
|
||||||
project_data = await response.json()
|
embed = discord.Embed(title="Tracked Modrinth Projects", color=discord.Color.blue())
|
||||||
latest_version = project_data.get("latest_version")
|
for project_id, data in tracked_projects.items():
|
||||||
if not latest_version or latest_version == data.get("latest_version"):
|
channel = self.bot.get_channel(data["channel"])
|
||||||
continue
|
channel_mention = channel.mention if channel else "Unknown channel"
|
||||||
|
embed.add_field(
|
||||||
|
name=data.get("name", project_id),
|
||||||
|
value=f"ID: `{project_id}`\nChannel: {channel_mention}",
|
||||||
|
inline=False
|
||||||
|
)
|
||||||
|
await ctx.send(embed=embed)
|
||||||
|
|
||||||
channel = self.bot.get_channel(data["channel"])
|
async def update_checker(self):
|
||||||
if channel:
|
await self.bot.wait_until_ready()
|
||||||
await channel.send(f"New update for `{project_data['title']}`: `{latest_version}`\n{project_data['id']}")
|
|
||||||
|
|
||||||
tracked_projects[project_id]["latest_version"] = latest_version
|
|
||||||
|
|
||||||
await self.config.guild(ctx.guild).tracked_projects.set(tracked_projects)
|
|
||||||
|
|
||||||
@commands.Cog.listener()
|
|
||||||
async def on_ready(self):
|
|
||||||
while True:
|
while True:
|
||||||
await self.check_updates()
|
try:
|
||||||
await discord.utils.sleep_until(discord.utils.utcnow().replace(second=0, microsecond=0) + timedelta(minutes=5))
|
all_guilds = await self.config.all_guilds()
|
||||||
|
for guild_id, guild_data in all_guilds.items():
|
||||||
|
guild = self.bot.get_guild(guild_id)
|
||||||
|
if not guild:
|
||||||
|
continue
|
||||||
|
|
||||||
|
tracked_projects = guild_data.get("tracked_projects", {})
|
||||||
|
for project_id, data in tracked_projects.items():
|
||||||
|
try:
|
||||||
|
async with self.session.get(f"{BASE_URL}/project/{project_id}/version") as response:
|
||||||
|
if response.status != 200:
|
||||||
|
continue
|
||||||
|
|
||||||
|
versions = await response.json()
|
||||||
|
if not versions:
|
||||||
|
continue
|
||||||
|
|
||||||
|
latest_version = versions[0]
|
||||||
|
if latest_version["id"] == data.get("latest_version"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
channel = self.bot.get_channel(data["channel"])
|
||||||
|
if channel:
|
||||||
|
embed = discord.Embed(
|
||||||
|
title=f"New Update for {data.get('name', project_id)}!",
|
||||||
|
description=f"Version: {latest_version.get('version_number', 'Unknown')}\n\n{latest_version.get('changelog', 'No changelog provided')}",
|
||||||
|
url=f"https://modrinth.com/project/{project_id}",
|
||||||
|
color=discord.Color.green(),
|
||||||
|
timestamp=datetime.now()
|
||||||
|
)
|
||||||
|
await channel.send(embed=embed)
|
||||||
|
|
||||||
|
tracked_projects[project_id]["latest_version"] = latest_version["id"]
|
||||||
|
await self.config.guild(guild).tracked_projects.set(tracked_projects)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
continue
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
await asyncio.sleep(300) # Check every 5 minutes
|
||||||
|
|
||||||
async def setup(bot):
|
async def setup(bot):
|
||||||
await bot.add_cog(ModrinthTracker(bot))
|
await bot.add_cog(ModrinthTracker(bot))
|
||||||
|
|
Loading…
Add table
Reference in a new issue