class Main: def __init__(self, parent): self.parent = parent self.update_forever = False # MAIN PROPERTIES self.settings = { "nick":"", "chan":"", "auth":"", "rate":10, "voic":True, "auto":[], "cmds":[]} self.auto_time_l = threading.Lock() self.auto_time = [] self.load_settings() self.save_settings() # strip # character, it can be added when needed if self.settings["chan"].startswith("#"): self.settings["chan"] = self.settings["chan"][1:] print(self.settings["nick"]) print(self.settings["chan"]) print(self.settings["auth"]) print(self.settings["rate"]) print(self.settings["voic"]) print(self.settings["auto"]) print(self.settings["cmds"]) if self.settings["rate"] == None: self.settings["rate"] = 10 self.channel_data = {} # CONTROL BUTTONS FRAME self.frame_control = ttk.Frame(self.parent, relief=SUNKEN, width = 50, borderwidth=15) self.btn_connect = ttk.Button(self.frame_control, text = 'Connect', width = 25, command = self.core_connect) self.btn_goto_auth = ttk.Button(self.frame_control, text = 'Authentication', width = 25, command = self.goto_authentication) self.btn_auto_msg = ttk.Button(self.frame_control, text = 'Auto-Messages', width = 25, command = self.goto_auto_message) self.btn_commands = ttk.Button(self.frame_control, text = 'Commands', width = 25, command = self.goto_commands) self.lab_followers_s = StringVar() self.lab_followers = ttk.Label(self.frame_control, textvariable = self.lab_followers_s, width = 25) self.lab_last5fol = ttk.Label(self.frame_control, text = "Last 5 followers:", width = 25) self.lst_last5fol = Listbox(self.frame_control, width = 25, height = 5, activestyle = 'none', takefocus = False, exportselection=False) self.lab_views_s = StringVar() self.lab_views = ttk.Label(self.frame_control, textvariable = self.lab_views_s, width = 25) self.lab_status_s = StringVar() self.lab_status = ttk.Label(self.frame_control, textvariable = self.lab_status_s, width = 25) self.lab_game_s = StringVar() self.lab_game = ttk.Label(self.frame_control, textvariable = self.lab_game_s, width = 25) self.lab_streams_s = StringVar() self.lab_streams = ttk.Label(self.frame_control, textvariable = self.lab_streams_s, width = 25) self.lab_popularity_s = StringVar() self.lab_popularity = ttk.Label(self.frame_control, textvariable = self.lab_popularity_s, width = 25) # CHAT AREA FRAME self.frame_chat = ttk.Frame(self.parent, relief=SUNKEN, width = 50, borderwidth=15) self.ent_chat_input_s = StringVar() self.ent_chat_input = ttk.Entry(self.frame_chat, textvariable = self.ent_chat_input_s) self.txt_chat_log = ScrolledText(self.frame_chat, wrap=WORD) self.chat = Chat(self.settings["nick"], realname=self.settings["nick"]) self.btn_chat_send = ttk.Button(self.frame_chat, text = 'Send', width=10, command = self.chat.chat_send, state = DISABLED) self.chat.setup(self.ent_chat_input_s, self.txt_chat_log) # STATUS AREA FRAME self.frame_status = ttk.Frame(self.parent, relief=SUNKEN) self.txt_status_s = StringVar() self.txt_status = ttk.Entry(self.frame_status, textvariable = self.txt_status_s) # GRID SETUP self.frame_control.grid (column=0, row=0, sticky=(N, S, E, W)) self.btn_connect.grid (column=0, row=0, sticky=(E, W)) self.btn_goto_auth.grid (column=0, row=1, sticky=(E, W)) self.btn_auto_msg.grid (column=0, row=2, sticky=(E, W)) self.btn_commands.grid (column=0, row=3, sticky=(E, W)) self.lab_followers.grid (column=0, row=4, sticky=(E, W)) self.lab_last5fol.grid (column=0, row=5, sticky=(E, W)) self.lst_last5fol.grid (column=0, row=6, sticky=(E, W)) self.lab_views.grid (column=0, row=7, sticky=(E, W)) self.lab_status.grid (column=0, row=8, sticky=(E, W)) self.lab_game.grid (column=0, row=9, sticky=(E, W)) self.lab_streams.grid (column=0, row=10, sticky=(E, W)) self.lab_popularity.grid(column=0, row=11, sticky=(E, W)) self.frame_chat.grid (column=1, row=0, sticky=(N, S, E, W)) self.ent_chat_input.grid(column=0, row=0, sticky=(E, W), columnspan=2) self.btn_chat_send.grid (column=1, row=0, sticky=E) self.txt_chat_log.grid (column=0, row=1, sticky=(N, S, E, W), columnspan=2) self.frame_status.grid (column=0, row=1, columnspan=2, sticky=(N, S, E, W)) self.txt_status.pack (fill=BOTH, expand=YES) # WINDOW FLAGS self.opened_dialog = False # PERFORM FIRST UPDATE MANUALLY TO POPULATE UI self.do_update() # SPEECH RECOGNITION if self.settings["voic"] == True: print("Using speech") self.run_speech() def goto_authentication(self): if not self.opened_dialog: self.opened_dialog = True # Instantiate window, bind focus change to func, set focus self.window = Authentication.Authentication(Toplevel(self.parent), self) self.window.parent.bind("<FocusOut>", self.focus_out) self.window.parent.focus_set() # Open window and make main window wait self.parent.wait_window(self.window.parent) self.opened_dialog = False else: self.window.parent.focus_set() def goto_auto_message(self): if not self.opened_dialog: self.opened_dialog = True # Instantiate window, bind focus change to func, set focus self.window = AutoMessage.AutoMessage(Toplevel(self.parent), self) self.window.parent.bind("<FocusOut>", self.focus_out) self.window.parent.focus_set() # Open window and make main window wait self.parent.wait_window(self.window.parent) self.opened_dialog = False def goto_commands(self): if not self.opened_dialog: self.opened_dialog = True # Instantiate window, bind focus change to func, set focus self.window = Commands.Commands(Toplevel(self.parent), self) self.window.parent.bind("<FocusOut>", self.focus_out) self.window.parent.focus_set() # Open window and make main window wait self.parent.wait_window(self.window.parent) self.opened_dialog = False def focus_out(self, event): pass #if self.opened_dialog: #self.window.goto_main() def get_update(self): result = {} channel = twitch.channels.by_name(self.settings["chan"]) follows = twitch.follows.by_channel(self.settings["chan"], limit = 5) stream = twitch.streams.by_channel(self.settings["chan"]) result['followers'] = channel["followers"] result['views'] = channel["views"] result['game'] = {} result['title'] = channel["status"] result['last5fol'] = [] result['status'] = 0 if stream['stream'] == None else 1 for i in follows["follows"]: result['last5fol'].append(i['user']['name']) streams = twitch.search.streams(channel["game"]) games = twitch.search.games(channel["game"]) result['game']['name'] = channel["game"] result['game']['total'] = streams["_total"] result['game']['popu'] = games["games"][0]["popularity"] if len(games["games"]) > 0 else 0 return result def do_update(self): update = self.get_update() # self.chat.print_line("SYS", str(update)) # debug if self.channel_data == {}: self.channel_data = update else: if update["followers"] - self.channel_data["followers"] > 0: self.chat.message_send("Gained %d follower%s! :D"%(followers - self.channel_data["followers"], "s" if update["followers"] - self.channel_data["followers"] > 1 else "")) self.channel_data["followers"] = update["followers"] elif self.channel_data["followers"] - update["followers"] > 0: self.chat.message_send("Lost %d follower%s! :("%(self.channel_data["followers"] - update["followers"], "s" if self.channel_data["followers"] - update["followers"] > 1 else "")) self.channel_data["followers"] = update["followers"] self.lab_followers_s.set("Followers: %d"%(self.channel_data["followers"])) self.lst_last5fol.delete(0, 4) for i in update["last5fol"]: self.lst_last5fol.insert(END, i) self.lst_last5fol['state'] = DISABLED self.lab_views_s.set("Views:" + str(update['views'])) self.lab_status_s.set("Status: Online" if update['status'] == 1 else "Status: Offline") self.lab_game_s.set("Game: " + update['game']['name']) self.lab_streams_s.set("Streams of game: " + str(update['game']['total'])) self.lab_popularity_s.set("Game Popularity: " + str(update['game']['popu'])) def do_automessage(self): self.auto_time_l.acquire() for i, a in enumerate(self.auto_time): if a[0] - time.clock() < 0.0: self.auto_time[i][0] = time.clock() + (a[1]['int'] * 60) self.chat.message_send(a[1]['msg']) self.auto_time_l.release() def reload_automessage_timings(self): self.auto_time_l.acquire() self.auto_time.clear() for i in self.settings['auto']: self.auto_time.append([time.clock() + (i['int'] * 60), i]) self.auto_time_l.release() def on_voice_command(self, command): self.txt_status_s.set(command) if command.startswith("connect"): self.core_connect() elif command.startswith("disconnect"): self.core_connect() elif command.startswith("chat "): self.chat.message_send(command[5:]) def run_update(self): """Updater function that runs on a thread to grab Twitch data via API""" while self.update_forever: self.do_update() self.do_automessage() time.sleep(self.settings["rate"]) print("updater thread finished") return 0 def run_speech(self): """Speech recognition thread""" print("Started speech thread") r = sr.Recognizer() m = sr.Microphone() print(m.device_index) self.txt_status_s.set("Waiting for voice input...") with m as source: r.adjust_for_ambient_noise(source) r.listen_in_background(m, self.speech_recognised) def speech_recognised(self, recogniser, audio): self.txt_status_s.set("Analysing input...") try: recognised = recogniser.recognize_google(audio) self.on_voice_command(recognised) except sr.UnknownValueError: self.txt_status_s.set("Could not understand audio") except sr.RequestError as e: self.txt_status_s.set("Speech recognition error!") print(e) def core_connect(self): if self.update_forever: self.btn_connect['text'] = "Connect" self.btn_goto_auth.configure(state = NORMAL) self.btn_chat_send.configure(state = DISABLED) self.chat.disconnect() self.update_forever = False else: self.btn_connect['text'] = "Disconnect" self.btn_goto_auth.configure(state = DISABLED) self.btn_chat_send.configure(state = NORMAL) self.chat.do_connect(self.settings["chan"], self.settings["nick"], self.settings["auth"], self.settings['cmds']) self.fakechat = threading.Thread(target=self.fake_chat) self.fakechat.start() self.update_forever = True self.updater = threading.Thread(target=self.run_update) self.updater.start() def fake_chat(self): time.sleep(2) self.chat.print_line("SYS", "Connected!") time.sleep(4) self.chat.print_line("Steve", "Hello everyone!") time.sleep(6) self.chat.print_line("Alice", "great stream!") time.sleep(7) self.chat.print_line("Bob", "whats your twitter?") time.sleep(5) self.chat.print_line("Alan", "type the !twitter command") time.sleep(6) self.chat.on_message("#southclaw", "Bob", "!twitter") time.sleep(5) self.chat.print_line("Bob", "thanks!") time.sleep(7) self.chat.print_line("Alice", "are you streaming tomorrow?") def load_settings(self): with io.open("settings.json", "r") as f: self.settings = json.load(f) self.reload_automessage_timings() def save_settings(self): with io.open("settings.json", "w") as f: json.dump(self.settings, f, indent = "\t", sort_keys = True)