2015-01-21 19:24:18 +00:00
#!/usr/bin/python
# http://wiki.shellium.org/w/Writing_an_IRC_bot_in_Python
# Import some necessary libraries.
import socket
import os
import sys
2015-06-22 18:01:16 +00:00
import time
2015-01-21 19:24:18 +00:00
from optparse import OptionParser
import fileinput
import random
import formatter
import get_users
2018-02-28 21:08:22 +00:00
import names
2015-01-21 19:24:18 +00:00
import mentions
import pretty_date
import inflect
2015-02-12 21:15:16 +00:00
import puzzle
2015-01-21 19:24:18 +00:00
parser = OptionParser ( )
parser . add_option ( " -s " , " --server " , dest = " server " , default = ' 127.0.0.1 ' ,
help = " the server to connect to " , metavar = " SERVER " )
parser . add_option ( " -c " , " --channel " , dest = " channel " , default = ' #bot_test ' ,
help = " the channel to join " , metavar = " CHANNEL " )
parser . add_option ( " -n " , " --nick " , dest = " nick " , default = ' tildebot ' ,
help = " the nick to use " , metavar = " NICK " )
( options , args ) = parser . parse_args ( )
p = inflect . engine ( )
2015-02-12 21:15:16 +00:00
challenges = { }
2015-02-02 19:47:47 +00:00
SCORE_FILE = " tildescores.txt "
JACKPOT_FILE = " tildejackpot.txt "
JACKPOT_MIN = 3
DEBUG = False
2015-01-21 19:24:18 +00:00
2018-10-05 17:46:25 +00:00
def ping ( pong ) :
ircsock . send ( " PONG {} \n " . format ( pong ) )
2015-01-21 19:24:18 +00:00
def sendmsg ( chan , msg ) :
ircsock . send ( " PRIVMSG " + chan + " : " + msg + " \n " )
def joinchan ( chan ) :
ircsock . send ( " JOIN " + chan + " \n " )
def hello ( ) :
ircsock . send ( " PRIVMSG " + channel + " :Hello! \n " )
def too_recent ( time1 , time2 ) :
if ( int ( time1 ) - int ( time2 ) < 60 * 60 ) :
return True
else :
return False
2017-03-30 21:39:44 +00:00
def get_positive ( ) :
2017-08-04 12:06:58 +00:00
return random . choice ( [ ' Yes ' , ' Yep ' , ' Yeppers ' , ' Correct ' , ' You got it ' , ' Yeah ' , ' Right on ' , ' Uh-huh ' , ' Positive ' , ' Totally right ' , ' Close enough ' , ' That \' s it ' ] )
2017-03-30 21:39:44 +00:00
def get_negative ( ) :
2017-08-04 12:06:58 +00:00
return random . choice ( [ ' No ' , ' Nope ' , ' Sorry ' , ' Wrong ' , ' Nuh-uh ' , ' Negatory ' , ' Incorrect ' , ' Not today ' , ' Try again ' , ' Maybe later ' , ' Probably not ' , ' Answer hazy ' , ' Not quite ' , \
' Not even close ' ] )
2017-03-30 21:39:44 +00:00
def get_superlative ( score ) :
if score > 4 :
return random . choice ( [ " super cool " , " totally rad " , " extraordinary " , " dynomite " , " #topdrawer " , " a #TopLad " , " the cat ' s meow " , " a tilde town hero " , " my favorite person " , " incredibly lucky " , \
2017-08-04 12:06:58 +00:00
" unbelievable " , " a tilde town hunk " , " could bring all the boys to the yard " , " worth twice their weight in gold " , " the hero we need " , " no ordinary townie " ] ) ;
2017-03-30 21:39:44 +00:00
elif score > 2 :
return random . choice ( [ " really cool " , " pretty neat " , " rather nice " , " a dynamic doggo " , " radical " , " intense " , " pretty lucky " , " knows the territory " , " has what it takes " , " has mad skillz " , \
2017-08-04 12:06:58 +00:00
" going the distance " , " a hard worker " , " my sunshine " , " ready to rumble " ] ) ;
2017-03-30 21:39:44 +00:00
else :
2017-08-04 12:06:58 +00:00
return random . choice ( [ " cool " , " nice " , " acceptible " , " good enough " , " a promising pupper " , " better than a horse " , " swell " , " a little lucky " , " just credible " , " my friend " , " probably not a robot " , \
" valuable to the team " ] ) ;
2017-03-30 21:39:44 +00:00
def get_bad_thing ( ) :
return random . choice ( [ " is a meanie " , " mugs me right off " , " is worse than a horse " , " smells like a ghost " , " probably didn ' t bathe today " , " didn ' t guess hard enough " , " isn ' t lucky " , \
" smells of elderberries " , " should reconsider their life choices " , " did ' t believe in the heart of the tilde " , " came to the wrong chat channel " , " should have stopped while they were ahead " , \
2017-08-04 12:06:58 +00:00
" requires annotations from an authoratative source " , " could have been a contender " , " spreads vicious rumors " , " drank my milkshake " , " is probably cheating " , " is trying too hard " ] ) ;
2017-03-30 21:39:44 +00:00
2018-02-28 21:08:22 +00:00
def get_prize ( name , isHuman , bonus = 0 ) :
2016-09-07 15:58:36 +00:00
prizes = [ 1 ] * 8 + [ 2 ] * 4 + [ 3 ] * 2 + [ 5 ] * isHuman #no 5pt prize for non-humans
prize = random . choice ( prizes ) + bonus
2015-02-12 21:15:16 +00:00
if ( random . randint ( 1 , 10 ) > 6 - 4 * isHuman ) : #80% of the time it's a normal prize (40% for not humans)
2018-02-28 21:08:22 +00:00
return [ prize , name + " : " + ( get_positive ( ) if isHuman else get_negative ( ) ) + " ! You are " + get_superlative ( prize ) + " and get " + p . number_to_words ( prize ) + " tildes! " ]
2015-02-02 19:47:47 +00:00
else : #20% of the time its a jackpot situation
with open ( JACKPOT_FILE , " r+ " ) as jackpotfile :
jackpot = int ( jackpotfile . readline ( ) . strip ( " \n " ) )
jackpotfile . seek ( 0 )
jackpotfile . truncate ( )
2015-02-12 21:15:16 +00:00
if ( random . randint ( 1 , 10 ) > 1 or not isHuman ) : #90% of the time it's a non-prize. non-humans never win jackpot
2016-09-07 15:58:36 +00:00
new_jackpot = jackpot + max ( 1 , prize )
jackpotfile . write ( str ( new_jackpot ) ) #increase the jackpot by the prize size
2018-02-28 21:08:22 +00:00
return [ 0 , name + " " + get_bad_thing ( ) + " and gets no tildes! (Jackpot is now " + str ( new_jackpot ) + " tildes) " ]
2015-02-02 19:47:47 +00:00
else : #hit jackpot!
jackpotfile . write ( str ( JACKPOT_MIN ) )
2018-02-28 21:08:22 +00:00
return [ jackpot , name + " hit the jackpot and won ** " + p . number_to_words ( jackpot ) + " tildes!** " ]
2015-02-02 19:47:47 +00:00
def show_jackpot ( channel ) :
with open ( JACKPOT_FILE , " r " ) as jackpotfile :
2015-02-06 19:35:22 +00:00
jackpot = int ( jackpotfile . readline ( ) . strip ( " \n " ) )
2015-02-02 19:47:47 +00:00
ircsock . send ( " PRiVMSG " + channel + " :The jackpot is currently " + p . number_to_words ( jackpot ) + " tildes! \n " )
2015-01-21 19:24:18 +00:00
2018-02-28 21:08:22 +00:00
def give_tilde ( channel , user , name , time , human , bonus = 0 ) :
2015-01-21 19:24:18 +00:00
found = False
2015-02-02 19:47:47 +00:00
with open ( SCORE_FILE , " r+ " ) as scorefile :
2015-01-21 19:24:18 +00:00
scores = scorefile . readlines ( )
scorefile . seek ( 0 )
scorefile . truncate ( )
for score in scores :
person = score . strip ( " \n " ) . split ( " &^ % " )
if ( person [ 0 ] == user ) :
found = True
2015-02-02 19:47:47 +00:00
if ( too_recent ( time , person [ 2 ] ) and not DEBUG ) :
2018-02-28 21:08:22 +00:00
ircsock . send ( " PRIVMSG " + channel + " : " + name + " asked for a tilde too recently and " + get_bad_thing ( ) + " . Try again later. \n " )
2015-01-21 19:24:18 +00:00
else :
2018-02-28 21:08:22 +00:00
prize = get_prize ( name , human , bonus )
2015-01-21 19:24:18 +00:00
score = person [ 0 ] + " &^ % " + str ( int ( person [ 1 ] ) + prize [ 0 ] ) + " &^ % " + time + " \n "
ircsock . send ( " PRIVMSG " + channel + " : " + prize [ 1 ] + " \n " )
scorefile . write ( score )
if ( not found ) :
2018-02-28 21:08:22 +00:00
prize = get_prize ( name , True , bonus )
2015-01-21 19:24:18 +00:00
ircsock . send ( " PRIVMSG " + channel + " :Welcome to the tilde game! Here ' s " + p . number_to_words ( prize [ 0 ] + 1 ) + " free tilde(s) to start you off. \n " )
scorefile . write ( user + " &^ % " + str ( prize [ 0 ] + 1 ) + " &^ % " + time + " \n " )
2018-02-28 21:08:22 +00:00
def show_tildescore ( channel , user , name ) :
2015-02-02 19:47:47 +00:00
with open ( SCORE_FILE , " r " ) as scorefile :
2015-01-21 19:24:18 +00:00
for idx , score in enumerate ( scorefile ) :
person = score . strip ( " \n " ) . split ( " &^ % " )
if ( person [ 0 ] == user ) :
2018-02-28 21:08:22 +00:00
ircsock . send ( " PRIVMSG " + channel + " : " + name + " has " + p . number_to_words ( person [ 1 ] ) + " tildes! \n " )
2015-01-21 19:24:18 +00:00
return
#person has not played yet
2018-02-28 21:08:22 +00:00
ircsock . send ( " PRIVMSG " + channel + " : " + name + " has no tildes yet! \n " )
2015-01-21 19:24:18 +00:00
2018-02-28 21:08:22 +00:00
def challenge ( channel , user , name , time ) :
2015-02-12 21:15:16 +00:00
if ( channel != " #bots " and not DEBUG ) :
2018-02-28 21:08:22 +00:00
ircsock . send ( " PRIVMSG " + channel + " : " + name + " is a meanie and gets no tildes. **Tildebot now only gives out tildes in the #bots channel.** \n " )
2015-02-12 21:15:16 +00:00
return
global challenges ;
challenge = puzzle . make_puzzle ( ) ;
2018-07-16 20:55:22 +00:00
challenges [ user ] = challenge [ 1 : ] ; #challenges[USER] = [ANSWER, BONUS]
ircsock . send ( " PRIVMSG " + channel + " : " + name + " : " + challenge [ 0 ] + " \n " )
2015-02-12 21:15:16 +00:00
2018-02-28 21:08:22 +00:00
def challenge_response ( channel , user , name , time , msg ) :
2015-02-12 21:15:16 +00:00
global challenges
print ( msg ) ;
if ( challenges . has_key ( user ) ) :
2018-07-16 20:55:22 +00:00
answer , bonus = challenges [ user ]
2018-07-16 21:01:36 +00:00
if ( ( callable ( answer ) and answer ( msg . lower ( ) ) ) or ( msg . lower ( ) == str ( answer ) . lower ( ) or msg == p . number_to_words ( answer ) ) ) :
2018-02-28 21:08:22 +00:00
give_tilde ( channel , user , name , time , True , bonus ) ;
2015-02-12 21:15:16 +00:00
else :
2018-02-28 21:08:22 +00:00
give_tilde ( channel , user , name , time , False , 0 ) ;
2015-02-12 21:15:16 +00:00
del challenges [ user ] ; #delete the user from challenges either way
2015-01-21 19:24:18 +00:00
def rollcall ( channel ) :
ircsock . send ( " PRIVMSG " + channel + " :tildebot reporting! I respond to !tilde !tildescore \n " )
def connect ( server , channel , botnick ) :
ircsock . connect ( ( server , 6667 ) )
ircsock . send ( " USER " + botnick + " " + botnick + " " + botnick + " :krowbar \n " ) # user authentication
ircsock . send ( " NICK " + botnick + " \n " )
joinchan ( channel )
2015-02-12 21:15:16 +00:00
if ( not DEBUG ) :
joinchan ( " #bots " )
2015-01-21 19:24:18 +00:00
def get_user_from_message ( msg ) :
try :
i1 = msg . index ( ' : ' ) + 1
i2 = msg . index ( ' ! ' )
return msg [ i1 : i2 ]
except ValueError :
return " "
def listen ( ) :
while 1 :
ircmsg = ircsock . recv ( 2048 )
2016-02-05 18:32:53 +00:00
for msg in ircmsg . split ( ' \n ' ) :
msg = msg . strip ( ' \n \r ' )
2015-01-21 19:24:18 +00:00
2018-10-05 17:46:25 +00:00
if msg [ : 4 ] == " PING " :
ping ( msg . split ( " " ) [ 1 ] )
2015-01-21 19:24:18 +00:00
2016-02-05 18:34:19 +00:00
formatted = formatter . format_message ( msg )
2015-01-21 19:24:18 +00:00
2016-02-05 18:32:53 +00:00
if " " == formatted :
continue
2015-01-21 19:24:18 +00:00
# print formatted
2016-02-05 18:32:53 +00:00
split = formatted . split ( " \t " )
iTime = split [ 0 ]
user = split [ 1 ]
2018-02-28 21:08:22 +00:00
name = names . get_name ( user )
2016-02-05 18:32:53 +00:00
command = split [ 2 ]
channel = split [ 3 ]
messageText = split [ 4 ]
2015-01-21 19:24:18 +00:00
2016-02-05 18:32:53 +00:00
if msg . find ( " :!tildescore " ) != - 1 :
2018-02-28 21:08:22 +00:00
show_tildescore ( channel , user , name )
2016-02-05 18:32:53 +00:00
elif msg . find ( " :!tilde " ) != - 1 and not challenges . has_key ( user ) :
2018-02-28 21:08:22 +00:00
challenge ( channel , user , name , iTime )
2018-07-16 20:43:26 +00:00
elif challenges . has_key ( user ) and ( channel == " #bots " or DEBUG ) :
2018-02-28 21:08:22 +00:00
challenge_response ( channel , user , name , iTime , messageText )
#give_tilde(channel, user, name, iTime)
2015-01-21 19:24:18 +00:00
2016-02-05 18:32:53 +00:00
if msg . find ( " :!jackpot " ) != - 1 :
2015-02-02 19:47:47 +00:00
show_jackpot ( channel )
2016-02-05 18:32:53 +00:00
if msg . find ( " :!rollcall " ) != - 1 :
rollcall ( channel )
2015-01-21 19:24:18 +00:00
2018-10-05 17:46:25 +00:00
if msg [ : 4 ] == " PING " :
ping ( msg . split ( " " ) [ 1 ] )
2015-01-21 19:24:18 +00:00
2016-02-05 18:32:53 +00:00
sys . stdout . flush ( )
time . sleep ( 1 )
2015-01-21 19:24:18 +00:00
ircsock = socket . socket ( socket . AF_INET , socket . SOCK_STREAM )
connect ( options . server , options . channel , options . nick )
listen ( )