Last active 1573581370

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

cahdiscord.py Raw
1#!/usr/bin/env python
2import discord
3from json import load
4from random import shuffle
5
6client = discord.Client()
7
8# https://github.com/crhallberg/json-against-humanity
9with open("full.md.json") as f:
10 cards = load(f)
11
12channels = {}
13
14number_emoji = ":one: :two: :three: :four: :five: :six: :seven: :eight: :nine: :keycap_ten:".split(" ")
15
16async def delete_message(message):
17 try:
18 await client.delete_message(message)
19 return True
20 except discord.errors.NotFound:
21 return False
22
23async 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
31async 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
38async 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
60async 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
77async 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
87def 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
97async 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
155async 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
160if __name__ == "__main__":
161 with open(".bottoken") as f:
162 client.run(f.read().strip())