async def on_message_delete(msg): log("Attempting to delete") await gc.client.wait_until_ready() # TODO: PM's have 'None' as a guild -- fix this later if msg.guild is None: return try: for guildlog in gc.guild_log_tree: if guildlog.guild == msg.guild: for channellog in guildlog.logs: if channellog.channel == msg.channel: ft = gc.ui.views[str( channellog.channel.id)].formattedText channellog.logs.remove(msg) ft.messages.remove(msg) ft.refresh() log("Deleted, updating") if msg.channel is gc.client.current_channel: draw_screen() return except: # if the message cannot be found, an exception will be raised # this could be #1: if the message was already deleted, # (happens when multiple calls get excecuted within the same time) # or the user was banned, (in which case all their msgs disappear) pass log("Could not delete message: {}".format(msg.clean_content))
def change_guild(arg): prev_guild = gc.client.current_guild gc.client.set_current_guild(arg) if gc.client.current_guild is prev_guild: return log("changed guild") gc.ui.channel_log_offset = -1 ui.draw_screen()
def remove_last_message(self): log("Attempting to delete last message") messages = gc.ui.views[str(self.current_channel.id)].formattedText.messages message = None i = len(messages)-1 while i >= 0: message = messages[i] if message.author.id == self.user.id: log("Deleting message '{}'".format(message.clean_content)) self.wait_until_client_task_completes((message.delete,)) gc.ui.views[str(self.current_channel.id)].formattedText.refresh() draw_screen() return i -= 1 log("Could not delete last message")
def key_input(): # if the next two aren't here, input does not work curses.cbreak() curses.noecho() editWin = gc.ui.editWin gc.ui_thread.wait_until_ui_task_completes((ui.draw_edit_win, True)) while not gc.doExit: ch = editWin.getch() if ch == -1 or not gc.ui.displayPanel.hidden(): time.sleep(0.01) continue if chr(ch) != '\n' and len(gc.ui.messageEdit.inputBuffer) > 0 and \ gc.ui.messageEdit.inputBuffer[0] != ord('/'): gc.typingBeingHandled = True # prevents crashes when enter is hit and input buf is empty if chr(ch) == '\n' and not gc.ui.messageEdit.inputBuffer: continue if ch == curses.KEY_PPAGE: gc.ui.channel_log_offset -= gc.settings["scroll_lines"] ui.draw_screen() continue elif ch == curses.KEY_NPAGE: gc.ui.channel_log_offset += gc.settings["scroll_lines"] ui.draw_screen() continue elif ch == curses.KEY_RESIZE: gc.ui.resize() ui.draw_screen() continue elif ch == curses.KEY_DC: # TODO: Add functionality here ui.draw_screen() continue # if ESC is pressed, clear messageEdit buffer elif ch == 27: ch = editWin.getch() if ch in (0x7f, ord('\b'), curses.KEY_BACKSPACE): gc.ui.messageEdit.reset() gc.ui_thread.wait_until_ui_task_completes( (ui.draw_edit_win, True)) continue ret = gc.ui.messageEdit.addKey(ch) if ret is not None: input_handler(ret) gc.ui.messageEdit.reset() call = (ui.draw_edit_win, True) gc.ui_thread.funcs.append(call) while not gc.doExit and (call in gc.ui_thread.funcs or \ call[0].__name__ in gc.ui_thread.locks): time.sleep(0.01) log("key_input finished") gc.tasksExited += 1
async def process_message(msg, channel_log): if channel_log.channel not in gc.channels_entered: await gc.client.init_channel(channel_log.channel) else: channel_log.append(calc_mutations(msg)) gc.ui.channel_log_offset += 1 if msg.guild is not None and \ channel_log.channel is not gc.client.current_channel: if msg.guild.me.mention in msg.content: channel_log.mentioned_in = True else: channel_log.unread = True if msg.guild is not None and \ msg.guild.me.mention in msg.content and \ "beep_mentions" in gc.settings and \ gc.settings["beep_mentions"]: curses.beep() log("Beep!") if channel_log is gc.client.current_channel_log: ui.draw_screen()
async def on_message_edit(msg_old, msg_new): await gc.client.wait_until_ready() if msg_old.clean_content == msg_new.clean_content: return clog = gc.client.current_channel if clog is None: return ft = gc.ui.views[str(clog.id)].formattedText msg_new.content = msg_new.content + " **(edited)**" idx = 0 while True: if len(ft.messages) >= idx: break if ft.messages[idx].id == msg_old.id: ft.messages[idx].content = msg_new.content break idx += 1 ft.refresh() if init_complete and msg_old.channel is gc.client.current_channel: draw_screen()
def parseCommand(command, arg=None): if arg is None: if command in ("refresh", "update"): ui.draw_screen() log("Manual update done", logging.info) elif command in ("quit", "exit"): try: gc.exit_thread.start() except SystemExit: pass elif command in ("help", 'h'): ui.draw_help() elif command in ("guilds", "glds", "servers", "servs"): ui.draw_guildlist() elif command in ("channels", "chans"): ui.draw_channellist() elif command == "emojis": ui.draw_emojilist() elif command in ("users", "members"): ui.draw_userlist() elif command == "nick": change_nick() elif command == "dm": change_guild("private messages") elif command in ("del", "rm"): gc.client.remove_last_message() elif command[0] == 'c': try: if command[1].isdigit(): channel_jump(command) ui.draw_screen() except IndexError: pass return if command in ('guild', 'g', 'server', 's'): change_guild(arg) elif command in ("channel", 'c'): gc.client.current_channel = arg gc.ui.channel_log_offset = -1 ui.draw_screen() elif command == "nick": change_nick(arg) return elif command in ("game", "activity"): gc.client.wait_until_client_task_completes( (gc.client.set_activity, arg)) elif command == "file": send_file(arg) elif command == "status": status = arg.lower() if status in ("away", "afk"): status = "idle" elif "disturb" in status: status = "dnd" if status in ("online", "offline", "idle", "dnd"): gc.client.wait_until_client_task_completes(\ (gc.client.set_status, status))
async def on_ready(): # these values are set in settings.yaml if gc.settings["default_prompt"] is not None: gc.client.prompt = gc.settings["default_prompt"].lower() else: gc.client.prompt = '~' if gc.settings["default_activity"] is not None: await gc.client.set_activity(gc.settings["default_activity"]) privateGuild = PrivateGuild(gc.client.user) channels = [] channel_logs = [] nchannels = 0 for idx, channel in enumerate(gc.client.private_channels): chl = PrivateChannel(channel, privateGuild, idx) channels.append(chl) channel_logs.append(ChannelLog(chl, [])) nchannels += 1 privateGuild.set_channels(channels) privateGuild.set_nchannels(nchannels) gc.guild_log_tree.append(GuildLog(privateGuild, channel_logs)) for guild in gc.client.guilds: # Null check to check guild availability if guild is None: continue serv_logs = [] nchannels = 0 for channel in guild.channels: # Null checks to test for bugged out channels #if channel is None or channel.type is None: # continue # Null checks for bugged out members if guild.me is None or guild.me.id is None \ or channel.permissions_for(guild.me) is None: continue if isinstance(channel, TextChannel): nchannels += 1 if channel.permissions_for(guild.me).read_messages: serv_logs.append(ChannelLog(channel, [])) # add the channellog to the tree gl = GuildLog(guild, serv_logs) gl.set_nchannels(nchannels) gc.guild_log_tree.append(gl) if gc.settings["default_guild"] is not None: gc.client.set_current_guild(gc.settings["default_guild"]) if gc.client.current_guild is None: print("ERROR: default_guild not found!") raise KeyboardInterrupt return if gc.settings["default_channel"] is not None: gc.client.current_channel = gc.settings["default_channel"].lower() gc.client.prompt = gc.settings["default_channel"].lower() # start our own coroutines gc.client.loop.create_task(gc.client.run_calls()) gc.ui_thread.start() while not gc.ui.isInitialized: await asyncio.sleep(0.1) await gc.client.init_channel() draw_screen() gc.key_input_thread = WorkerThread(gc, key_input) gc.typing_handler_thread = WorkerThread(gc, typing_handler) gc.exit_thread = WorkerThread(gc, kill) gc.key_input_thread.start() gc.typing_handler_thread.start() global init_complete init_complete = True