Last active
June 1, 2022 17:49
-
-
Save Consolatis/1d80ab36f06d19fd14c3d7fa82ee8c30 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import hexchat | |
import subprocess | |
__module_name__ = "StupidNotifier" | |
__module_version__ = "0.8" | |
__module_description__ = "On notification change title via wmctrl." | |
# https://hexchat.readthedocs.io/en/latest/script_python.html#channels | |
# ^ is simply wrong! The actual flags can be found at | |
# https://github.com/hexchat/hexchat/blob/master/src/common/plugin.c#L118 | |
CHANFLAGS_BLINK_TRAY = 1 << 17 | |
CHANFLAGS_BLINK_TASKBAR = 1 << 19 | |
CHANFLAGS_BLINK = CHANFLAGS_BLINK_TRAY | CHANFLAGS_BLINK_TASKBAR | |
# Set to 0 to disable desktop notifications | |
NOTIFY_TIMEOUT = 10000 | |
# Prefix which is looped through on the taskbar | |
TITLE_PREFIX = "..." | |
class StupidNotifier: | |
def __init__(self): | |
self.timer = None | |
self.title_index = 0 | |
self.pipe_path = '/tmp/hexchat_1' | |
self.pipe_icon = '' | |
self.hooks = [ | |
hexchat.hook_print("Channel Action", self.channel_filter), | |
hexchat.hook_print("Channel Message", self.channel_filter), | |
hexchat.hook_print("Channel Notice", self.channel_filter), | |
hexchat.hook_print("Channel Action Hilight", self.notify), | |
hexchat.hook_print("Channel Msg Hilight", self.notify), | |
hexchat.hook_print("Private Action", self.notify), | |
hexchat.hook_print("Private Action to Dialog", self.notify), | |
hexchat.hook_print("Private Message", self.notify), | |
hexchat.hook_print("Private Message to Dialog", self.notify), | |
hexchat.hook_print("Focus Window", self.focus) | |
] | |
hexchat.hook_unload(self.unload) | |
self.pipe_clean() | |
def _get_channel(self, channel): | |
channel = channel.lower() | |
for chan in hexchat.get_list("channels"): | |
if chan.channel.lower() == channel: | |
return chan | |
return None | |
def channel_filter(self, *args): | |
channel_name = hexchat.get_info("channel") | |
channel = self._get_channel(channel_name) | |
if channel and channel.flags & CHANFLAGS_BLINK: | |
self.notify(*args) | |
def notify(self, *args): | |
if hexchat.get_info('win_status') == 'active': | |
# Hexchat currently in focus | |
return | |
self.call_notify_send(*args, timeout=NOTIFY_TIMEOUT) | |
if self.timer: | |
# Already in notify loop | |
return | |
self.timer = hexchat.hook_timer(500, self.timer_triggered, args) | |
def focus(self, *args): | |
if not self.timer: | |
# Not currently in notify loop | |
return | |
hexchat.unhook(self.timer) | |
self.timer = None | |
self.pipe_clean() | |
def unload(self, *args): | |
try: | |
for hook in self.hooks: | |
hexchat.unhook(hook) | |
if self.timer: | |
hexchat.unhook(self.timer) | |
self.timer = None | |
except Exception as e: | |
print(f"Unloading failed: {type(e)}: {e}") | |
def timer_triggered(self, *args): | |
# This is blocking hexchat. but who cares | |
self.pipe_update() | |
self.call_wmctrl() | |
return True | |
def pipe_clean(self): | |
if os.path.exists(self.pipe_path): | |
self.pipe_icon = b'' | |
with open (self.pipe_path, 'wb') as pipe: | |
pipe.write(b'\x00' + b'\x00'.join((self.pipe_icon, b'', b'')) + b'\n') | |
pipe.flush() | |
def pipe_update(self): | |
if os.path.exists(self.pipe_path): | |
self.pipe_icon = b'hexchat' if self.pipe_icon != b'hexchat' else b'dialog-warning' | |
with open (self.pipe_path, 'wb') as pipe: | |
pipe.write(b'\x00' + b'\x00'.join((self.pipe_icon, b'', b'')) + b'\n') | |
pipe.flush() | |
def call_notify_send(self, *args, timeout=3000): | |
if not args or not timeout: | |
return | |
args = args[0] | |
if len(args) < 2: | |
print("call_notify_send has no idea how to parse args[0]:", str(args)) | |
return | |
channel = hexchat.get_info("channel") | |
sender, message = args[:2] | |
if message == channel: | |
# Out of channel Notice | |
message = args[2] | |
where = 'in' if channel.startswith('#') else 'from' | |
notify_args = ( | |
'notify-send', | |
'-i', 'hexchat', | |
'-t', str(timeout), | |
f"New message {where} {channel}", | |
f"\n{sender}: {message}" | |
) | |
subprocess.run(notify_args) | |
def call_wmctrl(self, *args): | |
title = TITLE_PREFIX[:self.title_index] | |
self.title_index = (self.title_index + 1) % (len(TITLE_PREFIX) + 1) | |
args = ( | |
'wmctrl', '-x', '-r', 'hexchat', '-N', f'{title} New Messages' | |
) | |
# -x uses the WM_CLASS instead of title | |
subprocess.run(args) | |
StupidNotifier() | |
print(f"{__module_name__} {__module_version__} started successfully") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment