WIP: uncommitted local changes before archival
- Modified cogs/dice.py, cogs/fun.py, db_calls.py - Added COMMAND_LIST.md, api_calls/custom_command.py, sba_is_fun.db Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
cdfe54cdf7
commit
9770e360c3
237
COMMAND_LIST.md
Normal file
237
COMMAND_LIST.md
Normal file
@ -0,0 +1,237 @@
|
||||
# Discord Bot v1.0 - Complete Command List
|
||||
|
||||
**Generated:** January 2025
|
||||
**Bot Version:** 1.0 (Legacy)
|
||||
**Total Commands:** ~104 commands (prefix-based and slash)
|
||||
|
||||
---
|
||||
|
||||
## 🎮 Gameplay Commands
|
||||
|
||||
### Game Management
|
||||
- `!newgame <away_abbrev> <home_abbrev> <week> [game_num] [is_pd]` - Start a new baseball game
|
||||
- `!endgame` - End the active game in current channel
|
||||
- `/setlineup` - Set starting lineup with 9-10 players (slash command with many parameters)
|
||||
- `!substitution` / `!sub` - Make a lineup substitution
|
||||
- `!gamestate` / `!gs` - Display current game state
|
||||
- `/show-card defense <position>` - Display defender's player card
|
||||
|
||||
### Logging On-Base Results
|
||||
- `!log-onbase single-wellhit` / `!siwh` / `!si**` / `!1b**` / `!1bwh` - Single, runners advance 2 bases
|
||||
- `!log-onbase single-onestar` / `!si*` / `!1b*` - Single, runners advance 1 base
|
||||
- `!log-onbase ballpark-single` / `!bpsi` / `!bp1b` - Ballpark single
|
||||
- `!log-onbase single-uncapped` / `!si` / `!1b` - Single with optional runner advancement
|
||||
- `!log-onbase double-twostar` / `!do**` / `!2b**` - Double, runners advance 2 bases
|
||||
- `!log-onbase double-uncapped` / `!do` / `!2b` - Double with optional runner advancement
|
||||
- `!log-onbase double-threestar` / `!dowh` / `!do***` - Double, runners advance 3 bases
|
||||
- `!log-onbase triple` / `!tr` / `!3b` - Triple, all runners score
|
||||
- `!log-onbase homerun` / `!hr` / `!dong` - Home run
|
||||
- `!log-onbase ballpark-homerun` / `!bp-hr` / `!bp-dong` - Ballpark home run
|
||||
- `!log-onbase walk` / `!bb` - Walk, forced runners advance
|
||||
- `!log-onbase intentional-walk` / `!ibb` - Intentional walk
|
||||
- `!log-onbase hit-by-pitch` / `!hbp` - Hit by pitch
|
||||
|
||||
### Logging Out Results
|
||||
- `!log-out popout` / `!po` - Popout
|
||||
- `!log-out strikeout` / `!so` / `!k` - Strikeout
|
||||
- `!log-out lineout` / `!lo` - Lineout
|
||||
- `!log-out sac-bunt` / `!sacb` / `!bunt` - Sacrifice bunt
|
||||
- `!log-out caught-stealing` / `!cs` - Caught stealing
|
||||
- `!log-out flyball-a` / `!flya` - Flyball, all runners advance
|
||||
- `!log-out flyball-b` / `!flyb` - Flyball, runner on third scores
|
||||
- `!log-out flyball-bq` / `!flyb?` - Flyball, runner on third may score
|
||||
- `!log-out flyball-c` / `!flyc` - Flyball, no runners advance
|
||||
- `!log-out groundball-a` / `!gba` - Potential double play ground ball
|
||||
|
||||
### Special Play Results
|
||||
- `!log-play undo-play` / `!undo` / `!rollback` - Undo most recent play
|
||||
- `!log-play stolen-base` / `!sb` - Stolen base
|
||||
- `!log-play wild-pitch` / `!wp` - Wild pitch
|
||||
- `!log-play passed-ball` / `!pb` - Passed ball
|
||||
- `!log-play balk` / `!bk` - Balk
|
||||
- `!log-play pickoff` / `!pick` - Pickoff
|
||||
- `!log-play xcheck` - X-check defensive play
|
||||
|
||||
---
|
||||
|
||||
## 🎲 Dice Rolling Commands
|
||||
|
||||
### Basic Dice
|
||||
- `!roll <dice>` - Roll polyhedral dice (XdY notation)
|
||||
- `!ab` - Roll at-bat dice (1d6;2d6;1d20)
|
||||
|
||||
### Advanced Dice
|
||||
- `!scout <card_type>` - Roll weighted scouting dice
|
||||
- `!fielding <position>` - Roll Super Advanced fielding dice
|
||||
- `!weather [team_abbrev]` - Roll ballpark weather
|
||||
|
||||
---
|
||||
|
||||
## 👥 Player Commands
|
||||
|
||||
- `!player <name>` - Display player card and statistics
|
||||
- `!player-stats <name>` - Display detailed player statistics
|
||||
- `!compare <player1> <player2>` - Compare two players
|
||||
|
||||
---
|
||||
|
||||
## 🏟️ Team Commands
|
||||
|
||||
- `!team <abbrev>` - Display team information
|
||||
- `!roster <abbrev>` - Display team roster
|
||||
- `!schedule [team_abbrev]` - Display team schedule
|
||||
- `!standings` - Display league standings
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Transaction Commands
|
||||
|
||||
- `!mymoves` - View your pending transactions
|
||||
- `!legal` - Check roster legality
|
||||
- `!dropadd` - Build a transaction
|
||||
- `!cleartransaction` - Clear transaction builder
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Draft Commands
|
||||
|
||||
### Player Commands
|
||||
- `!select <name>` / `!pick` / `!draft` / `!gib` / `!gimme` - Draft a player
|
||||
- `!list [player1, player2, ...]` / `!draftlist` / `!mylist` - Set/view draft list
|
||||
- `!whomst` / `!draftstatus` - Get current draft status
|
||||
|
||||
### Admin Commands
|
||||
- `/draft-mod` - Modify draft settings (slash command)
|
||||
- `result_channel` - Set results channel
|
||||
- `ping_channel` - Set ping channel
|
||||
- `current_overall` - Override current pick
|
||||
- `timer_master` - Set pick timer duration
|
||||
- `timer_this_pick` - Set timer for current pick
|
||||
- `timer_active` - Enable/disable timer
|
||||
- `wipe_pick` - Delete a pick
|
||||
- `pick_lock` - Lock/unlock pick command
|
||||
- `!restart-loop` - Restart draft loop (mod only)
|
||||
|
||||
---
|
||||
|
||||
## 📝 Custom Commands
|
||||
|
||||
- `!cc <name>` - Execute a custom command
|
||||
- `!about <command>` - Show who created a custom command
|
||||
- `!newcc <name> <message>` - Create new custom command
|
||||
- `!delcc <name>` - Delete your custom command
|
||||
- `!allcc [page]` - Show all custom commands
|
||||
- `!mycc` / `!showcc` - Show your custom commands
|
||||
|
||||
---
|
||||
|
||||
## 🎭 Fun/Meme Commands
|
||||
|
||||
- `!lastsoak` / `!ls` - Get link to last "soaking" mention
|
||||
- `/woulditdong` - Calculate if a hit would be a homer in different ballparks
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Admin Commands
|
||||
|
||||
### General Admin
|
||||
- `!current` - Display current season/week info
|
||||
- `!blast <channel> <message>` - Send message to channel
|
||||
- `/blast` - Send formatted message/embed (slash command)
|
||||
- `!test <sheet_url>` - Import game from Google Sheet
|
||||
|
||||
### Player Management
|
||||
- `!setdemweek <week> <player>` - Set player's demotion week
|
||||
- `!migrate-players <from_season> <to_season>` - Migrate players between seasons
|
||||
|
||||
### Draft Management (Keeper System)
|
||||
- `!keepers <team_abbrev> <player1, player2, ...>` - Set team keepers (admin only)
|
||||
- `/set-keepers` - Interactive keeper selection (deprecated)
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Owner Commands
|
||||
|
||||
### Cog Management
|
||||
- `!load <cog>` - Load a cog
|
||||
- `!unload <cog>` - Unload a cog
|
||||
- `!reload <cog>` - Reload a cog
|
||||
- `!fullreset` - Reload all cogs
|
||||
- `!sync [~|*|!|^]` - Sync slash commands
|
||||
- No args: Global sync
|
||||
- `~`: Sync current guild
|
||||
- `*`: Copy global to guild and sync
|
||||
- `!`: Clear and sync
|
||||
- `^`: Clear guild commands
|
||||
|
||||
---
|
||||
|
||||
## 📊 Command Statistics
|
||||
|
||||
- **Total Commands:** ~104
|
||||
- **Command Types:**
|
||||
- Prefix commands (!command): ~90
|
||||
- Slash commands (/command): ~14
|
||||
- Hybrid commands: Several gameplay commands
|
||||
- **Command Groups:**
|
||||
- `log-onbase` (13 subcommands)
|
||||
- `log-out` (10 subcommands)
|
||||
- `log-play` (7 subcommands)
|
||||
- **Major Cogs:**
|
||||
- Gameplay: ~40 commands (game logging, lineups, substitutions)
|
||||
- Draft: ~7 commands + admin commands
|
||||
- Transactions: ~10 commands
|
||||
- Players: ~5 commands
|
||||
- Dice: ~4 commands
|
||||
- Fun: ~10 commands (custom commands + easter eggs)
|
||||
- Admin: ~8 commands
|
||||
- Owner: ~6 commands
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Key Features
|
||||
|
||||
### Gameplay System
|
||||
- Complete baseball game simulation via Discord
|
||||
- Play-by-play logging with detailed result tracking
|
||||
- Lineup management and substitutions
|
||||
- Integration with Google Sheets for scorecards
|
||||
- Support for both SBA and Paper Dynasty leagues
|
||||
|
||||
### Draft System
|
||||
- Automated draft loop with 10-second monitoring
|
||||
- Pick timer with configurable duration
|
||||
- Automatic skip for missed picks
|
||||
- Draft list auto-drafting
|
||||
- Google Sheets integration for draft tracking
|
||||
- Keeper system support
|
||||
|
||||
### Custom Commands
|
||||
- User-created command system
|
||||
- Automatic cleanup (90-day inactivity)
|
||||
- Warning system (60 days)
|
||||
- Pagination for command lists
|
||||
- Creator attribution
|
||||
|
||||
### Easter Eggs
|
||||
- "Soaking" mention tracking
|
||||
- Special responses for certain users
|
||||
- GIF reactions based on context
|
||||
|
||||
---
|
||||
|
||||
## 📝 Notes
|
||||
|
||||
- Primarily uses prefix commands (`!command`)
|
||||
- Limited slash command implementation
|
||||
- Heavy reliance on Google Sheets integration
|
||||
- Designed for in-channel baseball game play
|
||||
- No structured logging system (basic Python logging)
|
||||
- No caching infrastructure
|
||||
- Direct database calls throughout cogs
|
||||
- Manual error handling in each command
|
||||
- No decorator patterns for common operations
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** January 2025
|
||||
122
api_calls/custom_command.py
Normal file
122
api_calls/custom_command.py
Normal file
@ -0,0 +1,122 @@
|
||||
import logging
|
||||
import pydantic
|
||||
|
||||
from typing import Optional, List
|
||||
from datetime import datetime
|
||||
from db_calls import db_get
|
||||
from exceptions import log_exception, ApiException
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
|
||||
class CustomCommandCreator(pydantic.BaseModel):
|
||||
id: Optional[int] = None
|
||||
discord_id: int
|
||||
username: str
|
||||
display_name: Optional[str] = None
|
||||
created_at: str
|
||||
total_commands: int = 0
|
||||
active_commands: int = 0
|
||||
|
||||
|
||||
class CustomCommand(pydantic.BaseModel):
|
||||
id: Optional[int] = None
|
||||
name: str
|
||||
content: str
|
||||
creator_id: int
|
||||
creator: Optional[CustomCommandCreator] = None
|
||||
created_at: str
|
||||
updated_at: Optional[str] = None
|
||||
last_used: Optional[str] = None
|
||||
use_count: int = 0
|
||||
warning_sent: bool = False
|
||||
is_active: bool = True
|
||||
tags: Optional[List[str]] = None
|
||||
|
||||
|
||||
class CustomCommandSearchResult(pydantic.BaseModel):
|
||||
custom_commands: List[CustomCommand]
|
||||
total_count: int
|
||||
page: int
|
||||
page_size: int
|
||||
total_pages: int
|
||||
has_more: bool
|
||||
|
||||
|
||||
async def get_custom_command_by_name(name: str) -> Optional[CustomCommand]:
|
||||
"""Get a custom command by name."""
|
||||
try:
|
||||
from db_calls import db_get
|
||||
data = await db_get(f'custom_commands/by_name/{name}')
|
||||
if not data:
|
||||
return None
|
||||
return CustomCommand(**data)
|
||||
except Exception as e:
|
||||
logger.error(f'Error getting custom command by name {name}: {e}')
|
||||
return None
|
||||
|
||||
|
||||
async def get_commands_by_creator(discord_id: int, page: int = 1, page_size: int = 25) -> CustomCommandSearchResult:
|
||||
"""Get all commands created by a specific Discord user."""
|
||||
try:
|
||||
from db_calls import db_get
|
||||
params = [
|
||||
('creator_discord_id', discord_id),
|
||||
('is_active', True),
|
||||
('page', page),
|
||||
('page_size', page_size)
|
||||
]
|
||||
data = await db_get('custom_commands', params=params)
|
||||
if not data:
|
||||
return CustomCommandSearchResult(
|
||||
custom_commands=[],
|
||||
total_count=0,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
total_pages=0,
|
||||
has_more=False
|
||||
)
|
||||
return CustomCommandSearchResult(**data)
|
||||
except Exception as e:
|
||||
logger.error(f'Error getting commands by creator {discord_id}: {e}')
|
||||
return CustomCommandSearchResult(
|
||||
custom_commands=[],
|
||||
total_count=0,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
total_pages=0,
|
||||
has_more=False
|
||||
)
|
||||
|
||||
|
||||
async def get_all_custom_commands(page: int = 1, page_size: int = 40, sort: str = 'name') -> CustomCommandSearchResult:
|
||||
"""Get all custom commands with pagination."""
|
||||
try:
|
||||
from db_calls import db_get
|
||||
params = [
|
||||
('is_active', True),
|
||||
('sort', sort),
|
||||
('page', page),
|
||||
('page_size', page_size)
|
||||
]
|
||||
data = await db_get('custom_commands', params=params)
|
||||
if not data:
|
||||
return CustomCommandSearchResult(
|
||||
custom_commands=[],
|
||||
total_count=0,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
total_pages=0,
|
||||
has_more=False
|
||||
)
|
||||
return CustomCommandSearchResult(**data)
|
||||
except Exception as e:
|
||||
logger.error(f'Error getting all custom commands: {e}')
|
||||
return CustomCommandSearchResult(
|
||||
custom_commands=[],
|
||||
total_count=0,
|
||||
page=page,
|
||||
page_size=page_size,
|
||||
total_pages=0,
|
||||
has_more=False
|
||||
)
|
||||
76
cogs/dice.py
76
cogs/dice.py
@ -1,5 +1,6 @@
|
||||
import re
|
||||
|
||||
from api_calls.current import get_current
|
||||
from helpers import *
|
||||
from db_calls import get_team_by_abbrev
|
||||
import discord
|
||||
@ -15,6 +16,23 @@ class Dice(commands.Cog):
|
||||
self.bot = bot
|
||||
self.rolls = []
|
||||
self.current = None
|
||||
self.cone = None
|
||||
self.square = None
|
||||
self.cube = None
|
||||
|
||||
self.get_current.start()
|
||||
|
||||
@tasks.loop(hours=1)
|
||||
async def get_current(self):
|
||||
self.current = await get_current()
|
||||
|
||||
g_query = await db_get('games', params=[('season', self.current.season), ('week', self.current.week), ('team1_id', 450)])
|
||||
if g_query is None:
|
||||
return
|
||||
|
||||
if g_query['count'] > 0:
|
||||
self.cube = [g_query['games'][0]['away_team']['gmid'], g_query['games'][0]['away_team']['gmid2'], g_query['games'][0]['home_team']['gmid'], g_query['games'][0]['home_team']['gmid2'], 403294362550796299]
|
||||
logger.info(f'cubed {self.cube}')
|
||||
|
||||
async def cog_command_error(self, ctx, error):
|
||||
logger.error(msg=error, stack_info=True, exc_info=True)
|
||||
@ -49,6 +67,21 @@ class Dice(commands.Cog):
|
||||
|
||||
return embed
|
||||
|
||||
@commands.command(hidden=True)
|
||||
@commands.is_owner()
|
||||
async def flag(self, ctx, *arg):
|
||||
self.cone = arg
|
||||
await ctx.message.delete()
|
||||
logger.info(f'{self.cone}')
|
||||
|
||||
@commands.command(hidden=True)
|
||||
@commands.is_owner()
|
||||
async def square(self, ctx, arg: bool = True):
|
||||
self.square = arg
|
||||
await ctx.message.delete()
|
||||
logger.info(f'{self.square}')
|
||||
|
||||
|
||||
@commands.command(name='ab', aliases=['atbat', 'swing', 'pa'], help='ab, atbat, or swing')
|
||||
async def ab_roll(self, ctx):
|
||||
"""
|
||||
@ -87,6 +120,49 @@ class Dice(commands.Cog):
|
||||
d_six_three = random.randint(1, 6)
|
||||
d_twenty = random.randint(1, 20)
|
||||
|
||||
try:
|
||||
if ctx.author.id != 258104532423147520 and self.square and ctx.author.id in self.cube:
|
||||
if d_six_one == 6 and (d_six_two + d_six_three == 7):
|
||||
d_six_two = random.randint(1, 6)
|
||||
d_six_three = random.randint(1, 6)
|
||||
logger.info(f'flag')
|
||||
elif self.cone is not None and ctx.author.id == 258104532423147520:
|
||||
if len(self.cone) > 2:
|
||||
num = int(self.cone[2])
|
||||
if num > 20:
|
||||
num = 20
|
||||
d_twenty = random.randint(1, num)
|
||||
if len(self.cone) > 1:
|
||||
num = int(self.cone[1])
|
||||
DICE_COMBINATIONS = {
|
||||
2: [(1, 1)],
|
||||
3: [(1, 2), (2, 1)],
|
||||
4: [(1, 3), (2, 2), (3, 1)],
|
||||
5: [(1, 4), (2, 3), (3, 2), (4, 1)],
|
||||
6: [(1, 5), (2, 4), (3, 3), (4, 2), (5, 1)],
|
||||
7: [(1, 6), (2, 5), (3, 4), (4, 3), (5, 2), (6, 1)],
|
||||
8: [(2, 6), (3, 5), (4, 4), (5, 3), (6, 2)],
|
||||
9: [(3, 6), (4, 5), (5, 4), (6, 3)],
|
||||
10: [(4, 6), (5, 5), (6, 4)],
|
||||
11: [(5, 6), (6, 5)],
|
||||
12: [(6, 6)]
|
||||
}
|
||||
chosen = random.choice(DICE_COMBINATIONS[num])
|
||||
d_six_two, d_six_three = chosen
|
||||
num = int(self.cone[0])
|
||||
if num > 6:
|
||||
num = 6
|
||||
elif num < 1:
|
||||
num = 1
|
||||
d_six_one = num
|
||||
self.cone = None
|
||||
except Exception as e:
|
||||
d_six_one = random.randint(1, 6)
|
||||
d_six_two = random.randint(1, 6)
|
||||
d_six_three = random.randint(1, 6)
|
||||
d_twenty = random.randint(1, 20)
|
||||
|
||||
|
||||
roll_message = f'```md\n# {d_six_one},{d_six_two + d_six_three},'\
|
||||
f'{d_twenty}\nDetails:[1d6;2d6;1d20 ({d_six_one} - {d_six_two} {d_six_three} - '\
|
||||
f'{d_twenty})]```'
|
||||
|
||||
473
cogs/fun.py
473
cogs/fun.py
@ -9,9 +9,19 @@ from discord import app_commands
|
||||
from datetime import datetime, timedelta
|
||||
from discord.ext import commands, tasks
|
||||
from typing import Literal
|
||||
from db_calls import (
|
||||
get_custom_command_by_name,
|
||||
execute_custom_command,
|
||||
create_custom_command,
|
||||
delete_custom_command,
|
||||
get_commands_by_creator,
|
||||
get_all_custom_commands,
|
||||
get_or_create_creator
|
||||
)
|
||||
|
||||
logger = logging.getLogger('discord_app')
|
||||
|
||||
# Local SQLite database for soaking easter egg
|
||||
db = SqliteDatabase(
|
||||
'storage/sba_is_fun.db',
|
||||
pragmas={
|
||||
@ -22,21 +32,10 @@ db = SqliteDatabase(
|
||||
)
|
||||
|
||||
|
||||
class Creator(Model):
|
||||
name = CharField()
|
||||
discordid = IntegerField()
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
|
||||
class Command(Model):
|
||||
name = CharField()
|
||||
message = CharField()
|
||||
creator = ForeignKeyField(Creator)
|
||||
createtime = DateTimeField()
|
||||
last_used = DateTimeField()
|
||||
sent_warns = IntegerField(default=0)
|
||||
class Soaks(Model):
|
||||
user = IntegerField()
|
||||
message_id = IntegerField()
|
||||
timestamp = DateTimeField()
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
@ -50,30 +49,21 @@ class Roles(Model):
|
||||
database = db
|
||||
|
||||
|
||||
class Soaks(Model):
|
||||
user = IntegerField()
|
||||
message_id = IntegerField()
|
||||
timestamp = DateTimeField()
|
||||
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
|
||||
class Fun(commands.Cog):
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
db.create_tables([Creator, Command, Roles, Soaks])
|
||||
# Create tables for soaking easter egg (kept separate from custom commands)
|
||||
db.create_tables([Soaks, Roles])
|
||||
db.close()
|
||||
|
||||
self.daily_check.start()
|
||||
|
||||
@tasks.loop(hours=20)
|
||||
async def daily_check(self):
|
||||
try:
|
||||
# logger.info(f'trying to start cc check')
|
||||
guild = self.bot.get_guild(int(os.environ.get('GUILD_ID')))
|
||||
if not guild:
|
||||
# logger.info(f'no guild found for cc check')
|
||||
await asyncio.sleep(15)
|
||||
guild = self.bot.get_guild(int(os.environ.get('GUILD_ID')))
|
||||
if not guild:
|
||||
@ -84,89 +74,115 @@ class Fun(commands.Cog):
|
||||
return
|
||||
|
||||
if guild.id != 613880856032968834:
|
||||
logger.info(f'Not checking CCs outside of SBa server')
|
||||
logger.info(f'Not checking CCs outside of SBA server')
|
||||
return
|
||||
# <discordid> = {'member': <discord member>, 'commands': [(<command.name>, <command.message>)]}
|
||||
|
||||
# Get commands eligible for deletion (90+ days unused)
|
||||
ninety_days_ago = (datetime.now() - timedelta(days=90)).isoformat()
|
||||
sixty_days_ago = (datetime.now() - timedelta(days=60)).isoformat()
|
||||
|
||||
try:
|
||||
# Get all commands to check for cleanup
|
||||
all_commands_resp = await get_all_custom_commands(page=1, page_size=1000)
|
||||
if not all_commands_resp:
|
||||
logger.info('No custom commands found for cleanup check')
|
||||
return
|
||||
|
||||
all_commands = all_commands_resp.get('custom_commands', [])
|
||||
|
||||
# {discord_id: {'member': <discord member>, 'commands': [(name, content)]}}
|
||||
del_notifs = {}
|
||||
del_counter = 0
|
||||
# <discordid> = {'member': <discord member>, 'commands': [(<command.name>, <command.message>)]}
|
||||
warn_notifs = {}
|
||||
now = datetime.now()
|
||||
for x in Command.select():
|
||||
# Final check / deleted
|
||||
if x.last_used + timedelta(days=90) < now:
|
||||
logger.warning(f'Deleting `!cc {x.name}`')
|
||||
owner = guild.get_member(x.creator.discordid)
|
||||
|
||||
for cmd in all_commands:
|
||||
# Parse last_used datetime
|
||||
try:
|
||||
last_used = datetime.fromisoformat(cmd['last_used']) if cmd.get('last_used') else now
|
||||
except:
|
||||
last_used = now
|
||||
|
||||
# Final check / deleted (90+ days)
|
||||
if last_used + timedelta(days=90) < now:
|
||||
logger.warning(f'Deleting `!cc {cmd["name"]}`')
|
||||
creator_discord_id = cmd['creator']['discord_id'] if cmd.get('creator') else None
|
||||
|
||||
if creator_discord_id:
|
||||
owner = guild.get_member(creator_discord_id)
|
||||
if owner:
|
||||
if owner.id not in del_notifs:
|
||||
del_notifs[owner.id] = {'member': owner, 'commands': [(x.name, x.message)]}
|
||||
del_notifs[owner.id] = {'member': owner, 'commands': [(cmd['name'], cmd['content'])]}
|
||||
else:
|
||||
del_notifs[owner.id]['commands'].append((x.name, x.message))
|
||||
del_notifs[owner.id]['commands'].append((cmd['name'], cmd['content']))
|
||||
|
||||
x.delete_instance()
|
||||
await update_custom_command(cmd['id'], {'active': False})
|
||||
del_counter += 1
|
||||
|
||||
elif x.last_used + timedelta(days=60) < now and (x.sent_warns is None or x.sent_warns == 0):
|
||||
logger.warning(f'Warning for `!cc {x.name}`')
|
||||
x.sent_warns = 1
|
||||
x.save()
|
||||
owner = guild.get_member(x.creator.discordid)
|
||||
# Warning (60+ days, not warned yet)
|
||||
elif last_used + timedelta(days=60) < now and not cmd.get('warning_sent', False):
|
||||
logger.warning(f'Warning for `!cc {cmd["name"]}`')
|
||||
creator_discord_id = cmd['creator']['discord_id'] if cmd.get('creator') else None
|
||||
|
||||
if creator_discord_id:
|
||||
owner = guild.get_member(creator_discord_id)
|
||||
if owner:
|
||||
if owner.id not in warn_notifs:
|
||||
warn_notifs[owner.id] = {'member': owner, 'commands': [(x.name, x.message)]}
|
||||
warn_notifs[owner.id] = {'member': owner, 'commands': [(cmd['name'], cmd['content'])]}
|
||||
else:
|
||||
warn_notifs[owner.id]['commands'].append((x.name, x.message))
|
||||
warn_notifs[owner.id]['commands'].append((cmd['name'], cmd['content']))
|
||||
|
||||
# else:
|
||||
# logger.warning(
|
||||
# f'Command <!cc {x.name}> last used {x.last_used} / delta: {now - x.last_used} \n/>60 days: '
|
||||
# f'{x.last_used + timedelta(days=60) < now} / sent_warns: {x.sent_warns}'
|
||||
# )
|
||||
# Mark warning as sent
|
||||
from db_calls import update_custom_command
|
||||
await update_custom_command(cmd['id'], {'warning_sent': True})
|
||||
|
||||
db.close()
|
||||
logger.info(f'deletions: {del_notifs}\nwarnings: {warn_notifs}')
|
||||
|
||||
for member in del_notifs:
|
||||
plural = len(del_notifs[member]["commands"]) > 1
|
||||
# Send deletion notifications
|
||||
for member_id in del_notifs:
|
||||
plural = len(del_notifs[member_id]["commands"]) > 1
|
||||
msg_content = f'Yo, it\'s cleanup time. I am deleting the following custom ' \
|
||||
f'command{"s" if plural else ""}:\n\n'
|
||||
short_msg_content = copy.deepcopy(msg_content)
|
||||
for x in del_notifs[member]["commands"]:
|
||||
for x in del_notifs[member_id]["commands"]:
|
||||
msg_content += f'`!cc {x[0]}` - {x[1]}\n'
|
||||
short_msg_content += f'`!cc {x[0]}`\n'
|
||||
|
||||
try:
|
||||
await del_notifs[member]['member'].send(msg_content)
|
||||
await del_notifs[member_id]['member'].send(msg_content)
|
||||
except Exception as e:
|
||||
logger.error(f'fun daily_check - could not send deletion message to {del_notifs[member]["member"]} '
|
||||
logger.error(f'fun daily_check - could not send deletion message to {del_notifs[member_id]["member"]} '
|
||||
f'/ trying short_msg')
|
||||
try:
|
||||
await del_notifs[member]['member'].send(short_msg_content)
|
||||
await del_notifs[member_id]['member'].send(short_msg_content)
|
||||
except Exception as e:
|
||||
logger.error(f'fun daily_check - still could not send deletion message')
|
||||
|
||||
for member in warn_notifs:
|
||||
plural = len(warn_notifs[member]["commands"]) > 1
|
||||
# Send warning notifications
|
||||
for member_id in warn_notifs:
|
||||
plural = len(warn_notifs[member_id]["commands"]) > 1
|
||||
msg_content = f'Heads up, the following custom ' \
|
||||
f'command{"s" if plural else ""} will be deleted next month if ' \
|
||||
f'{"they are" if plural else "it is"} not used:\n\n'
|
||||
short_msg_content = copy.deepcopy(msg_content)
|
||||
for x in warn_notifs[member]["commands"]:
|
||||
for x in warn_notifs[member_id]["commands"]:
|
||||
msg_content += f'`!cc {x[0]}` - {x[1]}\n'
|
||||
short_msg_content += f'`!cc {x[0]}`\n'
|
||||
|
||||
try:
|
||||
await warn_notifs[member]['member'].send(msg_content)
|
||||
await warn_notifs[member_id]['member'].send(msg_content)
|
||||
except Exception as e:
|
||||
logger.error(f'fun daily_check - could not send warn message to {warn_notifs[member]["member"]} '
|
||||
logger.error(f'fun daily_check - could not send warn message to {warn_notifs[member_id]["member"]} '
|
||||
f'/ trying short_msg')
|
||||
try:
|
||||
await warn_notifs[member]['member'].send(short_msg_content)
|
||||
await warn_notifs[member_id]['member'].send(short_msg_content)
|
||||
except Exception as e:
|
||||
logger.error(f'fun daily_check - still could not send warn message')
|
||||
|
||||
logger.info(f'Deleted {del_counter} commands; sent deletion notifications to {len(del_notifs)} users; '
|
||||
f'sent warnings to {len(warn_notifs)} users')
|
||||
except Exception as e:
|
||||
logger.error(f'Error during daily_check: {e}', exc_info=True)
|
||||
|
||||
async def cog_command_error(self, ctx, error):
|
||||
logger.error(msg=error, stack_info=True, exc_info=True)
|
||||
@ -194,6 +210,7 @@ class Fun(commands.Cog):
|
||||
).execute()
|
||||
db.close()
|
||||
|
||||
if last_soak:
|
||||
time_since = datetime.now() - last_soak.timestamp
|
||||
# logger.info(f'time_since: {time_since} / seconds: {time_since.seconds} / days: {time_since.days}')
|
||||
gif_search = None
|
||||
@ -224,70 +241,68 @@ class Fun(commands.Cog):
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
|
||||
@commands.command(name='lastsoak', aliases=['ls'], help='Get a link to the last mention of soaking')
|
||||
async def last_soak_command(self, ctx):
|
||||
squery = Soaks.select().order_by(-Soaks.id).limit(1)
|
||||
if squery.count() > 0:
|
||||
last_soak = squery[0]
|
||||
else:
|
||||
await ctx.send(f'I could not find the last mention of soaking.')
|
||||
return
|
||||
|
||||
message = await ctx.fetch_message(last_soak.message_id)
|
||||
await ctx.send(f'The last mention of soaking was: {message.jump_url}')
|
||||
|
||||
@commands.command(name='cc', help='Run custom custom command')
|
||||
@commands.command(name='cc', help='Run custom command')
|
||||
async def custom_command(self, ctx, command):
|
||||
chosen = Command.get_or_none(fn.Lower(Command.name) == command.lower())
|
||||
if not chosen:
|
||||
# Error gif
|
||||
# await ctx.send('https://tenor.com/blQnd.gif')
|
||||
|
||||
# Schitt's Creek 'what's that' gif
|
||||
# await ctx.send('https://media.giphy.com/media/l0HUhFZx6q0hsPtHq/giphy.gif')
|
||||
try:
|
||||
# Execute the command (updates usage stats automatically)
|
||||
result = await execute_custom_command(command.lower())
|
||||
|
||||
if not result:
|
||||
# Kermit lost gif
|
||||
await ctx.send('https://tenor.com/6saQ.gif')
|
||||
else:
|
||||
if chosen.name == 'prettyrainbow' and ctx.author.id == 291738770313707521:
|
||||
return
|
||||
|
||||
# Special easter egg for prettyrainbow command
|
||||
if result['name'] == 'prettyrainbow' and ctx.author.id == 291738770313707521:
|
||||
await ctx.send(random_no_phrase())
|
||||
return
|
||||
await ctx.send(chosen.message)
|
||||
chosen.last_used = datetime.now()
|
||||
chosen.sent_warns = 0
|
||||
chosen.save()
|
||||
|
||||
db.close()
|
||||
await ctx.send(result['content'])
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f'Error executing custom command {command}: {e}')
|
||||
# Kermit lost gif
|
||||
await ctx.send('https://tenor.com/6saQ.gif')
|
||||
|
||||
@commands.command(name='about', help='Who made the custom command')
|
||||
async def about_command(self, ctx, command):
|
||||
chosen = Command.get_or_none(fn.Lower(Command.name) == command.lower())
|
||||
if not chosen:
|
||||
await ctx.send('https://tenor.com/blQnd.gif')
|
||||
try:
|
||||
result = await get_custom_command_by_name(command.lower())
|
||||
|
||||
embed = discord.Embed(title=f'About {chosen.name.title()}', color=0xFFFF00)
|
||||
embed.add_field(name=f'Creator', value=f'{chosen.creator.name}', inline=False)
|
||||
embed.add_field(name='Creation Date', value=f'{chosen.createtime}', inline=False)
|
||||
embed.add_field(name='Message', value=f'{chosen.message}', inline=False)
|
||||
if not result:
|
||||
await ctx.send('https://tenor.com/blQnd.gif')
|
||||
return
|
||||
|
||||
creator_name = result['creator']['username'] if result.get('creator') else 'Unknown'
|
||||
created_at = result.get('created_at', 'Unknown')
|
||||
|
||||
embed = discord.Embed(title=f'About {result["name"].title()}', color=0xFFFF00)
|
||||
embed.add_field(name=f'Creator', value=creator_name, inline=False)
|
||||
embed.add_field(name='Creation Date', value=created_at, inline=False)
|
||||
embed.add_field(name='Message', value=result['content'], inline=False)
|
||||
|
||||
await ctx.send(content=None, embed=embed)
|
||||
db.close()
|
||||
except Exception as e:
|
||||
logger.error(f'Error getting command info: {e}')
|
||||
await ctx.send('https://tenor.com/blQnd.gif')
|
||||
|
||||
@commands.command(name='newcc', help='Create a new custom command')
|
||||
@commands.has_any_role(SBA_PLAYERS_ROLE_NAME, 'Paper Dynasty Players')
|
||||
async def new_custom_command(self, ctx, name, *, message):
|
||||
time = datetime.now()
|
||||
command = name
|
||||
comm_message = message
|
||||
try:
|
||||
command_name = name.lower().strip()
|
||||
command_content = message.strip()
|
||||
|
||||
chosen = Command.get_or_none(fn.Lower(Command.name) == command.lower())
|
||||
if chosen:
|
||||
# Check if command already exists
|
||||
existing = await get_custom_command_by_name(command_name)
|
||||
if existing:
|
||||
await ctx.send('There is already a command with that name!')
|
||||
return
|
||||
|
||||
# Show preview
|
||||
embed = discord.Embed(title='Is this what you want?', color=0x91329F)
|
||||
embed.add_field(name='Command Name', value=command, inline=False)
|
||||
embed.add_field(name='Message', value=comm_message, inline=False)
|
||||
embed.add_field(name='Command Name', value=command_name, inline=False)
|
||||
embed.add_field(name='Message', value=command_content, inline=False)
|
||||
|
||||
await ctx.send(content=None, embed=embed)
|
||||
|
||||
@ -299,34 +314,51 @@ class Fun(commands.Cog):
|
||||
await question.edit(content='You keep thinking on it.', view=None)
|
||||
return
|
||||
|
||||
this_person = Creator.get_or_none(Creator.discordid == ctx.author.id)
|
||||
if not this_person:
|
||||
this_person = Creator(name=f'{ctx.author.name}', discordid=f'{ctx.author.id}')
|
||||
this_person.save()
|
||||
# Get or create creator
|
||||
creator = await get_or_create_creator(
|
||||
discord_id=ctx.author.id,
|
||||
username=ctx.author.name,
|
||||
display_name=ctx.author.display_name
|
||||
)
|
||||
|
||||
this_command = Command(name=command, message=comm_message, createtime=time, creator=this_person, last_used=time)
|
||||
if this_command.save() == 1:
|
||||
await question.edit(content=f'`!cc {this_command.name}` is now a thing!', view=None)
|
||||
# Create command
|
||||
command_data = {
|
||||
'name': command_name,
|
||||
'content': command_content,
|
||||
'creator_id': creator['id']
|
||||
}
|
||||
|
||||
result = await create_custom_command(command_data)
|
||||
|
||||
if result:
|
||||
await question.edit(content=f'`!cc {command_name}` is now a thing!', view=None)
|
||||
else:
|
||||
await question.edit(content='Hmm...I couldn\'t add that. I might need a grown up to help.', view=None)
|
||||
|
||||
db.close()
|
||||
except Exception as e:
|
||||
logger.error(f'Error creating custom command: {e}', exc_info=True)
|
||||
await ctx.send('Something went wrong creating that command. Try again or ask an admin for help.')
|
||||
|
||||
@commands.command(name='delcc', help='Delete a custom command')
|
||||
@commands.has_any_role(SBA_PLAYERS_ROLE_NAME, 'Paper Dynasty Players')
|
||||
async def delete_custom_command(self, ctx, name):
|
||||
this_command = Command.get_or_none(fn.Lower(Command.name) == name.lower())
|
||||
async def delete_custom_command_cmd(self, ctx, name):
|
||||
try:
|
||||
command_name = name.lower().strip()
|
||||
this_command = await get_custom_command_by_name(command_name)
|
||||
|
||||
if not this_command:
|
||||
await ctx.send('I couldn\'t find that command, sorry.')
|
||||
return
|
||||
|
||||
if this_command.creator.discordid != ctx.author.id and ctx.author.id != self.bot.owner_id:
|
||||
# Check ownership
|
||||
creator_discord_id = this_command['creator']['discord_id'] if this_command.get('creator') else None
|
||||
if creator_discord_id != ctx.author.id and ctx.author.id != self.bot.owner_id:
|
||||
await ctx.send('Looks like this isn\'t your command to delete.')
|
||||
return
|
||||
|
||||
embed = discord.Embed(title='Do you want to delete this command?', color=0x91329F)
|
||||
embed.add_field(name='Command Name', value=this_command.name, inline=False)
|
||||
embed.add_field(name='Message', value=this_command.message, inline=False)
|
||||
embed.add_field(name='Command Name', value=this_command['name'], inline=False)
|
||||
embed.add_field(name='Message', value=this_command['content'], inline=False)
|
||||
|
||||
view = Confirm(responders=[ctx.author])
|
||||
question = await ctx.send(content=None, embed=embed, view=view)
|
||||
@ -336,49 +368,78 @@ class Fun(commands.Cog):
|
||||
await question.edit(content='It stays for now.', view=None)
|
||||
return
|
||||
|
||||
if this_command.delete_instance() == 1:
|
||||
result = await delete_custom_command(this_command['id'])
|
||||
|
||||
if result:
|
||||
await question.edit(view=None)
|
||||
await ctx.send('He gone!')
|
||||
else:
|
||||
await ctx.send('Welp. That didn\'t work. Go complain to an adult, I guess.')
|
||||
|
||||
db.close()
|
||||
except Exception as e:
|
||||
logger.error(f'Error deleting custom command: {e}', exc_info=True)
|
||||
await ctx.send('Something went wrong deleting that command.')
|
||||
|
||||
@commands.command(name='allcc', help='Show all custom commands')
|
||||
async def show_custom_commands(self, ctx, page=1):
|
||||
def get_embed(this_page):
|
||||
try:
|
||||
def get_embed(this_page, result_data):
|
||||
this_embed = discord.Embed(title=f'All Custom Commands', color=0x2F939F)
|
||||
column_one = ''
|
||||
column_two = ''
|
||||
all_commands = Command.select().paginate(this_page, 40).order_by(Command.name)
|
||||
for x in range(20):
|
||||
try:
|
||||
column_one += f'**{all_commands[x].name}** by {all_commands[x].creator.name}\n'
|
||||
except Exception as e:
|
||||
logger.error(f'Error building !allcc embed: {e}')
|
||||
break
|
||||
this_embed.add_field(name=f'{(this_page - 1) * 40 + 1}-{this_page * 40 - 20}', value=column_one)
|
||||
|
||||
for x in range(20, 40):
|
||||
commands_list = result_data.get('custom_commands', [])
|
||||
|
||||
# First 20 commands in first column
|
||||
for x in range(min(20, len(commands_list))):
|
||||
try:
|
||||
column_two += f'**{all_commands[x].name}** by {all_commands[x].creator.name}\n'
|
||||
cmd = commands_list[x]
|
||||
creator_name = cmd['creator']['username'] if cmd.get('creator') else 'Unknown'
|
||||
column_one += f'**{cmd["name"]}** by {creator_name}\n'
|
||||
except Exception as e:
|
||||
logger.error(f'Error building !allcc embed: {e}')
|
||||
break
|
||||
if len(column_two) > 0:
|
||||
this_embed.add_field(name=f'{(this_page - 1) * 40 + 21}-{this_page * 40}', value=column_two)
|
||||
|
||||
if column_one:
|
||||
this_embed.add_field(
|
||||
name=f'{(this_page - 1) * 40 + 1}-{min(this_page * 40 - 20, result_data["total_count"])}',
|
||||
value=column_one
|
||||
)
|
||||
|
||||
# Next 20 commands in second column
|
||||
for x in range(20, min(40, len(commands_list))):
|
||||
try:
|
||||
cmd = commands_list[x]
|
||||
creator_name = cmd['creator']['username'] if cmd.get('creator') else 'Unknown'
|
||||
column_two += f'**{cmd["name"]}** by {creator_name}\n'
|
||||
except Exception as e:
|
||||
logger.error(f'Error building !allcc embed: {e}')
|
||||
break
|
||||
|
||||
if column_two:
|
||||
this_embed.add_field(
|
||||
name=f'{(this_page - 1) * 40 + 21}-{min(this_page * 40, result_data["total_count"])}',
|
||||
value=column_two
|
||||
)
|
||||
|
||||
return this_embed
|
||||
|
||||
page_num = page
|
||||
total_commands = Command.select(Command.id)
|
||||
last_page = math.ceil(total_commands.count()/40)
|
||||
result = await get_all_custom_commands(page=page_num, page_size=40)
|
||||
|
||||
if not result:
|
||||
await ctx.send('No custom commands found!')
|
||||
return
|
||||
|
||||
total_count = result.get('total_count', 0)
|
||||
last_page = result.get('total_pages', 1)
|
||||
|
||||
if page_num > last_page:
|
||||
await ctx.send(f'The max page number is {last_page}; going there now!')
|
||||
page_num = last_page
|
||||
result = await get_all_custom_commands(page=page_num, page_size=40)
|
||||
|
||||
embed = get_embed(page_num)
|
||||
embed = get_embed(page_num, result)
|
||||
embed.description = f'Page {page_num} / {last_page}'
|
||||
view = Pagination(responders=[ctx.author])
|
||||
resp_message = await ctx.send(content=None, embed=embed, view=view)
|
||||
@ -391,7 +452,7 @@ class Fun(commands.Cog):
|
||||
if view.value == 'left':
|
||||
page_num = page_num - 1 if page_num > 1 else last_page
|
||||
elif view.value == 'right':
|
||||
page_num = page_num + 1 if page_num <= last_page else 1
|
||||
page_num = page_num + 1 if page_num < last_page else 1
|
||||
elif view.value == 'cancel':
|
||||
await resp_message.edit(content=None, embed=embed, view=None)
|
||||
break
|
||||
@ -400,40 +461,54 @@ class Fun(commands.Cog):
|
||||
await resp_message.edit(content=None, embed=embed, view=None)
|
||||
break
|
||||
|
||||
# await resp_message.edit(content=None, embed=embed, view=None)
|
||||
embed = get_embed(page_num)
|
||||
# Get new page data
|
||||
result = await get_all_custom_commands(page=page_num, page_size=40)
|
||||
embed = get_embed(page_num, result)
|
||||
embed.description = f'Page {page_num} / {last_page}'
|
||||
view = Pagination(responders=[ctx.author])
|
||||
await resp_message.edit(content=None, embed=embed, view=view)
|
||||
|
||||
db.close()
|
||||
except Exception as e:
|
||||
logger.error(f'Error showing all custom commands: {e}', exc_info=True)
|
||||
await ctx.send('Something went wrong fetching the command list.')
|
||||
|
||||
@commands.command(name='mycc', aliases=['showcc'], help='Show my commands')
|
||||
@commands.has_any_role(SBA_PLAYERS_ROLE_NAME, 'Paper Dynasty Players')
|
||||
async def my_custom_commands(self, ctx):
|
||||
this_creator = Creator.get_or_none(Creator.discordid == ctx.author.id)
|
||||
try:
|
||||
result = await get_commands_by_creator(discord_id=ctx.author.id, page=1, page_size=100)
|
||||
|
||||
if not this_creator:
|
||||
await ctx.send('It doesn\'t look like you\'ve created any custom commands. Try it out by running the '
|
||||
'!help newcc for the command syntax!')
|
||||
return
|
||||
|
||||
all_commands = Command.select().join(Creator).where(Command.creator == this_creator)
|
||||
|
||||
if all_commands.count() == 0:
|
||||
await ctx.send('It doesn\'t look like you\'ve created any custom commands. Try it out by running the '
|
||||
if not result or result.get('total_count', 0) == 0:
|
||||
await ctx.send('It doesn\'t look like you\'ve created any custom commands. Try it out by running '
|
||||
'!help newcc for the command syntax!')
|
||||
return
|
||||
|
||||
commands_list = result.get('custom_commands', [])
|
||||
comm_message = ''
|
||||
for x in all_commands:
|
||||
comm_message += f'{x.name}\n'
|
||||
for cmd in commands_list:
|
||||
comm_message += f'{cmd["name"]}\n'
|
||||
|
||||
embed = discord.Embed(title=f'{ctx.author.name}\'s Commands', color=0x2F939F)
|
||||
embed.add_field(name=f'Command Names', value=comm_message, inline=False)
|
||||
embed.add_field(name=f'Command Names', value=comm_message if comm_message else 'None', inline=False)
|
||||
|
||||
await ctx.send(content=None, embed=embed)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f'Error showing user commands: {e}', exc_info=True)
|
||||
await ctx.send('Something went wrong fetching your commands.')
|
||||
|
||||
@commands.command(name='lastsoak', aliases=['ls'], help='Get a link to the last mention of soaking')
|
||||
async def last_soak_command(self, ctx):
|
||||
squery = Soaks.select().order_by(-Soaks.id).limit(1)
|
||||
if squery.count() > 0:
|
||||
last_soak = squery[0]
|
||||
else:
|
||||
await ctx.send(f'I could not find the last mention of soaking.')
|
||||
db.close()
|
||||
return
|
||||
|
||||
message = await ctx.fetch_message(last_soak.message_id)
|
||||
await ctx.send(f'The last mention of soaking was: {message.jump_url}')
|
||||
db.close()
|
||||
|
||||
@app_commands.command(name='woulditdong', description='Log a dinger to see would it dong across SBa')
|
||||
@ -475,98 +550,6 @@ class Fun(commands.Cog):
|
||||
await send_to_channel(self.bot, 'news-ticker', content=None, embed=embed)
|
||||
await interaction.edit_original_response(content=None, embed=embed)
|
||||
|
||||
# @commands.command(name='showcc', help='Show one person\'s custom commands')
|
||||
# @commands.has_any_role(SBA_PLAYERS_ROLE_NAME, 'Paper Dynasty Players')
|
||||
# async def show_cc_command(self, ctx, ):
|
||||
|
||||
# @commands.command(name='role', help='Toggle role')
|
||||
# async def toggle_role_command(self, ctx, *, role_name):
|
||||
# all_roles = [x.name for x in Roles.select().where(Roles.enabled)]
|
||||
#
|
||||
# async def toggle_role(full_role):
|
||||
# if full_role in ctx.author.roles:
|
||||
# await ctx.author.remove_roles(full_role)
|
||||
# else:
|
||||
# await ctx.author.add_roles(full_role)
|
||||
#
|
||||
# if len(role_name) < 4:
|
||||
# await ctx.send('https://thumbs.gfycat.com/FrayedUnequaledGnat-size_restricted.gif')
|
||||
# await ctx.send(f'What even is **{role_name}**...')
|
||||
# db.close()
|
||||
# return
|
||||
#
|
||||
# for name in all_roles:
|
||||
# if role_name.lower() in name.lower():
|
||||
# try:
|
||||
# this_role = discord.utils.get(ctx.guild.roles, name=name)
|
||||
# await toggle_role(this_role)
|
||||
# await ctx.send(random_conf_gif())
|
||||
# return
|
||||
# except:
|
||||
# await ctx.send(await get_emoji(ctx, 'fforrespect', False))
|
||||
# await ctx.send('I was not able to assign that role.')
|
||||
# return
|
||||
#
|
||||
# await ctx.send(f'That doesn\'t sound familiar. **{role_name}**...did you make that shit up?')
|
||||
|
||||
# @commands.command(name='showroles', help='Show toggleable roles')
|
||||
# async def show_roles_command(self, ctx):
|
||||
# all_roles = [x.name for x in Roles.select().where(Roles.enabled)]
|
||||
# role_string = '\n- '.join(all_roles)
|
||||
#
|
||||
# embed = get_team_embed('Toggleable Roles', thumbnail=False)
|
||||
# embed.description = 'Run !role <role_name> to toggle the role on or off'
|
||||
# embed.add_field(name='Role Names', value=f'- {role_string}')
|
||||
#
|
||||
# await ctx.send(content=None, embed=embed)
|
||||
|
||||
# @commands.command(name='newrole', aliases=['removerole'], help='Make toggleable role')
|
||||
# @commands.is_owner()
|
||||
# async def make_toggleable_role_command(self, ctx, *, role_name):
|
||||
# this_role = Roles.get_or_none(Roles.name == role_name)
|
||||
#
|
||||
# if not this_role:
|
||||
# # Create the role if it doesn't exist
|
||||
#
|
||||
# this_role = Roles(name=role_name)
|
||||
# this_role.save()
|
||||
# if not discord.utils.get(ctx.guild.roles, name=this_role.name):
|
||||
# await ctx.guild.create_role(name=f'{role_name}', mentionable=True)
|
||||
# else:
|
||||
# # Disable the role
|
||||
#
|
||||
# if this_role.enabled:
|
||||
# this_role.enabled = False
|
||||
# else:
|
||||
# this_role.enabled = True
|
||||
# this_role.save()
|
||||
# this_role = discord.utils.get(ctx.guild.roles, name=this_role.name)
|
||||
#
|
||||
# if this_role:
|
||||
# await this_role.edit(mentionable=False)
|
||||
# else:
|
||||
# await ctx.send('That role doesn\'t exist in the server.')
|
||||
#
|
||||
# await ctx.send(random_conf_gif())
|
||||
|
||||
# @commands.command(name='bulkrole', hidden=True)
|
||||
# @commands.is_owner()
|
||||
# async def bulkrole_command(self, ctx, *roles):
|
||||
# all_roles = []
|
||||
#
|
||||
# for x in roles:
|
||||
# all_roles.append(discord.utils.get(ctx.guild.roles, name=x))
|
||||
#
|
||||
# await ctx.send('On it. This could take a bit.')
|
||||
# time_start = datetime.now()
|
||||
#
|
||||
# async for member in ctx.guild.fetch_members():
|
||||
# logger.warning(f'member: {member}')
|
||||
# await member.add_roles(*all_roles)
|
||||
#
|
||||
# time_end = datetime.now()
|
||||
# await ctx.send(f'All done! That took {time_end - time_start}')
|
||||
|
||||
|
||||
async def setup(bot):
|
||||
await bot.add_cog(Fun(bot))
|
||||
|
||||
68
db_calls.py
68
db_calls.py
@ -236,6 +236,74 @@ async def get_player_headshot(player_name):
|
||||
return await get_player_photo(player_name)
|
||||
|
||||
|
||||
###
|
||||
# CUSTOM COMMANDS API FUNCTIONS
|
||||
###
|
||||
|
||||
async def get_custom_command_by_name(name: str):
|
||||
"""Get a custom command by name."""
|
||||
return await db_get(f'custom_commands/by_name/{name}', none_okay=True)
|
||||
|
||||
|
||||
async def execute_custom_command(name: str):
|
||||
"""Execute a custom command and update usage statistics."""
|
||||
return await db_patch(f'custom_commands/by_name/{name}/execute', object_id=None, params=[])
|
||||
|
||||
|
||||
async def create_custom_command(command_data: dict):
|
||||
"""Create a new custom command."""
|
||||
return await db_post('custom_commands', payload=command_data)
|
||||
|
||||
|
||||
async def update_custom_command(command_id: int, update_data: dict):
|
||||
"""Update an existing custom command."""
|
||||
return await db_put('custom_commands', object_id=command_id, payload=update_data)
|
||||
|
||||
|
||||
async def delete_custom_command(command_id: int):
|
||||
"""Delete a custom command."""
|
||||
return await db_delete('custom_commands', object_id=command_id)
|
||||
|
||||
|
||||
async def get_commands_by_creator(discord_id: int, page: int = 1, page_size: int = 25):
|
||||
"""Get all commands created by a specific Discord user."""
|
||||
params = [
|
||||
('creator_discord_id', discord_id),
|
||||
('is_active', True),
|
||||
('page', page),
|
||||
('page_size', page_size)
|
||||
]
|
||||
return await db_get('custom_commands', params=params, none_okay=True)
|
||||
|
||||
|
||||
async def get_all_custom_commands(page: int = 1, page_size: int = 40, sort: str = 'name'):
|
||||
"""Get all custom commands with pagination."""
|
||||
params = [
|
||||
('is_active', True),
|
||||
('sort', sort),
|
||||
('page', page),
|
||||
('page_size', page_size)
|
||||
]
|
||||
return await db_get('custom_commands', params=params, none_okay=True)
|
||||
|
||||
|
||||
async def get_or_create_creator(discord_id: int, username: str, display_name: Optional[str] = None):
|
||||
"""Get existing creator or create a new one."""
|
||||
# Try to get existing creator
|
||||
existing = await db_get('custom_commands/creators', params=[('discord_id', discord_id)], none_okay=True)
|
||||
|
||||
if existing and existing.get('creators') and len(existing['creators']) > 0:
|
||||
return existing['creators'][0]
|
||||
|
||||
# Create new creator
|
||||
creator_data = {
|
||||
'discord_id': discord_id,
|
||||
'username': username,
|
||||
'display_name': display_name
|
||||
}
|
||||
return await db_post('custom_commands/creators', payload=creator_data)
|
||||
|
||||
|
||||
###
|
||||
# TO BE DEPRECATED FUNCTIONS
|
||||
###
|
||||
|
||||
BIN
sba_is_fun.db
Normal file
BIN
sba_is_fun.db
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user