diff --git a/python/CFDataFile.py b/python/CFDataFile.py new file mode 100644 index 000000000..4994e44fc --- /dev/null +++ b/python/CFDataFile.py @@ -0,0 +1,144 @@ +# CFDataFile.py - CFData classes +# +# Copyright (C) 2002 Joris Bontje +# +# This program 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +import os +import string +import CFPython + +class CFDataFile: + '''Plain text storage for Crossfire data''' + + def __init__(self, datafile_name): + self.datafile_name = datafile_name + self.filename = os.path.join((CFPython.GetLocalDirectory()),'datafiles',datafile_name) + + def exists(self): + '''checks for datafile''' + if os.path.isfile(self.filename): + return 1 + else: + return 0 + + def make_file(self, header): + '''creates a datafile, making the column header from a list''' + try: + file = open(self.filename,'w') + except: + print "Can't create datafile %s" % self.datafile_name + return 0 + else: + temp = [] + for item in header: + temp.append(str(item)) + contents = '#|%s\n' %(string.join(temp,'|')) + file.write(contents) + file.close() + print "New datafile created: %s" % self.datafile_name + + def getData(self): + '''Gets the formatted file as a dictionary + The # key contains the column headers for the file''''' + try: + file = open(self.filename,'r') + except: + raise 'Unable to read %s' % self.datafile_name + else: + temp = file.read().split('\n') + file.close() + contents = temp[:-1] + DF = {} + templist = [] + for list in contents: + templist = list.split('|') + DF[templist[0]] = templist[1:] + return DF + + def putData(self, dic): + '''Writes dictionary to formatted file''' + try: + file = open(self.filename,'w') + except: + raise 'Unable to open %s for writing' % self.datafile_name + else: + header = dic['#'] + del dic['#'] + index = dic.keys() + index.sort() + contents = '#|%s\n' %(string.join(header,'|')) + file.write(contents) + for entry in index: + tmp = [] + stringlist = dic[entry] + for item in stringlist: + tmp.append(str(item)) + temp = '%s|%s\n' %(entry, (string.join(tmp,'|'))) + file.write(temp) + file.close() + +class CFData: + '''CFData Object is basically a dictionary parsed from the datafile''' + + def __init__(self, filename, header): + self.header = header + self.datafile = CFDataFile(filename) + + if self.datafile.exists(): + self.datadb = self.datafile.getData() + if self.datadb['#'] != self.header: + raise 'Header does not match! You may need to fix the object or the datafile.' + else: + self.datafile.make_file(self.header) + self.datadb = self.datafile.getData() + + def remove_record(self, name): + if self.datadb.has_key(name): + del self.datadb[name] + self.datafile.putData(self.datadb) + return 1 + else: + return 0 + + def exist(self, name): + if self.datadb.has_key(name): + return 1 + else: + return 0 + + def get_record(self, name): + if self.exist(name): + record = {} + for header, item in zip(self.header,self.datadb[name]): + record[header]=item + record['#'] = name + return record + else: + return 0 + + def put_record(self, record): + name = record['#'] + del record['#'] + temp = [] + for item in self.header: + temp.append(record[item]) + self.datadb[name]=temp + self.datafile.putData(self.datadb) + + + + diff --git a/python/CFLog.py b/python/CFLog.py index 943526198..c3c63cbb2 100644 --- a/python/CFLog.py +++ b/python/CFLog.py @@ -18,46 +18,66 @@ # # The author can be reached via e-mail at jbontje@suespammers.org # -#Updated to use new path functions in CFPython -Todd Mitchell -import shelve -import os.path +# Updated to use new path functions in CFPython -Todd Mitchell +# +# Updated to add new fields and functions (kick, muzzle) +# and rewritten to use plain text file storage (CFDataFile) instead of shelve. + import CFPython + from time import localtime, strftime, time +from CFDataFile import CFDataFile, CFData class CFLog: - logdb_file = os.path.join(CFPython.GetLocalDirectory(),'crossfirelog') - logdb = {} - def __init__(self): - self.logdb = shelve.open(self.logdb_file) + logheader = ['Born', 'IP', 'Last_Login_Date', 'Login_Count', 'Kick_Count' + , 'Last_Kick_Date', 'Muzzle_Count', 'Last_Muzzle_Date'] + self.log = CFData('Player_log', logheader) def create(self, name): date = strftime("%a, %d %b %Y %H:%M:%S CEST", localtime(time())) - count=1 - self.logdb[name]=['unknown', date, count] - - def update(self, name, ip): - date = strftime("%a, %d %b %Y %H:%M:%S CEST", localtime(time())) - count=0 - if self.logdb.has_key(name): - oldip, olddate, count=self.logdb[name] - count+=1 - self.logdb[name]=[ip, date, count] + record={'#': name + ,'Born':date + ,'IP':'unknown' + ,'Last_Login_Date':date + ,'Login_Count':0 + ,'Kick_Count':0 + ,'Last_Kick_Date':'never' + ,'Muzzle_Count':0 + ,'Last_Muzzle_Date':'never'} + self.log.put_record(record) def remove(self, name): - if self.logdb.has_key(name): - del self.logdb[name] - - def exist(self, name): - if self.logdb.has_key(name): - return 1 + self.log.remove_record(name) + + def login_update(self, name, ip): + date = strftime("%a, %d %b %Y %H:%M:%S CEST", localtime(time())) + record = self.log.get_record(name) + record['IP']=ip + record['Last_Login_Date']=date + record['Login_Count']=int(record['Login_Count'])+1 + self.log.put_record(record) + + def kick_update(self, name): + date = strftime("%a, %d %b %Y %H:%M:%S CEST", localtime(time())) + record = self.log.get_record(name) + record['Kick_Count']=int(record['Kick_Count'])+1 + record['Last_Kick_Date']=date + self.log.put_record(record) + + def muzzle_update(self, name): + date = strftime("%a, %d %b %Y %H:%M:%S CEST", localtime(time())) + record = self.log.get_record(name) + record['Muzzle_Count']=int(record['Muzzle_Count'])+1 + record['Last_Muzzle_Date']=date + self.log.put_record(record) + + def info(self, name): + record = self.log.get_record(name) + if record: + return record else: return 0 - - def info(self, name): - if self.exist(name): - ip, date, count=self.logdb[name] - return ip, date, count diff --git a/python/IPO/say.py b/python/IPO/say.py index 242262a44..ec7f77830 100755 --- a/python/IPO/say.py +++ b/python/IPO/say.py @@ -74,7 +74,7 @@ elif text[0] == 'literacy': elif text[0] == 'mailscroll': if len(text)==2: - if log.exist(text[1]): + if log.info(text[1]): if (CFPython.PayAmount(activator, priceMailScroll*50)): CFPython.Say(whoami, 'Here is your mailscroll') id = CFPython.CreateObject('scroll', (x, y)) @@ -92,7 +92,7 @@ elif text[0] == 'mailscroll': elif text[0] == 'mailwarning': if (CFPython.IsDungeonMaster(activator)): if len(text)==2: - if log.exist(text[1]): + if log.info(text[1]): CFPython.Say(whoami, 'Here is your mailwarning') id = CFPython.CreateObject('diploma', (x, y)) CFPython.SetName(id, 'mailwarning T: '+text[1]+' F: '+ activatorname) @@ -105,16 +105,5 @@ elif text[0] == 'mailwarning': else: CFPython.Say(whoami, 'You need to be DM to be able to use this command') - -elif text[0] == 'seen': - if len(text)==2: - if log.exist(text[1]): - ip, date, count = log.info(text[1]) - CFPython.Say(whoami, "I have seen '%s' joining %d times, last at %s." % (text[1], count, date)) - else: - CFPython.Say(whoami, "I have never seen '%s' joining" % text[1]) - else: - CFPython.Say(whoami, 'Usage "seen "') - else: CFPython.Say(whoami, 'Do you need help?') diff --git a/python/IPO/seen.py b/python/IPO/seen.py index c47dfb5a6..8d4ac2e52 100644 --- a/python/IPO/seen.py +++ b/python/IPO/seen.py @@ -20,19 +20,22 @@ # #Updated to use new path functions in CFPython, and broken into tiny bits by -Todd Mitchell # -# seen - tells player information from logger +# seen - tells player information from logger import CFPython import sys +import string import os.path sys.path.append(os.path.join(CFPython.GetDataDirectory(),CFPython.GetMapDirectory(),'python')) + import CFLog activator=CFPython.WhoIsActivator() activatorname=CFPython.GetName(activator) whoami=CFPython.WhoAmI() +isDM=CFPython.IsDungeonMaster(activator) x=CFPython.GetXPosition(activator) y=CFPython.GetYPosition(activator) @@ -40,18 +43,65 @@ log = CFLog.CFLog() text = string.split(CFPython.WhatIsMessage()) if text[0] == 'seen': - if len(text)==2: - if log.exist(text[1]): - ip, date, count = log.info(text[1]) - if (CFPython.IsDungeonMaster(activator)): - CFPython.Say(whoami, "I have seen '%s' %d times.\nI saw them last coming from\nIP: %s\non %s." % (text[1], count, ip, date)) - else: - CFPython.Say(whoami, "I have seen '%s' %d times.\nI saw them last at %s." % (text[1], count, date)) - else: - CFPython.Say(whoami, "I have never seen '%s'." % text[1]) - else: - CFPython.Say(whoami, 'Usage "seen "') + if len(text)==2: + record = log.info(text[1]) + if record: + if isDM: + message = "I have seen '%s' %d times.\nI saw them last coming from\nIP: %s\non %s." % (text[1], int(record['Login_Count']), record['IP'], record['Last_Login_Date']) + else: + message = "I have seen '%s' %d times.\nI saw them last at %s." % (text[1], int(record['Login_Count']), record['Last_Login_Date']) + else: + message = "I have never seen '%s'." % text[1] + else: + message = 'Usage "seen "' +elif text[0] == 'help': + if isDM: + message = "How can I help you? Here is a quick list of commands:\nseen, muzzlestatus, muzzlecount, lastmuzzle, kickcount, lastkick" + else: + message = "I have seen just about everybody - go ahead and ask me." + +elif text[0] == 'muzzlecount' and isDM: + if len(text)==2: + record = log.info(text[1]) + if record: + message = "%s has been muzzled %d times" % (text[1],int(record['Muzzle_Count'])) + else: + message = "I have no knowledge of '%s'." % text[1] + else: + message = 'Usage "muzzlecount "' + +elif text[0] == 'lastmuzzle' and isDM: + if len(text)==2: + record = log.info(text[1]) + if record: + message = "%s was last muzzled on %s" % (text[1],record['Last_Muzzle_Date']) + else: + message = "I have no knowledge of '%s'." % text[1] + else: + message = 'Usage "muzzlestatus "' + +elif text[0] == 'kickcount' and isDM: + if len(text)==2: + record = log.info(text[1]) + if record: + message = "%s has been kicked %d times" % (text[1],int(record['Kick_Count'])) + else: + message = "I have no knowledge of '%s'." % text[1] + else: + message = 'Usage "kickcount "' + +elif text[0] == 'lastkick' and isDM: + if len(text)==2: + record = log.info(text[1]) + if record: + message = "%s was last kicked out on %s" % (text[1],record['Last_Kick_Date']) + else: + message = "I have no knowledge of '%s'." % text[1] + else: + message = 'Usage "lastkick "' else: - CFPython.Say(whoami, 'You looking for someone?') + message = "Do you need help?" + +CFPython.Say(whoami, message) diff --git a/python/events/python_born.py b/python/events/python_born.py index 8dc2b977b..7b37dcf52 100644 --- a/python/events/python_born.py +++ b/python/events/python_born.py @@ -22,9 +22,9 @@ import CFPython import sys -sys.path.append('%s/%s/python' %(CFPython.GetDataDirectory(),CFPython.GetMapDirectory())) +import os.path +sys.path.append(os.path.join(CFPython.GetDataDirectory(),CFPython.GetMapDirectory(),'python')) import CFLog -import string activator = CFPython.WhoIsActivator() name = CFPython.GetName(activator) diff --git a/python/events/python_kick.py b/python/events/python_kick.py new file mode 100644 index 000000000..ddc5d920a --- /dev/null +++ b/python/events/python_kick.py @@ -0,0 +1,30 @@ +# python_kick.py - handler for global KICK event +# +# Copyright (C) 2004 Todd Mitchell +# +# This program 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +import CFPython +import sys +import os.path +sys.path.append(os.path.join(CFPython.GetDataDirectory(),CFPython.GetMapDirectory(),'python')) +import CFLog + +activator = CFPython.WhoIsActivator() +name = CFPython.GetName(activator) + +log = CFLog.CFLog() +log.kick_update(name) diff --git a/python/events/python_login.py b/python/events/python_login.py index 20e11e378..bb2a24275 100644 --- a/python/events/python_login.py +++ b/python/events/python_login.py @@ -22,10 +22,10 @@ import CFPython import sys -sys.path.append('%s/%s/python' %(CFPython.GetDataDirectory(),CFPython.GetMapDirectory())) +import os.path +sys.path.append(os.path.join(CFPython.GetDataDirectory(),CFPython.GetMapDirectory(),'python')) import CFMail import CFLog -import string activator = CFPython.WhoIsActivator() name = CFPython.GetName(activator) @@ -34,7 +34,7 @@ ip = CFPython.WhatIsMessage() mail = CFMail.CFMail() log = CFLog.CFLog() total = mail.countmail(name) -log.update(name, ip) +log.login_update(name, ip) if total > 0: CFPython.Write('You have some mail waiting for you', activator) diff --git a/python/events/python_muzzle.py b/python/events/python_muzzle.py new file mode 100644 index 000000000..5626863c9 --- /dev/null +++ b/python/events/python_muzzle.py @@ -0,0 +1,30 @@ +# python_muzzle.py - handler for global MUZZLE event +# +# Copyright (C) 2004 Todd Mitchell +# +# This program 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 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +import CFPython +import sys +import os.path +sys.path.append(os.path.join(CFPython.GetDataDirectory(),CFPython.GetMapDirectory(),'python')) +import CFLog + +activator = CFPython.WhoIsActivator() +name = CFPython.GetName(activator) + +log = CFLog.CFLog() +log.muzzle_update(name) diff --git a/python/events/python_remove.py b/python/events/python_remove.py index 568ca3fdb..45517ec17 100644 --- a/python/events/python_remove.py +++ b/python/events/python_remove.py @@ -23,7 +23,8 @@ import CFPython import sys -sys.path.append('%s/%s/python' %(CFPython.GetDataDirectory(),CFPython.GetMapDirectory())) +import os.path +sys.path.append(os.path.join(CFPython.GetDataDirectory(),CFPython.GetMapDirectory(),'python')) import CFLog import CFBank