Last active 1573581370

A brief musing on the plausibility of a cards against humanity bot for discord

S Smith revised this gist 1573617369. Go to revision

1 file changed, 162 insertions

cahdiscord.py(file created)

@@ -0,0 +1,162 @@
1 + #!/usr/bin/env python
2 + import discord
3 + from json import load
4 + from random import shuffle
5 +
6 + client = discord.Client()
7 +
8 + # https://github.com/crhallberg/json-against-humanity
9 + with open("full.md.json") as f:
10 + cards = load(f)
11 +
12 + channels = {}
13 +
14 + number_emoji = ":one: :two: :three: :four: :five: :six: :seven: :eight: :nine: :keycap_ten:".split(" ")
15 +
16 + async def delete_message(message):
17 + try:
18 + await client.delete_message(message)
19 + return True
20 + except discord.errors.NotFound:
21 + return False
22 +
23 + async def cleanup(channel, important=False):
24 + global channels
25 + for msg in channels.get(channel, {}).get("for_deletion", []):
26 + await delete_message(msg)
27 + if important:
28 + for msg in channels.get(channel, {}).get("important_msgs", []):
29 + await delete_message(msg)
30 +
31 + async def send_message_cleanup(channel, message):
32 + global channels
33 + print(message)
34 + resp = await client.send_message(channel, message)
35 + channels[channel]["for_deletion"].append(resp)
36 + return resp
37 +
38 + async def cmd_start(message, *args):
39 + global channels
40 + channel = message.channel
41 + owner = message.author
42 + await delete_message(message)
43 + if not args:
44 + args = ["base", "cahe1", "cahe2", "cahe3"]
45 + selected = []
46 + for pack in args:
47 + for _pack in cards["metadata"].keys():
48 + if pack.lower() == _pack.lower():
49 + selected.append(_pack)
50 + channels[channel]["white"] += [c for c in cards["white"] if c["deck"] == _pack]
51 + channels[channel]["black"] += [c for c in cards["black"] if c["deck"] == _pack]
52 + break
53 + channels[channel]["selected"] = selected
54 + channels[channel]["active"] = True
55 + channels[channel]["owner"] = owner
56 + await send_message_cleanup(channel, "Starting a game with packs:\n" + "\n".join(selected))
57 + channels[channel]["joining"] = True
58 + await send_message_cleanup(channel, "Say anything to join the game, say ready when it's time to start")
59 +
60 + async def cmd_packs(message, *args):
61 + global channels
62 + channel = message.channel
63 + await delete_message(message)
64 + if channels[channel]["active"]:
65 + return
66 + packs = cards["metadata"]
67 + out = ""
68 + for k in sorted(packs.keys()):
69 + this = "{}: {}{}\n".format(k, packs[k]["name"], " (official)" if packs[k]["official"] else "")
70 + if len(out+this) > 2000:
71 + await send_message_cleanup(channel, out.strip())
72 + out = this
73 + else:
74 + out += this
75 + await send_message_cleanup(channel, out.strip())
76 +
77 + async def cmd_stop(message, *args):
78 + global channels
79 + channel = message.channel
80 + await delete_message(message)
81 + if channels[channel]["owner"] and channels[channel]["owner"] != message.author:
82 + await send_message_cleanup(channel, "Only the game owner can stop a game")
83 + return
84 + await cleanup(channel, important=True)
85 + del channels[channel]
86 +
87 + def draw(count, deck):
88 + out = []
89 + if len(deck) < count:
90 + return False
91 + for _ in range(1, count+1):
92 + shuffle(deck)
93 + out.append(deck.pop())
94 + return out
95 +
96 + @client.event
97 + async def on_message(message):
98 + if message.author == client.user:
99 + return
100 +
101 + global channels
102 + if not message.channel in channels:
103 + channels[message.channel] = {
104 + "important_msgs": [],
105 + "for_deletion": [],
106 + "active": False,
107 + "joining": False,
108 + "white": [],
109 + "black": [],
110 + "owner": None,
111 + "players": {}
112 + }
113 + channel = message.channel
114 + content = message.content
115 + author = message.author
116 + info = channels[channel]
117 + players = info["players"]
118 + if info["joining"]:
119 + if content.lower() == "ready":
120 + await delete_message(message)
121 + if author == info["owner"]:
122 + info["joining"] = False
123 + await cleanup(channel)
124 + await send_message_cleanup(channel, "Here we gooo")
125 + else:
126 + await send_message_cleanup(channel, "You didn't start the game! Only the person that started the game can ready up")
127 + return
128 + if author.id in players:
129 + return
130 + await delete_message(message)
131 + players[author.id] = {
132 + "hand": draw(10, info["white"])
133 + }
134 + print(players)
135 + await send_message_cleanup(channel, "{} has joined the game!".format(author.nick or author.name))
136 + await client.send_message(
137 + author,
138 + "Your white cards are:\n" +
139 + "\n".join(
140 + "{}: {}".format(number_emoji[n], c["text"]) for n,c in enumerate(players[author.id]["hand"])
141 + )
142 + )
143 + return
144 + if (content[0] == "!" and len(content) > 1) or channels[channel]["active"]:
145 + await cleanup(channel)
146 + cmd, *args = content[1 if content[0] == "!" else 0:].split(" ")
147 + try:
148 + await globals()["cmd_" + cmd](message, *args)
149 + except KeyError:
150 + # await client.send_message(channel, "Command not found")
151 + print("Command not found: " + cmd)
152 + pass
153 +
154 + @client.event
155 + async def on_ready():
156 + print("Logged in as {} ({})".format(client.user.name, client.user.id))
157 + if client.user.bot:
158 + print(discord.utils.oauth_url(client.user.id, permissions=discord.Permissions(67497024)))
159 +
160 + if __name__ == "__main__":
161 + with open(".bottoken") as f:
162 + client.run(f.read().strip())
Newer Older