diff --git a/bridge.pl b/bridge.pl new file mode 100644 index 0000000..6d03592 --- /dev/null +++ b/bridge.pl @@ -0,0 +1,142 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use POE; +use POE::Component::IRC; +use WWW::Telegram::BotAPI; + +# ------------------------------------------------- +# Import secrets +# ------------------------------------------------- +require './.secrets.pm'; + +my $IRC_SERVER = '127.0.0.1'; +my $IRC_PORT = 6667; +my $IRC_NICK = 'Jerry'; +my $IRC_CHANNEL = $Secrets::IRC_CHANNEL; + +my $NICKSERV_PASSWORD = $Secrets::NICKSERV_PASSWORD; + +# ------------------------------------------------- +# Telegram Setup +# ------------------------------------------------- +my $telegram = WWW::Telegram::BotAPI->new( + token => $Secrets::TELEGRAM_TOKEN +); + +my $allowed_user = $Secrets::TELEGRAM_USER_ID; + +# Keep track of last update to avoid duplicates +my $last_update_id = 0; + +# ------------------------------------------------- +# IRC Setup +# ------------------------------------------------- +my $irc = POE::Component::IRC->spawn( + Nick => $IRC_NICK, + Server => $IRC_SERVER, + Port => $IRC_PORT, + Ircname => 'Telegram Bridge Bot', +) or die "Cannot spawn IRC component\n"; + +POE::Session->create( + package_states => [ + main => [ + qw( + _start + irc_001 + irc_public + irc_msg + irc_disconnected + poll_telegram + ) + ], + ], +); + +$poe_kernel->run(); +exit 0; + +# ------------------------------------------------- +# POE Handlers +# ------------------------------------------------- +sub _start { + my ($kernel) = $_[KERNEL]; + + $irc->yield(register => 'all'); + $irc->yield(connect => {}); + + # Poll Telegram every 2 seconds + $kernel->delay(poll_telegram => 2); +} + +sub irc_001 { + # Connected + $irc->yield(join => $IRC_CHANNEL); + $irc->yield(privmsg => 'NickServ' => "IDENTIFY $NICKSERV_PASSWORD"); +} + +sub irc_public { + my ($who, $where, $what) = @_[ARG0, ARG1, ARG2]; + my $nick = (split /!/, $who)[0]; + my $channel = $where->[0]; + + return unless $channel eq $IRC_CHANNEL; + + send_telegram("[$nick] $what"); +} + +sub irc_msg { + my ($who, $what) = @_[ARG0, ARG2]; + my $nick = (split /!/, $who)[0]; + + send_telegram("[PM from $nick] $what"); +} + +sub irc_disconnected { + $irc->yield(connect => {}); +} + +# ------------------------------------------------- +# Telegram Polling +# ------------------------------------------------- +sub poll_telegram { + my ($kernel) = $_[KERNEL]; + + my $updates = eval { $telegram->getUpdates({ offset => $last_update_id }) }; + if ($@) { + warn "Telegram poll failed: $@"; + } elsif ($updates && $updates->{ok}) { + for my $update (@{ $updates->{result} }) { + $last_update_id = $update->{update_id} + 1; + + next unless $update->{message}; + my $msg = $update->{message}; + + # Only allow the specific user + next unless $msg->{from}{id} == $allowed_user; + + my $text = $msg->{text} // ''; + next unless $text; + + $irc->yield(privmsg => $IRC_CHANNEL => $text); + } + } + + $kernel->delay(poll_telegram => 2); +} + +# ------------------------------------------------- +# Send message to Telegram +# ------------------------------------------------- +sub send_telegram { + my ($text) = @_; + eval { + $telegram->sendMessage({ + chat_id => $allowed_user, + text => $text, + }); + }; + warn "Failed to send telegram message: $@" if $@; +}