2014-12-09 10:00:19 +00:00
#!/bin/python
2014-12-21 18:50:24 +00:00
#
2014-12-22 21:52:37 +00:00
# Cryptonote tipbot
2014-12-21 18:50:24 +00:00
# Copyright 2014 moneromooo
# Inspired by "Simple Python IRC bot" by berend
#
2014-12-23 10:47:56 +00:00
# The Cryptonote tipbot is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
2014-12-09 10:00:19 +00:00
import socket
2014-12-21 18:50:24 +00:00
import select
2014-12-09 10:00:19 +00:00
import sys
2014-12-21 18:50:24 +00:00
import random
2014-12-09 10:00:19 +00:00
import re
import redis
import hashlib
import json
import httplib
2014-12-21 18:50:24 +00:00
import time
2014-12-23 09:42:55 +00:00
import string
2014-12-09 10:00:19 +00:00
2014-12-22 17:03:03 +00:00
tipbot_name = " monero-testnet-tipbot "
2014-12-21 18:50:24 +00:00
irc_network = ' irc.freenode.net '
irc_port = 6667
irc_homechan = ' #txtptest000 '
2014-12-22 21:52:37 +00:00
irc_timeout_seconds = 600
2014-12-09 10:00:19 +00:00
redis_host = " 127.0.0.1 "
redis_port = 7777
2014-12-21 18:50:24 +00:00
2014-12-22 13:30:59 +00:00
bitmonerod_host = ' testfull.monero.cc ' # '127.0.0.1'
bitmonerod_port = 28081 # 6060
2014-12-09 10:00:19 +00:00
wallet_host = ' 127.0.0.1 '
wallet_port = 6061
2014-12-21 18:50:24 +00:00
wallet_update_time = 30 # seconds
2014-12-22 21:52:37 +00:00
coin = 1e12
coin_name = " Monero "
2014-12-23 09:28:37 +00:00
coin_denominations = [ [ 1000000 , 1 , " piconero " ] , [ 1000000000 , 1e6 , " micronero " ] , [ 1000000000000 , 1e9 , " millinero " ] ]
2014-12-22 21:52:37 +00:00
address_length = [ 95 , 95 ] # min/max size of addresses
address_prefix = [ ' 4 ' , ' 9 ' ] # allowed prefixes of addresses
2014-12-21 18:50:24 +00:00
withdrawal_fee = 10000000000
min_withdraw_amount = 2 * withdrawal_fee
withdraw_disabled = False
2014-12-23 11:14:35 +00:00
disable_withdraw_on_error = True
2014-12-22 21:52:37 +00:00
web_wallet_url = " https://mymonero.com/ " # None is there's none
2014-12-21 18:50:24 +00:00
2014-12-22 13:38:48 +00:00
admins = [ " moneromooo " , " moneromoo " ]
2014-12-22 20:48:11 +00:00
# list of nicks to ignore for rains - bots, trolls, etc
no_rain_to_nicks = [ ]
2014-12-21 18:50:24 +00:00
userstable = dict ( )
2014-12-25 20:43:45 +00:00
registered_users = set ( )
2014-12-21 18:50:24 +00:00
calltable = dict ( )
last_wallet_update_time = None
last_ping_time = time . time ( )
def log ( stype , msg ) :
2014-12-24 18:49:05 +00:00
header = " %s \t %s \t " % ( time . ctime ( time . time ( ) ) , stype )
print " %s %s " % ( header , str ( msg ) . replace ( " \n " , " \n " + header ) )
2014-12-21 18:50:24 +00:00
def log_error ( msg ) :
log ( " ERROR " , msg )
def log_warn ( msg ) :
log ( " WARNING " , msg )
def log_info ( msg ) :
log ( " INFO " , msg )
def log_log ( msg ) :
log ( " LOG " , msg )
def log_IRCRECV ( msg ) :
log ( " IRCRECV " , msg )
2014-12-25 22:03:51 +00:00
def log_IRCSEND ( msg ) :
log ( " IRCSEND " , msg )
def SendIRC ( msg ) :
log_IRCSEND ( msg )
irc . send ( msg + ' \r \n ' )
2014-12-21 18:50:24 +00:00
def connect_to_irc ( network , port ) :
global irc
try :
irc = socket . socket ( socket . AF_INET , socket . SOCK_STREAM )
irc . connect ( ( network , port ) )
except Exception , e :
log_error ( ' Error initializing IRC: %s ' % str ( e ) )
exit ( )
log_IRCRECV ( irc . recv ( 4096 ) )
2014-12-25 22:03:51 +00:00
SendIRC ( ' PASS ********* ' )
SendIRC ( ' NICK %s ' % tipbot_name )
SendIRC ( ' USER %s %s %s : %s ' % ( tipbot_name , tipbot_name , tipbot_name , tipbot_name ) )
2014-12-21 18:50:24 +00:00
def connect_to_redis ( host , port ) :
try :
2014-12-22 13:30:59 +00:00
return redis . Redis ( host = host , port = port )
2014-12-21 18:50:24 +00:00
except Exception , e :
log_error ( ' Error initializing redis: %s ' % str ( e ) )
exit ( )
2014-12-09 10:00:19 +00:00
def GetHost ( host ) : # Return Host
host = host . split ( ' @ ' ) [ 1 ]
host = host . split ( ' ' ) [ 0 ]
return host
def GetChannel ( data ) : # Return Channel
channel = data . split ( ' # ' ) [ 1 ]
channel = channel . split ( ' : ' ) [ 0 ]
channel = ' # ' + channel
channel = channel . strip ( ' \t \n \r ' )
return channel
def GetNick ( data ) : # Return Nickname
nick = data . split ( ' ! ' ) [ 0 ]
nick = nick . replace ( ' : ' , ' ' )
nick = nick . replace ( ' ' , ' ' )
nick = nick . strip ( ' \t \n \r ' )
return nick
2014-12-21 18:50:24 +00:00
def GetPassword ( ) :
try :
f = open ( ' tipbot-password.txt ' , ' r ' )
for p in f :
p = p . strip ( " \r \n " )
f . close ( )
return p
except Exception , e :
log_error ( ' could not fetch password: %s ' % str ( e ) )
raise
return " xxx "
2014-12-09 10:00:19 +00:00
def Send ( msg ) :
2014-12-25 22:03:51 +00:00
SendIRC ( ' PRIVMSG ' + irc_homechan + ' : ' + msg )
2014-12-09 10:00:19 +00:00
def SendTo ( where , msg ) :
2014-12-25 22:03:51 +00:00
SendIRC ( ' PRIVMSG ' + where + ' : ' + msg )
2014-12-09 10:00:19 +00:00
def Join ( chan ) :
2014-12-25 22:03:51 +00:00
SendIRC ( ' JOIN ' + chan )
2014-12-09 10:00:19 +00:00
def Part ( chan ) :
2014-12-25 22:03:51 +00:00
SendIRC ( ' PART ' + chan )
2014-12-09 10:00:19 +00:00
2014-12-21 18:50:24 +00:00
def Who ( chan ) :
2014-12-25 22:03:51 +00:00
SendIRC ( ' WHO ' + chan )
2014-12-21 18:50:24 +00:00
2014-12-26 17:13:26 +00:00
def IsParamPresent ( parms , idx ) :
return len ( parms ) > idx
def GetParam ( parms , idx ) :
if IsParamPresent ( parms , idx ) :
return parms [ idx ]
return None
2014-12-09 10:00:19 +00:00
def CheckRegistered ( nick , ifyes , yesdata , ifno , nodata ) :
if nick not in calltable :
calltable [ nick ] = [ ]
calltable [ nick ] . append ( [ ifyes , yesdata , ifno , nodata ] )
2014-12-25 20:43:45 +00:00
if nick in registered_users :
PerformNextAction ( nick , True )
else :
SendTo ( ' nickserv ' , " ACC " + nick )
2014-12-21 18:50:24 +00:00
def IsAdmin ( nick ) :
2014-12-22 13:38:48 +00:00
return nick in admins
2014-12-09 10:00:19 +00:00
def CheckAdmin ( nick , ifyes , yesdata , ifno , nodata ) :
2014-12-21 18:50:24 +00:00
if not IsAdmin ( nick ) :
log_warn ( ' CheckAdmin: nick %s is not admin, cannot call %s with %s ' % ( str ( nick ) , str ( ifyes ) , str ( yesdata ) ) )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " Access denied " )
return
CheckRegistered ( nick , ifyes , yesdata , ifno , nodata )
def PerformNextAction ( nick , registered ) :
2014-12-25 20:43:45 +00:00
if registered :
registered_users . add ( nick )
else :
registered_users . discard ( nick )
2014-12-09 10:00:19 +00:00
if nick not in calltable :
2014-12-21 18:50:24 +00:00
log_error ( ' Nothing in queue for %s ' % nick )
2014-12-09 10:00:19 +00:00
return
try :
if registered :
calltable [ nick ] [ 0 ] [ 0 ] ( nick , calltable [ nick ] [ 0 ] [ 1 ] )
else :
calltable [ nick ] [ 0 ] [ 2 ] ( nick , calltable [ nick ] [ 0 ] [ 3 ] )
del calltable [ nick ] [ 0 ]
except Exception , e :
2014-12-21 18:50:24 +00:00
log_error ( ' PerformNextAction: Exception in action, continuing: %s ' % str ( e ) )
2014-12-09 10:00:19 +00:00
del calltable [ nick ] [ 0 ]
def GetPaymentID ( nick ) :
salt = " 2u3g55bkwrui32fi3g4bGR$j5g4ugnujb " ;
p = hashlib . sha256 ( salt + nick ) . hexdigest ( ) ;
2014-12-21 18:50:24 +00:00
try :
redis . hset ( " paymentid " , p , nick )
except Exception , e :
log_error ( ' GetPaymentID: failed to set payment ID for %s to redis: %s ' % ( nick , str ( e ) ) )
2014-12-09 10:00:19 +00:00
return p
2014-12-21 18:50:24 +00:00
def GetTipbotAddress ( ) :
try :
j = SendWalletJSONRPCCommand ( " getaddress " , None )
if not " result " in j :
log_error ( ' GetTipbotAddress: No result found in getaddress reply ' )
return ERROR
result = j [ " result " ]
if not " address " in result :
log_error ( ' GetTipbotAddress: No address found in getaddress reply ' )
return ERROR
return result [ " address " ]
except Exception , e :
log_error ( " GetTipbotAddress: Error retrieving tipbot address: %s " % str ( e ) )
return " ERROR "
2014-12-09 10:00:19 +00:00
def GetNickFromPaymendID ( p ) :
nick = redis . hget ( " paymentid " , p )
2014-12-21 18:50:24 +00:00
log_log ( ' PaymendID %s => %s ' % ( p , str ( nick ) ) )
2014-12-09 10:00:19 +00:00
return nick
def AmountToString ( amount ) :
if amount == None :
amount = 0
lamount = long ( amount )
2014-12-23 09:28:37 +00:00
samount = None
if lamount == 0 :
samount = " 0 %s " % coin_name
2014-12-09 10:00:19 +00:00
else :
2014-12-23 09:28:37 +00:00
for den in coin_denominations :
if lamount < den [ 0 ] :
samount = " %.16g %s " % ( float ( lamount ) / den [ 1 ] , den [ 2 ] )
break
if not samount :
2014-12-22 21:52:37 +00:00
samount = " %.16g %s " % ( float ( lamount ) / coin , coin_name )
2014-12-22 14:25:09 +00:00
log_log ( " AmountToString: %s -> %s " % ( str ( amount ) , samount ) )
2014-12-09 10:00:19 +00:00
return samount
def GetBalance ( nick , data ) :
2014-12-21 18:50:24 +00:00
log_log ( " GetBalance: checking %s " % nick )
sendto = data [ 0 ]
2014-12-09 10:00:19 +00:00
try :
balance = redis . hget ( " balances " , nick )
if balance == None :
balance = 0
sbalance = AmountToString ( balance )
2014-12-21 18:50:24 +00:00
SendTo ( sendto , " %s ' s balance is %s " % ( nick , sbalance ) )
2014-12-09 10:00:19 +00:00
except Exception , e :
2014-12-21 18:50:24 +00:00
log_error ( ' GetBalance: exception: %s ' % str ( e ) )
SendTo ( sendto , " An error has occured " )
2014-12-09 10:00:19 +00:00
def AddBalance ( nick , data ) :
amount = data
2014-12-21 18:50:24 +00:00
log_info ( " AddBalance: Adding %s to %s ' s balance " % ( AmountToString ( amount ) , nick ) )
2014-12-09 10:00:19 +00:00
try :
balance = redis . hincrby ( " balances " , nick , amount )
except Exception , e :
2014-12-21 18:50:24 +00:00
log_error ( ' AddBalance: exception: %s ' % str ( e ) )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " An error has occured " )
def Tip ( nick , data ) :
2014-12-21 18:50:24 +00:00
sendto = data [ 0 ]
who = data [ 1 ]
2014-12-09 10:00:19 +00:00
try :
2014-12-21 18:50:24 +00:00
amount = float ( data [ 2 ] )
2014-12-09 10:00:19 +00:00
except Exception , e :
2014-12-21 18:50:24 +00:00
SendTo ( sendto , " Usage: tip nick amount " )
2014-12-09 10:00:19 +00:00
return
2014-12-25 20:43:26 +00:00
units = long ( amount * coin )
if units < = 0 :
SendTo ( sendto , " Invalid amount " )
return
2014-12-09 10:00:19 +00:00
2014-12-25 20:43:26 +00:00
log_info ( " Tip: %s wants to tip %s %s " % ( nick , who , AmountToString ( units ) ) )
2014-12-09 10:00:19 +00:00
try :
balance = redis . hget ( " balances " , nick )
if balance == None :
balance = 0
balance = long ( balance )
if units > balance :
2014-12-22 20:46:58 +00:00
SendTo ( sendto , " You only have %s " % ( AmountToString ( balance ) ) )
2014-12-09 10:00:19 +00:00
return
2014-12-21 18:50:24 +00:00
log_info ( ' Tip: %s tipping %s %u units, with balance %u ' % ( nick , who , units , balance ) )
2014-12-09 10:00:19 +00:00
try :
p = redis . pipeline ( )
p . hincrby ( " balances " , nick , - units ) ;
p . hincrby ( " balances " , who , units )
p . execute ( )
2014-12-22 14:25:09 +00:00
SendTo ( sendto , " %s has tipped %s %s " % ( nick , who , AmountToString ( units ) ) )
2014-12-09 10:00:19 +00:00
except Exception , e :
2014-12-21 18:50:24 +00:00
SendTo ( sendto , " An error occured " )
return
except Exception , e :
log_error ( ' Tip: exception: %s ' % str ( e ) )
SendTo ( sendto , " An error has occured " )
def ScanWho ( nick , data ) :
chan = data [ 0 ]
2014-12-26 16:57:03 +00:00
userstable [ chan ] = dict ( )
2014-12-21 18:50:24 +00:00
Who ( chan )
def Rain ( nick , data ) :
chan = data [ 0 ]
try :
amount = float ( data [ 1 ] )
except Exception , e :
SendTo ( sendto , " Usage: rain amount [users] " )
return
2014-12-26 17:13:26 +00:00
users = GetParam ( data , 2 )
if users :
try :
users = long ( users )
except Exception , e :
SendTo ( sendto , " Usage: rain amount [users] " )
return
2014-12-21 18:50:24 +00:00
if amount < = 0 :
SendTo ( sendto , " Usage: rain amount [users] " )
return
if users != None and users < = 0 :
SendTo ( sendto , " Usage: rain amount [users] " )
return
2014-12-22 21:52:37 +00:00
units = long ( amount * coin )
2014-12-21 18:50:24 +00:00
try :
balance = redis . hget ( " balances " , nick )
if balance == None :
balance = 0
balance = long ( balance )
if units > balance :
SendTo ( sendto , " You only have %s " % ( AmountToString ( balance ) ) )
2014-12-09 10:00:19 +00:00
return
2014-12-21 18:50:24 +00:00
2014-12-26 16:57:03 +00:00
userlist = userstable [ chan ] . keys ( )
2014-12-21 18:50:24 +00:00
userlist . remove ( nick )
2014-12-22 20:48:11 +00:00
for n in no_rain_to_nicks :
userlist . remove ( n )
2014-12-21 18:50:24 +00:00
if users == None or users > len ( userlist ) :
users = len ( userlist )
everyone = True
else :
everyone = False
2014-12-22 20:50:47 +00:00
if users == 0 :
SendTo ( sendto , " Nobody eligible for rain " )
return
2014-12-21 18:50:24 +00:00
if units < users :
2014-12-23 09:28:37 +00:00
SendTo ( sendto , " This would mean not even an atomic unit per nick " )
2014-12-21 18:50:24 +00:00
return
log_info ( " %s wants to rain %s on %s users in %s " % ( nick , AmountToString ( units ) , users , chan ) )
log_log ( " users in %s : %s " % ( chan , str ( userlist ) ) )
random . shuffle ( userlist )
userlist = userlist [ 0 : users ]
log_log ( " selected users in %s : %s " % ( chan , userlist ) )
user_units = long ( units / users )
if everyone :
msg = " %s rained %s on everyone in the channel " % ( nick , AmountToString ( user_units ) )
else :
msg = " %s rained %s on: " % ( nick , AmountToString ( user_units ) )
pipe = redis . pipeline ( )
pipe . hincrby ( " balances " , nick , - units )
for user in userlist :
pipe . hincrby ( " balances " , user , user_units )
if not everyone :
msg = msg + " " + user
pipe . execute ( )
SendTo ( sendto , " %s " % msg )
except Exception , e :
log_error ( ' Rain: exception: %s ' % str ( e ) )
SendTo ( sendto , " An error has occured " )
return
2014-12-27 19:31:54 +00:00
def RainActive ( nick , data ) :
chan = data [ 0 ]
amount = GetParam ( data , 1 )
hours = GetParam ( data , 2 )
minfrac = GetParam ( data , 3 )
try :
amount = float ( amount )
if amount < = 0 :
raise RuntimeError ( " " )
except Exception , e :
SendTo ( sendto , " Invalid amount " )
return
try :
hours = float ( hours )
if hours < = 0 :
raise RuntimeError ( " " )
except Exception , e :
SendTo ( sendto , " Invalid hours " )
return
if minfrac :
try :
minfrac = float ( minfrac )
if minfrac < 0 or minfrac > 1 :
raise RuntimeError ( " " )
except Exception , e :
SendTo ( sendto , " minfrac must be a number between 0 and 1 " )
return
else :
minfrac = 0
units = long ( amount * coin )
try :
balance = redis . hget ( " balances " , nick )
if balance == None :
balance = 0
balance = long ( balance )
if units > balance :
SendTo ( sendto , " You only have %s " % ( AmountToString ( balance ) ) )
return
now = time . time ( )
userlist = userstable [ chan ] . keys ( )
userlist . remove ( nick )
for n in no_rain_to_nicks :
userlist . remove ( n )
weights = dict ( )
weight = 0
for n in userlist :
t = userstable [ chan ] [ n ]
if t == None :
continue
dt = now - t
if dt < = hours * 3600 :
w = ( 1 * ( hours * 3600 - dt ) + minfrac * ( 1 - ( hours * 3600 - dt ) ) ) / ( hours * 3600 )
weights [ n ] = w
weight + = w
if len ( weights ) == 0 :
SendTo ( sendto , " Nobody eligible for rain " )
return
# if units < users:
# SendTo(sendto, "This would mean not even an atomic unit per nick")
# return
pipe = redis . pipeline ( )
pipe . hincrby ( " balances " , nick , - units )
rained_units = 0
nnicks = 0
minu = None
maxu = None
for n in weights :
user_units = long ( units * weights [ n ] / weight )
if user_units < = 0 :
continue
log_info ( " %s rained %s on %s (last active %f hours ago) " % ( nick , AmountToString ( user_units ) , n , GetTimeSinceActive ( chan , n ) / 3600 ) )
pipe . hincrby ( " balances " , n , user_units )
rained_units + = user_units
if not minu or user_units < minu :
minu = user_units
if not maxu or user_units > maxu :
maxu = user_units
nnicks = nnicks + 1
if maxu == None :
SendTo ( sendto , " This would mean not even an atomic unit per nick " )
return
pipe . execute ( )
log_info ( " %s rained %s - %s (total %s , acc %s ) on the %d nicks active in the last %f hours " % ( nick , AmountToString ( minu ) , AmountToString ( maxu ) , AmountToString ( units ) , AmountToString ( rained_units ) , nnicks , hours ) )
SendTo ( sendto , " %s rained %s - %s on the %d nicks active in the last %f hours " % ( nick , AmountToString ( minu ) , AmountToString ( maxu ) , nnicks , hours ) )
except Exception , e :
log_error ( ' Rain: exception: %s ' % str ( e ) )
SendTo ( sendto , " An error has occured " )
return
2014-12-23 11:14:35 +00:00
def DisableWithdraw ( nick , data ) :
2014-12-22 16:39:20 +00:00
global withdraw_disabled
2014-12-23 11:14:35 +00:00
if nick :
log_warn ( ' DisableWithdraw: disabled by %s ' % nick )
else :
log_warn ( ' DisableWithdraw: disabled ' )
2014-12-21 18:50:24 +00:00
withdraw_disabled = True
2014-12-23 11:14:35 +00:00
def EnableWithdraw ( nick , data ) :
global withdraw_disabled
log_info ( ' EnableWithdraw: enabled by %s ' % nick )
withdraw_disabled = False
def CheckDisableWithdraw ( ) :
if disable_withdraw_on_error :
DisableWithdraw ( None , None )
2014-12-26 12:16:08 +00:00
def IsValidAddress ( address ) :
if len ( address ) < address_length [ 0 ] or len ( address ) > address_length [ 1 ] :
return False
for prefix in address_prefix :
if address . startswith ( prefix ) :
return True
return False
2014-12-21 18:50:24 +00:00
def Withdraw ( nick , data ) :
address = data [ 0 ]
2014-12-26 12:16:08 +00:00
if not IsValidAddress ( address ) :
2014-12-21 18:50:24 +00:00
SendTo ( nick , " Invalid address " )
return
2014-12-26 17:13:26 +00:00
amount = GetParam ( data , 1 )
2014-12-26 12:01:26 +00:00
if amount :
try :
famount = float ( amount )
if ( famount < 0 ) :
raise RuntimeError ( " " )
amount = long ( famount * coin )
amount + = withdrawal_fee
except Exception , e :
SendTo ( nick , " Invalid amount " )
return
2014-12-21 18:50:24 +00:00
if min_withdraw_amount < = 0 or withdrawal_fee < = 0 or min_withdraw_amount < withdrawal_fee :
log_error ( ' Withdraw: Inconsistent withdrawal settings ' )
SendTo ( nick , " An error has occured " )
return
2014-12-26 12:01:26 +00:00
log_info ( " Withdraw: %s wants to withdraw %s to %s " % ( nick , AmountToString ( amount ) if amount else " all " , address ) )
2014-12-21 18:50:24 +00:00
if withdraw_disabled :
log_error ( ' Withdraw: disabled ' )
SendTo ( nick , " Sorry, withdrawal is disabled due to a wallet error which requires admin assistance " )
return
try :
balance = redis . hget ( " balances " , nick )
if balance == None :
balance = 0
balance = long ( balance )
2014-12-09 10:00:19 +00:00
except Exception , e :
2014-12-21 18:50:24 +00:00
log_error ( ' Withdraw: exception: %s ' % str ( e ) )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " An error has occured " )
2014-12-21 18:50:24 +00:00
return
2014-12-26 12:01:26 +00:00
if amount :
if amount > balance :
log_info ( " Withdraw: %s trying to withdraw %s , but only has %s " % ( nick , AmountToString ( amount ) , AmountToString ( balance ) ) )
SendTo ( nick , " You only have %s " % AmountToString ( balance ) )
return
else :
amount = balance
if amount < = 0 or amount < min_withdraw_amount :
log_info ( " Withdraw: Minimum withdrawal balance: %s , %s cannot withdraw %s " % ( AmountToString ( min_withdraw_amount ) , nick , AmountToString ( amount ) ) )
SendTo ( nick , " Minimum withdrawal balance: %s , cannot withdraw %s " % ( AmountToString ( min_withdraw_amount ) , AmountToString ( amount ) ) )
2014-12-21 18:50:24 +00:00
return
try :
fee = long ( withdrawal_fee )
2014-12-26 12:01:26 +00:00
topay = long ( amount - fee )
2014-12-21 18:50:24 +00:00
log_info ( ' Withdraw: Raw: fee: %s , to pay: %s ' % ( str ( fee ) , str ( topay ) ) )
log_info ( ' Withdraw: fee: %s , to pay: %s ' % ( AmountToString ( fee ) , AmountToString ( topay ) ) )
params = {
' destinations ' : [ { ' address ' : address , ' amount ' : topay } ] ,
' payment_id ' : GetPaymentID ( nick ) ,
' fee ' : fee ,
' mixin ' : 0 ,
' unlock_time ' : 0 ,
}
j = SendWalletJSONRPCCommand ( " transfer " , params )
except Exception , e :
log_error ( ' Withdraw: Error in transfer: %s ' % str ( e ) )
2014-12-23 11:14:35 +00:00
CheckDisableWithdraw ( )
2014-12-21 18:50:24 +00:00
SendTo ( nick , " An error has occured " )
return
if not " result " in j :
log_error ( ' Withdraw: No result in transfer reply ' )
2014-12-23 11:14:35 +00:00
CheckDisableWithdraw ( )
2014-12-21 18:50:24 +00:00
SendTo ( nick , " An error has occured " )
return
result = j [ " result " ]
if not " tx_hash " in result :
log_error ( ' Withdraw: No tx_hash in transfer reply ' )
2014-12-23 11:14:35 +00:00
CheckDisableWithdraw ( )
2014-12-21 18:50:24 +00:00
SendTo ( nick , " An error has occured " )
return
tx_hash = result [ " tx_hash " ]
2014-12-26 12:01:26 +00:00
log_info ( ' %s has withdrawn %s , tx hash %s ' % ( nick , amount , str ( tx_hash ) ) )
SendTo ( nick , " Tx sent: %s " % tx_hash )
2014-12-21 18:50:24 +00:00
try :
2014-12-26 12:01:26 +00:00
redis . hincrby ( " balances " , nick , - amount )
2014-12-21 18:50:24 +00:00
except Exception , e :
log_error ( ' Withdraw: FAILED TO SUBTRACT BALANCE: exception: %s ' % str ( e ) )
2014-12-23 11:14:35 +00:00
CheckDisableWithdraw ( )
2014-12-21 18:50:24 +00:00
2014-12-09 10:00:19 +00:00
def SendJSONRPCCommand ( host , port , method , params ) :
try :
http = httplib . HTTPConnection ( host , port )
except Exception , e :
2014-12-21 18:50:24 +00:00
log_error ( ' SendJSONRPCCommand: Error connecting to %s : %u : %s ' % ( host , port , str ( e ) ) )
2014-12-09 10:00:19 +00:00
raise
d = dict ( id = " 0 " , jsonrpc = " 2.0 " , method = method , params = params )
try :
j = json . dumps ( d ) . encode ( )
except Exception , e :
2014-12-21 18:50:24 +00:00
log_error ( ' SendJSONRPCCommand: Failed to encode JSON: %s ' % str ( e ) )
2014-12-09 10:00:19 +00:00
http . close ( )
raise
2014-12-21 18:50:24 +00:00
log_log ( ' SendJSONRPCCommand: Sending json as body: %s ' % j )
2014-12-09 10:00:19 +00:00
headers = None
try :
http . request ( " POST " , " /json_rpc " , body = j )
except Exception , e :
2014-12-21 18:50:24 +00:00
log_error ( ' SendJSONRPCCommand: Failed to post request: %s ' % str ( e ) )
2014-12-09 10:00:19 +00:00
http . close ( )
raise
response = http . getresponse ( )
2014-12-21 18:50:24 +00:00
log_log ( ' SendJSONRPCCommand: Received reply status: %s ' % response . status )
2014-12-09 10:00:19 +00:00
if response . status != 200 :
2014-12-21 18:50:24 +00:00
log_error ( ' SendJSONRPCCommand: Error, not 200: %s ' % str ( response . status ) )
2014-12-09 10:00:19 +00:00
http . close ( )
raise RuntimeError ( " Error " + response . status )
s = response . read ( )
2014-12-21 18:50:24 +00:00
log_log ( ' SendJSONRPCCommand: Received reply: %s ' % str ( s ) )
2014-12-09 10:00:19 +00:00
try :
j = json . loads ( s )
except Exception , e :
2014-12-21 18:50:24 +00:00
log_error ( ' SendJSONRPCCommand: Failed to decode JSON: %s ' % str ( e ) )
2014-12-09 10:00:19 +00:00
http . close ( )
raise
http . close ( )
return j
def SendHTMLCommand ( host , port , method ) :
try :
http = httplib . HTTPConnection ( host , port )
except Exception , e :
2014-12-21 18:50:24 +00:00
log_error ( ' SendHTMLCommand: Error connecting to %s : %u : %s ' % ( host , port , str ( e ) ) )
2014-12-09 10:00:19 +00:00
raise
headers = None
try :
http . request ( " POST " , " / " + method )
except Exception , e :
2014-12-21 18:50:24 +00:00
log_error ( ' SendHTMLCommand: Failed to post request: %s ' % str ( e ) )
2014-12-09 10:00:19 +00:00
http . close ( )
raise
response = http . getresponse ( )
2014-12-21 18:50:24 +00:00
log_log ( ' SendHTMLCommand: Received reply status: %s ' % response . status )
2014-12-09 10:00:19 +00:00
if response . status != 200 :
2014-12-21 18:50:24 +00:00
log_error ( ' SendHTMLCommand: Error, not 200: %s ' % str ( response . status ) )
2014-12-09 10:00:19 +00:00
http . close ( )
raise RuntimeError ( " Error " + response . status )
s = response . read ( )
2014-12-21 18:50:24 +00:00
log_log ( ' SendHTMLCommand: Received reply: %s ' % s )
2014-12-09 10:00:19 +00:00
try :
j = json . loads ( s )
except Exception , e :
2014-12-21 18:50:24 +00:00
log_error ( ' SendHTMLCommand: Failed to decode JSON: %s ' % str ( e ) )
2014-12-09 10:00:19 +00:00
http . close ( )
raise
http . close ( )
return j
def SendWalletJSONRPCCommand ( method , params ) :
return SendJSONRPCCommand ( wallet_host , wallet_port , method , params )
def SendBitmonerodJSONRPCCommand ( method , params ) :
return SendJSONRPCCommand ( bitmonerod_host , bitmonerod_port , method , params )
def SendBitmonerodHTMLCommand ( method ) :
return SendHTMLCommand ( bitmonerod_host , bitmonerod_port , method )
def GetHeight ( nick , data ) :
2014-12-21 18:50:24 +00:00
log_info ( ' GetHeight: %s wants to know block height ' % nick )
2014-12-09 10:00:19 +00:00
try :
j = SendBitmonerodHTMLCommand ( " getheight " )
except Exception , e :
2014-12-21 18:50:24 +00:00
log_error ( ' GetHeight: error: %s ' % str ( e ) )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " An error has occured " )
return
2014-12-21 18:50:24 +00:00
log_log ( ' GetHeight: Got reply: %s ' % str ( j ) )
2014-12-09 10:00:19 +00:00
if not " height " in j :
2014-12-21 18:50:24 +00:00
log_error ( ' GetHeight: Cannot see height in here ' )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " Height not found " )
return
2014-12-21 18:50:24 +00:00
height = j [ " height " ]
log_info ( ' GetHeight: geight is %s ' % str ( height ) )
SendTo ( nick , " Height: %s " % str ( height ) )
2014-12-09 10:00:19 +00:00
def GetTipbotBalance ( nick , data ) :
2014-12-21 18:50:24 +00:00
log_info ( ' %s wants to know the tipbot balance ' % nick )
2014-12-09 10:00:19 +00:00
try :
j = SendWalletJSONRPCCommand ( " getbalance " , None )
except Exception , e :
SendTo ( nick , " An error has occured " )
return
if not " result " in j :
2014-12-21 18:50:24 +00:00
log_error ( ' GetTipbotBalance: result not found in reply ' )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " An error has occured " )
return
result = j [ " result " ]
if not " balance " in result :
2014-12-21 18:50:24 +00:00
log_error ( ' GetTipbotBalance: balance not found in result ' )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " An error has occured " )
return
if not " unlocked_balance " in result :
2014-12-21 18:50:24 +00:00
log_error ( ' GetTipbotBalance: unlocked_balance not found in result ' )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " An error has occured " )
return
balance = result [ " balance " ]
unlocked_balance = result [ " unlocked_balance " ]
2014-12-21 18:50:24 +00:00
log_log ( ' GetTipbotBalance: balance: %s ' % str ( balance ) )
log_log ( ' GetTipbotBalance: unlocked_balance: %s ' % str ( unlocked_balance ) )
2014-12-09 10:00:19 +00:00
pending = long ( balance ) - long ( unlocked_balance )
if pending < 0 :
2014-12-21 18:50:24 +00:00
log_error ( ' GetTipbotBalance: Negative pending balance! balance %s , unlocked %s ' % ( str ( balance ) , str ( unlocked ) ) )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " An error has occured " )
return
if pending == 0 :
2014-12-21 18:50:24 +00:00
log_info ( " GetTipbotBalance: Tipbot balance: %s " % AmountToString ( balance ) )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " Tipbot balance: %s " % AmountToString ( balance ) )
else :
2014-12-21 18:50:24 +00:00
log_info ( " GetTipbotBalance: Tipbot balance: %s ( %s pending) " % ( AmountToString ( unlocked_balance ) , AmountToString ( pending ) ) )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " Tipbot balance: %s ( %s pending) " % ( AmountToString ( unlocked_balance ) , AmountToString ( pending ) ) )
2014-12-22 13:30:59 +00:00
def DumpUsers ( nick , data ) :
log_info ( str ( userstable ) )
2014-12-09 10:00:19 +00:00
def Help ( nick ) :
2014-12-22 14:25:09 +00:00
time . sleep ( 0.5 )
2014-12-22 21:52:37 +00:00
SendTo ( nick , " Help for %s : " % tipbot_name )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " !isregistered - show whether you are currently registered with freenode " )
SendTo ( nick , " !balance - show your current balance " )
2014-12-23 11:16:22 +00:00
time . sleep ( 0.5 )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " !tip <nick> <amount> - tip another user " )
2014-12-22 21:52:37 +00:00
SendTo ( nick , " !rain <amount> [<users>] - rain some %s on everyone (or just a few) " % coin_name )
2014-12-27 19:31:54 +00:00
SendTo ( nick , " !rainactive <amount> <hours> [minfrac]- rain some %s on who was active recently " % coin_name )
2014-12-26 12:01:26 +00:00
SendTo ( nick , " !withdraw <address> [<amount>] - withdraw part or all of your balance " )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " !info - information about the tipbot " )
2014-12-22 14:25:09 +00:00
time . sleep ( 0.5 )
2014-12-22 21:52:37 +00:00
SendTo ( nick , " You can send %s to your tipbot account: " % coin_name ) ;
2014-12-21 18:50:24 +00:00
SendTo ( nick , " Address: %s " % GetTipbotAddress ( ) )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " Payment ID: %s " % GetPaymentID ( nick ) )
SendTo ( nick , " NO WARRANTY, YOU MAY LOSE YOUR COINS " )
2014-12-22 14:25:09 +00:00
time . sleep ( 0.5 )
2014-12-21 18:50:24 +00:00
SendTo ( nick , " Minimum withdrawal: %s " % AmountToString ( min_withdraw_amount ) )
SendTo ( nick , " Withdrawal fee: %s " % AmountToString ( withdrawal_fee ) )
2014-12-22 21:52:37 +00:00
if web_wallet_url :
2014-12-23 11:16:22 +00:00
time . sleep ( 0.5 )
2014-12-22 21:52:37 +00:00
SendTo ( nick , " No %s address ? You can use %s " % ( coin_name , web_wallet_url ) )
2014-12-09 10:00:19 +00:00
def Info ( nick ) :
2014-12-22 14:25:09 +00:00
time . sleep ( 0.5 )
2014-12-22 21:52:37 +00:00
SendTo ( nick , " Info for %s : " % tipbot_name )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " Type !help for a list of commands " )
SendTo ( nick , " NO WARRANTY, YOU MAY LOSE YOUR COINS " )
2014-12-22 14:25:09 +00:00
time . sleep ( 0.5 )
2014-12-22 21:52:37 +00:00
SendTo ( nick , " By sending your %s to the tipbot, you are giving up their control " % coin_name )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " to whoever runs the tipbot. Any tip you make/receive using the tipbot " )
SendTo ( nick , " is obviously not anonymous. The tipbot wallet may end up corrupt, or be " )
SendTo ( nick , " stolen, the server compromised, etc. While I hope this won ' t be the case, " )
2014-12-23 11:16:22 +00:00
time . sleep ( 0.5 )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " I will not offer any warranty whatsoever for the use of the tipbot or the " )
2014-12-22 21:52:37 +00:00
SendTo ( nick , " return of any %s . Use at your own risk. " % coin_name )
2014-12-09 10:00:19 +00:00
SendTo ( nick , " That being said, I hope you enjoy using it :) " )
2014-12-22 13:30:59 +00:00
def InitScanBlockHeight ( ) :
try :
scan_block_height = redis . get ( " scan_block_height " )
scan_block_height = long ( scan_block_height )
except Exception , e :
try :
redis . set ( " scan_block_height " , 0 )
except Exception , e :
log_error ( ' Failed to initialize scan_block_height: %s ' % str ( e ) )
2014-12-21 18:50:24 +00:00
def UpdateCoin ( ) :
global last_wallet_update_time
if last_wallet_update_time == None :
last_wallet_update_time = 0
t = time . time ( )
dt = t - last_wallet_update_time
if dt < wallet_update_time :
return
try :
try :
scan_block_height = redis . get ( " scan_block_height " )
scan_block_height = long ( scan_block_height )
except Exception , e :
log_error ( ' Failed to get scan_block_height: %s ' % str ( e ) )
last_wallet_update_time = time . time ( )
return
full_payment_ids = redis . hgetall ( " paymentid " )
#print 'Got full payment ids: %s' % str(full_payment_ids)
payment_ids = [ ]
for pid in full_payment_ids :
payment_ids . append ( pid )
#print 'Got payment ids: %s' % str(payment_ids)
params = {
" payment_ids " : payment_ids ,
" min_block_height " : scan_block_height
}
j = SendWalletJSONRPCCommand ( " get_bulk_payments " , params )
#print 'Got j: %s' % str(j)
if " result " in j :
result = j [ " result " ]
if " payments " in result :
payments = result [ " payments " ]
log_info ( ' UpdateCoin: Got %d payments ' % len ( payments ) )
for p in payments :
log_log ( ' UpdateCoin: Looking at payment %s ' % str ( p ) )
bh = p [ " block_height " ]
if bh > scan_block_height :
scan_block_height = bh
log_log ( ' UpdateCoin: seen payments up to block %d ' % scan_block_height )
try :
pipe = redis . pipeline ( )
pipe . set ( " scan_block_height " , scan_block_height )
log_log ( ' UpdateCoin: processing payments ' )
for p in payments :
payment_id = p [ " payment_id " ]
tx_hash = p [ " tx_hash " ]
amount = p [ " amount " ]
try :
recipient = GetNickFromPaymendID ( payment_id )
log_info ( ' UpdateCoin: Found payment %s to %s for %s ' % ( tx_hash , recipient , AmountToString ( amount ) ) )
pipe . hincrby ( " balances " , recipient , amount ) ;
except Exception , e :
log_error ( ' UpdateCoin: No nick found for payment id %s , tx hash %s , amount %s ' % ( payment_id , tx_hash , amount ) )
log_log ( ' UpdateCoin: Executing received payments pipeline ' )
pipe . execute ( )
except Exception , e :
log_error ( ' UpdateCoin: failed to set scan_block_height: %s ' % str ( e ) )
else :
log_log ( ' UpdateCoin: No payments in get_bulk_payments reply ' )
else :
log_error ( ' UpdateCoin: No results in get_bulk_payments reply ' )
except Exception , e :
log_error ( ' UpdateCoin: Failed to get bulk payments: %s ' % str ( e ) )
last_wallet_update_time = time . time ( )
2014-12-26 16:57:03 +00:00
def UpdateLastActiveTime ( chan , nick ) :
if not chan in userstable :
log_error ( " UpdateLastActiveTime: %s spoke in %s , but %s not found in users table " % ( nick , chan , chan ) )
userstable [ chan ] = dict ( )
if not nick in userstable [ chan ] :
log_error ( " UpdateLastActiveTime: %s spoke in %s , but was not found in that channel ' s users table " % ( nick , chan ) )
userstable [ chan ] [ nick ] = None
userstable [ chan ] [ nick ] = time . time ( )
def GetTimeSinceActive ( chan , nick ) :
if not chan in userstable :
log_error ( " GetTimeSinceActive: channel %s not found in users table " % chan )
return None
if not nick in userstable [ chan ] :
log_error ( " GetTimeSinceActive: %s not found in channel %s ' s users table " % ( nick , chan ) )
return None
t = userstable [ chan ] [ nick ]
if t == None :
return None
dt = time . time ( ) - t
if dt < 0 :
log_error ( " GetTimeSinceActive: %s active in %s in the future " % ( nick , chan ) )
return None
return dt
def GetActiveNicks ( chan , seconds ) :
nicks = [ ]
if not chan in userstable :
return [ ]
now = time . time ( )
for nick in userstable [ chan ] :
t = userstable [ chan ] [ nick ]
if t == None :
continue
dt = now - t
if dt < 0 :
log_error ( " GetActiveNicks: %s active in %s in the future " % ( nick , chan ) )
continue
if dt < seconds :
nicks . append ( nick )
return nicks
def ShowActivity ( nick , data ) :
achan = data [ 0 ]
anick = data [ 1 ]
activity = GetTimeSinceActive ( achan , anick )
if activity :
SendTo ( nick , " %s was active in %s %f seconds ago " % ( anick , achan , activity ) )
else :
SendTo ( nick , " %s was never active in %s " % ( anick , achan ) )
2014-12-09 10:00:19 +00:00
#def Op(to_op, chan):
2014-12-25 22:03:51 +00:00
# SendIRC( 'MODE ' + chan + ' +o: ' + to_op)
2014-12-09 10:00:19 +00:00
#
#def DeOp(to_deop, chan):
2014-12-25 22:03:51 +00:00
# SendIRC( 'MODE ' + chan + ' -o: ' + to_deop)
2014-12-09 10:00:19 +00:00
#
#def Voice(to_v, chan):
2014-12-25 22:03:51 +00:00
# SendIRC( 'MODE ' + chan + ' +v: ' + to_v)
2014-12-09 10:00:19 +00:00
#
#def DeVoice(to_dv, chan):
2014-12-25 22:03:51 +00:00
# SendIRC( 'MODE ' + chan + ' -v: ' + to_dv)
2014-12-09 10:00:19 +00:00
#------------------------------------------------------------------------------#
buffered_data = " "
def getline ( s ) :
global buffered_data
idx = buffered_data . find ( " \n " )
if idx == - 1 :
2014-12-21 18:50:24 +00:00
try :
( r , w , x ) = select . select ( [ s . fileno ( ) ] , [ ] , [ ] , 1 )
if s . fileno ( ) in r :
newdata = s . recv ( 4096 , socket . MSG_DONTWAIT )
else :
newdata = None
if s . fileno ( ) in x :
log_error ( ' getline: IRC socket in exception set ' )
newdata = None
except Exception , e :
log_error ( ' getline: Exception: %s ' % str ( e ) )
2014-12-23 10:24:19 +00:00
# Broken pipe when we get kicked for spam
if str ( e ) . find ( " Broken pipe " ) != - 1 :
raise
2014-12-21 18:50:24 +00:00
newdata = None
if newdata == None :
return None
buffered_data + = newdata
2014-12-09 10:00:19 +00:00
idx = buffered_data . find ( " \n " )
if idx == - 1 :
ret = buffered_data
buffered_data = " "
return ret
ret = buffered_data [ 0 : idx + 1 ]
buffered_data = buffered_data [ idx + 1 : ]
return ret
2014-12-21 18:50:24 +00:00
connect_to_irc ( irc_network , irc_port )
2014-12-22 13:30:59 +00:00
redis = connect_to_redis ( redis_host , redis_port )
InitScanBlockHeight ( )
2014-12-21 18:50:24 +00:00
2014-12-09 10:00:19 +00:00
while True :
action = None
2014-12-23 10:24:19 +00:00
try :
data = getline ( irc )
except Exception , e :
log_warn ( ' Exception fron getline, we were probably disconnected, reconnecting in 5 seconds ' )
time . sleep ( 5 )
last_ping_time = time . time ( )
connect_to_irc ( irc_network , irc_port )
continue
2014-12-21 18:50:24 +00:00
# All that must be done even when nothing from IRC - data may be None here
UpdateCoin ( )
if data == None :
2014-12-22 21:52:37 +00:00
if time . time ( ) - last_ping_time > irc_timeout_seconds :
2014-12-23 10:24:19 +00:00
log_warn ( ' %s seconds without PING, reconnecting in 5 seconds ' % irc_timeout_seconds )
time . sleep ( 5 )
2014-12-21 18:50:24 +00:00
last_ping_time = time . time ( )
connect_to_irc ( irc_network , irc_port )
continue
2014-12-09 10:00:19 +00:00
data = data . strip ( " \r \n " )
2014-12-21 18:50:24 +00:00
log_IRCRECV ( data )
2014-12-09 10:00:19 +00:00
2014-12-22 13:30:59 +00:00
# consider any IRC data as a ping
last_ping_time = time . time ( )
2014-12-09 10:00:19 +00:00
if data . find ( ' Welcome to the freenode Internet Relay Chat Network ' ) != - 1 :
2014-12-25 20:22:29 +00:00
userstable = dict ( )
2014-12-25 20:43:45 +00:00
registered_users . clear ( )
2014-12-21 18:50:24 +00:00
SendTo ( " nickserv " , " IDENTIFY %s " % GetPassword ( ) )
Join ( irc_homechan )
#ScanWho(None,[irc_homechan])
2014-12-09 10:00:19 +00:00
2014-12-21 18:50:24 +00:00
if data . find ( ' PING ' ) == 0 :
log_log ( ' Got PING, replying PONG ' )
last_ping_time = time . time ( )
2014-12-25 22:03:51 +00:00
SendIRC ( ' PONG ' + data . split ( ) [ 1 ] )
2014-12-21 18:50:24 +00:00
continue
2014-12-09 10:00:19 +00:00
2014-12-23 10:24:19 +00:00
if data . find ( ' ERROR :Closing Link: ' ) == 0 :
log_warn ( ' We were kicked from IRC, reconnecting in 5 seconds ' )
time . sleep ( 5 )
last_ping_time = time . time ( )
connect_to_irc ( irc_network , irc_port )
continue
2014-12-09 10:00:19 +00:00
#--------------------------- Action check --------------------------------#
if data . find ( ' : ' ) == - 1 :
2014-12-21 18:50:24 +00:00
continue
2014-12-09 10:00:19 +00:00
try :
2014-12-22 13:30:59 +00:00
cparts = data . split ( ' : ' )
if len ( cparts ) < 2 :
2014-12-09 10:00:19 +00:00
continue
2014-12-22 13:30:59 +00:00
if len ( cparts ) > = 3 :
text = cparts [ 2 ]
2014-12-21 18:50:24 +00:00
else :
text = " "
2014-12-22 13:30:59 +00:00
parts = cparts [ 1 ] . split ( ' ' )
2014-12-09 10:00:19 +00:00
who = parts [ 0 ]
action = parts [ 1 ]
chan = parts [ 2 ]
except Exception , e :
2014-12-21 18:50:24 +00:00
log_error ( ' main parser: Exception, continuing: %s ' % str ( e ) )
2014-12-09 10:00:19 +00:00
continue
if action == None :
continue
2014-12-21 18:50:24 +00:00
#print 'text: ', text
#print 'who: ', who
#print 'action: ', action
#print 'chan: ', chan
2014-12-09 10:00:19 +00:00
# if data.find('#') != -1:
# action = data.split('#')[0]
# action = action.split(' ')[1]
# if data.find('NICK') != -1:
# if data.find('#') == -1:
# action = 'NICK'
#----------------------------- Actions -----------------------------------#
2014-12-21 18:50:24 +00:00
try :
if action == ' NOTICE ' :
2014-12-09 10:00:19 +00:00
if who == " NickServ!NickServ@services. " :
2014-12-21 18:50:24 +00:00
#if text.find('Information on ') != -1:
# ns_nick = text.split(' ')[2].strip("\002")
# print 'NickServ says %s is registered' % ns_nick
# PerformNextAction(ns_nick, True)
#elif text.find(' is not registered') != -1:
# ns_nick = text.split(' ')[0].strip("\002")
# print 'NickServ says %s is not registered' % ns_nick
# PerformNextAction(ns_nick, False)
if text . find ( ' ACC ' ) != - 1 :
stext = text . split ( ' ' )
ns_nick = stext [ 0 ]
ns_acc = stext [ 1 ]
ns_status = stext [ 2 ]
if ns_acc == " ACC " :
if ns_status == " 3 " :
log_info ( ' NickServ says %s is identified ' % ns_nick )
PerformNextAction ( ns_nick , True )
else :
log_info ( ' NickServ says %s is not identified ' % ns_nick )
PerformNextAction ( ns_nick , False )
else :
log_error ( ' ACC line not as expected... ' )
elif action == ' 352 ' :
try :
who_chan = parts [ 3 ]
who_chan_user = parts [ 7 ]
if not who_chan_user in userstable [ who_chan ] :
2014-12-26 16:57:03 +00:00
userstable [ who_chan ] [ who_chan_user ] = None
log_log ( " New list of users in %s : %s " % ( who_chan , str ( userstable [ who_chan ] . keys ( ) ) ) )
2014-12-21 18:50:24 +00:00
except Exception , e :
log_error ( ' Failed to parse " who " line: %s : %s ' % ( data , str ( e ) ) )
2014-12-22 13:30:59 +00:00
elif action == ' 353 ' :
try :
who_chan = parts [ 4 ]
who_chan_users = cparts [ 2 ] . split ( " " )
for who_chan_user in who_chan_users :
if not who_chan_user in userstable [ who_chan ] :
if who_chan_user [ 0 ] == " @ " :
who_chan_user = who_chan_user [ 1 : ]
2014-12-26 16:57:03 +00:00
userstable [ who_chan ] [ who_chan_user ] = None
log_log ( " New list of users in %s : %s " % ( who_chan , str ( userstable [ who_chan ] . keys ( ) ) ) )
2014-12-22 13:30:59 +00:00
except Exception , e :
log_error ( ' Failed to parse " who " line: %s : %s ' % ( data , str ( e ) ) )
2014-12-21 18:50:24 +00:00
elif action == ' PRIVMSG ' :
2014-12-26 16:57:03 +00:00
UpdateLastActiveTime ( chan , GetNick ( who ) )
2014-12-23 09:42:55 +00:00
exidx = text . find ( ' ! ' )
if exidx != - 1 and len ( text ) > exidx + 1 and text [ exidx + 1 ] in string . ascii_letters :
2014-12-09 10:00:19 +00:00
cmd = text . split ( ' ! ' ) [ 1 ]
cmd = cmd . split ( ' ' )
cmd [ 0 ] = cmd [ 0 ] . strip ( ' \t \n \r ' )
2014-12-21 18:50:24 +00:00
if chan [ 0 ] == ' # ' :
sendto = chan
else :
sendto = GetNick ( who )
log_log ( ' Found command: " %s " in channel " %s " , replying to %s ' % ( str ( cmd ) , str ( chan ) , sendto ) )
#if cmd[0] == 'join':
# Join('#' + cmd[1])
#elif cmd[0] == 'part':
# Part('#' + cmd[1])
if cmd [ 0 ] == ' help ' :
Help ( GetNick ( who ) )
2014-12-09 10:00:19 +00:00
elif cmd [ 0 ] == ' isregistered ' :
CheckRegistered ( GetNick ( who ) , SendTo , " You are registered " , SendTo , " You are not registered " )
elif cmd [ 0 ] == ' balance ' :
2014-12-21 18:50:24 +00:00
CheckRegistered ( GetNick ( who ) , GetBalance , [ sendto ] , SendTo , " You must be registered with Freenode to query balance " )
2014-12-09 10:00:19 +00:00
elif cmd [ 0 ] == ' tip ' :
if len ( cmd ) == 3 :
2014-12-26 17:13:26 +00:00
parms = [ sendto ]
parms . extend ( cmd [ 1 : ] )
CheckRegistered ( GetNick ( who ) , Tip , parms , SendTo , " You must be registered with Freenode to tip " )
2014-12-09 10:00:19 +00:00
else :
SendTo ( GetNick ( who ) , " Usage: !tip nick amount " ) ;
2014-12-21 18:50:24 +00:00
elif cmd [ 0 ] == ' withdraw ' :
2014-12-26 12:01:26 +00:00
if len ( cmd ) == 2 or len ( cmd ) == 3 :
2014-12-26 17:13:26 +00:00
CheckRegistered ( GetNick ( who ) , Withdraw , cmd [ 1 : ] , SendTo , " You must be registered with Freenode to withdraw " )
2014-12-21 18:50:24 +00:00
else :
SendTo ( GetNick ( who ) , " Usage: !withdraw address " ) ;
elif cmd [ 0 ] == ' info ' :
Info ( GetNick ( who ) )
elif cmd [ 0 ] == ' rain ' :
if chan [ 0 ] == ' # ' :
if len ( cmd ) == 2 or len ( cmd ) == 3 :
2014-12-26 17:13:26 +00:00
parms = [ chan ]
parms . extend ( cmd [ 1 : ] )
CheckRegistered ( GetNick ( who ) , Rain , parms , SendTo , " You must be registered with Freenode to rain " )
2014-12-21 18:50:24 +00:00
else :
2014-12-26 17:13:26 +00:00
SendTo ( sendto , " Usage: !rain amount [users] " ) ;
2014-12-21 18:50:24 +00:00
else :
SendTo ( sendto , " Raining can only be done in a channel " )
2014-12-27 19:31:54 +00:00
elif cmd [ 0 ] == ' rainactive ' :
if chan [ 0 ] == ' # ' :
if len ( cmd ) == 3 or len ( cmd ) == 4 :
parms = [ chan ]
parms . extend ( cmd [ 1 : ] )
CheckRegistered ( GetNick ( who ) , RainActive , parms , SendTo , " You must be registered with Freenode to rain " )
else :
SendTo ( sendto , " Usage: !rain amount [users] " ) ;
else :
SendTo ( sendto , " Raining can only be done in a channel " )
2014-12-21 18:50:24 +00:00
# admin commands
2014-12-09 10:00:19 +00:00
elif cmd [ 0 ] == ' height ' :
CheckAdmin ( GetNick ( who ) , GetHeight , None , SendTo , " You must be admin " )
elif cmd [ 0 ] == ' tipbot_balance ' :
CheckAdmin ( GetNick ( who ) , GetTipbotBalance , None , SendTo , " You must be admin " )
2014-12-21 18:50:24 +00:00
elif cmd [ 0 ] == ' addbalance ' :
CheckAdmin ( GetNick ( who ) , AddBalance , cmd [ 1 ] , SendTo , " You must be admin " )
elif cmd [ 0 ] == ' scanwho ' :
CheckAdmin ( GetNick ( who ) , ScanWho , [ chan ] , SendTo , " You must be admin " )
elif cmd [ 0 ] == ' enable_withdraw ' :
CheckAdmin ( GetNick ( who ) , EnableWithdraw , None , SendTo , " You must be admin " )
2014-12-23 11:14:35 +00:00
elif cmd [ 0 ] == ' disable_withdraw ' :
CheckAdmin ( GetNick ( who ) , DisableWithdraw , None , SendTo , " You must be admin " )
2014-12-22 13:30:59 +00:00
elif cmd [ 0 ] == ' dump_users ' :
CheckAdmin ( GetNick ( who ) , DumpUsers , None , SendTo , " You must be admin " )
2014-12-26 16:57:03 +00:00
elif cmd [ 0 ] == ' show_activity ' :
if len ( cmd ) == 3 :
2014-12-26 17:13:26 +00:00
CheckAdmin ( GetNick ( who ) , ShowActivity , cmd [ 1 : ] , SendTo , " You must be admin " )
2014-12-26 16:57:03 +00:00
else :
SendTo ( sendto , " Usage: show_activity channel nick " )
2014-12-21 18:50:24 +00:00
else :
SendTo ( GetNick ( who ) , " Invalid command, try !help " )
elif action == ' JOIN ' :
nick = GetNick ( who )
log_info ( ' %s joined the channel ' % nick )
if not chan in userstable :
2014-12-26 16:57:03 +00:00
userstable [ chan ] = dict ( )
2014-12-21 18:50:24 +00:00
if nick in userstable [ chan ] :
log_warn ( ' %s joined, but already in %s ' % ( nick , chan ) )
else :
2014-12-26 16:57:03 +00:00
userstable [ chan ] [ nick ] = None
log_log ( " New list of users in %s : %s " % ( chan , str ( userstable [ chan ] . keys ( ) ) ) )
2014-12-21 18:50:24 +00:00
elif action == ' PART ' :
nick = GetNick ( who )
2014-12-24 10:26:59 +00:00
log_info ( ' %s left the channel ' % nick )
2014-12-21 18:50:24 +00:00
if not nick in userstable [ chan ] :
2014-12-24 10:26:59 +00:00
log_warn ( ' %s left, but was not in %s ' % ( nick , chan ) )
2014-12-21 18:50:24 +00:00
else :
2014-12-26 16:57:03 +00:00
del userstable [ chan ] [ nick ]
log_log ( " New list of users in %s : %s " % ( chan , str ( userstable [ chan ] . keys ( ) ) ) )
2014-12-21 18:50:24 +00:00
2014-12-24 10:26:59 +00:00
elif action == ' QUIT ' :
nick = GetNick ( who )
log_info ( ' %s quit ' % nick )
removed_list = " "
for chan in userstable :
log_log ( " Checking in %s " % chan )
if nick in userstable [ chan ] :
removed_list = removed_list + " " + chan
2014-12-26 16:57:03 +00:00
del userstable [ chan ] [ nick ]
log_log ( " New list of users in %s : %s " % ( chan , str ( userstable [ chan ] . keys ( ) ) ) )
2014-12-24 10:26:59 +00:00
2014-12-21 18:50:24 +00:00
elif action == ' NICK ' :
nick = GetNick ( who )
new_nick = text
log_info ( ' %s renamed to %s ' % ( nick , new_nick ) )
for c in userstable :
log_log ( ' checking %s ' % c )
if nick in userstable [ c ] :
2014-12-26 16:57:03 +00:00
del userstable [ c ] [ nick ]
2014-12-21 18:50:24 +00:00
if new_nick in userstable [ c ] :
log_warn ( ' %s is the new name of %s , but was already in %s ' % ( new_nick , nick , c ) )
else :
2014-12-26 16:57:03 +00:00
userstable [ c ] [ new_nick ] = None
log_log ( " New list of users in %s : %s " % ( c , str ( userstable [ c ] . keys ( ) ) ) )
2014-12-21 18:50:24 +00:00
except Exception , e :
log_error ( ' Exception in top level action processing: %s ' % str ( e ) )
2014-12-09 10:00:19 +00:00