-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
245 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import os, yaml, sys | ||
|
||
def get_config(file): | ||
with open(file, 'r') as yaml_file: | ||
config = yaml.safe_load(yaml_file) | ||
return config |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
# modules/dbFunctions.py | ||
|
||
import mysql.connector | ||
import yaml | ||
import logging | ||
|
||
|
||
def create_connection(): | ||
try: | ||
connection = mysql.connector.connect(**db_config) | ||
if connection.is_connected(): | ||
return connection | ||
except mysql.connector.Error as e: | ||
logging.error(f"Error connecting to the database: {e}") | ||
return None | ||
|
||
def create_user(information): | ||
try: | ||
connection = create_connection() | ||
if connection: | ||
cursor = connection.cursor() | ||
|
||
# Extract information from the input dictionary | ||
primary_email = information.get('primaryEmail', '') | ||
primary_discord = information.get('primaryDiscord', '') | ||
primary_discord_id = information.get('primaryDiscordId', '') | ||
payment_method = information.get('paymentMethod', '') | ||
payment_person = information.get('paymentPerson', '') | ||
paid_amount = information.get('paidAmount', '') | ||
server = information.get('server', '') | ||
is_4k = information.get('4k', '') | ||
status = "Active" | ||
start_date = information.get('startDate', '') | ||
join_date = start_date | ||
end_date = information.get('endDate', '') | ||
|
||
# SQL query to insert a new user into the database | ||
insert_query = """ | ||
INSERT INTO users (primaryEmail, primaryDiscord, primaryDiscordId, paymentMethod, paymentPerson, paidAmount, server, 4k, status, joinDate, startDate, endDate) | ||
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) | ||
""" | ||
cursor.execute(insert_query, (primary_email, primary_discord, primary_discord_id, payment_method, payment_person, paid_amount, server, is_4k, status, join_date, start_date, end_date)) | ||
|
||
# Commit the changes | ||
connection.commit() | ||
logging.info(f"Created new user with primary email: {primary_email}") | ||
except mysql.connector.Error as e: | ||
logging.error(f"Error creating user: {e}") | ||
finally: | ||
if connection.is_connected(): | ||
cursor.close() | ||
connection.close() | ||
|
||
|
||
def find_user(search_term): | ||
search_term = search_term.lower() | ||
columns = ['primaryEmail', 'secondaryEmail', 'primaryDiscord', 'secondaryDiscord', 'paymentPerson'] | ||
matching_rows_list = [] | ||
email_regex = r'^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}$' | ||
|
||
for column in columns: | ||
try: | ||
connection = create_connection() | ||
if connection: | ||
cursor = connection.cursor(dictionary=True) | ||
is_email_field = re.search(email_regex, column.lower()) | ||
if is_email_field: | ||
query = f"SELECT * FROM users WHERE LOWER({column}) LIKE %s AND {column} REGEXP %s" | ||
cursor.execute(query, ('%' + search_term + '%', email_regex)) | ||
else: | ||
query = f"SELECT * FROM users WHERE LOWER({column}) LIKE %s" | ||
cursor.execute(query, ('%' + search_term + '%',)) | ||
matching_rows = cursor.fetchall() | ||
for row in matching_rows: | ||
if row not in matching_rows_list: | ||
matching_rows_list.append(row) | ||
except mysql.connector.Error as e: | ||
logging.error(f"Error searching for users: {e}") | ||
finally: | ||
if connection.is_connected(): | ||
cursor.close() | ||
connection.close() | ||
|
||
return matching_rows_list | ||
|
||
|
||
def update_database(user_id, field, value): | ||
try: | ||
connection = create_connection() | ||
if connection: | ||
cursor = connection.cursor() | ||
|
||
# SQL query to update the specified field for the given user ID | ||
update_query = f"UPDATE users SET {field} = %s WHERE id = %s" | ||
cursor.execute(update_query, (value, user_id)) | ||
|
||
# Commit the changes | ||
connection.commit() | ||
logging.info(f"Updated {field} for user ID {user_id} to {value}") | ||
except mysql.connector.Error as e: | ||
logging.error(f"Error updating database: {e}") | ||
finally: | ||
if connection.is_connected(): | ||
cursor.close() | ||
connection.close() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import discord | ||
import logging | ||
from discord import app_commands, Embed | ||
from discord.ext import commands | ||
from discord.ui import Select, View, Button | ||
|
||
|
||
async def add_role(user_id, role_name): | ||
guild_id = int(config['discord']['guildId']) | ||
|
||
try: | ||
guild = bot.get_guild(guild_id) | ||
if not guild: | ||
logging.error(f"Guild with ID {guild_id} not found.") | ||
return # Exit early if guild is not found | ||
|
||
user = await guild.fetch_member(user_id) | ||
if not user: | ||
logging.error(f"Member with ID {user_id} not found in the guild.") | ||
return # Exit early if user is not found | ||
|
||
role = discord.utils.get(guild.roles, name=role_name) | ||
if not role: | ||
logging.error(f"Role '{role_name}' not found in guild '{guild.name}'.") | ||
return # Exit early if role is not found | ||
|
||
logging.info(f"Assigning role '{role_name}' to user ID {user_id}") | ||
await user.add_roles(role) | ||
logging.info(f"Added role '{role_name}' to user {user.name} ({user.id})") | ||
|
||
except discord.Forbidden: | ||
logging.error(f"Bot doesn't have permission to add roles.") | ||
except discord.HTTPException as e: | ||
logging.error(f"HTTP error occurred while adding role: {e}") | ||
|
||
|
||
async def send_discord_message(to_user, subject, body): | ||
user = await bot.fetch_user(to_user) | ||
embed = Embed(title=f"**{subject}**", description=body, color=discord.Colour.blue()) | ||
try: | ||
await user.send(embed=embed) | ||
except discord.errors.Forbidden as e: | ||
logging.warning(f"Failed to send message to {user.name}#{user.discriminator}: {e}") | ||
except Exception as e: | ||
logging.error(f"An unexpected error occurred for {user.name}: {e}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import logging | ||
from email.mime.multipart import MIMEMultipart | ||
from email.mime.text import MIMEText | ||
import smtplib | ||
from modules import configFunctions | ||
|
||
|
||
|
||
def send_email(config_location, subject, body, to_emails): | ||
config = configFunctions.get_config(config_location) | ||
email_config = config.get('email', {}) | ||
smtp_server = email_config.get('smtpServer', '') | ||
smtp_port = email_config.get('smtpPort', 587) | ||
smtp_username = email_config.get('smtpUsername', '') | ||
smtp_password = email_config.get('smtpPassword', '') | ||
|
||
if not smtp_server or not smtp_username or not smtp_password: | ||
raise ValueError("Email configuration is incomplete. Please check your config file.") | ||
|
||
msg = MIMEMultipart() | ||
msg['From'] = smtp_username | ||
msg['To'] = to_emails | ||
msg['Subject'] = subject | ||
msg.attach(MIMEText(body, 'plain')) | ||
|
||
with smtplib.SMTP(smtp_server, smtp_port) as server: | ||
server.starttls() | ||
server.login(smtp_username, smtp_password) | ||
server.sendmail(smtp_username, to_emails, msg.as_string()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import math | ||
from modules import configFunctions | ||
|
||
|
||
def calculate_term_length(server, amount, is_4k): | ||
config = configFunctions.get_config(config_location) | ||
plex_config = config.get(f"PLEX-{server}", {}) | ||
pricing_section = plex_config.get('4k' if is_4k == 'Yes' else '1080p', {}) | ||
|
||
one_month_price = pricing_section.get('1Month', 0) | ||
three_month_price = pricing_section.get('3Month', 0) | ||
six_month_price = pricing_section.get('6Month', 0) | ||
twelve_month_price = pricing_section.get('12Month', 0) | ||
|
||
# Check if the amount matches exactly any known subscription length | ||
if amount == twelve_month_price: | ||
return 12 | ||
elif amount == six_month_price: | ||
return 6 | ||
elif amount == three_month_price: | ||
return 3 | ||
elif amount == one_month_price: | ||
return 1 | ||
|
||
# Check if the amount covers multiple years | ||
if amount > twelve_month_price: | ||
years_paid_for = amount / twelve_month_price | ||
if years_paid_for.is_integer(): | ||
return int(years_paid_for * 12) # Convert years to months | ||
|
||
# Mixed payment scenario: Iteratively calculate possible month combinations | ||
term_length = 0 | ||
remaining_amount = amount | ||
|
||
# Check for the maximum number of full 12-month subscriptions first | ||
while remaining_amount >= twelve_month_price: | ||
term_length += 12 | ||
remaining_amount -= twelve_month_price | ||
|
||
# Check for the maximum number of full 6-month subscriptions | ||
while remaining_amount >= six_month_price: | ||
term_length += 6 | ||
remaining_amount -= six_month_price | ||
|
||
# Check for the maximum number of full 3-month subscriptions | ||
while remaining_amount >= three_month_price: | ||
term_length += 3 | ||
remaining_amount -= three_month_price | ||
|
||
# Check for the maximum number of full 1-month subscriptions | ||
while remaining_amount >= one_month_price: | ||
term_length += 1 | ||
remaining_amount -= one_month_price | ||
|
||
# Handle small overpayments by checking if the remaining amount is negligible | ||
if remaining_amount < one_month_price: | ||
return term_length | ||
|
||
# If the remaining amount is still significant, then the payment does not exactly match any subscription plan | ||
return 0 |