-
Notifications
You must be signed in to change notification settings - Fork 29
/
Commands.py
279 lines (243 loc) · 13.3 KB
/
Commands.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
import json
import logging as log
import datetime
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode
import MainController
import GamesController
from Constants.Config import STATS
from Boardgamebox.Board import Board
from Boardgamebox.Game import Game
from Boardgamebox.Player import Player
from Constants.Config import ADMIN
# Enable logging
log.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=log.INFO,
filename='logs/logging.log')
logger = log.getLogger(__name__)
commands = [ # command description used in the "help" command
'/help - Gives you information about the available commands',
'/start - Gives you a short piece of information about Secret Blue',
'/symbols - Shows you all possible symbols of the board',
'/rules - Gives you a link to the official Secret Blue rules',
'/newgame - Creates a new game',
'/join - Joins an existing game',
'/startgame - Starts an existing game when all players have joined',
'/cancelgame - Cancels an existing game. All data of the game will be lost',
'/board - Prints the current board with fascist and liberals tracks, presidential order and election counter',
'/votes - Prints who voted',
'/calltovote - Calls the players to vote'
]
symbols = [
u"\u25FB\uFE0F" + ' Empty field without special power',
u"\u2716\uFE0F" + ' Field covered with a card', # X
u"\U0001F52E" + ' Presidential Power: Policy Peek', # crystal
u"\U0001F50E" + ' Presidential Power: Investigate Loyalty', # inspection glass
u"\U0001F5E1" + ' Presidential Power: Execution', # knife
u"\U0001F454" + ' Presidential Power: Call Special Election', # tie
u"\U0001F54A" + ' Liberals win', # dove
u"\u2620" + ' Fascists win' # skull
]
def command_symbols(bot, update):
cid = update.message.chat_id
symbol_text = "The following symbols can appear on the board: \n"
for i in symbols:
symbol_text += i + "\n"
bot.send_message(cid, symbol_text)
def command_board(bot, update):
cid = update.message.chat_id
if cid in GamesController.games.keys():
if GamesController.games[cid].board:
bot.send_message(cid, GamesController.games[cid].board.print_board())
else:
bot.send_message(cid, "There is no running game in this chat. Please start the game with /startgame")
else:
bot.send_message(cid, "There is no game in this chat. Create a new game with /newgame")
def command_start(bot, update):
cid = update.message.chat_id
bot.send_message(cid,
"\"Secret Blue is a social deduction game for 5-10 people about finding and stopping the Secret Blue."
" The majority of players are liberals. If they can learn to trust each other, they have enough "
"votes to control the table and win the game. But some players are fascists. They will say whatever "
"it takes to get elected, enact their agenda, and blame others for the fallout. The liberals must "
"work together to discover the truth before the fascists install their cold-blooded leader and win "
"the game.\"\n- official description of Secret Blue\n\nAdd me to a group and type /newgame to create a game!")
command_help(bot, update)
def command_rules(bot, update):
cid = update.message.chat_id
btn = [[InlineKeyboardButton("Rules", url="http://www.secrethitler.com/assets/Secret_Hitler_Rules.pdf")]]
rulesMarkup = InlineKeyboardMarkup(btn)
bot.send_message(cid, "Read the official Secret Hitler rules:", reply_markup=rulesMarkup)
# pings the bot
def command_ping(bot, update):
cid = update.message.chat_id
bot.send_message(cid, 'pong - v0.4')
# prints statistics, only ADMIN
def command_stats(bot, update):
cid = update.message.chat_id
if cid == ADMIN:
with open(STATS, 'r') as f:
stats = json.load(f)
stattext = "+++ Statistics +++\n" + \
"Liberal Wins (policies): " + str(stats.get("libwin_policies")) + "\n" + \
"Liberal Wins (killed Blue): " + str(stats.get("libwin_kill")) + "\n" + \
"Fascist Wins (policies): " + str(stats.get("fascwin_policies")) + "\n" + \
"Fascist Wins (Blue chancellor): " + str(stats.get("fascwin_blue")) + "\n" + \
"Games cancelled: " + str(stats.get("cancelled")) + "\n\n" + \
"Total amount of groups: " + str(len(stats.get("groups"))) + "\n" + \
"Games running right now: "
bot.send_message(cid, stattext)
# help page
def command_help(bot, update):
cid = update.message.chat_id
help_text = "The following commands are available:\n"
for i in commands:
help_text += i + "\n"
bot.send_message(cid, help_text)
def command_newgame(bot, update):
cid = update.message.chat_id
game = GamesController.games.get(cid, None)
groupType = update.message.chat.type
if groupType not in ['group', 'supergroup']:
bot.send_message(cid, "You have to add me to a group first and type /newgame there!")
elif game:
bot.send_message(cid, "There is currently a game running. If you want to end it please type /cancelgame!")
else:
GamesController.games[cid] = Game(cid, update.message.from_user.id)
with open(STATS, 'r') as f:
stats = json.load(f)
if cid not in stats.get("groups"):
stats.get("groups").append(cid)
with open(STATS, 'w') as f:
json.dump(stats, f)
bot.send_message(cid, "New game created! Each player has to /join the game.\nThe initiator of this game (or the admin) can /join too and type /startgame when everyone has joined the game!")
def command_join(bot, update):
groupName = update.message.chat.title
cid = update.message.chat_id
groupType = update.message.chat.type
game = GamesController.games.get(cid, None)
fname = update.message.from_user.first_name
if groupType not in ['group', 'supergroup']:
bot.send_message(cid, "You have to add me to a group first and type /newgame there!")
elif not game:
bot.send_message(cid, "There is no game in this chat. Create a new game with /newgame")
elif game.board:
bot.send_message(cid, "The game has started. Please wait for the next game!")
elif update.message.from_user.id in game.playerlist:
bot.send_message(game.cid, "You already joined the game, %s!" % fname)
elif len(game.playerlist) >= 10:
bot.send_message(game.cid, "You have reached the maximum amount of players. Please start the game with /startgame!")
else:
uid = update.message.from_user.id
player = Player(fname, uid)
try:
bot.send_message(uid, "You joined a game in %s. I will soon tell you your secret role." % groupName)
game.add_player(uid, player)
except Exception:
bot.send_message(game.cid,
fname + ", I can\'t send you a private message. Please go to @thesecretbluebot and click \"Start\".\nYou then need to send /join again.")
else:
log.info("%s (%d) joined a game in %d" % (fname, uid, game.cid))
if len(game.playerlist) > 4:
bot.send_message(game.cid, fname + " has joined the game. Type /startgame if this was the last player and you want to start with %d players!" % len(game.playerlist))
elif len(game.playerlist) == 1:
bot.send_message(game.cid, "%s has joined the game. There is currently %d player in the game and you need 5-10 players." % (fname, len(game.playerlist)))
else:
bot.send_message(game.cid, "%s has joined the game. There are currently %d players in the game and you need 5-10 players." % (fname, len(game.playerlist)))
def command_startgame(bot, update):
log.info('command_startgame called')
cid = update.message.chat_id
game = GamesController.games.get(cid, None)
if not game:
bot.send_message(cid, "There is no game in this chat. Create a new game with /newgame")
elif game.board:
bot.send_message(cid, "The game is already running!")
elif update.message.from_user.id != game.initiator and bot.getChatMember(cid, update.message.from_user.id).status not in ("administrator", "creator"):
bot.send_message(game.cid, "Only the initiator of the game or a group admin can start the game with /startgame")
elif len(game.playerlist) < 5:
bot.send_message(game.cid, "There are not enough players (min. 5, max. 10). Join the game with /join")
else:
player_number = len(game.playerlist)
MainController.inform_players(bot, game, game.cid, player_number)
MainController.inform_fascists(bot, game, player_number)
game.board = Board(player_number, game)
log.info(game.board)
log.info("len(games) Command_startgame: " + str(len(GamesController.games)))
game.shuffle_player_sequence()
game.board.state.player_counter = 0
bot.send_message(game.cid, game.board.print_board())
#group_name = update.message.chat.title
#bot.send_message(ADMIN, "Game of Secret Blue started in group %s (%d)" % (group_name, cid))
MainController.start_round(bot, game)
def command_cancelgame(bot, update):
log.info('command_cancelgame called')
cid = update.message.chat_id
if cid in GamesController.games.keys():
game = GamesController.games[cid]
status = bot.getChatMember(cid, update.message.from_user.id).status
if update.message.from_user.id == game.initiator or status in ("administrator", "creator"):
MainController.end_game(bot, game, 99)
else:
bot.send_message(cid, "Only the initiator of the game or a group admin can cancel the game with /cancelgame")
else:
bot.send_message(cid, "There is no game in this chat. Create a new game with /newgame")
def command_votes(bot, update):
try:
#Send message of executing command
cid = update.message.chat_id
#bot.send_message(cid, "Looking for history...")
#Check if there is a current game
if cid in GamesController.games.keys():
game = GamesController.games.get(cid, None)
if not game.dateinitvote:
# If date of init vote is null, then the voting didnt start
bot.send_message(cid, "The voting didn't start yet.")
else:
#If there is a time, compare it and send history of votes.
start = game.dateinitvote
stop = datetime.datetime.now()
elapsed = stop - start
if elapsed > datetime.timedelta(minutes=1):
history_text = "Vote history for President %s and Chancellor %s:\n\n" % (game.board.state.nominated_president.name, game.board.state.nominated_chancellor.name)
for player in game.player_sequence:
# If the player is in the last_votes (He voted), mark him as he registered a vote
if player.uid in game.board.state.last_votes:
history_text += "%s registered a vote.\n" % (game.playerlist[player.uid].name)
else:
history_text += "%s didn't register a vote.\n" % (game.playerlist[player.uid].name)
bot.send_message(cid, history_text)
else:
bot.send_message(cid, "Five minutes must pass to see the votes")
else:
bot.send_message(cid, "There is no game in this chat. Create a new game with /newgame")
except Exception as e:
bot.send_message(cid, str(e))
def command_calltovote(bot, update):
try:
#Send message of executing command
cid = update.message.chat_id
#bot.send_message(cid, "Looking for history...")
#Check if there is a current game
if cid in GamesController.games.keys():
game = GamesController.games.get(cid, None)
if not game.dateinitvote:
# If date of init vote is null, then the voting didnt start
bot.send_message(cid, "The voting didn't start yet.")
else:
#If there is a time, compare it and send history of votes.
start = game.dateinitvote
stop = datetime.datetime.now()
elapsed = stop - start
if elapsed > datetime.timedelta(minutes=1):
# Only remember to vote to players that are still in the game
history_text = ""
for player in game.player_sequence:
# If the player is not in last_votes send him reminder
if player.uid not in game.board.state.last_votes:
history_text += "It's time to vote [%s](tg://user?id=%d).\n" % (game.playerlist[player.uid].name, player.uid)
bot.send_message(cid, text=history_text, parse_mode=ParseMode.MARKDOWN)
else:
bot.send_message(cid, "Five minutes must pass to see call to vote")
else:
bot.send_message(cid, "There is no game in this chat. Create a new game with /newgame")
except Exception as e:
bot.send_message(cid, str(e))