def highlight_collect_cb(word, word_eol, userdata): """Looks for highlighted words (set on HexChat/X-Chat settings) and copy the entire line who contains it to the "GatoScript" tab. Arguments: word -- array of strings sent by HexChat/X-Chat to every hook word_eol -- array of strings sent by HexChat/X-Chat to every hook userdata -- optional variable that can be sent to a hook (ignored) """ if hexchat.get_prefs("irc_extra_hilight") != '': highlight = hexchat.get_prefs("irc_extra_hilight").split(",") # Extract some text to compose the output string channel = word[2] nick = word[0].split("!")[0][1:] text = word_eol[3][1:] # If there is any highlighted word, compose the string and write it to # the script query for highlighted in highlight: exp = re.compile(highlighted, re.IGNORECASE) if exp.search(text): if word[3] in action_txt: helper.query_line("".join([ nick, "has mentioned \003", color(), highlighted, "\003 in a query: <", nick, "> ", word_eol[4][:-1]])) else: helper.query_line("".join([ nick, " has mentioned \003", color(), highlighted, "\003 in ", channel, ": <", nick, "> ", text])) return hexchat.EAT_NONE
def notify(title, message): if hexchat.get_prefs('away_omit_alerts') and hexchat.get_info('away'): return if hexchat.get_prefs('gui_focus_omitalerts') and hexchat.get_info('win_status') == 'active': return Notifier.notify(hexchat.strip(message), title=hexchat.strip(title), sender='org.hexchat', sound='default')
def keypress(w, we, u): if re.search(affected_networks, hexchat.get_info("network")): key, state, key_str, str_len = w if int(key) == 65289: # <Tab> inputbox = hexchat.get_info("inputbox") pos = hexchat.get_prefs("state_cursor") text, suffix = inputbox[:pos], inputbox[pos:] prefix, space, word = text.rpartition(" ") if len(word): prefix += space if word[0] == '#': return hexchat.EAT_NONE # let the built-in completion handle channels if word[0] == '@': word = word[1:] users = [] for u in hexchat.get_list("users"): if not hexchat.nickcmp(u.nick[:len(word)], word): users.append((u.nick, u.lasttalk)) for c in hexchat.get_list("channels"): if c.context == hexchat.get_context(): if c.type == 3: if not hexchat.nickcmp(c.channel[:len(word)], word): users.append((c.channel, 0)) # if we're in a dialog, include the targer user if len(users): if len(users) == 1: completion = "@" + users[0][0] + " " else: if hexchat.get_prefs("completion_sort") == 1: users = sorted(users, key = lambda x: -x[1]) else: users = sorted(users, key = lambda x: x[0].lower()) nicks = [u[0] for u in users] print(" ".join(nicks)) common = None # longest common prefix for nick in nicks: if common == None: common = word + nick[len(word):] # copy the case of characters entered by the user else: while hexchat.nickcmp(nick[:len(common)], common): common = common[:-1] for nick in nicks: if not hexchat.nickcmp(nick, word): common = nick # if we have an exact match, ignore the case of user's characters completion = "@" + common hexchat.command("settext " + prefix + completion + suffix) hexchat.command("setcursor " + str(len(prefix) + len(completion))) return hexchat.EAT_ALL else: prevword = prefix.rpartition(" ")[2] if len(prevword) and prevword[0] == '@': return hexchat.EAT_ALL # don't let the built-in completion kick in if we just completed a nick else: return hexchat.EAT_NONE else: return hexchat.EAT_NONE
def do_autocomplete(input, nicks): global old_input, old_last_word, old_match, old_state_cursor state_cursor = hexchat.get_prefs("state_cursor") tail = input[state_cursor:] head = input[:state_cursor] if not head.rstrip(): return hexchat.EAT_NONE parts = head.rstrip().split(" ") # if the input is exactly we left it previously, go into cycling mode if input == old_input and state_cursor == old_state_cursor: cycle = True last_word = old_last_word else: last_word = parts[-1].lower() old_last_word = last_word cycle = False # find matches matches = [match for match in nicks if match.lower().startswith(last_word)] if len(matches) > hexchat.get_prefs("completion_amount"): # print out a list of matches and quit hexchat.prnt(" ".join(matches)) return hexchat.EAT_ALL elif len(matches) < 1: # no matches return hexchat.EAT_NONE # find out which element in the match list we want if cycle is True and old_match in matches: ind = matches.index(old_match) + 1 if ind >= len(matches): ind = 0 else: ind = 0 old_match = matches[ind] # add completion suffix if input is only one word if len(parts) == 1: head = matches[ind] + hexchat.get_prefs("completion_suffix") else: head = "{} {}".format(" ".join(parts[:-1]), matches[ind]) head += " " new_state_cursor = len(head) input = head + tail hexchat.command("SETTEXT {}".format(input)) hexchat.command("SETCURSOR {}".format(new_state_cursor)) old_input = input old_state_cursor = new_state_cursor return hexchat.EAT_ALL
def notify(title, message): if hexchat.get_prefs('away_omit_alerts') and hexchat.get_info('away'): return if hexchat.get_prefs('gui_focus_omitalerts') and hexchat.get_info( 'win_status') == 'active': return Notifier.notify(hexchat.strip(message), title=hexchat.strip(title), sender='org.hexchat', sound='default')
def preprocess_inputbox(inputbox): # Return values: # doprocess, message, fullcommand, cmd_length # TODO: only return at end. # "doprocess" means we can understand what needs to be parsed in the inputbox so that we can have content to pastebin. # "message" is the content to pastebin, without the command. # "fullcommand" is the command we have parsed from the inputbox. # e.g. "/msg OtherUser" # "cmd_legth" is how much space this command would take up in the raw message to the server. cmdprefix = hexchat.get_prefs("input_command_char") # default is "/" as in "/msg" if inputbox.startswith(cmdprefix + cmdprefix) or not inputbox.startswith(cmdprefix): # ('//msg blah' is the same as '/say /msg blah') cmd_length = commands_options['say']['cmdlength'] return True, inputbox, "", cmd_length else: boxsplit = [word for word in re.split(re_words, inputbox) if word] print_debug("boxsplit", boxsplit) command = boxsplit[0] command = command.lstrip("/").rstrip() options = get_opts_for_cmd(command, inputbox) if options is not None: paramcount = options['paramcount'] print_debug("paramcount", paramcount) re_cmd_and_msg = r'^((?:[^\s]*\s){%d}[^\s]*)\s(.*)' % paramcount # http://stackoverflow.com/a/17060122/3143160 # fullcommand here would be "/msg OtherUser" in the example of "/msg OtherUser message" split_cmd_and_msg = [word for word in re.split(re_cmd_and_msg, inputbox) if word] fullcommand = split_cmd_and_msg[0] message = inputbox[len(fullcommand)+1:] fullcommand.strip() cmd_length = options['cmdlength'] return True, message, fullcommand, cmd_length return False, None, None, None
def privmsg_cb(word, word_eol, userdata): if word[0][1:].split("!")[0] == "jtv": for chan in hexchat.get_list("channels"): if chan.type == 1 and chan.id == hexchat.get_prefs("id"): chan.context.set() hexchat.emit_print("Server Text", word_eol[3][1:]) return hexchat.EAT_ALL
def greplog(channel, pattern): logmask = hexchat.get_prefs("irc_logmask") logfile = logmask.replace("%n", hexchat.get_info("network")).replace("%s",hexchat.get_info("server")).replace("%c",channel) logfile = os.path.join(hexchat.get_info("configdir"), "logs", logfile) if not os.path.isfile(logfile): error("log-file %s does not exist" % logfile) return hexchat.EAT_ALL if is_linux: # on linux hexchat.command("exec grep '" + pattern + "' " + logfile) else: with open(logfile, "r") as f: for line in f: try: if re.search(pattern, line): hexchat.prnt(line) except: if line.find(pattern) > -1: hexchat.prnt(line) return hexchat.EAT_ALL
def preprocess_inputbox(inputbox): # Return values: # doprocess, message, fullcommand, cmd_length # TODO: only return at end. # "doprocess" means we can understand what needs to be parsed in the inputbox so that we can have content to pastebin. # "message" is the content to pastebin, without the command. # "fullcommand" is the command we have parsed from the inputbox. # e.g. "/msg OtherUser" # "cmd_legth" is how much space this command would take up in the raw message to the server. cmdprefix = hexchat.get_prefs("input_command_char") # default is "/" as in "/msg" if not inputbox.startswith(cmdprefix): cmd_length = commands_options['say']['cmdlength'] return True, inputbox, "", cmd_length else: boxsplit = [word for word in re.split(re_words, inputbox) if word] print_debug("boxsplit", boxsplit) command = boxsplit[0] command = command.lstrip("/").rstrip() options = get_opts_for_cmd(command, inputbox) if options is not None: paramcount = options['paramcount'] re_cmd_and_msg = r"((?:\S*\s){%s})" % paramcount # fullcommand here would be "/msg OtherUser" in the example of "/msg OtherUser message" # TODO: /msg otheruser longmsg doesn't work _, fullcommand, message = [word for word in re.split(re_cmd_and_msg, inputbox) if word] fullcommand.strip() cmd_length = options['cmdlength'] return True, message, fullcommand, cmd_length return False, None, None, None
def open_tabs(): server_context = hexchat.get_info("server") tab_options = hexchat.get_prefs('tab_new_to_front') hexchat.command("set -quiet tab_new_to_front 0") for tab in TABS: hexchat.command("NEWSERVER -noconnect %s" % tab)
def getNick(prefix,nick): if bool(hexchat.get_prefs('text_color_nicks')): nick = addColor(nick) else: # as omnomirc can color nicks on itself nick = hexchat.strip(nick) nick = nick.replace(' ','\xA0') return '\x0F'+prefix+'\x0F\xA0'+nick
def privmsg_cb(word, word_eol, userdata): if word[0][1:].split('!')[0] == 'jtv': for chan in hexchat.get_list('channels'): if chan.type == 1 and chan.id == hexchat.get_prefs('id'): chan.context.set() hexchat.emit_print('Server Text', word_eol[3][1:]) return hexchat.EAT_ALL
def update_textbox(match, group): start = match.start(group) end = match.end(group) string = match.string text = string[:start] + placeholder * (end - start) + string[end:] cur_pos = hexchat.get_prefs("state_cursor") hexchat.command("settext " + text) hexchat.command("setcursor " + str(cur_pos))
def netId(ctx=None): if ctx == None or ctx == hexchat.get_context(): return hexchat.get_prefs("id") else: for c in hexchat.get_list("channels"): if c.context == ctx: return c.id return "?"
def ghost(word, word_eol, userdata): nickname = hexchat.get_prefs("irc_nick1") password = hexchat.get_info("nickserv") hexchat.command("nickserv ghost %s %s" % (nickname, password)) hexchat.command("nick %s" % nickname) hexchat.command("nickserv identify %s" % password) return hexchat.EAT_NONE
def netId(ctx = None): if ctx == None or ctx == hexchat.get_context(): return hexchat.get_prefs("id") else: for c in hexchat.get_list("channels"): if c.context == ctx: return c.id return "?"
def handle_start_blinking(self): if hexchat.get_prefs('away_omit_alerts') and hexchat.get_info('away'): return if hexchat.get_prefs('gui_focus_omitalerts') and \ hexchat.get_info('win_status') == 'active': return active = hexchat.get_pluginpref("razeralert_active") if not active: return False while self.blink: subprocess.call(['/home/gabriel/dev/hexchat-razeralert/keyboard_controller.py', 'black']) time.sleep(.25) subprocess.call(['/home/gabriel/dev/hexchat-razeralert/keyboard_controller.py', 'gabriel']) time.sleep(.25)
def check_highlight(message): hilights = hexchat.get_prefs("irc_extra_hilight") hilight_list = hilights.split(",") if hexchat.get_info("nick") in message: return True elif any(message.find(check) > -1 for check in hilight_list): return True else: return False
def insert_zws(word, word_eol, userdata): text = hexchat.get_info("inputbox") cursor = hexchat.get_prefs("state_cursor") text = text[:cursor] + "\u200B" + text[cursor:] hexchat.command("SETTEXT {}".format(text)) hexchat.command("SETCURSOR {}".format(cursor + 1)) return hexchat.EAT_ALL
def privmsg_cb(word, word_eol, userdata): if word[0][1:].split('!')[0] == 'jtv': if word[2][0] != '#': for chan in hexchat.get_list('channels'): if chan.type == 1 and chan.id == hexchat.get_prefs('id'): chan.context.emit_print('Server Text', word_eol[3][1:]) return hexchat.EAT_ALL elif word[3] in (':USERCOLOR', ':USERSTATE', ':HISTORYEND', ':EMOTESET', ':CLEARCHAT', ':SPECIALUSER'): return hexchat.EAT_ALL
def insert_zws(word, word_eol, userdata): text = hexchat.get_info('inputbox') cursor = hexchat.get_prefs('state_cursor') text = text[:cursor] + '\u200B' + text[cursor:] hexchat.command('SETTEXT {}'.format(text)) hexchat.command('SETCURSOR {}'.format(cursor + 1)) return hexchat.EAT_ALL
def findLogTab(): context = hexchat.find_context(channel=LOG_TAB) if context == None: # Create a new one in the background newtofront = hexchat.get_prefs('gui_tab_newtofront') hexchat.command('set -quiet gui_tab_newtofront 0') hexchat.command('newserver -noconnect {0}'.format(LOG_TAB)) hexchat.command('set -quiet gui_tab_newtofront {}'.format(newtofront)) return hexchat.find_context(channel=LOG_TAB) else: return context
def update(key_type): global unmasked_command, old_cursor try: textbox = hexchat.get_info("inputbox") cur_pos = hexchat.get_prefs("state_cursor") if unmasked_command == None: for pat in patterns: match = re.search(pat, textbox, flags=re.I) if match: group = group_name(match) unmasked_command = textbox old_cursor = cur_pos update_textbox(match, group) break else: if key_type == "edit": old_prefix, old_suffix = unmasked_command[: old_cursor], unmasked_command[ old_cursor:] new_prefix, new_suffix = textbox[:cur_pos], textbox[cur_pos:] if len(new_prefix) <= len(old_prefix): prefix = old_prefix[:len(new_prefix)] else: prefix = old_prefix + new_prefix[len(old_prefix):] if len(new_suffix) <= len(old_suffix): if len(new_suffix): suffix = old_suffix[-len(new_suffix):] else: suffix = "" else: if len(old_suffix): suffix = new_suffix[:-len(old_suffix)] + old_suffix else: suffix = new_suffix command = prefix + suffix elif key_type == "reset": command = textbox else: command = unmasked_command for pat in patterns: match = re.search(pat, command, flags=re.I) if match: group = group_name(match) unmasked_command = command old_cursor = cur_pos update_textbox(match, group) break else: reset_textbox(command, cur_pos) unmasked_command = None old_cursor = None except: unmasked_command = None old_cursor = None raise
def process(word, word_eol, userdata): # States taken from https://github.com/TingPing/plugins/blob/master/HexChat/growl.py # Thanks TingPing! try: if hexchat.get_prefs('away_omit_alerts') and hexchat.get_info('away'): return None if hexchat.get_prefs('gui_focus_omitalerts') and hexchat.get_info( 'win_status') == 'active': return None except Exception as err: pass try: if len(word) >= 3: Pop(word[2] + word[0], word[1]) else: Pop(word[0], word[1]) except Exception as err: print('Bubbling Error:') print(err)
def privmsg_cb(word, word_eol, userdata): nick = word[0][1:].split('!')[0] if nick == 'jtv' or nick == 'twitchnotify': if word[2][0] != '#': for chan in hexchat.get_list('channels'): if chan.type == 1 and chan.id == hexchat.get_prefs('id'): chan.context.emit_print('Server Text', word_eol[3][1:]) return hexchat.EAT_ALL else: hexchat.emit_print('Server Text', word_eol[3][1:]) return hexchat.EAT_ALL
def keypress_cb(word, word_eol, userdata): global last_index global last_completes global last_text global last_pos if not word[0] == '65289': # Tab return if not hexchat.get_info('channel') == '>>python<<': return shift_key_is_down = bool(int(word[1]) & 1) # check if shift modifier is hold text = hexchat.get_info('inputbox') pos = hexchat.get_prefs('state_cursor') if not text: return base = text[:pos].split(' ')[-1] module, _, prefix = base.rpartition('.') if not module: # can not dir() the console's interpreter state sadly return if last_text != text or last_pos != pos: # new completion context try: exec('import {}'.format(module), exec_scope) # Has to be imported to dir() it completions = eval('dir({})'.format(module), exec_scope) except (NameError, SyntaxError, ImportError): return completions = [c for c in completions if c.startswith(prefix)] if not completions: return index = 0 else: # same context, insert next completion completions = last_completes direction = 1 if not shift_key_is_down else -1 index = (last_index + direction) % len(completions) complete_text = completions[index] new_text = text[:pos - len(prefix)] + complete_text + text[pos:] new_pos = pos - len(prefix) + len(complete_text) hexchat.command('settext {}'.format(new_text)) hexchat.command('setcursor {}'.format(new_pos)) last_index = index last_completes = completions last_text = new_text last_pos = new_pos
def find_log_tab(): """ Create separate tab for debugging messages """ context = hexchat.find_context(channel=LOG_CONTEXT_NAME) if context == None: newtofront = hexchat.get_prefs('gui_tab_newtofront') hexchat.command('set -quiet gui_tab_newtofront 0') hexchat.command('newserver -noconnect {0}'.format(LOG_CONTEXT_NAME)) hexchat.command('set -quiet gui_tab_newtofront {}'.format(newtofront)) return hexchat.find_context(channel=LOG_CONTEXT_NAME) else: return context
def unloaded_cb(userdata): # first remove MENU entry, only if we really unload, if we reload, we don't do this, since new calls to MENU ADD update the GUI if hexchat.get_pluginpref("menu_added") == 0: hexchat.command ("MENU DEL \"Auto XDCC\"") hexchat.set_pluginpref("menu_added",0) # Force close running threads for packlist in packlist_manager.packlists.values(): packlist.download_manager.terminate(True) if config.telegram_bot: config.telegram_bot.terminate(True) if int(hexchat.get_prefs('dcc_auto_recv')) != 0: hexchat.command("set dcc_auto_recv 0") if int(hexchat.get_prefs('dcc_remove')) != int(default_clear_finished): hexchat.command("set dcc_remove " + str(default_clear_finished)) sleep(0.1) hexchat_parser.printer.x("Plugin unloaded") return hexchat.EAT_ALL
def update(key_type): global unmasked_command, old_cursor try: textbox = hexchat.get_info("inputbox") cur_pos = hexchat.get_prefs("state_cursor") if unmasked_command == None: for pat in patterns: match = re.search(pat, textbox, flags = re.I) if match: group = group_name(match) unmasked_command = textbox old_cursor = cur_pos update_textbox(match, group) break else: if key_type == "edit": old_prefix, old_suffix = unmasked_command[:old_cursor], unmasked_command[old_cursor:] new_prefix, new_suffix = textbox[:cur_pos], textbox[cur_pos:] if len(new_prefix) <= len(old_prefix): prefix = old_prefix[:len(new_prefix)] else: prefix = old_prefix + new_prefix[len(old_prefix):] if len(new_suffix) <= len(old_suffix): if len(new_suffix): suffix = old_suffix[-len(new_suffix):] else: suffix = "" else: if len(old_suffix): suffix = new_suffix[:-len(old_suffix)] + old_suffix else: suffix = new_suffix command = prefix + suffix elif key_type == "reset": command = textbox else: command = unmasked_command for pat in patterns: match = re.search(pat, command, flags = re.I) if match: group = group_name(match) unmasked_command = command old_cursor = cur_pos update_textbox(match, group) break else: reset_textbox(command, cur_pos) unmasked_command = None old_cursor = None except: unmasked_command = None old_cursor = None raise
def find_highlighttab(arg1): context = hexchat.find_context(channel=arg1) if context == None: newtofront = hexchat.get_prefs('gui_tab_newtofront') hexchat.command('set -quiet gui_tab_newtofront 0') hexchat.command('newserver -noconnect {0}'.format(arg1)) hexchat.command('set -quiet gui_tab_newtofront {}'.format(newtofront)) return hexchat.find_context(channel=arg1) else: return context
def find_highlighttab(): context = hexchat.find_context(channel=TAB_NAME) if context == None: # Create a new one in the background newtofront = hexchat.get_prefs('gui_tab_newtofront') hexchat.command('set -quiet gui_tab_newtofront 0') hexchat.command('newserver -noconnect {0}'.format(TAB_NAME)) hexchat.command('set -quiet gui_tab_newtofront {}'.format(newtofront)) return hexchat.find_context(channel=TAB_NAME) else: return context
def highlights_tab(): """ Function which will return context of tab for logging highlights. If the tab does not exist, it is created. """ context = hexchat.find_context(channel=HIGHLIGHTS_TAB) if context is None: newtofront = hexchat.get_prefs('gui_tab_newtofront') hexchat.command('set -quiet gui_tab_newtofront 0') hexchat.command('newserver -noconnect {}'.format(HIGHLIGHTS_TAB)) hexchat.command('set -quiet gui_tab_newtofront {}'.format(newtofront)) context = hexchat.find_context(channel=HIGHLIGHTS_TAB) return context
def commandLog(w, we, u): context = hexchat.find_context(channel = logTab) if context: context.command("clear") context.command("gui focus") else: oldSetting = hexchat.get_prefs("gui_tab_newtofront") hexchat.command("set -quiet gui_tab_newtofront 1") hexchat.command("query " + logTab) hexchat.command("set -quiet gui_tab_newtofront " + str(oldSetting)) context = hexchat.find_context(channel = logTab) for t, entry in logHistory: context.prnt(time.strftime("[%H:%M:%S] ", t) + entry) return hexchat.EAT_ALL
def commandLog(w, we, u): context = hexchat.find_context(channel=logTab) if context: context.command("clear") context.command("gui focus") else: oldSetting = hexchat.get_prefs("gui_tab_newtofront") hexchat.command("set -quiet gui_tab_newtofront 1") hexchat.command("query " + logTab) hexchat.command("set -quiet gui_tab_newtofront " + str(oldSetting)) context = hexchat.find_context(channel=logTab) for t, entry in logHistory: context.prnt(time.strftime("[%H:%M:%S] ", t) + entry) return hexchat.EAT_ALL
def move_cb(word, word_eol, userdata): global moved if moved: return for chan in hexchat.get_list("channels"): if chan.type == 1 and chan.id == hexchat.get_prefs("id"): network_context = chan.context moved = True network_context.emit_print("Change Nick", word[0], word[1]) moved = False return hexchat.EAT_ALL
def Hnotices(word, word_eol, userdata): if word[0] == None or '!' not in word[0]: return hexchat.EAT_NONE nick, host = word[0].split('!', 1) nick = nick[1:] message = word_eol[3][1:] if "@services." in host.lower() and word[2][0] != '#': cur_id = hexchat.get_prefs("id") context = hexchat.find_context() for chan in hexchat.get_list('channels'): if chan.id == cur_id and chan.context == context: context.emit_print("Notice", nick, message) return hexchat.EAT_ALL return hexchat.EAT_NONE
def load_session(): for pref in hexchat.list_pluginpref(): if len(pref) > 8 and pref[:8] == 'session_': network = pref[8:] channels = hexchat.get_pluginpref('session_' + network).split(',') hexchat.command('url irc://"{}"/'.format(network)) # Using url avoids autojoin hexchat.find_context(server=network).set() delay = hexchat.get_prefs('irc_join_delay') + 10 for chan in channels: if chan[0] != '#': hexchat.command('timer {} query -nofocus {}'.format(delay, chan)) else: hexchat.command('timer {} join {}'.format(delay, chan)) hexchat.del_pluginpref('session_' + network)
def Hnotices(word, word_eol, userdata): if word[0] == None or '!' not in word[0]: return hexchat.EAT_NONE nick,host = word[0].split('!', 1) nick = nick[1:] message = word_eol[3][1:] if "@services." in host.lower() and word[2][0] != '#': cur_id = hexchat.get_prefs("id") context = hexchat.find_context(); for chan in hexchat.get_list('channels'): if chan.id == cur_id and chan.context == context: context.emit_print("Notice",nick,message); return hexchat.EAT_ALL return hexchat.EAT_NONE
def handle_start_blinking(self): if hexchat.get_prefs('away_omit_alerts') and hexchat.get_info('away'): return if hexchat.get_prefs('gui_focus_omitalerts') and \ hexchat.get_info('win_status') == 'active': return active = hexchat.get_pluginpref("razeralert_active") if not active: return False while self.blink: subprocess.call([ '/home/gabriel/dev/hexchat-razeralert/keyboard_controller.py', 'black' ]) time.sleep(.25) subprocess.call([ '/home/gabriel/dev/hexchat-razeralert/keyboard_controller.py', 'gabriel' ]) time.sleep(.25)
def msg_cb(word, word_eol, event_name, attrs): global edited if edited or is_today(attrs.time): return format = hexchat.get_prefs('stamp_text_format') hexchat.command('set -quiet stamp_text_format {}'.format('%m-%d ' + format)) edited = True hexchat.emit_print(event_name, word[0], word[1], time=attrs.time) edited = False hexchat.command('set -quiet stamp_text_format {}'.format(format)) return hexchat.EAT_ALL
def load_session(): for pref in hexchat.list_pluginpref(): if len(pref) > 8 and pref[:8] == 'session_': network = pref[8:] channels = hexchat.get_pluginpref('session_' + network).split(',') hexchat.command( 'url irc://"{}"/'.format(network)) # Using url avoids autojoin hexchat.find_context(server=network).set() delay = hexchat.get_prefs('irc_join_delay') + 10 for chan in channels: if chan[0] != '#': hexchat.command('timer {} query -nofocus {}'.format( delay, chan)) else: hexchat.command('timer {} join {}'.format(delay, chan)) hexchat.del_pluginpref('session_' + network)
def on_away(word, word_eol, userdata): """Hook function to be called upon usage of the away command""" global flag if not flag: try: away_msg = word_eol[1] except IndexError: away_msg = hexchat.get_prefs("away_reason") for channel in hexchat.get_list("channels"): if channel.type == 1 and channel.context.get_info("away") is None: flag = True channel.context.command("away " + away_msg) return hexchat.EAT_HEXCHAT else: flag = False
def get_inputbox_infos(): inputbox = hexchat.get_info('inputbox') channel = hexchat.get_info('channel') if not inputbox.strip(): return if not inputbox.lower().startswith( ('/znc ', '/msg *')) and not channel.startswith('*'): return cursor_pos = hexchat.get_prefs('state_cursor') before_cursor = inputbox[:cursor_pos] after_cursor = inputbox[cursor_pos:] parts = before_cursor.split(' ') if not parts: return to_complete = parts[-1] before_cursor = ' '.join(parts[:-1]) pre_commands = before_cursor.split() if to_complete.startswith('*') and inputbox.lower().startswith( ('/msg ', '/znc ')): # autocomplete channel/znc module pre_commands.pop(0) return BoxInfo(None, pre_commands, to_complete, cursor_pos, before_cursor, after_cursor) # determine current module name and possibly already complete commands if inputbox.lower().startswith(('/msg *', '/znc *')): pre_commands = before_cursor.split()[2:] channel = before_cursor.split()[1] elif inputbox.lower().startswith('/znc '): pre_commands = before_cursor.split()[1:] channel = '*status' elif inputbox.startswith('/'): # any other command return return BoxInfo(channel, pre_commands, to_complete, cursor_pos, before_cursor, after_cursor)
def auth_cb(word, word_eol, userdata): if not hexchat.get_info('network') in NETWORKS: return # This will fail if user does not have pubkey set if word[1] == '+': user = hexchat.get_prefs('irc_user_name') if not USERNAME else USERNAME hexchat.emit_print('SASL Authenticating', user, 'ECDSA-NIST256P-CHALLENGE') encoded = base64.b64encode(user + '\000' + user) hexchat.command('quote AUTHENTICATE {}'.format(encoded)) return hexchat.EAT_ALL try: ret = subprocess.check_output(['ecdsatool', 'sign', KEY_FILE, word_eol[1]]) hexchat.command('quote AUTHENTICATE {}'.format(ret)) # TODO: Long messages? except (subprocess.CalledProcessError, OSError) as e: print('Error running ecdsatool: {}'.format(e)) hexchat.command('quote AUTHENTICATE *') return hexchat.EAT_ALL
def on_key_press(word, word_eol, userdata): msg = hexchat.get_info('inputbox') pos = hexchat.get_prefs('state_cursor') # If this fails for you, it's because of # https://github.com/hexchat/hexchat/issues/869 key = int(word[0]) modifier = int(word[1]) if not msg: return if ( pos and key in (KEY_TAB, KEY_SPACE) and not (modifier & KEY_MOD_SHIFT) and msg[pos - 1] == "#" ): channel = hexchat.get_info('channel') msg = msg[:pos - 1] + channel + msg[pos:] hexchat.command("settext %s" % msg) hexchat.command("setcursor %d" % (pos + len(channel) - 1))
def get_inputbox_infos(): inputbox = hexchat.get_info('inputbox') channel = hexchat.get_info('channel') if not inputbox.strip(): return if not inputbox.lower().startswith(('/znc ', '/msg *')) and not channel.startswith('*'): return cursor_pos = hexchat.get_prefs('state_cursor') before_cursor = inputbox[:cursor_pos] after_cursor = inputbox[cursor_pos:] parts = before_cursor.split(' ') if not parts: return to_complete = parts[-1] before_cursor = ' '.join(parts[:-1]) pre_commands = before_cursor.split() if to_complete.startswith('*') and inputbox.lower().startswith(('/msg ', '/znc ')): # autocomplete channel/znc module pre_commands.pop(0) return BoxInfo(None, pre_commands, to_complete, cursor_pos, before_cursor, after_cursor) # determine current module name and possibly already complete commands if inputbox.lower().startswith(('/msg *', '/znc *')): pre_commands = before_cursor.split()[2:] channel = before_cursor.split()[1] elif inputbox.lower().startswith('/znc '): pre_commands = before_cursor.split()[1:] channel = '*status' elif inputbox.startswith('/'): # any other command return return BoxInfo(channel, pre_commands, to_complete, cursor_pos, before_cursor, after_cursor)
def auth_cb(word, word_eol, userdata): if not hexchat.get_info('network') in NETWORKS: return # This will fail if user does not have pubkey set if word[1] == '+': user = hexchat.get_prefs('irc_user_name') if not USERNAME else USERNAME hexchat.emit_print('SASL Authenticating', user, 'ECDSA-NIST256P-CHALLENGE') encoded = base64.b64encode(user + '\000' + user) hexchat.command('quote AUTHENTICATE {}'.format(encoded)) return hexchat.EAT_ALL try: ret = subprocess.check_output( ['ecdsatool', 'sign', KEY_FILE, word_eol[1]]) hexchat.command( 'quote AUTHENTICATE {}'.format(ret)) # TODO: Long messages? except (subprocess.CalledProcessError, OSError) as e: print('Error running ecdsatool: {}'.format(e)) hexchat.command('quote AUTHENTICATE *') return hexchat.EAT_ALL
def preprocess_inputbox(inputbox): # Return values: # doprocess, message, fullcommand, cmd_length # TODO: only return at end. # "doprocess" means we can understand what needs to be parsed in the inputbox so that we can have content to pastebin. # "message" is the content to pastebin, without the command. # "fullcommand" is the command we have parsed from the inputbox. # e.g. "/msg OtherUser" # "cmd_legth" is how much space this command would take up in the raw message to the server. cmdprefix = hexchat.get_prefs( "input_command_char") # default is "/" as in "/msg" if inputbox.startswith(cmdprefix + cmdprefix) or not inputbox.startswith(cmdprefix): # ('//msg blah' is the same as '/say /msg blah') cmd_length = commands_options['say']['cmdlength'] return True, inputbox, "", cmd_length else: boxsplit = [word for word in re.split(re_words, inputbox) if word] print_debug("boxsplit", boxsplit) command = boxsplit[0] command = command.lstrip("/").rstrip() options = get_opts_for_cmd(command, inputbox) if options is not None: paramcount = options['paramcount'] print_debug("paramcount", paramcount) re_cmd_and_msg = r'^((?:[^\s]*\s*){%d}[^\s]*)\s(.*)' % paramcount # by perreal https://stackoverflow.com/a/17060122/3143160 # fullcommand here would be "/msg OtherUser" in the example of "/msg OtherUser message" split_cmd_and_msg = [ word for word in re.split(re_cmd_and_msg, inputbox) if word ] fullcommand = split_cmd_and_msg[0] message = inputbox[len(fullcommand) + 1:] fullcommand = fullcommand.strip() cmd_length = options['cmdlength'] return True, message, fullcommand, cmd_length return False, None, None, None
def get_with_cursor(): cursorposition = hexchat.get_prefs("state_cursor") inputbox = get() return "".join((inputbox[:cursorposition], CURSORPLACEHOLDER, inputbox[cursorposition:]))
__module_description__ = ("Allows easy accessing of URLs. When active, links" "can be launched with a few keypresses.") import hexchat import re from time import time # networks['network']['channel'][index] = {'time': message time, 'data': word, # 'event': type of event} networks = {} uids = [] halt = False hint_hook = None hooked = False scrollback = hexchat.get_prefs("text_max_lines") # from http://daringfireball.net/2010/07/improved_regex_for_matching_urls url_regex = (r"(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)" "(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+" "(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|" "[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))") url_regex = re.compile(url_regex) def pretty_print(msg): print("\00307>> " + msg) def eat_event(word, word_eol, event): if halt is True: return hexchat.EAT_PLUGIN def new_msg(word, word_eol, event, attr):