def _on_py_command(word, word_eol, userdata): subcmd = __decode(ffi.string(word[2])).lower() if subcmd == 'exec': python = __decode(ffi.string(word_eol[3])) exec_in_interp(python) elif subcmd == 'load': filename = __decode(ffi.string(word[3])) load_filename(filename) elif subcmd == 'unload': name = __decode(ffi.string(word[3])) if not unload_name(name): lib.hexchat_print(lib.ph, b'Can\'t find a python plugin with that name') elif subcmd == 'reload': name = __decode(ffi.string(word[3])) if not reload_name(name): lib.hexchat_print(lib.ph, b'Can\'t find a python plugin with that name') elif subcmd == 'console': lib.hexchat_command(lib.ph, b'QUERY >>python<<') elif subcmd == 'list': list_plugins() elif subcmd == 'about': lib.hexchat_print(lib.ph, b'HexChat Python interface version ' + VERSION) else: lib.hexchat_command(lib.ph, b'HELP PY') return 3
def _on_say_command(word, word_eol, userdata): channel = ffi.string(lib.hexchat_get_info(lib.ph, b'channel')) if channel == b'>>python<<': python = ffi.string(word_eol[1]) lib.hexchat_print(lib.ph, b'>>> ' + python) exec_in_interp(__decode(python)) return 0
def _on_say_command(word, word_eol, userdata): channel = ffi.string(lib.hexchat_get_info(lib.ph, b'channel')) if channel == b'>>python<<': python = ffi.string(word_eol[1]) lib.hexchat_print(lib.ph, b'>>> ' + python) exec_in_interp(__decode(python)) return 1 return 0
def __cstrarray_to_list(arr): i = 0 ret = [] while arr[i] != ffi.NULL: ret.append(ffi.string(arr[i])) i += 1 return ret
def _on_reload_command(word, word_eol, userdata): filename = ffi.string(word[2]) if filename.endswith(b'.py'): reload_name(__decode(filename)) return 3 return 0
def get_info(name): ret = lib.hexchat_get_info(lib.ph, name.encode()) if ret == ffi.NULL: return None if name in ('gtkwin_ptr', 'win_ptr'): # Surely there is a less dumb way? ptr = repr(ret).rsplit(' ', 1)[1][:-1] return ptr return __decode(ffi.string(ret))
def load_filename(filename): filename = os.path.expanduser(filename) if not os.path.isabs(filename): configdir = __decode(ffi.string(lib.hexchat_get_info(lib.ph, b'configdir'))) filename = os.path.join(configdir, 'addons', filename) if filename and not any(plugin.filename == filename for plugin in plugins): plugin = Plugin() if plugin.loadfile(filename): plugins.add(plugin) return True return False
def autoload(): configdir = __decode(ffi.string(lib.hexchat_get_info(lib.ph, b'configdir'))) addondir = os.path.join(configdir, 'addons') try: with change_cwd(addondir): # Maintaining old behavior for f in os.listdir(addondir): if f.endswith('.py'): log('Autoloading', f) # TODO: Set cwd load_filename(os.path.join(addondir, f)) except FileNotFoundError as e: log('Autoload failed', e)
def get_prefs(name): string_out = ffi.new('char**') int_out = ffi.new('int*') type = lib.hexchat_get_prefs(lib.ph, name.encode(), string_out, int_out) if type is 0: return None elif type is 1: return __decode(ffi.string(string_out[0])) elif type is 2 or type is 3: # XXX: 3 should be a bool, but keeps API return int_out[0] else: assert False
def get_prefs(name): string_out = ffi.new('char**') int_out = ffi.new('int*') _type = lib.hexchat_get_prefs(lib.ph, name.encode(), string_out, int_out) if _type == 0: return None if _type == 1: return __decode(ffi.string(string_out[0])) if _type in (2, 3): # XXX: 3 should be a bool, but keeps API return int_out[0] raise AssertionError('Out of bounds pref storage')
def _on_plugin_init(plugin_name, plugin_desc, plugin_version, arg, libdir): global hexchat global hexchat_stdout signal.signal(signal.SIGINT, signal.SIG_DFL) plugin_name[0] = PLUGIN_NAME plugin_desc[0] = PLUGIN_DESC plugin_version[0] = PLUGIN_VERSION try: libdir = __decode(ffi.string(libdir)) modpath = os.path.join(libdir, '..', 'python') sys.path.append(os.path.abspath(modpath)) hexchat = importlib.import_module('hexchat') except (UnicodeDecodeError, ImportError) as e: lib.hexchat_print(lib.ph, b'Failed to import module: ' + repr(e).encode()) return 0 hexchat_stdout = Stdout() sys.stdout = hexchat_stdout sys.stderr = hexchat_stdout pydoc.help = pydoc.Helper(HelpEater(), HelpEater()) lib.hexchat_hook_command(lib.ph, b'', 0, lib._on_say_command, ffi.NULL, ffi.NULL) lib.hexchat_hook_command(lib.ph, b'LOAD', 0, lib._on_load_command, ffi.NULL, ffi.NULL) lib.hexchat_hook_command(lib.ph, b'UNLOAD', 0, lib._on_unload_command, ffi.NULL, ffi.NULL) lib.hexchat_hook_command(lib.ph, b'RELOAD', 0, lib._on_reload_command, ffi.NULL, ffi.NULL) lib.hexchat_hook_command( lib.ph, b'PY', 0, lib._on_py_command, b'''Usage: /PY LOAD <filename> UNLOAD <filename|name> RELOAD <filename|name> LIST EXEC <command> CONSOLE ABOUT''', ffi.NULL) lib.hexchat_print(lib.ph, b'Python interface loaded') autoload() return 1
def get_pluginpref(name): name = name.encode() string_out = ffi.new('char[512]') if lib.hexchat_pluginpref_get_str(lib.ph, name, string_out) != 1: return None string = ffi.string(string_out) # This API stores everything as a string so we have to figure out what # its actual type was supposed to be. if len(string) > 12: # Can't be a number return __decode(string) number = lib.hexchat_pluginpref_get_int(lib.ph, name) if number == -1 and string != b'-1': return __decode(string) return number
def _on_plugin_init(plugin_name, plugin_desc, plugin_version, arg, libdir): global hexchat global hexchat_stdout signal.signal(signal.SIGINT, signal.SIG_DFL) plugin_name[0] = PLUGIN_NAME plugin_desc[0] = PLUGIN_DESC plugin_version[0] = PLUGIN_VERSION try: libdir = __decode(ffi.string(libdir)) modpath = os.path.join(libdir, '..', 'python') sys.path.append(os.path.abspath(modpath)) hexchat = importlib.import_module('hexchat') except (UnicodeDecodeError, ImportError) as e: lib.hexchat_print(lib.ph, b'Failed to import module: ' + repr(e).encode()) return 0 hexchat_stdout = Stdout() sys.stdout = hexchat_stdout sys.stderr = hexchat_stdout pydoc.help = pydoc.Helper(HelpEater(), HelpEater()) lib.hexchat_hook_command(lib.ph, b'', 0, lib._on_say_command, ffi.NULL, ffi.NULL) lib.hexchat_hook_command(lib.ph, b'LOAD', 0, lib._on_load_command, ffi.NULL, ffi.NULL) lib.hexchat_hook_command(lib.ph, b'UNLOAD', 0, lib._on_unload_command, ffi.NULL, ffi.NULL) lib.hexchat_hook_command(lib.ph, b'RELOAD', 0, lib._on_reload_command, ffi.NULL, ffi.NULL) lib.hexchat_hook_command(lib.ph, b'PY', 0, lib._on_py_command, b'''Usage: /PY LOAD <filename> UNLOAD <filename|name> RELOAD <filename|name> LIST EXEC <command> CONSOLE ABOUT''', ffi.NULL) lib.hexchat_print(lib.ph, b'Python interface loaded') autoload() return 1
def string_getter(field): string = lib.hexchat_list_str(lib.ph, list_, field) if string != ffi.NULL: return __decode(ffi.string(string)) return ''
def create_wordlist(words): size = wordlist_len(words) return [__decode(ffi.string(words[i])) for i in range(1, size + 1)]
def wordlist_len(words): for i in range(31, 1, -1): if ffi.string(words[i]): return i return 0
def strip(text, length=-1, flags=3): stripped = lib.hexchat_strip(lib.ph, text.encode(), length, flags) ret = __decode(ffi.string(stripped)) lib.hexchat_free(lib.ph, stripped) return ret
def list_pluginpref(): prefs_str = ffi.new('char[4096]') if lib.hexchat_pluginpref_list(lib.ph, prefs_str) == 1: return __decode(ffi.string(prefs_str)).split(',') return []