initial commit

This commit is contained in:
Ranomier 2022-03-07 17:57:22 +01:00
commit 7b25cd51ed
8 changed files with 552 additions and 0 deletions

View file

@ -0,0 +1,20 @@
FROM python:3
ENV HOME_DIR="/OhFortuna"
ENV BOT_DATA_DIR="${HOME_DIR}/data"
ENV PATH="${HOME_DIR}/.local/bin:${PATH}"
ENV PIP_DISABLE_PIP_VERSION_CHECK="1"
RUN addgroup --gid '1000' 'abc'; \
adduser --system --disabled-password --uid '1000' --home "$HOME_DIR" --gid '1000' 'abc'; \
chmod 750 "$HOME_DIR"
COPY --chown=abc:abc ./src "$HOME_DIR"
USER abc
WORKDIR "$HOME_DIR"
RUN chmod u+x "${HOME_DIR}/bot.py"; \
mkdir "$BOT_DATA_DIR"; \
pip install --user discord
CMD "${HOME_DIR}"/bot.py

View file

@ -0,0 +1,7 @@
This bot is written in Python 3.8, for seamless experience, please install Python version 3.8 or above.
External Library used:
- discord.py
- python-dotenv
Please install the libraries stated above for the bot to work.

339
build/OhFortuna/src/bot.py Normal file
View file

@ -0,0 +1,339 @@
#!/usr/bin/env python3
import os
from os.path import isfile
from random import randrange
import re
import math
import json
import discord
from discord.ext import commands
if 'BOT_TOKEN' in os.environ:
TOKEN = os.environ['BOT_TOKEN']
else:
with open('tokenfile', 'r') as tokenfd:
TOKEN = tokenfd.read().strip().strip('\n')
BOT_DATA_DIR = os.getenv('BOT_DATA_DIR', '')
#print(TOKEN)
#
#import sys
#sys.exit(1)
# Setup Bot
bot = commands.Bot(command_prefix='!')
# Bot Initialization
@bot.event
async def on_ready():
print("\n{name} is online\n".format(name=bot.user.name))
# ──────────────────────
# Start of Code
# ──────────────────────
# === Functions ===
def dice(value):
value = value.split("d")
amount, face = int(value[0]), int(value[1])
rolled = []
for i in range(0,amount):
rolled.append(randrange(face)+1)
return rolled
def find(value, data):
i = 0
for x in data:
if value in x:
return i
i+=1
return "False"
def fetch_var(ctx, var):
emsg = False
user = ctx.message.author.id
path = os.path.join(BOT_DATA_DIR, "{0}.txt".format(user))
if isfile(path) == True:
with open(path, "r") as file:
data = json.load(file)
if var in data:
key = str(data[var])
else:
emsg = "`{0}` does not exist in user database".format(var)
key = False
else:
emsg = "Database does not exist. Please start with `!uvar`"
key = False
return key, emsg
def check_doublet(roll):
a, b = roll[0], roll[1]
if a == b:
return True
else:
return False
# === Error Handler ===
# Ignore Command Not Found Error in Console
@bot.event
async def on_command_error(ctx, error):
if isinstance(error, commands.CommandNotFound):
return
raise error
# === Commands ===
@bot.command(name="uvar", aliases=["gvar"], brief="Create/Change/Remove variable", description="You may use this command to create/change/remove either user or global variable\nUse !uvar for user's database; !gvar for global database", usage="[change/remove] <Variable> <Value>")
async def uvar(ctx, *args):
if ctx.invoked_with == "gvar":
command = "gvar"
path = os.path.join(BOT_DATA_DIR, "Global.txt")
else:
command = "uvar"
path = os.path.join(BOT_DATA_DIR, '{}.txt'.format(ctx.message.author.id))
if len(args) == 2:
if args[0] != "delete":
name, value = args[0], args[1]
if value.isnumeric():
value = int(value)
if isfile(path) != True:
data = {name: value}
with open(path, 'w') as file:
file.write(json.dumps(data))
await ctx.reply("Create the variable: `{0}` with value: {1}".format(name, value))
else:
with open(path, 'r') as file:
data = json.load(file)
if (name in data):
await ctx.reply("This name already exist")
else:
data[name] = value
with open(path, 'w') as file:
file.write(json.dumps(data))
await ctx.reply("Create the variable: `{0}` with value: {1}".format(name, value))
else:
await ctx.reply("Please enter a valid value\nFor more info, please use `!help {}`".format(command))
else:
name = args[1]
if isfile(path):
with open(path, 'r') as file:
data = json.load(file)
if name in data.keys():
data.pop(name)
with open(path, 'w') as file:
file.write(json.dumps(data))
await ctx.reply("Variable: `{0}` is deleted".format(name))
else:
await ctx.reply("That variable does not exist")
else:
await ctx.reply("Database does not exist, please start by entering `!{}`".format(command))
elif len(args) == 3:
action, name, value = args[0].lower(), args[1], args[2]
if action == "change":
if value.isnumeric():
value = int(value)
if isfile(path):
with open(path, 'r') as file:
data = json.load(file)
if name in data:
data[name] = value
with open(path, 'w') as file:
file.write(json.dumps(data))
await ctx.reply("Changed the variable: `{0}` value to: {1}".format(name, value))
else:
await ctx.reply("This variable does not exist, please add with `!{}`".format(command))
else:
await ctx.reply("User data does not exist, please use `!{}` to make new value".format(command))
else:
await ctx.reply("Please enter a valid value\nFor more info, please use `!help {}`".format(command))
else:
await ctx.reply("This action does not exist\nFor more info, please use `!help {}`".format(command))
else:
await ctx.reply("Please insert the variable and value\nFor more info, please use `!help {}`".format(command))
@bot.command(name="ulist", aliases=["glist"], brief="Check list of variables", description="Use this command to check the variables in user/global database")
async def ulist(ctx):
if ctx.invoked_with == "glist":
path = os.path.join(BOT_DATA_DIR, "Global.txt")
else:
path = os.path.join(BOT_DATA_DIR, '{}.txt'.format(ctx.message.author.id))
if isfile(path):
with open(path, 'r') as file:
data = json.load(file)
var = []
if ctx.invoked_with == "glist":
var.append("**Global Variables**")
else:
var.append("**{0}'s Variables**".format(ctx.message.author.display_name))
for i in data:
line = "{0} `{1}`".format(i, data[i])
var.append(line)
await ctx.reply("\n".join(var))
else:
await ctx.reply("There is no variable list yet")
@bot.command(name="uclear", aliases=["gclear"], brief="Clear variables from database")
async def uclear(ctx):
if ctx.invoked_with == "gclear":
name = "global"
path = os.path.join(BOT_DATA_DIR, "Global.txt")
else:
name = "user"
path = os.path.join(BOT_DATA_DIR, '{}.txt'.format(ctx.message.author.id))
if isfile(path):
os.remove(path)
await ctx.reply("Cleared the {0} data".format(name))
else:
await ctx.reply("The {0} data is already empty".format(name))
@bot.command(name="roll", brief="Discretionary dice rolls", description="Use this to roll dice of any types and with simple math\nFor example: !roll 3d10+1\nRefers to 3 Dice with 10 Sides, adds 1",usage="<Value> [%Alias]")
async def roll(ctx, value: str = False, name: str = False):
if value != False:
try:
line = []
if not name:
name = ctx.message.author.display_name
line.append("**{0}'s Roll**".format(name.strip("%")))
vlist = re.split('([+-/*//])', value)
x = 0
for i in vlist:
if "d" in i:
i = dice(i)
vlist[x] = i
x+=1
x = 0
roll = 1
for i in vlist:
if type(i) == list:
line.append("Roll {0}: `{1}`".format(roll, ", ".join(list(map(str, i)))))
roll+=1
vlist[x] = sum(i)
x+=1
vlist = ' '.join(list(map(str, vlist)))
total = eval(vlist)
line.append("\nTotal: {0} = **{1}**".format(vlist, total))
await ctx.reply("\n".join(line))
except:
await ctx.reply("Invalid roll value\nFor more info, please use `!help roll`")
else:
await ctx.reply("Please indicate the roll variable\nFor more info, please use `!help roll`")
@bot.command(name="r",aliases=["r+","r++","r-","i"], brief="Standard/Initiative roll", description="You may use this command to roll either standard or initiative dice roll\nFor example: !r 3+VAR-VAR2 %Snowy #10\n\n*!i does not support target", usage="[Var/Number] [%Alias] [#Target]")
async def roll(ctx, *, value: str = False):
try:
command = ctx.invoked_with
line = False
no_error = True
name = ctx.message.author.display_name
cname = "False"
target = "False"
if command == "r":
roll = dice("2d10")
line = "{0},{1}".format(roll[0], roll[1])
elif command == "r+":
roll = sorted(dice("3d10"), reverse=True)
line = "{0},{1},~~{2}~~".format(roll[0], roll[1], roll[2])
roll.pop(2)
elif command == "r++":
roll = sorted(dice("4d10"), reverse=True)
line = "{0},{1},~~{2}~~,~~{3}~~".format(roll[0], roll[1], roll[2], roll[3])
roll.pop(3)
roll.pop(2)
elif command == "r-":
roll = sorted(dice("3d10"))
line = "{0},{1},~~{2}~~".format(roll[0], roll[1], roll[2])
roll.pop(2)
elif command == "i":
roll = dice("1d10")
line = "{0}".format(roll[0])
if value:
value = re.split('([+-/*// ])', value)
value = [x for x in value if x.strip()]
cname = find("%", value)
if cname != "False":
cname = value.pop(cname)
name = cname.strip("%")
target = find("#", value)
if target != "False":
target = value.pop(target)
target = int(target.strip("#"))
if command == "i":
no_error = False
await ctx.reply("Initiative (`!i`) does not accept target value")
x = 0
for i in value:
if no_error:
if i.isnumeric():
pass
elif (i == "+") | (i == "-") | (i == "*") | (i == "/"):
pass
else:
var, emsg = fetch_var(ctx, i)
if var:
value[x] = var
else:
await ctx.reply(emsg)
no_error = False
break
x+=1
else:
break
if no_error:
total = 0
if value:
total = eval(' '.join(list(map(str, value))))
total += sum(roll)
if target != "False":
if check_doublet(roll) & (total < target):
output = "Dramatic Failure"
elif check_doublet(roll) & (total > target):
staging = math.floor((total-target)/2)+1
output = "Exceptional Success, {0} staging(s)".format(staging)
elif total < target:
output = "Failure"
elif total == target:
output = "Tough Luck, 1 staging"
elif total > target:
staging = math.floor((total-target)/3)+1
output = "Success, {0} staging(s)".format(staging)
if value:
output = "{0}'s Roll: {1} ({2}[+{3}]={4} vs. {5})".format(name, output, line, "".join(value), total, target)
else:
output = "{0}'s Roll: {1} ({2}={3} vs. {4})".format(name, output, line, total, target)
await ctx.reply(output)
else:
if value:
output = "{0}[+{1}]".format(line, "".join(value))
else:
output = "{0}".format(line)
if command == "i":
output = "{0}'s roll: Initiative {1} ({2})".format(name, total, output)
elif check_doublet(roll):
output = "{0}'s roll: a Doublet {1} ({2})".format(name, total, output)
else:
output = "{0}'s roll: {1} ({2})".format(name, total, output)
await ctx.reply(output)
else:
total = sum(roll)
if command == "i":
output = "{0}'s roll: Initiative {1} ({2})".format(name, total, line)
elif check_doublet(roll):
output = "{0}'s roll: Doublet {1} ({2})".format(name, total, line)
else:
output = "{0}'s roll: {1} ({2})".format(name, total, line)
await ctx.reply(output)
except:
await ctx.reply("Invalid arguement, please use `!help r/i to learn more`")
bot.run(TOKEN)

View file

@ -0,0 +1 @@
discord

View file

@ -0,0 +1 @@
DemoToken123