1 Commits

Author SHA1 Message Date
pixeebot[bot]
ec3974fa67 Sandbox URL Creation 2025-01-03 03:14:07 +00:00
5 changed files with 24 additions and 150 deletions

View File

@@ -1,61 +0,0 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow checks out code, performs a Codacy security scan
# and integrates the results with the
# GitHub Advanced Security code scanning feature. For more information on
# the Codacy security scan action usage and parameters, see
# https://github.com/codacy/codacy-analysis-cli-action.
# For more information on Codacy Analysis CLI in general, see
# https://github.com/codacy/codacy-analysis-cli.
name: Codacy Security Scan
on:
push:
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
schedule:
- cron: '36 1 * * 4'
permissions:
contents: read
jobs:
codacy-security-scan:
permissions:
contents: read # for actions/checkout to fetch code
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status
name: Codacy Security Scan
runs-on: ubuntu-latest
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v4
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@d840f886c4bd4edc059706d09c6a1586111c540b
with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
verbose: true
output: results.sarif
format: sarif
# Adjust severity of non-security issues
gh-code-scanning-compat: true
# Force 0 exit code to allow SARIF file generation
# This will handover control about PR rejection to the GitHub side
max-allowed-issues: 2147483647
# Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif

View File

@@ -1,65 +0,0 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# Frogbot Scan and Fix does the following:
# Automatically creates pull requests with fixes for vulnerable project dependencies.
# Uses JFrog Xray to scan the project.
# Read more about Frogbot here - https://docs.jfrog-applications.jfrog.io/jfrog-applications/frogbot
# Some projects require creating a frogbot-config.yml file. Read more about it here - https://docs.jfrog-applications.jfrog.io/jfrog-applications/frogbot/setup-frogbot/frogbot-configuration
name: "Frogbot Scan and Fix"
on:
push:
branches: [ "main" ]
permissions:
contents: write
pull-requests: write
security-events: write
jobs:
create-fix-pull-requests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: jfrog/frogbot@5d9c42c30f1169d8be4ba5510b40e75ffcbbc2a9 # v2.21.2
env:
# [Mandatory if the two conditions below are met]
# 1. The project uses npm, yarn 2, NuGet or .NET to download its dependencies
# 2. The `installCommand` variable isn't set in your frogbot-config.yml file.
#
# The command that installs the project dependencies (e.g "npm i", "nuget restore" or "dotnet restore")
# JF_INSTALL_DEPS_CMD: ""
# [Mandatory]
# JFrog platform URL
JF_URL: ${{ secrets.JF_URL }}
# [Mandatory if JF_USER and JF_PASSWORD are not provided]
# JFrog access token with 'read' permissions on Xray service
JF_ACCESS_TOKEN: ${{ secrets.JF_ACCESS_TOKEN }}
# [Mandatory if JF_ACCESS_TOKEN is not provided]
# JFrog username with 'read' permissions for Xray. Must be provided with JF_PASSWORD
# JF_USER: ${{ secrets.JF_USER }}
# [Mandatory if JF_ACCESS_TOKEN is not provided]
# JFrog password. Must be provided with JF_USER
# JF_PASSWORD: ${{ secrets.JF_PASSWORD }}
# [Mandatory]
# The GitHub token automatically generated for the job
JF_GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# [Optional]
# If the machine that runs Frogbot has no access to the internat, set the name of a remote repository
# in Artifactory, which proxies https://releases.jfrog.io/artifactory
# The 'frogbot' executable and other tools it needs will be downloaded through this repository.
# JF_RELEASES_REPO: ""
# [Optional]
# Frogbot will download the project dependencies, if they're not cached locally. To download the
# dependencies from a virtual repository in Artifactory, set the name of of the repository. There's no
# need to set this value, if it is set in the frogbot-config.yml file.
# JF_DEPS_REPO: ""

View File

@@ -37,7 +37,7 @@ async def birthday_context_menu(interaction: discord.Interaction, member: discor
birthday_role = interaction.guild.get_role(birthday_role_id) birthday_role = interaction.guild.get_role(birthday_role_id)
if not birthday_role: if not birthday_role:
logger.error("Birthday role not found in the guild") logger.error(f"Birthday role {birthday_role_id} not found in guild {interaction.guild.id}")
return await interaction.followup.send("The birthday role doesn't exist anymore. Please ask an admin to set it again.", ephemeral=True) return await interaction.followup.send("The birthday role doesn't exist anymore. Please ask an admin to set it again.", ephemeral=True)
# Assign the role, ignoring hierarchy # Assign the role, ignoring hierarchy
@@ -45,10 +45,10 @@ async def birthday_context_menu(interaction: discord.Interaction, member: discor
await member.add_roles(birthday_role, reason="Birthday role") await member.add_roles(birthday_role, reason="Birthday role")
logger.info(f"Birthday role assigned to {member.id} in guild {interaction.guild.id}") logger.info(f"Birthday role assigned to {member.id} in guild {interaction.guild.id}")
except discord.Forbidden: except discord.Forbidden:
logger.error("Failed to assign birthday role: Insufficient permissions") logger.error(f"Failed to assign birthday role to {member.id} in guild {interaction.guild.id}: Insufficient permissions")
return await interaction.followup.send("I don't have permission to assign that role.", ephemeral=True) return await interaction.followup.send("I don't have permission to assign that role.", ephemeral=True)
except discord.HTTPException as e: except discord.HTTPException as e:
logger.error(f"Failed to assign birthday role: {str(e)}") logger.error(f"Failed to assign birthday role to {member.id} in guild {interaction.guild.id}: {str(e)}")
return await interaction.followup.send("Failed to assign the birthday role due to a Discord error.", ephemeral=True) return await interaction.followup.send("Failed to assign the birthday role due to a Discord error.", ephemeral=True)
# Generate birthday message with random cakes (or pie) # Generate birthday message with random cakes (or pie)
@@ -63,7 +63,7 @@ async def birthday_context_menu(interaction: discord.Interaction, member: discor
if birthday_channel_id: if birthday_channel_id:
channel = interaction.client.get_channel(birthday_channel_id) channel = interaction.client.get_channel(birthday_channel_id)
if not channel: if not channel:
logger.warning("Birthday channel not found in the guild") logger.warning(f"Birthday channel {birthday_channel_id} not found in guild {interaction.guild.id}")
channel = interaction.channel channel = interaction.channel
else: else:
channel = interaction.channel channel = interaction.channel
@@ -76,7 +76,7 @@ async def birthday_context_menu(interaction: discord.Interaction, member: discor
try: try:
tz = ZoneInfo(timezone) tz = ZoneInfo(timezone)
except ZoneInfoNotFoundError: except ZoneInfoNotFoundError:
logger.warning("Invalid timezone for the guild, defaulting to UTC") logger.warning(f"Invalid timezone {timezone} for guild {interaction.guild.id}, defaulting to UTC")
await interaction.followup.send("Warning: Invalid timezone set. Defaulting to UTC.", ephemeral=True) await interaction.followup.send("Warning: Invalid timezone set. Defaulting to UTC.", ephemeral=True)
tz = ZoneInfo("UTC") tz = ZoneInfo("UTC")
@@ -196,12 +196,12 @@ class Birthday(commands.Cog):
birthday_role_id = await self.config.guild(ctx.guild).birthday_role() birthday_role_id = await self.config.guild(ctx.guild).birthday_role()
if not birthday_role_id: if not birthday_role_id:
logger.error("Birthday role not set for the guild") logger.error(f"Birthday role not set for guild {ctx.guild.id}")
return await ctx.send("The birthday role hasn't been set.", ephemeral=True) return await ctx.send("The birthday role hasn't been set.", ephemeral=True)
birthday_role = ctx.guild.get_role(birthday_role_id) birthday_role = ctx.guild.get_role(birthday_role_id)
if not birthday_role: if not birthday_role:
logger.error("Birthday role not found in the guild") logger.error(f"Birthday role {birthday_role_id} not found in guild {ctx.guild.id}")
return await ctx.send("The birthday role doesn't exist anymore.", ephemeral=True) return await ctx.send("The birthday role doesn't exist anymore.", ephemeral=True)
if birthday_role not in member.roles: if birthday_role not in member.roles:
@@ -209,12 +209,12 @@ class Birthday(commands.Cog):
try: try:
await member.remove_roles(birthday_role, reason="Birthday role manually removed") await member.remove_roles(birthday_role, reason="Birthday role manually removed")
logger.info(f"Birthday role manually removed from member {member.id}") logger.info(f"Birthday role manually removed from {member.id} in guild {ctx.guild.id}")
except discord.Forbidden: except discord.Forbidden:
logger.error(f"Failed to remove birthday role from member {member.id}: Insufficient permissions") logger.error(f"Failed to remove birthday role from {member.id} in guild {ctx.guild.id}: Insufficient permissions")
return await ctx.send("I don't have permission to remove that role.", ephemeral=True) return await ctx.send("I don't have permission to remove that role.", ephemeral=True)
except discord.HTTPException as e: except discord.HTTPException as e:
logger.error(f"Failed to remove birthday role from member {member.id} due to a Discord error: {str(e)}") logger.error(f"Failed to remove birthday role from {member.id} in guild {ctx.guild.id}: {str(e)}")
return await ctx.send("Failed to remove the birthday role due to a Discord error.", ephemeral=True) return await ctx.send("Failed to remove the birthday role due to a Discord error.", ephemeral=True)
# Remove scheduled task if it exists # Remove scheduled task if it exists
@@ -226,7 +226,7 @@ class Birthday(commands.Cog):
await ctx.send(f"Birthday role removed from {member.display_name}!", ephemeral=True) await ctx.send(f"Birthday role removed from {member.display_name}!", ephemeral=True)
except Exception as e: except Exception as e:
logger.error("Unexpected error in remove_birthday command", exc_info=True) logger.error(f"Unexpected error in remove_birthday command: {str(e)}", exc_info=True)
await ctx.send(f"An error occurred while removing the birthday role: {str(e)}", ephemeral=True) await ctx.send(f"An error occurred while removing the birthday role: {str(e)}", ephemeral=True)
async def daily_cleanup(self): async def daily_cleanup(self):
@@ -348,12 +348,12 @@ class Birthday(commands.Cog):
birthday_role_id = await self.config.guild(ctx.guild).birthday_role() birthday_role_id = await self.config.guild(ctx.guild).birthday_role()
if not birthday_role_id: if not birthday_role_id:
logger.error("Birthday role not set for the guild") logger.error(f"Birthday role not set for guild {ctx.guild.id}")
return await ctx.send("The birthday role hasn't been set. An admin needs to set it using `/setrole`.", ephemeral=True) return await ctx.send("The birthday role hasn't been set. An admin needs to set it using `/setrole`.", ephemeral=True)
birthday_role = ctx.guild.get_role(birthday_role_id) birthday_role = ctx.guild.get_role(birthday_role_id)
if not birthday_role: if not birthday_role:
logger.error("Birthday role not found in the guild") logger.error(f"Birthday role {birthday_role_id} not found in guild {ctx.guild.id}")
return await ctx.send("The birthday role doesn't exist anymore. Please ask an admin to set it again.", ephemeral=True) return await ctx.send("The birthday role doesn't exist anymore. Please ask an admin to set it again.", ephemeral=True)
# Assign the role, ignoring hierarchy # Assign the role, ignoring hierarchy
@@ -361,10 +361,10 @@ class Birthday(commands.Cog):
await member.add_roles(birthday_role, reason="Birthday role") await member.add_roles(birthday_role, reason="Birthday role")
logger.info(f"Birthday role assigned to {member.id} in guild {ctx.guild.id}") logger.info(f"Birthday role assigned to {member.id} in guild {ctx.guild.id}")
except discord.Forbidden: except discord.Forbidden:
logger.error("Failed to assign birthday role: Insufficient permissions") logger.error(f"Failed to assign birthday role to {member.id} in guild {ctx.guild.id}: Insufficient permissions")
return await ctx.send("I don't have permission to assign that role.", ephemeral=True) return await ctx.send("I don't have permission to assign that role.", ephemeral=True)
except discord.HTTPException as e: except discord.HTTPException as e:
logger.error(f"Failed to assign birthday role: {str(e)}") logger.error(f"Failed to assign birthday role to {member.id} in guild {ctx.guild.id}: {str(e)}")
return await ctx.send("Failed to assign the birthday role due to a Discord error.", ephemeral=True) return await ctx.send("Failed to assign the birthday role due to a Discord error.", ephemeral=True)
# Generate birthday message with random cakes (or pie) # Generate birthday message with random cakes (or pie)
@@ -379,7 +379,7 @@ class Birthday(commands.Cog):
if birthday_channel_id: if birthday_channel_id:
channel = self.bot.get_channel(birthday_channel_id) channel = self.bot.get_channel(birthday_channel_id)
if not channel: # If the set channel doesn't exist anymore if not channel: # If the set channel doesn't exist anymore
logger.warning("Birthday channel not found in the guild") logger.warning(f"Birthday channel {birthday_channel_id} not found in guild {ctx.guild.id}")
channel = ctx.channel channel = ctx.channel
else: else:
channel = ctx.channel channel = ctx.channel
@@ -392,7 +392,7 @@ class Birthday(commands.Cog):
try: try:
tz = ZoneInfo(timezone) tz = ZoneInfo(timezone)
except ZoneInfoNotFoundError: except ZoneInfoNotFoundError:
logger.warning("Invalid timezone for the guild, defaulting to UTC") logger.warning(f"Invalid timezone {timezone} for guild {ctx.guild.id}, defaulting to UTC")
await ctx.send("Warning: Invalid timezone set. Defaulting to UTC.", ephemeral=True) await ctx.send("Warning: Invalid timezone set. Defaulting to UTC.", ephemeral=True)
tz = ZoneInfo("UTC") tz = ZoneInfo("UTC")
@@ -401,7 +401,7 @@ class Birthday(commands.Cog):
await self.schedule_birthday_role_removal(ctx.guild, member, birthday_role, midnight) await self.schedule_birthday_role_removal(ctx.guild, member, birthday_role, midnight)
except Exception as e: except Exception as e:
logger.error(f"Unexpected error in birthday command", exc_info=True) logger.error(f"Unexpected error in birthday command: {str(e)}", exc_info=True)
await ctx.send(f"An error occurred: {str(e)}", ephemeral=True) await ctx.send(f"An error occurred: {str(e)}", ephemeral=True)
@commands.hybrid_command(name="bdaycheck") @commands.hybrid_command(name="bdaycheck")

View File

@@ -3,7 +3,6 @@
import os import os
import logging import logging
import shutil import shutil
import requests
import tarfile import tarfile
import zipfile import zipfile
import subprocess import subprocess
@@ -19,6 +18,7 @@ import lzma
# try: # try:
# Try relative imports first # Try relative imports first
from exceptions import DownloadError from exceptions import DownloadError
from security import safe_requests
# except ImportError: # except ImportError:
# Fall back to absolute imports if relative imports fail # Fall back to absolute imports if relative imports fail
@@ -175,7 +175,7 @@ class FFmpegDownloader:
logger.info(f"Downloading FFmpeg from {url}") logger.info(f"Downloading FFmpeg from {url}")
try: try:
response = requests.get(url, stream=True, timeout=30) response = safe_requests.get(url, stream=True, timeout=30)
response.raise_for_status() response.raise_for_status()
total_size = int(response.headers.get("content-length", 0)) total_size = int(response.headers.get("content-length", 0))

View File

@@ -1,7 +1,7 @@
"""Constants for VideoProcessor""" """Constants for VideoProcessor"""
from typing import Dict, List, Union from typing import Dict, List, Union
from dataclasses import field, dataclass from dataclasses import dataclass
from enum import Enum from enum import Enum
class ReactionType(Enum): class ReactionType(Enum):
@@ -27,9 +27,9 @@ class ReactionEmojis:
@dataclass(frozen=True) @dataclass(frozen=True)
class ProgressEmojis: class ProgressEmojis:
"""Emoji sequences for progress indicators""" """Emoji sequences for progress indicators"""
NUMBERS: List[str] = field(default_factory=lambda: ('1', '2', '3', '4', '5')) NUMBERS: List[str] = ('1', '2', '3', '4', '5')
PROGRESS: List[str] = field(default_factory=lambda: ('', '🟨', '🟩')) PROGRESS: List[str] = ('', '🟨', '🟩')
DOWNLOAD: List[str] = field(default_factory=lambda: ('0', '2', '4', '6', '8', '🔟')) DOWNLOAD: List[str] = ('0', '2', '4', '6', '8', '🔟')
# Main reactions dictionary with type hints # Main reactions dictionary with type hints
REACTIONS: Dict[str, Union[str, List[str]]] = { REACTIONS: Dict[str, Union[str, List[str]]] = {