Sunday, April 28, 2024
10
rated 0 times [  10] [ 0]  / answers: 1 / hits: 5529  / 2 Years ago, wed, june 15, 2022, 7:33:05

I just switched from the Konversation IRC client to the terminal based IRSSI. I'm starting IRSSI on a remote machine using GNU screen + SSH. I do not get any sound notification on new messages, which means that I've to check out IRSSI once in a while for new messages.



That's not really productive, so I'm looking for an application / script that plays a sound (preferably /usr/share/sounds/KDE-Im-Irc-Event.ogg and not the annoying beep) on my machine if there is any activity. It would be great if I can disable the notification for certain channels.



Or, if that's not possible, some sort of notification via libnotify, thus making it available to GNOME and KDE.


More From » notification

 Answers
4

I did not like libnotify, so I created an UDP server in Python and a client application for irssi. Note that this answer applies to the original requirements in revision 1, it does not have text notification.



Client



This version reacts to various messages directed at you. If you would like to be notified of messages in any channel, remove the leading # in the #'message public' line. Some rate-limiting is implemented, there will be at least 1.3 seconds delay between notifications.



##
## Put me in ~/.irssi/scripts, and then execute the following in irssi:
##
## /load perl
## /script load notifyudp
##

use strict;
use Irssi;
use IO::Socket;
use vars qw($VERSION %IRSSI);
use Time::HiRes qw(time);

$VERSION = "0.3.20140930";
%IRSSI = (
authors => 'Lekensteyn',
contact => '[email protected]',
name => 'notifyudp.pl',
description => 'Send a UDP signal to a remote machine',
license => 'GPLv3+'
);

Irssi::settings_add_str('notifyudp', 'notifyudp_ip_addr', '');
# port 0 = disabled
Irssi::settings_add_int('notifyudp', 'notifyudp_port', 0);
Irssi::settings_add_bool('notifyudp', 'notifyudp_auto_start', 0);

my $sock;

sub notify_load {
if ($sock) {
Irssi::print('NotifyUDP: Already connected.');
return;
}
my $ip = Irssi::settings_get_str('notifyudp_ip_addr');
my $port = Irssi::settings_get_int('notifyudp_port');
if (!$port || !$ip) {
Irssi::print('NotifyUDP: No port or host set, /set notifyudp for more information..');
return;
}
if ($port < 1024 || $port > 65535) {
Irssi::print('NotifyUDP: Invalid port, must be 1024 <= port <= 65535, resetting and ignoring.');
Irssi::settings_set_int('notifyudp_port', 0);
return;
}
$sock = new IO::Socket::INET(
PeerAddr => $ip,
PeerPort => $port,
Proto => 'udp',
Timeout => 1
);
Irssi::print("NotifyUDP: IP $ip will be notified on port $port.");
}

my $last_time = 0;
sub notify {
if ($sock) {
my $now = time;
my $notify_delay = 1.3;
if (abs($now - $last_time) > $notify_delay) {
$last_time = $now;
$sock->send("M");
}
}
}
sub notify_if_hilighted {
my ($dest, $text, $stripped) = @_;
if ($dest->{level} & MSGLEVEL_HILIGHT) {
notify();
}
}

sub notify_stop {
if ($sock) {
Irssi::print("NotifyUDP: Stopping.");
$sock->send("S");
$sock = undef;
} else {
Irssi::print("NotifyUDP: not active.");
}
}

sub cmd_notifyudp {
my ($cmd) = @_;
if ($cmd eq 'start') {
notify_load();
} elsif ($cmd eq 'stop') {
notify_stop();
} elsif ($cmd eq 'ping') {
notify();
} else {
Irssi::print('NotifyUDP: Usage: /notifyudp [start|stop|ping]');
}
}

Irssi::command_bind('notifyudp', 'cmd_notifyudp');

my @signals = (
# Uncomment the following to get notifs for every (channel) message
#'message public',
'message private',
'dcc request',

'message irc notice', # NickServ responses and such

# whenever the server dies
'server connected',
'server connect failed',
'server disconnected',

'message invite',
'message topic',
'message dcc',
'ctcp msg',
'ctcp reply',
);
Irssi::signal_add('print text', 'notify_if_hilighted');
foreach (@signals) {
Irssi::signal_add($_, 'notify');
}

if (Irssi::settings_get_bool('notifyudp_auto_start')) {
Irssi::print('NotifyUDP: automatic connection with the sound server is enabled.');
notify_load();
} else {
Irssi::print('NotifyUDP: automatic connection with the sound server is disabled.');
}


Server



When started, it listens on all addresses, port 3533. If it receives a UDP packet "M", it plays /usr/share/sounds/KDE-Im-Irc-Event.ogg using paplay ("PulseAudio play"). On receiving S, it quits the server. Since it's open-source, you are free to remove this.



#!/usr/bin/env python
# udpsoundserver.py

"""Listen on a UDP port and play a sound when 'M' is received

Starts the server listening on UDP port PORT (3533 by default) on address HOST
(by default all addresses). Valid commands are:
M - play Music
S - Stop the server
"""
try:
import socketserver
except ImportError:
import SocketServer as socketserver
from os import system,getpid
import threading
import sys

# leave it empty to listen on all addresses
HOST = ""
PORT = 3533


class UDPSvr(socketserver.BaseRequestHandler):
def handle(self):
data = self.request[0]
if sys.version >= '3':
data = str(data, "ISO-8859-1")
data = data.strip()
if data == "M":
ding.dong()
elif data == "S":
ding.die()

class Worker(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.daemon = True
def run(self):
server.serve_forever();

class Handler(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.daemon = True
self.play = False
self.must_die = False

def run(self):
self.event = threading.Event()
while True:
self.event.wait(1.)
if self.event.isSet():
if self.play:
print("Playing...")
system("paplay /usr/share/sounds/KDE-Im-Irc-Event.ogg")
# no else if to allow shutdown signals
if self.must_die:
print("Shutting down...")
server.shutdown()
break
self.play = False
self.event.clear()

def dong(self):
self.play = True
self.event.set()

def die(self):
self.must_die = True
self.event.set()

def ca(num, x):
print("Caught SIGINT, shutting down...")
ding.die()

import signal
if __name__ == "__main__":
print("My PID is: " + str(getpid()))

if len(sys.argv) > 1:
HOST = sys.argv[1]
if len(sys.argv) > 2:
PORT = int(sys.argv[2])

print("Host: " + HOST)
print("Port: " + str(PORT))
server = socketserver.UDPServer((HOST, PORT), UDPSvr)

ding = Handler()
signal.signal(signal.SIGINT, ca)
worker = Worker()
ding.start()
worker.start()
# might not be the cleanest, but it allows Ctrl + C
while ding.isAlive():
ding.join(3600)


The sequence of starting the remote server becomes:



screen -dm path/to/udpsoundserver.py
ssh -R 5355:localhost:5355


After logging in, I run:



screen -t irssi irssi


Should you need to reconnect later:



screen -r irssi


After starting irssi, you need to set the host and port:



/set notifyudp_ip_addr 127.0.0.1
/set notifyudp_port 5355


To make it connect automatically on startup:



/set notifyudp_auto_start 1


The first time, you need to start Notify UDP manually since it was not auto started yet:



/notifyudp start


In order to test the notification:



/notifyudp ping


To-do:




  • make the soundserver stop on disconnect

  • allow for skipping channels


[#43873] Friday, June 17, 2022, 2 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
arsleyeuth

Total Points: 72
Total Questions: 121
Total Answers: 112

Location: North Korea
Member since Mon, Oct 31, 2022
2 Years ago
;