SSH를 통한 소리 알림


12

Konversation IRC 클라이언트에서 터미널 기반 IRSSI로 전환했습니다. GNU screen + SSH를 사용하여 원격 시스템에서 IRSSI를 시작하고 있습니다. 새 메시지에 대한 알림이 들리지 않아서 새 메시지에 대해 가끔 IRSSI를 확인해야합니다.

그것은 실제로 생산적 /usr/share/sounds/KDE-Im-Irc-Event.ogg이지 않으므로 활동이있는 경우 내 컴퓨터 에서 소리 (바람직하게 는 경고음이 아닌) 를 재생하는 응용 프로그램 / 스크립트를 찾고 있습니다. 특정 채널에 대해 알림을 비활성화 할 수 있다면 좋을 것입니다.

또는 가능하지 않은 경우을 통해 일종의 알림 libnotify을 보내서 그놈 및 KDE에서 사용할 수있게합니다.

답변:


9

libnotify가 마음에 들지 않아서 파이썬으로 UDP 서버를 만들고 irssi를위한 클라이언트 응용 프로그램을 만들었습니다. 이 답변은 개정판 1 의 원래 요구 사항에 적용되며 문자 알림이 없습니다.

고객

이 버전은 사용자를 향한 다양한 메시지에 반응합니다. 임의의 채널에서 메시지에 대한 알림을 받으려면 행 에서 선행 #을 제거하십시오 #'message public'. 일부 속도 제한이 구현되며 알림간에 최소 1.3 초의 지연이 발생합니다.

##
## 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.');
}

섬기는 사람

시작되면 모든 주소에서 포트 3533을 수신합니다. UDP 패킷 "M"을 수신하면 ( "PulseAudio play")를 /usr/share/sounds/KDE-Im-Irc-Event.ogg사용하여 paplay재생합니다. 수신 S하면 서버를 종료합니다. 오픈 소스이기 때문에 자유롭게 제거 할 수 있습니다.

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

원격 서버 시작 순서는 다음과 같습니다.

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

로그인 후 다음을 실행합니다.

screen -t irssi irssi

나중에 다시 연결해야 할 경우 :

screen -r irssi

시작 후 irssi호스트와 포트를 설정해야합니다.

/set notifyudp_ip_addr 127.0.0.1
/set notifyudp_port 5355

시작시 자동 연결되도록하려면 :

/set notifyudp_auto_start 1

처음에는 UDP가 아직 자동 시작되지 않았기 때문에 Notify UDP를 수동으로 시작해야합니다.

/notifyudp start

알림을 테스트하려면 다음을 수행하십시오.

/notifyudp ping

할 것:

  • 사운드 서버 연결을 끊을 때 중지
  • 채널 건너 뛰기 허용

당신은 텍스트 인디케이터가 요구 사항은 아니라고 말했는데, 그 문구는 그것이 좋을 것이라고 암시했지만, 선호되는 옵션은 아니 었습니다. 수정에 대해 사과 드리며 원할 경우 롤백 할 수 있습니다.
jrg

문제 없습니다. 대안이있는 것이 좋습니다. 내 해결책은 내가 해킹했다고 말 했으므로 귀하의 답변을 시도해 볼 가치가 있습니다.
Lekensteyn

7

나는 libnotify로 이것을한다. 나는 나이 전에 그것을 발견 했다.

챔피언처럼 작동합니다. 나는 리눅스에서 libnotify와 함께 사용했지만 (여전히 Linux 컴퓨터를 사용하는 경우에도 마찬가지이지만) 지금은 대부분 맥북을 사용하고 있으므로 mac에서 libnotify를 대신하여 growl을 사용합니다.

# 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

에로드하려면 irssi다음을 실행하십시오.

/load perl

/script load fnotify

그런 다음로 라우팅해야 libnotify합니다. 그렇게하려면 다음을 쉘 스크립트로 저장하고 로그인시 실행하십시오.

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

레임 GROWLer. ;) 내가 볼게요.
jrg

나는이 Q를 게시 한 날 후에 나중에 이것을 확인할 것입니다. 나는 내가 사용했던 perl과 python 스크립트를 함께 해킹했습니다.
Lekensteyn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.