adding debt app
This commit is contained in:
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Run Bot",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"program": "main.py",
|
||||
"console": "integratedTerminal",
|
||||
"envFile": "${workspaceFolder}/.env"
|
||||
}
|
||||
]
|
||||
}
|
||||
+7
-7
@@ -1,8 +1,8 @@
|
||||
import discord
|
||||
from core.bot import bot, user_repo
|
||||
# import discord
|
||||
# from core.bot import bot, user_repo
|
||||
|
||||
@bot.command(name='exp')
|
||||
async def show_exp(ctx):
|
||||
user_id = ctx.author.id
|
||||
exp = await user_repo.get_exp(user_id)
|
||||
await ctx.send(f"{ctx.author.mention} has {exp} experience points!")
|
||||
# @bot.command(name='exp')
|
||||
# async def show_exp(ctx):
|
||||
# user_id = ctx.author.id
|
||||
# exp = await user_repo.get_exp(user_id)
|
||||
# await ctx.send(f"{ctx.author.mention} has {exp} experience points!")
|
||||
+63
-100
@@ -1,131 +1,94 @@
|
||||
import discord
|
||||
from datetime import datetime
|
||||
from core.bot import bot, server_repo, channel_repo, channel_app_repo, home_debt_repo
|
||||
from models import DiscordServer, DiscordChannel, DiscordChannelApp
|
||||
from typing import Any
|
||||
from core.bot import bot, server_repo, channel_repo, home_debt_repo
|
||||
|
||||
@bot.tree.command(name='set-home-debt', description='Set channel to home debt')
|
||||
async def set_home_debt(interaction: discord.Interaction, channel: discord.TextChannel):
|
||||
try:
|
||||
# Get or create server
|
||||
# Kiểm tra xem người dùng có quyền admin không
|
||||
if not interaction.user.guild_permissions.administrator:
|
||||
await interaction.response.send_message("Bạn cần có quyền Administrator để sử dụng lệnh này!", ephemeral=True)
|
||||
return
|
||||
|
||||
# Ensure server is in database
|
||||
server = await server_repo.get(str(interaction.guild_id))
|
||||
if not server:
|
||||
server = DiscordServer(
|
||||
id=str(interaction.guild_id),
|
||||
name=interaction.guild.name,
|
||||
created_at=datetime.now(),
|
||||
updated_at=datetime.now()
|
||||
)
|
||||
server = await server_repo.create(server)
|
||||
await interaction.response.send_message("Server chưa được khởi tạo trong database! Vui lòng sử dụng lệnh /init_server trước.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Get or create channel
|
||||
discord_channel = await channel_repo.get(str(channel.id))
|
||||
# Ensure channel was registered in database
|
||||
discord_channel = await channel_repo.get_channel(channel.id)
|
||||
if not discord_channel:
|
||||
discord_channel = DiscordChannel(
|
||||
id=str(channel.id),
|
||||
server_id=str(interaction.guild_id),
|
||||
name=channel.name,
|
||||
type='text',
|
||||
created_at=datetime.now(),
|
||||
updated_at=datetime.now()
|
||||
)
|
||||
discord_channel = await channel_repo.create(discord_channel)
|
||||
|
||||
# Create or update home debt app
|
||||
apps = await channel_app_repo.get_by_channel(str(channel.id))
|
||||
home_debt_app = next((app for app in apps if app.app_type == 'home_debt'), None)
|
||||
|
||||
if home_debt_app:
|
||||
home_debt_app.config = {'enabled': True}
|
||||
await channel_app_repo.update(home_debt_app)
|
||||
await channel_repo.create_channel(interaction.guild_id, channel.id, 'home_debt')
|
||||
else:
|
||||
home_debt_app = DiscordChannelApp(
|
||||
id=f"{channel.id}_home_debt",
|
||||
channel_id=str(channel.id),
|
||||
app_type='home_debt',
|
||||
config={'enabled': True},
|
||||
created_at=datetime.now(),
|
||||
updated_at=datetime.now()
|
||||
)
|
||||
await channel_app_repo.create(home_debt_app)
|
||||
await channel_repo.update_channel(channel.id, 'home_debt')
|
||||
|
||||
await interaction.response.send_message(f"Home debt app has been set up for {channel.mention}")
|
||||
await interaction.response.send_message(f"home_debt app đã được cấu hình cho {channel.mention}")
|
||||
except Exception as e:
|
||||
await interaction.response.send_message(f"Error setting up home debt app: {str(e)}")
|
||||
await interaction.response.send_message(f"Lỗi khi cấu hình home_debt app: {str(e)}")
|
||||
|
||||
@bot.tree.command(name="add_member", description="Thêm thành viên mới vào nhà")
|
||||
async def add_member(interaction: discord.Interaction, member: discord.Member):
|
||||
"""Thêm thành viên mới vào nhà"""
|
||||
try:
|
||||
# Kiểm tra xem thành viên đã tồn tại chưa
|
||||
existing_member = await home_debt_repo.get_member(member.id)
|
||||
if existing_member:
|
||||
await interaction.response.send_message(f"Thành viên {member.name} đã tồn tại trong hệ thống!", ephemeral=True)
|
||||
# Decorator to check if the channel is registered and configured for home_debt app
|
||||
def check_channel_home_debt():
|
||||
def decorator(func):
|
||||
async def wrapper(interaction: discord.Interaction, *args, **kwargs):
|
||||
channel = await channel_repo.get_channel(interaction.channel_id)
|
||||
if not channel:
|
||||
await interaction.response.send_message("Channel chưa được đăng ký!", ephemeral=True)
|
||||
return
|
||||
if channel.app != 'home_debt':
|
||||
await interaction.response.send_message("Lệnh này chỉ có thể sử dụng trong channel đã được cấu hình cho home_debt app!", ephemeral=True)
|
||||
return
|
||||
await func(interaction, *args, **kwargs)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
# Thêm thành viên mới
|
||||
await home_debt_repo.add_member(member.id, member.name)
|
||||
await interaction.response.send_message(f"Đã thêm thành viên {member.name} vào hệ thống!", ephemeral=True)
|
||||
@bot.tree.command(name="home-debt-add", description="Thêm khoản chi tiêu mới")
|
||||
# @check_channel_home_debt()
|
||||
async def home_debt_add(interaction: discord.Interaction, amount: float, description: str):
|
||||
"""Vì home chỉ có 2 người nên sẽ tự động thêm khoản chi tiêu cho người còn lại"""
|
||||
try:
|
||||
# Get info other user from home_debt table
|
||||
other_user = await home_debt_repo.get_other(interaction.user.id)
|
||||
other_user.value += amount / 2
|
||||
await home_debt_repo.update_home_debt(other_user)
|
||||
await interaction.response.send_message(f"Đã thêm khoản chi tiêu: {description} - {amount / 2}đ cho {other_user.user_id}", ephemeral=False)
|
||||
except Exception as e:
|
||||
await interaction.response.send_message(f"Có lỗi xảy ra: {str(e)}", ephemeral=True)
|
||||
|
||||
@bot.tree.command(name="add_expense", description="Thêm khoản chi tiêu mới")
|
||||
async def add_expense(interaction: discord.Interaction, amount: float, description: str):
|
||||
"""Thêm khoản chi tiêu mới"""
|
||||
@bot.tree.command(name="home-debt-check", description="Kiểm tra số dư của bạn")
|
||||
async def home_debt_check(interaction: discord.Interaction):
|
||||
"""Kiểm tra số dư của mọi người"""
|
||||
try:
|
||||
# Kiểm tra xem người dùng có phải là thành viên không
|
||||
member = await home_debt_repo.get_member(interaction.user.id)
|
||||
if not member:
|
||||
await interaction.response.send_message("Bạn chưa được thêm vào hệ thống! Vui lòng sử dụng lệnh /add_member trước.", ephemeral=True)
|
||||
return
|
||||
|
||||
# Thêm khoản chi tiêu
|
||||
expense = await home_debt_repo.add_expense(amount, description, interaction.user.id)
|
||||
await interaction.response.send_message(f"Đã thêm khoản chi tiêu: {description} - {amount}đ", ephemeral=True)
|
||||
# Lấy số dư của mọi người
|
||||
home_debts = await home_debt_repo.get_all()
|
||||
await interaction.response.send_message(f"Số dư của mọi người: {home_debts}", ephemeral=True)
|
||||
except Exception as e:
|
||||
await interaction.response.send_message(f"Có lỗi xảy ra: {str(e)}", ephemeral=True)
|
||||
|
||||
@bot.tree.command(name="check_balance", description="Kiểm tra số dư của bạn")
|
||||
async def check_balance(interaction: discord.Interaction):
|
||||
"""Kiểm tra số dư của bạn"""
|
||||
@bot.tree.command(name="vay-debt", description="Vay nợ")
|
||||
async def vay_debt(interaction: discord.Interaction, amount: float, description: str):
|
||||
"""Vay nợ"""
|
||||
try:
|
||||
# Kiểm tra xem người dùng có phải là thành viên không
|
||||
member = await home_debt_repo.get_member(interaction.user.id)
|
||||
if not member:
|
||||
await interaction.response.send_message("Bạn chưa được thêm vào hệ thống! Vui lòng sử dụng lệnh /add_member trước.", ephemeral=True)
|
||||
return
|
||||
# Get info user from home_debt table
|
||||
user = await home_debt_repo.get(interaction.user.id)
|
||||
user.value += amount
|
||||
await home_debt_repo.update_home_debt(user)
|
||||
|
||||
# Lấy số dư
|
||||
balance = await home_debt_repo.get_balance(interaction.user.id)
|
||||
await interaction.response.send_message(f"Số dư của bạn: {balance}đ", ephemeral=True)
|
||||
# Send message to user
|
||||
await interaction.response.send_message(f"Đã vay nợ: {description} - {amount}đ cho {user.user_id}", ephemeral=False)
|
||||
except Exception as e:
|
||||
await interaction.response.send_message(f"Có lỗi xảy ra: {str(e)}", ephemeral=True)
|
||||
|
||||
@bot.tree.command(name="list_expenses", description="Xem danh sách chi tiêu")
|
||||
async def list_expenses(interaction: discord.Interaction):
|
||||
"""Xem danh sách chi tiêu"""
|
||||
@bot.tree.command(name="tra-debt", description="Trả nợ")
|
||||
async def tra_debt(interaction: discord.Interaction, amount: float):
|
||||
"""Trả nợ"""
|
||||
try:
|
||||
# Kiểm tra xem người dùng có phải là thành viên không
|
||||
member = await home_debt_repo.get_member(interaction.user.id)
|
||||
if not member:
|
||||
await interaction.response.send_message("Bạn chưa được thêm vào hệ thống! Vui lòng sử dụng lệnh /add_member trước.", ephemeral=True)
|
||||
return
|
||||
# Get info user from home_debt table
|
||||
user = await home_debt_repo.get(interaction.user.id)
|
||||
user.value -= amount
|
||||
await home_debt_repo.update_home_debt(user)
|
||||
|
||||
# Lấy danh sách chi tiêu
|
||||
expenses = await home_debt_repo.get_expenses()
|
||||
if not expenses:
|
||||
await interaction.response.send_message("Chưa có khoản chi tiêu nào!", ephemeral=True)
|
||||
return
|
||||
|
||||
# Tạo embed message
|
||||
embed = discord.Embed(title="Danh sách chi tiêu", color=discord.Color.blue())
|
||||
for expense in expenses:
|
||||
member = await home_debt_repo.get_member(expense.member_id)
|
||||
embed.add_field(
|
||||
name=f"{expense.description} - {expense.amount}đ",
|
||||
value=f"Người chi: {member.name}",
|
||||
inline=False
|
||||
)
|
||||
|
||||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||
# Send message to user
|
||||
await interaction.response.send_message(f"Đã trả nợ: {amount}đ cho {user.user_id}", ephemeral=False)
|
||||
except Exception as e:
|
||||
await interaction.response.send_message(f"Có lỗi xảy ra: {str(e)}", ephemeral=True)
|
||||
+11
-21
@@ -1,28 +1,18 @@
|
||||
import discord
|
||||
from datetime import datetime
|
||||
from core.bot import bot, server_repo, channel_repo, channel_app_repo
|
||||
from models import DiscordServer, DiscordChannel, DiscordChannelApp
|
||||
|
||||
@bot.tree.command(name='test', description='Test command')
|
||||
async def test(interaction: discord.Interaction):
|
||||
try:
|
||||
# Get server
|
||||
server = await server_repo.get(str(interaction.guild_id))
|
||||
if server:
|
||||
await interaction.response.send_message(f"Server: {server.name}")
|
||||
else:
|
||||
await interaction.response.send_message("Server not found")
|
||||
except Exception as e:
|
||||
await interaction.response.send_message(f"Error: {e}")
|
||||
from core.bot import bot, server_repo
|
||||
|
||||
@bot.tree.command(name='help', description='Show help')
|
||||
async def help(interaction: discord.Interaction):
|
||||
embed = discord.Embed(title="Help", description="Here is a list of commands you can use:")
|
||||
embed.add_field(name="!exp", value="Show your experience points", inline=True)
|
||||
embed.add_field(name="!test", value="Test command", inline=True)
|
||||
embed.add_field(name="!help", value="Show help", inline=True)
|
||||
embed.add_field(name="!set-home-debt", value="Set channel to home debt", inline=True)
|
||||
await interaction.response.send_message(embed=embed)
|
||||
"""Command để hiển thị danh sách các lệnh"""
|
||||
# Get all commands
|
||||
commands = bot.tree.get_commands()
|
||||
command_list = "\n".join([f"• {c.name}: {c.description}" for c in commands])
|
||||
|
||||
# Create embed with command list
|
||||
embed = discord.Embed(title="Help", description="Đây là danh sách các lệnh bạn có thể sử dụng:")
|
||||
embed.add_field(name="Danh sách lệnh", value=command_list, inline=False)
|
||||
await interaction.response.send_message(embed=embed, ephemeral=False)
|
||||
print(f"Đã gửi lệnh help cho {interaction.user.name}")
|
||||
|
||||
@bot.tree.command(name="init_server", description="Khởi tạo thông tin server trong database")
|
||||
async def init_server(interaction: discord.Interaction):
|
||||
|
||||
+2
-2
@@ -16,12 +16,12 @@ intents.guilds = True
|
||||
bot = commands.Bot(command_prefix='!', intents=intents)
|
||||
|
||||
# Initialize repositories
|
||||
from repositories import ServerRepository, ChannelRepository, ChannelAppRepository, UserRepository
|
||||
from repositories import ServerRepository, ChannelRepository, ChannelAppRepository, HomeDebtRepository
|
||||
|
||||
server_repo = ServerRepository()
|
||||
channel_repo = ChannelRepository()
|
||||
channel_app_repo = ChannelAppRepository()
|
||||
user_repo = UserRepository()
|
||||
home_debt_repo = HomeDebtRepository()
|
||||
|
||||
# Store user cooldowns
|
||||
from typing import Dict, Set
|
||||
|
||||
+5
-55
@@ -1,58 +1,8 @@
|
||||
from datetime import datetime
|
||||
from .bot import bot, user_repo, user_cooldowns, active_voice_users, CHAT_EXP_POINTS, CHAT_COOLDOWN, VOICE_EXP_POINTS_PER_MINUTE
|
||||
from core.bot import bot
|
||||
from core.tasks import sync_commands
|
||||
|
||||
@bot.event
|
||||
async def on_ready():
|
||||
print(f'{bot.user} has connected to Discord!')
|
||||
from .tasks import update_voice_exp
|
||||
update_voice_exp.start()
|
||||
try:
|
||||
synced = await bot.tree.sync()
|
||||
print(f"Synced {len(synced)} command(s)")
|
||||
except Exception as e:
|
||||
print(f"Failed to sync commands: {e}")
|
||||
|
||||
@bot.event
|
||||
async def on_message(message):
|
||||
if message.author.bot:
|
||||
return
|
||||
|
||||
# Handle chat experience points
|
||||
user_id = message.author.id
|
||||
current_time = datetime.now()
|
||||
|
||||
if user_id not in user_cooldowns or (current_time - user_cooldowns[user_id]).total_seconds() >= CHAT_COOLDOWN:
|
||||
current_exp = await user_repo.get_exp(user_id)
|
||||
new_exp = current_exp + CHAT_EXP_POINTS
|
||||
await user_repo.update_exp(user_id, new_exp)
|
||||
user_cooldowns[user_id] = current_time
|
||||
print(f"Added {CHAT_EXP_POINTS} exp points to {message.author.name}. Total: {new_exp}")
|
||||
|
||||
await bot.process_commands(message)
|
||||
|
||||
@bot.event
|
||||
async def on_voice_state_update(member, before, after):
|
||||
if member.bot:
|
||||
return
|
||||
|
||||
# User joined a voice channel
|
||||
if before.channel is None and after.channel is not None:
|
||||
current_time = datetime.now().isoformat()
|
||||
await user_repo.update_voice_time(member.id, current_time)
|
||||
active_voice_users.add(member.id)
|
||||
print(f"{member.name} joined voice channel {after.channel.name}")
|
||||
|
||||
# User left a voice channel
|
||||
elif before.channel is not None and after.channel is None:
|
||||
if member.id in active_voice_users:
|
||||
active_voice_users.remove(member.id)
|
||||
last_join_time = await user_repo.get_voice_time(member.id)
|
||||
if last_join_time:
|
||||
join_time = datetime.fromisoformat(last_join_time)
|
||||
time_spent = datetime.now() - join_time
|
||||
minutes = int(time_spent.total_seconds() / 60)
|
||||
exp_points = minutes * VOICE_EXP_POINTS_PER_MINUTE
|
||||
current_exp = await user_repo.get_exp(member.id)
|
||||
new_exp = current_exp + exp_points
|
||||
await user_repo.update_exp(member.id, new_exp)
|
||||
print(f"{member.name} spent {minutes} minutes in voice. Added {exp_points} exp points. Total: {new_exp}")
|
||||
print(f'{bot.user} đã tham gia vào server!')
|
||||
await sync_commands.start()
|
||||
print("Đã đồng bộ lệnh!")
|
||||
+19
-15
@@ -1,18 +1,22 @@
|
||||
from discord.ext import tasks
|
||||
from datetime import datetime
|
||||
from .bot import bot, user_repo, active_voice_users, VOICE_EXP_POINTS_PER_MINUTE
|
||||
from core.bot import bot
|
||||
|
||||
# @tasks.loop(minutes=1)
|
||||
# async def update_voice_exp():
|
||||
# current_time = datetime.now()
|
||||
# for user_id in list(active_voice_users):
|
||||
# last_join_time = await user_repo.get_voice_time(user_id)
|
||||
# if last_join_time:
|
||||
# join_time = datetime.fromisoformat(last_join_time)
|
||||
# time_spent = current_time - join_time
|
||||
# if time_spent.total_seconds() >= 60:
|
||||
# current_exp = await user_repo.get_exp(user_id)
|
||||
# new_exp = current_exp + VOICE_EXP_POINTS_PER_MINUTE
|
||||
# await user_repo.update_exp(user_id, new_exp)
|
||||
# await user_repo.update_voice_time(user_id, current_time.isoformat())
|
||||
# print(f"Thêm {VOICE_EXP_POINTS_PER_MINUTE} điểm kinh nghiệm cho user {user_id} cho thời gian voice")
|
||||
|
||||
@tasks.loop(minutes=1)
|
||||
async def update_voice_exp():
|
||||
current_time = datetime.now()
|
||||
for user_id in list(active_voice_users):
|
||||
last_join_time = await user_repo.get_voice_time(user_id)
|
||||
if last_join_time:
|
||||
join_time = datetime.fromisoformat(last_join_time)
|
||||
time_spent = current_time - join_time
|
||||
if time_spent.total_seconds() >= 60:
|
||||
current_exp = await user_repo.get_exp(user_id)
|
||||
new_exp = current_exp + VOICE_EXP_POINTS_PER_MINUTE
|
||||
await user_repo.update_exp(user_id, new_exp)
|
||||
await user_repo.update_voice_time(user_id, current_time.isoformat())
|
||||
print(f"Added {VOICE_EXP_POINTS_PER_MINUTE} exp points to user {user_id} for voice time")
|
||||
async def sync_commands():
|
||||
await bot.tree.sync()
|
||||
print("Đã đồng bộ lệnh!")
|
||||
@@ -1,35 +0,0 @@
|
||||
from supabase import create_client, Client
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from infra.db import PostgresConnection
|
||||
|
||||
load_dotenv()
|
||||
|
||||
class Database:
|
||||
def __init__(self):
|
||||
uri: str = os.getenv('SUPABASE_URI')
|
||||
if not uri:
|
||||
raise ValueError("SUPABASE_URI environment variable is not set")
|
||||
|
||||
# Parse URI to get URL and key
|
||||
# Format: postgresql://postgres:[YOUR-PASSWORD]@db.[YOUR-PROJECT-REF].supabase.co:5432/postgres
|
||||
parts = uri.split('@')
|
||||
if len(parts) != 2:
|
||||
raise ValueError("Invalid SUPABASE_URI format")
|
||||
|
||||
# Extract project reference from the host
|
||||
host = parts[1].split(':')[0]
|
||||
project_ref = host.split('.')[1]
|
||||
|
||||
# Construct Supabase URL and key
|
||||
url = f"https://{project_ref}.supabase.co"
|
||||
key = os.getenv('SUPABASE_KEY') # Still need the anon key for API access
|
||||
|
||||
if not key:
|
||||
raise ValueError("SUPABASE_KEY environment variable is not set")
|
||||
|
||||
self.supabase: Client = create_client(url, key)
|
||||
|
||||
class BaseRepository:
|
||||
def __init__(self):
|
||||
self.db = PostgresConnection()
|
||||
@@ -1,45 +0,0 @@
|
||||
from typing import Optional, List
|
||||
from .base import BaseRepository
|
||||
from models.channel import DiscordChannel
|
||||
|
||||
class ChannelRepository(BaseRepository):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.table = self.db.get_table('discord_channel')
|
||||
|
||||
async def get_channel(self, channel_id: int) -> Optional[DiscordChannel]:
|
||||
try:
|
||||
response = self.table.select('*').eq('channel_id', channel_id).execute()
|
||||
if response.data:
|
||||
return DiscordChannel(**response.data[0])
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Error getting channel: {e}")
|
||||
return None
|
||||
|
||||
async def get_channels_by_server(self, server_id: int) -> List[DiscordChannel]:
|
||||
try:
|
||||
response = self.table.select('*').eq('server_id', server_id).execute()
|
||||
return [DiscordChannel(**channel) for channel in response.data]
|
||||
except Exception as e:
|
||||
print(f"Error getting channels: {e}")
|
||||
return []
|
||||
|
||||
async def create_channel(self, channel_id: int, server_id: int, channel_name: str) -> Optional[DiscordChannel]:
|
||||
try:
|
||||
channel = DiscordChannel(channel_id=channel_id, server_id=server_id, channel_name=channel_name)
|
||||
response = self.table.insert(channel.dict()).execute()
|
||||
return DiscordChannel(**response.data[0])
|
||||
except Exception as e:
|
||||
print(f"Error creating channel: {e}")
|
||||
return None
|
||||
|
||||
async def update_channel(self, channel_id: int, channel_name: str) -> Optional[DiscordChannel]:
|
||||
try:
|
||||
response = self.table.update({'channel_name': channel_name}).eq('channel_id', channel_id).execute()
|
||||
if response.data:
|
||||
return DiscordChannel(**response.data[0])
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Error updating channel: {e}")
|
||||
return None
|
||||
@@ -1,43 +0,0 @@
|
||||
from typing import Optional, List
|
||||
from .base import BaseRepository
|
||||
from models.channel_app import DiscordChannelApp
|
||||
|
||||
class ChannelAppRepository(BaseRepository):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.table = self.db.get_table('discord_channel_app')
|
||||
|
||||
async def get_channel_app(self, channel_id: int, app_name: str) -> Optional[DiscordChannelApp]:
|
||||
try:
|
||||
response = self.table.select('*').eq('channel_id', channel_id).eq('app_name', app_name).execute()
|
||||
if response.data:
|
||||
return DiscordChannelApp(**response.data[0])
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Error getting channel app: {e}")
|
||||
return None
|
||||
|
||||
async def get_channel_apps(self, channel_id: int) -> List[DiscordChannelApp]:
|
||||
try:
|
||||
response = self.table.select('*').eq('channel_id', channel_id).execute()
|
||||
return [DiscordChannelApp(**app) for app in response.data]
|
||||
except Exception as e:
|
||||
print(f"Error getting channel apps: {e}")
|
||||
return []
|
||||
|
||||
async def create_channel_app(self, channel_id: int, app_name: str) -> Optional[DiscordChannelApp]:
|
||||
try:
|
||||
app = DiscordChannelApp(channel_id=channel_id, app_name=app_name)
|
||||
response = self.table.insert(app.dict()).execute()
|
||||
return DiscordChannelApp(**response.data[0])
|
||||
except Exception as e:
|
||||
print(f"Error creating channel app: {e}")
|
||||
return None
|
||||
|
||||
async def delete_channel_app(self, channel_id: int, app_name: str) -> bool:
|
||||
try:
|
||||
response = self.table.delete().eq('channel_id', channel_id).eq('app_name', app_name).execute()
|
||||
return len(response.data) > 0
|
||||
except Exception as e:
|
||||
print(f"Error deleting channel app: {e}")
|
||||
return False
|
||||
@@ -1,40 +0,0 @@
|
||||
from typing import Optional
|
||||
from .base import BaseRepository
|
||||
from models.server import DiscordServer
|
||||
|
||||
class ServerRepository(BaseRepository):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.table = self.db.get_table('discord_server')
|
||||
|
||||
async def get_server(self, server_id: int) -> Optional[DiscordServer]:
|
||||
"""Get Discord server by ID"""
|
||||
try:
|
||||
response = self.table.select('*').eq('server_id', server_id).execute()
|
||||
if response.data:
|
||||
return DiscordServer(**response.data[0])
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Error getting server: {e}")
|
||||
return None
|
||||
|
||||
async def create_server(self, server_id: int, server_name: str) -> Optional[DiscordServer]:
|
||||
"""Create new Discord server"""
|
||||
try:
|
||||
server = DiscordServer(server_id=server_id, server_name=server_name)
|
||||
response = self.table.insert(server.dict()).execute()
|
||||
return DiscordServer(**response.data[0])
|
||||
except Exception as e:
|
||||
print(f"Error creating server: {e}")
|
||||
return None
|
||||
|
||||
async def update_server(self, server_id: int, server_name: str) -> Optional[DiscordServer]:
|
||||
"""Update Discord server"""
|
||||
try:
|
||||
response = self.table.update({'server_name': server_name}).eq('server_id', server_id).execute()
|
||||
if response.data:
|
||||
return DiscordServer(**response.data[0])
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Error updating server: {e}")
|
||||
return None
|
||||
@@ -1,11 +1,11 @@
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from core.bot import bot
|
||||
from core import events, tasks
|
||||
from apps import experience, server
|
||||
from core.bot import bot
|
||||
from apps import home_debt, server
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
# Run the bot
|
||||
bot.run(os.getenv('DISCORD_TOKEN'))
|
||||
bot.run(os.getenv('BOT_TOKEN'))
|
||||
|
||||
+5
-4
@@ -1,5 +1,6 @@
|
||||
from .server import DiscordServer
|
||||
from .channel import DiscordChannel
|
||||
from .channel_app import DiscordChannelApp
|
||||
from models.server import DiscordServer
|
||||
from models.channel import DiscordChannel
|
||||
from models.channel_app import DiscordChannelApp
|
||||
from models.home_debt import DiscordHomeDebt
|
||||
|
||||
__all__ = ['DiscordServer', 'DiscordChannel', 'DiscordChannelApp']
|
||||
__all__ = ['DiscordServer', 'DiscordChannel', 'DiscordChannelApp', 'DiscordHomeDebt']
|
||||
@@ -1,12 +0,0 @@
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
@dataclass
|
||||
class DiscordDebtGroup:
|
||||
id: Optional[int]
|
||||
name: str
|
||||
description: str
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
members: List[DiscordHomeDebt]
|
||||
@@ -0,0 +1,26 @@
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
@dataclass
|
||||
class DiscordHomeDebt:
|
||||
id: Optional[int]
|
||||
user_id: int
|
||||
value: int
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
def __str__(self):
|
||||
return f"ID: {self.id}, User ID: {self.user_id}, Value: {self.value}, Created At: {self.created_at}, Updated At: {self.updated_at}"
|
||||
|
||||
def __repr__(self):
|
||||
return self.__str__()
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
"id": self.id,
|
||||
"user_id": self.user_id,
|
||||
"value": self.value,
|
||||
"created_at": self.created_at,
|
||||
"updated_at": self.updated_at
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
from .server import ServerRepository
|
||||
from .channel import ChannelRepository
|
||||
from .channel_app import ChannelAppRepository
|
||||
from .user import UserRepository
|
||||
from .home_debt import HomeDebtRepository
|
||||
|
||||
__all__ = ['ServerRepository', 'ChannelRepository', 'ChannelAppRepository', 'UserRepository']
|
||||
__all__ = ['ServerRepository', 'ChannelRepository', 'ChannelAppRepository', 'HomeDebtRepository']
|
||||
+44
-90
@@ -1,103 +1,57 @@
|
||||
from typing import List, Optional
|
||||
from datetime import datetime
|
||||
from models.debt_group import HomeMember, Expense, ExpenseShare
|
||||
from models.home_debt import DiscordHomeDebt
|
||||
from infra.db import postgres
|
||||
|
||||
class HomeDebtRepository:
|
||||
_instance = None
|
||||
_initialized = False
|
||||
|
||||
def __new__(cls):
|
||||
if cls._instance is None:
|
||||
cls._instance = super(HomeDebtRepository, cls).__new__(cls)
|
||||
return cls._instance
|
||||
|
||||
def __init__(self):
|
||||
if not HomeDebtRepository._initialized:
|
||||
self.db = postgres.get_table('home_members')
|
||||
HomeDebtRepository._initialized = True
|
||||
self.table = postgres.get_table('discord_home_debt')
|
||||
|
||||
async def add_member(self, discord_user_id: int, name: str) -> HomeMember:
|
||||
"""Thêm thành viên mới vào nhà"""
|
||||
data = await self.db.table("home_members").insert({
|
||||
"discord_user_id": discord_user_id,
|
||||
"name": name
|
||||
}).execute()
|
||||
return HomeMember(**data.data[0])
|
||||
|
||||
async def get_member(self, discord_user_id: int) -> Optional[HomeMember]:
|
||||
"""Lấy thông tin thành viên theo discord_user_id"""
|
||||
data = await self.db.table("home_members").select("*").eq("discord_user_id", discord_user_id).execute()
|
||||
if not data.data:
|
||||
async def get(self, discord_user_id: int) -> Optional[DiscordHomeDebt]:
|
||||
"""Lấy thông tin thành viên"""
|
||||
try:
|
||||
response = self.table.select('*').eq('user_id', discord_user_id).execute()
|
||||
if response.data:
|
||||
return DiscordHomeDebt(**response.data[0])
|
||||
return None
|
||||
return HomeMember(**data.data[0])
|
||||
|
||||
async def get_all_members(self) -> List[HomeMember]:
|
||||
"""Lấy danh sách tất cả thành viên"""
|
||||
data = await self.db.table("home_members").select("*").execute()
|
||||
return [HomeMember(**member) for member in data.data]
|
||||
|
||||
async def add_expense(self, amount: float, description: str, paid_by: int) -> Expense:
|
||||
"""Thêm khoản chi tiêu mới"""
|
||||
# Tạo expense
|
||||
expense_data = await self.db.table("expenses").insert({
|
||||
"amount": amount,
|
||||
"description": description,
|
||||
"paid_by": paid_by
|
||||
}).execute()
|
||||
expense = Expense(**expense_data.data[0])
|
||||
|
||||
# Lấy danh sách thành viên
|
||||
members = await self.get_all_members()
|
||||
share_amount = amount / len(members)
|
||||
|
||||
# Tạo expense shares cho từng thành viên
|
||||
for member in members:
|
||||
await self.db.table("expense_shares").insert({
|
||||
"expense_id": expense.id,
|
||||
"member_id": member.discord_user_id,
|
||||
"share_amount": share_amount,
|
||||
"is_paid": member.discord_user_id == paid_by # Người trả tiền được đánh dấu là đã trả
|
||||
}).execute()
|
||||
|
||||
return expense
|
||||
|
||||
async def get_expense(self, expense_id: int) -> Optional[Expense]:
|
||||
"""Lấy thông tin khoản chi tiêu"""
|
||||
data = await self.db.table("expenses").select("*").eq("id", expense_id).execute()
|
||||
if not data.data:
|
||||
except Exception as e:
|
||||
print(f"Error getting user: {e}")
|
||||
return None
|
||||
return Expense(**data.data[0])
|
||||
|
||||
async def get_all_expenses(self) -> List[Expense]:
|
||||
"""Lấy danh sách tất cả khoản chi tiêu"""
|
||||
data = await self.db.table("expenses").select("*").order("created_at", desc=True).execute()
|
||||
return [Expense(**expense) for expense in data.data]
|
||||
|
||||
async def get_expense_shares(self, expense_id: int) -> List[ExpenseShare]:
|
||||
"""Lấy danh sách chia tiền của một khoản chi tiêu"""
|
||||
data = await self.db.table("expense_shares").select("*").eq("expense_id", expense_id).execute()
|
||||
return [ExpenseShare(**share) for share in data.data]
|
||||
|
||||
async def mark_share_as_paid(self, share_id: int) -> Optional[ExpenseShare]:
|
||||
"""Đánh dấu một phần chia tiền đã được trả"""
|
||||
data = await self.db.table("expense_shares").update({
|
||||
"is_paid": True
|
||||
}).eq("id", share_id).execute()
|
||||
if not data.data:
|
||||
async def get_other(self, discord_user_id: int) -> Optional[DiscordHomeDebt]:
|
||||
"""Lấy thông tin thành viên khác"""
|
||||
try:
|
||||
response = self.table.select('*').neq('user_id', discord_user_id).execute()
|
||||
if response.data:
|
||||
return DiscordHomeDebt(**response.data[0])
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Error getting other member: {e}")
|
||||
return None
|
||||
return ExpenseShare(**data.data[0])
|
||||
|
||||
async def get_member_balance(self, discord_user_id: int) -> float:
|
||||
"""Tính số dư của một thành viên (số tiền phải trả - số tiền đã trả)"""
|
||||
# Lấy tất cả expense shares của thành viên
|
||||
data = await self.db.table("expense_shares").select("*").eq("member_id", discord_user_id).execute()
|
||||
shares = [ExpenseShare(**share) for share in data.data]
|
||||
async def create_home_debt(self, user_id: int, value: int) -> Optional[DiscordHomeDebt]:
|
||||
"""Tạo mới khoản nợ"""
|
||||
try:
|
||||
home_debt = DiscordHomeDebt(user_id=user_id, value=value)
|
||||
response = self.table.insert(home_debt.dict(exclude_none=True)).execute()
|
||||
return DiscordHomeDebt(**response.data[0])
|
||||
except Exception as e:
|
||||
print(f"Error creating home debt: {e}")
|
||||
return None
|
||||
|
||||
# Tính tổng số tiền phải trả
|
||||
total_owed = sum(share.share_amount for share in shares)
|
||||
async def update_home_debt(self, home_debt: DiscordHomeDebt) -> Optional[DiscordHomeDebt]:
|
||||
"""Cập nhật khoản nợ"""
|
||||
try:
|
||||
response = self.table.update(home_debt.dict(exclude_none=True)).eq('user_id', home_debt.user_id).execute()
|
||||
return DiscordHomeDebt(**response.data[0])
|
||||
except Exception as e:
|
||||
print(f"Error updating home debt: {e}")
|
||||
return None
|
||||
|
||||
# Tính tổng số tiền đã trả
|
||||
total_paid = sum(share.share_amount for share in shares if share.is_paid)
|
||||
|
||||
return total_owed - total_paid
|
||||
async def get_all(self) -> List[DiscordHomeDebt]:
|
||||
"""Lấy tất cả khoản nợ"""
|
||||
try:
|
||||
response = self.table.select('*').execute()
|
||||
return [DiscordHomeDebt(**home_debt) for home_debt in response.data]
|
||||
except Exception as e:
|
||||
print(f"Error getting all home debts: {e}")
|
||||
return []
|
||||
@@ -1,47 +0,0 @@
|
||||
from typing import Optional
|
||||
from infra.db import postgres
|
||||
|
||||
class UserRepository:
|
||||
def __init__(self):
|
||||
self.exp_table = postgres.get_table('user_exp')
|
||||
self.voice_table = postgres.get_table('voice_time')
|
||||
|
||||
async def get_exp(self, user_id: int) -> int:
|
||||
"""Get user's experience points from database"""
|
||||
try:
|
||||
response = self.exp_table.select('exp_points').eq('user_id', user_id).execute()
|
||||
if response.data:
|
||||
return response.data[0]['exp_points']
|
||||
return 0
|
||||
except Exception as e:
|
||||
print(f"Error getting user exp: {e}")
|
||||
return 0
|
||||
|
||||
async def update_exp(self, user_id: int, exp_points: int) -> bool:
|
||||
"""Update user's experience points in database"""
|
||||
try:
|
||||
response = self.exp_table.upsert({'user_id': user_id, 'exp_points': exp_points}).execute()
|
||||
return len(response.data) > 0
|
||||
except Exception as e:
|
||||
print(f"Error updating user exp: {e}")
|
||||
return False
|
||||
|
||||
async def get_voice_time(self, user_id: int) -> Optional[str]:
|
||||
"""Get user's voice time from database"""
|
||||
try:
|
||||
response = self.voice_table.select('last_join_time').eq('user_id', user_id).execute()
|
||||
if response.data:
|
||||
return response.data[0]['last_join_time']
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"Error getting user voice time: {e}")
|
||||
return None
|
||||
|
||||
async def update_voice_time(self, user_id: int, join_time: str) -> bool:
|
||||
"""Update user's voice time in database"""
|
||||
try:
|
||||
response = self.voice_table.upsert({'user_id': user_id, 'last_join_time': join_time}).execute()
|
||||
return len(response.data) > 0
|
||||
except Exception as e:
|
||||
print(f"Error updating user voice time: {e}")
|
||||
return False
|
||||
Reference in New Issue
Block a user