Soundbenachrichtigung über SSH

12

Ich bin gerade vom Konversation IRC-Client auf das terminalbasierte IRSSI umgestiegen. Ich starte IRSSI auf einem Remote-Computer mit GNU-Bildschirm + SSH. Ich erhalte keine akustische Benachrichtigung bei neuen Nachrichten. Das bedeutet, dass ich ab und zu nach neuen Nachrichten bei IRSSI suchen muss.

Das ist nicht wirklich produktiv, daher suche ich nach einer Anwendung / einem Skript, die / das /usr/share/sounds/KDE-Im-Irc-Event.oggauf meinem Computer einen Ton (vorzugsweise und nicht den nervigen Piepton) ausgibt, wenn Aktivitäten auftreten. Es wäre toll, wenn ich die Benachrichtigung für bestimmte Kanäle deaktivieren könnte.

Oder, falls dies nicht möglich ist, eine Art Benachrichtigung über libnotify, um sie GNOME und KDE zur Verfügung zu stellen.

Lekensteyn
quelle

Antworten:

9

Ich mochte libnotify nicht, also habe ich in Python einen UDP-Server und eine Client-Anwendung für irssi erstellt. Beachten Sie, dass diese Antwort auf die ursprünglichen Anforderungen in Revision 1 zutrifft und keine Textbenachrichtigung enthält.

Klient

Diese Version reagiert auf verschiedene Nachrichten, die an Sie gerichtet sind. Wenn Sie über Nachrichten in einem Kanal benachrichtigt werden möchten, entfernen Sie das führende Zeichen #in der #'message public'Zeile. Einige Ratenbegrenzungen sind implementiert. Zwischen den Benachrichtigungen liegt eine Verzögerung von mindestens 1,3 Sekunden.

##
## 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

Beim Start werden alle Adressen abgehört, Port 3533. Wenn ein UDP-Paket "M" empfangen wird, wird die Wiedergabe /usr/share/sounds/KDE-Im-Irc-Event.oggmit paplay("PulseAudio-Wiedergabe") ausgeführt. Beim Empfang Swird der Server beendet. Da es sich um Open Source handelt, können Sie dieses entfernen.

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

Die Reihenfolge zum Starten des Remote-Servers lautet:

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

Nach dem Einloggen starte ich:

screen -t irssi irssi

Sollten Sie später erneut eine Verbindung herstellen müssen:

screen -r irssi

Nach dem Start irssimüssen Sie den Host und den Port einstellen:

/set notifyudp_ip_addr 127.0.0.1
/set notifyudp_port 5355

So stellen Sie beim Start automatisch eine Verbindung her:

/set notifyudp_auto_start 1

Beim ersten Mal müssen Sie UDP manuell benachrichtigen, da es noch nicht automatisch gestartet wurde:

/notifyudp start

Um die Benachrichtigung zu testen:

/notifyudp ping

Machen:

  • Schalten Sie den Soundserver beim Trennen der Verbindung aus
  • Ermöglichen Sie das Überspringen von Kanälen
Lekensteyn
quelle
Sie sagten, der Textindikator sei keine Voraussetzung - die Formulierung impliziere, dass es nett wäre, sei aber nicht die bevorzugte Option. Ich entschuldige mich für die Bearbeitung, und Sie können es zurücksetzen, wenn Sie möchten.
Juni,
Kein Problem, es ist gut Alternativen zu haben. Meine Lösung ist, wie gesagt, zusammen gehackt, daher ist Ihre Antwort möglicherweise einen Versuch wert.
Lekensteyn
7

Ich mache das mit libnotify. Ich fand diese vor Alter.

Es funktioniert wie ein Champion. Früher habe ich es mit libnotify unter Linux verwendet (und mache es immer noch, wenn ich auf einem Linux-Computer bin), aber die meiste Zeit bin ich jetzt auf einem Macbook, also benutze ich Growl als Ersatz für libnotify auf dem Mac.

# todo: grap topic changes

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

use Irssi;
$VERSION = '0.0.3';
%IRSSI = (
    authors     => 'Thorsten Leemhuis',
    contact     => '[email protected]',
    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

irssiFühren Sie zum Laden Folgendes aus:

/load perl

/script load fnotify

Dann müssen wir es weiterleiten libnotify. Speichern Sie dazu Folgendes als Shell-Skript und führen Sie es bei der Anmeldung aus:

# 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?)
Bill Childers
quelle
Lahme GROWLer. ;) Ich werde mal schauen.
Freitag,
Ich werde das später überprüfen, einen Tag nach der Veröffentlichung dieses QI habe ich ein Perl- und Python-Skript gehackt, das ich damals verwendet habe.
Lekensteyn