forked from hacktor/Bridge
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsignalpoller
executable file
·189 lines (166 loc) · 7.37 KB
/
signalpoller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#!/usr/bin/perl -w
#
# Signal Poller for Hermod Gateway Bot.
#
# Keeping a tail on the tosignal file for messages to send to signal.
# Polling the signal group for new messages. These are send to telegram
# and irc
#
# 2019, Ruben de Groot
use strict;
use JSON;
use HTTP::Tiny;
use HTTP::Request::Common;
use LWP::UserAgent;
use URI::Escape;
use Text::Unidecode;
use DBI;
open my $fh, '<', "/etc/hermod.json" or die "error opening configuration $!";
my $cfg = decode_json do { local $/; <$fh> };
$cfg->{nicks} = getalias($cfg);
open my $tail, "<", $cfg->{signal}->{infile} or die @_;
my $inode = (stat($cfg->{signal}->{infile}))[1];
open my $debug, ">>", $cfg->{signal}->{debug} if defined $cfg->{signal}->{debug};
# SEEK_END
seek($tail, 0, 2) or die @_;
# tailing signal infile and telegram downloads for stuff to send
for (;;) {
sleep 1; # not to get too tight loop
# check if logfiles haven't turned over below our feet
if ($inode != (stat($cfg->{signal}->{infile}))[1]) {
close $tail;
$inode = (stat($cfg->{signal}->{infile}))[1];
open($tail,$cfg->{signal}->{infile}) or next;
} else {
# SEEK_CUR
seek($tail, 0, 1);
}
# send new messages to signal group
my $telsend ='';
while (my $line = <$tail>) {
if ($line =~ /^FILE:/) {
# send photo's, documents
$line = substr $line,5;
my ($file,$caption) = split / /, $line, 2;
qx( $cfg->{signal}->{cli} -u $cfg->{signal}->{phone} send -g $cfg->{signal}->{gid} -m "$caption" -a $cfg->{telegram}->{attachments}/$file );
} else {
$telsend .= $line."\n";
}
}
if ($telsend) {
open my $sc, "|-", $cfg->{signal}->{cli}, "-u", $cfg->{signal}->{phone}, "send", "-g", $cfg->{signal}->{gid};
print $sc $telsend;
close $sc;
}
# now poll the signal group for new messages
my $json = JSON->new->allow_nonref;
my @lines = qx( $cfg->{signal}->{cli} -u $cfg->{signal}->{phone} receive --json );
for my $line (@lines) {
print $debug $line if defined $cfg->{signal}->{debug};
print $line; chomp $line;
my $sigmsg = $json->decode($line);
next unless defined $sigmsg->{envelope}->{dataMessage};
$sigmsg = $sigmsg->{envelope};
my $datamsg = $sigmsg->{dataMessage};
my $sender = (defined $sigmsg->{source}) ? $sigmsg->{source} : "";
my $group = (defined $datamsg->{groupInfo}->{groupId}) ? $datamsg->{groupInfo}->{groupId} : "";
my $text = (defined $datamsg->{message}) ? $datamsg->{message} : "";
my $attach = (defined $datamsg->{attachments}) ? $datamsg->{attachments} : undef;
# anonymize sender telephone
my $anonsender = $sender;
if (defined $cfg->{nicks}->{$sender}) {
$anonsender = $cfg->{nicks}->{$sender};
} else {
$anonsender =~ s/.*(\d\d\d\d)$/Piraat-$1/;
nickhelp($cfg,$sender,$anonsender);
setalias($cfg,$sender,$anonsender);
}
# check for setnick command
if ($text =~ /^!setnick/) {
(my $nick = $text) =~ s/^!setnick ([\w]+).*$/$1/;
if ($nick) {
setalias($cfg,$sender,$nick);
$cfg->{nicks}->{$sender} = $nick;
$text = "$anonsender is now known as $nick\n";
# notify all chats
open my $w, ">>", $cfg->{signal}->{infile} or die "Died opening file $cfg->{signal}->{infile}";
print $w "$text";
close $w;
open $w, ">>", $cfg->{irc}->{infile} or die "Died opening irc infile $cfg->{signal}->{file}";
print $w "[Sg] $text";
close $w;
my $URL = "https://api.telegram.org/bot$cfg->{telegram}->{token}/sendMessage?chat_id=$cfg->{telegram}->{chat_id}&text=";
my $telmsg = uri_escape_utf8("[Sg] $text");
my $response = HTTP::Tiny->new->get( "$URL$telmsg" );
print "$response->{status} $response->{reason}\n";
next;
}
}
# only relay group messages with contents
next unless $group eq $cfg->{signal}->{gid};
next unless $text or $attach;
# relay to telegram
my $telmsg;
my $URL = "https://api.telegram.org/bot$cfg->{telegram}->{token}/sendMessage?chat_id=$cfg->{telegram}->{chat_id}&text=";
eval { $telmsg = uri_escape("[Sg] $anonsender: $text"); };
$telmsg = uri_escape_utf8("[Sg] $anonsender: $text") if $@;
my $response = HTTP::Tiny->new->get( "$URL$telmsg" );
print "$response->{status} $response->{reason}\n";
# relay to IRC
#$text = unidecode($text);
my @lines = split /\n/, $text;
open my $w, ">>", $cfg->{irc}->{infile} or die "Died opening irc infile $cfg->{irc}->{infile}";
foreach my $line (@lines) {
print $w "[Sg] $anonsender: $line\n" if $line;
}
close $w;
# relay optional attachments
foreach my $att (@$attach) {
(my $ext = $att->{contentType}) =~ s#.*/##;
my ($msg, $URL, $type);
my $ua = LWP::UserAgent->new;
rename "$cfg->{signal}->{attachments}/$att->{id}", "$cfg->{signal}->{attachments}/$att->{id}.$ext";
if ($att->{contentType} =~ /image/) {
$URL = "https://api.telegram.org/bot$cfg->{telegram}->{token}/sendPhoto";
$type = 'photo';
$msg = "[Sg] **$anonsender sends an image: $cfg->{signal}->{url}/$att->{id}.$ext\n";
} else {
$URL = "https://api.telegram.org/bot$cfg->{telegram}->{token}/sendDocument";
$type = 'document';
$msg = "[Sg] **$anonsender sends a document: $cfg->{signal}->{url}/$att->{id}.$ext\n";
}
$ua->post($URL, Content_Type => 'form-data',
Content => { $type => ["$cfg->{signal}->{attachments}/$att->{id}.$ext"],
chat_id => $cfg->{telegram}->{chat_id},
caption => "[Sg $ext $type send by $anonsender]"},);
open $w, ">>", $cfg->{irc}->{infile} or die "Died opening irc infile $cfg->{irc}->{infile}";
print $w $msg;
close $w;
}
close $w;
}
}
sub getalias {
my $cfg = shift;
my $alias;
my $dbh = DBI->connect("dbi:SQLite:dbname=$cfg->{signal}->{db}", "", "", { RaiseError => 1 }, ) or die $DBI::errstr;
my $obj = $dbh->prepare("select * from alias");
$obj->execute() or die $DBI::errstr;
while (my $row = $obj->fetchrow_hashref()) {
$alias->{$row->{phone}} = $row->{nick};
}
return $alias;
}
sub setalias {
my ($cfg,$phone,$nick) = @_;
my $dbh = DBI->connect("dbi:SQLite:dbname=$cfg->{signal}->{db}", "", "", { RaiseError => 1 }, ) or die $DBI::errstr;
$dbh->do("insert or replace into alias (phone,nick) values (?,?)", undef, $phone, $nick) or die $DBI::errstr;
$dbh->disconnect();
}
sub nickhelp {
my ($cfg,$phone,$nick) = @_;
my $text = 'You do not have a nickname set. You are now known as '.$nick;
$text .= '. To change this, simply type !setnick yournickname on a new line in the group or in a private message to me.';
my $out = qx( $cfg->{signal}->{cli} -u $cfg->{signal}->{phone} send -m "$text" $phone );
print $debug $out if defined $cfg->{signal}->{debug};
}