diff options
author | B. Watson <urchlay@slackware.uk> | 2025-01-07 16:56:20 -0500 |
---|---|---|
committer | B. Watson <urchlay@slackware.uk> | 2025-01-07 16:56:20 -0500 |
commit | 98945a09973e1cba76e7b2da4d5fd238d193f393 (patch) | |
tree | 09e101442f141056d5e782827c5b98833494f873 | |
parent | 66fb8a7b8a2aacf75fda2009db60d9ef42958425 (diff) | |
download | stupid-irssi-tricks-98945a09973e1cba76e7b2da4d5fd238d193f393.tar.gz |
units.pl: added (unit conversions for a bot)
-rw-r--r-- | units.pl | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/units.pl b/units.pl new file mode 100644 index 0000000..927d541 --- /dev/null +++ b/units.pl @@ -0,0 +1,128 @@ +#!/usr/bin/perl + +# Unit conversions (weight/measure/etc) for an irssi bot. + +use warnings; +no strict; + +use POSIX 'round'; +use Irssi qw/signal_add/; + +$helpmsg = "Usage: !units <number> <unit> [[to] <to-unit>]. Examples: !units 50 miles km; !units 20C to F. With no <to-unit>, tries to guess based on <unit> (e.g. C will convert to F)"; + +# default output unit based on input unit +%default_unit = ( + F => 'C', + C => 'F', + f => 'c', + c => 'f', + mi => 'km', + mile => 'km', + km => 'mile', + ft => 'meter', + foot => 'm', + feet => 'm', + yd => 'm', + yard => 'm', + in => 'cm', + inch => 'cm', + inches => 'cm', + lb => 'kg', + pound => 'kg', + lbs => 'kg', + gal => 'l', + gallon => 'l', + cc => 'floz', + floz => 'cc', +); + +# round to nearest 1/100, e.g. 1.004 is 1, 1.005 is 1.01. +sub round_result { + return round($_[0] * 100) / 100; +} + +sub convert { + for($_[0]) { + s/°([cfk])\b/$1/i; + + if(/[^\s0-9a-zA-Z\/\^]/) { + return "malformed request"; + } + + s/\s+to\b//; + s/fl\w*\.?\s?o[uz]\w*/floz/; + + my ($num, $from, $to) = (/(\d+|\.\d+|\d+\.\d+)\s*([\w\^\/]+)(?:\s+([\w+\^\/]+))?$/); + + return "malformed request" unless defined $num && defined $from; + + $to = $default_unit{$from} unless defined $to; + unless(defined $to) { + my $f = $from; + $f =~ s/s$//; + $to = $default_unit{$f}; + } + return "no default conversion for $from" unless defined $to; + + #warn "was: num $num, from $from, to $to\n"; + my $realfrom = $from; + my $realto = $to; + my $realnum = $num; + my $space = " "; + + if($from =~ /^([cfk])$/i) { + $realfrom = uc $1; + $from = "temp" . uc($1) . "($num)"; + $num = ""; + $space = ""; + } + + if($to =~ /^([cfk])$/i) { + $realto = uc $1; + $to = "temp" . uc($1); + $space = ""; + } + + #warn "now: num $num, from $from, to $to\n"; + + # was using: -o'%.1f', but it doesn't do rounding, plus it + # prints 1 as 1.0. + + chomp($result = `units -1t '$num$from' '$to' 2>&1`); + if($?) { + if($result =~ /conformability error/) { + return "Can't convert $realfrom to $realto"; + } else { + return $result; + } + } else { + $result = round_result($result); + return "$realnum$space$realfrom is $result$space$realto"; + } + } +} + +sub on_public_msg { + my ($server, $msg, $nick, $address, $target) = @_; + my $mynick = $server->{nick}; + + unless(length $target) { + $target = $nick; + $nick = $mynick; + } + + if($target eq $mynick) { + # private message... send response to sender + $target = $nick; + } + + if($msg !~ /^!units\s+(.+)/) { + return; + } + + my $input = $1; + my $result = convert($input); + $server->command("msg $target $result"); +} + +signal_add("message public", "on_public_msg"); |