Skip to content

Commit

Permalink
Merge pull request #26 from yomcube/nsmbw-pr
Browse files Browse the repository at this point in the history
NSMBW changes
  • Loading branch information
Dash-QC authored Dec 11, 2024
2 parents b166078 + 8e4ea66 commit 3b925b8
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 18 deletions.
63 changes: 50 additions & 13 deletions api/nsmbwii/nsmbwii_file_handling.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from api.submissions import handle_submissions, first_time_submission
from api.utils import is_task_currently_running, readable_to_float, get_team_size, is_in_team, get_leader
from api.nsmbwii.nsmbwii_utils import get_vi_count
from api.utils import is_task_currently_running, readable_to_float, get_team_size, is_in_team, get_leader, is_task_currently_running
from commands.db.requesttask import has_requested_already, is_time_over
from api.db_classes import get_session, Submissions, Teams, Userbase
from sqlalchemy import insert, update, select
from struct import unpack
Expand All @@ -10,9 +10,42 @@ async def handle_nsmbwii_files(message, attachments, file_dict, self):
current_task = await is_task_currently_running()

if file_dict.get("dtm") is not None:
index = file_dict.get("dtm")

if current_task:
##################################################
# Cases where someone is denied submission
##################################################

# Speed task: Has not requested task, or time is over
is_speed_task = (await is_task_currently_running())[4]
is_released = (await is_task_currently_running())[7]

if is_speed_task:
if not (await has_requested_already(message.author.id)) and not is_released:
await message.channel.send("You may not submit yet! Use `$requesttask` first.")
return

if await is_time_over(message.author.id):
# If they have not submitted, they get a different message.
async with get_session() as session:
query = select(Submissions.user_id).where(Submissions.user_id == message.author.id)
result = (await session.execute(query)).first()


if result is None:
message_to_send = (f"You can't submit, your time is up! If you wish to send in a late submission, "
f"please DM the current host so they can add your submission manually.")

else:
message_to_send = "You can't submit, your time is up!"


await message.channel.send(message_to_send)
return

##################################################
# Otherwise continue
##################################################

# handle submission
await handle_submissions(message, self)
Expand All @@ -24,10 +57,10 @@ async def handle_nsmbwii_files(message, attachments, file_dict, self):
try:
dtm = bytearray(dtm_data)
if dtm[:4] == b'DTM\x1A':
vi_count = unpack('<L', dtm[0xD:0x11])[0]
vi_count = unpack("<Q", dtm[0xD:0x15])[0]

# float time to upload to db
time = vi_count / 60
time = vi_count

except UnboundLocalError:
# This exception catches blank dtm files
Expand All @@ -49,29 +82,33 @@ async def handle_nsmbwii_files(message, attachments, file_dict, self):
####################
# Adding submission
####################


url = " ".join(a.url for a in attachments)

# Hacky, but the character is set with the DTM bytes so
# another field doesn't have to be added to the DB

# first time submission (within the task)
if await first_time_submission(submitter_id):
async with get_session() as session:
await session.execute(insert(Submissions).values(task=current_task[0], name=submitter_name,
user_id=submitter_id,
url=attachments[index].url, time=time, dq=0,
dq_reason=''))
url=url, time=time, character=dtm,
dq=0, dq_reason=''))
await session.commit()

# If not first submission: replace old submission
else:
async with get_session() as session:
await session.execute(update(Submissions).values(url=attachments[index].url, time=time)
await session.execute(update(Submissions).values(url=url, time=time, character=dtm)
.where(Submissions.user_id == submitter_id))
await session.commit()

# Tell the user the submission has been received
print(f"File received!\nBy: {message.author}\nMessage sent: {message.content}")
await message.channel.send(
"`.dtm` file detected!\nThe file was successfully saved. "
"Type `$info` for more information about the file.")
"`.dtm` file detected!\nThe file was successfully saved.")

# No ongoing task
else:
await message.channel.send("There is no active task yet.")

await message.channel.send("There is no active task.")
6 changes: 4 additions & 2 deletions api/submissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

if DEFAULT == 'mkw':
guild_id = 1214800758881394718
elif DEFAULT == 'nsmbw':
guild_id = 1238999592947810366


async def get_submission_channel(comp):
Expand Down Expand Up @@ -245,8 +247,8 @@ async def handle_dms(message, self):
channel = self.bot.get_channel(await get_logs_channel(DEFAULT))
attachments = message.attachments
if channel:
await channel.send("Message from " + str(author_dn) + ": " + message.content + " "
.join([attachment.url for attachment in message.attachments if message.attachments]))
await channel.send(f"Message from {author_dn}: {message.content} " +
" ".join([attachment.url for attachment in message.attachments if message.attachments]))

#########################
# Recognizing submission
Expand Down
94 changes: 94 additions & 0 deletions commands/db/info_nsmbw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import discord
from discord.ext import commands
from api.utils import float_to_readable, get_team_size, is_in_team, get_leader
from api.db_classes import Submissions, get_session
from sqlalchemy import select
from struct import unpack


class Info(commands.Cog):
def __init__(self, bot):
self.bot = bot

@commands.command(name="info", aliases=['status'])
@commands.dm_only()
async def info(self, ctx):
async with get_session() as session:
# Verify if collab task, and if author is in a team
team_size = await get_team_size()

# TODO: Temporary fix for a bug where you can't use $info after task has ended; currently only will work for
# solo tasks after task has ended

if team_size is not None and team_size > 1 and await is_in_team(ctx.author.id):
submission_id = await get_leader(ctx.author.id)
else:
submission_id = ctx.author.id


# Get submission
submission = (await session.execute(select(Submissions.task, Submissions.url, Submissions.time,
Submissions.dq, Submissions.dq_reason, Submissions.character)
.where(Submissions.user_id == submission_id))).fetchone()

if not submission:
await ctx.reply("Either there is no ongoing task, or you have not submitted.")
return

# variables for all the columns
task_num = submission[0]
url = submission[1]
time = submission[2]
dq = bool(submission[3])
dq_reason = submission[4]
dtm = submission[5]

def yesno(b):
return "Yes" if bool(b) else "No"

embed = discord.Embed(title=f"Task {task_num} submission", color=discord.Color.from_rgb(0, 235, 0))

embed.add_field(name="File", value=url, inline=True)
embed.add_field(name="Time", value=f"{time / 60} seconds", inline=True)
embed.add_field(name="DQ", value=yesno(dq), inline=True)
if dq:
embed.add_field(name="DQ reason", value=dq_reason, inline=True)

# Separator
embed.add_field(name="", value="", inline=False)

(gameId, isWii, controllers, savestate, vi, inputs, lag,
rerecords, video, audio, md5, timestamp) = unpack("<6s3B3Q8xL32x16s16s16sq", dtm[4:0x89])

embed.add_field(name="Game ID", value=gameId.decode('utf-8'), inline=True)
embed.add_field(name="Is Wii Game", value=yesno(isWii), inline=True)

controllers_str = ""
first = True
i = 0
while i < 8:
if controllers & (1 << i):
controllers_str += ("" if first else ", ") + ("GC " if i/4 < 1 else "Wii ") + str((i % 4) + 1)
first = False
i += 1

embed.add_field(name="Controllers Plugged", value=controllers_str, inline=True)
embed.add_field(name="From Savestate", value=yesno(savestate), inline=True)
embed.add_field(name="VI Count", value=vi, inline=True)
embed.add_field(name="Input Count", value=inputs, inline=True)
embed.add_field(name="Lag Count", value=lag, inline=True)
embed.add_field(name="Rerecords", value=rerecords, inline=True)
embed.add_field(name="Video Backend", value=video.decode('utf-8'), inline=True)
embed.add_field(name="Audio Backend", value=audio.decode('utf-8'), inline=True)
embed.add_field(name="MD5 Hash", value=f"`{md5.hex()}`", inline=False)
embed.add_field(name="Start Time", value=f"<t:{timestamp}> (<t:{timestamp}:R>)", inline=False)


await ctx.reply(embed=embed)
await ctx.send(
"Note that unless your submission has been edited manually by a host, the time shown is the "
"VI count from your DTM.\nFull DTM file info can be found [here](https://yomcube.github.io/file-utils/?f=DTM).")


async def setup(bot):
await bot.add_cog(Info(bot))
15 changes: 13 additions & 2 deletions commands/utilities/bug-report.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
from discord.ext import commands
import discord
from dotenv import load_dotenv
from os import getenv

load_dotenv()
DEFAULT = getenv('DEFAULT')

class Bug(commands.Cog):
def __init__(self, bot) -> None:
Expand All @@ -13,8 +18,14 @@ async def command(self, ctx, *, bug: str):

await dash.send(bug)
await shxd.send(bug)

await ctx.reply(f"Bug sent to {shxd.display_name} and {dash.display_name}, thank you!\nRemember that you can also [open an issue](https://github.com/crackhex/TAS-Comp-Bot-py/issues/new) on Github if you have an account.")
names = [ shxd.display_name, dash.display_name ]

if DEFAULT == 'nsmbw':
tomcube = self.bot.get_user(1096803802029510766)
names.append(tomcube.display_name)
await tomcube.send(bug)

await ctx.reply(f"Bug sent to {' and '.join(names)}, thank you!\nRemember that you can also [open an issue](https://github.com/crackhex/TAS-Comp-Bot-py/issues/new) on Github if you have an account.")
except discord.HTTPException:
await ctx.send("Failed to send message")

Expand Down
3 changes: 2 additions & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
load_dotenv()
TOKEN = os.getenv('TOKEN')
DB_DIR = os.path.abspath(os.getenv('DB_DIR'))
DEFAULT = os.getenv('DEFAULT')

os.makedirs(DB_DIR) if not os.path.exists(DB_DIR) else None
activity = discord.Game(name="Dolphin Emulator")
Expand All @@ -37,7 +38,7 @@
'commands.db.admin.set-tasks-channel',
'commands.db.admin.togglereminderpings',
'commands.db.admin.config',
'commands.db.info',
'commands.db.info_nsmbw' if DEFAULT == 'nsmbw' else 'commands.db.info',
'commands.db.requesttask',
'commands.db.setname',
'commands.db.team.collab',
Expand Down

0 comments on commit 3b925b8

Please sign in to comment.