зеркало из https://github.com/mozilla/MozDef.git
90% more pep8, 10% less cruft
This commit is contained in:
Родитель
8577534819
Коммит
ee42f669fb
405
bot/mozdefbot.py
405
bot/mozdefbot.py
|
@ -4,76 +4,76 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
"""mozdef bot using KitnIRC."""
|
||||
import logging
|
||||
import threading
|
||||
from datetime import datetime
|
||||
import time
|
||||
import sys
|
||||
import kitnirc.client
|
||||
import random
|
||||
import pyes
|
||||
import pytz
|
||||
from dateutil.parser import parse
|
||||
import netaddr
|
||||
import pygeoip
|
||||
import os
|
||||
from configlib import getConfig,OptionParser
|
||||
import pika
|
||||
import json
|
||||
import select
|
||||
import kitnirc.client
|
||||
import logging
|
||||
import netaddr
|
||||
import os
|
||||
import pika
|
||||
import pygeoip
|
||||
import pytz
|
||||
import random
|
||||
import select
|
||||
import threading
|
||||
import time
|
||||
from configlib import getConfig, OptionParser
|
||||
from datetime import datetime
|
||||
from dateutil.parser import parse
|
||||
|
||||
greetz=["mozdef bot in da house",
|
||||
"mozdef here..what's up",
|
||||
"mozdef has joined the room..no one panic",
|
||||
"mozdef bot here..nice to see everyone"]
|
||||
greetz = ["mozdef bot in da house",
|
||||
"mozdef here..what's up",
|
||||
"mozdef has joined the room..no one panic",
|
||||
"mozdef bot here..nice to see everyone"]
|
||||
|
||||
retorts=["why, why soo mean?",
|
||||
"someone got up on the wrong side of...",
|
||||
"yo momma arcsight",
|
||||
"gross arcsight..why you do that?",
|
||||
"fat chance arcsight",
|
||||
"arcsight you're such a show off"]
|
||||
retorts = ["why, why soo mean?",
|
||||
"someone got up on the wrong side of...",
|
||||
"yo momma arcsight",
|
||||
"gross arcsight..why you do that?",
|
||||
"fat chance arcsight",
|
||||
"arcsight you're such a show off"]
|
||||
|
||||
panics=["don't panic",
|
||||
".. a towel has immense psychological value",
|
||||
"..but in fact the message was this: 'So Long, and Thanks for All the Fish.'",
|
||||
"42",
|
||||
"What I need..is a strong drink and a peer group --Douglas Adams",
|
||||
"Eddies in the space-time continuum.",
|
||||
"segmentation fault..SEP"
|
||||
]
|
||||
panics = ["don't panic",
|
||||
".. a towel has immense psychological value",
|
||||
"..but in fact the message was this: 'So Long, and Thanks for All the Fish.'",
|
||||
"42",
|
||||
"What I need..is a strong drink and a peer group --Douglas Adams",
|
||||
"Eddies in the space-time continuum.",
|
||||
"segmentation fault..SEP"
|
||||
]
|
||||
|
||||
if os.path.isfile('quotes.txt'):
|
||||
quotes=open('quotes.txt').readlines()
|
||||
quotes = open('quotes.txt').readlines()
|
||||
else:
|
||||
quotes=['nothing to say..add a quotes.txt file!']
|
||||
quotes = ['nothing to say..add a quotes.txt file!']
|
||||
|
||||
colors = {'red': '\x034\x02',
|
||||
'normal': '\x03\x02',
|
||||
'blue': '\x032\x02',
|
||||
'green': '\x033\x02',
|
||||
'yellow': '\x038\x02',
|
||||
}
|
||||
'normal': '\x03\x02',
|
||||
'blue': '\x032\x02',
|
||||
'green': '\x033\x02',
|
||||
'yellow': '\x038\x02',
|
||||
}
|
||||
|
||||
keywords = {'INFORMATIONAL': colors['green'],
|
||||
'INFO': colors['green'],
|
||||
'WARNING': colors['yellow'],
|
||||
'CRITICAL': colors['red'],
|
||||
'mozdef': colors['blue'],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def colorify(data):
|
||||
for i in keywords:
|
||||
data = data.replace(i, keywords[i]+i+colors['normal'], 1)
|
||||
data = data.replace(i, keywords[i] + i + colors['normal'], 1)
|
||||
return data
|
||||
|
||||
#http://code.activestate.com/recipes/576684-simple-threading-decorator/
|
||||
|
||||
def run_async(func):
|
||||
"""
|
||||
run_async(func)
|
||||
function decorator, intended to make "func" run in a separate
|
||||
thread (asynchronously).
|
||||
Returns the created Thread object
|
||||
from: http://code.activestate.com/recipes/576684-simple-threading-decorator/
|
||||
|
||||
E.g.:
|
||||
@run_async
|
||||
|
@ -91,39 +91,42 @@ def run_async(func):
|
|||
t2.join()
|
||||
"""
|
||||
from threading import Thread
|
||||
from multiprocessing import Process
|
||||
from functools import wraps
|
||||
|
||||
@wraps(func)
|
||||
def async_func(*args, **kwargs):
|
||||
func_hl = Thread(target = func, args = args, kwargs = kwargs)
|
||||
func_hl = Thread(target=func, args=args, kwargs=kwargs)
|
||||
func_hl.start()
|
||||
return func_hl
|
||||
return async_func
|
||||
|
||||
def toUTC(suspectedDate,localTimeZone="US/Pacific"):
|
||||
|
||||
def toUTC(suspectedDate, localTimeZone="US/Pacific"):
|
||||
'''make a UTC date out of almost anything'''
|
||||
utc=pytz.UTC
|
||||
objDate=None
|
||||
if type(suspectedDate)==str:
|
||||
objDate=parse(suspectedDate,fuzzy=True)
|
||||
elif type(suspectedDate)==datetime:
|
||||
objDate=suspectedDate
|
||||
|
||||
utc = pytz.UTC
|
||||
objDate = None
|
||||
if type(suspectedDate) == str:
|
||||
objDate = parse(suspectedDate, fuzzy=True)
|
||||
elif type(suspectedDate) == datetime:
|
||||
objDate = suspectedDate
|
||||
|
||||
if objDate.tzinfo is None:
|
||||
objDate=pytz.timezone(localTimeZone).localize(objDate)
|
||||
objDate=utc.normalize(objDate)
|
||||
objDate = pytz.timezone(localTimeZone).localize(objDate)
|
||||
objDate = utc.normalize(objDate)
|
||||
else:
|
||||
objDate=utc.normalize(objDate)
|
||||
objDate = utc.normalize(objDate)
|
||||
if objDate is not None:
|
||||
objDate=utc.normalize(objDate)
|
||||
|
||||
objDate = utc.normalize(objDate)
|
||||
|
||||
return objDate
|
||||
|
||||
|
||||
def getQuote():
|
||||
aquote='{0} --Mos Def'.format(quotes[random.randint(0,len(quotes)-1)].strip())
|
||||
aquote = '{0} --Mos Def'.format(
|
||||
quotes[random.randint(0, len(quotes) - 1)].strip())
|
||||
return aquote
|
||||
|
||||
|
||||
def isIP(ip):
|
||||
try:
|
||||
netaddr.IPNetwork(ip)
|
||||
|
@ -131,84 +134,99 @@ def isIP(ip):
|
|||
except:
|
||||
return False
|
||||
|
||||
|
||||
def ipLocation(ip):
|
||||
location=""
|
||||
location = ""
|
||||
try:
|
||||
gi = pygeoip.GeoIP('GeoLiteCity.dat', pygeoip.MEMORY_CACHE)
|
||||
geoDict=gi.record_by_addr(str(netaddr.IPNetwork(ip)[0]))
|
||||
if not geoDict==None:
|
||||
location=geoDict['country_name']
|
||||
geoDict = gi.record_by_addr(str(netaddr.IPNetwork(ip)[0]))
|
||||
if geoDict is not None:
|
||||
location = geoDict['country_name']
|
||||
if geoDict['country_code'] in ('US'):
|
||||
if geoDict['metro_code']:
|
||||
location=location + '/{0}'.format(geoDict['metro_code'])
|
||||
location = location + '/{0}'.format(geoDict['metro_code'])
|
||||
except Exception as e:
|
||||
location=""
|
||||
location = ""
|
||||
return location
|
||||
|
||||
|
||||
|
||||
def formatAlert(jsonDictIn):
|
||||
#defaults
|
||||
severity='INFO'
|
||||
summary=''
|
||||
category=''
|
||||
# defaults
|
||||
severity = 'INFO'
|
||||
summary = ''
|
||||
category = ''
|
||||
if 'severity' in jsonDictIn.keys():
|
||||
severity=jsonDictIn['severity']
|
||||
severity = jsonDictIn['severity']
|
||||
if 'summary' in jsonDictIn.keys():
|
||||
summary=jsonDictIn['summary']
|
||||
summary = jsonDictIn['summary']
|
||||
if 'category' in jsonDictIn.keys():
|
||||
category=jsonDictIn['category']
|
||||
|
||||
return colorify('{0}: {1} {2}'.format(severity,colors['blue']+ category +colors['normal'],summary))
|
||||
category = jsonDictIn['category']
|
||||
|
||||
return colorify('{0}: {1} {2}'.format(severity, colors['blue']
|
||||
+ category
|
||||
+ colors['normal'],
|
||||
summary))
|
||||
|
||||
|
||||
class alertsListener(threading.Thread):
|
||||
def __init__(self,client):
|
||||
|
||||
def __init__(self, client):
|
||||
threading.Thread.__init__(self)
|
||||
# A flag to notify the thread that it should finish up and exit
|
||||
self.kill = False
|
||||
self.lastRunTime=datetime.now()
|
||||
self.client=client
|
||||
self.lastalerts=[]
|
||||
self.lastRunTime = datetime.now()
|
||||
self.client = client
|
||||
self.lastalerts = []
|
||||
self.openMQ()
|
||||
self.mqError=False
|
||||
self.connection =None
|
||||
self.mqError = False
|
||||
self.connection = None
|
||||
self.channel = None
|
||||
|
||||
def alertsCallback(self, ch, method, properties, bodyin):
|
||||
self.client.root_logger.debug(" [x]event {0}:{1}".format(method.routing_key, bodyin))
|
||||
self.client.root_logger.debug(
|
||||
" [x]event {0}:{1}".format(method.routing_key, bodyin))
|
||||
try:
|
||||
jbody=json.loads(bodyin)
|
||||
self.client.msg(options.alertircchannel,formatAlert(jbody))
|
||||
jbody = json.loads(bodyin)
|
||||
self.client.msg(options.alertircchannel, formatAlert(jbody))
|
||||
|
||||
except Exception as e:
|
||||
self.client.root_logger.error('Exception on message queue callback {0}'.format(e))
|
||||
self.client.root_logger.error(
|
||||
'Exception on message queue callback {0}'.format(e))
|
||||
|
||||
@run_async
|
||||
def openMQ(self):
|
||||
try:
|
||||
if self.connection is None and not self.kill:
|
||||
self.mqError=False
|
||||
self.connection = pika.BlockingConnection(pika.ConnectionParameters(host=options.mqserver,heartbeat_interval=10))
|
||||
#give the irc client visibility to our connection state.
|
||||
self.client.mqconnection=self.connection
|
||||
self.mqError = False
|
||||
self.connection = pika.BlockingConnection(
|
||||
pika.ConnectionParameters(host=options.mqserver, heartbeat_interval=10))
|
||||
# give the irc client visibility to our connection state.
|
||||
self.client.mqconnection = self.connection
|
||||
self.client.root_logger.info('opening message queue channel')
|
||||
if self.channel is None:
|
||||
if self.channel is None:
|
||||
self.channel = self.connection.channel()
|
||||
self.channel.exchange_declare(exchange=options.alertexchange,type='topic')
|
||||
self.channel.exchange_declare(
|
||||
exchange=options.alertexchange, type='topic')
|
||||
result = self.channel.queue_declare(exclusive=False)
|
||||
queue_name = result.method.queue
|
||||
self.channel.queue_bind(exchange=options.alertexchange, queue=queue_name,routing_key=options.alertqueue)
|
||||
|
||||
self.client.root_logger.info('INFO consuming message queue {0}'.format(options.alertqueue))
|
||||
self.client.msg(options.alertircchannel,'consuming message queue {0}'.format(options.alertqueue))
|
||||
self.channel.basic_consume(self.alertsCallback,queue=queue_name,no_ack=True)
|
||||
self.channel.queue_bind(
|
||||
exchange=options.alertexchange, queue=queue_name, routing_key=options.alertqueue)
|
||||
|
||||
self.client.root_logger.info(
|
||||
'INFO consuming message queue {0}'.format(options.alertqueue))
|
||||
self.client.msg(
|
||||
options.alertircchannel, 'consuming message queue {0}'.format(options.alertqueue))
|
||||
self.channel.basic_consume(
|
||||
self.alertsCallback, queue=queue_name, no_ack=True)
|
||||
self.channel.start_consuming()
|
||||
except pika.exceptions.ConnectionClosed as e:
|
||||
self.client.root_logger.error("MQ Connection closed {0}".format(e))
|
||||
self.client.msg(options.alertircchannel,"ERROR: Message queue is closed. No alerts for you")
|
||||
self.mqError=True
|
||||
self.client.msg(
|
||||
options.alertircchannel, "ERROR: Message queue is closed. No alerts for you")
|
||||
self.mqError = True
|
||||
try:
|
||||
self.connection=None
|
||||
self.channel=None
|
||||
self.connection = None
|
||||
self.channel = None
|
||||
except:
|
||||
pass
|
||||
except AttributeError:
|
||||
|
@ -216,9 +234,11 @@ class alertsListener(threading.Thread):
|
|||
except select.error:
|
||||
pass
|
||||
except Exception as e:
|
||||
self.mqError=True
|
||||
self.client.root_logger.error("Exception {0} while processing alerts message queue.".format(type(e)))
|
||||
self.client.msg(options.alertircchannel,"ERROR: Exception {0} while processing alerts message queue".format(e))
|
||||
self.mqError = True
|
||||
self.client.root_logger.error(
|
||||
"Exception {0} while processing alerts message queue.".format(type(e)))
|
||||
self.client.msg(
|
||||
options.alertircchannel, "ERROR: Exception {0} while processing alerts message queue".format(e))
|
||||
|
||||
try:
|
||||
if self.connection is not None:
|
||||
|
@ -226,10 +246,10 @@ class alertsListener(threading.Thread):
|
|||
except:
|
||||
pass
|
||||
finally:
|
||||
self.connection=None
|
||||
self.channel=None
|
||||
|
||||
def run(self):
|
||||
self.connection = None
|
||||
self.channel = None
|
||||
|
||||
def run(self):
|
||||
while not self.kill:
|
||||
try:
|
||||
self.client.root_logger.debug('checking mq connections')
|
||||
|
@ -237,67 +257,27 @@ class alertsListener(threading.Thread):
|
|||
self.openMQ()
|
||||
self.client.root_logger.info('opening mq connection')
|
||||
time.sleep(10)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
self.client.root_logger.error("Exception {0} while polling alerts message queue health.".format(e))
|
||||
self.client.root_logger.error(
|
||||
"Exception {0} while polling alerts message queue health.".format(e))
|
||||
time.sleep(int(10))
|
||||
|
||||
class alertsWorker(threading.Thread):
|
||||
def __init__(self,client):
|
||||
threading.Thread.__init__(self)
|
||||
# A flag to notify the thread that it should finish up and exit
|
||||
self.kill = False
|
||||
self.lastRunTime=datetime.now()
|
||||
self.client=client
|
||||
self.lastalerts=[]
|
||||
|
||||
|
||||
def run(self):
|
||||
while not self.kill:
|
||||
self.checkAlerts()
|
||||
|
||||
def checkAlerts(self):
|
||||
try:
|
||||
if (datetime.now() - self.lastRunTime).seconds > int(10):
|
||||
|
||||
self.client.root_logger.debug("checking for alerts" )
|
||||
#self.client.msg("#mzdf","checking for alerts...")
|
||||
#analert='{0}: {1}'.format(datetime.now(),random.randint(0,100))
|
||||
esresults=esSearchFail2ban(toUTC(self.lastRunTime))
|
||||
#esresults=esSearchFail2ban(toUTC("Nov 18"))
|
||||
for analert in esresults:
|
||||
if analert not in self.lastalerts:
|
||||
self.lastalerts.append(analert)
|
||||
self.client.msg(alertChannel,analert)
|
||||
self.client.root_logger.debug('sent {0}'.format(analert))
|
||||
if len(self.lastalerts)>100:
|
||||
self.client.root_logger.debug('removing:{0}'.format(self.lastalerts[0]))
|
||||
self.lastalerts.remove(self.lastalerts[0])
|
||||
self.lastRunTime=datetime.now()
|
||||
else:
|
||||
#self.client.root_logger.debug("not alert time..sleeping")
|
||||
time.sleep(int(5))
|
||||
except Exception as e:
|
||||
self.client.root_logger.error("Exception {0} while checking for alerts.".format(e))
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class mozdefBot():
|
||||
|
||||
def __init__(self, ):
|
||||
|
||||
# Logging initialization
|
||||
self.log_handler = logging.StreamHandler()
|
||||
self.log_formatter = logging.Formatter("%(asctime)s %(message)s")
|
||||
self.log_handler.setFormatter(self.log_formatter)
|
||||
|
||||
|
||||
self.root_logger = logging.getLogger()
|
||||
self.root_logger.addHandler(self.log_handler)
|
||||
self.root_logger.setLevel(logging.INFO)
|
||||
|
||||
self.client = kitnirc.client.Client(options.host, options.port)
|
||||
self.client.root_logger=self.root_logger
|
||||
self.client.root_logger = self.root_logger
|
||||
self.client.connect(
|
||||
nick=options.nick,
|
||||
username=options.username or options.nick,
|
||||
|
@ -305,9 +285,9 @@ class mozdefBot():
|
|||
password=options.password,
|
||||
ssl=True
|
||||
)
|
||||
self.threads=[]
|
||||
self.mqconnection=None
|
||||
|
||||
self.threads = []
|
||||
self.mqconnection = None
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
@self.client.handle('WELCOME')
|
||||
|
@ -316,47 +296,57 @@ class mozdefBot():
|
|||
return
|
||||
for chan in options.join.split(","):
|
||||
if chan in options.channelkeys.keys():
|
||||
client.join(chan,options.channelkeys[chan])
|
||||
client.join(chan, options.channelkeys[chan])
|
||||
else:
|
||||
client.join(chan)
|
||||
t=alertsListener(self.client)
|
||||
t = alertsListener(self.client)
|
||||
self.threads.append(t)
|
||||
t.start()
|
||||
|
||||
@self.client.handle('LINE')
|
||||
def line_handler(client,*params):
|
||||
def line_handler(client, *params):
|
||||
try:
|
||||
self.root_logger.debug('linegot:' + line)
|
||||
except AttributeError as e:
|
||||
#catch error in kitnrc : chan.remove(actor) where channel object has no attribute remove
|
||||
# catch error in kitnrc : chan.remove(actor) where channel
|
||||
# object has no attribute remove
|
||||
pass
|
||||
|
||||
@self.client.handle('PRIVMSG')
|
||||
def priv_handler(client,actor,recipient,message):
|
||||
self.root_logger.debug('privmsggot:' + message + ' from ' + actor)
|
||||
def priv_handler(client, actor, recipient, message):
|
||||
self.root_logger.debug(
|
||||
'privmsggot:' + message + ' from ' + actor)
|
||||
if 'ArcSight' in actor or 'jeff' in actor:
|
||||
if 'BANG' in message:
|
||||
self.client.msg(recipient,random.choice(retorts))
|
||||
self.client.msg(recipient, random.choice(retorts))
|
||||
if "!help" in message:
|
||||
self.client.msg(recipient,"I just send alerts and taunt arcsight..for now..but try these:")
|
||||
self.client.msg(recipient,"!quote --get a quote from my buddy Mos Def")
|
||||
self.client.msg(recipient,"!panic --panic (or not )")
|
||||
self.client.msg(recipient,"!ipinfo --do a geoip lookup on an ip address")
|
||||
self.client.msg(
|
||||
recipient, "I just send alerts and taunt arcsight..for now..but try these:")
|
||||
self.client.msg(
|
||||
recipient, "!quote --get a quote from my buddy Mos Def")
|
||||
self.client.msg(recipient, "!panic --panic (or not )")
|
||||
self.client.msg(
|
||||
recipient, "!ipinfo --do a geoip lookup on an ip address")
|
||||
if "!quote" in message:
|
||||
self.client.msg(recipient,getQuote())
|
||||
self.client.msg(recipient, getQuote())
|
||||
if "!panic" in message:
|
||||
self.client.msg(recipient,random.choice(panics))
|
||||
self.client.msg(recipient, random.choice(panics))
|
||||
if "!ipinfo" in message:
|
||||
for i in message.split():
|
||||
if isIP(i):
|
||||
ip=netaddr.IPNetwork(i)[0]
|
||||
if ( not ip.is_loopback() and not ip.is_private() and not ip.is_reserved()):
|
||||
self.client.msg(recipient,"{0} location: {1}".format(i,ipLocation(i)))
|
||||
ip = netaddr.IPNetwork(i)[0]
|
||||
if (not ip.is_loopback() and not ip.is_private() and not ip.is_reserved()):
|
||||
self.client.msg(
|
||||
recipient, "{0} location: {1}".format(i, ipLocation(i)))
|
||||
else:
|
||||
self.client.msg(recipient,"{0}: hrm..loopback? private ip?".format(i))
|
||||
self.client.msg(
|
||||
recipient, "{0}: hrm..loopback? private ip?".format(i))
|
||||
|
||||
@self.client.handle('JOIN')
|
||||
def join_handler(client, user,channel,*params):
|
||||
def join_handler(client, user, channel, *params):
|
||||
self.root_logger.debug('%r' % channel)
|
||||
if user.nick==options.nick:
|
||||
self.client.msg(channel,colorify(random.choice(greetz)))
|
||||
if user.nick == options.nick:
|
||||
self.client.msg(channel, colorify(random.choice(greetz)))
|
||||
self.client.run()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
|
@ -376,33 +366,48 @@ class mozdefBot():
|
|||
if self.client.mqconnection is not None:
|
||||
self.client.mqconnection.close()
|
||||
|
||||
|
||||
def initConfig():
|
||||
#initialize config options
|
||||
#sets defaults or overrides from config file.
|
||||
options.host=getConfig('host','irc.somewhere.com',options.configfile)
|
||||
options.nick=getConfig('nick','mozdefnick',options.configfile)
|
||||
options.port=getConfig('port',6697,options.configfile)
|
||||
options.username=getConfig('username','username',options.configfile)
|
||||
options.realname=getConfig('realname','realname',options.configfile)
|
||||
options.password=getConfig('password','',options.configfile)
|
||||
options.join=getConfig('join','#mzdf',options.configfile)
|
||||
options.esserver=getConfig('esserver','localhost',options.configfile)
|
||||
options.mqserver=getConfig('mqserver','localhost',options.configfile)
|
||||
options.alertqueue=getConfig('alertqueue','mozdef.alert',options.configfile)
|
||||
options.alertexchange=getConfig('alertexchange','alerts',options.configfile)
|
||||
options.alertircchannel=getConfig('alertircchannel','',options.configfile)
|
||||
options.channelkeys=json.loads(getConfig('channelkeys','{"#somechannel": "somekey"}',options.configfile))
|
||||
|
||||
if options.alertircchannel=='':
|
||||
options.alertircchannel=options.join
|
||||
# initialize config options
|
||||
# sets defaults or overrides from config file.
|
||||
options.host = getConfig('host', 'irc.somewhere.com', options.configfile)
|
||||
options.nick = getConfig('nick', 'mozdefnick', options.configfile)
|
||||
options.port = getConfig('port', 6697, options.configfile)
|
||||
options.username = getConfig('username', 'username', options.configfile)
|
||||
options.realname = getConfig('realname', 'realname', options.configfile)
|
||||
options.password = getConfig('password', '', options.configfile)
|
||||
options.join = getConfig('join', '#mzdf', options.configfile)
|
||||
options.mqserver = getConfig('mqserver', 'localhost', options.configfile)
|
||||
options.alertqueue = getConfig(
|
||||
'alertqueue',
|
||||
'mozdef.alert',
|
||||
options.configfile)
|
||||
options.alertexchange = getConfig(
|
||||
'alertexchange',
|
||||
'alerts',
|
||||
options.configfile)
|
||||
options.alertircchannel = getConfig(
|
||||
'alertircchannel',
|
||||
'',
|
||||
options.configfile)
|
||||
options.channelkeys = json.loads(getConfig(
|
||||
'channelkeys',
|
||||
'{"#somechannel": "somekey"}',
|
||||
options.configfile))
|
||||
|
||||
if options.alertircchannel == '':
|
||||
options.alertircchannel = options.join
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser=OptionParser()
|
||||
parser.add_option("-c", dest='configfile' , default='', help="configuration file to use")
|
||||
(options,args) = parser.parse_args()
|
||||
initConfig()
|
||||
|
||||
thebot=mozdefBot()
|
||||
parser = OptionParser()
|
||||
parser.add_option(
|
||||
"-c", dest='configfile',
|
||||
default='',
|
||||
help="configuration file to use")
|
||||
(options, args) = parser.parse_args()
|
||||
initConfig()
|
||||
|
||||
thebot = mozdefBot()
|
||||
thebot.run()
|
||||
|
||||
# vim: set ts=4 sts=4 sw=4 et:
|
||||
|
|
Загрузка…
Ссылка в новой задаче