aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2025-01-07 16:56:20 -0500
committerB. Watson <urchlay@slackware.uk>2025-01-07 16:56:20 -0500
commit98945a09973e1cba76e7b2da4d5fd238d193f393 (patch)
tree09e101442f141056d5e782827c5b98833494f873
parent66fb8a7b8a2aacf75fda2009db60d9ef42958425 (diff)
downloadstupid-irssi-tricks-98945a09973e1cba76e7b2da4d5fd238d193f393.tar.gz
units.pl: added (unit conversions for a bot)
-rw-r--r--units.pl128
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");