forked from kemonomimi/nyabot
main+data_manager: Started work on marriage system
This commit adds a data_manager submodule that handles reading/writing data. For now it's backed by a single json file, but in the future we should move to a sqlite3 database The marriage system uses Discord Interactions and views, and works for basic things TODO: - Poly marriage support - Listing marriages through a command
This commit is contained in:
parent
406d3b5c8f
commit
95139026e5
3 changed files with 175 additions and 1 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
token
|
token
|
||||||
|
data.json
|
||||||
|
|
51
data_manager.py
Normal file
51
data_manager.py
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
# TODO: If you need to grow this class, consider moving to a sqlite3 database!
|
||||||
|
|
||||||
|
import io
|
||||||
|
import json
|
||||||
|
|
||||||
|
DATA_PATH = "data.json"
|
||||||
|
|
||||||
|
|
||||||
|
def __load_json_or_make_empty_object(fp: io.TextIOWrapper):
|
||||||
|
data = {}
|
||||||
|
fp.seek(0)
|
||||||
|
try:
|
||||||
|
data = json.load(fp)
|
||||||
|
except ValueError as exception:
|
||||||
|
print(exception, DATA_PATH, "wasn't a JSON file, making it one...")
|
||||||
|
# fp doesn't point to a file with valid json, replacing the content with "{}"
|
||||||
|
fp.seek(0)
|
||||||
|
fp.write("{}")
|
||||||
|
fp.truncate()
|
||||||
|
fp.flush()
|
||||||
|
return {}
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def get_data() -> dict:
|
||||||
|
with open(DATA_PATH, 'a+') as fp:
|
||||||
|
return __load_json_or_make_empty_object(fp)
|
||||||
|
|
||||||
|
|
||||||
|
# Helper class for writing to the data file in a sage way
|
||||||
|
class DataWriter:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.__data_fp: io.TextIOWrapper | None = None
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.__data_fp = open(DATA_PATH, 'w+')
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, *_):
|
||||||
|
if self.__data_fp is not None:
|
||||||
|
self.__data_fp.close()
|
||||||
|
|
||||||
|
# Set a new value to the data
|
||||||
|
def set_data(self, json_data: dict):
|
||||||
|
if self.__data_fp is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.__data_fp.seek(0)
|
||||||
|
json.dump(json_data, self.__data_fp)
|
||||||
|
self.__data_fp.truncate()
|
||||||
|
self.__data_fp.flush()
|
122
main.py
122
main.py
|
@ -4,6 +4,8 @@ import discord
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
import data_manager
|
||||||
|
|
||||||
intents = discord.Intents.default()
|
intents = discord.Intents.default()
|
||||||
intents.message_content = True
|
intents.message_content = True
|
||||||
|
|
||||||
|
@ -35,12 +37,132 @@ boop - Boops target user
|
||||||
Slash commands:
|
Slash commands:
|
||||||
```
|
```
|
||||||
/help - Shows this message
|
/help - Shows this message
|
||||||
|
/marry - Marries someone
|
||||||
```
|
```
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def __find_mariage_for_member_id(member_id: int) -> list[int]:
|
||||||
|
data = data_manager.get_data()
|
||||||
|
if "marriages" not in data:
|
||||||
|
data["marriages"] = []
|
||||||
|
with data_manager.DataWriter() as writer:
|
||||||
|
writer.set_data(data)
|
||||||
|
return []
|
||||||
|
|
||||||
|
for marriage in data["marriages"]:
|
||||||
|
if member_id in marriage:
|
||||||
|
return marriage
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
# Interraction views
|
||||||
|
|
||||||
|
|
||||||
|
class MariageConfirmationView(discord.ui.View):
|
||||||
|
def __init__(self, target: discord.Member):
|
||||||
|
super().__init__()
|
||||||
|
self.timeout = None
|
||||||
|
self.marriage_accepted: bool | None = None
|
||||||
|
self.target = target
|
||||||
|
|
||||||
|
@discord.ui.button(label="Accept", style=discord.ButtonStyle.green, row=1)
|
||||||
|
async def accept(self, _: discord.ui.Button, interaction: discord.Interaction):
|
||||||
|
if interaction.user != self.target:
|
||||||
|
print(interaction.user, self.target)
|
||||||
|
await interaction.response.send_message(
|
||||||
|
"ur not the one getting married, silly :3"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
user_who_replied = interaction.user
|
||||||
|
mention = user_who_replied.mention \
|
||||||
|
if user_who_replied is not None else "<something went wrong :‹>"
|
||||||
|
await interaction.response.send_message(
|
||||||
|
f"{mention} accepted the proposal :3 lovely"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.marriage_accepted = True
|
||||||
|
self.stop()
|
||||||
|
|
||||||
|
@discord.ui.button(label="Deny", style=discord.ButtonStyle.red, row=1)
|
||||||
|
async def deny(self, _: discord.ui.Button, interaction: discord.Interaction):
|
||||||
|
if interaction.user != self.target:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
"ur not the one getting married, silly :3"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
user_who_replied = interaction.user
|
||||||
|
mention = user_who_replied.mention \
|
||||||
|
if user_who_replied is not None else "<something went wrong :‹>"
|
||||||
|
|
||||||
|
await interaction.response.send_message(
|
||||||
|
f"{mention} didn't wanna get married yet..."
|
||||||
|
)
|
||||||
|
|
||||||
|
self.marriage_accepted = False
|
||||||
|
self.stop()
|
||||||
|
|
||||||
# Slash commands
|
# Slash commands
|
||||||
|
|
||||||
|
|
||||||
|
@bot.slash_command()
|
||||||
|
@discord.guild_only()
|
||||||
|
@discord.option(
|
||||||
|
"target", type=discord.Member,
|
||||||
|
description="Which user to marry",
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
async def marry(
|
||||||
|
context: discord.ApplicationContext, member_to_marry: discord.Member
|
||||||
|
):
|
||||||
|
# Check if the person asked in mariage is interested
|
||||||
|
marriage_asker = context.author
|
||||||
|
if marriage_asker is None:
|
||||||
|
await context.respond("ow :/ something went wonky wonky, try again!")
|
||||||
|
return
|
||||||
|
|
||||||
|
marriage_confirmation = MariageConfirmationView(member_to_marry)
|
||||||
|
await context.respond(
|
||||||
|
f"{member_to_marry.mention}, would you like to marry"
|
||||||
|
+ f" {marriage_asker.mention}?", view=marriage_confirmation)
|
||||||
|
|
||||||
|
await marriage_confirmation.wait()
|
||||||
|
if marriage_confirmation.marriage_accepted is None:
|
||||||
|
await context.respond("silly little bug going on :3 try again l8er :3")
|
||||||
|
return
|
||||||
|
|
||||||
|
if marriage_confirmation.marriage_accepted == False:
|
||||||
|
await context.respond(
|
||||||
|
"no consent == no marriage! consent is key to a happy life :3"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Marriage was accepted, yay :3!
|
||||||
|
askers_marriage = __find_mariage_for_member_id(marriage_asker.id)
|
||||||
|
askees_marriage = __find_mariage_for_member_id(member_to_marry.id)
|
||||||
|
|
||||||
|
# Now check for polycules
|
||||||
|
if len(askees_marriage) == 0 and len(askers_marriage) == 0:
|
||||||
|
# No polycules, just update the records to marry the two :3
|
||||||
|
data = data_manager.get_data()
|
||||||
|
data["marriages"].append([marriage_asker.id, member_to_marry.id])
|
||||||
|
with data_manager.DataWriter() as writer:
|
||||||
|
writer.set_data(data)
|
||||||
|
|
||||||
|
await context.respond(
|
||||||
|
f"{marriage_asker.mention} married {member_to_marry.mention}"
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
await context.respond(
|
||||||
|
"ooh looks like you're trying to do a ploly marriage..." +
|
||||||
|
" unfortunately, that's still a work in progress," +
|
||||||
|
" come back later to register it :3"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@bot.slash_command()
|
@bot.slash_command()
|
||||||
async def help(ctx: discord.ApplicationContext):
|
async def help(ctx: discord.ApplicationContext):
|
||||||
await ctx.respond(HELP_MESSAGE)
|
await ctx.respond(HELP_MESSAGE)
|
||||||
|
|
Loading…
Reference in a new issue