44"""
55
66import discord
7- import requests
8- from bs4 import BeautifulSoup
97from discord import app_commands
108from discord .ext import commands
119
1412import os
1513import shutil
1614from urllib .parse import urlparse
15+ import re
1716
1817from .base_cog import BaseCog
1918from ..utils .helpers import (
@@ -33,117 +32,6 @@ def __init__(self, bot: commands.Bot):
3332 super ().__init__ (bot )
3433 self .logger .info ("Admin cog loaded" )
3534
36- async def _fetch_url_content (self , url : str ) -> str :
37- """Fetch and clean content from a URL."""
38- # Validate URL format
39- if not url .startswith (("http://" , "https://" )):
40- url = "https://" + url
41-
42- # Fetch the webpage
43- headers = {
44- "User-Agent" : (
45- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
46- "(KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
47- )
48- }
49- response = requests .get (url , headers = headers , timeout = 10 )
50- response .raise_for_status ()
51-
52- # Parse HTML content
53- soup = BeautifulSoup (response .content , "html.parser" )
54-
55- # Remove script and style elements
56- for script in soup (["script" , "style" ]):
57- script .decompose ()
58-
59- # Get text content and clean it
60- text = soup .get_text ()
61- return clean_webpage_text (text )
62-
63- @commands .command (name = "fetchurl" )
64- @commands .has_permissions (administrator = True )
65- async def fetchurl_prefix (self , ctx : commands .Context , url : str ) -> None :
66- """Prefix command to fetch text content from a URL."""
67- try :
68- # Send initial response
69- await ctx .send ("🔄 Fetching content from URL..." )
70-
71- # Fetch and process content
72- text = await self ._fetch_url_content (url )
73-
74- if not text .strip ():
75- await self .send_error (
76- ctx ,
77- "❌ No Content Found" ,
78- "No readable text content was found on the provided URL." ,
79- )
80- return
81-
82- # Create embed with the content
83- embed = create_embed (
84- title = f"📄 Content from { url } " ,
85- description = f"```\n { text } \n ```" ,
86- color = discord .Color .blue (),
87- footer = f"Fetched from { url } " ,
88- )
89-
90- await ctx .send (embed = embed )
91-
92- except requests .exceptions .RequestException as e :
93- await self .send_error (
94- ctx , "❌ Fetch Error" , f"Failed to fetch content from the URL: { str (e )} "
95- )
96- except (discord .DiscordException , OSError ) as e :
97- self .logger .error ("Error in fetchurl command: %s" , e )
98- await self .send_error (
99- ctx , "❌ Unexpected Error" , f"An unexpected error occurred: { str (e )} "
100- )
101-
102- @app_commands .command (
103- name = "fetchurl" , description = "Fetch and display text content from a URL"
104- )
105- @app_commands .describe (url = "The URL to fetch text content from" )
106- @app_commands .checks .has_permissions (administrator = True )
107- async def fetchurl (self , interaction : discord .Interaction , url : str ) -> None :
108- """Slash command to fetch text content from a URL."""
109- await interaction .response .defer ()
110-
111- try :
112- # Fetch and process content
113- text = await self ._fetch_url_content (url )
114-
115- if not text .strip ():
116- await self .send_interaction_error (
117- interaction ,
118- "❌ No Content Found" ,
119- "No readable text content was found on the provided URL." ,
120- )
121- return
122-
123- # Create embed with the content
124- embed = create_embed (
125- title = f"📄 Content from { url } " ,
126- description = f"```\n { text } \n ```" ,
127- color = discord .Color .blue (),
128- footer = f"Fetched from { url } " ,
129- )
130-
131- await interaction .followup .send (embed = embed )
132-
133- except requests .exceptions .RequestException as e :
134- await self .send_interaction_error (
135- interaction ,
136- "❌ Fetch Error" ,
137- f"Failed to fetch content from the URL: { str (e )} " ,
138- )
139- except (discord .DiscordException , OSError ) as e :
140- self .logger .error ("Error in fetchurl command: %s" , e )
141- await self .send_interaction_error (
142- interaction ,
143- "❌ Unexpected Error" ,
144- f"An unexpected error occurred: { str (e )} " ,
145- )
146-
14735 @app_commands .command (
14836 name = "synccommands" , description = "Manually sync slash commands"
14937 )
@@ -201,6 +89,10 @@ async def synccommands_prefix(self, ctx: commands.Context) -> None:
20189 async def applytemplate_prefix (
20290 self , ctx : commands .Context , url : str , folder : str = None , branch : str = "main"
20391 ) -> None :
92+ # Sanitize URL: only allow github.com/*
93+ if not re .match (r"^https?://github\.com/[^/]+/[^/]+" , url ):
94+ await ctx .send ("❌ Only direct github.com repository URLs are supported." )
95+ return
20496 self .logger .info (
20597 f"[applytemplate_prefix] User: { ctx .author } , URL: { url } , folder: { folder } , branch: { branch } "
20698 )
@@ -236,6 +128,10 @@ async def applytemplate(
236128 folder : str = None ,
237129 branch : str = "main" ,
238130 ) -> None :
131+ # Sanitize URL: only allow github.com/*
132+ if not re .match (r"^https?://github\.com/[^/]+/[^/]+" , url ):
133+ await interaction .response .send_message ("❌ Only direct github.com repository URLs are supported." , ephemeral = True )
134+ return
239135 self .logger .info (
240136 f"[applytemplate_slash] User: { interaction .user } , URL: { url } , folder: { folder } , branch: { branch } "
241137 )
0 commit comments