
added configuration management for ui using agent.config folder mails is a proposal how to store mails (contains some samples) git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1887 fd906abe-77d9-0310-91a1-e0d9ade77398
582 lines
20 KiB
Python
582 lines
20 KiB
Python
#------------------------------------------------------
|
|
# AgentHome.py
|
|
# source file for agent UI
|
|
# author: Juergen Menzinger
|
|
# version: 0.1
|
|
#------------------------------------------------------
|
|
|
|
import os
|
|
from nevow import loaders, rend, static, url, inevow, tags
|
|
from nevow.inevow import IRequest
|
|
from twisted.internet import defer
|
|
|
|
from loops.agent.crawl.outlook import MSOutlook
|
|
from loops.agent import core
|
|
|
|
# ---- global definitions and settings ---------------------------------
|
|
os.environ['HOME'] = os.path.dirname(core.__file__)
|
|
OUTLOOK2000 = 1
|
|
JOBCONFIGS = os.path.join(os.path.expanduser('~'),'jobconf.txt')
|
|
MAIL_DIR = os.path.join(os.path.expanduser('~'),'mails')
|
|
agent = core.Agent()
|
|
config = agent.config
|
|
resourcesDirectory = 'resources'
|
|
templatesDirectory = 'templates'
|
|
#----------------------------------------------------------
|
|
|
|
|
|
def template(fn):
|
|
return loaders.xmlfile(os.path.join(templatesDirectory, fn))
|
|
|
|
def getConfigIndex(index_name, default_value, fn=None):
|
|
iterator = 0
|
|
index_used = True
|
|
#check what crawling jobs exist to create a valid job index
|
|
while index_used == True:
|
|
if config.crawl[iterator].setdefault(index_name,default_value) == default_value:
|
|
index_used = False
|
|
else:
|
|
index_used = True
|
|
iterator = iterator + 1
|
|
return iterator
|
|
|
|
|
|
# AgentHome
|
|
# root page of the Agent UI
|
|
|
|
class AgentHome(rend.Page):
|
|
|
|
"""Main class that builds the root ressource for the loops agent ui.
|
|
|
|
Instance variables:
|
|
usermode -- can be 'Simple' or 'Advanced'
|
|
|
|
Class methods:
|
|
At the moment all methods of this class except the __init__ although public,
|
|
are intended to be called directly or stand-alone.
|
|
|
|
__init__ -- Load the initial start-up settings from config
|
|
|
|
"""
|
|
|
|
child_resources = static.File(resourcesDirectory)
|
|
docFactory = template('agent.html')
|
|
|
|
def __init__(self,first_start=1):
|
|
""" Initialize the AgentHome object.
|
|
|
|
If first_start = 1 then the initalization procedure is run, which mainly
|
|
loads the stored settings from the agent ini-file into instance variables of the class.
|
|
|
|
Keyword arguments:
|
|
first_start -- defaults to 1
|
|
|
|
"""
|
|
print "[PAGECLASS] AgentHome"
|
|
if first_start == 1:
|
|
self.usermode = config.ui.web.setdefault('usermode','Simple')
|
|
print "[AgentHome] setting self.usermode: ", config.ui.web.usermode
|
|
|
|
"""
|
|
def locateChild(self, ctx, segments):
|
|
return self, ()
|
|
"""
|
|
|
|
# calls to child pages
|
|
|
|
def child_joboverview(self,context):
|
|
""" User requested page from menue: 'job overview' """
|
|
return JobOverView()
|
|
|
|
def child_collectOutlookMails(self,context):
|
|
"""Display page for starting Outlook Crawler"""
|
|
return AgentOutlookMailCrawl()
|
|
|
|
def child_viewOutlookMails(self,context):
|
|
"""Display page that shows all currently collected Outlook Mails."""
|
|
return AgentOutlookMailView()
|
|
|
|
# "Startpage" methods (class AgentHome)
|
|
|
|
def child_changeUserMode(self,context):
|
|
"""Change user mode.
|
|
|
|
User has klicked the Change User Mode button, so
|
|
change UserMode from Simple <-> Professional
|
|
|
|
"""
|
|
print "[child_changeUserMode] UserMode: ", config.ui.web.usermode
|
|
print "[child_changeUserMode] ----retrieving form values----"
|
|
form = IRequest(context).args
|
|
if form != {}:
|
|
for elem in form:
|
|
print "[child_changeUserMode] ", form[elem]
|
|
if config.ui.web.usermode == "Simple":
|
|
config.ui.web.usermode = "Advanced"
|
|
else:
|
|
config.ui.web.usermode = "Simple"
|
|
print "[child_changeUserMode] : ", config.ui.web.usermode
|
|
config.save()
|
|
return AgentHome(first_start=0)
|
|
|
|
# "job overview" methods (class JobOverView)
|
|
|
|
def child_ViewJobDetails(self,context):
|
|
"""Get details for the selected job.
|
|
|
|
Reads all information about the selected job from file/ database.
|
|
Returns page object which displays the available information.
|
|
|
|
"""
|
|
selected_job = ((IRequest(context).uri).split("?"))[1]
|
|
JOBDETAILS = 'joblist.txt'
|
|
file_pointer = open(JOBDETAILS,"r")
|
|
job_details = ""
|
|
job_list = file_pointer.readlines()
|
|
for line in job_list:
|
|
if line.startswith(selected_job):
|
|
job_details = line
|
|
break
|
|
file_pointer.close()
|
|
job_details = job_details.split(";")
|
|
return JobOverViewDetails(job_details)
|
|
|
|
# "collect Outlook Mails" methods (class AgentOutlookMailCrawl)
|
|
|
|
def child_submitOutlookCrawlJob(self,context):
|
|
"""Initiate Outlook crawling job as requested by user."""
|
|
|
|
ag = core.Agent()
|
|
config2 = ag.config
|
|
conf = config2
|
|
crawlSubfolder = False
|
|
form = IRequest(context).args
|
|
if form != {}:
|
|
iterator = getConfigIndex('type','unused')
|
|
#save job configuration
|
|
if form['mailCrawlInterval'][0] == "oneTime":
|
|
conf.load('crawl[%i].state = "completed"' %(iterator))
|
|
else:
|
|
conf.load('crawl[%i].state = "active"' %(iterator))
|
|
conf.load('crawl[%i].jobid = "outlook%i"' %(iterator, iterator))
|
|
conf.load('crawl[%i].type = "OutlookMail"' %(iterator))
|
|
conf.load('crawl[%i].folder = "%s"'%(iterator,form["searchFolder"][0])) #always Inbox, ev. read from Outlook which folders are available?
|
|
conf.load('crawl[%i].getsubfolder = "%s"'%(iterator,form["selectSubfolder"][0]))
|
|
conf.load('crawl[%i].latest = ""'%(iterator)) #TODO: who does parsing?
|
|
conf.load('crawl[%i].filter_criteria = "%s"'%(iterator,form["selectFilterCriteria"][0]))
|
|
conf.load('crawl[%i].filter_pattern = "%s"'%(iterator,form["filterPattern"][0]))
|
|
conf.load('crawl[%i].content_format = "%s"'%(iterator,form["selectContentFormat"][0]))
|
|
conf.load('crawl[%i].include_attachements = "%s"'%(iterator,form["selectAttachements"][0]))
|
|
conf.load('crawl[%i].interval = "%s"'%(iterator,form["mailCrawlInterval"][0]))
|
|
conf.save()
|
|
|
|
if form["mailCrawlInterval"][0] == 'oneTime':
|
|
if OUTLOOK2000 == 1:
|
|
#Outlook2000 (= Outlook 9) has different attributes
|
|
fieldsMail = ['Body',
|
|
'HTMLBody',
|
|
'CC',
|
|
'SenderName',
|
|
'Recipients',
|
|
'To',
|
|
'Attachments',
|
|
'Subject'
|
|
]
|
|
else:
|
|
fieldsMail = ['Body',
|
|
'BodyFormat',
|
|
'HTMLBody',
|
|
'CC',
|
|
'SenderEmailAddress',
|
|
'Recipients',
|
|
'To',
|
|
'Attachments',
|
|
'Subject'
|
|
]
|
|
if form["selectSubfolder"][0] == 'Yes':
|
|
crawlSubfolder = True
|
|
|
|
OutlookObj = MSOutlook()
|
|
mails = OutlookObj.loadInbox(fieldsMail,crawlSubfolder)
|
|
# currently deferreds are not implemented in outlook.py
|
|
#deferred.addCallback(self.defMailCrawl,context)
|
|
#deferred.addErrback(self.defMailCrawlError,context)
|
|
#return deferred
|
|
return self.defMailCrawl(mails,context)
|
|
else:
|
|
#TODO implement forwarding to next form (scheduler)
|
|
return AgentOutlookMailCrawl("Scheduled Mail Crawling not implemented yet.")
|
|
|
|
else:
|
|
return AgentOutlookMailCrawl("An error occurred: form data has been empty.")
|
|
return AgentOutlookMailCrawl("Crawl Job settings have been saved.")
|
|
|
|
def defMailCrawl(self,mail_collection,context):
|
|
"""Save and Forward the mail collection to a page view."""
|
|
files = os.listdir(MAIL_DIR)
|
|
filename = "Mail%i" %(len(files))
|
|
print "Writing emails to files."
|
|
for elem in mail_collection:
|
|
fp = open((os.path.join(MAIL_DIR,filename)),'w')
|
|
fp.write(str(elem))
|
|
fp.close()
|
|
return AgentOutlookMailView(mail_collection)
|
|
|
|
def defMailCrawlError(self,ErrorMessage,context):
|
|
"""Handles errors that ocurred in the MailCrawler."""
|
|
return AgentHome(first_start=0)
|
|
|
|
# rendering methods of Startpage
|
|
|
|
def render_getActiveUserMode(self,context,data):
|
|
return config.ui.web.usermode
|
|
|
|
def render_getAgentVersion(self,context,data):
|
|
return "0.1 alpha"
|
|
|
|
def render_footer_fragment(self,context,data):
|
|
return context.tag[FooterFragment(data)]
|
|
|
|
def render_navigation_fragment(self,context,data):
|
|
return context.tag[NavigationFragment(data)]
|
|
|
|
def render_top_fragment(self,context,data):
|
|
return context.tag[TopFragment(data)]
|
|
|
|
def render_header_fragment(self,context,data):
|
|
return context.tag[HeaderFragment(data)]
|
|
|
|
|
|
class FooterFragment(rend.Fragment):
|
|
docFactory = template('footer.html')
|
|
|
|
|
|
class NavigationFragment(rend.Fragment):
|
|
docFactory = template('navigation.html')
|
|
|
|
|
|
class TopFragment(rend.Fragment):
|
|
docFactory = template('top.html')
|
|
|
|
|
|
class HeaderFragment(rend.Fragment):
|
|
docFactory = template('header.html')
|
|
|
|
|
|
# subpages of AgentHome
|
|
|
|
class JobOverView(rend.Page):
|
|
|
|
"""Builds page that lists all currently registered jobs.
|
|
|
|
Instance variables:
|
|
currently none in use
|
|
|
|
Class methods:
|
|
At the moment all methods of this class except the __init__ although public,
|
|
are intended to be called directly or stand-alone.
|
|
|
|
__init__ -- Store the initial settings retrieved from AgentHome.
|
|
|
|
"""
|
|
|
|
docFactory = template('joblisting.html')
|
|
|
|
def __init__(self):
|
|
print "[PAGECLASS] JobOverView"
|
|
|
|
# rendering methods of job overview
|
|
|
|
def data_displayViewForm(self,context,data):
|
|
return "Overview of all running Crawling jobs"
|
|
|
|
def render_getActiveUserMode(self,context,data):
|
|
return config.ui.web.usermode
|
|
|
|
def render_fillJobTable(self,ctx,data):
|
|
"""Build table which displays all registered jobs."""
|
|
|
|
#---- get the registered jobs from the jobfile ----
|
|
joblist = []
|
|
iterator = 0
|
|
config.load()
|
|
while iterator < len(config.crawl):
|
|
joblist.append(dict(config.crawl[iterator].items()))
|
|
iterator = iterator + 1
|
|
for elem in joblist:
|
|
print elem
|
|
job_table = [tags.tr
|
|
[
|
|
tags.td
|
|
[
|
|
tags.a(href="ViewJobDetails?%s" %(job_details['jobid']))
|
|
[
|
|
tags.b
|
|
[
|
|
"[" + job_details['jobid'] +"]"
|
|
]
|
|
]
|
|
],
|
|
tags.td[job_details['state']],
|
|
tags.td[job_details['interval']],
|
|
tags.td[job_details['filter_criteria']],
|
|
tags.td[job_details['folder']]
|
|
]
|
|
for job_details in joblist
|
|
]
|
|
return job_table
|
|
|
|
def render_footer_fragment(self,context,data):
|
|
return context.tag[FooterFragment(data)]
|
|
|
|
def render_navigation_fragment(self,context,data):
|
|
return context.tag[NavigationFragment(data)]
|
|
|
|
def render_top_fragment(self,context,data):
|
|
return context.tag[TopFragment(data)]
|
|
|
|
def render_header_fragment(self,context,data):
|
|
return context.tag[HeaderFragment(data)]
|
|
|
|
|
|
class JobOverViewDetails(rend.Page):
|
|
|
|
"""Builds page that displays detailed information about a selected job.
|
|
|
|
Instance variables:
|
|
jobdetails -- list that contains all available job information
|
|
|
|
Class methods:
|
|
At the moment all methods of this class except the __init__ although public,
|
|
are intended to be called directly or stand-alone.
|
|
|
|
__init__ -- Store the selected job in member variable.
|
|
|
|
"""
|
|
|
|
docFactory = template('jobdetail.html')
|
|
|
|
def __init__(self, selectedJob=[]):
|
|
print "[PAGECLASS] JobOverViewDetails"
|
|
self.jobdetails = selectedJob
|
|
|
|
# rendering methods of job view details
|
|
|
|
def data_displayViewForm(self,context,data):
|
|
return "Detailed view of crawling job."
|
|
|
|
def render_getActiveUserMode(self,context,data):
|
|
return config.ui.web.usermode
|
|
|
|
def render_displayJobDetails(self,ctx,data):
|
|
"""Build the table containing information about the selected job."""
|
|
|
|
print "*******************************************************"
|
|
print "[render_displayJobDetails] received form: ", str(self.jobdetails)
|
|
print "[render_displayJobDetails] usermode: ", config.ui.web.usermode
|
|
print "*******************************************************"
|
|
job_detail = []
|
|
job_detail = [tags.tr
|
|
[
|
|
tags.td["PID"],
|
|
tags.td[self.jobdetails[0]]
|
|
],
|
|
tags.tr
|
|
[
|
|
tags.td["State"],
|
|
tags.td[self.jobdetails[1]]
|
|
],
|
|
tags.tr
|
|
[
|
|
tags.td["Interval"],
|
|
tags.td[self.jobdetails[2]]
|
|
],
|
|
tags.tr
|
|
[
|
|
tags.td["Search Criteria"],
|
|
tags.td[self.jobdetails[3]]
|
|
],
|
|
tags.tr
|
|
[
|
|
tags.td["Job Scope"],
|
|
tags.td[self.jobdetails[4]]
|
|
],
|
|
tags.tr
|
|
[
|
|
tags.td["Filter"],
|
|
tags.td[self.jobdetails[5]]
|
|
],
|
|
tags.tr
|
|
[
|
|
tags.td["Follow Up Tasks"],
|
|
tags.td[self.jobdetails[6]]
|
|
]
|
|
]
|
|
return job_detail
|
|
|
|
def render_footer_fragment(self,context,data):
|
|
return context.tag[FooterFragment(data)]
|
|
|
|
def render_navigation_fragment(self,context,data):
|
|
return context.tag[NavigationFragment(data)]
|
|
|
|
def render_top_fragment(self,context,data):
|
|
return context.tag[TopFragment(data)]
|
|
|
|
def render_header_fragment(self,context,data):
|
|
return context.tag[HeaderFragment(data)]
|
|
|
|
|
|
class AgentOutlookMailView(rend.Page):
|
|
|
|
"""Builds page that displays an overview of all collected mails.
|
|
|
|
Instance variables:
|
|
page_message -- string that is displayed on the page
|
|
mail_collection -- collection containing all currently collected mails.
|
|
|
|
Class methods:
|
|
At the moment all methods of this class except the __init__ although public,
|
|
are intended to be called directly or stand-alone.
|
|
|
|
__init__ -- Store the mail collection object and the pagemessage
|
|
|
|
"""
|
|
|
|
docFactory = template('mail.html')
|
|
|
|
def __init__(self, mail_collection=[], pagemessage=""):
|
|
print "[PAGECLASS] AgentOutlookMailView"
|
|
self.mail_collection = mail_collection
|
|
self.page_message = pagemessage
|
|
|
|
# rendering methods of Collect Outlook Mails
|
|
|
|
def data_displayViewForm(self,context,data):
|
|
return "Detailed view of all collected Outlook Mails."
|
|
|
|
def render_getActiveUserMode(self,context,data):
|
|
return config.ui.web.usermode
|
|
|
|
def render_systemMessage(self,context,data):
|
|
"""Displays messages from the system to the user."""
|
|
message = tags.b[self.page_message]
|
|
return message
|
|
|
|
def render_displayOutlookMails(self,ctx,data):
|
|
"""Builds table containing all currently collected mails."""
|
|
if self.mail_collection != []:
|
|
mail_table = [tags.tr
|
|
[
|
|
tags.td
|
|
[
|
|
tags.a(href="ViewMailDetails?%s" %(str(mailObject.get('SenderName'))))
|
|
[
|
|
tags.b
|
|
[
|
|
"[" + str(mailObject.get('SenderName')) +"]"
|
|
]
|
|
]
|
|
],
|
|
tags.td[str(mailObject.get('CC'))],
|
|
tags.td[str(mailObject.get('Subject'))],
|
|
tags.td[str(mailObject.get('To'))],
|
|
tags.td['SourceFolder']
|
|
]
|
|
for mailObject in self.mail_collection
|
|
]
|
|
return mail_table
|
|
else:
|
|
mailFiles = os.listdir(MAIL_DIR)
|
|
#TODO: read mail data from files
|
|
mail_table = [tags.tr
|
|
[
|
|
tags.td
|
|
[
|
|
tags.a(href="ViewMailDetails?%s" %(str(mail)))
|
|
[
|
|
tags.b
|
|
[
|
|
"[" + str(mail) +"]"
|
|
]
|
|
]
|
|
],
|
|
tags.td[str(mail)],
|
|
tags.td[str(mail)],
|
|
tags.td[str(mail)],
|
|
tags.td[str(mail)]
|
|
]
|
|
for mail in mailFiles
|
|
]
|
|
return mail_table
|
|
|
|
|
|
def render_footer_fragment(self,context,data):
|
|
return context.tag[FooterFragment(data)]
|
|
|
|
def render_navigation_fragment(self,context,data):
|
|
return context.tag[NavigationFragment(data)]
|
|
|
|
def render_top_fragment(self,context,data):
|
|
return context.tag[TopFragment(data)]
|
|
|
|
def render_header_fragment(self,context,data):
|
|
return context.tag[HeaderFragment(data)]
|
|
|
|
|
|
class AgentOutlookMailCrawl(rend.Page):
|
|
|
|
"""Builds page where an Outlook Mail Crawler can be configured and run.
|
|
|
|
Instance variables:
|
|
page_message -- string that is displayed on the page
|
|
|
|
Class methods:
|
|
At the moment all methods of this class except the __init__ although public,
|
|
are intended to be called directly or stand-alone.
|
|
|
|
__init__ -- store pagemessage in member variable
|
|
|
|
"""
|
|
|
|
docFactory = template('mailcrawl.html')
|
|
|
|
def __init__(self, pagemessage=""):
|
|
print "[PAGECLASS] AgentOutlookMailCrawl"
|
|
self.page_message = pagemessage
|
|
|
|
# rendering methods of Collect Outlook Mails
|
|
|
|
def data_displayViewForm(self,context,data):
|
|
return "Configure your MailCrawl Job in the form below.\
|
|
You then can either choose to start it as a\
|
|
single job, or as scheduled job (further input\
|
|
for scheduler necessary). For each new collect\
|
|
procedure a filter will be added, so that just\
|
|
mails received in Outlook after the recent Crawl\
|
|
Job has been run, will be collected."
|
|
|
|
def render_getActiveUserMode(self,context,data):
|
|
return config.ui.web.usermode
|
|
|
|
def render_displayOutlookMails(self,ctx,data):
|
|
"""Currently no implementation"""
|
|
return ""
|
|
|
|
def render_systemMessage(self,context,data):
|
|
"""Displays messages from the system to the user."""
|
|
message = tags.b[self.page_message]
|
|
return message
|
|
|
|
def render_footer_fragment(self,context,data):
|
|
return context.tag[FooterFragment(data)]
|
|
|
|
def render_navigation_fragment(self,context,data):
|
|
return context.tag[NavigationFragment(data)]
|
|
|
|
def render_top_fragment(self,context,data):
|
|
return context.tag[TopFragment(data)]
|
|
|
|
def render_header_fragment(self,context,data):
|
|
return context.tag[HeaderFragment(data)]
|
|
|