root/lang/perl/App-MadEye/trunk/lib/App/MadEye/Plugin/Notify/XMPP.pm @ 14999

Revision 14999, 4.4 kB (checked in by tokuhirom, 5 years ago)

hm. should not depend to this module.

Line 
1package App::MadEye::Plugin::Notify::XMPP;
2use strict;
3use warnings;
4use base qw/App::MadEye::Plugin::Base/;
5use Text::Truncate qw/truncstr/;
6use Net::XMPP;
7use Carp;
8use Data::Dumper;
9use Encode;
10use XML::Stream;
11
12sub notify : Hook {
13    my ( $self, $context, $args ) = @_;
14
15    my $config = $self->config->{config};
16
17    my ( $username, $componentname ) = split /@/, $config->{jid};
18    $config->{host} ||= $componentname;
19    my $client = Net::XMPP::Client->new( debuglevel => 2 );
20    my $connectattempts = 3;
21    my $connectsleep    = 1;
22    my ($status, $error);
23    while (--$connectattempts >= 0) {
24        $status = $client->Connect(
25            hostname       => $config->{host},
26            port           => $config->{port} || 5222,
27            tls            => $config->{tls}  || 0,
28            componentname  => $componentname,
29            connectiontype => 'http',
30        );
31        last if defined $status;
32        sleep $connectsleep;
33    }
34    unless (defined $status) {
35        carp "[FATAL] failed to connect ".join(':',$config->{host}, $config->{port}) . ' : ' . $client->GetErrorCode->{text};
36        return;
37    }
38
39    {
40
41        # quick hack to connect Google Talk
42        # override XML::Stream-1.22 by hirose31++
43        no warnings 'redefine';
44        *XML::Stream::SASLClient = sub {
45            my $self     = shift;
46            my $sid      = shift;
47            my $username = shift;
48            my $password = shift;
49
50            my $mechanisms = $self->GetStreamFeature( $sid, "xmpp-sasl" );
51
52            return unless defined($mechanisms);
53
54            my $sasl = new Authen::SASL(
55                mechanism => join( " ", @{$mechanisms} ),
56                callback  => {
57                    authname => $username . "@"
58                      . (
59                             $self->{SIDS}->{$sid}->{to}
60                          or $self->{SIDS}->{$sid}->{hostname}
61                      ),
62                    user => $username,
63                    pass => $password
64                }
65            );
66
67            $self->{SIDS}->{$sid}->{sasl}->{client}   = $sasl->client_new();
68            $self->{SIDS}->{$sid}->{sasl}->{username} = $username;
69            $self->{SIDS}->{$sid}->{sasl}->{password} = $password;
70            $self->{SIDS}->{$sid}->{sasl}->{authed}   = 0;
71            $self->{SIDS}->{$sid}->{sasl}->{done}     = 0;
72
73            $self->SASLAuth($sid);
74        };
75    }
76
77    ( $status, $error ) = $client->AuthSend(
78        username => $username,
79        password => $config->{password},
80        resource => 'MadEye',
81    );
82    unless ( $status and $status eq 'ok' ) {
83        carp "[FATAL] authentication failure : $username, $status, $error";
84        return;
85    }
86
87    for my $to (@{ $config->{recipients} }) {
88        $client->MessageSend(
89            to   => $to,
90            body => encode('utf-8', _format( $args, $config->{cutoff_length} )),
91        );
92    }
93
94    $client->Disconnect();
95}
96
97sub _format {
98    my ( $args, $cutoff_length ) = @_;
99
100    my $text = '';
101    while ( my ( $module, $targets ) = each %$args ) {
102        $module = _moniker($module);
103        $text .= "= $module\n"
104          . truncstr( _format_target($targets), $cutoff_length ) . "\n";
105    }
106    $text;
107}
108
109sub _format_target {
110    my $targets = shift;
111
112    my $text = '';
113    for my $target (@$targets) {
114        $text .= "- $target->{target}\n";
115        $text .= "$target->{message}\n";
116    }
117    $text;
118}
119
120sub _moniker {
121    my $module = shift;
122    $module =~ s/.+:://;
123    $module;
124}
125
1261;
127__END__
128
129=head1 NAME
130
131App::MadEye::Plugin::Notify::XMPP - notify with XMPP
132
133=head1 SYNOPSIS
134
135  - module: Notify::XMPP
136    config:
137      jid: example@gmail.com
138      password: YOUR PASSWORD
139      host: talk.google.com
140      cutoff_length: 1000
141      tls: 1
142      recipients:
143        - example@gmail.com
144
145=head1 SCHEMA
146
147    type: map
148    mapping:
149        port:
150            type: int
151            required: no
152        jid:
153            type: str
154            required: yes
155        password:
156            required: yes
157            type: str
158        host:
159            required: no
160            type: str
161        cutoff_length:
162            required: yes
163            type: int
164        recipients:
165            type: any
166            required: yes
167        tls:
168            type: int
169            required: no
170
171=head1 AUTHOR
172
173Tokuhiro Matsuno
174
175=head1 THANKS TO
176
177hirose31++ # a lot of code stallen from http://d.hatena.ne.jp/hirose31/20060817/1155821365
178
179=head1 SEE ALSO
180
181L<App::MadEye>, L<Net::XMPP>
182
Note: See TracBrowser for help on using the browser.