# iDonkey for mldonkey
#
## by Stefan Tomanek
#
use strict;
use vars qw($VERSION %IRSSI);
$VERSION = "2004051601";
%IRSSI = (
authors => "Stefan 'tommie' Tomanek",
contact => "stefan\@pico.ruhr.de",
name => "iDonkey",
description => "equips Irssi with an interface to mldonkey",
license => "GPLv2",
changed => "$VERSION",
modules => "IO::Socket::INET Data::Dumper LWP::UserAgent HTML::Entities",
sbitems => "idonkey",
commands => "idonkey"
);
use Irssi 20020324;
use Irssi::TextUI;
use IO::Socket::INET;
use LWP::UserAgent;
use HTML::Entities;
use Data::Dumper;
use POSIX;
use vars qw($forked $timer $timer2 $index %downloads $nresults $seen $credits $noul %edlinks $expected);
sub show_help() {
my $help = $IRSSI{name}." $VERSION
/idonkey (downloads)
List your current downloads
/idonkey launch
Start a new mldonkey process
/idonkey quit
Quit the mldonkey
/idonkey servers (connected)
List connected servers
/idonkey servers all
List all servers
/idonkey servers connect
/) {
#print "FOO";
my $new = { date => $2, id => $1, title => $3, category => $4 };
push @releases, $new;
}
}
return \@releases;
}
sub sharereactor_search ($) {
my ($query) = @_;
my $enc_query = HTML::Entities::encode($query);
my $ua = LWP::UserAgent->new(env_proxy => 1,
keep_alive => 1,
timeout => 30);
my $response = $ua->get('http://www.sharereactor.com/search.php?search='.$enc_query.'&category=0');
return unless $response->is_success();
my @results;
foreach (split /\n/, $response->content()) {
if (/(.*?)<\/a>/) {
push @results, { name => $2, id => $1 };
my $ua2 = LWP::UserAgent->new(env_proxy => 1,
keep_alive => 1,
timeout => 30);
my $response2 = $ua2->get('http://www.sharereactor.com/downloadrelease.php?id='.$1);
foreach (split /\n/, $response2->content()) {
if (/"(ed2k:\/\/\|file\|.*?\|\d+\|.*?\|)";/) {
push @{ $results[-1]->{files} }, $1;
}
}
} elsif (/(.*?)<\/a>/) {
$results[-1]->{category} = $1;
}
}
#print $_->{name}." ".$_->{id}."\n" foreach @results;
return \@results;
}
sub bittorrent_search ($) {
my ($query) = @_;
my $enc_query = HTML::Entities::encode($query);
my $ua = LWP::UserAgent->new(env_proxy => 1,
keep_alive => 1,
timeout => 30);
my $response = $ua->get('http://www.bytemonsoon.com/?search='.$enc_query.'&cat=0&incldead=0');
return unless $response->is_success();
my @results;
foreach (split /\n/, $response->content()) {
if (/^(.*?)<\/b><\/a><\/td>$/) {
push @results, { name => $2, id => $1 };
} elsif (/^ torrent<\/a><\/td>$/) {
$results[-1]->{torrent} = "http://www.bytemonsoon.com/$1";
}
}
return \@results
}
sub get_ovstats {
my $sock = donkey_connect();
return unless $sock;
$sock->print("ovstats\n");
my $result;
$result->{nodes} = [];
while ($_ = $sock->getline()) {
if (/^ +(\d+\.\d+\.\d+.\d+:\d+)$/) {
push @{ $result->{nodes} }, $1;
} elsif (/^ Search hits: (\d+)$/) {
$result->{search_hits} = $1;
} elsif (/^ Source hits: (\d+)$/) {
$result->{source_hits} = $1;
} elsif (/^$/) {
last;
}
}
return $result;
}
sub is_fake ($) {
my ($hash) = @_;
my $ua = LWP::UserAgent->new(env_proxy => 1,
keep_alive => 1,
timeout => 30);
my $url = 'http://edonkeyfakes.ath.cx/fakecheck/update/fakecheck.php';
my %form = ( hash => $hash );
my $response = $ua->post($url, \%form);
return unless $response->is_success();
return not ($response->content() =~ /Your query didn't match anything in our fakedatabase\!/);
}
sub get_settings ($) {
my ($regexp) = @_;
my $sock = donkey_connect();
return unless $sock;
$sock->print("voo\n");
my $result = {};
while ($_ = $sock->getline()) {
if (/^(.*?) = (.*?)$/) {
my ($key, $val) = ($1, $2);
#print "<".$regexp.">";
next unless ($key =~ /$regexp/i);
$result->{$key} = $val;
} else {
$sock->close();
return $result;
}
}
}
sub reshare {
my $sock = donkey_connect();
return 0 unless $sock;
$sock->print("reshare\n");
$sock->close();
return 1;
}
sub close_fds {
my $sock = donkey_connect();
return 0 unless $sock;
$sock->print("close_fds\n");
$sock->close();
return 1;
}
sub change_setting ($$) {
my ($key, $val) = @_;
my $result;
$result->{key} = $key;
$result->{old} = get_settings($key)->{$key};
my $sock = donkey_connect();
return unless $sock;
$sock->print("set ".$key." ".$val."\n");
$sock->close();
#$result->{new} = $val;
$result->{new} = get_settings($key)->{$key};
return $result;
}
sub get_servers ($) {
my ($all) = @_;
my $sock = donkey_connect();
return unless $sock;
if ($all) {
$sock->print("vma\n");
} else {
$sock->print("vm\n");
}
my $result;
while ($_ = $sock->getline()) {
#if (/^\[(.*?) (\d+) *\] ([0-9.]+):(\d+) + (.*?) + (\d+) +(\d+) (Connected)?$/) {
if (/^\[(.*?) (\d+) *\] (.+):(\d+) + (.*?) + (\d+) +(\d+) (Connected)?$/) {
my $server = { net => $1,
id => $2,
ip => $3,
port => $4,
comment => $5,
users => $6,
files => $7
};
$result->{$2} = $server;
} elsif (/^ *$/) {
$sock->close();
return $result;
}
}
}
sub search_file ($) {
my ($query) = @_;
my $sock = donkey_connect();
return unless $sock;
$sock->print("s ".$query."\n");
while ($_ = $sock->getline()) {
if (/Query \d+ Sent to \d+/) {
$sock->close;
return 1;
} elsif (/exception/) {
$sock->close;
return 0;
}
}
}
sub list_downloads ($) {
my ($data) = @_;
my $text = downloads2text($data, '/.*/'); #downloads_list($data, '/.*/');
print CLIENTCRAP &draw_box('iDonkey', $text, 'Downloads', 1);
}
sub get_best_name ($) {
my ($names) = @_;
my $result;
foreach (@$names) {
# It's a hash
$result = $_;
last unless /[A-Z0-9]{32}/;
}
return $result;
}
sub downloads2text ($$) {
my ($downloads, $regexp) = @_;
my $length = Irssi::settings_get_int('idonkey_max_filename_length');
my $text;
my @table;
my @chunks;
my @names;
my ($speed, $downloaded, $size) = (0,0,0);
foreach (sort {get_best_name($downloads->{$a}{names}) cmp get_best_name($downloads->{$b}{names})} keys %$downloads) {
my @line;
my $filename = get_best_name($downloads->{$_}{names});
my $name = shorten_filename($filename, $length);
$name =~ s/%/%%/g;
my $download;
# Color codes:
# Yellow Paused
# Bold green Completed
# Green Downloading & 100% available
# Blue Downloading, but not completly on network
if ($downloads->{$_}{rate} =~ /Paused|Queued/) {
$download .= '%yo%n';
} elsif ($downloads->{$_}{rate} eq 'Completed') {
$download .= '%Go%n';
} else {
if ($downloads->{$_}{available}) {
$download .= '%go%n';
} else {
$download .= '%bo%n';
}
$speed += $downloads->{$_}{rate};
}
$size += $downloads->{$_}{size};
$downloaded += $downloads->{$_}{downloaded};
$download .= ' %9'.$name.'%9 ('.$_.')';
push @names, $download;
#$text .= "\n" if 1;
push @line, round($downloads->{$_}{downloaded}, $downloads->{$_}{size});
#$text .= ' '.round($downloads->{$_}{downloaded}, $downloads->{$_}{size})."/";
push @line, round($downloads->{$_}{size},$downloads->{$_}{size});
push @line, '('.$downloads->{$_}{percent}.'%%)';
#$text .= round($downloads->{$_}{size},$downloads->{$_}{size})." (".$downloads->{$_}{percent}."%%)";
if ($downloads->{$_}{rate} =~ /^[0-9.]+$/) {
push @line, $downloads->{$_}{rate}." kb/s";
} elsif ($downloads->{$_}{rate} eq '-') {
push @line, "0 kb/s";
} else {
push @line, $downloads->{$_}{rate};
}
#push @line, ' ['.$downloads->{$_}{sources}.'/'.$downloads->{$_}{onlist}.' @'.$downloads->{$_}{net}.']' if (defined $downloads->{$_}{sources});
my $netload = '[';
$netload .= $downloads->{$_}{sources}."@";
$netload .= $downloads->{$_}{net}.']';
push @line, $netload;
push @line, .$downloads->{$_}{tag};
#$text .= "\n";
if (1 || $downloads->{$_}{chunks}) {
if (ref $downloads->{$_}{chunks} && @{$downloads->{$_}{chunks}} > 1) {
my $chunk;
$chunk .= '[';
foreach (@{$downloads->{$_}{chunks}}) {
if ($_ > 1) {
$chunk .= '%g|%n';
} elsif ($_ == 1) {
$chunk .= '%b:%n';
} else {
$chunk .= '%r.%n';
}
}
$chunk .= "]";
push @chunks, $chunk;
} else {
push @chunks, "";
}
}
push @table, \@line;
}
foreach (split /\n/, array2table(@table)) {
$text .= (shift @names)."\n";
$text .= " ".$_."\n";
if (Irssi::settings_get_bool('idonkey_show_chunks')) {
my $chunk = shift @chunks;
$text .= " ".$chunk."\n" if $chunk;
}
}
my $percent = $size > 0 ? ($downloaded / $size)*100 : 0;
$percent = $1 if ($percent =~ /(\d+\.\d{1}).*?/);
if (keys %$downloads > 1) {
$text .= "".'%9Total:%9 ';
$text .= round($downloaded, $size).'/';
$text .= round($size, $size);
$text .= ' ('.$percent.'%%), '.$speed.' kb/s';
}
return $text;
}
sub round ($$) {
return $_[0] unless Irssi::settings_get_bool('idonkey_round_filesize');
if ($_[1] > 100000) {
return sprintf "%.2fMB", $_[0]/1024/1024;
} else {
return sprintf "%.2fKB", $_[0]/1024;
}
}
sub get_queries {
my $sock = donkey_connect();
# FIXME A real parser here?
return undef unless $sock;
$sock->print("vs\n");
my %result;
my $num;
while ($_ = readline($sock)) {
chop;
if (/^Searching (\d+) queries$/) {
$num = $1;
} elsif (/^\[(\d+) *\](.*) .*?$/) {
my $id = $1;
my $regexp = $2;
my @token = $regexp =~ /CONTAINS\[(.*?)\]/g;
$result{$id} = \@token;
$num--;
}
last if (defined $num && $num == 0);
}
return \%result;
}
sub get_results ($) {
my ($filter) = @_;
my $sock = donkey_connect();
my $net = '.*';
if ($filter =~ /-net (.*?)(?: |$)/) {
$net = $1;
}
#my $regexp = '.*';
my @filters;
while ($filter =~ /(\!?)\/(.*?)\//g) {
my %entry = ( "reverse" => $1 ? 1 : 0,
"regexp" => $2
);
push @filters, \%entry;
}
my $result;
my @results;
my $waiting = 0;
my $filtered = 0;
return undef unless $sock;
my $num = 0;
$sock->print("vr\n");
my @token;
while ($_ = readline($sock)) {
chop;
if (/^Result of search (\d+)$/) {
my $searches = get_queries();
@token = @{ $searches->{$1} } if ref $searches->{$1};
} elsif (/^(\d+) results \((?:done|(-?\d+) waiting)\)$/) {
$num = $1;
$waiting = $2 if $2;
unless ($num) {
$sock->close();
last();
}
} elsif (/^\[ *(\d+)\] (.*?(?: Napster)?) (.*)/) {
# FIXME Find a better Solution for open Napster
my %data = ( id=> $1, filename => $3, visible => 1, net => $2);
$data{visible} = 1 unless @filters;
foreach my $entry (@filters) {
next unless $data{visible};
my $regexp = $entry->{regexp};
my $reverse = $entry->{reverse};
if (not $reverse) {
$data{visible} = 0 if not ($data{filename} =~ /$regexp/i);
} else {
$data{visible} = 0 if ($data{filename} =~ /$regexp/i);
}
}
if (Irssi::settings_get_bool('idonkey_filter_search_results') && @token) {
foreach (@token) {
$data{visible} = 0 unless $data{filename} =~ /$_/i;
last unless $data{visible};
}
$data{visible} = 0 unless $data{net} =~ /$net/i;
}
if (Irssi::settings_get_bool('idonkey_filter_nameless_results')) {
$data{visible} = 0 unless $data{filename};
}
push @results, \%data;
} elsif (/^ ALREADY DOWNLOADED$/) {
$results[-1]->{downloaded} = 1;
} elsif (/^ +(-?\d+) ([0-9A-Z]{32}) (\d+)?/) {
$results[-1]->{size} = $1;
$results[-1]->{hash} = $2;
$results[-1]->{sources} = $3;
unless ($results[-1]->{visible}) {
pop @results;
$filtered++;
} else {
#$results[-1]->{fake} = is_fake($results[-1]->{hash});
}
} elsif (/No search to print/ || /^$/ || /^exception/) {
$sock->close();
last();
}
}
my $sortby = Irssi::settings_get_str('idonkey_sort_results_by');
@results = sort {uc($a->{$sortby}) <=> uc($b->{$sortby})} @results;
$result->{results} = \@results;
$result->{waiting} = $waiting;
$result->{filtered} = $filtered;
return $result;
}
sub list_servers ($) {
my ($data) = @_;
my @text;
foreach (sort { $data->{$a}{id} <=> $data->{$b}{id} } keys %$data) {
push @text, ["%9".$data->{$_}{id}."%9", $data->{$_}{net}, $data->{$_}{ip}.':'.$data->{$_}{port}, $data->{$_}{users}, $data->{$_}{files}, $data->{$_}{comment}];
}
unshift @text, ["%9ID%9", "%9net%9", "%9address%9", "%9users%9", "%9files%9", "%9comment%9"] if @text;
print CLIENTCRAP &draw_box('iDonkey', array2table(@text), 'servers', 1);
}
sub list_results ($) {
my ($data) = @_;
my $results = $data->{results};
my @text;
$seen = $nresults;
my $length = Irssi::settings_get_int('idonkey_max_filename_length');
foreach (@$results) {
my @line;
next unless $_->{visible};
my $file = shorten_filename($_->{filename}, $length);
$file =~ s/%/%%/g;
push @line, '%9'.$_->{id}.'%9';
push @line, '%9'.$file.'%9';
push @line, $_->{fake} ? '%RF%n' : '';
push @line, $_->{downloaded} ? '%GD%n' : '';
push @line, $_->{net} if defined $_->{net};
push @line, '['.$_->{sources}.']';
push @line, round($_->{size}, $_->{size});
push @text, \@line;
}
my $footer = 'Results';
$footer .= ' ('.$data->{filtered}.' filtered)' if $data->{filtered} > 0;
$footer .= ' ('.$data->{waiting}.' waiting)' if $data->{waiting} > 0;
print CLIENTCRAP &draw_box('iDonkey', array2table(@text), $footer, 1);
}
sub get_file ($$) {
my ($file, $force) = @_;
my $sock = donkey_connect();
return unless $sock;
$sock->print("d ".$file."\n");
while ($_ = $sock->getline()) {
if (/download started/) {
$sock->close();
return 1;
} elsif (/(File already downloaded|could not start download)/) {
if ($force) {
$sock->print("force_download\n");
$sock->close();
return 1
} else {
$sock->close();
return 0;
}
}
}
}
sub download_link ($$) {
my ($url, $force) = @_;
my $sock = donkey_connect();
return unless $sock;
$sock->print("dllink ".$url."\n");
$sock->print("force_download\n") if $force;
while ($_ = $sock->getline()) {
if (/download (started|forced)|Done/) {
$sock->close();
return 1;
} elsif (/Unable|bad syntax|exception/ && not $force) {
$sock->close();
return 0;
}
}
}
sub connect_servers ($$) {
my ($ids, $disconnect) = @_;
my $sock = donkey_connect();
return unless $sock;
$sock->print("c\n") unless (@$ids);
foreach (@$ids) {
if ($disconnect) {
$sock->print("x ".$_."\n");
} else {
$sock->print("c ".$_."\n");
}
}
$sock->close();
}
sub quit_donkey {
my $sock = donkey_connect();
return unless $sock;
$sock->print("kill\n");
$sock->close();
return 1;
}
sub commit_downloads {
my $sock = donkey_connect();
return unless $sock;
$sock->print("commit\n");
$sock->close();
until ($_ = $sock->getline()) {
#if (/commited/) {
return 1;
#} else {
# return 0;
#}
}
}
sub get_status_info {
my $result;
$result->{downloads} = get_downloads();
$result->{waiting} = get_results('/.*/')->{waiting};
my $upload = no_upload(0);
$result->{credit} = $upload->[1];
$result->{noupload} = $upload->[0];
return $result;
}
sub cmd_idonkey ($$$) {
my ($args, $server, $witem) = @_;
my @arg = split(/ /, $args);
if (@arg == 0 || $arg[0] eq 'downloads') {
#list_downloads();
bg_do('downloads');
} elsif ($arg[0] eq 'help') {
show_help();
} elsif ($arg[0] =~ /pause|resume|cancel/ && defined $arg[1]) {
bg_do(join(' ', @arg));
} elsif ($arg[0] =~ /results/) {
bg_do(join(' ', @arg));
} elsif ($arg[0] eq 'search') {
shift @arg;
if (search_file(join(' ', @arg))) {
$seen = 0;
$nresults = 0;
print CLIENTCRAP "%R>>%n Query '".join(' ', @arg)."' sent to network...";
}
} elsif ($arg[0] eq 'get' && defined $arg[1]) {
shift @arg;
my $force = 0;
foreach my $id (@arg) {
if ($id eq 'force') {
$force = 1;
} elsif (get_file($id, $force)) {
print CLIENTCRAP "%R>>%n Download of file ".$id." started";
} else {
print CLIENTCRAP "%R>>%n Download of file ".$id." failed";
}
}
} elsif ($arg[0] eq 'dllink' && defined $arg[1]) {
shift @arg;
join(' ', @arg) =~ /(force )?(.*)/;
my $force = defined $1 ? 1 : 0;
if (download_link($2, $1)) {
print CLIENTCRAP "%R>>%n Download of ".$2." started";
} else {
print CLIENTCRAP "%R>>%n Download of ".$2." failed";
}
} elsif ($arg[0] eq 'commit') {
if (commit_downloads()) {
print CLIENTCRAP "%R>>%n Completed downloads saved";
} else {
print CLIENTCRAP "%R>>%n Saving completed downloads failed";
}
} elsif ($arg[0] eq 'launch') {
my $cmd = Irssi::settings_get_str('idonkey_mldonkey_cmd');
system($cmd);
print CLIENTCRAP "%R>>%n MLDonkey launched";
} elsif ($arg[0] eq 'quit') {
if ( quit_donkey() ) {
print CLIENTCRAP "%R>>%n MLDonkey killed";
} else {
print CLIENTCRAP "%R>>%n Unable to kill MLDonkey";
}
} elsif ($arg[0] eq 'servers') {
shift @arg;
if ( (not @arg) || ($arg[0] eq 'connected') ) {
bg_do('servers');
} elsif ($arg[0] eq 'disconnect') {
shift @arg;
connect_servers(\@arg, 1);
} elsif ($arg[0] eq 'connect') {
shift @arg;
connect_servers(\@arg, 0);
} elsif ($arg[0] eq 'all') {
bg_do('allservers');
}
} elsif ($arg[0] eq 'overnet') {
shift @arg;
if ( (not @arg) || ($arg[0] eq 'stats') ) {
bg_do('ovstats');
} elsif ($arg[0] eq 'nodes') {
bg_do('ovnodes');
}
} elsif ($arg[0] eq 'settings') {
shift @arg;
if ( (not @arg) ) {
# Do something
} elsif ($arg[0] eq 'show') {
shift @arg;
bg_do('settings '.join(' ',@arg));
} elsif ($arg[0] eq 'change') {
shift @arg;
return unless (defined $arg[0] && defined $arg[1]);
my $key = shift @arg;
my $val = join(' ', @arg);
bg_do('set '.$key.' '.$val)
}
} elsif ($arg[0] eq 'shares') {
shift @arg;
if ( (not @arg) ) {
## list shares?
} elsif ($arg[0] eq 'reshare') {
bg_do('reshare');
} elsif ($arg[0] eq 'close') {
bg_do('close_fds');
}
} elsif ($arg[0] eq 'sharereactor') {
shift @arg;
if ( (not @arg) || $arg[0] eq 'latest') {
print CLIENTCRAP "%B>>%n Retrieving latest releases...";
bg_do('sr-latest');
} elsif ($arg[0] eq 'search') {
shift @arg;
bg_do('sr-search '.join(" ", @arg));
print CLIENTCRAP "%B>>%n Searching ShareReactor for '".join(" ", @arg)."'";
} elsif ($arg[0] eq 'download' && defined $arg[1]) {
shift @arg;
download_sr(join(" ", @arg));
}
} elsif ($arg[0] eq 'bittorrent') {
shift @arg;
if ($arg[0] eq 'search') {
shift @arg;
bg_do('bt-search '.join(" ", @arg));
print CLIENTCRAP "%B>>%n Searching BitTorrent for '".join(" ", @arg)."'";
}
} elsif ($arg[0] eq 'noupload') {
shift @arg;
if (@arg && $arg[0] =~ /-?\d+/) {
bg_do('noupload '.$arg[0]);
}
} elsif ($arg[0] eq 'client-stats') {
bg_do('client-stats');
} elsif ($arg[0] eq 'forget') {
bg_do('forget');
} elsif ($arg[0] eq 'fake' && defined $arg[1]) {
shift @arg;
foreach (@arg) {
next unless /\d+/;
bg_do('fake '.$_);
}
}
}
sub download_sr ($) {
my ($download) = @_;
if (defined $edlinks{$download}) {
foreach my $link (@{ $edlinks{$download} }) {
if (download_link($link,0)) {
print CLIENTCRAP "%R>>%n Download of ".$link." started";
} else {
print CLIENTCRAP "%R>>%n Download of ".$link." failed";
}
}
} else {
print CLIENTCRAP "%B>>%n Unknown release, try searching for it.";
}
}
sub shorten_filename ($$) {
my ($file, $length) = @_;
unless ($length == 0) {
my $post = 4;
my $pre = $length-5-$post;
$file =~ s/^(.{$pre}).*(.{$post})/$1\[\.\.\.\]$2/;
}
return $file;
}
sub filename_percent ($$) {
my ($name, $percent) = @_;
my $length = length($name);
my $done = $length * ($percent/100);
my $string = '%g%U'.substr($name, 0, $done).'%U%n%y'.substr($name, $done, $length).'%n';
return $string;
}
sub sb_idonkey ($$) {
my ($item, $get_size_only) = @_;
my $line;
$line .= $nresults."|" if ($seen != $nresults && defined $seen);
$line .= '%F'.$expected."%F|" if $expected > 0;
$line .= $noul."min|" if $noul > 0;
#my $length = Irssi::settings_get_int('idonkey_max_filename_length');
my $length = Irssi::settings_get_int('idonkey_statusbar_max_filename_length');
my $i = 0;
foreach (sort keys %downloads) {
$index = 0 if $index > (scalar keys %downloads)-1;
unless ($i == $index) {
$i++;
next;
}
unless (Irssi::settings_get_bool('idonkey_statusbar_show_paused')) {
if ($downloads{$_}{rate} eq 'Paused') {
$index++;
next;
}
}
my $filename = get_best_name($downloads{$_}{names});
my $file = shorten_filename($filename, $length);
$line .= filename_percent($file, $downloads{$_}{percent});
$line .= ' '.$downloads{$_}{percent}.'%% ';
unless ($downloads{$_}{rate} eq '-') {
$line .= $downloads{$_}{rate};
$line .= ' kb/s' if $downloads{$_}{rate} =~ /^[0-9.]+$/;
}
$line .= ' ';
$i++;
}
$line =~ s/ $//;
my $format = "{sb ".$line."}";
$item->{min_size} = $item->{max_size} = length($line);
$item->default_handler($get_size_only, $format, 0, 1);
}
sub call_for_status {
bg_do('status');
}
sub sig_complete_word ($$$$$) {
my ($list, $window, $word, $linestart, $want_space) = @_;
if ($linestart =~ /^.idonkey (pause|resume|cancel)/) {
foreach (sort {get_best_name($downloads{$a}{names}) cmp get_best_name($downloads{$b}{names})} keys %downloads) {
my $name = get_best_name($downloads{$_}{names});
if ( ($1 eq 'resume' && $downloads{$_}{rate} eq 'Paused') ||
($1 eq 'pause' && not $downloads{$_}{rate} eq 'Paused') ||
($1 eq 'cancel') ) {
push @$list, $name if $name =~ /^(\Q$word\E.*)?$/i;
}
}
Irssi::signal_stop();
} elsif ($linestart =~ /^.idonkey search/) {
my @opts = ('minsize', 'maxsize', 'media', 'Video', 'Audio', 'format', 'title', 'album', 'artist', 'field', 'not', 'and', 'or');
foreach (@opts) {
$_ = '-'.$_;
push @$list, $_ if /^(\Q$word\E.*)?$/i;
}
Irssi::signal_stop();
} elsif ($linestart =~ /^.idonkey sharereactor download/) {
foreach (sort keys %edlinks) {
push @$list, $_ if /^(\Q$word\E.*)?$/i;
}
Irssi::signal_stop();
} elsif ($linestart =~ /^.idonkey dllink/) {
foreach (sort keys %edlinks) {
foreach my $link (@{ $edlinks{$_} }) {
push @$list, $link if $link =~ /^(\Q$word\E.*)?$/i;
}
}
Irssi::signal_stop();
} elsif ($linestart =~ /^.idonkey results/) {
my @opts = ('net');
foreach (@opts) {
$_ = '-'.$_;
push @$list, $_ if /^(\Q$word\E.*)?$/i;
}
}
}
sub next_status {
$index++;
$index = 0 if $index > (scalar keys %downloads)-1;
Irssi::statusbar_items_redraw('idonkey');
}
sub install_timer {
return if defined $timer;
my $timeout = Irssi::settings_get_int('idonkey_statusbar_interval');
my $timeout2 = Irssi::settings_get_int('idonkey_update_interval');
return unless $timeout && $timeout2;
$timer = Irssi::timeout_add($timeout*1000, \&next_status, undef);
$timer2 = Irssi::timeout_add($timeout2*1000, \&call_for_status, undef);
}
sub uninstall_timer {
return unless defined $timer;
Irssi::timeout_remove($timer);
Irssi::timeout_remove($timer2);
$timer = undef;
}
Irssi::command_bind('idonkey', \&cmd_idonkey);
foreach my $cmd ('downloads', 'pause', 'resume', 'results', 'search', 'get', 'get force', 'cancel', 'help', 'commit', 'dllink', 'dllink force', 'launch', 'quit', 'servers', 'servers disconnect', 'servers connected', 'servers all', 'servers connect', 'overnet', 'overnet stats', 'overnet nodes', 'settings', 'settings show', 'settings change', 'shares', 'shares reshare', 'shares close', 'sharereactor', 'sharereactor search', 'sharereactor download', 'sharereactor latest', 'noupload', 'client-stats', 'forget', 'fake', 'bittorrent', 'bittorrent search') {
Irssi::command_bind('idonkey '.$cmd => sub {
cmd_idonkey("$cmd ".$_[0], $_[1], $_[2]); });
}
Irssi::signal_add_first('complete word', \&sig_complete_word);
Irssi::settings_add_str($IRSSI{name}, 'idonkey_password', '');
Irssi::settings_add_str($IRSSI{name}, 'idonkey_host', 'localhost');
Irssi::settings_add_int($IRSSI{name}, 'idonkey_port', 4000);
Irssi::settings_add_int($IRSSI{name}, 'idonkey_max_filename_length', 65);
# sources, filename, id, size
Irssi::settings_add_str($IRSSI{name}, 'idonkey_sort_results_by', "id");
Irssi::settings_add_bool($IRSSI{name}, 'idonkey_round_filesize', 1);
Irssi::settings_add_bool($IRSSI{name}, 'idonkey_filter_nameless_results', 1);
Irssi::settings_add_bool($IRSSI{name}, 'idonkey_filter_search_results', 0);
Irssi::settings_add_bool($IRSSI{name}, 'idonkey_show_chunks', 1);
Irssi::settings_add_str($IRSSI{name}, 'idonkey_mldonkey_cmd', 'screen mldonkey');
Irssi::settings_add_int($IRSSI{name}, 'idonkey_statusbar_interval', 0);
Irssi::settings_add_bool($IRSSI{name}, 'idonkey_statusbar_show_paused', 1);
Irssi::settings_add_int($IRSSI{name}, 'idonkey_update_interval', 0);
Irssi::settings_add_bool($IRSSI{name}, 'idonkey_update_results', 1);
Irssi::settings_add_int($IRSSI{name}, 'idonkey_statusbar_max_filename_length', 25);
Irssi::statusbar_item_register('idonkey', 0, "sb_idonkey");
install_timer();
print CLIENTCRAP '%B>>%n '.$IRSSI{name}.' '.$VERSION.' loaded, /idonkey help';