#!/usr/bin/python # # import needed stuff import os, re, sys, time, ConfigParser # more than we need, strip later # the following is to mark the start of debug info for dnotify print """ ########################################################################### """ ## ## some up front notes: ## This script needs an IRC client that can write chat logs to a file. ## For it to work properly needs to be called with dnotify or inotify ## in the following form: ## dnotify -M /absolute/path/to/logs -e /path/to/saytail.py ## The /absolute/path/to/logs is set by hand at present and assigned to the ## variable logpath (see below) ## presently other markers are set to read Konversation logs but with a ## little bit of modification it should be able to read any log that is ## written one line at a time, and with a little more modification it ## should be able to read just about any log a normal user can read. ## ## Initialization # assign default varriable values # variables to hold text from log filetext = "" # the contents of the entire log" lastline = "" # the line we want to read from filetext # variables indicating what to look for in text messagemarker = "] <" # in konversation marks end time begin message special_marker = "] *" # in konversation marks /me join_marker = "] Join " # in konversation marks join nick_marker = "] Nick " # in konversation change nick # used in loop to find boundry of time stamp to message marker = "" # will set = to messagemarker or special_marker # will hold results of processed text logbody = "" # string for body, the raw message itself loghead = "" # string for head of log, likely time stamp nickname = "" # string for nickname in log, also see Notes message = "" # message minus nickname and bad characters filler = "" # goes between nick and message, was "said" # will hold final output to speech engine saytext = "" # what will be sent to dcop to say aloud # still hand coded logpath = "/home/kurt/logs/" ## ## find the file in logpath that has changed and assign to logname os.chdir(logpath) # change working directory to logpath latest = 0 # set latest to zero this_time = 0 # set this_time to zero os.listdir(logpath) # gets files that are in working directory, logpath #print os.listdir(logpath) for file in os.listdir(logpath): # loop thorough each file # get the time the file was last modified this_time = os.path.getmtime(file) # in seconds since epoch # debug line - remove later print "this_time = ",this_time if latest == 0: # this should only pass first time through latest = this_time # pick the first file as a standard for comparison # debug line - remove later print "latest = ",latest," file = ",file if this_time >= latest: # how does it compare, larger is more recent latest = this_time # if larger make it a new standard lastfile = file # if larger make its associated file new standard # debug line - remove later # print "this_time = ",this_time,"latest = ",latest # debug line - remove later print "lastfile = ",lastfile # assign the most recently modified file name in logpath to logname logname = lastfile # this was the most recently modified file, so use it ## OK, we now know which file was last updated # so put the path and name together to use later log = logpath + logname # print out values of logpath, logname, and log for testing #print "logpath is\t", logpath #print "logname is\t", logname #print "log is\t\t", log # remove later # open the log for reading logfile = open(log, "r") # temp test ... prints info about the file NOT its contents #print "here is info on logfile... ", logfile ## initialization end ## ## ## get last line of log # read in all of logfile and set as filetext filetext = logfile.readlines() # test to see what happened remove later print "filetext = \"",filetext[-1],"\"" # get the last line of the filetext & assign to lastline lastline = filetext[-1] ## end get last line of log ## ## ## Do some tricks with the last line of log # Preform any tests here to see if line not suitable to further process # if the line is a part/join/system or in any way not wanted in an obvious # way based on type of log format etc. Check for things like line starting # with *** or not including < and > and any other matching substrings etc. ## ## make function to loop through line testing & separating parts of text ## gets the head and body of the last line, lastline def get_head_body(h,b): # define function """ This function loops character by character through lastline looking for indication of end of time stamp and beginning of either a user message or a /me statement or join/part statement """ c = 0 # reset counter to 0 loghead = "" # set string which will contain the head of the line to null logbody = "" # set string which will contain the body of the line to null for lstr in lastline: # start loop going through characters in lastline if c <= lastline.find(marker) + len(marker) - 2: # see if marker reached loghead += lstr # add character from lastline to loghead else: # if it isn't the head it must be the body logbody += lstr # add character from lastline to logbody c = c + 1 # count for c, to fail when c is greater than size of head print "body =",logbody print "length of marker =", len(marker) return loghead, logbody ## end get head and body of last line, lastline ## ## ## This if, elif, else sequence to test lastline to see what kind of ## message it is. Then it is acted on accordingly # most are normal messages so we test this first if lastline.find(messagemarker) + 1: # continue if message marker is found marker = messagemarker # set marker to message marker loghead, logbody = get_head_body(loghead, logbody) # call loop function filler = " said " # needed between nick and body if normal message # debug print command next print "pass" # yes it passed c = 0 # set count to 0 nickname = "" # insures nickname is null at this point ??? is this needed ??? if logbody.find(">"): # continue if the body contains character in a nick for lstr in logbody: # start loop & go through characters in logbody if c <= logbody.find(">") + 1: # reach end of nick nickname += lstr # add characters until > is reached else: # if i t isn't the nick it is the message message += lstr # add character from logbody c = c + 1 # increase count by one # we only get here if the message marker was not found in lastline and we # now test to see if it is a /me or join/part message, the next most likely elif lastline.find(special_marker) + 1: # checks for special marker marker = special_marker # set marker to special marker # debug print command print "I found the second substring marking /me or join part" # if we got here we don't need to separate the nick from the body this next # line may change or not. Also see notes about loghead loghead, logbody = get_head_body(loghead, logbody) # call function to loop through text nickname = "" logbody = logbody[len(marker)-3:] message = logbody # We get here if lastline exists but isn't a normal message or a special # message. We just throw our hands up, sigh, and fail silently or not else: # no it didn't so now what? print "fail" # so I print "fail" print "lastline.find(special_marker) + 1 = ",lastline.find(special_marker) + 1 # debug print lines next print "loghead =",loghead print "logbody =",logbody print "message =",message ## ## do more tricks # replace <> brackets from nickname | anyone know an easier way? nickname = nickname.replace("<", "") # replaces < with null nickname = nickname.replace(">", "") # removes > with null # trim out any left over white space nickname = nickname.strip() # strips white space from nick message = message.strip() # strips white space from message # replace any unwanted characters or strings still left message = message.replace("\\", "backslash") # replace \ with "backslash" ## to do: apply more filters to nick & message # turn result into saytext to be spoken using dcop # should only do this if regular message not /me statement if len(message) and logbody.find(">"): # don't say blank message saytext = nickname + filler + message # compose actual articulation print "saytext = ",saytext # debug tool comment out when finished ## end do more tricks ## ## ## send final message to be spoken to speech engine # Start KTTSD (if not already running) os.system('kttsd') # sends kttsd command to shell # say message using dcop # can comment out next line of code to save time in debugging # since it takes quite a bit of time to say the message each time os.system('dcop kttsd KSpeech sayMessage " ' + saytext + ' " "en"') ## message should have been spoken now ## # next 3 print lines are for debugging only #print filetext, "\n", saytext, "\n" #print saytext, "\n" #print "That's all folks!" ## ## end of program ## ############################## NOTES ###################################### # # # Just a spot for thoughts not related to specific existing code # # # ########################################################################### ## RE: making note section a part of group development ################ # # Python won't take multi line comments but we mayb be able to get # around that by making a dummy variable at the end. Once development # is finished we can trim it out of the end of the file. We could start # the section with something like the above and we could easily automate # removing comments when finished, or pull notes out of files while still # in development. Not something to worry about now, but as a later help # in coordinating development. There may be other things to do with it # or it might not be worth the trouble, but maybe give it a try. # # now is this anal or what? ## ## RE: The need for keeping the head portion of a log. So far we have no # need to use it, but some time in the future we may want the script to # have the ability to speak or otherwise use the head, which is normally # if not exclusively a time stamp. ## ############################### END ######################################