3465 lines
142 KiB
Python
3465 lines
142 KiB
Python
import asyncio
|
|
import datetime
|
|
import logging
|
|
import math
|
|
import os
|
|
import random
|
|
import traceback
|
|
|
|
import discord
|
|
import pygsheets
|
|
import requests
|
|
from discord.ext import commands
|
|
from api_calls import *
|
|
|
|
from bs4 import BeautifulSoup
|
|
from difflib import get_close_matches
|
|
from dataclasses import dataclass
|
|
from typing import Optional, Literal
|
|
|
|
from exceptions import log_exception
|
|
from in_game.gameplay_models import Team
|
|
|
|
|
|
SBA_SEASON = 11
|
|
PD_SEASON = 9
|
|
ranked_cardsets = [20, 21, 22, 17, 18, 19]
|
|
LIVE_CARDSET_ID = 24
|
|
LIVE_PROMO_CARDSET_ID = 25
|
|
MAX_CARDSET_ID = 30
|
|
CARDSETS = {
|
|
'Ranked': {
|
|
'primary': ranked_cardsets,
|
|
'human': ranked_cardsets
|
|
},
|
|
'Minor League': {
|
|
'primary': [20, 8], # 1998, Mario
|
|
'secondary': [6], # 2013
|
|
'human': [x for x in range(1, MAX_CARDSET_ID)]
|
|
},
|
|
'Major League': {
|
|
'primary': [20, 21, 17, 18, 12, 6, 7, 8], # 1998, 1998 Promos, 2024, 24 Promos, 2008, 2013, 2012, Mario
|
|
'secondary': [5, 3], # 2019, 2022
|
|
'human': ranked_cardsets
|
|
},
|
|
'Hall of Fame': {
|
|
'primary': [x for x in range(1, MAX_CARDSET_ID)],
|
|
'secondary': [],
|
|
'human': ranked_cardsets
|
|
},
|
|
'Flashback': {
|
|
'primary': [5, 1, 3, 9, 8], # 2019, 2021, 2022, 2023, Mario
|
|
'secondary': [13, 5], # 2018, 2019
|
|
'human': [5, 1, 3, 9, 8] # 2019, 2021, 2022, 2023
|
|
},
|
|
'gauntlet-3': {
|
|
'primary': [13], # 2018
|
|
'secondary': [5, 11, 9], # 2019, 2016, 2023
|
|
'human': [x for x in range(1, MAX_CARDSET_ID)]
|
|
},
|
|
'gauntlet-4': {
|
|
'primary': [3, 6, 16], # 2022, 2013, Backyard Baseball
|
|
'secondary': [4, 9], # 2022 Promos, 2023
|
|
'human': [3, 4, 6, 9, 15, 16]
|
|
},
|
|
'gauntlet-5': {
|
|
'primary': [17, 8], # 2024, Mario
|
|
'secondary': [13], # 2018
|
|
'human': [x for x in range(1, MAX_CARDSET_ID)]
|
|
},
|
|
'gauntlet-6': {
|
|
'primary': [20, 8], # 1998, Mario
|
|
'secondary': [12], # 2008
|
|
'human': [x for x in range(1, MAX_CARDSET_ID)]
|
|
},
|
|
'gauntlet-7': {
|
|
'primary': [5, 23], # 2019, Brilliant Stars
|
|
'secondary': [1], # 2021
|
|
'human': [x for x in range(1, MAX_CARDSET_ID)]
|
|
}
|
|
}
|
|
SBA_COLOR = 'a6ce39'
|
|
PD_PLAYERS = 'Paper Dynasty Players'
|
|
SBA_PLAYERS_ROLE_NAME = f'Season {SBA_SEASON} Players'
|
|
PD_PLAYERS_ROLE_NAME = f'Paper Dynasty Players'
|
|
PD_CARD_URL = 'https://sombaseball.ddns.net/cards/pd'
|
|
PKMN_REF_URL = 'https://pkmncards.com/card/'
|
|
RATINGS_BATTER_FORMULA = '=IMPORTRANGE("1zDmlOw94gTzOAjqOpNdDZsg0O6rxNWkL4-XT6-iL2IE","guide_Batters!A1:CD")'
|
|
RATINGS_PITCHER_FORMULA = '=IMPORTRANGE("1zDmlOw94gTzOAjqOpNdDZsg0O6rxNWkL4-XT6-iL2IE","guide_Pitchers!A1:BQ")'
|
|
RATINGS_SHEET_KEY = '1zDmlOw94gTzOAjqOpNdDZsg0O6rxNWkL4-XT6-iL2IE'
|
|
ALL_MLB_TEAMS = {
|
|
'Arizona Diamondbacks': ['ARI', 'Diamondbacks'],
|
|
'Atlanta Braves': ['ATL', 'MLN', 'Braves'],
|
|
'Baltimore Orioles': ['BAL', 'Orioles'],
|
|
'Boston Red Sox': ['BOS', 'Red Sox'],
|
|
'Chicago Cubs': ['CHC', 'Cubs'],
|
|
'Chicago White Sox': ['CHW', 'White Sox'],
|
|
'Cincinnati Reds': ['CIN', 'Reds'],
|
|
'Cleveland Guardians': ['CLE', 'Guardians'],
|
|
'Colorado Rockies': ['COL', 'Rockies'],
|
|
'Detroit Tigers': ['DET', 'Tigers'],
|
|
'Houston Astros': ['HOU', 'Astros'],
|
|
'Kansas City Royals': ['KCR', 'Royals'],
|
|
'Los Angeles Angels': ['LAA', 'CAL', 'Angels'],
|
|
'Los Angeles Dodgers': ['LAD', 'Dodgers'],
|
|
'Miami Marlins': ['MIA', 'Marlins'],
|
|
'Milwaukee Brewers': ['MIL', 'MKE', 'Brewers'],
|
|
'Minnesota Twins': ['MIN', 'Twins'],
|
|
'New York Mets': ['NYM', 'Mets'],
|
|
'New York Yankees': ['NYY', 'Yankees'],
|
|
'Oakland Athletics': ['OAK', 'Athletics'],
|
|
'Philadelphia Phillies': ['PHI', 'Phillies'],
|
|
'Pittsburgh Pirates': ['PIT', 'Pirates'],
|
|
'San Diego Padres': ['SDP', 'Padres'],
|
|
'Seattle Mariners': ['SEA', 'Mariners'],
|
|
'San Francisco Giants': ['SFG', 'Giants'],
|
|
'St Louis Cardinals': ['STL', 'Cardinals'],
|
|
'Tampa Bay Rays': ['TBR', 'Rays'],
|
|
'Texas Rangers': ['TEX', 'Senators', 'Rangers'],
|
|
'Toronto Blue Jays': ['TOR', 'Jays'],
|
|
'Washington Nationals': ['WSN', 'WAS', 'Nationals'],
|
|
}
|
|
IMAGES = {
|
|
'logo': 'https://sombaseball.ddns.net/static/images/sba-logo.png',
|
|
'mvp-hype': f'{PD_CARD_URL}/mvp.png',
|
|
'pack-sta': f'{PD_CARD_URL}/pack-standard.png',
|
|
'pack-pre': f'{PD_CARD_URL}/pack-premium.png',
|
|
'pack-mar': f'{PD_CARD_URL}/sluggers/mario-gauntlet.png',
|
|
'pack-pkmnbs': f'https://i.postimg.cc/635M4X52/pokemon-brilliantstars.jpg',
|
|
'mvp': {
|
|
'Arizona Diamondbacks': f'{PD_CARD_URL}/mvp/arizona-diamondbacks.gif',
|
|
'Atlanta Braves': f'{PD_CARD_URL}/mvp/atlanta-braves.gif',
|
|
'Baltimore Orioles': f'{PD_CARD_URL}/mvp/baltimore-orioles.gif',
|
|
'Boston Red Sox': f'{PD_CARD_URL}/mvp/boston-red-sox.gif',
|
|
'Chicago Cubs': f'{PD_CARD_URL}/mvp/chicago-cubs.gif',
|
|
'Chicago White Sox': f'{PD_CARD_URL}/mvp/chicago-white-sox.gif',
|
|
'Cincinnati Reds': f'{PD_CARD_URL}/mvp/cincinnati-reds.gif',
|
|
'Cleveland Indians': f'{PD_CARD_URL}/mvp/cleveland-guardians.gif',
|
|
'Cleveland Guardians': f'{PD_CARD_URL}/mvp/cleveland-guardians.gif',
|
|
'Colorado Rockies': f'{PD_CARD_URL}/mvp/colorado-rockies.gif',
|
|
'Detroit Tigers': f'{PD_CARD_URL}/mvp/detroit-tigers.gif',
|
|
'Houston Astros': f'{PD_CARD_URL}/mvp/houston-astros.gif',
|
|
'Kansas City Royals': f'{PD_CARD_URL}/mvp/kansas-city-royals.gif',
|
|
'Los Angeles Angels': f'{PD_CARD_URL}/mvp/los-angeles-angels.gif',
|
|
'Los Angeles Dodgers': f'{PD_CARD_URL}/mvp/los-angeles-dodgers.gif',
|
|
'Miami Marlins': f'{PD_CARD_URL}/mvp/miami-marlins.gif',
|
|
'Milwaukee Brewers': f'{PD_CARD_URL}/mvp/milwaukee-brewers.gif',
|
|
'Minnesota Twins': f'{PD_CARD_URL}/mvp/minnesota-twins.gif',
|
|
'New York Mets': f'{PD_CARD_URL}/mvp/new-york-mets.gif',
|
|
'New York Yankees': f'{PD_CARD_URL}/mvp/new-york-yankees.gif',
|
|
'Oakland Athletics': f'{PD_CARD_URL}/mvp/oakland-athletics.gif',
|
|
'Philadelphia Phillies': f'{PD_CARD_URL}/mvp/philadelphia-phillies.gif',
|
|
'Pittsburgh Pirates': f'{PD_CARD_URL}/mvp/pittsburgh-pirates.gif',
|
|
'San Diego Padres': f'{PD_CARD_URL}/mvp/san-diego-padres.gif',
|
|
'Seattle Mariners': f'{PD_CARD_URL}/mvp/seattle-mariners.gif',
|
|
'San Francisco Giants': f'{PD_CARD_URL}/mvp/san-francisco-giants.gif',
|
|
'St Louis Cardinals': f'{PD_CARD_URL}/mvp/st-louis-cardinals.gif',
|
|
'St. Louis Cardinals': f'{PD_CARD_URL}/mvp/st-louis-cardinals.gif',
|
|
'Tampa Bay Rays': f'{PD_CARD_URL}/mvp/tampa-bay-rays.gif',
|
|
'Texas Rangers': f'{PD_CARD_URL}/mvp/texas-rangers.gif',
|
|
'Toronto Blue Jays': f'{PD_CARD_URL}/mvp/toronto-blue-jays.gif',
|
|
'Washington Nationals': f'{PD_CARD_URL}/mvp/washington-nationals.gif',
|
|
'Junior All Stars': f'{PD_CARD_URL}/mvp.png',
|
|
'Mario Super Sluggers': f'{PD_CARD_URL}/mvp.png',
|
|
'Pokemon League': 'https://i.postimg.cc/ydzYB7BR/masterball.jpg'
|
|
},
|
|
'gauntlets': f'{PD_CARD_URL}/gauntlets.png'
|
|
}
|
|
INFIELD_X_CHART = {
|
|
'si1': {
|
|
'rp': 'No runner on first: Batter is safe at first and no one covers second. Batter to second, runners only '
|
|
'advance 1 base.\nRunner on first: batter singles, runners advance 1 base.',
|
|
'e1': 'Single and Error, batter to second, runners advance 2 bases.',
|
|
'e2': 'Single and Error, batter to third, all runners score.',
|
|
'no': 'Single, runners advance 1 base.'
|
|
},
|
|
'po': {
|
|
'rp': 'The batters hits a popup. None of the fielders take charge on the play and the ball drops in the '
|
|
'infield for a SI1! All runners advance 1 base.',
|
|
'e1': 'The catcher drops a popup for an error. All runners advance 1 base.',
|
|
'e2': 'The catcher grabs a squib in front of the plate and throws it into right field. The batter goes to '
|
|
'second and all runners score.',
|
|
'no': 'The batter pops out to the catcher.'
|
|
},
|
|
'fo': {
|
|
'rp': 'Batter swings and misses, but is awarded first base on a catcher interference call! One base error, '
|
|
'baserunners advance only if forced.',
|
|
'e1': 'The catcher drops a foul popup for an error. Batter rolls AB again.',
|
|
'e2': 'The catcher drops a foul popup for an error. Batter rolls AB again.',
|
|
'no': 'Runner(s) on base: make a passed ball check. If no passed ball, batter pops out to the catcher. If a '
|
|
'passed ball occurs, batter roll his AB again.\nNo runners: batter pops out to the catcher'
|
|
},
|
|
'g1': {
|
|
'rp': 'Runner on first, <2 outs: runner on first breaks up the double play, gbB\n'
|
|
'Else: gbA',
|
|
'e1': 'Error, batter to first, runners advance 1 base.',
|
|
'e2': 'Error, batter to second, runners advance 2 bases.',
|
|
'no': 'Consult Groundball Chart: `!gbA`'
|
|
},
|
|
'g2': {
|
|
'rp': 'Runner(s) on base: fielder makes bad throw for lead runner but batter is out at first for a gbC\n'
|
|
'No runners: gbB',
|
|
'e1': 'Error, batter to first, runners advance 1 base.',
|
|
'e2': 'Error, batter to second, runners advance 2 bases.',
|
|
'no': 'Consult Groundball Chart: `!gbB`'
|
|
},
|
|
'g3': {
|
|
'rp': 'Runner(s) on base: fielder checks the runner before throwing to first and allows a SI*\n'
|
|
'No runners: gbC',
|
|
'e1': 'Error, batter to first, runners advance 1 base.',
|
|
'e2': 'Error, batter to second, runners advance 2 bases.',
|
|
'no': 'Consult Groundball Chart: `!gbC`'
|
|
},
|
|
'spd': {
|
|
'rp': 'Catcher throws to first and hits the batter-runner in the back, SI1',
|
|
'e1': 'Error, batter to first, runners advance 1 base.',
|
|
'e2': 'Error, batter to second, runners advance 2 bases.',
|
|
'no': 'Speed check, Batter\'s safe range = Running; if safe, SI*; if out, gbC'
|
|
},
|
|
}
|
|
OUTFIELD_X_CHART = {
|
|
'si2': {
|
|
'rp': 'Batter singles, baserunners advance 2 bases. As the batter rounds first, the fielder throws behind him '
|
|
'and catches him off the bag for an out!',
|
|
'e1': 'Single and error, batter to second, runners advance 2 bases.',
|
|
'e2': 'Single and error, batter to third, all runners score.',
|
|
'e3': 'Single and error, batter to third, all runners score',
|
|
'no': 'Single, all runners advance 2 bases.'
|
|
},
|
|
'do2': {
|
|
'rp': 'Batter doubles and runners advance three bases, but batter-runner is caught between second and third! '
|
|
'He is tagged out in the rundown.',
|
|
'e1': 'Double and error, batter to third, all runners score.',
|
|
'e2': 'Double and error, batter to third, all runners score.',
|
|
'e3': 'Double and error, batter and all runners score. Little league home run!',
|
|
'no': 'Double, all runners advance 2 bases.'
|
|
},
|
|
'do3': {
|
|
'rp': 'Batter doubles and runners advance three bases, but batter-runner is caught between second and third! '
|
|
'He is tagged out in the rundown.',
|
|
'e1': 'Double and error, batter to third, all runners score.',
|
|
'e2': 'Double and error, batter and all runners score. Little league home run!',
|
|
'e3': 'Double and error, batter and all runners score. Little league home run!',
|
|
'no': 'Double, all runners score.'
|
|
},
|
|
'tr3': {
|
|
'rp': 'Batter hits a ball into the gap and the outfielders collide trying to make the play! The ball rolls to '
|
|
'the wall and the batter trots home with an inside-the-park home run!',
|
|
'e1': 'Triple and error, batter and all runners score. Little league home run!',
|
|
'e2': 'Triple and error, batter and all runners score. Little league home run!',
|
|
'e3': 'Triple and error, batter and all runners score. Little league home run!',
|
|
'no': 'Triple, all runners score.'
|
|
},
|
|
'f1': {
|
|
'rp': 'The outfielder races back and makes a diving catch and collides with the wall! In the time he takes to '
|
|
'recuperate, all baserunners tag-up and advance 2 bases.',
|
|
'e1': '1 base error, runners advance 1 base.',
|
|
'e2': '2 base error, runners advance 2 bases.',
|
|
'e3': '3 base error, batter to third, all runners score.',
|
|
'no': 'Flyball A'
|
|
},
|
|
'f2': {
|
|
'rp': 'The outfielder catches the flyball for an out. If there is a runner on third, he tags-up and scores. '
|
|
'The play is appealed and the umps rule that the runner left early and is out on the appeal!',
|
|
'e1': '1 base error, runners advance 1 base.',
|
|
'e2': '2 base error, runners advance 2 bases.',
|
|
'e3': '3 base error, batter to third, all runners score.',
|
|
'no': 'Flyball B'
|
|
},
|
|
'f3': {
|
|
'rp': 'The outfielder makes a running catch in the gap! The lead runner lost track of the ball and was '
|
|
'advancing - he cannot return in time and is doubled off by the outfielder.',
|
|
'e1': '1 base error, runners advance 1 base.',
|
|
'e2': '2 base error, runners advance 2 bases.',
|
|
'e3': '3 base error, batter to third, all runners score.',
|
|
'no': 'Flyball C'
|
|
}
|
|
}
|
|
RARITY = {
|
|
'HoF': 8,
|
|
'MVP': 5,
|
|
'All-Star': 3,
|
|
'Starter': 2,
|
|
'Reserve': 1,
|
|
'Replacement': 0
|
|
}
|
|
SELECT_CARDSET_OPTIONS = [
|
|
discord.SelectOption(label='2025 Live', value='24'),
|
|
discord.SelectOption(label='2025 Promos', value='25'),
|
|
discord.SelectOption(label='1998 Season', value='20'),
|
|
discord.SelectOption(label='1998 Promos', value='21'),
|
|
discord.SelectOption(label='2024 Season', value='17'),
|
|
discord.SelectOption(label='2024 Promos', value='18'),
|
|
discord.SelectOption(label='2023 Season', value='9'),
|
|
discord.SelectOption(label='2023 Promos', value='10'),
|
|
discord.SelectOption(label='2022 Season', value='3'),
|
|
discord.SelectOption(label='2022 Promos', value='4'),
|
|
discord.SelectOption(label='2021 Season', value='1'),
|
|
discord.SelectOption(label='2019 Season', value='5'),
|
|
discord.SelectOption(label='2018 Season', value='13'),
|
|
discord.SelectOption(label='2018 Promos', value='14'),
|
|
discord.SelectOption(label='2016 Season', value='11'),
|
|
discord.SelectOption(label='2013 Season', value='6'),
|
|
discord.SelectOption(label='2012 Season', value='7')
|
|
]
|
|
ACTIVE_EVENT_LITERAL = Literal['2025 Season']
|
|
DEFENSE_LITERAL = Literal['Pitcher', 'Catcher', 'First Base', 'Second Base', 'Third Base', 'Shortstop', 'Left Field', 'Center Field', 'Right Field']
|
|
DEFENSE_NO_PITCHER_LITERAL = Literal['Catcher', 'First Base', 'Second Base', 'Third Base', 'Shortstop', 'Left Field', 'Center Field', 'Right Field']
|
|
COLORS = {
|
|
'sba': int('a6ce39', 16),
|
|
'yellow': int('FFEA00', 16),
|
|
'red': int('C70039', 16),
|
|
'white': int('FFFFFF', 16)
|
|
}
|
|
INSULTS = [
|
|
'Ugh, who even are you?',
|
|
'Ugh, who even are you? Go away.',
|
|
'Ugh, who even are you? Leave me alone.',
|
|
'I will call the fucking cops!',
|
|
'I will call the fucking cops! Go away.',
|
|
'I will call the fucking cops! Leave me alone',
|
|
'Please don\'t talk to me',
|
|
'Don\'t talk to me.',
|
|
'Eww, don\'t talk to me.',
|
|
'Get away from me.',
|
|
'Get away from me, creep.',
|
|
'Get away from me, loser.',
|
|
'Get away from me, pedobear.',
|
|
'Why are you even here?',
|
|
'Why are you even here? Get lost.',
|
|
'Why are you even here? Scram.',
|
|
'Why are you even here? No one knows who you are.',
|
|
'HEY, DON\'T TOUCH ME!',
|
|
'Hey, don\'t touch me!'
|
|
]
|
|
|
|
|
|
class Question:
|
|
def __init__(self, bot, channel, prompt, qtype, timeout, embed=None):
|
|
"""
|
|
Version 0.4
|
|
|
|
:param bot, discord bot object
|
|
:param channel, discord Channel object
|
|
:param prompt, string, prompt message to post
|
|
:param qtype, string, 'yesno', 'int', 'float', 'text', or 'url'
|
|
:param timeout, float, time to wait for a response
|
|
"""
|
|
if not prompt and not embed:
|
|
raise TypeError('prompt and embed may not both be None')
|
|
|
|
self.bot = bot
|
|
self.channel = channel
|
|
self.prompt = prompt
|
|
self.qtype = qtype
|
|
self.timeout = timeout
|
|
self.embed = embed
|
|
|
|
async def ask(self, responders: list):
|
|
"""
|
|
Params: responder, list of discord User objects
|
|
Returns: True/False if confirm question; full response otherwise
|
|
"""
|
|
yes = ['yes', 'y', 'ye', 'yee', 'yerp', 'yep', 'yeet', 'yip', 'yup', 'yarp', 'si']
|
|
no = ['no', 'n', 'nope', 'nah', 'nyet', 'nein']
|
|
|
|
if type(responders) is not list:
|
|
raise TypeError('Responders must be a list of Members')
|
|
|
|
def yesno(mes):
|
|
return mes.channel == self.channel and mes.author in responders and mes.content.lower() in yes + no
|
|
|
|
def text(mes):
|
|
return mes.channel == self.channel and mes.author in responders
|
|
|
|
await self.channel.send(content=self.prompt, embed=self.embed)
|
|
|
|
try:
|
|
resp = await self.bot.wait_for(
|
|
'message',
|
|
timeout=self.timeout,
|
|
check=yesno if self.qtype == 'yesno' else text
|
|
)
|
|
except asyncio.TimeoutError:
|
|
return None
|
|
except Exception as e:
|
|
await self.channel.send(f'Yuck, do you know what this means?\n\n{e}')
|
|
return None
|
|
|
|
if self.qtype == 'yesno':
|
|
if resp.content.lower() in yes:
|
|
return True
|
|
else:
|
|
return False
|
|
elif self.qtype == 'int':
|
|
return int(resp.content)
|
|
elif self.qtype == 'float':
|
|
return float(resp.content)
|
|
elif self.qtype == 'url':
|
|
if resp.content[:7] == 'http://' or resp.content[:8] == 'https://':
|
|
return resp.content
|
|
else:
|
|
return False
|
|
else:
|
|
return resp.content
|
|
|
|
|
|
class Confirm(discord.ui.View):
|
|
def __init__(self, responders: list, timeout: float = 300.0, label_type: Literal['yes', 'confirm'] = None):
|
|
super().__init__(timeout=timeout)
|
|
if not isinstance(responders, list):
|
|
raise TypeError('responders must be a list')
|
|
self.value = None
|
|
self.responders = responders
|
|
if label_type == 'yes':
|
|
self.confirm.label = 'Yes'
|
|
self.cancel.label = 'No'
|
|
|
|
# When the confirm button is pressed, set the inner value to `True` and
|
|
# stop the View from listening to more input.
|
|
# We also send the user an ephemeral message that we're confirming their choice.
|
|
@discord.ui.button(label='Confirm', style=discord.ButtonStyle.green)
|
|
async def confirm(self, interaction: discord.Interaction, button: discord.ui.Button):
|
|
if interaction.user not in self.responders:
|
|
return
|
|
|
|
self.value = True
|
|
self.clear_items()
|
|
self.stop()
|
|
|
|
# This one is similar to the confirmation button except sets the inner value to `False`
|
|
@discord.ui.button(label='Cancel', style=discord.ButtonStyle.grey)
|
|
async def cancel(self, interaction: discord.Interaction, button: discord.ui.Button):
|
|
if interaction.user not in self.responders:
|
|
return
|
|
|
|
self.value = False
|
|
self.clear_items()
|
|
self.stop()
|
|
|
|
|
|
class ButtonOptions(discord.ui.View):
|
|
def __init__(self, responders: list, timeout: float = 300.0, labels=None):
|
|
super().__init__(timeout=timeout)
|
|
if not isinstance(responders, list):
|
|
raise TypeError('responders must be a list')
|
|
self.value = None
|
|
self.responders = responders
|
|
self.options = labels
|
|
for count, x in enumerate(labels):
|
|
if count == 0:
|
|
self.option1.label = x
|
|
if x is None or x.lower() == 'na' or x == 'N/A':
|
|
self.remove_item(self.option1)
|
|
if count == 1:
|
|
self.option2.label = x
|
|
if x is None or x.lower() == 'na' or x == 'N/A':
|
|
self.remove_item(self.option2)
|
|
if count == 2:
|
|
self.option3.label = x
|
|
if x is None or x.lower() == 'na' or x == 'N/A':
|
|
self.remove_item(self.option3)
|
|
if count == 3:
|
|
self.option4.label = x
|
|
if x is None or x.lower() == 'na' or x == 'N/A':
|
|
self.remove_item(self.option4)
|
|
if count == 4:
|
|
self.option5.label = x
|
|
if x is None or x.lower() == 'na' or x == 'N/A':
|
|
self.remove_item(self.option5)
|
|
|
|
@discord.ui.button(label='Option 1', style=discord.ButtonStyle.primary)
|
|
async def option1(self, interaction: discord.Interaction, button: discord.ui.Button):
|
|
if interaction.user not in self.responders:
|
|
return
|
|
|
|
self.value = self.options[0]
|
|
self.clear_items()
|
|
self.stop()
|
|
|
|
@discord.ui.button(label='Option 2', style=discord.ButtonStyle.primary)
|
|
async def option2(self, interaction: discord.Interaction, button: discord.ui.Button):
|
|
if interaction.user not in self.responders:
|
|
return
|
|
|
|
self.value = self.options[1]
|
|
self.clear_items()
|
|
self.stop()
|
|
|
|
@discord.ui.button(label='Option 3', style=discord.ButtonStyle.primary)
|
|
async def option3(self, interaction: discord.Interaction, button: discord.ui.Button):
|
|
if interaction.user not in self.responders:
|
|
return
|
|
|
|
self.value = self.options[2]
|
|
self.clear_items()
|
|
self.stop()
|
|
|
|
@discord.ui.button(label='Option 4', style=discord.ButtonStyle.primary)
|
|
async def option4(self, interaction: discord.Interaction, button: discord.ui.Button):
|
|
if interaction.user not in self.responders:
|
|
return
|
|
|
|
self.value = self.options[3]
|
|
self.clear_items()
|
|
self.stop()
|
|
|
|
@discord.ui.button(label='Option 5', style=discord.ButtonStyle.primary)
|
|
async def option5(self, interaction: discord.Interaction, button: discord.ui.Button):
|
|
if interaction.user not in self.responders:
|
|
return
|
|
|
|
self.value = self.options[4]
|
|
self.clear_items()
|
|
self.stop()
|
|
|
|
|
|
class Pagination(discord.ui.View):
|
|
def __init__(self, responders: list, timeout: float = 300.0):
|
|
super().__init__(timeout=timeout)
|
|
if not isinstance(responders, list):
|
|
raise TypeError('responders must be a list')
|
|
|
|
self.value = None
|
|
self.responders = responders
|
|
|
|
@discord.ui.button(label='⏮️', style=discord.ButtonStyle.blurple)
|
|
async def left_button(self, interaction: discord.Interaction, button: discord.ui.Button):
|
|
if interaction.user not in self.responders:
|
|
logger.info(f'{interaction.user} is not in {self.responders}')
|
|
return
|
|
|
|
self.value = 'left'
|
|
await interaction.response.defer()
|
|
self.stop()
|
|
|
|
@discord.ui.button(label='❌️', style=discord.ButtonStyle.secondary)
|
|
async def cancel_button(self, interaction: discord.Interaction, button: discord.ui.Button):
|
|
if interaction.user not in self.responders:
|
|
logger.info(f'{interaction.user} is not in {self.responders}')
|
|
return
|
|
|
|
self.value = 'cancel'
|
|
await interaction.response.defer()
|
|
self.stop()
|
|
|
|
@discord.ui.button(label='⏭️', style=discord.ButtonStyle.blurple)
|
|
async def right_button(self, interaction: discord.Interaction, button: discord.ui.Button):
|
|
if interaction.user not in self.responders:
|
|
logger.info(f'{interaction.user} is not in {self.responders}')
|
|
return
|
|
|
|
self.value = 'right'
|
|
await interaction.response.defer()
|
|
self.stop()
|
|
|
|
|
|
class SelectChoicePackTeam(discord.ui.Select):
|
|
def __init__(self, which: Literal['AL', 'NL'], team, cardset_id: Optional[int] = None):
|
|
self.which = which
|
|
self.owner_team = team
|
|
self.cardset_id = cardset_id
|
|
if which == 'AL':
|
|
options = [
|
|
discord.SelectOption(label='Baltimore Orioles'),
|
|
discord.SelectOption(label='Boston Red Sox'),
|
|
discord.SelectOption(label='Chicago White Sox'),
|
|
discord.SelectOption(label='Cleveland Guardians'),
|
|
discord.SelectOption(label='Detroit Tigers'),
|
|
discord.SelectOption(label='Houston Astros'),
|
|
discord.SelectOption(label='Kansas City Royals'),
|
|
discord.SelectOption(label='Los Angeles Angels'),
|
|
discord.SelectOption(label='Minnesota Twins'),
|
|
discord.SelectOption(label='New York Yankees'),
|
|
discord.SelectOption(label='Oakland Athletics'),
|
|
discord.SelectOption(label='Seattle Mariners'),
|
|
discord.SelectOption(label='Tampa Bay Rays'),
|
|
discord.SelectOption(label='Texas Rangers'),
|
|
discord.SelectOption(label='Toronto Blue Jays')
|
|
]
|
|
else:
|
|
options = [
|
|
discord.SelectOption(label='Arizona Diamondbacks'),
|
|
discord.SelectOption(label='Atlanta Braves'),
|
|
discord.SelectOption(label='Chicago Cubs'),
|
|
discord.SelectOption(label='Cincinnati Reds'),
|
|
discord.SelectOption(label='Colorado Rockies'),
|
|
discord.SelectOption(label='Los Angeles Dodgers'),
|
|
discord.SelectOption(label='Miami Marlins'),
|
|
discord.SelectOption(label='Milwaukee Brewers'),
|
|
discord.SelectOption(label='New York Mets'),
|
|
discord.SelectOption(label='Philadelphia Phillies'),
|
|
discord.SelectOption(label='Pittsburgh Pirates'),
|
|
discord.SelectOption(label='San Diego Padres'),
|
|
discord.SelectOption(label='San Francisco Giants'),
|
|
discord.SelectOption(label='St. Louis Cardinals'),
|
|
discord.SelectOption(label='Washington Nationals')
|
|
]
|
|
super().__init__(placeholder=f'Select an {which} team', options=options)
|
|
|
|
async def callback(self, interaction: discord.Interaction):
|
|
team_id = None
|
|
if self.which == 'AL':
|
|
if self.values[0] == 'Baltimore Orioles':
|
|
team_id = 3
|
|
elif self.values[0] == 'Boston Red Sox':
|
|
team_id = 4
|
|
elif self.values[0] == 'Chicago White Sox':
|
|
team_id = 6
|
|
elif self.values[0] == 'Cleveland Guardians':
|
|
team_id = 8
|
|
elif self.values[0] == 'Detroit Tigers':
|
|
team_id = 10
|
|
elif self.values[0] == 'Houston Astros':
|
|
team_id = 11
|
|
elif self.values[0] == 'Kansas City Royals':
|
|
team_id = 12
|
|
elif self.values[0] == 'Los Angeles Angels':
|
|
team_id = 13
|
|
elif self.values[0] == 'Minnesota Twins':
|
|
team_id = 17
|
|
elif self.values[0] == 'New York Yankees':
|
|
team_id = 19
|
|
elif self.values[0] == 'Oakland Athletics':
|
|
team_id = 20
|
|
elif self.values[0] == 'Seattle Mariners':
|
|
team_id = 24
|
|
elif self.values[0] == 'Tampa Bay Rays':
|
|
team_id = 27
|
|
elif self.values[0] == 'Texas Rangers':
|
|
team_id = 28
|
|
elif self.values[0] == 'Toronto Blue Jays':
|
|
team_id = 29
|
|
else:
|
|
if self.values[0] == 'Arizona Diamondbacks':
|
|
team_id = 1
|
|
elif self.values[0] == 'Atlanta Braves':
|
|
team_id = 2
|
|
elif self.values[0] == 'Chicago Cubs':
|
|
team_id = 5
|
|
elif self.values[0] == 'Cincinnati Reds':
|
|
team_id = 7
|
|
elif self.values[0] == 'Colorado Rockies':
|
|
team_id = 9
|
|
elif self.values[0] == 'Los Angeles Dodgers':
|
|
team_id = 14
|
|
elif self.values[0] == 'Miami Marlins':
|
|
team_id = 15
|
|
elif self.values[0] == 'Milwaukee Brewers':
|
|
team_id = 16
|
|
elif self.values[0] == 'New York Mets':
|
|
team_id = 18
|
|
elif self.values[0] == 'Philadelphia Phillies':
|
|
team_id = 21
|
|
elif self.values[0] == 'Pittsburgh Pirates':
|
|
team_id = 22
|
|
elif self.values[0] == 'San Diego Padres':
|
|
team_id = 23
|
|
elif self.values[0] == 'San Francisco Giants':
|
|
team_id = 25
|
|
elif self.values[0] == 'St. Louis Cardinals':
|
|
team_id = 26
|
|
elif self.values[0] == 'Washington Nationals':
|
|
team_id = 30
|
|
|
|
await interaction.response.edit_message(content=f'You selected the **{self.values[0]}**', view=None)
|
|
# Get the selected packs
|
|
params = [
|
|
('pack_type_id', 8), ('team_id', self.owner_team['id']), ('opened', False), ('limit', 1),
|
|
('exact_match', True)
|
|
]
|
|
if self.cardset_id is not None:
|
|
params.append(('pack_cardset_id', self.cardset_id))
|
|
p_query = await db_get('packs', params=params)
|
|
if p_query['count'] == 0:
|
|
logger.error(f'open-packs - no packs found with params: {params}')
|
|
raise ValueError(f'Unable to open packs')
|
|
|
|
this_pack = await db_patch('packs', object_id=p_query['packs'][0]['id'], params=[('pack_team_id', team_id)])
|
|
|
|
await open_choice_pack(this_pack, self.owner_team, interaction, self.cardset_id)
|
|
|
|
|
|
class SelectOpenPack(discord.ui.Select):
|
|
def __init__(self, options: list, team: dict):
|
|
self.owner_team = team
|
|
super().__init__(placeholder='Select a Pack Type', options=options)
|
|
|
|
async def callback(self, interaction: discord.Interaction):
|
|
logger.info(f'SelectPackChoice - selection: {self.values[0]}')
|
|
pack_vals = self.values[0].split('-')
|
|
logger.info(f'pack_vals: {pack_vals}')
|
|
|
|
# Get the selected packs
|
|
params = [('team_id', self.owner_team['id']), ('opened', False), ('limit', 5), ('exact_match', True)]
|
|
|
|
open_type = 'standard'
|
|
if 'Standard' in pack_vals:
|
|
open_type = 'standard'
|
|
params.append(('pack_type_id', 1))
|
|
elif 'Premium' in pack_vals:
|
|
open_type = 'standard'
|
|
params.append(('pack_type_id', 3))
|
|
elif 'Daily' in pack_vals:
|
|
params.append(('pack_type_id', 4))
|
|
elif 'Promo Choice' in pack_vals:
|
|
open_type = 'choice'
|
|
params.append(('pack_type_id', 9))
|
|
elif 'MVP' in pack_vals:
|
|
open_type = 'choice'
|
|
params.append(('pack_type_id', 5))
|
|
elif 'All Star' in pack_vals:
|
|
open_type = 'choice'
|
|
params.append(('pack_type_id', 6))
|
|
elif 'Mario' in pack_vals:
|
|
open_type = 'choice'
|
|
params.append(('pack_type_id', 7))
|
|
elif 'Team Choice' in pack_vals:
|
|
open_type = 'choice'
|
|
params.append(('pack_type_id', 8))
|
|
else:
|
|
raise KeyError(f'Cannot identify pack details: {pack_vals}')
|
|
|
|
# If team isn't already set on team choice pack, make team pack selection now
|
|
await interaction.response.edit_message(view=None)
|
|
|
|
cardset_id = None
|
|
if 'Team Choice' in pack_vals and 'Cardset' in pack_vals:
|
|
# cardset_id = pack_vals[2]
|
|
cardset_index = pack_vals.index('Cardset')
|
|
cardset_id = pack_vals[cardset_index + 1]
|
|
params.append(('pack_cardset_id', cardset_id))
|
|
if 'Team' not in pack_vals:
|
|
view = SelectView(
|
|
[SelectChoicePackTeam('AL', self.owner_team, cardset_id),
|
|
SelectChoicePackTeam('NL', self.owner_team, cardset_id)],
|
|
timeout=30
|
|
)
|
|
await interaction.channel.send(
|
|
content=None,
|
|
view=view
|
|
)
|
|
return
|
|
|
|
params.append(('pack_team_id', pack_vals[pack_vals.index('Team') + 1]))
|
|
else:
|
|
if 'Team' in pack_vals:
|
|
params.append(('pack_team_id', pack_vals[pack_vals.index('Team') + 1]))
|
|
if 'Cardset' in pack_vals:
|
|
cardset_id = pack_vals[pack_vals.index('Cardset') + 1]
|
|
params.append(('pack_cardset_id', cardset_id))
|
|
|
|
p_query = await db_get('packs', params=params)
|
|
if p_query['count'] == 0:
|
|
logger.error(f'open-packs - no packs found with params: {params}')
|
|
raise ValueError(f'Unable to open packs')
|
|
|
|
# Open the packs
|
|
if open_type == 'standard':
|
|
await open_st_pr_packs(p_query['packs'], self.owner_team, interaction)
|
|
elif open_type == 'choice':
|
|
await open_choice_pack(p_query['packs'][0], self.owner_team, interaction, cardset_id)
|
|
|
|
|
|
class SelectPaperdexCardset(discord.ui.Select):
|
|
def __init__(self):
|
|
options = [
|
|
discord.SelectOption(label='2025 Live'),
|
|
discord.SelectOption(label='1998 Season'),
|
|
discord.SelectOption(label='2024 Season'),
|
|
discord.SelectOption(label='2023 Season'),
|
|
discord.SelectOption(label='2022 Season'),
|
|
discord.SelectOption(label='2022 Promos'),
|
|
discord.SelectOption(label='2021 Season'),
|
|
discord.SelectOption(label='2019 Season'),
|
|
discord.SelectOption(label='2018 Season'),
|
|
discord.SelectOption(label='2016 Season'),
|
|
discord.SelectOption(label='2013 Season'),
|
|
discord.SelectOption(label='2012 Season'),
|
|
discord.SelectOption(label='2008 Season'),
|
|
discord.SelectOption(label='Mario Super Sluggers')
|
|
]
|
|
super().__init__(placeholder='Select a Cardset', options=options)
|
|
|
|
async def callback(self, interaction: discord.Interaction):
|
|
logger.info(f'SelectPaperdexCardset - selection: {self.values[0]}')
|
|
cardset_id = None
|
|
if self.values[0] == '2022 Season':
|
|
cardset_id = 3
|
|
elif self.values[0] == '2022 Promos':
|
|
cardset_id = 4
|
|
elif self.values[0] == '2021 Season':
|
|
cardset_id = 1
|
|
elif self.values[0] == '2019 Season':
|
|
cardset_id = 5
|
|
elif self.values[0] == '2013 Season':
|
|
cardset_id = 6
|
|
elif self.values[0] == '2012 Season':
|
|
cardset_id = 7
|
|
elif self.values[0] == 'Mario Super Sluggers':
|
|
cardset_id = 8
|
|
elif self.values[0] == '2023 Season':
|
|
cardset_id = 9
|
|
elif self.values[0] == '2016 Season':
|
|
cardset_id = 11
|
|
elif self.values[0] == '2008 Season':
|
|
cardset_id = 12
|
|
elif self.values[0] == '2018 Season':
|
|
cardset_id = 13
|
|
elif self.values[0] == '2024 Season':
|
|
cardset_id = 17
|
|
elif self.values[0] == '2024 Promos':
|
|
cardset_id = 18
|
|
elif self.values[0] == '1998 Season':
|
|
cardset_id = 20
|
|
elif self.values[0] == '2025 Live':
|
|
cardset_id = 24
|
|
|
|
c_query = await db_get('cardsets', object_id=cardset_id, none_okay=False)
|
|
await interaction.response.edit_message(content=f'Okay, sifting through your cards...', view=None)
|
|
|
|
cardset_embeds = await paperdex_cardset_embed(
|
|
team=await get_team_by_owner(interaction.user.id),
|
|
this_cardset=c_query
|
|
)
|
|
await embed_pagination(cardset_embeds, interaction.channel, interaction.user)
|
|
|
|
|
|
class SelectPaperdexTeam(discord.ui.Select):
|
|
def __init__(self, which: Literal['AL', 'NL']):
|
|
self.which = which
|
|
if which == 'AL':
|
|
options = [
|
|
discord.SelectOption(label='Baltimore Orioles'),
|
|
discord.SelectOption(label='Boston Red Sox'),
|
|
discord.SelectOption(label='Chicago White Sox'),
|
|
discord.SelectOption(label='Cleveland Guardians'),
|
|
discord.SelectOption(label='Detroit Tigers'),
|
|
discord.SelectOption(label='Houston Astros'),
|
|
discord.SelectOption(label='Kansas City Royals'),
|
|
discord.SelectOption(label='Los Angeles Angels'),
|
|
discord.SelectOption(label='Minnesota Twins'),
|
|
discord.SelectOption(label='New York Yankees'),
|
|
discord.SelectOption(label='Oakland Athletics'),
|
|
discord.SelectOption(label='Seattle Mariners'),
|
|
discord.SelectOption(label='Tampa Bay Rays'),
|
|
discord.SelectOption(label='Texas Rangers'),
|
|
discord.SelectOption(label='Toronto Blue Jays')
|
|
]
|
|
else:
|
|
options = [
|
|
discord.SelectOption(label='Arizona Diamondbacks'),
|
|
discord.SelectOption(label='Atlanta Braves'),
|
|
discord.SelectOption(label='Chicago Cubs'),
|
|
discord.SelectOption(label='Cincinnati Reds'),
|
|
discord.SelectOption(label='Colorado Rockies'),
|
|
discord.SelectOption(label='Los Angeles Dodgers'),
|
|
discord.SelectOption(label='Miami Marlins'),
|
|
discord.SelectOption(label='Milwaukee Brewers'),
|
|
discord.SelectOption(label='New York Mets'),
|
|
discord.SelectOption(label='Philadelphia Phillies'),
|
|
discord.SelectOption(label='Pittsburgh Pirates'),
|
|
discord.SelectOption(label='San Diego Padres'),
|
|
discord.SelectOption(label='San Francisco Giants'),
|
|
discord.SelectOption(label='St. Louis Cardinals'),
|
|
discord.SelectOption(label='Washington Nationals')
|
|
]
|
|
super().__init__(placeholder=f'Select an {which} team', options=options)
|
|
|
|
async def callback(self, interaction: discord.Interaction):
|
|
team_id = None
|
|
if self.which == 'AL':
|
|
if self.values[0] == 'Baltimore Orioles':
|
|
team_id = 3
|
|
elif self.values[0] == 'Boston Red Sox':
|
|
team_id = 4
|
|
elif self.values[0] == 'Chicago White Sox':
|
|
team_id = 6
|
|
elif self.values[0] == 'Cleveland Guardians':
|
|
team_id = 8
|
|
elif self.values[0] == 'Detroit Tigers':
|
|
team_id = 10
|
|
elif self.values[0] == 'Houston Astros':
|
|
team_id = 11
|
|
elif self.values[0] == 'Kansas City Royals':
|
|
team_id = 12
|
|
elif self.values[0] == 'Los Angeles Angels':
|
|
team_id = 13
|
|
elif self.values[0] == 'Minnesota Twins':
|
|
team_id = 17
|
|
elif self.values[0] == 'New York Yankees':
|
|
team_id = 19
|
|
elif self.values[0] == 'Oakland Athletics':
|
|
team_id = 20
|
|
elif self.values[0] == 'Seattle Mariners':
|
|
team_id = 24
|
|
elif self.values[0] == 'Tampa Bay Rays':
|
|
team_id = 27
|
|
elif self.values[0] == 'Texas Rangers':
|
|
team_id = 28
|
|
elif self.values[0] == 'Toronto Blue Jays':
|
|
team_id = 29
|
|
else:
|
|
if self.values[0] == 'Arizona Diamondbacks':
|
|
team_id = 1
|
|
elif self.values[0] == 'Atlanta Braves':
|
|
team_id = 2
|
|
elif self.values[0] == 'Chicago Cubs':
|
|
team_id = 5
|
|
elif self.values[0] == 'Cincinnati Reds':
|
|
team_id = 7
|
|
elif self.values[0] == 'Colorado Rockies':
|
|
team_id = 9
|
|
elif self.values[0] == 'Los Angeles Dodgers':
|
|
team_id = 14
|
|
elif self.values[0] == 'Miami Marlins':
|
|
team_id = 15
|
|
elif self.values[0] == 'Milwaukee Brewers':
|
|
team_id = 16
|
|
elif self.values[0] == 'New York Mets':
|
|
team_id = 18
|
|
elif self.values[0] == 'Philadelphia Phillies':
|
|
team_id = 21
|
|
elif self.values[0] == 'Pittsburgh Pirates':
|
|
team_id = 22
|
|
elif self.values[0] == 'San Diego Padres':
|
|
team_id = 23
|
|
elif self.values[0] == 'San Francisco Giants':
|
|
team_id = 25
|
|
elif self.values[0] == 'St. Louis Cardinals':
|
|
team_id = 26
|
|
elif self.values[0] == 'Washington Nationals':
|
|
team_id = 30
|
|
|
|
t_query = await db_get('teams', object_id=team_id, none_okay=False)
|
|
await interaction.response.edit_message(content=f'Okay, sifting through your cards...', view=None)
|
|
|
|
team_embeds = await paperdex_team_embed(team=await get_team_by_owner(interaction.user.id), mlb_team=t_query)
|
|
await embed_pagination(team_embeds, interaction.channel, interaction.user)
|
|
|
|
|
|
class SelectBuyPacksCardset(discord.ui.Select):
|
|
def __init__(self, team: dict, quantity: int, pack_type_id: int, pack_embed: discord.Embed, cost: int):
|
|
options = [
|
|
discord.SelectOption(label='2025 Live'),
|
|
discord.SelectOption(label='1998 Season'),
|
|
discord.SelectOption(label='Pokemon - Brilliant Stars'),
|
|
discord.SelectOption(label='2024 Season'),
|
|
discord.SelectOption(label='2023 Season'),
|
|
discord.SelectOption(label='2022 Season'),
|
|
discord.SelectOption(label='2021 Season'),
|
|
discord.SelectOption(label='2019 Season'),
|
|
discord.SelectOption(label='2018 Season'),
|
|
discord.SelectOption(label='2016 Season'),
|
|
discord.SelectOption(label='2013 Season'),
|
|
discord.SelectOption(label='2012 Season'),
|
|
discord.SelectOption(label='2008 Season')
|
|
]
|
|
self.team = team
|
|
self.quantity = quantity
|
|
self.pack_type_id = pack_type_id
|
|
self.pack_embed = pack_embed
|
|
self.cost = cost
|
|
super().__init__(placeholder='Select a Cardset', options=options)
|
|
|
|
async def callback(self, interaction: discord.Interaction):
|
|
logger.info(f'SelectBuyPacksCardset - selection: {self.values[0]}')
|
|
cardset_id = None
|
|
if self.values[0] == '2022 Season':
|
|
cardset_id = 3
|
|
elif self.values[0] == '2021 Season':
|
|
cardset_id = 1
|
|
elif self.values[0] == '2019 Season':
|
|
cardset_id = 5
|
|
elif self.values[0] == '2013 Season':
|
|
cardset_id = 6
|
|
elif self.values[0] == '2012 Season':
|
|
cardset_id = 7
|
|
elif self.values[0] == '2023 Season':
|
|
cardset_id = 9
|
|
elif self.values[0] == '2016 Season':
|
|
cardset_id = 11
|
|
elif self.values[0] == '2008 Season':
|
|
cardset_id = 12
|
|
elif self.values[0] == '2018 Season':
|
|
cardset_id = 13
|
|
elif self.values[0] == '2024 Season':
|
|
cardset_id = 17
|
|
elif self.values[0] == '1998 Season':
|
|
cardset_id = 20
|
|
elif self.values[0] == '2025 Live':
|
|
cardset_id = 24
|
|
elif self.values[0] == 'Pokemon - Brilliant Stars':
|
|
cardset_id = 23
|
|
self.pack_embed.set_image(url=IMAGES['pack-pkmnbs'])
|
|
|
|
self.pack_embed.description = f'{self.pack_embed.description} - {self.values[0]}'
|
|
view = Confirm(responders=[interaction.user], timeout=30)
|
|
await interaction.response.edit_message(
|
|
content=None,
|
|
embed=self.pack_embed,
|
|
view=None
|
|
)
|
|
question = await interaction.channel.send(
|
|
content=f'Your Wallet: {self.team["wallet"]}₼\n'
|
|
f'Pack{"s" if self.quantity > 1 else ""} Price: {self.cost}₼\n'
|
|
f'After Purchase: {self.team["wallet"] - self.cost}₼\n\n'
|
|
f'Would you like to make this purchase?',
|
|
view=view
|
|
)
|
|
await view.wait()
|
|
|
|
if not view.value:
|
|
await question.edit(
|
|
content='Saving that money. Smart.',
|
|
view=None
|
|
)
|
|
return
|
|
|
|
p_model = {
|
|
'team_id': self.team['id'],
|
|
'pack_type_id': self.pack_type_id,
|
|
'pack_cardset_id': cardset_id
|
|
}
|
|
await db_post('packs', payload={'packs': [p_model for x in range(self.quantity)]})
|
|
await db_post(f'teams/{self.team["id"]}/money/-{self.cost}')
|
|
|
|
await question.edit(
|
|
content=f'{"They are" if self.quantity > 1 else "It is"} all yours! Go rip \'em with `/open-packs`',
|
|
view=None
|
|
)
|
|
|
|
|
|
class SelectBuyPacksTeam(discord.ui.Select):
|
|
def __init__(
|
|
self, which: Literal['AL', 'NL'], team: dict, quantity: int, pack_type_id: int, pack_embed: discord.Embed,
|
|
cost: int):
|
|
self.which = which
|
|
self.team = team
|
|
self.quantity = quantity
|
|
self.pack_type_id = pack_type_id
|
|
self.pack_embed = pack_embed
|
|
self.cost = cost
|
|
if which == 'AL':
|
|
options = [
|
|
discord.SelectOption(label='Baltimore Orioles'),
|
|
discord.SelectOption(label='Boston Red Sox'),
|
|
discord.SelectOption(label='Chicago White Sox'),
|
|
discord.SelectOption(label='Cleveland Guardians'),
|
|
discord.SelectOption(label='Detroit Tigers'),
|
|
discord.SelectOption(label='Houston Astros'),
|
|
discord.SelectOption(label='Kansas City Royals'),
|
|
discord.SelectOption(label='Los Angeles Angels'),
|
|
discord.SelectOption(label='Minnesota Twins'),
|
|
discord.SelectOption(label='New York Yankees'),
|
|
discord.SelectOption(label='Oakland Athletics'),
|
|
discord.SelectOption(label='Seattle Mariners'),
|
|
discord.SelectOption(label='Tampa Bay Rays'),
|
|
discord.SelectOption(label='Texas Rangers'),
|
|
discord.SelectOption(label='Toronto Blue Jays')
|
|
]
|
|
else:
|
|
options = [
|
|
discord.SelectOption(label='Arizona Diamondbacks'),
|
|
discord.SelectOption(label='Atlanta Braves'),
|
|
discord.SelectOption(label='Chicago Cubs'),
|
|
discord.SelectOption(label='Cincinnati Reds'),
|
|
discord.SelectOption(label='Colorado Rockies'),
|
|
discord.SelectOption(label='Los Angeles Dodgers'),
|
|
discord.SelectOption(label='Miami Marlins'),
|
|
discord.SelectOption(label='Milwaukee Brewers'),
|
|
discord.SelectOption(label='New York Mets'),
|
|
discord.SelectOption(label='Philadelphia Phillies'),
|
|
discord.SelectOption(label='Pittsburgh Pirates'),
|
|
discord.SelectOption(label='San Diego Padres'),
|
|
discord.SelectOption(label='San Francisco Giants'),
|
|
discord.SelectOption(label='St. Louis Cardinals'),
|
|
discord.SelectOption(label='Washington Nationals')
|
|
]
|
|
super().__init__(placeholder=f'Select an {which} team', options=options)
|
|
|
|
async def callback(self, interaction: discord.Interaction):
|
|
team_id = None
|
|
if self.which == 'AL':
|
|
if self.values[0] == 'Baltimore Orioles':
|
|
team_id = 3
|
|
elif self.values[0] == 'Boston Red Sox':
|
|
team_id = 4
|
|
elif self.values[0] == 'Chicago White Sox':
|
|
team_id = 6
|
|
elif self.values[0] == 'Cleveland Guardians':
|
|
team_id = 8
|
|
elif self.values[0] == 'Detroit Tigers':
|
|
team_id = 10
|
|
elif self.values[0] == 'Houston Astros':
|
|
team_id = 11
|
|
elif self.values[0] == 'Kansas City Royals':
|
|
team_id = 12
|
|
elif self.values[0] == 'Los Angeles Angels':
|
|
team_id = 13
|
|
elif self.values[0] == 'Minnesota Twins':
|
|
team_id = 17
|
|
elif self.values[0] == 'New York Yankees':
|
|
team_id = 19
|
|
elif self.values[0] == 'Oakland Athletics':
|
|
team_id = 20
|
|
elif self.values[0] == 'Seattle Mariners':
|
|
team_id = 24
|
|
elif self.values[0] == 'Tampa Bay Rays':
|
|
team_id = 27
|
|
elif self.values[0] == 'Texas Rangers':
|
|
team_id = 28
|
|
elif self.values[0] == 'Toronto Blue Jays':
|
|
team_id = 29
|
|
else:
|
|
if self.values[0] == 'Arizona Diamondbacks':
|
|
team_id = 1
|
|
elif self.values[0] == 'Atlanta Braves':
|
|
team_id = 2
|
|
elif self.values[0] == 'Chicago Cubs':
|
|
team_id = 5
|
|
elif self.values[0] == 'Cincinnati Reds':
|
|
team_id = 7
|
|
elif self.values[0] == 'Colorado Rockies':
|
|
team_id = 9
|
|
elif self.values[0] == 'Los Angeles Dodgers':
|
|
team_id = 14
|
|
elif self.values[0] == 'Miami Marlins':
|
|
team_id = 15
|
|
elif self.values[0] == 'Milwaukee Brewers':
|
|
team_id = 16
|
|
elif self.values[0] == 'New York Mets':
|
|
team_id = 18
|
|
elif self.values[0] == 'Philadelphia Phillies':
|
|
team_id = 21
|
|
elif self.values[0] == 'Pittsburgh Pirates':
|
|
team_id = 22
|
|
elif self.values[0] == 'San Diego Padres':
|
|
team_id = 23
|
|
elif self.values[0] == 'San Francisco Giants':
|
|
team_id = 25
|
|
elif self.values[0] == 'St. Louis Cardinals':
|
|
team_id = 26
|
|
elif self.values[0] == 'Washington Nationals':
|
|
team_id = 30
|
|
|
|
self.pack_embed.description = f'{self.pack_embed.description} - {self.values[0]}'
|
|
view = Confirm(responders=[interaction.user], timeout=30)
|
|
await interaction.response.edit_message(
|
|
content=None,
|
|
embed=self.pack_embed,
|
|
view=None
|
|
)
|
|
question = await interaction.channel.send(
|
|
content=f'Your Wallet: {self.team["wallet"]}₼\n'
|
|
f'Pack{"s" if self.quantity > 1 else ""} Price: {self.cost}₼\n'
|
|
f'After Purchase: {self.team["wallet"] - self.cost}₼\n\n'
|
|
f'Would you like to make this purchase?',
|
|
view=view
|
|
)
|
|
await view.wait()
|
|
|
|
if not view.value:
|
|
await question.edit(
|
|
content='Saving that money. Smart.',
|
|
view=None
|
|
)
|
|
return
|
|
|
|
p_model = {
|
|
'team_id': self.team['id'],
|
|
'pack_type_id': self.pack_type_id,
|
|
'pack_team_id': team_id
|
|
}
|
|
await db_post('packs', payload={'packs': [p_model for x in range(self.quantity)]})
|
|
await db_post(f'teams/{self.team["id"]}/money/-{self.cost}')
|
|
|
|
await question.edit(
|
|
content=f'{"They are" if self.quantity > 1 else "It is"} all yours! Go rip \'em with `/open-packs`',
|
|
view=None
|
|
)
|
|
|
|
|
|
class SelectUpdatePlayerTeam(discord.ui.Select):
|
|
def __init__(self, which: Literal['AL', 'NL'], player: dict, reporting_team: dict, bot):
|
|
self.bot = bot
|
|
self.which = which
|
|
self.player = player
|
|
self.reporting_team = reporting_team
|
|
if which == 'AL':
|
|
options = [
|
|
discord.SelectOption(label='Baltimore Orioles'),
|
|
discord.SelectOption(label='Boston Red Sox'),
|
|
discord.SelectOption(label='Chicago White Sox'),
|
|
discord.SelectOption(label='Cleveland Guardians'),
|
|
discord.SelectOption(label='Detroit Tigers'),
|
|
discord.SelectOption(label='Houston Astros'),
|
|
discord.SelectOption(label='Kansas City Royals'),
|
|
discord.SelectOption(label='Los Angeles Angels'),
|
|
discord.SelectOption(label='Minnesota Twins'),
|
|
discord.SelectOption(label='New York Yankees'),
|
|
discord.SelectOption(label='Oakland Athletics'),
|
|
discord.SelectOption(label='Seattle Mariners'),
|
|
discord.SelectOption(label='Tampa Bay Rays'),
|
|
discord.SelectOption(label='Texas Rangers'),
|
|
discord.SelectOption(label='Toronto Blue Jays')
|
|
]
|
|
else:
|
|
options = [
|
|
discord.SelectOption(label='Arizona Diamondbacks'),
|
|
discord.SelectOption(label='Atlanta Braves'),
|
|
discord.SelectOption(label='Chicago Cubs'),
|
|
discord.SelectOption(label='Cincinnati Reds'),
|
|
discord.SelectOption(label='Colorado Rockies'),
|
|
discord.SelectOption(label='Los Angeles Dodgers'),
|
|
discord.SelectOption(label='Miami Marlins'),
|
|
discord.SelectOption(label='Milwaukee Brewers'),
|
|
discord.SelectOption(label='New York Mets'),
|
|
discord.SelectOption(label='Philadelphia Phillies'),
|
|
discord.SelectOption(label='Pittsburgh Pirates'),
|
|
discord.SelectOption(label='San Diego Padres'),
|
|
discord.SelectOption(label='San Francisco Giants'),
|
|
discord.SelectOption(label='St. Louis Cardinals'),
|
|
discord.SelectOption(label='Washington Nationals')
|
|
]
|
|
super().__init__(placeholder=f'Select an {which} team', options=options)
|
|
|
|
async def callback(self, interaction: discord.Interaction):
|
|
if self.values[0] == self.player['franchise'] or self.values[0] == self.player['mlbclub']:
|
|
await interaction.response.send_message(
|
|
content=f'Thank you for the help, but it looks like somebody beat you to it! '
|
|
f'**{player_desc(self.player)}** is already assigned to the **{self.player["mlbclub"]}**.'
|
|
)
|
|
return
|
|
|
|
view = Confirm(responders=[interaction.user], timeout=15)
|
|
await interaction.response.edit_message(
|
|
content=f'Should I update **{player_desc(self.player)}**\'s team to the **{self.values[0]}**?',
|
|
view=None
|
|
)
|
|
question = await interaction.channel.send(
|
|
content=None,
|
|
view=view
|
|
)
|
|
await view.wait()
|
|
|
|
if not view.value:
|
|
await question.edit(
|
|
content='That didnt\'t sound right to me, either. Let\'s not touch that.',
|
|
view=None
|
|
)
|
|
return
|
|
else:
|
|
await question.delete()
|
|
|
|
await db_patch('players', object_id=self.player['player_id'], params=[
|
|
('mlbclub', self.values[0]), ('franchise', self.values[0])
|
|
])
|
|
await db_post(f'teams/{self.reporting_team["id"]}/money/25')
|
|
await send_to_channel(
|
|
self.bot, 'pd-news-ticker',
|
|
content=f'{interaction.user.name} just updated **{player_desc(self.player)}**\'s team to the '
|
|
f'**{self.values[0]}**'
|
|
)
|
|
await interaction.channel.send(f'All done!')
|
|
|
|
|
|
class SelectView(discord.ui.View):
|
|
def __init__(self, select_objects: list[discord.ui.Select], timeout: float = 300.0):
|
|
super().__init__(timeout=timeout)
|
|
|
|
for x in select_objects:
|
|
self.add_item(x)
|
|
|
|
|
|
class Dropdown(discord.ui.Select):
|
|
def __init__(self, option_list: list, placeholder: str = 'Make your selection', min_values: int = 1,
|
|
max_values: int = 1, callback=None):
|
|
# Set the options that will be presented inside the dropdown
|
|
# options = [
|
|
# discord.SelectOption(label='Red', description='Your favourite colour is red', emoji='🟥'),
|
|
# discord.SelectOption(label='Green', description='Your favourite colour is green', emoji='🟩'),
|
|
# discord.SelectOption(label='Blue', description='Your favourite colour is blue', emoji='🟦'),
|
|
# ]
|
|
|
|
# The placeholder is what will be shown when no option is chosen
|
|
# The min and max values indicate we can only pick one of the three options
|
|
# The options parameter defines the dropdown options. We defined this above
|
|
|
|
# If a default option is set on any SelectOption, the View will not process if only the default is
|
|
# selected by the user
|
|
self.custom_callback = callback
|
|
super().__init__(
|
|
placeholder=placeholder,
|
|
min_values=min_values,
|
|
max_values=max_values,
|
|
options=option_list
|
|
)
|
|
|
|
async def callback(self, interaction: discord.Interaction):
|
|
# Use the interaction object to send a response message containing
|
|
# the user's favourite colour or choice. The self object refers to the
|
|
# Select object, and the values attribute gets a list of the user's
|
|
# selected options. We only want the first one.
|
|
# await interaction.response.send_message(f'Your favourite colour is {self.values[0]}')
|
|
logger.info(f'Dropdown callback: {self.custom_callback}')
|
|
await self.custom_callback(interaction, self.values)
|
|
|
|
|
|
class DropdownView(discord.ui.View):
|
|
def __init__(self, dropdown_objects: list[Dropdown], timeout: float = 300.0):
|
|
super().__init__(timeout=timeout)
|
|
|
|
# self.add_item(Dropdown())
|
|
for x in dropdown_objects:
|
|
self.add_item(x)
|
|
|
|
|
|
def random_conf_gif():
|
|
conf_gifs = [
|
|
'https://tenor.com/view/boom-annakendrick-pitchperfect-pitchperfect2-micdrop-gif-5143507',
|
|
'https://tenor.com/view/boom-annakendrick-pitchperfect-pitchperfect2-micdrop-gif-5143507',
|
|
'https://tenor.com/view/boom-annakendrick-pitchperfect-pitchperfect2-micdrop-gif-5143507',
|
|
'https://tenor.com/view/explosion-boom-iron-man-gif-14282225',
|
|
'https://tenor.com/view/betty-white-dab-consider-it-done-gif-11972415',
|
|
'https://tenor.com/view/done-and-done-spongebob-finished-just-did-it-gif-10843280',
|
|
'https://tenor.com/view/thumbs-up-okay-ok-well-done-gif-13840394',
|
|
'https://tenor.com/view/tinkerbell-peter-pan-all-done-gif-15003723',
|
|
'https://tenor.com/view/done-and-done-ron-swanson-gotchu-gif-10843254',
|
|
'https://tenor.com/view/sponge-bob-thumbs-up-ok-smile-gif-12038157',
|
|
'https://tenor.com/view/thumbs-up-cool-okay-bye-gif-8633196',
|
|
'https://i0.wp.com/media1.giphy.com/media/iwvuPyfi7z14I/giphy.gif',
|
|
'https://media1.tenor.com/images/859a2d3b201fbacec13904242976b9e0/tenor.gif',
|
|
'https://tenor.com/bc1OJ.gif',
|
|
'https://tenor.com/1EmF.gif',
|
|
'https://tenor.com/ZYCh.gif',
|
|
'https://tenor.com/patd.gif',
|
|
'https://tenor.com/u6mU.gif',
|
|
'https://tenor.com/x2sa.gif',
|
|
'https://tenor.com/bAVeS.gif',
|
|
'https://tenor.com/bxOcj.gif',
|
|
'https://tenor.com/ETJ7.gif',
|
|
'https://tenor.com/bpH3g.gif',
|
|
'https://tenor.com/biF9q.gif',
|
|
'https://tenor.com/OySS.gif',
|
|
'https://tenor.com/bvVFv.gif',
|
|
'https://tenor.com/bFeqA.gif'
|
|
]
|
|
return conf_gifs[random.randint(0, len(conf_gifs) - 1)]
|
|
|
|
|
|
def random_no_gif():
|
|
no_gifs = [
|
|
'https://tenor.com/view/youre-not-my-dad-dean-jensen-ackles-supernatural-you-arent-my-dad-gif-19503399',
|
|
'https://tenor.com/view/youre-not-my-dad-kid-gif-8300190',
|
|
'https://tenor.com/view/youre-not-my-supervisor-youre-not-my-boss-gif-12971403',
|
|
'https://tenor.com/view/dont-tell-me-what-to-do-gif-4951202'
|
|
]
|
|
return no_gifs[random.randint(0, len(no_gifs) - 1)]
|
|
|
|
|
|
def random_salute_gif():
|
|
salute_gifs = [
|
|
'https://media.giphy.com/media/fSAyceY3BCgtiQGnJs/giphy.gif',
|
|
'https://media.giphy.com/media/bsWDUSFUmJCOk/giphy.gif',
|
|
'https://media.giphy.com/media/hStvd5LiWCFzYNyxR4/giphy.gif',
|
|
'https://media.giphy.com/media/RhSR5xXDsXJ7jbnrRW/giphy.gif',
|
|
'https://media.giphy.com/media/lNQvrlPdbmZUU2wlh9/giphy.gif',
|
|
'https://gfycat.com/skeletaldependableandeancat',
|
|
'https://i.gifer.com/5EJk.gif',
|
|
'https://tenor.com/baJUV.gif',
|
|
'https://tenor.com/bdnQH.gif',
|
|
'https://tenor.com/bikQU.gif',
|
|
'https://i.pinimg.com/originals/04/36/bf/0436bfc9861b4b57ffffda82d3adad6e.gif',
|
|
'https://media.giphy.com/media/6RtOG4Q7v34kw/giphy.gif',
|
|
'https://keyassets-p2.timeincuk.net/wp/prod/wp-content/uploads/sites/42/2017/04/anigif_'
|
|
'enhanced-946-1433453114-7.gif',
|
|
'https://keyassets-p2.timeincuk.net/wp/prod/wp-content/uploads/sites/42/2017/04/100c5d677cc28ea3f15'
|
|
'4c70d641f655b_meme-crying-gif-crying-gif-meme_620-340.gif',
|
|
'https://media.giphy.com/media/fnKd6rCHaZoGdzLjjA/giphy.gif',
|
|
'https://media.giphy.com/media/47D5jmVc4f7ylygXYD/giphy.gif',
|
|
'https://media.giphy.com/media/I4wGMXoi2kMDe/giphy.gif',
|
|
]
|
|
return salute_gifs[random.randint(0, len(salute_gifs) - 1)]
|
|
|
|
|
|
def random_conf_word():
|
|
conf_words = [
|
|
'dope',
|
|
'cool',
|
|
'got it',
|
|
'noice',
|
|
'ok',
|
|
'lit',
|
|
]
|
|
return conf_words[random.randint(0, len(conf_words) - 1)]
|
|
|
|
|
|
def random_codename():
|
|
all_names = [
|
|
'Shong', 'DerekSux', 'JoeSux', 'CalSux', 'Friend', 'Andrea', 'Ent', 'Lindved', 'Camp', 'Idyll', 'Elaphus',
|
|
'Turki', 'Shrimp', 'Primary', 'Anglica', 'Shail', 'Blanket', 'Baffled', 'Deer', 'Thisted', 'Brisk', 'Shy',
|
|
'Table', 'Jorts', 'Renati', 'Gisky', 'Prig', 'Bathtub', 'Gallery', 'Mavas', 'Chird', 'Oxyura', 'Mydal', 'Brown',
|
|
'Vasen', 'Worthy', 'Bivver', 'Cirlus', 'Self', 'Len', 'Sharp', 'Dart', 'Crepis', 'Ferina', 'Curl', 'Lancome',
|
|
'Stuff', 'Glove', 'Consist', 'Smig', 'Egg', 'Pleat', 'Picture', 'Spin', 'Ridgty', 'Ickled', 'Abashed', 'Haul',
|
|
'Cordage', 'Chivery', 'Stointy', 'Baa', 'Here', 'Ulmi', 'Tour', 'Tribe', 'Crunch', 'Used', 'Pigface', 'Audit',
|
|
'Written', 'Once', 'Fickle', 'Drugged', 'Swarm', 'Blimber', 'Torso', 'Retusa', 'Hockey', 'Pusty', 'Sallow',
|
|
'Next', 'Mansion', 'Glass', 'Screen', 'Josiah', 'Bonkey', 'Stuff', 'Sane', 'Blooded', 'Gnat', 'Liparis',
|
|
'Ocean', 'Sway', 'Roband', 'Still', 'Ribba', 'Biryani', 'Halibut', 'Flyn', 'Until', 'Depend', 'Intel',
|
|
'Affinis', 'Chef', 'Trounce', 'Crawl', 'Grab', 'Eggs', 'Malfroy', 'Sitta', 'Cretin', 'May', 'Smithii',
|
|
'Saffron', 'Crummy', 'Powered', 'Rail', 'Trait', 'Koiled', 'Bronze', 'Quickly', 'Vikis', 'Trift', 'Jubilar',
|
|
'Deft', 'Juncus', 'Sodding', 'Distant', 'Poecile', 'Pipe', 'Sell', 'Inops', 'Peusi', 'Sparrow', 'Yams',
|
|
'Kidneys', 'Artery', 'Vuffin', 'Boink', 'Bos', 'Notable', 'Alba', 'Spurge', 'Ruby', 'Cilia', 'Pellow', 'Nox',
|
|
'Woozy', 'Semvik', 'Tyda', 'Season', 'Lychnis', 'Ibestad', 'Bagge', 'Marked', 'Browdie', 'Fisher', 'Tilly',
|
|
'Troll', 'Gypsy', 'Thisted', 'Flirt', 'Stop', 'Radiate', 'Poop', 'Plenty', 'Jeff', 'Magpie', 'Roof', 'Ent',
|
|
'Dumbo', 'Pride', 'Weights', 'Winted', 'Dolden', 'Meotica', 'Yikes', 'Teeny', 'Fizz', 'Eide', 'Foetida',
|
|
'Crash', 'Mann', 'Salong', 'Cetti', 'Balloon', 'Petite', 'Find', 'Sputter', 'Patula', 'Upstage', 'Aurora',
|
|
'Dadson', 'Drate', 'Heidal', 'Robin', 'Auditor', 'Ithil', 'Warmen', 'Pat', 'Muppet', '007', 'Advantage',
|
|
'Alert', 'Backhander', 'Badass', 'Blade', 'Blaze', 'Blockade', 'Blockbuster', 'Boxer', 'Brimstone', 'Broadway',
|
|
'Buccaneer', 'Champion', 'Cliffhanger', 'Coachman', 'Comet', 'Commander', 'Courier', 'Cowboy', 'Crawler',
|
|
'Crossroads', 'DeepSpace', 'Desperado', 'Double-Decker', 'Echelon', 'Edge', 'Encore', 'EnRoute', 'Escape',
|
|
'Eureka', 'Evangelist', 'Excursion', 'Explorer', 'Fantastic', 'Firefight', 'Foray', 'Forge', 'Freeway',
|
|
'Frontier', 'FunMachine', 'Galaxy', 'GameOver', 'Genesis', 'Hacker', 'Hawkeye', 'Haybailer', 'Haystack',
|
|
'Hexagon', 'Hitman', 'Hustler', 'Iceberg', 'Impossible', 'Impulse', 'Invader', 'Inventor', 'IronWolf',
|
|
'Jackrabbit', 'Juniper', 'Keyhole', 'Lancelot', 'Liftoff', 'MadHatter', 'Magnum', 'Majestic', 'Merlin',
|
|
'Multiplier', 'Netiquette', 'Nomad', 'Octagon', 'Offense', 'OliveBranch', 'OlympicTorch', 'Omega', 'Onyx',
|
|
'Orbit', 'OuterSpace', 'Outlaw', 'Patron', 'Patriot', 'Pegasus', 'Pentagon', 'Pilgrim', 'Pinball', 'Pinnacle',
|
|
'Pipeline', 'Pirate', 'Portal', 'Predator', 'Prism', 'RagingBull', 'Ragtime', 'Reunion', 'Ricochet',
|
|
'Roadrunner', 'Rockstar', 'RobinHood', 'Rover', 'Runabout', 'Sapphire', 'Scrappy', 'Seige', 'Shadow',
|
|
'Shakedown', 'Shockwave', 'Shooter', 'Showdown', 'SixPack', 'SlamDunk', 'Slasher', 'Sledgehammer', 'Spirit',
|
|
'Spotlight', 'Starlight', 'Steamroller', 'Stride', 'Sunrise', 'Superhuman', 'Supernova', 'SuperBowl', 'Sunset',
|
|
'Sweetheart', 'TopHand', 'Touchdown', 'Tour', 'Trailblazer', 'Transit', 'Trekker', 'Trio', 'TriplePlay',
|
|
'TripleThreat', 'Universe', 'Unstoppable', 'Utopia', 'Vicinity', 'Vector', 'Vigilance', 'Vigilante', 'Vista',
|
|
'Visage', 'Vis-à-vis', 'VIP', 'Volcano', 'Volley', 'Whizzler', 'Wingman', 'Badger', 'BlackCat', 'Bobcat',
|
|
'Caracal', 'Cheetah', 'Cougar', 'Jaguar', 'Leopard', 'Lion', 'Lynx', 'MountainLion', 'Ocelot', 'Panther',
|
|
'Puma', 'Siamese', 'Serval', 'Tiger', 'Wolverine', 'Abispa', 'Andrena', 'BlackWidow', 'Cataglyphis',
|
|
'Centipede', 'Cephalotes', 'Formica', 'Hornet', 'Jellyfish', 'Scorpion', 'Tarantula', 'Yellowjacket', 'Wasp',
|
|
'Apollo', 'Ares', 'Artemis', 'Athena', 'Hercules', 'Hermes', 'Iris', 'Medusa', 'Nemesis', 'Neptune', 'Perseus',
|
|
'Poseidon', 'Triton', 'Zeus', 'Aquarius', 'Aries', 'Cancer', 'Capricorn', 'Gemini', 'Libra', 'Leo', 'Pisces',
|
|
'Sagittarius', 'Scorpio', 'Taurus', 'Virgo', 'Andromeda', 'Aquila', 'Cassiopeia', 'Cepheus', 'Cygnus',
|
|
'Delphinus', 'Drako', 'Lyra', 'Orion', 'Perseus', 'Serpens', 'Triangulum', 'Anaconda', 'Boa', 'Cobra',
|
|
'Copperhead', 'Cottonmouth', 'Garter', 'Kingsnake', 'Mamba', 'Python', 'Rattler', 'Sidewinder', 'Taipan',
|
|
'Viper', 'Alligator', 'Barracuda', 'Crocodile', 'Gator', 'GreatWhite', 'Hammerhead', 'Jaws', 'Lionfish',
|
|
'Mako', 'Moray', 'Orca', 'Piranha', 'Shark', 'Stingray', 'Axe', 'BattleAxe', 'Bayonet', 'Blade', 'Crossbowe',
|
|
'Dagger', 'Excalibur', 'Halberd', 'Hatchet', 'Machete', 'Saber', 'Samurai', 'Scimitar', 'Scythe', 'Stiletto',
|
|
'Spear', 'Sword', 'Aurora', 'Avalanche', 'Blizzard', 'Cyclone', 'Dewdrop', 'Downpour', 'Duststorm', 'Fogbank',
|
|
'Freeze', 'Frost', 'GullyWasher', 'Gust', 'Hurricane', 'IceStorm', 'JetStream', 'Lightning', 'Mist', 'Monsoon',
|
|
'Rainbow', 'Raindrop', 'SandStorm', 'Seabreeze', 'Snowflake', 'Stratosphere', 'Storm', 'Sunrise', 'Sunset',
|
|
'Tornado', 'Thunder', 'Thunderbolt', 'Thunderstorm', 'TropicalStorm', 'Twister', 'Typhoon', 'Updraft', 'Vortex',
|
|
'Waterspout', 'Whirlwind', 'WindChill', 'Archimedes', 'Aristotle', 'Confucius', 'Copernicus', 'Curie',
|
|
'daVinci', 'Darwin', 'Descartes', 'Edison', 'Einstein', 'Epicurus', 'Freud', 'Galileo', 'Hawking',
|
|
'Machiavelli', 'Marx', 'Newton', 'Pascal', 'Pasteur', 'Plato', 'Sagan', 'Socrates', 'Tesla', 'Voltaire',
|
|
'Baccarat', 'Backgammon', 'Blackjack', 'Chess', 'Jenga', 'Jeopardy', 'Keno', 'Monopoly', 'Pictionary', 'Poker',
|
|
'Scrabble', 'TrivialPursuit', 'Twister', 'Roulette', 'Stratego', 'Yahtzee', 'Aquaman', 'Batman', 'BlackPanther',
|
|
'BlackWidow', 'CaptainAmerica', 'Catwoman', 'Daredevil', 'Dr.Strange', 'Flash', 'GreenArrow', 'GreenLantern',
|
|
'Hulk', 'IronMan', 'Phantom', 'Thor', 'SilverSurfer', 'SpiderMan', 'Supergirl', 'Superman', 'WonderWoman',
|
|
'Wolverine', 'Hypersonic', 'Lightspeed', 'Mach1,2,3,4,etc', 'Supersonic', 'WarpSpeed', 'Amiatina', 'Andalusian',
|
|
'Appaloosa', 'Clydesdale', 'Colt', 'Falabella', 'Knabstrupper', 'Lipizzan', 'Lucitano', 'Maverick', 'Mustang',
|
|
'Palomino', 'Pony', 'QuarterHorse', 'Stallion', 'Thoroughbred', 'Zebra', 'Antigua', 'Aruba', 'Azores', 'Baja',
|
|
'Bali', 'Barbados', 'Bermuda', 'BoraBora', 'Borneo', 'Capri', 'Cayman', 'Corfu', 'Cozumel', 'Curacao', 'Fiji',
|
|
'Galapagos', 'Hawaii', 'Ibiza', 'Jamaica', 'Kauai', 'Lanai', 'Majorca', 'Maldives', 'Maui', 'Mykonos',
|
|
'Nantucket', 'Oahu', 'Tahiti', 'Tortuga', 'Roatan', 'Santorini', 'Seychelles', 'St.Johns', 'St.Lucia',
|
|
'Albatross', 'BaldEagle', 'Blackhawk', 'BlueJay', 'Chukar', 'Condor', 'Crane', 'Dove', 'Eagle', 'Falcon',
|
|
'Goose(GoldenGoose)', 'Grouse', 'Hawk', 'Heron', 'Hornbill', 'Hummingbird', 'Lark', 'Mallard', 'Oriole',
|
|
'Osprey', 'Owl', 'Parrot', 'Penguin', 'Peregrine', 'Pelican', 'Pheasant', 'Quail', 'Raptor', 'Raven', 'Robin',
|
|
'Sandpiper', 'Seagull', 'Sparrow', 'Stork', 'Thunderbird', 'Toucan', 'Vulture', 'Waterfowl', 'Woodpecker',
|
|
'Wren', 'C-3PO', 'Chewbacca', 'Dagobah', 'DarthVader', 'DeathStar', 'Devaron', 'Droid', 'Endor', 'Ewok', 'Hoth',
|
|
'Jakku', 'Jedi', 'Leia', 'Lightsaber', 'Lothal', 'Naboo', 'Padawan', 'R2-D2', 'Scarif', 'Sith', 'Skywalker',
|
|
'Stormtrooper', 'Tatooine', 'Wookie', 'Yoda', 'Zanbar', 'Canoe', 'Catamaran', 'Cruiser', 'Cutter', 'Ferry',
|
|
'Galleon', 'Gondola', 'Hovercraft', 'Hydrofoil', 'Jetski', 'Kayak', 'Longboat', 'Motorboat', 'Outrigger',
|
|
'PirateShip', 'Riverboat', 'Sailboat', 'Skipjack', 'Schooner', 'Skiff', 'Sloop', 'Steamboat', 'Tanker',
|
|
'Trimaran', 'Trawler', 'Tugboat', 'U-boat', 'Yacht', 'Yawl', 'Lancer', 'Volunteer', 'Searchlight', 'Passkey',
|
|
'Deacon', 'Rawhide', 'Timberwolf', 'Eagle', 'Tumbler', 'Renegade', 'Mogul'
|
|
]
|
|
|
|
this_name = all_names[random.randint(0, len(all_names) - 1)]
|
|
return this_name
|
|
|
|
|
|
def random_no_phrase():
|
|
phrases = [
|
|
'uhh...no',
|
|
'lol no',
|
|
'nope',
|
|
]
|
|
|
|
|
|
async def send_to_bothole(ctx, content, embed):
|
|
await discord.utils.get(ctx.guild.text_channels, name='pd-bot-hole') \
|
|
.send(content=content, embed=embed)
|
|
|
|
|
|
async def send_to_news(ctx, content, embed):
|
|
await discord.utils.get(ctx.guild.text_channels, name='pd-news-ticker') \
|
|
.send(content=content, embed=embed)
|
|
|
|
|
|
async def typing_pause(ctx, seconds=1):
|
|
async with ctx.typing():
|
|
await asyncio.sleep(seconds)
|
|
|
|
|
|
async def pause_then_type(ctx, message):
|
|
async with ctx.typing():
|
|
await asyncio.sleep(len(message) / 100)
|
|
await ctx.send(message)
|
|
|
|
|
|
async def check_if_pdhole(ctx):
|
|
if ctx.message.channel.name != 'pd-bot-hole':
|
|
await ctx.send('Slide on down to my bot-hole for running commands.')
|
|
await ctx.message.add_reaction('❌')
|
|
return False
|
|
return True
|
|
|
|
|
|
def get_roster_sheet_legacy(team):
|
|
return f'https://docs.google.com/spreadsheets/d/{team.gsheet}/edit'
|
|
|
|
|
|
def get_special_embed(special):
|
|
embed = discord.Embed(title=f'{special.name} - Special #{special.get_id()}',
|
|
color=discord.Color.random(),
|
|
description=f'{special.short_desc}')
|
|
embed.add_field(name='Description', value=f'{special.long_desc}', inline=False)
|
|
# embed.add_field(name='To Redeem', value=f'Run .redeem {special.get_id()}', inline=False)
|
|
if special.thumbnail.lower() != 'none':
|
|
embed.set_thumbnail(url=f'{special.thumbnail}')
|
|
if special.url.lower() != 'none':
|
|
embed.set_image(url=f'{special.url}')
|
|
|
|
return embed
|
|
|
|
|
|
def get_random_embed(title, thumb=None):
|
|
embed = discord.Embed(title=title, color=discord.Color.random())
|
|
if thumb:
|
|
embed.set_thumbnail(url=thumb)
|
|
|
|
return embed
|
|
|
|
|
|
async def get_player_photo(player):
|
|
search_term = player['bbref_id'] if player['bbref_id'] else player['p_name']
|
|
req_url = f'https://www.thesportsdb.com/api/v1/json/1/searchplayers.php?p={search_term}'
|
|
|
|
try:
|
|
resp = requests.get(req_url, timeout=.5)
|
|
except Exception as e:
|
|
return None
|
|
if resp.status_code == 200 and resp.json()['player']:
|
|
if resp.json()['player'][0]['strSport'] == 'Baseball':
|
|
await db_patch('players', object_id=player['player_id'],
|
|
params=[('headshot', resp.json()['player'][0]['strThumb'])])
|
|
return resp.json()['player'][0]['strThumb']
|
|
return None
|
|
|
|
|
|
async def get_player_headshot(player):
|
|
search_term = player['bbref_id'] if player['bbref_id'] else player['p_name']
|
|
req_url = f'https://www.baseball-reference.com/search/search.fcgi?search={search_term}'
|
|
|
|
try:
|
|
resp = requests.get(req_url, timeout=2).text
|
|
soup = BeautifulSoup(resp, 'html.parser')
|
|
for item in soup.find_all('img'):
|
|
if 'headshot' in item['src']:
|
|
await db_patch('players', object_id=player['player_id'], params=[('headshot', item['src'])])
|
|
return item['src']
|
|
except:
|
|
pass
|
|
return await get_player_photo(player)
|
|
|
|
|
|
def fuzzy_search(name, master_list):
|
|
if name.lower() in master_list:
|
|
return name.lower()
|
|
|
|
great_matches = get_close_matches(name, master_list, cutoff=0.8)
|
|
if len(great_matches) == 1:
|
|
return great_matches[0]
|
|
elif len(great_matches) > 0:
|
|
matches = great_matches
|
|
else:
|
|
matches = get_close_matches(name, master_list, n=6)
|
|
if len(matches) == 1:
|
|
return matches[0]
|
|
|
|
if not matches:
|
|
raise ValueError(f'{name.title()} was not found')
|
|
|
|
return matches[0]
|
|
|
|
|
|
async def fuzzy_player_search(ctx, channel, bot, name, master_list):
|
|
"""
|
|
Takes a name to search and returns the name of the best match
|
|
|
|
:param ctx: discord context
|
|
:param channel: discord channel
|
|
:param bot: discord.py bot object
|
|
:param name: string
|
|
:param master_list: list of names
|
|
:return:
|
|
"""
|
|
matches = fuzzy_search(name, master_list)
|
|
|
|
embed = discord.Embed(
|
|
title="Did You Mean...",
|
|
description='Enter the number of the card you would like to see.',
|
|
color=0x7FC600
|
|
)
|
|
count = 1
|
|
for x in matches:
|
|
embed.add_field(name=f'{count}', value=x, inline=False)
|
|
count += 1
|
|
embed.set_footer(text='These are the closest matches. Spell better if they\'re not who you want.')
|
|
this_q = Question(bot, channel, None, 'int', 45, embed=embed)
|
|
resp = await this_q.ask([ctx.author])
|
|
|
|
if not resp:
|
|
return None
|
|
if resp < count:
|
|
return matches[resp - 1]
|
|
else:
|
|
raise ValueError(f'{resp} is not a valid response.')
|
|
|
|
|
|
async def create_channel_old(
|
|
ctx, channel_name: str, category_name: str, everyone_send=False, everyone_read=True, allowed_members=None,
|
|
allowed_roles=None):
|
|
this_category = discord.utils.get(ctx.guild.categories, name=category_name)
|
|
if not this_category:
|
|
raise ValueError(f'I couldn\'t find a category named **{category_name}**')
|
|
|
|
overwrites = {
|
|
ctx.guild.me: discord.PermissionOverwrite(read_messages=True, send_messages=True),
|
|
ctx.guild.default_role: discord.PermissionOverwrite(read_messages=everyone_read, send_messages=everyone_send)
|
|
}
|
|
if allowed_members:
|
|
if isinstance(allowed_members, list):
|
|
for member in allowed_members:
|
|
overwrites[member] = discord.PermissionOverwrite(read_messages=True, send_messages=True)
|
|
if allowed_roles:
|
|
if isinstance(allowed_roles, list):
|
|
for role in allowed_roles:
|
|
overwrites[role] = discord.PermissionOverwrite(read_messages=True, send_messages=True)
|
|
|
|
this_channel = await ctx.guild.create_text_channel(
|
|
channel_name,
|
|
overwrites=overwrites,
|
|
category=this_category
|
|
)
|
|
|
|
logger.info(f'Creating channel ({channel_name}) in ({category_name})')
|
|
|
|
return this_channel
|
|
|
|
|
|
async def react_and_reply(ctx, reaction, message):
|
|
await ctx.message.add_reaction(reaction)
|
|
await ctx.send(message)
|
|
|
|
|
|
async def send_to_channel(bot, channel_name, content=None, embed=None):
|
|
guild = bot.get_guild(int(os.environ.get('GUILD_ID')))
|
|
if not guild:
|
|
logger.error('Cannot send to channel - bot not logged in')
|
|
return
|
|
|
|
this_channel = discord.utils.get(guild.text_channels, name=channel_name)
|
|
|
|
if not this_channel:
|
|
this_channel = discord.utils.get(guild.text_channels, id=channel_name)
|
|
if not this_channel:
|
|
raise NameError(f'**{channel_name}** channel not found')
|
|
|
|
return await this_channel.send(content=content, embed=embed)
|
|
|
|
|
|
async def get_or_create_role(ctx, role_name, mentionable=True):
|
|
this_role = discord.utils.get(ctx.guild.roles, name=role_name)
|
|
# logger.info(f'this_role: {this_role} / role_name: {role_name} (POST SEARCH)')
|
|
|
|
if not this_role:
|
|
this_role = await ctx.guild.create_role(name=role_name, mentionable=mentionable)
|
|
# logger.info(f'this_role: {this_role} / role_name: {role_name} (PRE RETURN)')
|
|
|
|
return this_role
|
|
|
|
|
|
"""
|
|
NEW FOR SEASON 4
|
|
"""
|
|
|
|
|
|
def get_team_embed(title, team=None, thumbnail: bool = True):
|
|
if team:
|
|
embed = discord.Embed(
|
|
title=title,
|
|
color=int(team["color"], 16) if team["color"] else int(SBA_COLOR, 16)
|
|
)
|
|
embed.set_footer(text=f'Paper Dynasty Season {team["season"]}', icon_url=IMAGES['logo'])
|
|
if thumbnail:
|
|
embed.set_thumbnail(url=team["logo"] if team["logo"] else IMAGES['logo'])
|
|
else:
|
|
embed = discord.Embed(
|
|
title=title,
|
|
color=int(SBA_COLOR, 16)
|
|
)
|
|
embed.set_footer(text=f'Paper Dynasty Season {PD_SEASON}', icon_url=IMAGES['logo'])
|
|
if thumbnail:
|
|
embed.set_thumbnail(url=IMAGES['logo'])
|
|
|
|
return embed
|
|
|
|
|
|
async def get_team_by_owner(owner_id: int):
|
|
team = await db_get('teams', params=[('gm_id', owner_id)])
|
|
|
|
if not team['count']:
|
|
return None
|
|
|
|
return team['teams'][0]
|
|
|
|
|
|
async def team_role(ctx, team: Team):
|
|
return await get_or_create_role(ctx, f'{team.abbrev} - {team.lname}')
|
|
|
|
|
|
def get_cal_user(ctx):
|
|
return ctx.guild.get_member(258104532423147520)
|
|
|
|
|
|
async def get_emoji(ctx, name, return_empty=True):
|
|
try:
|
|
emoji = await commands.converter.EmojiConverter().convert(ctx, name)
|
|
except:
|
|
if return_empty:
|
|
emoji = ''
|
|
else:
|
|
return name
|
|
return emoji
|
|
|
|
|
|
def get_all_pos(player):
|
|
all_pos = []
|
|
|
|
for x in range(1, 8):
|
|
if player[f'pos_{x}']:
|
|
all_pos.append(player[f'pos_{x}'])
|
|
|
|
return all_pos
|
|
|
|
|
|
async def create_channel(
|
|
ctx, channel_name: str, category_name: str, everyone_send=False, everyone_read=True,
|
|
read_send_members: list = None, read_send_roles: list = None, read_only_roles: list = None):
|
|
this_category = discord.utils.get(ctx.guild.categories, name=category_name)
|
|
if not this_category:
|
|
raise ValueError(f'I couldn\'t find a category named **{category_name}**')
|
|
|
|
overwrites = {
|
|
ctx.guild.me: discord.PermissionOverwrite(read_messages=True, send_messages=True),
|
|
ctx.guild.default_role: discord.PermissionOverwrite(read_messages=everyone_read, send_messages=everyone_send)
|
|
}
|
|
if read_send_members:
|
|
for member in read_send_members:
|
|
overwrites[member] = discord.PermissionOverwrite(read_messages=True, send_messages=True)
|
|
if read_send_roles:
|
|
for role in read_send_roles:
|
|
overwrites[role] = discord.PermissionOverwrite(read_messages=True, send_messages=True)
|
|
if read_only_roles:
|
|
for role in read_only_roles:
|
|
overwrites[role] = discord.PermissionOverwrite(read_messages=True, send_messages=False)
|
|
|
|
this_channel = await ctx.guild.create_text_channel(
|
|
channel_name,
|
|
overwrites=overwrites,
|
|
category=this_category
|
|
)
|
|
|
|
logger.info(f'Creating channel ({channel_name}) in ({category_name})')
|
|
|
|
return this_channel
|
|
|
|
|
|
async def share_channel(channel, user, read_only=False):
|
|
await channel.set_permissions(user, read_messages=True, send_messages=not read_only)
|
|
|
|
|
|
async def get_card_embeds(card, include_stats=False) -> list:
|
|
embed = discord.Embed(
|
|
title=f'{card["player"]["p_name"]}',
|
|
color=int(card['player']['rarity']['color'], 16)
|
|
)
|
|
# embed.description = card['team']['lname']
|
|
embed.description = f'{card["player"]["cardset"]["name"]} / {card["player"]["mlbclub"]}'
|
|
embed.set_author(name=card['team']['lname'], url=IMAGES['logo'], icon_url=card['team']['logo'])
|
|
embed.set_footer(text=f'Paper Dynasty Season {card["team"]["season"]}', icon_url=IMAGES['logo'])
|
|
|
|
if include_stats:
|
|
b_query = await db_get(
|
|
'plays/batting', params=[('player_id', card['player']['player_id']), ('season', PD_SEASON)])
|
|
p_query = await db_get(
|
|
'plays/pitching', params=[('player_id', card['player']['player_id']), ('season', PD_SEASON)])
|
|
|
|
embed.add_field(name='Player ID', value=f'{card["player"]["player_id"]}')
|
|
embed.add_field(name='Rarity', value=f'{card["player"]["rarity"]["name"]}')
|
|
embed.add_field(name='Cost', value=f'{card["player"]["cost"]}₼')
|
|
|
|
pos_string = ", ".join(get_all_pos(card['player']))
|
|
embed.add_field(name='Positions', value=pos_string)
|
|
# all_dex = card['player']['paperdex']
|
|
all_dex = await db_get('paperdex', params=[("player_id", card["player"]["player_id"]), ('flat', True)])
|
|
count = all_dex['count']
|
|
if card['team']['lname'] != 'Paper Dynasty':
|
|
bool_list = [True for elem in all_dex['paperdex'] if elem['team'] == card['team']['id']]
|
|
if any(bool_list):
|
|
if count == 1:
|
|
coll_string = f'Only you'
|
|
else:
|
|
coll_string = f'You and {count - 1} other{"s" if count - 1 != 1 else ""}'
|
|
elif count:
|
|
coll_string = f'{count} other team{"s" if count != 1 else ""}'
|
|
else:
|
|
coll_string = f'0 teams'
|
|
embed.add_field(name='Collected By', value=coll_string)
|
|
else:
|
|
embed.add_field(name='Collected By', value=f'{count} team{"s" if count != 1 else ""}')
|
|
|
|
# TODO: check for dupes with the included paperdex data
|
|
# if card['team']['lname'] != 'Paper Dynasty':
|
|
# team_dex = await db_get('cards', params=[("player_id", card["player"]["player_id"]), ('team_id', card['team']['id'])])
|
|
# count = 1 if not team_dex['count'] else team_dex['count']
|
|
# embed.add_field(name='# Dupes', value=f'{count - 1} dupe{"s" if count - 1 != 1 else ""}')
|
|
|
|
# embed.add_field(name='Team', value=f'{card["player"]["mlbclub"]}')
|
|
if card['player']['franchise'] != 'Pokemon':
|
|
player_pages = f'[BBRef]({get_player_url(card["player"], "bbref")})'
|
|
else:
|
|
player_pages = f'[Pkmn]({PKMN_REF_URL}{card["player"]["bbref_id"]})'
|
|
embed.add_field(name='Player Page', value=f'{player_pages}')
|
|
embed.set_image(url=card["player"]["image"])
|
|
|
|
headshot = card['player']['headshot'] if card['player']['headshot'] else await get_player_headshot(card['player'])
|
|
if headshot:
|
|
embed.set_thumbnail(url=headshot)
|
|
else:
|
|
embed.set_thumbnail(url=IMAGES['logo'])
|
|
|
|
if card['player']['franchise'] == 'Pokemon':
|
|
if card['player']['fangr_id'] is not None:
|
|
try:
|
|
evo_mon = await db_get('players', object_id=card['player']['fangr_id'], none_okay=True)
|
|
if evo_mon is not None:
|
|
embed.add_field(
|
|
name='Evolves Into',
|
|
value=f'{evo_mon["p_name"]}'
|
|
)
|
|
except Exception as e:
|
|
logging.error('could not pull evolution: {e}', exc_info=True, stack_info=True)
|
|
if '420420' not in card['player']['strat_code']:
|
|
try:
|
|
evo_mon = await db_get('players', object_id=card['player']['strat_code'], none_okay=True)
|
|
if evo_mon is not None:
|
|
embed.add_field(
|
|
name='Evolves From',
|
|
value=f'{evo_mon["p_name"]}'
|
|
)
|
|
except Exception as e:
|
|
logging.error('could not pull evolution: {e}', exc_info=True, stack_info=True)
|
|
|
|
if include_stats:
|
|
if b_query['count'] > 0:
|
|
b = b_query['stats'][0]
|
|
|
|
re24 = f'{b["re24"]:.2f}'
|
|
batting_string = f'```\n' \
|
|
f' AVG OBP SLG\n' \
|
|
f' {b["avg"]:.3f} {b["obp"]:.3f} {b["slg"]:.3f}\n``````\n' \
|
|
f' OPS wOBA RE24\n' \
|
|
f' {b["ops"]:.3f} {b["woba"]:.3f} {re24: ^5}\n``````\n' \
|
|
f' PA H RBI 2B 3B HR SB\n' \
|
|
f'{b["pa"]: >3} {b["hit"]: ^3} {b["rbi"]: ^3} {b["double"]: >2} {b["triple"]: >2} ' \
|
|
f'{b["hr"]: >2} {b["sb"]: >2}```\n'
|
|
embed.add_field(name='Batting Stats', value=batting_string, inline=False)
|
|
if p_query['count'] > 0:
|
|
p = p_query['stats'][0]
|
|
|
|
ip_whole = math.floor(p['outs'] / 3)
|
|
ip_denom = p['outs'] % 3
|
|
ips = ip_whole + (ip_denom * 0.1)
|
|
|
|
kpbb = f'{p["k/bb"]:.1f}'
|
|
era = f'{p["era"]:.2f}'
|
|
whip = f'{p["whip"]:.2f}'
|
|
re24 = f'{p["re24"]:.2f}'
|
|
|
|
pitching_string = f'```\n' \
|
|
f' W-L SV ERA WHIP\n' \
|
|
f'{p["win"]: >2}-{p["loss"]: <2} {p["save"]: >2} {era: >5} {whip: >4}\n``````\n' \
|
|
f' IP SO K/BB RE24\n' \
|
|
f'{ips: >5} {p["so"]: ^3} {kpbb: ^4} {re24: ^5}\n```'
|
|
embed.add_field(name='Pitching Stats', value=pitching_string, inline=False)
|
|
|
|
if not card['player']['image2']:
|
|
return [embed]
|
|
|
|
card_two = discord.Embed(color=int(card['player']['rarity']['color'], 16))
|
|
card_two.set_footer(text=f'Paper Dynasty Season {card["team"]["season"]}', icon_url=IMAGES['logo'])
|
|
card_two.set_image(url=card['player']['image2'])
|
|
|
|
return [embed, card_two]
|
|
|
|
|
|
def image_embed(image_url: str, title: str = None, color: str = None, desc: str = None, author_name: str = None,
|
|
author_icon: str = None):
|
|
embed_color = int(SBA_COLOR, 16)
|
|
if color is not None:
|
|
embed_color = int(color, 16)
|
|
|
|
embed = discord.Embed(color=embed_color)
|
|
|
|
if title is not None:
|
|
embed.title = title
|
|
if desc is not None:
|
|
embed.description = desc
|
|
if author_name is not None:
|
|
icon = author_icon if author_icon is not None else IMAGES['logo']
|
|
embed.set_author(name=author_name, icon_url=icon)
|
|
embed.set_footer(text=f'Paper Dynasty Season {PD_SEASON}', icon_url=IMAGES['logo'])
|
|
embed.set_image(url=image_url)
|
|
return embed
|
|
|
|
|
|
def is_shiny(card):
|
|
if card['player']['rarity']['value'] >= 5:
|
|
return True
|
|
return False
|
|
|
|
|
|
async def display_cards(
|
|
cards: list, team: dict, channel, user, bot=None, pack_cover: str = None, cust_message: str = None,
|
|
add_roster: bool = True, pack_name: str = None) -> bool:
|
|
cards.sort(key=lambda x: x['player']['rarity']['value'])
|
|
card_embeds = [await get_card_embeds(x) for x in cards]
|
|
page_num = 0 if pack_cover is None else -1
|
|
seen_shiny = False
|
|
|
|
view = Pagination([user], timeout=10)
|
|
l_emoji = await get_emoji(channel.guild, 'arrow_left')
|
|
r_emoji = await get_emoji(channel.guild, 'arrow_right')
|
|
view.left_button.disabled = True
|
|
view.left_button.label = f'{l_emoji}Prev: -/{len(card_embeds)}'
|
|
view.cancel_button.label = f'Close Pack'
|
|
view.right_button.label = f'Next: {page_num + 2}/{len(card_embeds)}{r_emoji}'
|
|
if len(cards) == 1:
|
|
view.right_button.disabled = True
|
|
|
|
if pack_cover:
|
|
msg = await channel.send(
|
|
content=None,
|
|
embed=image_embed(pack_cover, title=f'{team["lname"]}', desc=pack_name),
|
|
view=view
|
|
)
|
|
else:
|
|
msg = await channel.send(content=None, embeds=card_embeds[page_num], view=view)
|
|
|
|
if cust_message:
|
|
follow_up = await channel.send(cust_message)
|
|
else:
|
|
follow_up = await channel.send(f'{user.mention} you\'ve got {len(cards)} cards here')
|
|
|
|
while True:
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
if view.value == 'cancel':
|
|
await msg.edit(view=None)
|
|
if add_roster:
|
|
await follow_up.edit(content=f'Refresh your cards here: {get_roster_sheet(team)}')
|
|
return True
|
|
if view.value == 'left':
|
|
page_num -= 1 if page_num > 0 else 0
|
|
if view.value == 'right':
|
|
page_num += 1 if page_num <= len(card_embeds) else len(card_embeds)
|
|
else:
|
|
if page_num == len(card_embeds) - 1:
|
|
await msg.edit(view=None)
|
|
if add_roster:
|
|
await follow_up.edit(content=f'Refresh your cards here: {get_roster_sheet(team)}')
|
|
return True
|
|
else:
|
|
page_num += 1
|
|
|
|
view.value = None
|
|
|
|
if is_shiny(cards[page_num]) and not seen_shiny:
|
|
seen_shiny = True
|
|
view = Pagination([user], timeout=300)
|
|
view.cancel_button.style = discord.ButtonStyle.success
|
|
view.cancel_button.label = 'Flip!'
|
|
view.left_button.label = '-'
|
|
view.right_button.label = '-'
|
|
view.left_button.disabled = True
|
|
view.right_button.disabled = True
|
|
|
|
await msg.edit(
|
|
embed=image_embed(
|
|
IMAGES['mvp'][cards[page_num]["player"]["franchise"]],
|
|
color='56f1fa',
|
|
author_name=team['lname'],
|
|
author_icon=team['logo']
|
|
),
|
|
view=view)
|
|
tmp_msg = await channel.send(content=f'<@&1163537676885033010> we\'ve got an MVP!')
|
|
await follow_up.edit(content=f'<@&1163537676885033010> we\'ve got an MVP!')
|
|
await tmp_msg.delete()
|
|
await view.wait()
|
|
|
|
view = Pagination([user], timeout=10)
|
|
view.right_button.label = f'Next: {page_num + 2}/{len(card_embeds)}{r_emoji}'
|
|
view.cancel_button.label = f'Close Pack'
|
|
view.left_button.label = f'{l_emoji}Prev: {page_num}/{len(card_embeds)}'
|
|
if page_num == 0:
|
|
view.left_button.label = f'{l_emoji}Prev: -/{len(card_embeds)}'
|
|
view.left_button.disabled = True
|
|
elif page_num == len(card_embeds) - 1:
|
|
view.timeout = 600.0
|
|
view.right_button.label = f'Next: -/{len(card_embeds)}{r_emoji}'
|
|
view.right_button.disabled = True
|
|
|
|
await msg.edit(content=None, embeds=card_embeds[page_num], view=view)
|
|
|
|
|
|
async def embed_pagination(
|
|
all_embeds: list, channel, user: discord.Member, custom_message: str = None,
|
|
timeout: int = 10, start_page: int = 0):
|
|
if start_page > len(all_embeds) - 1 or start_page < 0:
|
|
page_num = 0
|
|
else:
|
|
page_num = start_page
|
|
|
|
view = Pagination([user], timeout=timeout)
|
|
l_emoji = ''
|
|
r_emoji = ''
|
|
view.right_button.label = f'Next: {page_num + 2}/{len(all_embeds)}{r_emoji}'
|
|
view.cancel_button.label = f'Cancel'
|
|
view.left_button.label = f'{l_emoji}Prev: {page_num}/{len(all_embeds)}'
|
|
if page_num == 0:
|
|
view.left_button.label = f'{l_emoji}Prev: -/{len(all_embeds)}'
|
|
view.left_button.disabled = True
|
|
elif page_num == len(all_embeds) - 1:
|
|
view.right_button.label = f'Next: -/{len(all_embeds)}{r_emoji}'
|
|
view.right_button.disabled = True
|
|
|
|
msg = await channel.send(content=custom_message, embed=all_embeds[page_num], view=view)
|
|
|
|
while True:
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
if view.value == 'cancel':
|
|
await msg.edit(view=None)
|
|
return True
|
|
if view.value == 'left':
|
|
page_num -= 1 if page_num > 0 else 0
|
|
if view.value == 'right':
|
|
page_num += 1 if page_num <= len(all_embeds) else len(all_embeds)
|
|
else:
|
|
if page_num == len(all_embeds) - 1:
|
|
await msg.edit(view=None)
|
|
return True
|
|
else:
|
|
page_num += 1
|
|
|
|
view.value = None
|
|
|
|
view = Pagination([user], timeout=timeout)
|
|
view.right_button.label = f'Next: {page_num + 2}/{len(all_embeds)}{r_emoji}'
|
|
view.cancel_button.label = f'Cancel'
|
|
view.left_button.label = f'{l_emoji}Prev: {page_num}/{len(all_embeds)}'
|
|
if page_num == 0:
|
|
view.left_button.label = f'{l_emoji}Prev: -/{len(all_embeds)}'
|
|
view.left_button.disabled = True
|
|
elif page_num == len(all_embeds) - 1:
|
|
view.timeout = 600.0
|
|
view.right_button.label = f'Next: -/{len(all_embeds)}{r_emoji}'
|
|
view.right_button.disabled = True
|
|
|
|
await msg.edit(content=None, embed=all_embeds[page_num], view=view)
|
|
|
|
|
|
def get_roster_sheet(team: Team, allow_embed: bool = False):
|
|
try:
|
|
sheet_url = team.gsheet
|
|
except AttributeError:
|
|
sheet_url = team['gsheet']
|
|
|
|
return f'{"" if allow_embed else "<"}' \
|
|
f'https://docs.google.com/spreadsheets/d/{sheet_url}/edit' \
|
|
f'{"" if allow_embed else ">"}'
|
|
|
|
|
|
def get_player_url(player, which="sba"):
|
|
if which == 'bbref':
|
|
return f'https://www.baseball-reference.com/search/search.fcgi?search={player["bbref_id"]}'
|
|
else:
|
|
stub_name = player["p_name"].replace(" ", "%20")
|
|
return f'https://sombaseball.ddns.net/players?name={stub_name}'
|
|
|
|
|
|
async def bad_channel(ctx):
|
|
bad_channels = ['paper-dynasty-chat', 'pd-news-ticker']
|
|
if ctx.message.channel.name in bad_channels:
|
|
await ctx.message.add_reaction('❌')
|
|
bot_hole = discord.utils.get(
|
|
ctx.guild.text_channels,
|
|
name=f'pd-bot-hole'
|
|
)
|
|
await ctx.send(f'Slide on down to the {bot_hole.mention} ;)')
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
def get_channel(ctx, name) -> Optional[discord.TextChannel]:
|
|
channel = discord.utils.get(
|
|
ctx.guild.text_channels,
|
|
name=name
|
|
)
|
|
if channel:
|
|
return channel
|
|
|
|
return None
|
|
|
|
|
|
async def get_test_pack(ctx, team):
|
|
pull_notifs = []
|
|
this_pack = await db_post('packs/one', payload={
|
|
'team_id': team['id'], 'pack_type_id': 1,
|
|
'open_time': int(datetime.datetime.timestamp(datetime.datetime.now())*1000)
|
|
})
|
|
ft_query = await db_get('players/random', params=[('max_rarity', 1), ('limit', 3)])
|
|
four_query = await db_get('players/random', params=[('min_rarity', 1), ('max_rarity', 3), ('limit', 1)])
|
|
five_query = await db_get('players/random', params=[('min_rarity', 5), ('max_rarity', 5), ('limit', 1)])
|
|
first_three = ft_query['players']
|
|
fourth = four_query['players']
|
|
fifth = five_query['players']
|
|
all_cards = [*first_three, *fourth, *fifth]
|
|
|
|
success = await db_post('cards', timeout=10, payload={'cards': [{
|
|
'player_id': x['player_id'], 'team_id': team['id'], 'pack_id': this_pack['id']} for x in all_cards]
|
|
})
|
|
if not success:
|
|
await ctx.send(f'I was not able to create these cards {get_emoji(ctx, "slight_frown")}')
|
|
return
|
|
|
|
for x in all_cards:
|
|
if x['rarity']['value'] >= 3:
|
|
pull_notifs.append(x)
|
|
|
|
for pull in pull_notifs:
|
|
await db_post('notifs', payload={
|
|
'created': int(datetime.datetime.timestamp(datetime.datetime.now())*1000),
|
|
'title': 'Rare Pull',
|
|
'field_name': f'{player_desc(pull)} ({pull["rarity"]["name"]})',
|
|
'message': f'Pulled by {team["abbrev"]}',
|
|
'about': f'Player-{pull["player_id"]}'
|
|
})
|
|
|
|
return [{'player': x, 'team': team} for x in all_cards]
|
|
|
|
|
|
async def roll_for_cards(all_packs: list, extra_val=None) -> list:
|
|
"""
|
|
Pack odds are calculated based on the pack type
|
|
|
|
Parameters
|
|
----------
|
|
extra_val
|
|
all_packs
|
|
|
|
Returns
|
|
-------
|
|
|
|
"""
|
|
all_players = []
|
|
team = all_packs[0]['team']
|
|
pack_ids = []
|
|
for pack in all_packs:
|
|
counts = {
|
|
'Rep': {
|
|
'count': 0,
|
|
'rarity': 0
|
|
},
|
|
'Res': {
|
|
'count': 0,
|
|
'rarity': 1
|
|
},
|
|
'Sta': {
|
|
'count': 0,
|
|
'rarity': 2
|
|
},
|
|
'All': {
|
|
'count': 0,
|
|
'rarity': 3
|
|
},
|
|
'MVP': {
|
|
'count': 0,
|
|
'rarity': 5
|
|
},
|
|
'HoF': {
|
|
'count': 0,
|
|
'rarity': 8
|
|
},
|
|
}
|
|
this_pack_players = []
|
|
if pack['pack_type']['name'] == 'Standard':
|
|
# Cards 1 - 2
|
|
for x in range(2):
|
|
d_1000 = random.randint(1, 1000)
|
|
if d_1000 <= 450:
|
|
counts['Rep']['count'] += 1
|
|
elif d_1000 <= 900:
|
|
counts['Res']['count'] += 1
|
|
else:
|
|
counts['Sta']['count'] += 1
|
|
|
|
# Card 3
|
|
d_1000 = random.randint(1, 1000)
|
|
if d_1000 <= 350:
|
|
counts['Rep']['count'] += 1
|
|
elif d_1000 <= 700:
|
|
counts['Res']['count'] += 1
|
|
elif d_1000 <= 950:
|
|
counts['Sta']['count'] += 1
|
|
else:
|
|
counts['All']['count'] += 1
|
|
|
|
# Card 4
|
|
d_1000 = random.randint(1, 1000)
|
|
if d_1000 <= 310:
|
|
counts['Rep']['count'] += 1
|
|
elif d_1000 <= 620:
|
|
counts['Res']['count'] += 1
|
|
elif d_1000 <= 940:
|
|
counts['Sta']['count'] += 1
|
|
elif d_1000 <= 990:
|
|
counts['All']['count'] += 1
|
|
else:
|
|
counts['MVP']['count'] += 1
|
|
|
|
# Card 5
|
|
d_1000 = random.randint(1, 1000)
|
|
if d_1000 <= 215:
|
|
counts['Rep']['count'] += 1
|
|
elif d_1000 <= 430:
|
|
counts['Res']['count'] += 1
|
|
elif d_1000 <= 930:
|
|
counts['Sta']['count'] += 1
|
|
elif d_1000 <= 980:
|
|
counts['All']['count'] += 1
|
|
elif d_1000 <= 990:
|
|
counts['MVP']['count'] += 1
|
|
else:
|
|
counts['HoF']['count'] += 1
|
|
|
|
elif pack['pack_type']['name'] == 'Premium':
|
|
# Card 1
|
|
d_1000 = random.randint(1, 1000)
|
|
if d_1000 <= 400:
|
|
counts['Rep']['count'] += 1
|
|
elif d_1000 <= 870:
|
|
counts['Res']['count'] += 1
|
|
elif d_1000 <= 970:
|
|
counts['Sta']['count'] += 1
|
|
elif d_1000 <= 990:
|
|
counts['All']['count'] += 1
|
|
else:
|
|
counts['MVP']['count'] += 1
|
|
|
|
# Card 2
|
|
d_1000 = random.randint(1, 1000)
|
|
if d_1000 <= 300:
|
|
counts['Rep']['count'] += 1
|
|
elif d_1000 <= 770:
|
|
counts['Res']['count'] += 1
|
|
elif d_1000 <= 970:
|
|
counts['Sta']['count'] += 1
|
|
elif d_1000 <= 990:
|
|
counts['All']['count'] += 1
|
|
else:
|
|
counts['MVP']['count'] += 1
|
|
|
|
# Card 3
|
|
d_1000 = random.randint(1, 1000)
|
|
if d_1000 <= 200:
|
|
counts['Rep']['count'] += 1
|
|
elif d_1000 <= 640:
|
|
counts['Res']['count'] += 1
|
|
elif d_1000 <= 940:
|
|
counts['Sta']['count'] += 1
|
|
elif d_1000 <= 990:
|
|
counts['All']['count'] += 1
|
|
else:
|
|
counts['MVP']['count'] += 1
|
|
|
|
# Card 4
|
|
d_1000 = random.randint(1, 1000)
|
|
if d_1000 <= 100:
|
|
counts['Rep']['count'] += 1
|
|
if d_1000 <= 530:
|
|
counts['Res']['count'] += 1
|
|
elif d_1000 <= 930:
|
|
counts['Sta']['count'] += 1
|
|
elif d_1000 <= 980:
|
|
counts['All']['count'] += 1
|
|
elif d_1000 <= 990:
|
|
counts['MVP']['count'] += 1
|
|
else:
|
|
counts['HoF']['count'] += 1
|
|
|
|
# Card 5
|
|
d_1000 = random.randint(1, 1000)
|
|
if d_1000 <= 380:
|
|
counts['Res']['count'] += 1
|
|
elif d_1000 <= 880:
|
|
counts['Sta']['count'] += 1
|
|
elif d_1000 <= 980:
|
|
counts['All']['count'] += 1
|
|
elif d_1000 <= 990:
|
|
counts['MVP']['count'] += 1
|
|
else:
|
|
counts['HoF']['count'] += 1
|
|
|
|
elif pack['pack_type']['name'] == 'Check-In Player':
|
|
logger.info(f'Building Check-In Pack // extra_val (type): {extra_val} {type(extra_val)}')
|
|
# Single Card
|
|
mod = 0
|
|
if isinstance(extra_val, int):
|
|
mod = extra_val
|
|
d_1000 = random.randint(1, 1000 + mod)
|
|
|
|
if d_1000 >= 1100:
|
|
counts['All']['count'] += 1
|
|
elif d_1000 >= 1000:
|
|
counts['Sta']['count'] += 1
|
|
elif d_1000 >= 500:
|
|
counts['Res']['count'] += 1
|
|
else:
|
|
counts['Rep']['count'] += 1
|
|
|
|
else:
|
|
raise TypeError(f'Pack type not recognized: {pack["pack_type"]["name"]}')
|
|
|
|
pull_notifs = []
|
|
for key in counts:
|
|
mvp_flag = None
|
|
|
|
if counts[key]['count'] > 0:
|
|
params = [
|
|
('min_rarity', counts[key]['rarity']), ('max_rarity', counts[key]['rarity']),
|
|
('limit', counts[key]['count'])
|
|
]
|
|
if all_packs[0]['pack_team'] is not None:
|
|
params.extend([('franchise', all_packs[0]['pack_team']['lname']), ('in_packs', True)])
|
|
elif all_packs[0]['pack_cardset'] is not None:
|
|
params.append(('cardset_id', all_packs[0]['pack_cardset']['id']))
|
|
else:
|
|
params.append(('in_packs', True))
|
|
|
|
pl = await db_get('players/random', params=params)
|
|
|
|
if pl['count'] != counts[key]['count']:
|
|
mvp_flag = counts[key]['count'] - pl['count']
|
|
logging.info(f'Set mvp flag to {mvp_flag} / cardset_id: {all_packs[0]["pack_cardset"]["id"]}')
|
|
|
|
for x in pl['players']:
|
|
this_pack_players.append(x)
|
|
all_players.append(x)
|
|
|
|
if x['rarity']['value'] >= 3:
|
|
pull_notifs.append(x)
|
|
|
|
if mvp_flag and all_packs[0]['pack_cardset']['id'] not in [23]:
|
|
logging.info(f'Adding {mvp_flag} MVPs for missing cards')
|
|
pl = await db_get('players/random', params=[('min_rarity', 5), ('limit', mvp_flag)])
|
|
|
|
for x in pl['players']:
|
|
this_pack_players.append(x)
|
|
all_players.append(x)
|
|
|
|
# Add dupes of Replacement/Reserve cards
|
|
elif mvp_flag:
|
|
logging.info(f'Adding {mvp_flag} duplicate pokemon cards')
|
|
for count in range(mvp_flag):
|
|
logging.info(f'Adding {pl["players"][0]["p_name"]} to the pack')
|
|
this_pack_players.append(x)
|
|
all_players.append(pl['players'][0])
|
|
|
|
success = await db_post(
|
|
'cards',
|
|
payload={'cards': [{
|
|
'player_id': x['player_id'], 'team_id': pack['team']['id'], 'pack_id': pack['id']} for x in this_pack_players]
|
|
},
|
|
timeout=10
|
|
)
|
|
if not success:
|
|
raise ConnectionError(f'Failed to create this pack of cards.')
|
|
|
|
await db_patch('packs', object_id=pack['id'], params=[
|
|
('open_time', int(datetime.datetime.timestamp(datetime.datetime.now())*1000))
|
|
])
|
|
pack_ids.append(pack['id'])
|
|
|
|
for pull in pull_notifs:
|
|
logger.info(f'good pull: {pull}')
|
|
await db_post('notifs', payload={
|
|
'created': int(datetime.datetime.timestamp(datetime.datetime.now())*1000),
|
|
'title': 'Rare Pull',
|
|
'field_name': f'{player_desc(pull)} ({pull["rarity"]["name"]})',
|
|
'message': f'Pulled by {team["abbrev"]}',
|
|
'about': f'Player-{pull["player_id"]}'
|
|
})
|
|
|
|
return pack_ids
|
|
|
|
|
|
async def give_packs(team: dict, num_packs: int, pack_type: dict = None) -> dict:
|
|
"""
|
|
Parameters
|
|
----------
|
|
pack_type
|
|
team
|
|
num_packs
|
|
|
|
Returns
|
|
-------
|
|
{ 'count': int, 'packs': [ all team packs ] }
|
|
"""
|
|
pt_id = pack_type['id'] if pack_type is not None else 1
|
|
await db_post(
|
|
'packs',
|
|
payload={'packs': [{'team_id': team['id'], 'pack_type_id': pt_id} for x in range(num_packs)]}
|
|
)
|
|
total_packs = await db_get('packs', params=[
|
|
('team_id', team['id']), ('opened', False)
|
|
])
|
|
|
|
return total_packs
|
|
|
|
|
|
def get_sheets(bot):
|
|
try:
|
|
return bot.get_cog('Gameplay').sheets
|
|
except Exception as e:
|
|
logger.error(f'Could not grab sheets auth: {e}')
|
|
raise ConnectionError(f'Bot has not authenticated with discord; please try again in 1 minute.')
|
|
|
|
|
|
def create_team_sheet(team, email: str, current, bot):
|
|
sheets = get_sheets(bot)
|
|
new_sheet = sheets.drive.copy_file(
|
|
f'{current["gsheet_template"]}',
|
|
f'{team["lname"]} Roster Sheet v{current["gsheet_version"]}',
|
|
'1539D0imTMjlUx2VF3NPMt7Sv85sb2XAJ'
|
|
)
|
|
logger.info(f'new_sheet: {new_sheet}')
|
|
|
|
this_sheet = sheets.open_by_key(new_sheet['id'])
|
|
this_sheet.share(email, role='writer')
|
|
team_data = this_sheet.worksheet_by_title('Team Data')
|
|
team_data.update_values(
|
|
crange='B1:B2',
|
|
values=[[f'{team["id"]}'], [f'\'{team_hash(team)}']]
|
|
)
|
|
logger.debug(f'this_sheet: {this_sheet}')
|
|
return this_sheet
|
|
|
|
|
|
async def refresh_sheet(team, bot, sheets=None) -> None:
|
|
return
|
|
if not sheets:
|
|
sheets = get_sheets(bot)
|
|
|
|
this_sheet = sheets.open_by_key(team['gsheet'])
|
|
my_cards = this_sheet.worksheet_by_title('My Cards')
|
|
all_cards = this_sheet.worksheet_by_title('All Cards')
|
|
|
|
my_cards.update_value('A2', 'FALSE')
|
|
all_cards.update_value('A2', 'FALSE')
|
|
await asyncio.sleep(1)
|
|
|
|
my_cards.update_value('A2', 'TRUE')
|
|
await asyncio.sleep(0.5)
|
|
all_cards.update_value('A2', 'TRUE')
|
|
|
|
|
|
def delete_sheet(team, bot):
|
|
sheets = get_sheets(bot)
|
|
this_sheet = sheets.open_by_key(team['gsheet'])
|
|
this_sheet.delete()
|
|
|
|
|
|
def share_sheet(team, email, bot) -> None:
|
|
sheets = get_sheets(bot)
|
|
this_sheet = sheets.open_by_key(team['gsheet'])
|
|
this_sheet.share(email, role='writer')
|
|
|
|
|
|
def int_timestamp(datetime_obj: datetime.datetime) -> int:
|
|
return int(datetime.datetime.timestamp(datetime_obj) * 1000)
|
|
|
|
|
|
def get_pos_abbrev(pos_name):
|
|
if pos_name == 'Catcher':
|
|
return 'C'
|
|
elif pos_name == 'First Base':
|
|
return '1B'
|
|
elif pos_name == 'Second Base':
|
|
return '2B'
|
|
elif pos_name == 'Third Base':
|
|
return '3B'
|
|
elif pos_name == 'Shortstop':
|
|
return 'SS'
|
|
elif pos_name == 'Left Field':
|
|
return 'LF'
|
|
elif pos_name == 'Center Field':
|
|
return 'CF'
|
|
elif pos_name == 'Right Field':
|
|
return 'RF'
|
|
elif pos_name == 'Pitcher':
|
|
return 'P'
|
|
elif pos_name == 'Designated Hitter':
|
|
return 'DH'
|
|
elif pos_name == 'Pinch Hitter':
|
|
return 'PH'
|
|
else:
|
|
raise KeyError(f'{pos_name} is not a recognized position name')
|
|
|
|
|
|
async def cardset_search(cardset: str, cardset_list: list) -> Optional[dict]:
|
|
cardset_name = fuzzy_search(cardset, cardset_list)
|
|
if not cardset_name:
|
|
return None
|
|
|
|
c_query = await db_get('cardsets', params=[('name', cardset_name)])
|
|
if c_query['count'] == 0:
|
|
return None
|
|
return c_query['cardsets'][0]
|
|
|
|
|
|
def get_blank_team_card(player):
|
|
return {'player': player, 'team': {'lname': 'Paper Dynasty', 'logo': IMAGES['logo'], 'season': PD_SEASON}}
|
|
|
|
|
|
def get_rosters(team, bot, roster_num: Optional[int] = None) -> list:
|
|
sheets = get_sheets(bot)
|
|
this_sheet = sheets.open_by_key(team['gsheet'])
|
|
r_sheet = this_sheet.worksheet_by_title(f'My Rosters')
|
|
logger.debug(f'this_sheet: {this_sheet} / r_sheet = {r_sheet}')
|
|
|
|
all_rosters = [None, None, None]
|
|
|
|
# Pull roster 1
|
|
if not roster_num or roster_num == 1:
|
|
roster_1 = r_sheet.range('B3:B28')
|
|
roster_name = r_sheet.cell('F30').value
|
|
logger.info(f'roster_1: {roster_1}')
|
|
|
|
if not roster_1[0][0].value == '':
|
|
all_rosters[0] = {'name': roster_name, 'roster_num': 1, 'team_id': team['id'], 'cards': None}
|
|
all_rosters[0]['cards'] = [int(x[0].value) for x in roster_1]
|
|
|
|
# Pull roster 2
|
|
if not roster_num or roster_num == 2:
|
|
roster_2 = r_sheet.range('B29:B54')
|
|
roster_name = r_sheet.cell('F31').value
|
|
logger.info(f'roster_2: {roster_2}')
|
|
|
|
if not roster_2[0][0].value == '':
|
|
all_rosters[1] = {'name': roster_name, 'roster_num': 2, 'team_id': team['id'], 'cards': None}
|
|
all_rosters[1]['cards'] = [int(x[0].value) for x in roster_2]
|
|
|
|
# Pull roster 3
|
|
if not roster_num or roster_num == 3:
|
|
roster_3 = r_sheet.range('B55:B80')
|
|
roster_name = r_sheet.cell('F32').value
|
|
logger.info(f'roster_3: {roster_3}')
|
|
|
|
if not roster_3[0][0].value == '':
|
|
all_rosters[2] = {'name': roster_name, 'roster_num': 3, 'team_id': team['id'], 'cards': None}
|
|
all_rosters[2]['cards'] = [int(x[0].value) for x in roster_3]
|
|
|
|
return all_rosters
|
|
|
|
|
|
def get_roster_lineups(team, bot, roster_num, lineup_num) -> list:
|
|
sheets = get_sheets(bot)
|
|
logger.debug(f'sheets: {sheets}')
|
|
this_sheet = sheets.open_by_key(team['gsheet'])
|
|
logger.debug(f'this_sheet: {this_sheet}')
|
|
r_sheet = this_sheet.worksheet_by_title('My Rosters')
|
|
logger.debug(f'r_sheet: {r_sheet}')
|
|
|
|
if lineup_num == 1:
|
|
row_start = 9
|
|
row_end = 17
|
|
else:
|
|
row_start = 18
|
|
row_end = 26
|
|
|
|
if roster_num == 1:
|
|
l_range = f'H{row_start}:I{row_end}'
|
|
elif roster_num == 2:
|
|
l_range = f'J{row_start}:K{row_end}'
|
|
else:
|
|
l_range = f'L{row_start}:M{row_end}'
|
|
|
|
logger.debug(f'l_range: {l_range}')
|
|
raw_cells = r_sheet.range(l_range)
|
|
logger.debug(f'raw_cells: {raw_cells}')
|
|
|
|
try:
|
|
lineup_cells = [(row[0].value, int(row[1].value)) for row in raw_cells]
|
|
except ValueError as e:
|
|
logger.error(f'Could not pull roster for {team["abbrev"]} due to a ValueError')
|
|
raise ValueError(f'Uh oh. Looks like your roster might not be saved. I am reading blanks when I try to '
|
|
f'get the card IDs')
|
|
logger.debug(f'lineup_cells: {lineup_cells}')
|
|
|
|
return lineup_cells
|
|
|
|
|
|
def post_ratings_guide(team, bot, this_sheet=None):
|
|
if not this_sheet:
|
|
sheets = get_sheets(bot)
|
|
this_sheet = sheets.open_by_key(team['gsheet'])
|
|
p_guide = this_sheet.worksheet_by_title('Full Guide - Pitchers')
|
|
b_guide = this_sheet.worksheet_by_title('Full Guide - Batters')
|
|
|
|
p_guide.update_value('A1', RATINGS_PITCHER_FORMULA)
|
|
b_guide.update_value('A1', RATINGS_BATTER_FORMULA)
|
|
|
|
|
|
async def legal_channel(ctx):
|
|
bad_channels = ['paper-dynasty-chat', 'pd-news-ticker', 'pd-network-news']
|
|
|
|
if isinstance(ctx, commands.Context):
|
|
if ctx.channel.name in bad_channels:
|
|
raise commands.CheckFailure(f'Slide on down to the {get_channel(ctx, "pd-bot-hole").mention} ;)')
|
|
else:
|
|
return True
|
|
|
|
elif ctx.channel.name in bad_channels:
|
|
# await ctx.message.add_reaction('❌')
|
|
# await ctx.send(f'Slide on down to the {get_channel(ctx, "pd-bot-hole").mention} ;)')
|
|
# logger.warning(f'{ctx.author.name} posted in illegal channel.')
|
|
# return False
|
|
raise discord.app_commands.AppCommandError(f'Slide on down to the {get_channel(ctx, "pd-bot-hole").mention} ;)')
|
|
else:
|
|
return True
|
|
|
|
|
|
def owner_only(interaction: discord.Interaction):
|
|
if interaction.user.id == 258104532423147520:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
def get_role(ctx, role_name):
|
|
return discord.utils.get(ctx.guild.roles, name=role_name)
|
|
|
|
|
|
async def team_summary_embed(team, ctx, include_roster: bool = True):
|
|
embed = get_team_embed(f'{team["lname"]} Overview', team)
|
|
|
|
embed.add_field(name='General Manager', value=team['gmname'], inline=False)
|
|
embed.add_field(name='Wallet', value=f'{team["wallet"]}₼')
|
|
# embed.add_field(name='Collection Value', value=team['collection_value'])
|
|
|
|
p_query = await db_get('packs', params=[('team_id', team['id']), ('opened', False)])
|
|
if p_query['count'] > 0:
|
|
all_packs = {}
|
|
for x in p_query['packs']:
|
|
if x['pack_type']['name'] not in all_packs:
|
|
all_packs[x['pack_type']['name']] = 1
|
|
else:
|
|
all_packs[x['pack_type']['name']] += 1
|
|
|
|
pack_string = ''
|
|
for pack_type in all_packs:
|
|
pack_string += f'{pack_type.title()}: {all_packs[pack_type]}\n'
|
|
else:
|
|
pack_string = 'None'
|
|
embed.add_field(name='Unopened Packs', value=pack_string)
|
|
embed.add_field(name='Team Rating', value=f'{team["ranking"]}')
|
|
|
|
r_query = await db_get(f'results/team/{team["id"]}?season={PD_SEASON}')
|
|
if r_query:
|
|
embed.add_field(
|
|
name='Record',
|
|
value=f'Ranked: {r_query["ranked_wins"]}-{r_query["ranked_losses"]}\n'
|
|
f'Unlimited: {r_query["casual_wins"]}-{r_query["casual_losses"]}'
|
|
)
|
|
|
|
# try:
|
|
# r_query = await db_get('rosters', params=[('team_id', team['id'])])
|
|
# if r_query['count']:
|
|
# embed.add_field(name=f'Rosters', value=f'** **', inline=False)
|
|
# for roster in r_query['rosters']:
|
|
# roster_string = ''
|
|
# for i in range(1, 27):
|
|
# card = roster[f'card_{i}']
|
|
# roster_string += f'{card["player"]["description"]} ({card["player"]["pos_1"]})\n'
|
|
# embed.add_field(
|
|
# name=f'{roster["name"]} Roster',
|
|
# value=roster_string if len(roster_string) else "Unknown"
|
|
# )
|
|
# else:
|
|
# embed.add_field(
|
|
# name='Rosters',
|
|
# value='You can set up to three rosters for quick switching from your team sheet.',
|
|
# inline=False
|
|
# )
|
|
# except Exception as e:
|
|
# logger.error(f'Could not pull rosters for {team["abbrev"]}')
|
|
# embed.add_field(
|
|
# name='Rosters',
|
|
# value='Unable to pull current rosters. `/pullroster` to sync.',
|
|
# inline=False
|
|
# )
|
|
|
|
if include_roster:
|
|
embed.add_field(name='Team Sheet', value=get_roster_sheet(team, allow_embed=True), inline=False)
|
|
|
|
embed.add_field(
|
|
name='For Help',
|
|
value=f'`/help-pd` has FAQs; feel free to post questions in '
|
|
f'{get_channel(ctx, "paper-dynasty-chat").mention}.',
|
|
inline=False
|
|
)
|
|
|
|
return embed
|
|
|
|
|
|
async def give_cards_to_team(team, players: list = None, player_ids: list = None, pack_id=None):
|
|
if not pack_id:
|
|
p_query = await db_post(
|
|
'packs/one',
|
|
payload={
|
|
'team_id': team['id'],
|
|
'pack_type_id': 4,
|
|
'open_time': datetime.datetime.timestamp(datetime.datetime.now()) * 1000}
|
|
)
|
|
pack_id = p_query['id']
|
|
|
|
if not players and not player_ids:
|
|
raise ValueError('One of players or player_ids must be provided to distribute cards')
|
|
|
|
if players:
|
|
await db_post('cards', payload={'cards': [
|
|
{'player_id': x['player_id'], 'team_id': team['id'], 'pack_id': pack_id} for x in players
|
|
]}, timeout=10)
|
|
elif player_ids:
|
|
await db_post('cards', payload={'cards': [
|
|
{'player_id': x, 'team_id': team['id'], 'pack_id': pack_id} for x in player_ids
|
|
]}, timeout=10)
|
|
|
|
|
|
def get_ratings_guide(sheets):
|
|
this_sheet = sheets.open_by_key(RATINGS_SHEET_KEY)
|
|
b_sheet = this_sheet.worksheet_by_title('ratings_Batters')
|
|
p_sheet = this_sheet.worksheet_by_title('ratings_Pitchers')
|
|
|
|
b_data = b_sheet.range('A2:N')
|
|
p_data = p_sheet.range('A2:N')
|
|
|
|
try:
|
|
batters = [
|
|
{
|
|
'player_id': int(x[0].value),
|
|
'p_name': x[1].value,
|
|
'rating': int(x[2].value),
|
|
'contact-r': int(x[3].value),
|
|
'contact-l': int(x[4].value),
|
|
'power-r': int(x[5].value),
|
|
'power-l': int(x[6].value),
|
|
'vision': int(x[7].value),
|
|
'speed': int(x[8].value),
|
|
'stealing': int(x[9].value),
|
|
'reaction': int(x[10].value),
|
|
'arm': int(x[11].value),
|
|
'fielding': int(x[12].value),
|
|
'hand': int(x[13].value),
|
|
} for x in b_data
|
|
]
|
|
pitchers = [
|
|
{
|
|
'player_id': int(x[0].value),
|
|
'p_name': x[1].value,
|
|
'rating': int(x[2].value),
|
|
'control-r': int(x[3].value),
|
|
'control-l': int(x[4].value),
|
|
'stuff-r': int(x[5].value),
|
|
'stuff-l': int(x[6].value),
|
|
'stamina': int(x[7].value),
|
|
'fielding': int(x[8].value),
|
|
'hit-9': int(x[9].value),
|
|
'k-9': int(x[10].value),
|
|
'bb-9': int(x[11].value),
|
|
'hr-9': int(x[12].value),
|
|
'hand': int(x[13].value),
|
|
} for x in p_data
|
|
]
|
|
except Exception as e:
|
|
return {'valid': False}
|
|
|
|
return {
|
|
'valid': True,
|
|
'batter_ratings': batters,
|
|
'pitcher_ratings': pitchers
|
|
}
|
|
|
|
|
|
async def paperdex_cardset_embed(team: dict, this_cardset: dict) -> list[discord.Embed]:
|
|
all_dex = await db_get(
|
|
'paperdex',
|
|
params=[('team_id', team['id']), ('cardset_id', this_cardset['id']), ('flat', True)]
|
|
)
|
|
dex_player_list = [x['player'] for x in all_dex['paperdex']]
|
|
|
|
hof_embed = get_team_embed(f'{team["lname"]} Collection', team=team)
|
|
mvp_embed = get_team_embed(f'{team["lname"]} Collection', team=team)
|
|
as_embed = get_team_embed(f'{team["lname"]} Collection', team=team)
|
|
sta_embed = get_team_embed(f'{team["lname"]} Collection', team=team)
|
|
res_embed = get_team_embed(f'{team["lname"]} Collection', team=team)
|
|
rep_embed = get_team_embed(f'{team["lname"]} Collection', team=team)
|
|
|
|
coll_data = {
|
|
99: {
|
|
'name': 'Hall of Fame',
|
|
'owned': 0,
|
|
'players': [],
|
|
'embeds': [hof_embed]
|
|
},
|
|
1: {
|
|
'name': 'MVP',
|
|
'owned': 0,
|
|
'players': [],
|
|
'embeds': [mvp_embed]
|
|
},
|
|
2: {
|
|
'name': 'All-Star',
|
|
'owned': 0,
|
|
'players': [],
|
|
'embeds': [as_embed]
|
|
},
|
|
3: {
|
|
'name': 'Starter',
|
|
'owned': 0,
|
|
'players': [],
|
|
'embeds': [sta_embed]
|
|
},
|
|
4: {
|
|
'name': 'Reserve',
|
|
'owned': 0,
|
|
'players': [],
|
|
'embeds': [res_embed]
|
|
},
|
|
5: {
|
|
'name': 'Replacement',
|
|
'owned': 0,
|
|
'players': [],
|
|
'embeds': [rep_embed]
|
|
},
|
|
'total_owned': 0
|
|
}
|
|
|
|
set_players = await db_get(
|
|
'players',
|
|
params=[('cardset_id', this_cardset['id']), ('flat', True), ('inc_dex', False)],
|
|
timeout=5
|
|
)
|
|
|
|
for player in set_players['players']:
|
|
if player['player_id'] in dex_player_list:
|
|
coll_data[player['rarity']]['owned'] += 1
|
|
coll_data['total_owned'] += 1
|
|
player['owned'] = True
|
|
else:
|
|
player['owned'] = False
|
|
|
|
logger.debug(f'player: {player} / type: {type(player)}')
|
|
coll_data[player['rarity']]['players'].append(player)
|
|
|
|
cover_embed = get_team_embed(f'{team["lname"]} Collection', team=team)
|
|
cover_embed.description = this_cardset['name']
|
|
cover_embed.add_field(name='# Total Cards', value=f'{set_players["count"]}')
|
|
cover_embed.add_field(name='# Collected', value=f'{coll_data["total_owned"]}')
|
|
display_embeds = [cover_embed]
|
|
|
|
for rarity_id in coll_data:
|
|
if rarity_id != 'total_owned':
|
|
if coll_data[rarity_id]['players']:
|
|
coll_data[rarity_id]['embeds'][0].description = f'Rarity: {coll_data[rarity_id]["name"]}'
|
|
coll_data[rarity_id]['embeds'][0].add_field(
|
|
name='# Collected / # Total Cards',
|
|
value=f'{coll_data[rarity_id]["owned"]} / {len(coll_data[rarity_id]["players"])}',
|
|
inline=False
|
|
)
|
|
|
|
chunk_string = ''
|
|
for index, this_player in enumerate(coll_data[rarity_id]['players']):
|
|
logger.debug(f'this_player: {this_player}')
|
|
chunk_string += '☑ ' if this_player['owned'] else '⬜ '
|
|
chunk_string += f'{this_player["p_name"]}\n'
|
|
|
|
if (index + 1) == len(coll_data[rarity_id]["players"]):
|
|
coll_data[rarity_id]['embeds'][0].add_field(
|
|
name=f'Group {math.ceil((index + 1) / 20)} / '
|
|
f'{math.ceil(len(coll_data[rarity_id]["players"]) / 20)}',
|
|
value=chunk_string
|
|
)
|
|
|
|
elif (index + 1) % 20 == 0:
|
|
coll_data[rarity_id]['embeds'][0].add_field(
|
|
name=f'Group {math.floor((index + 1) / 20)} / '
|
|
f'{math.ceil(len(coll_data[rarity_id]["players"]) / 20)}',
|
|
value=chunk_string
|
|
)
|
|
chunk_string = ''
|
|
|
|
display_embeds.append(coll_data[rarity_id]['embeds'][0])
|
|
|
|
return display_embeds
|
|
|
|
|
|
async def paperdex_team_embed(team: dict, mlb_team: dict) -> list[discord.Embed]:
|
|
all_dex = await db_get(
|
|
'paperdex',
|
|
params=[('team_id', team['id']), ('franchise', mlb_team['lname']), ('flat', True)]
|
|
)
|
|
dex_player_list = [x['player'] for x in all_dex['paperdex']]
|
|
|
|
c_query = await db_get('cardsets')
|
|
coll_data = {'total_owned': 0}
|
|
|
|
total_players = 0
|
|
for x in c_query['cardsets']:
|
|
set_players = await db_get(
|
|
'players',
|
|
params=[('cardset_id', x['id']), ('franchise', mlb_team['lname']), ('flat', True), ('inc_dex', False)]
|
|
)
|
|
if set_players is not None:
|
|
coll_data[x['id']] = {
|
|
'name': x['name'],
|
|
'owned': 0,
|
|
'players': [],
|
|
'embeds': [get_team_embed(f'{team["lname"]} Collection', team=team)]
|
|
}
|
|
total_players += set_players['count']
|
|
|
|
for player in set_players['players']:
|
|
if player['player_id'] in dex_player_list:
|
|
coll_data[x['id']]['owned'] += 1
|
|
coll_data['total_owned'] += 1
|
|
player['owned'] = True
|
|
else:
|
|
player['owned'] = False
|
|
|
|
logger.debug(f'player: {player} / type: {type(player)}')
|
|
coll_data[x['id']]['players'].append(player)
|
|
|
|
cover_embed = get_team_embed(f'{team["lname"]} Collection', team=team)
|
|
cover_embed.description = mlb_team['lname']
|
|
cover_embed.add_field(name='# Total Cards', value=f'{total_players}')
|
|
cover_embed.add_field(name='# Collected', value=f'{coll_data["total_owned"]}')
|
|
display_embeds = [cover_embed]
|
|
|
|
for cardset_id in coll_data:
|
|
if cardset_id != 'total_owned':
|
|
if coll_data[cardset_id]['players']:
|
|
coll_data[cardset_id]['embeds'][0].description = f'{mlb_team["lname"]} / ' \
|
|
f'{coll_data[cardset_id]["name"]}'
|
|
coll_data[cardset_id]['embeds'][0].add_field(
|
|
name='# Collected / # Total Cards',
|
|
value=f'{coll_data[cardset_id]["owned"]} / {len(coll_data[cardset_id]["players"])}',
|
|
inline=False
|
|
)
|
|
|
|
chunk_string = ''
|
|
for index, this_player in enumerate(coll_data[cardset_id]['players']):
|
|
logger.debug(f'this_player: {this_player}')
|
|
chunk_string += '☑ ' if this_player['owned'] else '⬜ '
|
|
chunk_string += f'{this_player["p_name"]}\n'
|
|
|
|
if (index + 1) == len(coll_data[cardset_id]["players"]):
|
|
coll_data[cardset_id]['embeds'][0].add_field(
|
|
name=f'Group {math.ceil((index + 1) / 20)} / '
|
|
f'{math.ceil(len(coll_data[cardset_id]["players"]) / 20)}',
|
|
value=chunk_string
|
|
)
|
|
|
|
elif (index + 1) % 20 == 0:
|
|
coll_data[cardset_id]['embeds'][0].add_field(
|
|
name=f'Group {math.floor((index + 1) / 20)} / '
|
|
f'{math.ceil(len(coll_data[cardset_id]["players"]) / 20)}',
|
|
value=chunk_string
|
|
)
|
|
chunk_string = ''
|
|
|
|
display_embeds.append(coll_data[cardset_id]['embeds'][0])
|
|
|
|
return display_embeds
|
|
|
|
|
|
def get_pack_cover(pack):
|
|
if pack['pack_cardset'] is not None and pack['pack_cardset'] == 23:
|
|
return IMAGES['pack-pkmnbs']
|
|
elif pack['pack_type']['name'] in ['Premium', 'MVP']:
|
|
return IMAGES['pack-pre']
|
|
elif pack['pack_type']['name'] == 'Standard':
|
|
return IMAGES['pack-sta']
|
|
elif pack['pack_type']['name'] == 'Mario':
|
|
return IMAGES['pack-mar']
|
|
else:
|
|
return None
|
|
|
|
|
|
async def open_st_pr_packs(all_packs: list, team: dict, context):
|
|
pack_channel = get_channel(context, 'pack-openings')
|
|
pack_cover = get_pack_cover(all_packs[0])
|
|
|
|
if pack_cover is None:
|
|
pack_channel = context.channel
|
|
|
|
if not pack_channel:
|
|
raise ValueError(f'I cannot find the pack-openings channel. {get_cal_user(context).mention} - halp?')
|
|
|
|
pack_ids = await roll_for_cards(all_packs)
|
|
if not pack_ids:
|
|
logger.error(f'open_packs - unable to roll_for_cards for packs: {all_packs}')
|
|
raise ValueError(f'I was not able to unpack these cards')
|
|
|
|
all_cards = []
|
|
for p_id in pack_ids:
|
|
new_cards = await db_get('cards', params=[('pack_id', p_id)])
|
|
all_cards.extend(new_cards['cards'])
|
|
|
|
if not all_cards:
|
|
logger.error(f'open_packs - unable to get cards for packs: {pack_ids}')
|
|
raise ValueError(f'I was not able to display these cards')
|
|
|
|
# Present cards to opening channel
|
|
if type(context) == commands.Context:
|
|
author = context.author
|
|
else:
|
|
author = context.user
|
|
|
|
await context.channel.send(content=f'Let\'s head down to {pack_channel.mention}!')
|
|
await display_cards(all_cards, team, pack_channel, author, pack_cover=pack_cover)
|
|
|
|
|
|
async def get_choice_from_cards(
|
|
interaction: discord.Interaction, all_players: list = None, cover_title: str = None,
|
|
cover_desc: str = None, cover_image_url: str = None, callback=None, temp_message: str = None,
|
|
conf_message: str = None, delete_message: bool = False):
|
|
# Display them with pagination, prev/next/select
|
|
card_embeds = [
|
|
await get_card_embeds(
|
|
{'player': x, 'team': {'lname': 'Paper Dynasty', 'season': PD_SEASON, 'logo': IMAGES['logo']}}
|
|
) for x in all_players
|
|
]
|
|
logger.debug(f'card embeds: {card_embeds}')
|
|
|
|
if cover_title is not None and cover_image_url is not None:
|
|
page_num = 0
|
|
|
|
view = Pagination([interaction.user], timeout=30)
|
|
view.left_button.disabled = True
|
|
view.left_button.label = f'Prev: -/{len(card_embeds)}'
|
|
view.cancel_button.label = f'Take This Card'
|
|
view.cancel_button.style = discord.ButtonStyle.success
|
|
view.cancel_button.disabled = True
|
|
view.right_button.label = f'Next: 1/{len(card_embeds)}'
|
|
|
|
msg = await interaction.channel.send(
|
|
content=None,
|
|
embed=image_embed(
|
|
image_url=cover_image_url,
|
|
title=cover_title,
|
|
desc=cover_desc
|
|
),
|
|
view=view
|
|
)
|
|
else:
|
|
page_num = 1
|
|
|
|
view = Pagination([interaction.user], timeout=30)
|
|
view.left_button.label = f'Prev: -/{len(card_embeds)}'
|
|
view.left_button.disabled = True
|
|
view.cancel_button.label = f'Take This Card'
|
|
view.cancel_button.style = discord.ButtonStyle.success
|
|
view.right_button.label = f'Next: {page_num + 1}/{len(card_embeds)}'
|
|
|
|
msg = await interaction.channel.send(content=None, embeds=card_embeds[page_num - 1], view=view)
|
|
|
|
if temp_message is not None:
|
|
temp_msg = await interaction.channel.send(content=temp_message)
|
|
else:
|
|
temp_msg = None
|
|
|
|
while True:
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
if view.value == 'cancel':
|
|
await msg.edit(view=None)
|
|
|
|
if callback is not None:
|
|
callback(all_players[page_num - 1])
|
|
|
|
if conf_message is not None:
|
|
if temp_msg is not None:
|
|
await temp_msg.edit(content=conf_message)
|
|
else:
|
|
await interaction.channel.send(content=conf_message)
|
|
break
|
|
if view.value == 'left':
|
|
page_num -= 1 if page_num > 1 else len(card_embeds)
|
|
if view.value == 'right':
|
|
page_num += 1 if page_num < len(card_embeds) else 1
|
|
else:
|
|
if page_num == len(card_embeds):
|
|
page_num = 1
|
|
else:
|
|
page_num += 1
|
|
|
|
view.value = None
|
|
|
|
view = Pagination([interaction.user], timeout=30)
|
|
view.left_button.label = f'Prev: {page_num - 1}/{len(card_embeds)}'
|
|
view.cancel_button.label = f'Take This Card'
|
|
view.cancel_button.style = discord.ButtonStyle.success
|
|
view.right_button.label = f'Next: {page_num + 1}/{len(card_embeds)}'
|
|
if page_num == 1:
|
|
view.left_button.label = f'Prev: -/{len(card_embeds)}'
|
|
view.left_button.disabled = True
|
|
elif page_num == len(card_embeds):
|
|
view.right_button.label = f'Next: -/{len(card_embeds)}'
|
|
view.right_button.disabled = True
|
|
|
|
await msg.edit(content=None, embeds=card_embeds[page_num - 1], view=view)
|
|
|
|
if delete_message:
|
|
await msg.delete()
|
|
return all_players[page_num - 1]
|
|
|
|
|
|
async def open_choice_pack(this_pack, team: dict, context, cardset_id: Optional[int] = None):
|
|
pack_channel = get_channel(context, 'pack-openings')
|
|
pack_cover = get_pack_cover(this_pack)
|
|
pack_type = this_pack['pack_type']['name']
|
|
|
|
players = []
|
|
|
|
if pack_type == 'Mario':
|
|
d1000 = random.randint(1, 1000)
|
|
if d1000 > 800:
|
|
rarity_id = 5
|
|
elif d1000 > 550:
|
|
rarity_id = 3
|
|
else:
|
|
rarity_id = 2
|
|
pl = await db_get(
|
|
'players/random',
|
|
params=[
|
|
('cardset_id', 8), ('min_rarity', rarity_id), ('max_rarity', rarity_id), ('limit', 4)
|
|
]
|
|
)
|
|
players = pl['players']
|
|
elif pack_type == 'Team Choice':
|
|
if this_pack['pack_team'] is None:
|
|
raise KeyError(f'Team not listed for Team Choice pack')
|
|
|
|
d1000 = random.randint(1, 1000)
|
|
pack_cover = this_pack['pack_team']['logo']
|
|
if d1000 > 800:
|
|
rarity_id = 5
|
|
pack_cover = IMAGES['mvp'][this_pack['pack_team']['lname']]
|
|
elif d1000 > 550:
|
|
rarity_id = 3
|
|
else:
|
|
rarity_id = 2
|
|
|
|
# # HAX FOR SOCC TO GET HIS MVP PACK
|
|
# if (team['abbrev'] in ['KSK', 'NJY']) and (datetime.datetime.today().day == 24):
|
|
# rarity_id = 5
|
|
|
|
min_rarity = rarity_id
|
|
while len(players) < 4 and rarity_id < 10:
|
|
params = [
|
|
('min_rarity', min_rarity), ('max_rarity', rarity_id), ('limit', 4 - len(players)),
|
|
('franchise', this_pack['pack_team']['lname'])
|
|
]
|
|
if this_pack['pack_team']['abbrev'] not in ['MSS']:
|
|
params.append(('in_packs', True))
|
|
if cardset_id is not None:
|
|
params.append(('cardset_id', cardset_id))
|
|
pl = await db_get(
|
|
'players/random',
|
|
params=params
|
|
)
|
|
if pl['count'] >= 0:
|
|
for x in pl['players']:
|
|
if x not in players:
|
|
players.append(x)
|
|
if len(players) < 4:
|
|
min_rarity += 1
|
|
rarity_id += 1
|
|
elif pack_type == 'Promo Choice':
|
|
if this_pack['pack_cardset'] is None:
|
|
raise KeyError(f'Cardset not listed for Promo Choice pack')
|
|
|
|
d1000 = random.randint(1, 1000)
|
|
pack_cover = IMAGES['mvp-hype']
|
|
cardset_id = this_pack['pack_cardset']['id']
|
|
rarity_id = 5
|
|
if d1000 > 800:
|
|
rarity_id = 8
|
|
|
|
while len(players) < 4 and rarity_id < 10:
|
|
pl = await db_get(
|
|
'players/random',
|
|
params=[('cardset_id', cardset_id), ('min_rarity', rarity_id), ('max_rarity', rarity_id),
|
|
('limit', 8)]
|
|
)
|
|
if pl['count'] >= 0:
|
|
for x in pl['players']:
|
|
if len(players) >= 4:
|
|
break
|
|
if x not in players:
|
|
players.append(x)
|
|
if len(players) < 4:
|
|
cardset_id = LIVE_CARDSET_ID
|
|
else:
|
|
# Get 4 MVP cards
|
|
rarity_id = 5
|
|
if pack_type == 'HoF':
|
|
rarity_id = 8
|
|
elif pack_type == 'All Star':
|
|
rarity_id = 3
|
|
|
|
min_rarity = rarity_id
|
|
while len(players) < 4 and rarity_id < 10:
|
|
params = [
|
|
('min_rarity', min_rarity), ('max_rarity', rarity_id), ('limit', 4), ('in_packs', True)
|
|
]
|
|
if this_pack['pack_team'] is not None:
|
|
params.append(('franchise', this_pack['pack_team']['lname']))
|
|
if cardset_id is not None:
|
|
params.append(('cardset_id', cardset_id))
|
|
pl = await db_get('players/random', params=params)
|
|
|
|
if pl['count'] > 0:
|
|
players.extend(pl['players'])
|
|
if len(players) < 4:
|
|
rarity_id += 3
|
|
|
|
if len(players) == 0:
|
|
logger.error(f'Could not create choice pack')
|
|
raise ConnectionError(f'Could not create choice pack')
|
|
|
|
if type(context) == commands.Context:
|
|
author = context.author
|
|
else:
|
|
author = context.user
|
|
|
|
logger.info(f'helpers - open_choice_pack - players: {players}')
|
|
|
|
# Display them with pagination, prev/next/select
|
|
card_embeds = [
|
|
await get_card_embeds(
|
|
# {'player': x, 'team': {'lname': 'Paper Dynasty', 'season': PD_SEASON, 'logo': IMAGES['logo']}}
|
|
{'player': x, 'team': team} # Show team and dupe info
|
|
) for x in players
|
|
]
|
|
logger.debug(f'card embeds: {card_embeds}')
|
|
page_num = 0
|
|
|
|
view = Pagination([author], timeout=30)
|
|
view.left_button.disabled = True
|
|
view.left_button.label = f'Prev: -/{len(card_embeds)}'
|
|
view.cancel_button.label = f'Take This Card'
|
|
view.cancel_button.style = discord.ButtonStyle.success
|
|
view.cancel_button.disabled = True
|
|
view.right_button.label = f'Next: 1/{len(card_embeds)}'
|
|
|
|
# React to selection
|
|
await context.channel.send(f'Let\'s head down to {pack_channel.mention}!')
|
|
msg = await pack_channel.send(
|
|
content=None,
|
|
embed=image_embed(pack_cover, title=f'{team["lname"]}', desc=f'{pack_type} Pack - Choose 1 of 4 {pack_type}s!'),
|
|
view=view
|
|
)
|
|
if rarity_id >= 5:
|
|
tmp_msg = await pack_channel.send(content=f'<@&1163537676885033010> we\'ve got an MVP!')
|
|
else:
|
|
tmp_msg = await pack_channel.send(content=f'We\'ve got a choice pack here!')
|
|
|
|
while True:
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
if view.value == 'cancel':
|
|
await msg.edit(view=None)
|
|
|
|
try:
|
|
await give_cards_to_team(team, players=[players[page_num - 1]], pack_id=this_pack['id'])
|
|
except Exception as e:
|
|
logger.error(f'failed to create cards: {e}')
|
|
raise ConnectionError(f'Failed to distribute these cards.')
|
|
|
|
await db_patch('packs', object_id=this_pack['id'], params=[
|
|
('open_time', int(datetime.datetime.timestamp(datetime.datetime.now()) * 1000))
|
|
])
|
|
await tmp_msg.edit(
|
|
content=f'{players[page_num - 1]["p_name"]} has been added to the '
|
|
f'**{team["sname"]}** binder!'
|
|
)
|
|
break
|
|
if view.value == 'left':
|
|
page_num -= 1 if page_num > 1 else len(card_embeds)
|
|
if view.value == 'right':
|
|
page_num += 1 if page_num < len(card_embeds) else 1
|
|
else:
|
|
if page_num == len(card_embeds):
|
|
page_num = 1
|
|
else:
|
|
page_num += 1
|
|
|
|
view.value = None
|
|
|
|
view = Pagination([author], timeout=30)
|
|
view.left_button.label = f'Prev: {page_num - 1}/{len(card_embeds)}'
|
|
view.cancel_button.label = f'Take This Card'
|
|
view.cancel_button.style = discord.ButtonStyle.success
|
|
view.right_button.label = f'Next: {page_num + 1}/{len(card_embeds)}'
|
|
if page_num == 1:
|
|
view.left_button.label = f'Prev: -/{len(card_embeds)}'
|
|
view.left_button.disabled = True
|
|
elif page_num == len(card_embeds):
|
|
view.right_button.label = f'Next: -/{len(card_embeds)}'
|
|
view.right_button.disabled = True
|
|
|
|
await msg.edit(content=None, embeds=card_embeds[page_num - 1], view=view)
|
|
|
|
|
|
async def confirm_pack_purchase(interaction, owner_team, num_packs, total_cost, pack_embed):
|
|
view = Confirm(responders=[interaction.user], timeout=30)
|
|
await interaction.channel.send(
|
|
content=None,
|
|
embed=pack_embed
|
|
)
|
|
question = await interaction.channel.send(
|
|
content=f'Your Wallet: {owner_team["wallet"]}₼\n'
|
|
f'Pack{"s" if num_packs > 1 else ""} Price: {total_cost}₼\n'
|
|
f'After Purchase: {owner_team["wallet"] - total_cost}₼\n\n'
|
|
f'Would you like to make this purchase?',
|
|
view=view
|
|
)
|
|
await view.wait()
|
|
|
|
if not view.value:
|
|
await question.edit(
|
|
content='Saving that money. Smart.',
|
|
view=None
|
|
)
|
|
return None
|
|
else:
|
|
return question
|
|
|
|
|
|
def player_desc(this_player) -> str:
|
|
if this_player['p_name'] in this_player['description']:
|
|
return this_player['description']
|
|
return f'{this_player["description"]} {this_player["p_name"]}'
|
|
|
|
|
|
def player_pcard(this_player):
|
|
if this_player['image'] is not None and 'pitching' in this_player['image']:
|
|
return this_player['image']
|
|
elif this_player['image2'] is not None and 'pitching' in this_player['image2']:
|
|
return this_player['image2']
|
|
else:
|
|
return this_player['image']
|
|
|
|
|
|
def player_bcard(this_player):
|
|
if this_player['image'] is not None and 'batting' in this_player['image']:
|
|
return this_player['image']
|
|
elif this_player['image2'] is not None and 'batting' in this_player['image2']:
|
|
return this_player['image2']
|
|
# elif this_player['image'] is not None and 'pitching' in this_player['image']:
|
|
# return PITCHER_BATTING_CARD
|
|
else:
|
|
return this_player['image']
|
|
|
|
|
|
def random_gif(search_term: str):
|
|
req_url = f'https://api.giphy.com/v1/gifs/translate?s={search_term}&api_key=H86xibttEuUcslgmMM6uu74IgLEZ7UOD'
|
|
|
|
resp = requests.get(req_url, timeout=3)
|
|
if resp.status_code == 200:
|
|
data = resp.json()
|
|
if 'trump' in data['data']['title']:
|
|
return random_conf_gif()
|
|
else:
|
|
return data['data']['url']
|
|
else:
|
|
logger.warning(resp.text)
|
|
raise ValueError(f'DB: {resp.text}')
|
|
|
|
|
|
def random_from_list(data_list: list):
|
|
item = data_list[random.randint(0, len(data_list) - 1)]
|
|
logger.info(f'random_from_list: {item}')
|
|
return item
|
|
|
|
|
|
def user_has_role(user: discord.User | discord.Member, role_name: str) -> bool:
|
|
for x in user.roles:
|
|
if x.name == role_name:
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def random_insult() -> str:
|
|
return random_from_list(INSULTS)
|
|
|
|
|
|
def position_name_to_abbrev(position_name):
|
|
if position_name == 'Catcher':
|
|
return 'C'
|
|
elif position_name == 'First Base':
|
|
return '1B'
|
|
elif position_name == 'Second Base':
|
|
return '2B'
|
|
elif position_name == 'Third Base':
|
|
return '3B'
|
|
elif position_name == 'Shortstop':
|
|
return 'SS'
|
|
elif position_name == 'Left Field':
|
|
return 'LF'
|
|
elif position_name == 'Center Field':
|
|
return 'CF'
|
|
elif position_name == 'Right Field':
|
|
return 'RF'
|
|
else:
|
|
log_exception(NameError, f'{position_name} not recognized')
|