206 lines
7.6 KiB
Python
206 lines
7.6 KiB
Python
from .template import *
|
|
import time
|
|
import numpy
|
|
from PIL import Image
|
|
import io
|
|
|
|
CHOOSE, ADDARG = range(2)
|
|
MESSAGE, WAKE, ALARM, IMAGE, ART = range(3,8)
|
|
|
|
class Clock(BotFunc):
|
|
"""pass on commands to clock-module"""
|
|
def __init__(self, db_utils, clock_module, art_api):
|
|
super().__init__(db_utils)
|
|
self.clock = clock_module
|
|
self.art_api = art_api
|
|
|
|
def create_handler(self):
|
|
handler = ConversationHandler(
|
|
entry_points=[CommandHandler("clock", self.entry_point)],
|
|
states={
|
|
CHOOSE : [
|
|
CallbackQueryHandler(self.wake_light, pattern="^wake$"),
|
|
CallbackQueryHandler(self.alarm_blink, pattern="^alarm$"),
|
|
CallbackQueryHandler(self.show_message, pattern="^message$"),
|
|
CallbackQueryHandler(self.show_image, pattern="^image$"),
|
|
CallbackQueryHandler(self.art_gallery, pattern="^gallery$"),
|
|
],
|
|
ADDARG : [MessageHandler(Filters.text, callback=self.get_arg1)],
|
|
MESSAGE: [MessageHandler(Filters.text, callback=self.exec_show_message)],
|
|
WAKE : [MessageHandler(Filters.text, callback=self.exec_wake_light)],
|
|
ALARM : [MessageHandler(Filters.text, callback=self.exec_alarm_blink)],
|
|
IMAGE : [MessageHandler(Filters.photo, callback=self.exec_show_image)],
|
|
ART : [MessageHandler(Filters.text, callback=self.exec_art_gallery)],
|
|
},
|
|
fallbacks=[CommandHandler('clock', self.entry_point)],
|
|
)
|
|
return handler
|
|
|
|
def entry_point(self, update: Update, context: CallbackContext) -> None:
|
|
keyboard = [
|
|
[InlineKeyboardButton("Make a wake-light", callback_data="wake")],
|
|
[InlineKeyboardButton("Blink as alarm", callback_data="alarm")],
|
|
[InlineKeyboardButton("Show a message", callback_data="message")],
|
|
[InlineKeyboardButton("Show an image", callback_data="image")],
|
|
[InlineKeyboardButton("Art gallery!", callback_data="gallery")],
|
|
]
|
|
reply_markup = InlineKeyboardMarkup(keyboard)
|
|
update.message.reply_text("What exactly do you want?", reply_markup=reply_markup)
|
|
return CHOOSE
|
|
|
|
|
|
def wake_light(self, update: Update, context: CallbackContext) -> None:
|
|
query = update.callback_query
|
|
query.answer()
|
|
|
|
query.edit_message_text("Ok. How long should the color cycle last? (In seconds)")
|
|
return WAKE
|
|
|
|
def alarm_blink(self, update: Update, context: CallbackContext) -> None:
|
|
query = update.callback_query
|
|
query.answer()
|
|
|
|
query.edit_message_text("Ok. How long should it blink? (In seconds)")
|
|
self.next_state = {ALARM : "What frequency (Hertz)"}
|
|
return ADDARG
|
|
|
|
def show_message(self, update: Update, context: CallbackContext) -> None:
|
|
query = update.callback_query
|
|
query.answer()
|
|
|
|
query.edit_message_text("Ok. What message will I show?")
|
|
return MESSAGE
|
|
|
|
def show_image(self, update: Update, context: CallbackContext) -> None:
|
|
query = update.callback_query
|
|
query.answer()
|
|
|
|
query.edit_message_text("How long (in minutes) should the image be displayed?")
|
|
self.next_state = {IMAGE : "Please send me the photo to display."}
|
|
return ADDARG
|
|
|
|
def art_gallery(self, update: Update, context: CallbackContext) -> None:
|
|
query = update.callback_query
|
|
query.answer()
|
|
|
|
query.edit_message_text("Ok. How long should we display art? (in hours")
|
|
self.next_state = {ART : "And how many artworks would you like to see during that time?"}
|
|
return ADDARG
|
|
|
|
def get_arg1(self, update: Update, context: CallbackContext) -> None:
|
|
a = update.message.text
|
|
self.additional_argument = a
|
|
update.message.reply_text("Furthermore: "+ list(self.next_state.values())[0])
|
|
return list(self.next_state.keys())[0]
|
|
|
|
|
|
|
|
|
|
###### actually running clock actions
|
|
def exec_wake_light(self, update: Update, context: CallbackContext) -> None:
|
|
duration = update.message.text
|
|
|
|
matrices = []
|
|
start_color = numpy.array([153, 0, 51])
|
|
end_color = numpy.array([255, 255, 0])
|
|
col_show = numpy.zeros((*self.clock.MOP.shape, 3))
|
|
col_show[:,:,...] = start_color
|
|
|
|
gradient = end_color - start_color
|
|
# steps are shown at a frequency of ?? frames / second =>
|
|
for i in range(duration * 2): # / 0.5
|
|
ct = i/20 * gradient
|
|
col_show[:,:,...] = [int(x) for x in ct+start_color]
|
|
matrices.append(col_show)
|
|
|
|
self.clock.out.queue.append({"matrices" : matrices})
|
|
return ConversationHandler.END
|
|
|
|
|
|
def exec_alarm_blink(self, update: Update, context: CallbackContext) -> None:
|
|
duration = self.additional_argument
|
|
|
|
matrices = []
|
|
duration = int(duration * 2)
|
|
empty = numpy.zeros((*self.clock.MOP.shape,3))
|
|
red = numpy.ones_like(empty) * 255
|
|
|
|
for _ in range(int(duration / 2)):
|
|
matrices.append(red)
|
|
matrices.append(empty)
|
|
|
|
self.clock.out.queue.append({"matrices": matrices})
|
|
return ConversationHandler.END
|
|
|
|
|
|
|
|
def exec_show_image(self, update: Update, context: CallbackContext) -> None:
|
|
duration = self.additional_argument
|
|
i = update.message.photo
|
|
img = update.message.photo[0]
|
|
bot = img.bot
|
|
id = img.file_id
|
|
|
|
file = bot.getFile(id).download_as_bytearray()
|
|
width = self.clock.shape[1]
|
|
height = self.clock.shape[0]
|
|
|
|
img = Image.open(io.BytesIO(file))
|
|
im_height = img.height
|
|
im_width = img.width
|
|
|
|
scalex = im_width // width
|
|
scaley = im_height // height
|
|
scale = min(scalex, scaley)
|
|
|
|
t = img.resize((width, height),box=(0,0,width*scale,height*scale))
|
|
a = numpy.asarray(t)
|
|
|
|
matrices = [a for _ in range(2*60*duration)]
|
|
|
|
self.clock.out.queue.append({"matrices": matrices})
|
|
return ConversationHandler.END
|
|
|
|
|
|
def exec_show_message(self, update: Update, context: CallbackContext) -> None:
|
|
message_str = update.message.text
|
|
update.message.reply_text("Now showing: " + message_str)
|
|
self.clock.run(self.clock.text_scroll,(message_str,))
|
|
return ConversationHandler.END
|
|
|
|
|
|
def exec_art_gallery(self, update: Update, context: CallbackContext) -> None:
|
|
duration = float(self.additional_argument)
|
|
number = int(update.message.text)
|
|
|
|
def output(number, duration):
|
|
for i in range(number):
|
|
img = self.art_api.get_random_art() # returns an PIL.Image object
|
|
im_height = img.height
|
|
im_width = img.width
|
|
|
|
width = self.clock.shape[1]
|
|
height = self.clock.shape[0]
|
|
|
|
scalex = im_width // width
|
|
scaley = im_height // height
|
|
scale = min(scalex, scaley)
|
|
|
|
t = img.resize((width, height),box=(0,0,width*scale,height*scale))
|
|
a = numpy.asarray(t)
|
|
self.clock.IO.put(a)
|
|
|
|
time.sleep(duration*3600 / number)
|
|
|
|
|
|
update.message.reply_text("Ok. Showing art for the next "+ str(duration) + " hours.")
|
|
self.clock.run(output,(number, duration))
|
|
return ConversationHandler.END
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# TODO FIx this to work with the new backend |