PageRenderTime 60ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/irc/bot.pl

https://bitbucket.org/StylusEater/clevelandpm
Perl | 646 lines | 579 code | 50 blank | 17 comment | 46 complexity | 36c9ac93bfe18b7dbc9d9824a5253a1b MD5 | raw file
  1. #!/usr/bin/perl -w
  2. use Sys::Hostname;
  3. use Perl6::Slurp;
  4. use JSON;
  5. use Geo::WeatherNWS;
  6. use strict;
  7. use IO::Socket;
  8. use IO::Select;
  9. use IO::Pipe qw();
  10. use IO::Handle;
  11. use List::Util qw(shuffle);
  12. use XML::LibXML;
  13. use URI::Escape;
  14. use DateTime;
  15. use LWP::UserAgent;
  16. use DBI;
  17. $| = 1;
  18. my $forever = 'yeah';
  19. our $VERSION = "0.38";
  20. our $password = shift || 'irclogs';
  21. #die('MySQL password not provided');
  22. our $chan = shift || '#cle.pm';
  23. #'#test';
  24. our $iter = shift || 0;
  25. our $me;
  26. our $p = XML::LibXML->new;
  27. our $sson = 0;
  28. our $g_dbh;
  29. MAINIRC: while ($forever)
  30. {
  31. $me = 'cle_pm_bot' . $iter;
  32. my $c;
  33. eval {
  34. $c = IO::Socket::INET->new(
  35. PeerAddr => 'irc.perl.org',
  36. PeerPort => '6667',
  37. Proto => 'tcp',
  38. Timeout => '30'
  39. ) || print "Error! $!\n";
  40. };
  41. binmode( $c, ':utf8' );
  42. if ($@)
  43. {
  44. warn "Server connection has gone away, will reconnect in 10 seconds";
  45. sleep 10;
  46. next(MAINIRC);
  47. }
  48. print $c "NICK $me\r\n";
  49. print $c "USER $me " . hostname . " irc.perl.org :CLE Bot\r\n";
  50. print $c "JOIN $chan\r\n";
  51. print $c "PRIVMSG $chan :bot.pl version $VERSION - type \"$me\" (no quotes) for command list\r\n";
  52. #io sel setup
  53. my $sock = IO::Select->new();
  54. $sock->add($c);
  55. $sock->add( \*STDIN );
  56. my $kick = 0;
  57. if ( my @handles = $sock->can_read(1) )
  58. {
  59. print "All handles ready";
  60. }
  61. while ( my @ready = $sock->can_read )
  62. {
  63. eval {
  64. foreach my $handle (@ready)
  65. {
  66. if ( $handle == $c )
  67. {
  68. # this is from the irc connection
  69. my $buffer;
  70. sysread( $c, $buffer, 4096 );
  71. if ( !$buffer )
  72. {
  73. warn "Server connection has gone away, will reconnect in 10 seconds";
  74. sleep 10;
  75. next(MAINIRC);
  76. }
  77. my @lines = split( /\n/, $buffer );
  78. foreach my $line (@lines)
  79. {
  80. eval { &parse_serverline( $c, $line ); };
  81. if ($@)
  82. {
  83. warn "$@ - will reconnect in 10 seconds";
  84. sleep 10;
  85. next(MAINIRC);
  86. }
  87. }
  88. }
  89. else
  90. {
  91. # we typed soemthing
  92. my $buffer = <STDIN>;
  93. if ($buffer)
  94. {
  95. if ( $buffer =~ /^\/me/ )
  96. {
  97. $buffer =~ s/^\/me //g;
  98. }
  99. else
  100. {
  101. &local_echo($buffer);
  102. print $c "PRIVMSG $chan :$buffer";
  103. }
  104. }
  105. }
  106. }
  107. };
  108. if ( $@ =~ /pow/ )
  109. {
  110. print "Seems alarmy: " . $@;
  111. }
  112. else
  113. {
  114. print $@ . "\n";
  115. }
  116. }
  117. }
  118. sub get_dbh
  119. {
  120. eval { $g_dbh->do("select now()"); };
  121. if ($@)
  122. {
  123. warn "Connecting to db on localhost";
  124. $g_dbh = DBI->connect( "DBI:mysql:database=irclogs;host=localhost", "irclogs", $password, { 'RaiseError' => 1 } );
  125. }
  126. return $g_dbh;
  127. }
  128. sub local_echo
  129. {
  130. my $message = shift;
  131. return;
  132. my $dbh = &get_dbh;
  133. my $userref = $dbh->selectrow_hashref( "select * from irc_user where shortname=?", undef, $me );
  134. my $chanref = $dbh->selectrow_hashref( "select * from irc_channel where name=?", undef, $chan );
  135. if ( !$chanref->{id} )
  136. {
  137. $dbh->do( "insert into irc_channel (name) values (?)", undef, $chan );
  138. $chanref = $dbh->selectrow_hashref( "select * from irc_channel where name=?", undef, $chan );
  139. }
  140. $message =~ s/[^\040-\176]//g;
  141. $dbh->do( "insert into irc_log (irc_channel_id,irc_user_id,irc_command,message,logged_at) values (?,?,?,?,now())",
  142. undef, $chanref->{id}, $userref->{id}, 'PRIVMSG', $message );
  143. }
  144. sub parse_serverline
  145. {
  146. my ( $sock, $serverline ) = @_;
  147. die "*** connection to server lost\n" if ( $serverline eq "" );
  148. # parse
  149. $serverline = "server $serverline" unless $serverline =~ /^:/;
  150. my ( $who, $cmd, $args ) = split( / /, $serverline, 3 );
  151. $who =~ s/^://;
  152. $cmd =~ tr/a-z/A-Z/;
  153. $args =~ s/^://;
  154. my $dbh = &get_dbh();
  155. if ( $cmd =~ /\d+/ )
  156. {
  157. print $cmd;
  158. if ( $cmd == 311 )
  159. {
  160. # serverline :irc.whapps.com 311 cle_pm_bot_1 styluseater ~styluseater 10.0.2.11 * :Adam M Dutko
  161. my ( $no, $junk, $realname ) = split( /:/, $serverline );
  162. my ( $server, $cmdnum, $me, $whoshort, @rest ) = split( /\s+/, $junk );
  163. $dbh->do( "update irc_user set realname=? where shortname=?", undef, $realname, $whoshort );
  164. }
  165. elsif ( $cmd == 433 )
  166. {
  167. #:emancipator.whapps.com 433 * cle_pm_bot_0 :Nickname already in use
  168. $iter++;
  169. die("nick dupe, retry");
  170. }
  171. else
  172. {
  173. print "unimpemented server cmd: ";
  174. print $serverline . "\n";
  175. return;
  176. }
  177. }
  178. return if ( !$cmd );
  179. # ok, its a user!
  180. my ( $whoshort, $wholong ) = split( /!/, $who, 2 );
  181. $dbh = &get_dbh;
  182. my $userref = $dbh->selectrow_hashref( "select * from irc_user where shortname=?", undef, $whoshort );
  183. if ( !$userref->{id} )
  184. {
  185. print $sock "WHOIS $whoshort\r\n";
  186. $dbh->do( "insert into irc_user (shortname,longname) values (?,?)", undef, $whoshort, $wholong );
  187. $userref = $dbh->selectrow_hashref( "select * from irc_user where shortname=?", undef, $whoshort );
  188. }
  189. #ok, we have all of the details, lets log this thing
  190. eval {
  191. if ( $cmd ne 'PING' )
  192. {
  193. my $msg = $args;
  194. if ( $cmd eq 'PRIVMSG' )
  195. {
  196. my $cr;
  197. ( $cr, $msg ) = split( /:/, $args, 2 );
  198. }
  199. my $chanref = $dbh->selectrow_hashref( "select * from irc_channel where name=?", undef, $chan );
  200. if ( !$chanref->{id} )
  201. {
  202. $dbh->do( "insert into irc_channel (name) values (?)", undef, $chan );
  203. $chanref = $dbh->selectrow_hashref( "select * from irc_channel where name=?", undef, $chan );
  204. }
  205. if ( $msg !~ /^bot lasts/ )
  206. {
  207. $msg =~ s/[^\040-\176]//g;
  208. $dbh->do(
  209. "insert into irc_log (irc_channel_id,irc_user_id,irc_command,message,logged_at) values (?,?,?,?,now())",
  210. undef, $chanref->{id}, $userref->{id}, $cmd, $msg
  211. );
  212. }
  213. }
  214. };
  215. if ( $cmd eq 'JOIN' )
  216. {
  217. print localtime(time) . " $whoshort ($wholong) has joined $args\n";
  218. if ( ( $whoshort ne $me ) && ($sson) )
  219. {
  220. my @one = (
  221. "RRRRAAAAAARRRWWWRRR",
  222. "Beware Coward!",
  223. "Beware, I Live!",
  224. "I am ... Sinistar",
  225. "I Hunger!",
  226. "I Hunger, Coward!",
  227. "Run, Coward!",
  228. "RUN RUN RUN!!!"
  229. );
  230. my @s1 = shuffle(@one);
  231. print $sock "PRIVMSG $chan :$s1[0]\r\n";
  232. &local_echo( $s1[0] );
  233. }
  234. }
  235. elsif ( $cmd eq 'KICK' )
  236. {
  237. # no
  238. my ( $whoshort, $wholong ) = split( /!/, $who, 2 );
  239. my ( $lchan, $the_kicked, $message ) = split( /\s+/, $args, 3 );
  240. print localtime(time) . " $whoshort ($wholong) has kicked $args\n";
  241. if ( $the_kicked eq $me )
  242. {
  243. # no you didnt
  244. print $sock "JOIN $lchan\r\n";
  245. }
  246. }
  247. elsif ( $cmd eq 'PART' )
  248. {
  249. my ( $whoshort, $wholong ) = split( /!/, $who, 2 );
  250. print localtime(time) . " $whoshort ($wholong) has left $args\n";
  251. ( $args, undef ) = split( / /, $args, 2 ) if $args =~ / /;
  252. }
  253. elsif ( $cmd eq 'PING' )
  254. {
  255. print $sock "PONG $args\n";
  256. print "*** PONG $args\n";
  257. }
  258. elsif ( $cmd eq 'QUIT' )
  259. {
  260. my ( $whoshort, $wholong ) = split( /!/, $who, 2 );
  261. chop $args if ( $args =~ /\W$/ );
  262. print localtime(time) . " Signoff $whoshort ($args)\n";
  263. }
  264. elsif ( $cmd eq 'PRIVMSG' )
  265. {
  266. my ( $whoshort, $wholong ) = split( /!/, $who, 2 );
  267. my ( $lchan, $message ) = split( /\:/, $args, 2 );
  268. print localtime(time) . " $whoshort: $message\n";
  269. # ok magic
  270. if ( ( $message =~ /^cle_pm_bot/ ) || ( $message =~ /^bot\s+/ ) )
  271. {
  272. my $me_or_alias;
  273. ( $me_or_alias, $message ) = split( /\s+/, $message, 2 );
  274. if ( !$message )
  275. {
  276. print $sock "PRIVMSG $lchan :usage $me_or_alias <command>\r\n";
  277. print $sock
  278. "PRIVMSG $lchan :implemented weather, sales, fortune, lastseen, lastsaid, randomator, forecast\r\n";
  279. }
  280. elsif ( $message =~ /^randomator/ )
  281. {
  282. my @ators =
  283. qw(abator abbreviator abdicator aberrator aberuncator ablator abnegator abominator abrogator accelerator accentuator acclamator accommodator accumulator acetylator activator actuator acupuncturator acutiator adjudicator administrator admirator adstipulator adulator adulterator advocator aerator agglomerator agglutinator aggravator aggregator agistator agitator alienator allegator alleviator alligator alliterator allocator alternator amalgamator ambulator ameliorator amplificator amputator animator annihilator annotator annunciator anticipator anticreator antioxygenator antivaccinator antivibrator apiator applicator appreciator approbator appropriator approximator arbitrator arborator archagitator archconspirator archdepredator archsacrificator argumentator arrogator articulator asphyxiator aspirator assassinator assecurator assentator assimilator associator attemperator attenuator attestator auscultator authenticator autocollimator autocrator autokrator autoregenerator autoxidator auxiliator averruncator aviator avigator barrator brachiator bronchodilator buccinator cachinnator calculator calibrator calorisator calumniator capitulator caprificator captivator carbonator carburator cardioaccelerator cardiodilator castigator castrator catalyzator caveator celebrator centuriator certificator chlorinator chronocrator cinerator circulator circumambulator circumaviator circumnavigator citator classificator coadjudicator coadjutator coadministrator coagitator coagulator coarbitrator coattestator coconsecrator coconspirator cocreator cocurator coemptionator coformulator cogitator cohobator colegislator collaborator collator collimator combinator commemorator commendator commentator comminator commiserator communicator commutator companator comparator compensator compilator compotator compurgator concatenator concentrator conciliator concionator condensator confabulator confederator confiscator conflagrator conformator confutator congratulator congregator conjugator conjurator consecrator conservator considerator consignificator consolidator conspirator consummator contaminator contemplator continuator convocator corporator corroborator corrugator cosenator costipulator cotranslator counterorator creator cremator criminator cultivator cunctator cuneator curator deaerator dearsenicator debellator decapitator decarbonator decator decelerator decimator declarator decollator deconcentrator decorator decorticator dedicator defalcator defecator deflagrator deflator deflocculator defoliator degerminator dehydrator dejerator delator delegator deliberator delineator demarcator demodulator demonstrator denigrator denitrator denitrificator denominator denunciator deoxidator dephlegmator depilator depopulator deprecator depreciator depredator depurator deputator derogator desiccator designator deteriorator determinator detonator detoxicator devastator deviator devirginator dialyzator dictator differentiator digladiator dilapidator dilatator dilator disarticulator disceptator discriminator disintegrator dislocator dismembrator dispensator dispergator disputator disseminator dissertator dissimulator dissipator divaricator divinator domesticator dominator donator duplicator edificator educator edulcorator ejaculator elaborator elator elevator eliminator elucidator elutriator emanator emancipator emasculator emendator emigrator emulator enervator enucleator enumerator enunciator epitomator equator equilibrator equivocator eradicator Escalator escalator escheator estimator estivator evacuator evaporator evocator exaggerator examinator excavator excitator excogitator excommunicator excoriator excruciator excusator execrator exemplificator exhilarator exhortator exhumator exonerator expatiator expectorator experimentator expiator expilator expirator expiscator explanator explicator explorator expostulator expropriator expurgator exsiccator extenuator exterminator extirpator extrapolator fabricator facilitator falsificator fascinator fecundator federator felicitator filator fixator flagellator flocculator formulator fornicator fractionator fulgurator fulminator fumigator funambulator fustigator gator generator germinator gesticulator gladiator glossator graduator grammatolator granulator gubernator gyrator habilitator hallucinator hereticator hibernator hortator hospitator humiliator hydrator hydrogenator hyperpredator hypoeliminator hypothecator illuminator illustrator imaginator imitator immigrator immolator impanator imperator impermeator impersonator impetrator implorator importunator imprecator impregnator impropriator improvisator inaugurator incantator incarcerator incinerator inclinator incorporator incriminator incrustator incubator inculcator indagator indemnificator indicator individuator indoctrinator infatuator inhalator initiator innovator inoculator insinuator inspirator inspissator instaurator instigator instillator insufflator insulator integrator intercommunicator intermediator interpellator interpolator interrogator intimidator intonator intoxicator intubator inundator invalidator investigator invigilator invigorator invocator irradiator irrigator irritator jaculator jejunator joculator judicator jurator justificator kosmokrator lachrymator lapidator laudator legator legislator levator levigator levitator liberator ligator liquidator literator litigator lixiviator locator lubricator lucubrator luminator machinator magnetogenerator maladministrator malaxator maltreator mandator manipulator masticator masturbator matriculator mediator medicator meditator meliorator Mercator methylator micromanipulator migrator miniator ministrator miscalculator miscegenator miscreator mitigator moderator modificator modulator monochromator monstrator multiplicator multivibrator murmurator mutilator mystificator narrator natator navigator Necator negator negotiator nitrator nivellator nomenclator nominator nonagglutinator nonconspirator nonvibrator notator novator nucleator nugator nullificator numerator obfuscator objurgator obligator obliterator obtruncator obturator obviator odorator officiator operator opinator orator orchestrator ordinator orientator originator oscillator oxidator oxygenator oxygenerator ozonator pacificator palliator Pantocrator participator peculator pedipulator penetrator perambulator percolator peregrinator perfectionator perforator perlustrator permeator permutator perorator perpetrator perpetuator perscrutator personator personificator perturbator phrator piscator plicator pollinator populator postillator postulator potator preadministrator precipitator preconspirator predator predestinator predicator prediscriminator predominator prefabricator prefator pregustator preinvestigator prejudicator premeditator preoperator preparator preseparator presignificator prestidigitator prestigiator prevaricator probator proclamator procrastinator procreator procurator prognosticator promulgator pronator pronunciator propagator propitiator propugnator prorogator prostrator protestator provocator pulsator pulverizator punctator punctuator purificator pylorodilator quadruplator qualificator radiator radiolocator ratiocinator recapitulator reciprocator reconciliator recreator recriminator rectificator recuperator recusator redintegrator refrigerator regenerator registrator regrator regulator rehypothecator reinstator rejuvenator relator relevator relocator remonstrator remunerator renovator renunciator reprobator repudiator resonator respirator restorator resuscitator retaliator revelator reverberator rotator rubiator rubricator ruinator ruminator Russificator rusticator sacrificator salivator Saltator saltator saturator scarificator scintillator scrutator sectator segregator senator separator sequestrator sibilator signator significator simplificator simulator somnambulator sophisticator spectator spectrocomparator speculator spoliator stabilizator stannator stator stereocomparator sternutator stimulator stipulator stridulator strigilator subadministrator subconservator subcurator subescheator subjugator sublimator substantiator substrator sulfonator sulfurator sulphonator sulphurator supercommentator supererogator superseminator supinator supplicator sustentator syncopator syndicator tabulator taxator temporator teretipronator tergiversator terminator testator testificator thermogenerator thermoregulator titillator titivator tolerator totalizator tractator transformator transilluminator translator transliterator transmigrator treator triangulator triturator triumphator truncator tubulator turboalternator turbogenerator turboventilator underescheator undermediator unificator urinator vaccinator vacillator valuator variator variegator vasodilator vaticinator venator venerator ventilator versificator viator vibrator vindicator vinificator violator visitator vitiator vituperator vivificator vociferator zelator);
  284. my @rd = shuffle(@ators);
  285. print $sock "PRIVMSG $lchan :Random beer name: " . ucfirst( lc( $rd[0] ) ) . "\r\n";
  286. &local_echo( "Random beer name: " . ucfirst( lc( $rd[0] ) ) );
  287. }
  288. elsif ( $message =~ /^sales/ )
  289. {
  290. my @one =
  291. qw(aggregate architect benchmark brand cultivate deliver deploy disintermediate drive e-enable embrace empower enable engage engineer enhance envisioneer evolve expedite exploit extend facilitate generate grow harness implement incentivize incubate innovate integrate iterate leverage matrix maximize mesh monetize morph optimize orchestrate productize recontextualize redefine reintermediate reinvent repurpose revolutionize scale seize strategize streamline syndicate synergize synthesize target transform transition unleash utilize visualize whiteboard);
  292. my @two =
  293. qw(B2B B2C back-end best-of-breed bleeding-edge bricks-and-clicks clicks-and-mortar collaborative compelling cross-platform cross-media customized cutting-edge distributed dot-com dynamic e-business efficient end-to-end enterprise extensible frictionless front-end global granular holistic impactful innovative integrated interactive intuitive killer leading-edge magnetic mission-critical next-generation one-to-one open-source out-of-the-box plug-and-play proactive real-time revolutionary rich robust scalable seamless sexy sticky strategic synergistic transparent turn-key ubiquitous user-centric value-added vertical viral virtual visionary web-enabled wireless world-class);
  294. my @three =
  295. qw(APIs action-items applications architectures bandwidth channels communities content convergence deliverables e-business APIs e-commerce e-markets e-services e-tailers experiences eyeballs functionalities infomediaries infrastructures initiatives interfaces markets methodologies APIs metrics mindshare models networks niches paradigms partnerships platforms APIs portals relationships ROI synergies web-readiness schemas solutions supply-chains systems APIs technologies users vortals webservices);
  296. my @s1 = shuffle(@one);
  297. my @s2 = shuffle(@two);
  298. my @s3 = shuffle(@three);
  299. print $sock "PRIVMSG $lchan :Just say \"$s1[0] $s2[0] $s3[0]\". It's a standard customization.\r\n";
  300. &local_echo("Just say \"$s1[0] $s2[0] $s3[0]\". It's a standard customization.");
  301. }
  302. elsif ( $message =~ /^sson/ )
  303. {
  304. $sson = 1;
  305. print $sock "PRIVMSG $lchan :sson 1\r\n";
  306. }
  307. elsif ( $message =~ /^ssoff/ )
  308. {
  309. $sson = 0;
  310. print $sock "PRIVMSG $lchan :sson 0\r\n";
  311. }
  312. elsif ( $message =~ /^sinistar/ )
  313. {
  314. my @one = (
  315. "RRRRAAAAAARRRWWWRRR",
  316. "Beware Coward!",
  317. "Beware, I Live!",
  318. "I am ... Sinistar",
  319. "I Hunger!",
  320. "I Hunger, Coward!",
  321. "Run, Coward!",
  322. "RUN RUN RUN!!!"
  323. );
  324. my @s1 = shuffle(@one);
  325. print $sock "PRIVMSG $lchan :$s1[0]\r\n";
  326. &local_echo( $s1[0] );
  327. }
  328. elsif ( $message =~ /^weather/ )
  329. {
  330. my $seesmetar;
  331. if ( $message =~ /metar/ )
  332. {
  333. $seesmetar = 1;
  334. $message =~ s/metar//g;
  335. }
  336. my @mparts = split( /\s+/, $message );
  337. my $station = $mparts[1] || 'kcvg';
  338. if ( $message =~ /inside/ )
  339. {
  340. my $dt = DateTime->now;
  341. my $tmp =
  342. `/Users/mslagle/Applications/HardwareMonitor.app/Contents/MacOS/hwmonitor -f 2>/dev/null| grep AMBIENT | cut -d':' -f2 | cut -d' ' -f2`;
  343. my $tmpc =
  344. `/Users/mslagle/Applications/HardwareMonitor.app/Contents/MacOS/hwmonitor 2>/dev/null| grep AMBIENT | cut -d':' -f2 | cut -d' ' -f2`;
  345. $tmp =~ s/[\r\n]//g;
  346. $tmpc =~ s/[\r\n]//g;
  347. my $metar;
  348. if ($seesmetar)
  349. {
  350. $metar =
  351. '(KCZ0 '
  352. . sprintf( '%02s%02s%02s', $dt->day, $dt->hour, $dt->minute )
  353. . 'Z VRB001KT 10SM OVC000CEL '
  354. . sprintf( '%02s', $tmpc )
  355. . '/00 AXXXX RMK A01)';
  356. }
  357. print $sock "PRIVMSG $lchan : Fair $tmp degrees - (no sensor) in $metar\r\n";
  358. &local_echo("Fair $tmp degrees - (no sensor) in $metar");
  359. }
  360. else
  361. {
  362. my $w = Geo::WeatherNWS->new();
  363. $w->setservername('tgftp.nws.noaa.gov');
  364. $w->setusername('anonymous');
  365. $w->setpassword('marc.slagle@online-rewards.com');
  366. $w->setdirectory("/data/observations/metar/stations");
  367. $w->getreport($station);
  368. my $speed;
  369. if ( $w->{windspeedmph} > 0 )
  370. {
  371. $speed = $w->{windspeedmph} . "mph";
  372. }
  373. my $metar;
  374. if ($seesmetar)
  375. {
  376. $metar = '(' . $w->{obs} . ')';
  377. }
  378. print $sock
  379. "PRIVMSG $lchan :$w->{conditionstext} $w->{temperature_f} degrees - $w->{pressure_inhg} in $metar\r\n";
  380. &local_echo("$w->{conditionstext} $w->{temperature_f} degrees - $w->{pressure_inhg} in $metar");
  381. }
  382. }
  383. elsif ( $message =~ /^fortune/ )
  384. {
  385. my @ret = `/usr/games/fortune -s | tr '\n' ' '`;
  386. foreach my $line (@ret)
  387. {
  388. $line =~ s/\s+/ /g;
  389. print $sock "PRIVMSG $lchan :$line\r\n";
  390. &local_echo($line);
  391. }
  392. }
  393. elsif ( $message =~ /^forecast/ )
  394. {
  395. eval {
  396. my $fn = '/var/www/cleveland.pm.org/cleveland.json';
  397. &lwp_fetch_data($fn);
  398. my $fcon = slurp($fn);
  399. my $json = from_json($fcon);
  400. my $fc_data = $json->{forecast}->{simpleforecast}->{forecastday};
  401. my ( @r1, @r2, @r3 );
  402. push( @r1, ' ' );
  403. push( @r2, 'Conditions' );
  404. push( @r3, 'Temp H/L' );
  405. my $utf_map = {
  406. chanceflurries => " \x{2603} ",
  407. chancerain => " \x{2602} ",
  408. chancesleet => " \x{2602} ",
  409. chancesnow => " \x{2603} ",
  410. chancetstorms => "\x{263c}/\x{2608} ",
  411. clear => " \x{263c} ", # ' ☼ ',
  412. cloudy => " \x{2601} ",
  413. flurries => " \x{2603} ",
  414. fog => ' Fog ',
  415. hazy => 'Haze ',
  416. mostlycloudy => "\x{263c}/\x{2601} ",
  417. mostlysunny => "\x{263c}/\x{2601} ",
  418. partlycloudy => "\x{263c}/\x{2601} ",
  419. partlysunny => "\x{263c}/\x{2601} ",
  420. sleet => " \x{2602} ",
  421. rain => " \x{2602} ",
  422. sleet => " \x{2602} ",
  423. snow => " \x{2603} ",
  424. sunny => " \x{263c} ", #' ☼ ',
  425. tstorms => " \x{2608} ",
  426. };
  427. foreach my $d (@$fc_data)
  428. {
  429. push( @r1, ' ' . $d->{date}->{weekday_short} . ' ' );
  430. if ( my $ic = $utf_map->{ $d->{icon} } )
  431. {
  432. push( @r2, ' ' . $ic );
  433. }
  434. else
  435. {
  436. push( @r2, $d->{skyicon} );
  437. }
  438. push( @r3, $d->{high}->{fahrenheit} . '/' . $d->{low}->{fahrenheit} );
  439. }
  440. # print $sock "PRIVMSG $lchan :" . sprintf("%12s\t%8s\t%8s %8s %8s\r\n",@r1);
  441. # print $sock "PRIVMSG $lchan :" . sprintf("%12s\t%7s\t%7s %7s %7s\r\n",@r2);
  442. # print $sock "PRIVMSG $lchan :" . sprintf("%12s\t%8s\t%8s %8s %8s\r\n",@r3);
  443. print $sock "PRIVMSG $lchan :"
  444. . pack( "A12 A8 A8 A8 A8", $r1[0], $r1[1], $r1[2], $r1[3], $r1[4] ) . "\r\n";
  445. print $sock "PRIVMSG $lchan :"
  446. . pack( "A12 A7 A7 A7 A7", $r2[0], $r2[1], $r2[2], $r2[3], ' ' . $r2[4] ) . "\r\n";
  447. print $sock "PRIVMSG $lchan :"
  448. . pack( "A12 A8 A8 A8 A8", $r3[0], $r3[1], $r3[2], $r3[3], $r3[4] ) . "\r\n";
  449. };
  450. if ($@)
  451. {
  452. warn $@;
  453. print $sock "PRIVMSG $lchan :I can't get the data right now\r\n";
  454. }
  455. }
  456. elsif ( $message =~ /^lastseen/ )
  457. {
  458. my ( $cmd, $user, $other ) = split( /\s+/, $message, 3 );
  459. if ($user)
  460. {
  461. eval {
  462. my $dbh = &get_dbh;
  463. my $userref =
  464. $dbh->selectrow_hashref( "select * from irclogs.irc_user where shortname=?", undef, $user );
  465. my $lastseen = $dbh->selectrow_hashref(
  466. "select il.logged_at,ic.name from irclogs.irc_log il
  467. inner join irclogs.irc_channel ic on (il.irc_channel_id=ic.id)
  468. where irc_user_id=? order by logged_at desc limit 1", undef, $userref->{id}
  469. );
  470. if ( $lastseen->{logged_at} )
  471. {
  472. print $sock
  473. "PRIVMSG $lchan :last saw $user at $lastseen->{logged_at} on $lastseen->{name}\r\n";
  474. }
  475. else
  476. {
  477. print $sock "PRIVMSG $lchan :\caACTION has never seen $user before\ca\n";
  478. }
  479. };
  480. if ($@)
  481. {
  482. print $sock "PRIVMSG $lchan :sorry: $@\r\n";
  483. }
  484. }
  485. else
  486. {
  487. print $sock "PRIVMSG $lchan :usage: lastseen nick\r\n";
  488. }
  489. }
  490. elsif ( $message =~ /^lastsaid/ )
  491. {
  492. my ( $cmd, $user, $other ) = split( /\s+/, $message, 3 );
  493. if ($user)
  494. {
  495. eval {
  496. my $dbh = &get_dbh;
  497. my $userref =
  498. $dbh->selectrow_hashref( "select * from irclogs.irc_user where shortname=?", undef, $user );
  499. my $chanref =
  500. $dbh->selectrow_hashref( "select * from irclogs.irc_channel where name=?", undef, $lchan );
  501. my $lastsaid = $dbh->selectrow_hashref(
  502. "select * from irclogs.irc_log il
  503. where irc_user_id=? and irc_channel_id=? and irc_command='PRIVMSG'
  504. order by logged_at desc limit 1", undef, $userref->{id}, $chanref->{id}
  505. );
  506. if ( $lastsaid->{logged_at} )
  507. {
  508. print $sock "PRIVMSG $lchan :$lastsaid->{logged_at} $user: $lastsaid->{message}\r\n";
  509. }
  510. else
  511. {
  512. print $sock
  513. "PRIVMSG $lchan :\caACTION has never seen $user say anything on $chanref->{name} before\ca\n";
  514. }
  515. };
  516. if ($@)
  517. {
  518. print $sock "PRIVMSG $lchan :sorry: $@\r\n";
  519. }
  520. }
  521. else
  522. {
  523. print $sock "PRIVMSG $lchan :usage: lastsaid nick\r\n";
  524. }
  525. }
  526. else
  527. {
  528. $message =~ s/[\r\n]//g;
  529. if ( $message =~ /\?$/ )
  530. {
  531. my $val = 'http://lmgtfy.com/?q=' . uri_escape($message);
  532. print $sock "PRIVMSG $lchan :$whoshort: $val\n";
  533. }
  534. else
  535. {
  536. print $sock "PRIVMSG $lchan:Does not seem to be implemented\r\n";
  537. }
  538. }
  539. }
  540. }
  541. else
  542. {
  543. #:emancipator.whapps.com 433 * cle_pm_bot_0 :Nickname already in use
  544. my @parts = split( /\s+/, $serverline );
  545. #print "*$parts[1]* $serverline\n";
  546. if ( $parts[1] eq "433" )
  547. {
  548. # nick in use
  549. $iter++;
  550. die("nick dupe, retry");
  551. }
  552. }
  553. }
  554. sub lwp_fetch_data
  555. {
  556. my $wd_file = shift;
  557. print "testing $wd_file\n";
  558. if ( -f $wd_file )
  559. {
  560. my @statinfo = stat($wd_file);
  561. my $age8 = ( $statinfo[8] - time() ) * -1;
  562. my $age = ( $statinfo[9] - time() ) * -1;
  563. my $age10 = ( $statinfo[10] - time() ) * -1;
  564. print $age . " seconds\n";
  565. if ( $age < 3600 )
  566. {
  567. return;
  568. }
  569. }
  570. print "$wd_file isnt there/is too old\n";
  571. # ok to get a new file, this is an hour old
  572. my $ua = LWP::UserAgent->new();
  573. my $response = $ua->get('http://api.wunderground.com/api/fa4a3adf03db95fc/forecast/q/OH/Cleveland.json');
  574. if ( $response->is_success )
  575. {
  576. open( JSON, "> $wd_file" );
  577. print $response->content;
  578. print JSON $response->content;
  579. close(JSON);
  580. }
  581. else
  582. {
  583. print Dumper($response);
  584. # must have busted... touch file to keep from sploding my key
  585. #system("touch $wd_file");
  586. }
  587. return;
  588. }