Last active
October 13, 2025 12:13
-
-
Save bferguson3/8aa17d1381721e74459dedcf23929cd2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # # # # # # # # # # # # # # | |
| # | |
| # 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