initial commit
This commit is contained in:
128
main.py
Normal file
128
main.py
Normal file
@@ -0,0 +1,128 @@
|
||||
import discord
|
||||
import json
|
||||
import re
|
||||
import os
|
||||
from urllib.parse import urlparse, parse_qs, urlencode, urlunparse
|
||||
from discord import app_commands
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
def load_json(filename):
|
||||
try:
|
||||
with open(filename, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
except FileNotFoundError:
|
||||
return {}
|
||||
|
||||
|
||||
def save_json(data, filename):
|
||||
with open(filename, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, indent=4)
|
||||
|
||||
|
||||
rules = load_json("url_rules.json")
|
||||
server_settings = load_json("server_settings.json")
|
||||
|
||||
intents = discord.Intents.default()
|
||||
intents.message_content = True
|
||||
client = discord.Client(intents=intents)
|
||||
tree = app_commands.CommandTree(client)
|
||||
|
||||
|
||||
def clean_url(url):
|
||||
parsed_url = urlparse(url)
|
||||
providers = [p for p in rules["providers"].items() if p[0] != "globalRules"] + [
|
||||
("globalRules", rules["providers"].get("globalRules", {}))
|
||||
]
|
||||
|
||||
for _, data in providers:
|
||||
if re.match(data.get("urlPattern", ""), url):
|
||||
query_params = parse_qs(parsed_url.query, keep_blank_values=True)
|
||||
filtered_params = {
|
||||
k: v
|
||||
for k, v in query_params.items()
|
||||
if not any(re.fullmatch(rule, k) for rule in data.get("rules", []))
|
||||
}
|
||||
cleaned_query = urlencode(filtered_params, doseq=True)
|
||||
return (
|
||||
urlunparse((
|
||||
parsed_url.scheme,
|
||||
parsed_url.netloc,
|
||||
parsed_url.path,
|
||||
parsed_url.params,
|
||||
cleaned_query,
|
||||
parsed_url.fragment,
|
||||
))
|
||||
if cleaned_query != parsed_url.query
|
||||
else None
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
@client.event
|
||||
async def on_ready():
|
||||
await tree.sync()
|
||||
|
||||
|
||||
@client.event
|
||||
async def on_message(message):
|
||||
if message.author == client.user or server_settings.get(
|
||||
str(message.guild.id), {}
|
||||
).get("disabled", False):
|
||||
return
|
||||
|
||||
for word in message.content.split():
|
||||
if word.startswith(("http://", "https://")) and (cleaned := clean_url(word)):
|
||||
await message.channel.send(f"Cleaned link: {cleaned}")
|
||||
break
|
||||
|
||||
|
||||
@tree.command(
|
||||
name="toggle",
|
||||
description="Toggle automatic link cleaning for this server (requires Manage Messages permission).",
|
||||
)
|
||||
async def toggle(interaction: discord.Interaction):
|
||||
if not interaction.user.guild_permissions.manage_messages:
|
||||
await interaction.response.send_message(
|
||||
"You need 'Manage Messages' permission to use this command.", ephemeral=True
|
||||
)
|
||||
return
|
||||
|
||||
guild_id = str(interaction.guild.id)
|
||||
server_settings[guild_id] = {
|
||||
"disabled": not server_settings.get(guild_id, {}).get("disabled", False)
|
||||
}
|
||||
save_json(server_settings, "server_settings.json")
|
||||
await interaction.response.send_message(
|
||||
f"Link cleaning {'disabled' if server_settings[guild_id]['disabled'] else 'enabled'}."
|
||||
)
|
||||
|
||||
|
||||
@tree.command(
|
||||
name="bomb", description="Cleans the first link found in the last 20 messages."
|
||||
)
|
||||
async def bomb(interaction: discord.Interaction):
|
||||
async for msg in interaction.channel.history(limit=20):
|
||||
for word in msg.content.split():
|
||||
if word.startswith(("http://", "https://")) and (
|
||||
cleaned := clean_url(word)
|
||||
):
|
||||
await interaction.response.send_message(f"Cleaned link: {cleaned}")
|
||||
return
|
||||
await interaction.response.send_message("No links found.")
|
||||
|
||||
|
||||
@tree.command(
|
||||
name="about",
|
||||
description="Explains the purpose of the bot and its privacy features.",
|
||||
)
|
||||
async def about(interaction: discord.Interaction):
|
||||
await interaction.response.send_message(
|
||||
"This bot removes tracking parameters from links to improve privacy. Use `/toggle` to enable/disable auto-cleaning, `/bomb` to clean a recent link manually, and `/about` for info."
|
||||
)
|
||||
|
||||
|
||||
TOKEN = os.getenv("DISCORD_BOT_TOKEN")
|
||||
client.run(TOKEN)
|
||||
Reference in New Issue
Block a user