Skip to content

Commit

Permalink
FoD Food War Commands (#512)
Browse files Browse the repository at this point in the history
* wip

* eraser wipe frames

* fade in and out

* eraser wipe in place

* zero draw frames

* final polish

* lil tweaks to nexttrek and cornmander
zmattingly authored Mar 31, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 9b3f8f1 commit 6b5efca
Showing 81 changed files with 334 additions and 46 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -130,6 +130,8 @@ images/profiles/*.png
images/profiles/*.jpg
images/cards/users/*.png
images/ep*
images/food_war/*.gif
images/food_war/*.png
images/slot_results/*.png
images/tongo/*.png
images/trades/*.png
253 changes: 253 additions & 0 deletions commands/food_war.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
import time
import pytz

from common import *
from utils.check_channel_access import access_check


# Create drop Slash Command Group
food_war = bot.create_group("food_war", "FoD Food War Commands!")

@food_war.command(
name="reset",
description="Reset the days since last FoD Food War",
)
@option(
name="reason",
description="Reason for reset?",
required=True,
min_length=1,
max_length=64
)
@commands.check(access_check)
async def reset(ctx:discord.ApplicationContext, reason:str):
await ctx.defer()

previous_reset = db_get_previous_reset()

embed = discord.Embed(
title="Resetting Days Since Last FoD Food War...",
description=f"{ctx.author.mention} is resetting the clock!",
color=discord.Color.gold()
)
embed.add_field(
name="Reason",
value=reason,
inline=False
)
if previous_reset:
pst_tz = pytz.timezone('America/Los_Angeles')
raw_now = datetime.utcnow().replace(tzinfo=pytz.utc)
raw_time_created = pytz.utc.localize(previous_reset['time_created'])
aware_now = pst_tz.normalize(raw_now.astimezone(pst_tz))
aware_time_created = pst_tz.normalize(raw_time_created.astimezone(pst_tz))

lifespan = aware_now - aware_time_created
days = lifespan.days

embed.add_field(
name="Previous Days",
value=f"{days} {'Day' if days == 1 else 'Days'}",
)
embed.add_field(
name=f"Previous Reason",
value=previous_reset['reason'],
)
else:
days = 0

db_reset_days(ctx.author.id, reason, days)

gif = await generate_food_war_reset_gif(days)
embed.set_image(url=f"attachment://{gif.filename}")
embed.set_footer(text="Again!? 💣")
await ctx.followup.send(embed=embed, file=gif)


@food_war.command(
name="check",
description="Check how many days it's been since last FoD Food War",
)
@commands.check(access_check)
async def check(ctx:discord.ApplicationContext):
previous_reset = db_get_previous_reset()

if not previous_reset:
await ctx.respond(
embed=discord.Embed(
title="No Wars Registered Yet!",
color=discord.Color.red()
),
ephemeral=True
)
return

await ctx.defer()

pst_tz = pytz.timezone('America/Los_Angeles')
raw_now = datetime.utcnow().replace(tzinfo=pytz.utc)
raw_time_created = pytz.utc.localize(previous_reset['time_created'])
aware_now = pst_tz.normalize(raw_now.astimezone(pst_tz))
aware_time_created = pst_tz.normalize(raw_time_created.astimezone(pst_tz))

lifespan = aware_now - aware_time_created
days = lifespan.days

embed = discord.Embed(
title=f"The Last FoD Food War...",
description=f"was {days} {'Day' if days == 1 else 'Days'} ago...",
color=discord.Color.gold()
)

embed.add_field(
name="Previous Days Streak",
value=f"{previous_reset['days']} {'Day' if previous_reset['days'] == 1 else 'Days'}",
)
embed.add_field(
name=f"Previous Reason",
value=previous_reset['reason'],
)

longest_reset = db_get_longest_reset()
if previous_reset['id'] == longest_reset['id']:
embed.add_field(
name="All-Time Longest Streak Was The Previous!",
value=f"Holy Guacamole! 🥑",
inline=False
)
else:
embed.add_field(
name="All-Time Longest Streak",
value=f"{longest_reset['days']} {'Day' if longest_reset['days'] == 1 else 'Days'}",
inline=False
)
embed.add_field(
name=f"All-Time Longest Streak Reason",
value=longest_reset['reason'],
inline=False
)

png = await generate_food_war_check_png(days)
embed.set_image(url=f"attachment://{png.filename}")
embed.set_footer(text="We can only hope it shall last longer... 🥑 ⚔️ 🙏")
await ctx.followup.send(embed=embed, file=png)


@to_thread
def generate_food_war_check_png(days):
marker_font = ImageFont.truetype("fonts/PermanentMarker.ttf", 200)

base_width = 600
base_height = 775

food_war_sign_image = Image.open("./images/templates/food_war/blank_sign.png").convert("RGBA")
food_war_base_image = Image.new("RGBA", (base_width, base_height), (0, 0, 0))
food_war_base_image.paste(food_war_sign_image, (0, 0))

d = ImageDraw.Draw(food_war_base_image)
d.text( (base_width/2, 200), f"{days}", fill=(0, 0, 0, 255), font=marker_font, anchor="mm", align="center")

image_filename = "current_days.png"
image_filepath = f"./images/food_war/{image_filename}"
if os.path.exists(image_filepath):
os.remove(image_filepath)

food_war_base_image.save(image_filepath)

while True:
time.sleep(0.05)
if os.path.isfile(image_filepath):
break

discord_image = discord.File(fp=image_filepath, filename=image_filename)
return discord_image

@to_thread
def generate_food_war_reset_gif(days):
marker_font = ImageFont.truetype("fonts/PermanentMarker.ttf", 200)

base_width = 600
base_height = 775

food_war_sign_image = Image.open("./images/templates/food_war/blank_sign.png").convert("RGBA")
food_war_base_image = Image.new("RGBA", (base_width, base_height), (0, 0, 0))
food_war_base_image.paste(food_war_sign_image, (0, 0))

base_text_frame = food_war_base_image.copy()
d = ImageDraw.Draw(base_text_frame)
d.text( (base_width/2, 200), f"{days}", fill=(0, 0, 0, 255), font=marker_font, anchor="mm", align="center")
frames = [base_text_frame]*20

# Eraser Wipe
for n in range(0, 54):
frame = base_text_frame.copy()
wipe_frame = Image.open(f"./images/templates/food_war/wipe/{'{:02d}'.format(n)}.png").convert('RGBA')
frame.paste(wipe_frame, (110, 85), wipe_frame)
frames.append(frame)

# Blank Frames
blank_frame = food_war_base_image.copy()
frames = frames + [blank_frame]*10

# Draw Zero
for n in range(0, 13):
frame = blank_frame.copy()
draw_frame = Image.open(f"./images/templates/food_war/draw/{'{:02d}'.format(n)}.png").convert('RGBA')
frame.paste(draw_frame, (110, 85), draw_frame)
frames.append(frame)

if n == 12:
frames = frames + [frame]*30

# Save
image_filename = "days_since_last_fod_food_war.gif"
image_filepath = f"./images/food_war/{image_filename}"
if os.path.exists(image_filepath):
os.remove(image_filepath)

frames[0].save(
image_filepath,
save_all=True, append_images=frames[1:], optimize=False, duration=40, loop=0
)

while True:
time.sleep(0.05)
if os.path.isfile(image_filepath):
break

discord_image = discord.File(fp=image_filepath, filename=image_filename)
return discord_image


def db_get_previous_reset():
with AgimusDB(dictionary=True) as query:
sql = "SELECT * FROM food_war ORDER BY id DESC LIMIT 1"
query.execute(sql)
previous_reset = query.fetchone()
return previous_reset

def db_reset_days(user_discord_id, reason, days):
with AgimusDB(dictionary=True) as query:
sql = "INSERT INTO food_war (user_discord_id, reason, days) VALUES (%s, %s, %s)"
vals = (user_discord_id, reason, days)
query.execute(sql, vals)

def db_get_longest_reset():
with AgimusDB(dictionary=True) as query:
sql = '''
SELECT fw.*
FROM (select fw.*,
(SELECT time_created
FROM food_war fw2
WHERE fw2.time_created > fw.time_created
ORDER BY time_created
LIMIT 1
) AS next_time_created
FROM food_war fw
) fw
ORDER BY timestampdiff(second, time_created, next_time_created) DESC
LIMIT 1;
'''
query.execute(sql)
longest_reset = query.fetchone()
return longest_reset
2 changes: 1 addition & 1 deletion commands/info.py
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ async def title_autocomplete(ctx: discord.AutocompleteContext):
return ['Invalid Show!']

@bot.slash_command(
name="info",
name="episode_info",
description="Get information about episodes of a show"
)
@option(
70 changes: 29 additions & 41 deletions commands/nextep.py
Original file line number Diff line number Diff line change
@@ -7,54 +7,42 @@

@bot.slash_command(
name="nexttrek",
description="Retrieve info on the next Trek episode",
)
@option(
name="show",
description="Which show?",
required=True,
choices=[
discord.OptionChoice(
name="Lower Decks",
value="lowerdecks"
),
discord.OptionChoice(
name="Picard",
value="picard"
),
discord.OptionChoice(
name="Prodigy",
value="prodigy"
),
discord.OptionChoice(
name="Strange New Worlds",
value="snw"
)
]
description="Retrieve info on the next upcoming Trek episode",
)
@commands.check(access_check)
async def nexttrek(ctx, show:str):
async def nexttrek(ctx:discord.ApplicationContext):
await ctx.defer()

tvmaze_ids = {
"discovery": 7480,
"lowerdecks": 39323,
"picard": 42193,
"prodigy": 49333,
"snw": 48090,
}
show_id = tvmaze_ids.get(show)
try:
show_data = requests.get(f"https://api.tvmaze.com/shows/{show_id}").json()
show_name = show_data["name"]
next_episode = show_data["_links"].get("nextepisode")
if (next_episode == None):
await ctx.respond(f"{get_emoji('ezri_frown_sad')} Sorry, doesn't look like we have info scheduled for the next episode of {show_name}.", ephemeral=True)
else:
episode_data = requests.get(next_episode["href"]).json()
embed = await get_next_episode_embed(show_data, episode_data)
await ctx.respond(embed=embed)
except Exception as err:
logger.error(err)
await ctx.respond(f"{get_emoji('emh_doctor_omg_wtf_zoom')} Sorry, something went wrong with the request!", ephemeral=True)
latest_episode_date = None
latest_episode_data = None
for show_id in tvmaze_ids.values():
try:
show_data = requests.get(f"https://api.tvmaze.com/shows/{show_id}").json()
next_episode = show_data["_links"].get("nextepisode")
if next_episode:
episode_data = requests.get(next_episode["href"]).json()
episode_date = episode_data['airdate']
if latest_episode_date is None or episode_date > latest_episode_date:
latest_episode_date = episode_date
latest_episode_data = episode_data
except Exception as err:
logger.error(err)

if latest_episode_data:
embed = await get_next_episode_embed(show_data, latest_episode_data)
await ctx.respond(embed=embed)
else:
await ctx.respond(embed=discord.Embed(
title="No Upcoming Trek Episode Data Found!",
description="Sadly there doesn't appear to be any impending Trek episodes coming up.\n\n"
"Please try again later!",
color=discord.Color.red()
))

@bot.slash_command(
name="nextep",
30 changes: 30 additions & 0 deletions configuration.json
Original file line number Diff line number Diff line change
@@ -488,6 +488,36 @@
"data": "data/all_characters.txt",
"parameters": []
},
"food_war check": {
"blocked_channels": [
"neelixs-morale-office",
"plasma-vent",
"counselor-trois-waiting-room",
"peoples-resistance-front-of-bajor",
"heuristic-associative-pathways",
"behind-the-visor",
"the-next-next-generation",
"sicks-bay"
],
"enabled": true,
"data": null,
"parameters": []
},
"food_war reset": {
"blocked_channels": [
"neelixs-morale-office",
"plasma-vent",
"counselor-trois-waiting-room",
"peoples-resistance-front-of-bajor",
"heuristic-associative-pathways",
"behind-the-visor",
"the-next-next-generation",
"sicks-bay"
],
"enabled": true,
"data": null,
"parameters": []
},
"gifbomb": {
"allowed_roles": [
"Admiral",
Loading

0 comments on commit 6b5efca

Please sign in to comment.