| 1 | #!/usr/bin/perl |
|---|
| 2 | |
|---|
| 3 | use strict; |
|---|
| 4 | use vars qw($VERSION %IRSSI); |
|---|
| 5 | use Irssi; |
|---|
| 6 | use Irssi::Irc; |
|---|
| 7 | use XML::RSS::Parser; |
|---|
| 8 | use LWP::UserAgent; |
|---|
| 9 | |
|---|
| 10 | $VERSION = '1.00'; |
|---|
| 11 | %IRSSI = ( |
|---|
| 12 | authors => 'jenk', |
|---|
| 13 | contact => 'irc.hardchats.com', |
|---|
| 14 | name => 'hp_rimming', |
|---|
| 15 | description => qq { |
|---|
| 16 | This bot will provide a channel with timely updates |
|---|
| 17 | of http://hp_rimming.livejournal.com |
|---|
| 18 | }, |
|---|
| 19 | license => 'BPL', |
|---|
| 20 | ); |
|---|
| 21 | |
|---|
| 22 | my $INTERVAL = 5; |
|---|
| 23 | my $MIN_ENTRY_LEN = 5_000; |
|---|
| 24 | my $done = 0; |
|---|
| 25 | my @entries; |
|---|
| 26 | my $win; |
|---|
| 27 | my $last_entry = ''; |
|---|
| 28 | |
|---|
| 29 | Irssi::command_bind('hp_latest' => \&hp_latest); |
|---|
| 30 | Irssi::command_bind('hp_done' => \&hp_done); |
|---|
| 31 | Irssi::command_bind('hp_start' => \&hp_start); |
|---|
| 32 | |
|---|
| 33 | sub main_loop { |
|---|
| 34 | while (! $done) { |
|---|
| 35 | sleep $INTERVAL; |
|---|
| 36 | last if $done; |
|---|
| 37 | |
|---|
| 38 | next unless $win; |
|---|
| 39 | |
|---|
| 40 | } |
|---|
| 41 | |
|---|
| 42 | $win->print(MSGLEVEL_CRAP, 'hp_rimming finished') if $win; |
|---|
| 43 | exit; |
|---|
| 44 | } |
|---|
| 45 | |
|---|
| 46 | sub hp_start { |
|---|
| 47 | my ($data, $server, $witem) = @_; |
|---|
| 48 | $win = $witem; |
|---|
| 49 | $win->print(MSGLEVEL_CRAP, "Starting hp_rimming bot"); |
|---|
| 50 | $win->command("MSG #rimming hi"); |
|---|
| 51 | $win->command("MSG #rimming hi"); |
|---|
| 52 | #main_loop(); |
|---|
| 53 | } |
|---|
| 54 | |
|---|
| 55 | sub hp_latest { |
|---|
| 56 | my ($data, $server, $witem) = @_; |
|---|
| 57 | |
|---|
| 58 | $data += 0; |
|---|
| 59 | |
|---|
| 60 | my $entry = fetch_entry($data); |
|---|
| 61 | return unless $entry; |
|---|
| 62 | $last_entry = $entry; |
|---|
| 63 | |
|---|
| 64 | if (! $witem || ! $witem->{name}) { |
|---|
| 65 | print "Invalid window"; |
|---|
| 66 | return; |
|---|
| 67 | } |
|---|
| 68 | |
|---|
| 69 | say_entry($witem->{name}, $entry); |
|---|
| 70 | } |
|---|
| 71 | |
|---|
| 72 | sub say_entry { |
|---|
| 73 | my ($where, $entry) = @_; |
|---|
| 74 | |
|---|
| 75 | my $win = Irssi::active_win(); |
|---|
| 76 | |
|---|
| 77 | my @lines = split("\n", $entry); |
|---|
| 78 | foreach my $line (@lines) { |
|---|
| 79 | chomp $line; |
|---|
| 80 | #$entry =~ s/(['"])/\\$1/g; |
|---|
| 81 | $win->command("MSG $where $line"); |
|---|
| 82 | } |
|---|
| 83 | } |
|---|
| 84 | |
|---|
| 85 | sub hp_done { |
|---|
| 86 | $done = 1; |
|---|
| 87 | } |
|---|
| 88 | |
|---|
| 89 | sub fetch_entry { |
|---|
| 90 | my $num = shift; |
|---|
| 91 | |
|---|
| 92 | my @entries = fetch_entries(); |
|---|
| 93 | |
|---|
| 94 | $num = @entries - 1 if $num >= @entries; |
|---|
| 95 | my $entry = $num ? $entries[$num] : shift @entries; |
|---|
| 96 | |
|---|
| 97 | return $entry; |
|---|
| 98 | } |
|---|
| 99 | |
|---|
| 100 | sub fetch_entries { |
|---|
| 101 | my $use_timingbot = shift; |
|---|
| 102 | |
|---|
| 103 | my $bot; |
|---|
| 104 | |
|---|
| 105 | if ($use_timingbot) { |
|---|
| 106 | require 'XML::RSS::TimingBot'; |
|---|
| 107 | $bot = XML::RSS::TimingBot->new; |
|---|
| 108 | } else { |
|---|
| 109 | $bot = LWP::UserAgent->new; |
|---|
| 110 | } |
|---|
| 111 | |
|---|
| 112 | my $win = Irssi::active_win(); |
|---|
| 113 | |
|---|
| 114 | # get latest posts |
|---|
| 115 | my $url = 'http://community.livejournal.com/hp_rimming/data/rss'; |
|---|
| 116 | $win->print("Fetching latest post..."); |
|---|
| 117 | my $response = $bot->get($url); |
|---|
| 118 | |
|---|
| 119 | if ($response->code == 304) { |
|---|
| 120 | # hasn't changed since last access |
|---|
| 121 | $win->print("No new posts"); |
|---|
| 122 | return; |
|---|
| 123 | } elsif ($response->code != 200) { |
|---|
| 124 | $win->print("Bad response getting $url: " . $response->status_line); |
|---|
| 125 | return; |
|---|
| 126 | } |
|---|
| 127 | |
|---|
| 128 | # save infoz |
|---|
| 129 | $bot->commit if ref $bot =~ /XML::RSS::TimingBot/; |
|---|
| 130 | |
|---|
| 131 | # parse latest posts |
|---|
| 132 | my @entries; |
|---|
| 133 | |
|---|
| 134 | my $p = XML::RSS::Parser->new; |
|---|
| 135 | my $feed = $p->parse_string($response->content); |
|---|
| 136 | |
|---|
| 137 | unless ($feed) { |
|---|
| 138 | $win->print("Error: could not parse feed"); |
|---|
| 139 | return (); |
|---|
| 140 | } |
|---|
| 141 | |
|---|
| 142 | # get item count |
|---|
| 143 | my $count = $feed->item_count; |
|---|
| 144 | print "Latest post count: ($count)\n"; |
|---|
| 145 | |
|---|
| 146 | # parse items |
|---|
| 147 | foreach my $i ( $feed->query('//item') ) { |
|---|
| 148 | my $entry_ele = $i->query('description'); |
|---|
| 149 | next unless $entry_ele; |
|---|
| 150 | my $entry = $entry_ele->text_content; |
|---|
| 151 | next unless $entry; |
|---|
| 152 | |
|---|
| 153 | # clean up entry |
|---|
| 154 | # strip html |
|---|
| 155 | $entry =~ s!<br\s*/?>!\n!g; |
|---|
| 156 | $entry =~ s/\<([^\<])+\>//g; |
|---|
| 157 | $entry =~ s/ / /gi; |
|---|
| 158 | $entry =~ s!</lj-cut<!!ig; |
|---|
| 159 | |
|---|
| 160 | next unless $entry && length $entry > $MIN_ENTRY_LEN; |
|---|
| 161 | |
|---|
| 162 | push @entries, $entry; |
|---|
| 163 | } |
|---|
| 164 | |
|---|
| 165 | return @entries; |
|---|
| 166 | } |
|---|