thanks.pm 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. use POE;
  2. my %karma = ();
  3. my $moar_karma = sub {
  4. my $n = shift;
  5. $karma{$n} //= 0;
  6. $karma{$n}++;
  7. };
  8. my $unhilite = sub {
  9. my $n = shift;
  10. substr($n, 1, 0) = "\xE2\x80\x8D"; # U+200D ZERO WIDTH JOINER
  11. # XXX- need to port to Unicode strings to get rid of this atrocity
  12. $n;
  13. };
  14. {
  15. schemata => {
  16. 0 => [
  17. "CREATE TABLE thanks (from_nick TEXT NOT NULL, to_nick TEXT NOT NULL,
  18. created_at INT NOT NULL DEFAULT CURRENT_TIMESTAMP)",
  19. "CREATE INDEX thanks_to_idx ON thanks (to_nick)",
  20. "CREATE INDEX thanks_from_idx ON thanks (from_nick)",
  21. "CREATE INDEX thanks_time_idx ON thanks (created_at)",
  22. ],
  23. },
  24. on_load => sub {
  25. my $res = $BotDb::db->selectall_arrayref("SELECT * FROM thanks", {Slice => {}});
  26. $moar_karma->($_->{to_nick}) for @$res;
  27. },
  28. irc_commands => {
  29. karma => sub {
  30. my ($source, $targets, $args, $auth) = @_;
  31. BotIrc::check_ctx() or return;
  32. my @args = map(lc, split(/\s+/, $args));
  33. @args = lc(BotIrc::ctx_source()) if !@args || !$args[0];
  34. my $placeholders = join(',', map {; '?' } @args);
  35. my $d30 = $BotDb::db->selectall_hashref("SELECT to_nick, CAST(count(to_nick)/10 AS INTEGER) AS nicksum FROM thanks WHERE to_nick IN ($placeholders) AND created_at > date('now','-30 day') GROUP BY to_nick", 'to_nick', {}, @args);
  36. my $given = $BotDb::db->selectall_hashref("SELECT from_nick, CAST(count(from_nick)/10 AS INTEGER) AS nicksum FROM thanks WHERE from_nick IN ($placeholders) GROUP BY from_nick", 'from_nick', {}, @args);
  37. my @karma = ();
  38. for my $n (@args) {
  39. next if (!exists $karma{$n});
  40. my $k = int($karma{$n}/10);
  41. next if !$k;
  42. my $n_escaped = $unhilite->($n);
  43. my $info = "$n_escaped: $k";
  44. $info .= " ($d30->{$n}{nicksum} in past 30 days)" if exists $d30->{$n};
  45. $info .= " ($given->{$n}{nicksum} given out)" if exists $given->{$n};
  46. push @karma, $info;
  47. }
  48. if (!@karma) {
  49. BotIrc::send_wisdom("the karma of the given users is shrouded in the mists of uncertainty.");
  50. return;
  51. }
  52. BotIrc::send_wisdom("the Genuine Real Life Karma™ REST API results are back! ". join(', ', @karma));
  53. },
  54. topkarma => sub {
  55. my ($source, $targets, $args, $auth) = @_;
  56. BotIrc::check_ctx() or return;
  57. my $all = ($args =~ /^all$/);
  58. my $all_filter = $all ? "" : " WHERE created_at > date('now','-30 day')";
  59. my $res = $BotDb::db->selectall_arrayref("SELECT to_nick, count(to_nick) AS nicksum FROM thanks$all_filter GROUP BY to_nick ORDER BY nicksum DESC LIMIT 5", {Slice => {}});
  60. if (!ref($res) || @$res < 5) {
  61. BotIrc::send_noise("not enough data for a top karma list");
  62. return;
  63. }
  64. splice @$res, 5;
  65. my @top = map { $unhilite->($_->{to_nick}) .": ". int($_->{nicksum}/10) } @$res;
  66. my $all_msg = $all ? "of all time" : "of past 30 days ('all' arg to see totals)";
  67. BotIrc::send_wisdom("top karmic beings $all_msg: ". join(', ', @top));
  68. }
  69. },
  70. irc_on_public => sub {
  71. BotIrc::check_ctx() or return 1;
  72. my $suffix_form = qr/\b/;
  73. my $is_suffix;
  74. if ($_[ARG2] =~ /\+\+/) {
  75. $suffix_form = qr/\+\+/;
  76. $is_suffix = 1;
  77. } else {
  78. return 0 if $_[ARG2] !~ /\b(?:thank\s*you|thanks|thx|ty|cheers)\b/i;
  79. }
  80. my $ctx = BotIrc::ctx_frozen();
  81. my @nicks = map(lc, $BotIrc::irc->channel_list($ctx->{channel}));
  82. @nicks = grep { $_[ARG2] =~ /\b\Q$_\E$suffix_form/i; } @nicks;
  83. for my $n (@nicks) {
  84. next if $n eq lc(BotIrc::ctx_source());
  85. if ($n eq lc($BotIrc::irc->nick_name())) {
  86. BotIrc::ctx_set_addressee(BotIrc::ctx_source());
  87. if ($is_suffix) {
  88. BotIrc::send_wisdom("as a bot, I live on a higher plane of existence than you do. Karma has no meaning here.");
  89. } else {
  90. BotIrc::send_wisdom("you're welcome, but please note that I'm a bot. I'm not programmed to care.");
  91. }
  92. }
  93. $moar_karma->($n);
  94. $BotDb::db->do("INSERT INTO thanks (from_nick, to_nick) VALUES(?, ?)", {}, lc(BotIrc::ctx_source()), $n);
  95. }
  96. return 1;
  97. },
  98. };