/
laundrybot.py
192 lines (157 loc) · 7.3 KB
/
laundrybot.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
# Laundry Bot for RC4, current telegram handle: @RC4LaundryBot
import os
import re
import logging
import requests
from datetime import datetime
import time
from emoji import emojize
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode
from telegram.ext import Updater, CommandHandler, CallbackQueryHandler
# Set up logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)
logger = logging.getLogger(__name__)
# Initialize global variables
RC_URL = "https://us-central1-rc4laundrybot.cloudfunctions.net/readData/RC4-"
LAUNDRY_LEVELS = [5, 8, 11, 14, 17]
MACHINES_INFO = {
'washer1': 'Washer 1',
'washer2': 'Washer 2',
'dryer1': 'Dryer 1',
'dryer2': 'Dryer 2'
}
# Building menu for every occasion
def build_menu(buttons, n_cols, header_buttons=None, footer_buttons=None):
menu = [buttons[i:i + n_cols] for i in range(0, len(buttons), n_cols)]
if header_buttons:
menu.insert(0, header_buttons)
if footer_buttons:
menu.append(footer_buttons)
return InlineKeyboardMarkup(menu)
# Building emojis for every occasion
ebluediamond = emojize(":small_blue_diamond: ", use_aliases=True)
etick = emojize(":white_check_mark: ", use_aliases=True)
ecross = emojize(":x: ", use_aliases=True)
esoon = emojize(":soon: ", use_aliases=True)
# start command initializes:
def check_handler(bot, update, user_data):
user = update.message.from_user
if 'pinned_level' in user_data:
level_status(bot, update, user_data,
from_pinned_level=True, new_message=True)
else:
ask_level(bot, update)
def ask_level(bot, update):
level_text = "Heyyo! I am RC4's Laundry Bot. <i>As I am currently in [BETA] mode, I can only show details for Ursa floor.</i>\n\n<b>Which laundry level do you wish to check?</b>"
level_buttons = []
for level in LAUNDRY_LEVELS:
label = 'Level {}'.format(level)
data = 'set_L{}'.format(level)
buttons = InlineKeyboardButton(text=label, callback_data=data) # data callback to set_pinned_level
level_buttons.append(buttons)
update.message.reply_text(text=level_text,
reply_markup=build_menu(level_buttons, 1),
parse_mode=ParseMode.HTML)
def set_pinned_level(bot, update, user_data):
query = update.callback_query
level = int(re.match('^set_L(5|8|11|14|17)$', query.data).group(1))
user_data['pinned_level'] = level
level_status(bot, update, user_data, from_pinned_level=True)
# Carves the status text for each level
def make_status_text(level_number):
laundry_data = ''
floor_url = RC_URL + str(level_number)
# Get Request to the database backend
machine_status = requests.get(floor_url).json()
for machine_id in MACHINES_INFO:
if machine_status[machine_id] == 0:
status_emoji = etick
elif machine_status[machine_id] == 1:
status_emoji = ecross
else:
status_emoji = esoon
machine_name = MACHINES_INFO[machine_id]
laundry_data += '{} {}\n'.format(status_emoji, machine_name)
# TODO: This should be the backend server time instead
current_time = datetime.fromtimestamp(time.time() + 8*3600).strftime('%d %B %Y %H:%M:%S')
return "<b>Showing statuses for Level {}</b>:\n\n" \
"{}\n" \
"Last updated: {}\n".format(level_number, laundry_data, current_time)
# Create the status menu which contains the help command, a pinned level number, and refresh button
def make_status_menu(level_number):
level_buttons = []
for level in LAUNDRY_LEVELS:
label = 'L{}'.format(level)
data = 'check_L{}'.format(level)
if level == level_number:
# label = u'\u2022 ' + label + u' \u2022'
label = ebluediamond + label
button = InlineKeyboardButton(text=label, callback_data=data)
level_buttons.append(button)
refresh_button = [InlineKeyboardButton(
text='Refresh',
callback_data='check_L{}'.format(level_number)
)]
help_button = [InlineKeyboardButton(
text='Help',
callback_data='Help'
)]
return build_menu(level_buttons, 5, footer_buttons=refresh_button, header_buttons=help_button)
def level_status(bot, update, user_data, from_pinned_level=False, new_message=False):
query = update.callback_query
if from_pinned_level:
level = user_data['pinned_level']
else:
level = int(re.match('^check_L(5|8|11|14|17)$', query.data).group(1))
user_data['check_level'] = level
if new_message:
update.message.reply_text(text=make_status_text(level),
reply_markup=make_status_menu(level),
parse_mode=ParseMode.HTML)
else:
bot.edit_message_text(text=make_status_text(level),
chat_id=query.message.chat_id,
message_id=query.message.message_id,
reply_markup=make_status_menu(level),
parse_mode=ParseMode.HTML)
def help_menu(bot, update, user_data, from_pinned_level=False, new_message=False):
query = update.callback_query
help_text = "<b>Help</b>\n\n" + "Washer 1 and Dryer 2 accept coins\n" + etick + "= Available / Job done\n" + esoon + "= Job finishing soon\n" + ecross + "= In use\n"
help_text += "\nInformation not accurate or faced a problem? Please message @PakornUe or @Cpf05, thank you!"
help_text += "\n\nThis is a project by RC4Space's Laundry Bot Team. We appreciate your feedback as we are currently still beta-testing in Ursa before launching the college-wide implementation! :)"
level = user_data['check_level']
help_menu_button = [InlineKeyboardButton(
text='Back',
callback_data='check_L{}'.format(level)
)]
bot.edit_message_text(text=help_text,
chat_id=query.message.chat_id,
message_id=query.message.message_id,
reply_markup=build_menu(help_menu_button, 1),
parse_mode=ParseMode.HTML)
def error(bot, update, error):
logger.warning('Update "%s" caused error "%s"', update, error)
def main():
TOKEN = os.environ['RC4LAUNDRYBOT_TOKEN']
#NAME = 'nuscollegelaundrybot'
#PORT = os.environ.get('PORT')
updater = Updater(TOKEN)
dp = updater.dispatcher
dp.add_handler(CommandHandler('start', check_handler, pass_user_data=True))
dp.add_handler(CallbackQueryHandler(set_pinned_level,
pattern='^set_L(5|8|11|14|17)$',
pass_user_data=True))
dp.add_handler(CallbackQueryHandler(level_status,
pattern='^check_L(5|8|11|14|17)$',
pass_user_data=True))
dp.add_handler(CallbackQueryHandler(help_menu,
pattern='Help',
pass_user_data=True))
dp.add_error_handler(error)
#updater.start_webhook(listen="0.0.0.0", port=int(PORT), url_path=TOKEN)
#updater.bot.setWebhook("https://{}.herokuapp.com/{}".format(NAME, TOKEN))
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()