2014-12-29 17:08:13 +00:00
|
|
|
#!/bin/python
|
|
|
|
#
|
|
|
|
# Cryptonote tipbot - commands
|
2015-01-01 17:43:01 +00:00
|
|
|
# Copyright 2014,2015 moneromooo
|
2014-12-29 17:08:13 +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.
|
|
|
|
#
|
|
|
|
|
2017-11-06 23:27:52 +00:00
|
|
|
import time
|
2014-12-29 17:08:13 +00:00
|
|
|
import tipbot.config as config
|
2014-12-31 10:30:07 +00:00
|
|
|
from tipbot.utils import *
|
2014-12-29 17:08:13 +00:00
|
|
|
|
2015-01-03 18:32:09 +00:00
|
|
|
modules = dict()
|
2014-12-29 17:08:13 +00:00
|
|
|
commands = dict()
|
2015-03-20 18:07:53 +00:00
|
|
|
event_handlers = dict()
|
2014-12-29 17:08:13 +00:00
|
|
|
calltable=dict()
|
|
|
|
|
2015-01-13 12:28:05 +00:00
|
|
|
def SendToProxy(link,msg):
|
|
|
|
link.send(msg)
|
2015-01-06 20:54:19 +00:00
|
|
|
|
2015-01-13 12:28:05 +00:00
|
|
|
def RunRegisteredCommand(link,ifyes,yesdata,ifno,nodata):
|
|
|
|
if link.identity() not in calltable:
|
|
|
|
calltable[link.identity()] = []
|
2017-11-06 23:27:52 +00:00
|
|
|
calltable[link.identity()].append([link,ifyes,yesdata,ifno,nodata,time.time()+10])
|
2015-01-13 12:28:05 +00:00
|
|
|
if link.network.is_identified(link):
|
|
|
|
RunNextCommand(link,True)
|
2014-12-29 17:08:13 +00:00
|
|
|
else:
|
2015-01-13 12:28:05 +00:00
|
|
|
link.network.identify(link)
|
2014-12-29 17:08:13 +00:00
|
|
|
|
2015-01-13 12:28:05 +00:00
|
|
|
def IsAdmin(link):
|
|
|
|
return link.identity() in config.admins
|
2014-12-29 17:08:13 +00:00
|
|
|
|
2015-01-13 12:28:05 +00:00
|
|
|
def RunAdminCommand(link,ifyes,yesdata,ifno,nodata):
|
|
|
|
if not IsAdmin(link):
|
|
|
|
log_warn('RunAdminCommand: %s is not admin, cannot call %s with %s' % (str(link.identity()),str(ifyes),str(yesdata)))
|
|
|
|
link.send("Access denied")
|
2014-12-29 17:08:13 +00:00
|
|
|
return
|
2015-01-13 12:28:05 +00:00
|
|
|
RunRegisteredCommand(link,ifyes,yesdata,ifno,nodata)
|
2014-12-29 17:08:13 +00:00
|
|
|
|
2015-01-13 12:28:05 +00:00
|
|
|
def RunNextCommand(link,registered):
|
|
|
|
identity = link.identity()
|
|
|
|
if identity not in calltable:
|
|
|
|
log_error('Nothing in queue for %s' % identity)
|
2014-12-29 17:08:13 +00:00
|
|
|
return
|
|
|
|
try:
|
2015-01-13 12:28:05 +00:00
|
|
|
link=calltable[identity][0][0]
|
2015-02-05 19:24:15 +00:00
|
|
|
Lock()
|
2014-12-29 17:08:13 +00:00
|
|
|
if registered:
|
2015-01-13 12:28:05 +00:00
|
|
|
calltable[identity][0][1](link,calltable[identity][0][2])
|
2014-12-29 17:08:13 +00:00
|
|
|
else:
|
2015-01-13 12:28:05 +00:00
|
|
|
calltable[identity][0][3](link,calltable[identity][0][4])
|
|
|
|
del calltable[identity][0]
|
2014-12-29 17:08:13 +00:00
|
|
|
except Exception, e:
|
|
|
|
log_error('RunNextCommand: Exception in action, continuing: %s' % str(e))
|
2015-01-13 12:28:05 +00:00
|
|
|
del calltable[identity][0]
|
2015-02-05 19:24:15 +00:00
|
|
|
finally:
|
|
|
|
Unlock()
|
2014-12-29 17:08:13 +00:00
|
|
|
|
2017-11-06 23:27:52 +00:00
|
|
|
def PruneOldWaitingCommands():
|
|
|
|
Lock()
|
|
|
|
now=time.time()
|
|
|
|
for identity in calltable.keys():
|
|
|
|
while len(calltable[identity])>0 and calltable[identity][0][5]<now:
|
2017-11-07 23:53:33 +00:00
|
|
|
link=calltable[identity][0][0]
|
2017-11-06 23:27:52 +00:00
|
|
|
log_info('deleting old command: %s, %s' % (str(calltable[identity][0][1]), str(calltable[identity][0][3])))
|
|
|
|
link.send("Nickserv didn't reply, gonna have to deny access, mate")
|
|
|
|
del calltable[identity][0]
|
|
|
|
Unlock()
|
|
|
|
|
2015-01-13 12:28:05 +00:00
|
|
|
def Commands(link,cmd):
|
|
|
|
if IsAdmin(link):
|
2014-12-29 17:08:13 +00:00
|
|
|
all = True
|
|
|
|
else:
|
|
|
|
all = False
|
2014-12-31 10:31:16 +00:00
|
|
|
|
|
|
|
module_name = GetParam(cmd,1)
|
|
|
|
|
2015-01-01 12:16:44 +00:00
|
|
|
if module_name:
|
2015-04-25 09:31:12 +00:00
|
|
|
if not module_name in modules:
|
|
|
|
link.send_private("%s is not a module, see module list with !commands" % module_name)
|
|
|
|
return
|
2015-01-13 12:28:05 +00:00
|
|
|
link.send_private("Commands for %s's %s module:" % (config.tipbot_name,module_name))
|
2015-01-01 12:16:44 +00:00
|
|
|
else:
|
2015-01-13 12:28:05 +00:00
|
|
|
link.send_private("Commands for %s (use !commands <modulename> for help about the module's commands):" % config.tipbot_name)
|
2014-12-31 10:31:16 +00:00
|
|
|
|
|
|
|
msgs = dict()
|
2014-12-29 17:08:13 +00:00
|
|
|
for command_name in commands:
|
2015-01-03 18:32:09 +00:00
|
|
|
for c in commands[command_name]:
|
|
|
|
if 'admin' in c and c['admin'] and not all:
|
2014-12-31 10:31:16 +00:00
|
|
|
continue
|
2015-01-03 18:32:09 +00:00
|
|
|
module = c['module']
|
|
|
|
if module_name:
|
|
|
|
if module_name != module:
|
|
|
|
continue
|
|
|
|
synopsis = c['name']
|
|
|
|
if 'parms' in c:
|
|
|
|
synopsis = synopsis + " " + c['parms']
|
2015-01-13 12:28:05 +00:00
|
|
|
link.send_private("%s - %s" % (synopsis, c['help']))
|
2014-12-31 10:31:16 +00:00
|
|
|
else:
|
2015-01-03 18:32:09 +00:00
|
|
|
if module in msgs:
|
|
|
|
msgs[module] = msgs[module] +(", ")
|
|
|
|
else:
|
|
|
|
msgs[module] = module + " module: "
|
|
|
|
msgs[module] = msgs[module] +(c['name'])
|
2014-12-31 10:31:16 +00:00
|
|
|
|
|
|
|
if not module_name:
|
|
|
|
for msg in msgs:
|
2015-01-13 12:28:05 +00:00
|
|
|
link.send_private("%s" % msgs[msg])
|
2014-12-29 17:08:13 +00:00
|
|
|
|
2015-01-03 18:32:09 +00:00
|
|
|
def RegisterModule(module):
|
|
|
|
if module['name'] in modules:
|
|
|
|
log_error('a module named %s is already registered' % module['name'])
|
|
|
|
return
|
|
|
|
modules[module['name']] = module
|
|
|
|
|
2015-01-11 09:47:24 +00:00
|
|
|
def GetModuleNameList(admin):
|
|
|
|
if admin:
|
|
|
|
all = True
|
|
|
|
else:
|
|
|
|
all = False
|
|
|
|
|
|
|
|
module_names = []
|
|
|
|
for command_name in commands:
|
|
|
|
for c in commands[command_name]:
|
|
|
|
if 'admin' in c and c['admin'] and not all:
|
|
|
|
continue
|
|
|
|
module = c['module']
|
|
|
|
if not module in module_names:
|
|
|
|
module_names.append(module)
|
|
|
|
return module_names
|
|
|
|
|
2014-12-29 17:08:13 +00:00
|
|
|
def RegisterCommand(command):
|
2015-01-01 17:43:01 +00:00
|
|
|
if command['name'] in commands:
|
2015-01-03 18:32:09 +00:00
|
|
|
log_warn('module %s redefined function %s from module %s' % (command['module'],command['name'],commands[command['name']][0]['module']))
|
|
|
|
else:
|
|
|
|
commands[command['name']] = []
|
|
|
|
commands[command['name']].append(command)
|
2014-12-29 17:08:13 +00:00
|
|
|
|
2015-03-20 18:07:53 +00:00
|
|
|
def RegisterEventHandler(eh):
|
|
|
|
if not eh['event'] in event_handlers:
|
|
|
|
event_handlers[eh['event']] = []
|
|
|
|
event_handlers[eh['event']].append(eh)
|
|
|
|
|
2015-01-13 12:28:05 +00:00
|
|
|
def OnCommand(link,cmd,check_admin,check_registered):
|
2015-01-03 18:32:09 +00:00
|
|
|
cmdparts = cmd[0].split(':')
|
|
|
|
log_log('cmdparts: %s' % str(cmdparts))
|
|
|
|
if len(cmdparts) == 2:
|
|
|
|
modulename = cmdparts[0]
|
|
|
|
cmdname = cmdparts[1]
|
|
|
|
elif len(cmdparts) == 1:
|
|
|
|
modulename = None
|
|
|
|
cmdname = cmdparts[0]
|
|
|
|
else:
|
2015-01-13 12:28:05 +00:00
|
|
|
link.send("Invalid command, try !help")
|
2015-01-03 18:32:09 +00:00
|
|
|
return
|
|
|
|
log_log('modulename: %s, cmdname: %s' % (str(modulename),str(cmdname)))
|
|
|
|
if cmdname in commands:
|
|
|
|
log_log('%s found in commands' % (str(cmd[0])))
|
|
|
|
if len(commands[cmdname]) > 1:
|
|
|
|
if not modulename:
|
|
|
|
msg = ""
|
|
|
|
for c in commands[cmdname]:
|
|
|
|
if msg != "":
|
|
|
|
msg = msg + ", "
|
|
|
|
msg = msg + c['module'] + ":" + cmd[0]
|
2015-01-13 12:28:05 +00:00
|
|
|
link.send("Ambiguous command, try one of: %s" % msg)
|
2015-01-03 18:32:09 +00:00
|
|
|
return
|
|
|
|
c = None
|
|
|
|
for command in commands[cmdname]:
|
|
|
|
if command['module'] == modulename:
|
|
|
|
c = command
|
|
|
|
break
|
|
|
|
if not c:
|
2015-01-13 12:28:05 +00:00
|
|
|
link.send("Invalid command, try !help")
|
2015-01-03 18:32:09 +00:00
|
|
|
return
|
|
|
|
else:
|
|
|
|
c = commands[cmdname][0]
|
2014-12-29 17:08:13 +00:00
|
|
|
if 'admin' in c and c['admin']:
|
2015-01-13 12:28:05 +00:00
|
|
|
check_admin(link,c['function'],cmd,SendToProxy,"You must be admin")
|
2014-12-29 17:08:13 +00:00
|
|
|
elif 'registered' in c and c['registered']:
|
2015-01-13 12:28:05 +00:00
|
|
|
check_registered(link,c['function'],cmd,SendToProxy,"You must be registered with Freenode")
|
2014-12-29 17:08:13 +00:00
|
|
|
else:
|
2015-02-05 19:24:15 +00:00
|
|
|
Lock()
|
|
|
|
try:
|
|
|
|
c['function'](link,cmd)
|
|
|
|
except:
|
|
|
|
raise
|
|
|
|
finally:
|
|
|
|
Unlock()
|
2014-12-29 17:08:13 +00:00
|
|
|
else:
|
2015-01-21 13:50:31 +00:00
|
|
|
silent = False
|
|
|
|
if link.network.name in config.silent_invalid_commands:
|
|
|
|
if cmdname in config.silent_invalid_commands[link.network.name]:
|
|
|
|
log_info('silently ignoring command %s on %s' % (cmdname,link.network.name))
|
|
|
|
silent = True
|
|
|
|
if not silent:
|
|
|
|
link.send("Invalid command, try !help")
|
2014-12-29 17:08:13 +00:00
|
|
|
|
2015-03-20 18:07:53 +00:00
|
|
|
def OnEvent(event,*args,**kwargs):
|
|
|
|
log_log('modulename: event %s' % str(event))
|
|
|
|
if not event in event_handlers:
|
|
|
|
return
|
|
|
|
|
|
|
|
for eh in event_handlers[event]:
|
|
|
|
Lock()
|
|
|
|
try:
|
|
|
|
log_log('Calling %s handler from module %s' % (str(event),eh['module']))
|
|
|
|
eh['function'](event,*args,**kwargs)
|
|
|
|
except:
|
|
|
|
raise
|
|
|
|
finally:
|
|
|
|
Unlock()
|
|
|
|
|
2015-01-13 12:28:05 +00:00
|
|
|
def RunIdleFunctions(param=None):
|
2015-01-22 19:29:31 +00:00
|
|
|
for module in modules:
|
|
|
|
if 'idle' in modules[module]:
|
|
|
|
f=modules[module]['idle']
|
|
|
|
try:
|
2015-02-05 19:24:15 +00:00
|
|
|
Lock()
|
2015-01-22 19:29:31 +00:00
|
|
|
f(param)
|
|
|
|
except Exception,e:
|
|
|
|
log_error("Exception running idle function %s from module %s: %s" % (str(f),module,str(e)))
|
2015-02-05 19:24:15 +00:00
|
|
|
finally:
|
|
|
|
Unlock()
|
2017-11-06 23:27:52 +00:00
|
|
|
PruneOldWaitingCommands()
|
2015-01-01 10:06:09 +00:00
|
|
|
|
2015-01-13 12:28:05 +00:00
|
|
|
def RunModuleHelpFunction(module,link):
|
2015-01-03 18:32:09 +00:00
|
|
|
if module in modules:
|
2015-01-01 14:23:34 +00:00
|
|
|
try:
|
2015-01-13 12:28:05 +00:00
|
|
|
modules[module]['help'](link)
|
2015-01-01 14:23:34 +00:00
|
|
|
except Exception,e:
|
2015-01-03 18:32:09 +00:00
|
|
|
log_error("Exception running help function %s from module %s: %s" % (str(modules[module]['help']),str(module),str(e)))
|
|
|
|
else:
|
2015-01-13 12:28:05 +00:00
|
|
|
link.send_private('No help found for module %s' % module)
|
2015-01-01 14:23:34 +00:00
|
|
|
|
2015-01-03 18:32:09 +00:00
|
|
|
def UnregisterModule(module):
|
2015-01-01 10:06:09 +00:00
|
|
|
global commands
|
2015-03-20 18:07:53 +00:00
|
|
|
global event_handlers
|
2015-01-01 10:06:09 +00:00
|
|
|
global idles
|
2014-12-29 17:08:13 +00:00
|
|
|
|
2015-01-22 19:29:31 +00:00
|
|
|
if not module in modules:
|
|
|
|
log_error('Trying to unregister module %s, which is not registered' % module)
|
|
|
|
return
|
2015-01-03 18:32:09 +00:00
|
|
|
|
2015-01-22 19:29:31 +00:00
|
|
|
if 'cleanup' in modules[module]:
|
|
|
|
modules[module]['cleanup']()
|
2015-01-01 10:06:09 +00:00
|
|
|
|
|
|
|
new_commands = dict()
|
|
|
|
for cmd in commands:
|
2015-01-03 18:32:09 +00:00
|
|
|
newlist = []
|
|
|
|
for c in commands[cmd]:
|
|
|
|
if c['module'] != module:
|
|
|
|
newlist.append(c)
|
|
|
|
if len(newlist) > 0:
|
|
|
|
new_commands[cmd] = newlist
|
2015-01-01 10:06:09 +00:00
|
|
|
commands = new_commands
|
2014-12-29 17:08:13 +00:00
|
|
|
|
2015-03-20 18:07:53 +00:00
|
|
|
new_event_handlers = dict()
|
|
|
|
for cmd in event_handlers:
|
|
|
|
newlist = []
|
|
|
|
for c in event_handlers[cmd]:
|
|
|
|
if c['module'] != module:
|
|
|
|
newlist.append(c)
|
|
|
|
if len(newlist) > 0:
|
|
|
|
new_event_handlers[cmd] = newlist
|
|
|
|
event_handlers = new_event_handlers
|
|
|
|
|
2015-01-22 19:29:31 +00:00
|
|
|
del modules[module]
|