Notifica sonora su SSH


12

Sono appena passato dal client Konversation IRC al terminale IRSSI. Sto avviando IRSSI su una macchina remota usando lo schermo GNU + SSH. Non ricevo alcuna notifica sonora sui nuovi messaggi, il che significa che devo controllare IRSSI di tanto in tanto per i nuovi messaggi.

Non è molto produttivo, quindi sto cercando un'applicazione / script che riproduca un suono (preferibilmente /usr/share/sounds/KDE-Im-Irc-Event.ogge non il fastidioso bip) sulla mia macchina se c'è qualche attività. Sarebbe bello se posso disabilitare la notifica per determinati canali.

Oppure, se ciò non è possibile, una sorta di notifica tramite libnotify, rendendola così disponibile per GNOME e KDE.

Risposte:


9

Non mi piaceva libnotify, quindi ho creato un server UDP in Python e un'applicazione client per irssi. Si noti che questa risposta si applica ai requisiti originali nella revisione 1 , non ha una notifica di testo.

Cliente

Questa versione risponde a vari messaggi indirizzati a te. Se desideri ricevere una notifica dei messaggi in qualsiasi canale, rimuovi il primo #nella #'message public'riga. È stata implementata una limitazione della velocità, ci saranno almeno 1,3 secondi di ritardo tra le notifiche.

##
## 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     => 'lekensteyn@gmail.com',
    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

Quando avviato, è in ascolto su tutti gli indirizzi, porta 3533. Se riceve un pacchetto UDP "M", riproduce /usr/share/sounds/KDE-Im-Irc-Event.oggusando paplay("Riproduzione PulseAudio"). Alla ricezione S, chiude il server. Dal momento che è open-source, sei libero di rimuoverlo.

#!/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)

La sequenza di avvio del server remoto diventa:

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

Dopo aver effettuato l'accesso, corro:

screen -t irssi irssi

Dovresti riconnetterti in seguito:

screen -r irssi

Dopo l'avvio irssi, è necessario impostare l'host e la porta:

/set notifyudp_ip_addr 127.0.0.1
/set notifyudp_port 5355

Per collegarlo automaticamente all'avvio:

/set notifyudp_auto_start 1

La prima volta, è necessario avviare Notifica UDP manualmente poiché non è stato ancora avviato automaticamente:

/notifyudp start

Per testare la notifica:

/notifyudp ping

Fare:

  • far arrestare il SoundServer alla disconnessione
  • consentire di saltare i canali

Hai detto che l'indicatore di testo non era un requisito: il fraseggio implicava che sarebbe stato bello, ma non era l'opzione preferita. Mi scuso per la modifica e puoi ripristinarla se vuoi.
jrg

Nessun problema, è bene avere alternative. La mia soluzione è come ho detto hackerato insieme, quindi la tua risposta potrebbe valere la pena provare.
Lekensteyn,

7

Lo faccio con libnotify. Ho trovato questo secoli fa.

Funziona come un campione. Lo usavo con libnotify su Linux (e lo faccio ancora quando sono su una macchina Linux) ma la maggior parte delle volte sono su un macbook ora, quindi uso growl come sostituto di libnotify su Mac.

# todo: grap topic changes

use strict;
use vars qw($VERSION %IRSSI);

use Irssi;
$VERSION = '0.0.3';
%IRSSI = (
    authors     => 'Thorsten Leemhuis',
    contact     => 'fedora@leemhuis.info',
    name        => 'fnotify',
    description => 'Write a notification to a file that shows who is talking to you in which channel.',
    url         => 'http://www.leemhuis.info/files/fnotify/',
    license     => 'GNU General Public License',
    changed     => '$Date: 2007-01-13 12:00:00 +0100 (Sat, 13 Jan 2007) $'
);

#--------------------------------------------------------------------
# In parts based on knotify.pl 0.1.1 by Hugo Haas
# http://larve.net/people/hugo/2005/01/knotify.pl
# which is based on osd.pl 0.3.3 by Jeroen Coekaerts, Koenraad Heijlen
# http://www.irssi.org/scripts/scripts/osd.pl
#
# Other parts based on notify.pl from Luke Macken
# http://fedora.feedjack.org/user/918/
#
#--------------------------------------------------------------------

#--------------------------------------------------------------------
# Private message parsing
#--------------------------------------------------------------------

sub priv_msg {
    my ($server,$msg,$nick,$address,$target) = @_;
    filewrite($nick." " .$msg );
}

#--------------------------------------------------------------------
# Printing hilight's
#--------------------------------------------------------------------

sub hilight {
    my ($dest, $text, $stripped) = @_;
    if ($dest->{level} & MSGLEVEL_HILIGHT) {
    filewrite($dest->{target}. " " .$stripped );
    }
}

#--------------------------------------------------------------------
# The actual printing
#--------------------------------------------------------------------

sub filewrite {
    my ($text) = @_;
    # FIXME: there is probably a better way to get the irssi-dir...
        open(FILE,">>$ENV{HOME}/.irssi/fnotify");
    print FILE $text . "\n";
        close (FILE);
}

#--------------------------------------------------------------------
# Irssi::signal_add_last / Irssi::command_bind
#--------------------------------------------------------------------

Irssi::signal_add_last("message private", "priv_msg");
Irssi::signal_add_last("print text", "hilight");

#- end

Per caricarlo irssi, eseguire quanto segue:

/load perl

/script load fnotify

Quindi, dobbiamo indirizzarlo a libnotify. Per fare ciò, salva quanto segue come script di shell ed eseguilo al login:

# yes, we need a way to flush the file on disconnect; i don't know one
# yes, that's flush is not atomic (but good enough for me)
ssh remote.system.somewhere "tail -n 10 .irssi/fnotify ; : > .irssi/fnotify ; tail -f .irssi/fnotify " | sed -u 's/[<@&]//g' | while read heading message  do  notify-send -i gtk-dialog-info -t 300000 -- "${heading}" "${message}"; done # the sed -u 's/[<@&]//g' is needed as those characters might confuse  notify-send (FIXME: is that a bug or a feature?)

Lame GROWLer. ;) Darò un'occhiata.
giovedì

Lo controllerò più tardi, un giorno dopo aver pubblicato questo QI, ho hackerato uno script perl e python insieme che ho usato allora.
Lekensteyn,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.