Skip to content

Instantly share code, notes, and snippets.

@bferguson3
Last active October 13, 2025 12:13
Show Gist options
  • Select an option

  • Save bferguson3/8aa17d1381721e74459dedcf23929cd2 to your computer and use it in GitHub Desktop.

Select an option

Save bferguson3/8aa17d1381721e74459dedcf23929cd2 to your computer and use it in GitHub Desktop.
# # # # # # # # # # # # # #
#
# Shinobigami Dice Bot
#
# commands: !h[elp], !r[oll], !v[elocity]
#
# How to use:
# 1. Login to Discord's developer home (https://discord.com/developers/applications)
# 2. Select New Application and fill in your bot's name, description etc. as desired
# 3. Copy the Public Key into "discord_bot_key.txt" in the same folder as this script
# 4. Run from the script folder with $ python3 ./sgbot.py
#
# * To install discord for python: $ python3 -m pip install discord
# * On Windows, use "python sgbot.py" instead
#
#
# Features:
# - Comment support for rolls (e.g. !roll 2d+2 goblin A)
# - Support for d66
# - Support for Plot reveals (waits for all inputs)
# - Multiple commands supported (split by line)
#
# Examples:
# !roll 2d6+3
# !roll d66 this is a comment
#
# Shinobigami-Pedia - Fansite with 500+ Translated Ninpo:
# https://www.twinngames.com/sgpedia
#
# (c)2025 bferguson3 @ github aka Bent
#
# # # # # # # # # # # # #
import discord,os,random,re,math,time
intents = discord.Intents.all()
client = discord.Client(command_prefix="!", intents=intents)
users_list = []
class User():
def __init__(self):
self.user = ""
self.last_v = -1
###
###
@client.event
async def on_ready():
print("We have logged in as {0.user}".format(client))
def RollDie(st="2d6"):
st = st.lower()
numdie = st.split("d")[0]
numsid = st.split("d")[1]
mod = 0
if numsid.find("+")!=-1:
mod = numsid.split("+")[1]
numsid = numsid.split("+")[0]
elif numsid.find("-")!=-1:
mod = numsid.split("-")[1]
numsid=numsid.split("+")[0]
# is d66?
_ss = False
if numsid == "66":
numsid = 6
numdie = 2
_ss = True
#
res = []
i = 0
while i < int(numdie):
res.append(random.randint(1,int(numsid)))
i += 1
res.append(int(mod))
# if d66:
if _ss:
if res[0] < res[1]:
res[0] *= 10
else:
res[1] *= 10
#
return res
###
def tot(r):
i = 0
tot = 0
while i < len(r):
tot += r[i]
i += 1
return tot
###
waiting_for=[]
random.seed()
@client.event
async def on_message(message):
global waiting_for
_arraymsg = ""
if message.author == client.user:
return
commands = message.content.lower().split("\n")
for msg in commands:
_time = time.strftime("%H:%M:%S | ", time.gmtime())
if msg.startswith("!r"):
try: # split at the "d":
_cmt = ""
if msg.lower().find("d") != -1:
#!roll 5d6+3 comment
_st = msg.split(" ") #_st[0] = !roll [1]=die [2]=comment
_r = _st[1]
i = 2
while i < len(_st):
_cmt += _st[i]
i += 1
res = RollDie(_r) # its an array this time
_arraymsg += message.author.display_name + ": **" + str(tot(res)) + "** ("
i = 0
while i < len(res) - 1:
_arraymsg += str(res[i]) + ", "
i += 1
_arraymsg = _arraymsg[:len(_arraymsg)-2] + " + " + str(res[len(res)-1]) + ") | " + _cmt
##
else:
res = RollDie()
_arraymsg += message.author.display_name + ": **" + str(tot(res)) + "** ("
i = 0
while i < len(res) - 1:
_arraymsg += str(res[i]) + ", "
i += 1
_arraymsg = _arraymsg[:len(_arraymsg)-2] + " + " + str(res[len(res)-1]) + ") | " + _cmt
except Exception as e:
_arraymsg += "Use dice format: xdy+z\n e.g. `!roll 2d6-1`, `!r 5d6`, `!r d66`"
print(_time, msg + " | ",": error", e)
###
elif msg.startswith("!v"):
try:
u = msg.lower().split(" ") # e.g. !velocity abba dabba
needed = len(u) - 1
i = 1
tgt = ""
ct = 0
_arraymsg = "Combat round: "
while i < len(u):
for n in client.get_all_members():
_n = n.display_name.lower()
if _n.find(u[i])==0:
ct = ct + 1
_arraymsg += n.display_name + ", "
uz = User()
uz.user = n.display_name
waiting_for.append(uz)
i += 1
if needed != ct:
_arraymsg = "I don't see those people!"
else:
_arraymsg += "enter your plot score. (Eg. `|| n ||`)"
except Exception as e:
print(e)
###
elif msg.startswith("!h"):
_arraymsg += "To use me:\n\n**!r** or **!roll** *x*dy+*n* to roll dice\n You can also add text for comments.\n d66 checks also supported.\n\n**!v** or **!velocity [name1] [name2] .. **to begin a combat round.\n\n**!h** or **!help** to see this text\n\nYou can also send multiple commands at once by splitting them one per line."
print(_time, message.author.display_name + " | ",": requested help")
###
elif msg.startswith("||"):
if len(waiting_for) > 0:
for p in waiting_for:
if message.author.display_name == p.user:
_z = re.sub(r'[^0-9]', '', msg)
if _z != "":
_z = int(_z)
if _z < 1 or _z > 6:
_arraymsg = "Error: Plot score must between 1 and 6!"
else:
p.last_v = _z
else:
_arraymsg = "Error detecting plot score."
break
#
not_all = False
for p in waiting_for:
if p.last_v == -1:
not_all = True
if not not_all: # all done
i = 0
_arraymsg += "Velocities: "
waiting_for = sorted(waiting_for, key=lambda p:p.last_v, reverse=True)
while i < len(waiting_for):
_arraymsg += waiting_for[i].user + ": " + str(waiting_for[i].last_v) + " | "
i += 1
waiting_for = []
#
###
###
if _arraymsg != "":
await message.channel.send(_arraymsg)
###
f = open("discord_bot_key.txt", "r")
key = f.read()
f.close()
client.run(key)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment