Пример #1
0
    def post(self, ns_instance_id):

        # 1. [WEB->RESTIF] RECEIVE PROCESS
        try:
            content = request.get_json(force=True)
            data = json.dumps(content)
        except Exception as e:
            data = ''

        # 2. [WEB->RESTIF] RECEIVE LOGGING
        ServiceManager.RecvLogging(self.logger, data, request)

        # 3. [RESTIF->APP] MAKE SEND STRUCT
        self.clientId = PLTEManager.getInstance().getClientReqId()
        reqMsg = ServiceManager.setApiToStructMsg(request, data, self.clientId)

        # 4. [RESTIF->APP] SEND QUEUE MESSAGE(RELAY)
        PLTEManager.getInstance().sendCommand(ApiDefine, self, reqMsg)

        # 5. WAIT
        self.receiveReqId = -1
        while self.clientId != self.receiveReqId:
            try:
                time.sleep(1)
            except Exception as e:
                self.logger.error(e)

        # 6. [RESTIF->WEB] SEND LOGGING
        ServiceManager.SendLogging(self.logger, self.resMsg)

        # 7. [RESTIF->WEB] SEND RESPONSE
        return flask.Response(
            self.resMsg.jsonBody,
            # mimetype=content_type,
            status=self.rspCode)
Пример #2
0
 def __init__(self, requestQueue, responseQueue, botID, debug=False) :
     Thread.__init__(self)
     self.messageRequestQueue = requestQueue
     self.messageResponseQueue = responseQueue
     self.serviceRequestQueue = Queue.Queue()
     self.serviceResponseQueue = Queue.Queue()
     self.subscriptionHandler = None
     self.botID = botID
     self.debug = debug
     self.serviceManager = ServiceManager()
     if(self.debug) : logger.debug('MessageHandler successfully created')
Пример #3
0
    def post(self, nsInstanceId):

        # 1. [WEB->RESTIF] RECEIVE PROCESS
        try:
            content = request.get_json(force=True)
            data = json.dumps(content)
        except Exception as e:
            data = ''

        # 2. [WEB->RESTIF] RECEIVE LOGGING
        ServiceManager.RecvLogging(self.logger, data, request)

        # 3. [RESTIF->APP] MAKE SEND STRUCT
        header = HttpHeader()
        header.method = ServiceManager.getMethodType(request.method)
        header.api_type = ApiType.NSLCM_API_TYPE
        header.resource_type = ResourceType.NSLCM_INSTANTIATE_NS_TASK
        header.op_type = OPType.Instantiate_NS_OP_TYPE
        header.encoding = ContentEncoding.PLAIN

        Info = ServiceManager.getHttpInfo(nsInstanceId)

        self.clientId = PLTEManager.getInstance().getClientReqId()
        reqMsg = ServiceManager.setApiToStructMsg(request, data, self.clientId,
                                                  header, Info)
        #reqMsg.info.ns_instance_id = nsInstanceId

        # 4. [RESTIF->APP] SEND QUEUE MESSAGE(RELAY)
        PLTEManager.getInstance().sendCommand(ApiDefine.NS_INSTANTIATION, self,
                                              reqMsg)

        # 5. WAIT
        self.receiveReqId = -1
        while self.clientId != self.receiveReqId:
            try:
                time.sleep(1)
            except Exception as e:
                self.logger.error(e)

        # 6. [RESTIF->WEB] SEND LOGGING
        ServiceManager.SendLogging(self.logger, self.resMsg)

        # 7. [RESTIF->WEB] SEND RESPONSE
        return flask.Response(
            self.resMsg.jsonBody,
            # mimetype=content_type,
            status=self.rspCode)
    def __init__(self, serviceRequestQueue, serviceResponseQueue, debug=False):
        Thread.__init__(self)
        # Set up Mongo DB
        client = pymongo.MongoClient(config.slack['mongoDB']['uri'])
        db = client[config.slack['mongoDB']['dbName']]
        self.collection = db[config.slack['mongoDB']['collectionName']]

        self.running = True
        self.debug = debug
        self.serviceRequestQueue = serviceRequestQueue
        self.serviceResponseQueue = serviceResponseQueue
        self.serviceManager = ServiceManager()
        self.serviceFunctions = self.setUpServiceFunctions()
        self.usersSubscriptions = {
        }  # Determine which users have access to which services
        if (self.debug):
            logger.debug('SubscriptionHandler successfully created')
Пример #5
0
def main():

    args = prepCmdArgs()
    try:

        ServiceManager().validateConfig()
        xBot = ExampleBot(config.slack['token'], args.debug)
        xBot.run()
    except Exception as e:
        print("Exception: " + e)
        sys.exit(1)
Пример #6
0
from ServiceManager import ServiceManager
import xml.etree.ElementTree as ET
import requests
import datetime
import re
import sys
#from flask import Flask
#from flask import request

#app = Flask(__name__)

myservice = ServiceManager()

# test dhl dropoff service
# paramdhl = {}
# paramdhl["pickup_date"] = "2017-05-26"
# paramdhl["ready_by_time"] = "10:20"
# paramdhl["close_time"] = "14:20"
paramdhl = {
    "requestor": {
        "name": "Rikhil",
        "phone": "23162",
        "company": "Saurabh"
    },
    "place": {
        "line1": "123 Test Ave",
        "line2": "Test Bus Park",
        "package_location": "Reception",
        "city": "PARIS",
        "post_code": "75018",
        "country_code": "FR"
Пример #7
0
class CLI:
    """A command line service manager"""
    _currentSubDomain = None
    _currentDomain = None
    _currentSubDomain = None
    _serviceManager = ServiceManager()

    def __init__(self):
        """Start the interactive cluster editor"""
        # Start the interactive shell
        while True:
            commandReturn = self._getCommand()
            # Check if the shell should be terminated
            if commandReturn == CommandReturnCode.Exit:
                break

    def _getCommand(self):
        """Prompt the user to input another command and run it
        
        Returns:
            CommandReturnCode: The run commands return code
        """
        commandString = input(ConsoleMod.HEADER + 'ServiceManager>' +
                              ConsoleMod.ENDC)
        command = Command(commandString)

        # No command was specified
        if len(command) == 0:
            return CommandReturnCode.Unknown

        # Exit the shell
        if command == 'exit':
            return CommandReturnCode.Exit

        # Domain commands
        commandReturnCode = self.__processDomainCommands(command)
        if commandReturnCode != CommandReturnCode.Unknown:
            return commandReturnCode

        # SubDomain commands
        commandReturnCode = self.__processSubDomainCommands(command)
        if commandReturnCode != CommandReturnCode.Unknown:
            return commandReturnCode

        # Module commands
        commandReturnCode = self.__processModuleCommands(command)
        if commandReturnCode != CommandReturnCode.Unknown:
            return commandReturnCode

        # The command couldn't be processed
        print(ConsoleMod.WARNING + 'command "' + commandString +
              '" couldn\'t be processed' + ConsoleMod.ENDC)
        return CommandReturnCode.Unknown

    def __processDomainCommands(self, command):
        """Process Domain related commands
        usage: [select|create|exit|delete|get|list|ls|current] [dm|domain] [DOMAIN]
        
        Args:
            command (string): The command input by the user
        
        Returns: The processed commands return code
        """
        # Make sure this is a domain command
        if len(command) not in range(2, 4) or (command[1] != 'dm'
                                               and command[1] != 'domain'):
            return CommandReturnCode.Unknown
        # Set variables
        commandName = command[0]
        domainName = command[2] if len(command) == 3 else ''

        # Select (and create if it doesn't exist) a domain
        if commandName == 'select' and domainName != '':
            # Tell user about possibly leaving a previous domain
            if self._currentDomain is not None:
                print('left domain "' + str(self._currentDomain))
            # Get the domain from the manager
            self._currentDomain = self._serviceManager.domain(domainName)
            print('selected domain "' + str(self._currentDomain) + '"')
            return CommandReturnCode.Success
        # Exit the current domain
        elif commandName == 'exit':
            print('left domain "' + str(self._currentDomain))
            self._currentDomain = None
            return CommandReturnCode.Success
        # Create a new domain
        elif commandName == 'create' and domainName != '':
            domain = self._serviceManager.domain(domainName)
            print('created domain "' + str(domain) + '"')
            return CommandReturnCode.Success
        # Delete a domain
        elif commandName == 'delete' and domainName != '':
            # Get the domain
            domain = self._serviceManager.domain(domainName)
            domainName = str(domain)
            # Now delete it
            self._serviceManager.deleteDomain(domain)
            print('deleted domain "' + domainName + '"')
            return CommandReturnCode.Success
        # Show the name of the currently selected domain
        elif commandName == 'current':
            print('current domain "' + str(self._currentDomain) + '"')
            return CommandReturnCode.Success
        # TODO: add a command to show a domains details
        # List all existing domains
        elif commandName == 'get' or commandName == 'list' or commandName == 'ls':
            print('available domains:')
            for domain in self._serviceManager.domains:
                print('\t', domain)
            return CommandReturnCode.Success
        # No matching command
        return CommandReturnCode.Unknown

    def __processSubDomainCommands(self, command):
        """Process SubDomain related commands
        usage: [select|create|exit|delete|get|list|ls|current] [sd|subdomain] [SUBDOMAIN]
        
        Args:
            command (string): The command input by the user
        
        Returns: The processed commands return code
        """
        # Make sure this is a subdomain command
        if len(command) not in range(2, 4) or (command[1] != 'sd'
                                               and command[1] != 'subdomain'):
            return CommandReturnCode.Unknown
        # A domain has to be selected for this
        if self._currentDomain is None:
            print(ConsoleMod.FAIL + 'a domain has to be selected' +
                  ConsoleMod.ENDC)
            return CommandReturnCode.Error
        # Set variables
        commandName = command[0]
        subDomainName = command[2] if len(command) == 3 else ''

        # Select (and create if it doesn't exist) a subdomain
        if commandName == 'select' and subDomainName != '':
            # Tell user about possibly leaving a previous subdomain
            if self._currentSubDomain is not None:
                print('left subdomain "' + str(self._currentSubDomain))
            # Get the subdomain from the current domain
            self._currentSubDomain = self._currentDomain.subDomain(
                subDomainName)
            print('selected subdomain "' + str(self._currentSubDomain) + '"')
            return CommandReturnCode.Success
        # Exit the current domain
        elif commandName == 'exit':
            print('left subdomain "' + str(self._currentSubDomain))
            self._currentSubDomain = None
            return CommandReturnCode.Success
        # Create a new subdomain
        elif commandName == 'create' and subDomainName != '':
            subdomain = self._currentDomain.subDomain(subDomainName)
            print('created subdomain "' + str(subdomain) + '"')
            return CommandReturnCode.Success
        # Delete a subdomain
        elif commandName == 'delete' and subDomainName != '':
            # Get the subdomain
            subdomain = self._currentDomain.subDomain(subDomainName)
            subDomainName = str(subdomain)
            # Now delete it
            subdomain.delete()
            print('deleted subdomain "' + subDomainName + '"')
            return CommandReturnCode.Success
        # Show the name of the currently selected subdomain
        elif commandName == 'current':
            print('current subdomain "' + str(self._currentSubDomain) + '"')
            return CommandReturnCode.Success
        # TODO: add a command to show a subdomains details
        # List all existing subdomains for this domain
        elif commandName == 'get' or commandName == 'list' or commandName == 'ls':
            print('available subdomains:')
            for subdomain in self._currentDomain.subDomains:
                print('\t', subdomain)
            return CommandReturnCode.Success
        # No matching command
        return CommandReturnCode.Unknown

    def __processModuleCommands(self, command):
        """Process Module related commands
        usage: [add|create|delete|rm|clean|up|down|get|list|ls|current] [md|module] [MODULE]
        
        Args:
            command (string): The command input by the user
        
        Returns: The processed commands return code
        """
        # Make sure this is a module command
        if len(command) not in range(2, 4) or (command[1] != 'md'
                                               and command[1] != 'module'):
            return CommandReturnCode.Unknown
        # A subdomain has to be selected for this
        if self._currentSubDomain is None:
            print(ConsoleMod.FAIL + 'a subdomain has to be selected' +
                  ConsoleMod.ENDC)
            return CommandReturnCode.Error
        # Set variables
        commandName = command[0]
        moduleName = command[2] if len(command) == 3 else ''

        # Add a new module to the current subdomain
        if (commandName == 'add'
                or commandName == 'create') and moduleName != '':
            # Create the module and add it to the subdomain
            module = ModuleLoader.new(moduleName, self._currentSubDomain)
            self._currentSubDomain.addModule(module)
            print('created module "' + str(module) + '"')
            return CommandReturnCode.Success
        # Delete a module from the current subdomain
        elif commandName == 'delete' or commandName == 'rm' or commandName == 'clean':
            moduleName = str(self._currentSubDomain.activeModule)
            self._currentSubDomain.deleteModule()
            print('deleted module "' + moduleName + '" from subdomain "' +
                  str(self._currentSubDomain) + '"')
            return CommandReturnCode.Success
        # Bring all containers of this module up
        elif commandName == 'up':
            # A module has to be active for this
            if self._currentSubDomain.activeModule is None:
                print(ConsoleMod.FAIL + 'the current subdomain "' +
                      str(self._currentSubDomain) + '" has no active module' +
                      ConsoleMod.ENDC)
                return CommandReturnCode.Error
            # Bring up the module
            self._currentSubDomain.activeModule.up()
            print('module "' + str(self._currentSubDomain.activeModule) +
                  '" is coming up')
            return CommandReturnCode.Success
        # Shut all containers of this module down
        elif commandName == 'down':
            # A module has to be active for this
            if self._currentSubDomain.activeModule is None:
                print(ConsoleMod.FAIL + 'the current subdomain "' +
                      str(self._currentSubDomain) + '" has no active module' +
                      ConsoleMod.ENDC)
                return CommandReturnCode.Error
            # Shut the containers down
            self._currentSubDomain.activeModule.down()
            print('module "' + str(self._currentSubDomain.activeModule) +
                  '" is going down')
            return CommandReturnCode.Success
        # TODO: add a command to show container logs
        # TODO: add a command to show container status
        # TODO: add a command to show module status (up/down/warning/error)
        # TODO: add a command to show a modules details
        # Show the name of the module for the currently selected subdomain
        elif commandName == 'get' or commandName == 'list' or commandName == 'ls' or commandName == 'current':
            print('current module "' +
                  str(self._currentSubDomain.activeModule) + '"')
            return CommandReturnCode.Success
        # No matching command
        return CommandReturnCode.Unknown
class SubscriptionHandler(Thread):
    def __init__(self, serviceRequestQueue, serviceResponseQueue, debug=False):
        Thread.__init__(self)
        # Set up Mongo DB
        client = pymongo.MongoClient(config.slack['mongoDB']['uri'])
        db = client[config.slack['mongoDB']['dbName']]
        self.collection = db[config.slack['mongoDB']['collectionName']]

        self.running = True
        self.debug = debug
        self.serviceRequestQueue = serviceRequestQueue
        self.serviceResponseQueue = serviceResponseQueue
        self.serviceManager = ServiceManager()
        self.serviceFunctions = self.setUpServiceFunctions()
        self.usersSubscriptions = {
        }  # Determine which users have access to which services
        if (self.debug):
            logger.debug('SubscriptionHandler successfully created')

    # Entry point for thread
    def run(self):

        self.loadScheduledJobs()

        while (self.running):
            try:

                schedule.run_pending()
                self.checkJobQueue()
            except (KeyboardInterrupt, SystemError):
                print(
                    "\n~~~~~~~~~~~ SubscriptionHandler KeyboardInterrupt Exception Found~~~~~~~~~~~\n"
                )
                self.running = False

    # Checks for updates of jobs
    def checkJobQueue(self):

        if (not self.serviceRequestQueue.empty()):

            request = self.serviceRequestQueue.get()
            self.serviceRequestQueue.task_done()

            serviceName = request['scheduleJob']['serviceName']
            tag = self.produceTag(request)

            if (self.debug):
                logger.info(
                    "SubscriptionHandler request found {}".format(request))

            if (request['scheduleJob']['action'] == 'add'):

                scheduleSuccessful = self.scheduleJob(request)
                dbSaveSuccessful = self.saveJob(request)

                if (scheduleSuccessful and dbSaveSuccessful):

                    self.addUserToSubscription(tag)

                    response = "Successfully scheduled and saved {} service request of type {} every {} {}.".format(
                        serviceName, request['scheduleJob']['type'],
                        str(request['scheduleJob']['interval']),
                        request['scheduleJob']['frequency'])
                    slackResponse = self.generateSlackResponse(
                        request['messageInfo']['slackUserId'],
                        request['messageInfo']['channel'], response)

                    self.serviceResponseQueue.put(slackResponse)

                else:
                    print(request)
                    response = "Unable to subscribe you to {} because you are already subscribe to this serivce.".format(
                        serviceName)

                    slackResponse = self.generateSlackResponse(
                        request['messageInfo']['slackUserId'],
                        request['messageInfo']['channel'], response)

                    self.serviceResponseQueue.put(slackResponse)

            elif (request['scheduleJob']['action'] == 'remove'):

                unscheduleSuccessful = self.unscheduleJob(request)
                dbRemoveSuccessful = self.deleteJob(request)

                if (unscheduleSuccessful and dbRemoveSuccessful):

                    self.removeUserFromSubscription(tag)

                    response = "Successfully unscheduled and removed {} service request of type {} every {} {}.".format(
                        request['scheduleJob']['serviceName'],
                        request['scheduleJob']['type'],
                        str(request['scheduleJob']['interval']),
                        request['scheduleJob']['frequency'])
                    slackResponse = self.generateSlackResponse(
                        request['messageInfo']['slackUserId'],
                        request['messageInfo']['channel'], response)

                    self.serviceResponseQueue.put(slackResponse)
                else:

                    response = "Unable to unsubscribe you from {} because you are no longer subscribe to this serivce.".format(
                        serviceName)
                    slackResponse = self.generateSlackResponse(
                        request['messageInfo']['slackUserId'],
                        request['messageInfo']['channel'], response)

                    self.serviceResponseQueue.put(slackResponse)

            elif (request['scheduleJob']['action'] == 'update'):

                updateSuccessful = self.updateJob(request)

                if (updateSuccessful):
                    response = "Successfully updated {} service request of type {} every {} {}.".format(
                        request['scheduleJob']['serviceName'],
                        request['scheduleJob']['type'],
                        str(request['scheduleJob']['interval']),
                        request['scheduleJob']['frequency'])
                    slackResponse = self.generateSlackResponse(
                        request['messageInfo']['slackUserId'],
                        request['messageInfo']['channel'], response)
                    self.serviceResponseQueue.put(slackResponse)
                else:

                    response = "Unable to update your service for service: {}.".format(
                        serviceName)
                    slackResponse = self.generateSlackResponse(
                        request['messageInfo']['slackUserId'],
                        request['messageInfo']['channel'], response)

                    self.serviceResponseQueue.put(slackResponse)

            else:
                print("Unknown action for Service request.")

    # Adds to reoccuring job to DB
    def saveJob(self, request):
        #FIXME: Use Mongo Schema to prevent ulgy jobs entrying db
        userId = request['messageInfo']['slackUserId']
        service = request['scheduleJob']['serviceName']

        # tag = self.produceTag(userId, service)
        tag = self.produceTag(request)

        if (not self.subscriptionExists(tag)):
            request['scheduleJob']['serviceTag'] = tag
            dbResult = self.collection.insert_one(request)
            result = dbResult.acknowledged
        else:
            print("User id {} is already subscribed to service {}".format(
                userId, service))

            result = False

        return result

    # Removes reoccuring job to DB
    def deleteJob(self, request):

        tag = self.produceTag(request)

        if (self.subscriptionExists(tag)):

            query = {"scheduleJob.serviceTag": tag}
            dbStat = self.collection.remove(query)

            if (dbStat['n'] <= 0):
                print("ERROR removing document with tag {}.")
                return False

            else:
                print(
                    "Mongdo DB document for tag {} has been properly removed.")
                return True
        else:
            print("Unable to removed tag because it does not exist")
            return False

    # NOTE: request contains new services
    def updateJob(self, request):

        tag = self.produceTag(request)

        query = {"scheduleJob.serviceTag": tag}

        update = {
            "$set": {
                "scheduleJob.day": request['scheduleJob']['day'],
                "scheduleJob.interval": request['scheduleJob']['interval'],
                "scheduleJob.time": request['scheduleJob']['time'],
                "scheduleJob.frequency": request['scheduleJob']['frequency'],
                "scheduleJob.type": request['scheduleJob']['type']
            }
        }

        result = self.collection.find_one_and_update(query, update)

        if (result is None): return False
        else: return True

    # Adds a job to Scheduler
    def scheduleJob(self, request):

        status = True
        tag = self.produceTag(request)
        serviceName = request['scheduleJob']['serviceName']

        if (not self.subscriptionExists(tag)):

            if (self.debug):
                logger.debug("Scheduling Job ...\n{}".format(request))

            if (self.isIntraDay(request)):
                status = self.scheduleIntraDayJob(request)

            elif (self.isIntraMonth(request)):
                status = self.scheduleIntraMonthJob(request)

            elif (self.isIntraYear(request)):
                pass
                # Not Implemented
                # status = self.scheduleIntraYearJob(request)

            else:
                if (self.debug): logger.error("Unable to schedule Job")
                status = False

        else:
            print(
                "You are already Subscribe to {} service".format(serviceName))
            status = False
        return status

    # Removes schedule jobs from schedule
    def unscheduleJob(self, job):

        status = True

        if (self.debug): logger.debug("Unscheduling Job ...")

        tag = job['messageInfo']['slackUserId'] + "_" + job['scheduleJob'][
            'serviceName']

        # : Figure out if a status can be evaluated
        schedule.clear(tag)

        return status

    # Unschedules a list of users from scheduler
    def unscheduledJobByTag(self, userIds, service):

        for userId in userIds:
            tag = userId + "_" + service
            # FIXME: Status of removal?
            schedule.clear(tag)

    # Loads all jobs from DB into scheduler
    def loadScheduledJobs(self):

        jobs = self.collection.find({})
        if (self.debug): logger.debug("Found {} logs in db".format(str(jobs)))
        for job in jobs:
            self.addUserToSubscription(self.extractTag(job))
            self.scheduleJob(job)

    # loads a tag into local subscription record
    def loadSubscriptions(self, tag):

        userId, service = tag.split("_")

        if (userId in self.usersSubscriptions):
            if (not (service in self.usersSubscriptions[userId])):
                self.usersSubscriptions[userId].append(service)
        else:
            self.usersSubscriptions[userId] = [service]

    # Helper method: Adds a new intra-day schedule job
    def scheduleIntraDayJob(self, request):

        status = True
        serviceName = request['scheduleJob']['serviceName']
        func = self.serviceFunctions[serviceName]
        frequency = request['scheduleJob']['frequency']
        interval = request['scheduleJob']['interval']

        args = {}

        args['service'] = self.serviceManager.getServiceDetails(serviceName)
        args['messageInfo'] = request['messageInfo']
        args['scheduleJob'] = request['scheduleJob']

        # NOTE: When would args be None?
        if (args is not None):
            #TODO: remove set value from messagehandler and determine serivceName within this file
            tag = request['messageInfo']['slackUserId'] + "_" + request[
                'scheduleJob']['serviceName']

            if frequency == 'minutes':
                schedule.every(interval).minutes.do(func, args).tag(tag)

            elif frequency == 'seconds':
                schedule.every(interval).seconds.do(func, args).tag(tag)

            elif frequency == 'hours':
                schedule.every(interval).hours.do(func, args).tag(tag)

            else:
                print("ERROR OCCURRED")
                status = False
        else:
            print("Error Occurred while searching for ServiceDetails")
            status = False

        return status

    # Helper method: Adds a new intra month schedule job
    def scheduleIntraMonthJob(self, job):
        pass

    # Helper method: Adds a new intra year schedule job
    def scheduleIntraYearJob(self, job):
        pass

    # Assigns a runnable function to each of the services in the service config
    def setUpServiceFunctions(self):

        serviceFunc = {}

        services = self.serviceManager.getAllServicesDetails()

        for service in services:
            serviceName = service['name']
            location = service['path']

            if (location.lower() == "internal"):
                methodName = service['entrypoint']
                function = self.getFunction(methodName)
                if (function is not None):
                    serviceFunc[serviceName] = function
            else:

                serviceFunc[serviceName] = self.runExternalService

        if (self.debug):
            logger.info("Setup Function list as {}".format(serviceFunc))

        return serviceFunc

    # Returns a function for a give serviceName
    def getFunction(self, methodName):
        if (callable(getattr(self, methodName))):
            return getattr(self, methodName)
        else:
            return None

    # Determines if there is a user subscription that exists for a given tag
    def subscriptionExists(self, tag):

        userId, service = tag.split("_")

        if (userId in self.usersSubscriptions):
            if (service in self.usersSubscriptions[userId]):
                return True
        else:
            return False

    # Adds a user to the local user subscription list
    def addUserToSubscription(self, tag):

        userId, service = tag.split("_")

        if (self.debug):
            logger.debug("service: {} userId: {} userSubscriptions: {}".format(
                service, userId, self.usersSubscriptions))

        if (userId in self.usersSubscriptions):

            self.usersSubscriptions[userId].append(service)
            if (self.debug):
                logger.debug("Added additional service to {}.".format(userId))
        else:
            self.usersSubscriptions[userId] = []
            if (self.debug):
                logger.debug("Adding new userId to usersSubscriptions")

            self.usersSubscriptions[userId].append(service)
            if (self.debug):
                logger.debug(
                    "Service: {} userId: {} added to userSubscriptions: {}".
                    format(service, userId, self.usersSubscriptions))

    # Removes a user to the local user subscription list
    def removeUserFromSubscription(self, tag):

        userId, service = tag.split("_")

        if (userId in self.usersSubscriptions):

            if (service in self.usersSubscriptions[userId]):
                self.usersSubscriptions[userId].remove(service)
            else:
                print("Tag {} does not exits. Can't remove".format(tag))

            if (not self.usersSubscriptions[userId]):
                del self.usersSubscriptions[userId]
        else:
            print("No userId {} exists".format(userId))

    #
    def getUserIdsForServiceName(self, serviceName):

        result = []

        for userId, serviceNames in enumerate(self.usersSubscriptions):
            if (serviceName in serviceNames):
                result.append(userId)

        return result

    def getServicesListForUsersId(self, userId):

        if (userId in self.usersSubscriptions):
            return self.usersSubscriptions[userId]
        else:
            return []

    def runExternalService(self, args):

        cmd = args['service']['language']
        filepath = args['service']['path'] + "/" + args['service']['entrypoint']

        serviceName = args['scheduleJob']['serviceName']

        output = subprocess.check_output([cmd, filepath])
        response = self.serviceManager.generateSlackResponseOutput(
            output, args['messageInfo'])

        if (response is not None):
            if (self.debug):
                logger.info(
                    "Returning response up to MessageHandler: {}".format(
                        response))
            self.serviceResponseQueue.put(response)
        else:
            print("The external service {} fail. Disable this service".format(
                serviceName))
            self.serviceManager.makeUnrunnableService(serviceName)
            userIds = self.getUserIdsForServiceName(serviceName)
            self.unscheduledJobByTag(userIds, serviceName)

    # Terminates thread loop
    def kill(self):
        self.running = False

    # Produces an job identifier
    def produceTag(self, request):
        return request['messageInfo']['slackUserId'] + "_" + request[
            'scheduleJob']['serviceName']

    #FIXME: Redundant method
    def extractTag(self, job):
        return job['scheduleJob']['serviceTag']

    # Determine if job is an intra day
    def isIntraDay(self, request):
        if (request['scheduleJob']['type'] == 'intra-day'): return True
        else: return False

    # Determine if job is an intra month
    def isIntraMonth(self, request):
        if (request['scheduleJob']['type'] == 'intra-month'): return True
        else: return False

    # Determine if job is an intra year
    def isIntraYear(self, request):
        if (request['scheduleJob']['type'] == 'intra-year'): return True
        else: return False

    # Text based job
    def helloJob(self, messageInfo):
        response = 'Hello World Fool!'

        self.generateSlackResponse(messageInfo['slackUserId'],
                                   messageInfo['channel'], response)

        self.serviceResponseQueue.put(messageInfo)

    # File based job
    def fileJob(self, messageInfo):

        messageInfo['action'] = 'writeToFile'
        messageInfo['responseType'] = 'file'
        messageInfo['response'] = './extras/images/slackdroid.png'

        self.serviceResponseQueue.put(messageInfo)

    def generateSlackResponse(self, slackUserId, channel, response):
        messageInfo = {}

        messageInfo['action'] = "writeToSlack"
        messageInfo['responseType'] = "text"
        messageInfo['slackUserId'] = slackUserId
        messageInfo['channel'] = channel
        messageInfo['response'] = response

        return messageInfo
Пример #9
0
from ServiceManager import ServiceManager
import datetime
import sys
import re 
import json


# from flask import Flask
# from flask import request

# app = Flask(__name__)

myservice = ServiceManager()

# test dhl dropoff service
# paramdhl = {}
# paramdhl["pickup_date"] = "2017-05-26"
# paramdhl["ready_by_time"] = "10:20"
# paramdhl["close_time"] = "14:20"
# myservice.call_service("dhl","pickup", paramdhl)

print ("\n")
# test parcel pickup service
# paramparcel = {}
# paramparcel['from'] = "France"
# paramparcel['to'] = "Cambodia"
# myservice.call_service("parcel", "pickup", paramparcel)


#========================= API GETWAY ================================
# @app.route("/<company>/<service>", methods = ["POST"])
Пример #10
0
class MessageHandler(Thread):
    
    def __init__(self, requestQueue, responseQueue, botID, debug=False) :
        Thread.__init__(self)
        self.messageRequestQueue = requestQueue
        self.messageResponseQueue = responseQueue
        self.serviceRequestQueue = Queue.Queue()
        self.serviceResponseQueue = Queue.Queue()
        self.subscriptionHandler = None
        self.botID = botID
        self.debug = debug
        self.serviceManager = ServiceManager()
        if(self.debug) : logger.debug('MessageHandler successfully created')

    # Entry point for thread
    def run(self) :
        self.running = True
        self.setUpThreads()
        # TODO: Figure out multi-threaded solution
        while(self.running) :
            try :
                if(self.messageRequestQueue.qsize() > 0) : 
                    message = self.messageRequestQueue.get()
                    if(self.debug) : logger.debug("Message requested received from Bot {}".format(str(message)))
                    self.handle(message)

                elif(self.serviceResponseQueue.qsize() > 0) :
                    response = self.serviceResponseQueue.get()
                    if(self.debug) : logger.debug("Message response received from SubscriptionHandler {}".format(str(response)))
                    self.messageResponseQueue.put(response)
            
            except(KeyboardInterrupt, SystemError) :
                if(self.debug) : logger.debug("\n~~~~~~~~~~~ MessageHandler KeyboardInterrupt Exception Found~~~~~~~~~~~\n")
                self.subscriptionHandler.kill()
                self.running = False


    def setUpThreads(self) :
        self.subscriptionHandler = SubscriptionHandler(self.serviceRequestQueue, self.serviceResponseQueue, self.debug)
        self.subscriptionHandler.setName("SubscriptionHandler Thread 1")
        self.subscriptionHandler.daemon = True
        self.subscriptionHandler.start()
        if(self.debug) : logger.info("Started thread: {}".format("SubscriptionHandler Thread 1"))

    # Parses all raw input from Slack
    def handle(self, rawInput):
        
        response = None
        if (not self.isEmpty(rawInput)) :
            if(self.isAValidMessage(rawInput) or not self.isTyping(rawInput)) :

                response = self.parseInput(rawInput)
                if(self.debug) : logger.debug("Handling valid message: {}".format(response))
                if(response != None) :
                    self.messageResponseQueue.put(response)

            else :
                if(self.debug) : logger.error("Invalid non-empty message received: {}".format(rawInput))
    
    # Kills Thread run method
    def kill(self) :
        self.running = False
        if(self.debug) : logger.info("Terminating MessageHandler")

    # Parses the raw slack input into parts
    def parseInput(self, rawInput) :

        if('user' in rawInput[0] and 'text' in rawInput[0] and 'channel' in rawInput[0]) :
            user = rawInput[0]['user']
            message = rawInput[0]['text']
            channel = rawInput[0]['channel']

            # Muscle logic 
            action, response = self.determineAction(rawInput[0])
            responseObject = self.generateMessageResponse(user, message, channel, action, response)

            return responseObject
        else :
            logger.warning("rawInput not valid. Modify handle criterion. {}".format(str(rawInput[0])))
            return None

    # Determine what action to take depending on the message
    def determineAction(self, rawInput) :

        userID = rawInput['user']
        message = rawInput['text']
        channel = rawInput['channel']
        userId = rawInput['user']

        if(self.isGreeting(message)) :
            if(self.debug) : logger.debug("Greeting found return random choice")
            return ("writeToSlack", random.choice(GREETING_RESPONSES))

        elif(self.isServiceListRequest(message)) :
            serviceList = self.serviceManager.getServicesNames()
            response = "Available Services\n"
            for index, service in enumerate(serviceList) :
                response += "\t{}. {}\n".format(index+1, service)
            
            if(self.debug) : logger.debug("Service List Request found {}".format(response))

            return ("writeToSlack", response)

        elif(self.isListAvailableServicesRequest(message)) :

            myServices = self.subscriptionHandler.getServicesListForUsersId(userId)
            response = None
            if(len(myServices) == 0) :
                response = "You are not subscribed to any services."
            else :
                response = "You are currently Subscribed to:\n"
                for index, myService in enumerate(myServices) :
                    response += "\t{}. {}\n".format(index+1, myService)

            return("writeToSlack", response)


        elif(self.isServiceRequest(message)) :
            # TODO: Determine if the two methods should be combined into one
            # TODO: Improve to handle all types of services
            
            serviceName = self.extractServiceName(message)

            if(self.serviceManager.isRunnableService(serviceName)) :
                    
                scheduleAction, scheduleType, frequency, interval = self.determineSchedule(message)

                if(self.debug) : logger.debug("Service Request for serviceName: {} scheduleAction: {}, scheduleType: {}, frequency: {}, interval {}".format(serviceName, scheduleAction, scheduleType, frequency, interval))

                if(serviceName is not None) :
                    serviceRequest = self.createServiceRequest(scheduleAction, userID, channel, serviceName, scheduleType, frequency, interval)
                    self.serviceRequestQueue.put(serviceRequest)
                    return ("writeToSlack", "Working on processing Service for message: " + self.stripTag(message) + " ...")
                else :
                    return ("writeToSlack", "Sorry I wasn't able to find a service for message: " + self.stripTag(message) + " ...")
            else :
                return ("writeToSlack", "Unable to retrieve requested service from message {}.".format(message))
        else :
            return ("writeToSlack", "Im not sure how to decipher \"" + self.stripTag(message) + "\".")

    def generateMessageResponse(self, user, message, channel, action=None, response=None) :
        
        responseObject = {}
        responseObject["user"] = str(user)
        responseObject['message'] = str(self.stripTag(message))
        responseObject['channel'] = str(channel)
        responseObject['action'] = action
        responseObject['response'] = response

        if(self.debug) : logger.debug("Generating responseObject: {}".format(str(responseObject)))
        return responseObject

    # FIXME Determine better way to parse user input and send appropriate service
    def determineSchedule(self, message) :
        
        result = None
        serviceNames = self.serviceManager.getServicesNames()
        for serviceName in serviceNames :

                if(serviceName.lower() in message.lower()) :
                    if("new" in message.lower()) :
                        result = "add"
                    elif("remove" in message.lower()) :
                        result = "remove"
                    elif("update" in message.lower()) :
                        result = "update"
                    break

        #TODO Figure out a way to parse user messages to determine action, scheduleType, frequency, and interval
        if(result == "update") :
            return (result, 'intra-day', 'minutes', 1)
        return (result, 'intra-day', 'seconds', 30)

    def createServiceRequest(self, scheduleAction, userId, channel, service, scheduleType, frequency, interval, time = None, day = None ) :

        if(self.debug) : logger.debug("Create service request with scheduleAction {} userId {} channel {} service {} schedultType {} frequency {} interval {}time {}  day {}".format(scheduleAction, userId, channel, service, scheduleType, frequency, interval, time, day))

        serviceRequest = {
            'messageInfo' : { 
                'action': None,
                'responseType' : None,      # Text of file
                'slackUserId' : userId,
                'channel' : channel,
                'response' : None
            },
            'scheduleJob' : {
                'action' : scheduleAction,
                'type' : scheduleType,
                'serviceName' : service, # Hello World
                'serviceTag' : None,
                'frequency' : frequency,
                'interval' : interval,
                'time' : time,
                'day' : day   
            }
        }

        if(self.debug) : logger.info("Created ServiceRequest {}".format(serviceRequest))

        return serviceRequest

    # FIXME Determine better way to parse user input and send appropriate service
    def extractServiceName(self, message) :
        
        result = None
        serviceNameList = self.serviceManager.getServicesNames()

        for serviceName in serviceNameList :
            if( serviceName.lower() in message.lower() ) :
                result = serviceName
                break

        return result

    # Determines if a message contains a greeting word
    def isGreeting(self, message) :
        for greeting in GREETING_KEYWORDS :
            if(greeting in message.lower()) :
                return True
        return False

    # #TODO: Improve this
    def isServiceListRequest(self, message) :
        if('list' in message.lower() and 'services' in message.lower()) : return True
        else : return False

    def isListAvailableServicesRequest(self, message) :
        if('my' in message.lower() and 'services' in message.lower()) : return True
        else : return False
    

    # TODO Implement to interact Service Manager
    def isServiceRequest(self, message) :
        for command in SERVICE_KEYWORDS :
            if(command in message.lower()) :
                return True
        return False

    # Removes the Slack bot ID from a message
    def stripTag(self, message) :
        botTag = "<@" + self.botID + ">"

        return message.replace(botTag, '').rstrip()

    # Determines if the raw input was sent by this bot
    def notSelf(self, rawInput) :
        if(rawInput[0].get('user') == self.botID) : return False
        else : return True 
    
    # Detect if a users is typing
    def isTyping(self, rawInput) :
        if(rawInput[0].get('type') == 'user_typing') : return True
        else : return False

    # Detects if raw input is Empty
    def isEmpty(self, rawInput) :
        if not rawInput : return True
        else : return False

    # Detects if the raw input is a message
    def isAValidMessage(self, rawInput) :
        if(rawInput[0].get('type') == 'message') : return True
        else : return False

    # Determines if the bot is mentioned in the raw input
    def botMentioned(self, rawInput) :
        if('text' in rawInput[0]) :
            if(self.botID in rawInput[0]['text']) : return True
        else : return False
    

    '''Example Message Handling using Textblob'''