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.