Ejemplo n.º 1
0
def SymphonyREST(method, endpoint, body):
    retVal = SymphonyAgentResponse()

    # Allowing for reauth from the async process
    if method != 'AUTH' and 'sessionToken' not in agentSession.headers:
        SymphonyReAuth()

    try:
        if method == 'GET':
            response = agentSession.get(endpoint)
        elif method == 'POST':
            response = agentSession.post(endpoint, data=body)
        elif method == 'POSTV2':
            response = PostV2(endpoint, body)
        elif method == 'POSTV2_1':
            response = PostV2_1(endpoint, body)
        elif method == 'AUTH':
            response = agentSession.post(endpoint)
        else:
            raise MethodNotImplementedException(method + ' is not yet implemented.')

        retVal.ResponseText = response.text
        retVal.ResponseCode = response.status_code

        if response.status_code == 200:
            retVal.Success = True
            retVal.ParseResponseJSON()
        elif response.status_code // 100 == 2:  # Any other 200 code, not success but don't throw exception
            retVal.Success = True
        else:
            response.raise_for_status()

    except requests.exceptions.HTTPError as httpex:
        errorStr = "Symphony REST Exception (http): " + str(httpex)
        botlog.LogConsoleInfo("Response Code: " + str(response.status_code))
        botlog.LogConsoleInfo("Response Message: " + response.text)
        retVal.ErrorMessage = errorStr
        stackTrace = 'Stack Trace: ' + ''.join(traceback.format_stack())
        botlog.LogSymphonyError(errorStr)
        botlog.LogSymphonyError(stackTrace)

    except requests.exceptions.RequestException as connex:
        errorStr = "Symphony REST Exception (connection - Status Code " + str(response.status_code) + \
                   "): " + str(connex)
        retVal.ErrorMessage = errorStr
        stackTrace = 'Stack Trace: ' + ''.join(traceback.format_stack())
        botlog.LogSymphonyError(errorStr)
        botlog.LogSymphonyError(stackTrace)

    except Exception as ex:
        errorStr = "Symphony REST Exception (system): " + str(ex)
        retVal.ErrorMessage = errorStr
        stackTrace = 'Stack Trace: ' + ''.join(traceback.format_stack())
        botlog.LogSystemError(errorStr)
        botlog.LogSystemError(stackTrace)

    finally:
        return retVal
Ejemplo n.º 2
0
    def Authenticate(self):

        botlog.LogConsoleInfo('Authenticating...')
        self.SessionToken = callout.GetSessionToken()

        if self.SessionToken != '':
            botlog.LogSymphonyInfo('Success! Session token obtained.')

            self.KeyAuthToken = callout.GetKeyManagerToken()

            if self.KeyAuthToken != '':
                botlog.LogSymphonyInfo('Success! Key Manager token obtained.')

                self.SessionExpirationDate = datetime.date.today() + datetime.timedelta(days=7)
                # self.RESTHeaders = {"sessionToken": self.SessionToken, "keyManagerToken": self.KeyAuthToken,
                #                     "Content-Type": "application/json"}

                self.RESTHeaders = callout.BuildHeaders(self.SessionToken, self.KeyAuthToken)

                # Attempting to use requests.Session
                callout.agentSession.headers.update(self.RESTHeaders)

                botlog.LogSymphonyInfo('Session expires on ' + str(self.SessionExpirationDate))

                self.IsAuthenticated = True
            else:
                botlog.LogSystemError("Failed to obtain KM Token")
        else:
            botlog.LogSystemError("Failed to obtain Session Token")
Ejemplo n.º 3
0
def LogSearchStart(engine: str, search: str):
    global search_index
    search_index += 1

    log.LogConsoleInfo("(" + str(search_index) + ") Searching " + engine + " for " + search)

    return search_index
Ejemplo n.º 4
0
def MatchEpic(bodytext: str):

    searchtext = bodytext.lower()
    epic_match = {}

    freq_dict = GetFrequencyDict(searchtext)

    for epic_key in EpicList:
        epic = EpicList.get(epic_key)
        for keyword in epic['keywords']:
            if keyword in freq_dict:
                count = epic_match.get(epic['name'], 0)
                epic_match[epic['name']] = count + freq_dict[keyword]

    # returns the epic name with the largest match count
    # If there are multiples with the same max count, returns the first one
    # I need to figure out a way to look at all the max values and pick the one with the
    # higher priority
    if len(epic_match) > 0:
        # log match dict to console
        log.LogConsoleInfo(json.dumps(epic_match))

        epic_name = max(epic_match.keys(), key=(lambda k: epic_match[k]))

        return EpicList.get(epic_name, DefaultItem)
    else:
        return DefaultItem
Ejemplo n.º 5
0
def ReparseRoomFeedback(messageDetail):

    streamId = messageDetail.StreamId

    if len(messageDetail.Command.UnnamedParams) > 0:
        timeStr = ''.join(messageDetail.Command.UnnamedParams)

        offsetSeconds = utdt.ConvertShorthandToSeconds(timeStr)

        if offsetSeconds <= 0:
            offsetSeconds = 15 * 60
    else:
        # Default to 15 mins if no valid time string is provided
        offsetSeconds = 15 * 60

    dtReparse = datetime.datetime.now() + datetime.timedelta(seconds=-1 *
                                                             offsetSeconds)

    messageList = symreader.GetSymphonyMessagesSinceDateTime(
        streamId, dtReparse)

    botlog.LogConsoleInfo('Attempting to resubmit (' + str(len(messageList)) +
                          ') messages.')

    from modules.plugins.Salesforce.commands import SubmitUserFeedbackCollection

    SubmitUserFeedbackCollection(messageList)
Ejemplo n.º 6
0
    def __init__(self, respItem):
        self.MessageId = msg.FormatSymphonyId(respItem.id) if hasattr(
            respItem, 'id') else '-1'
        # I REALLY don't like the idea of EAFP. Sometimes it's just better to check things first
        # instead of just throwing an exception like a big 'ol tantrum.
        self.FromUserId = str(respItem.fromUserId) if hasattr(
            respItem, 'fromUserId') else '-1'
        self.StreamId = msg.FormatSymphonyId(respItem.streamId) if hasattr(
            respItem, 'streamId') else '-1'
        # Some of the message types (like room additions) have no message
        self.MessageRaw = respItem.message if hasattr(respItem,
                                                      'message') else None
        self.Type = respItem.v2messageType if hasattr(respItem,
                                                      'v2messageType') else ''

        self.Attachments = self.ParseAttachments(respItem)
        # respItem.attachments if hasattr(respItem, 'attachments') else []

        self.IsValid = self.Type == 'V2Message'
        self.Sender = None
        self.ChatRoom = None
        self.Command = None

        if len(self.Attachments) > 0:
            log.LogConsoleInfo(respItem)
Ejemplo n.º 7
0
def GetSymphonyMessages(endpoint):
    response = callout.SymphonyGET(endpoint)

    # Messages coming from the API are formatted as an array of JSON objects
    # Thus, I need to break up the array, parse the individual objects, and pass
    # the list of python objects back to the engine
    messageItems = []
    if response.Success:
        for respItem in response.ResponseData:
            # Hopefully this will
            try:
                if respItem.v2messageType and respItem.v2messageType == 'V2Message':
                    detail = msg.MessageDetail(respItem)
                    detail.Sender = user.GetSymphonyUserDetail(
                        detail.FromUserId)
                    detail.ChatRoom = stream.GetStreamInfo(respItem.streamId)
                    botlog.LogSymphonyInfo(detail.GetConsoleLogLine())

                    if detail.Sender and detail.Sender.IsValidSender:
                        detail.InitiateCommandParsing()

                    messageItems.append(detail)
                elif respItem.v2messageType != 'V2Message':
                    botlog.LogConsoleInfo('Non-chat Message Type: ' +
                                          respItem.v2messageType)
                else:
                    botlog.LogConsoleInfo('Non-chat Message Type: unknown')

            except SystemExit:
                botlog.LogConsoleInfo('Exiting Ares.')
            except Exception as ex:
                errorStr = "Symphony REST Exception (system): " + str(ex)
                # stackTrace = 'Stack Trace: ' + ''.join(traceback.format_stack())
                exInfo = sys.exc_info()
                stackTrace = 'Stack Trace: ' + ''.join(
                    traceback.format_exception(exInfo[0], exInfo[1],
                                               exInfo[2]))
                botlog.LogSystemError(errorStr)
                botlog.LogSystemError(stackTrace)
                botlog.LogConsoleInfo(response.ResponseText)

    return messageItems
Ejemplo n.º 8
0
def PollDataFeed(datafeedId):
    datafeedEP = config.SymphonyBaseURL + '/agent/v2/datafeed/' + datafeedId + '/read'
    #datafeedEP = config.SymphonyBaseURL + '/agent/v4/datafeed/' + datafeedId + '/read'

    response = callout.SymphonyGET(datafeedEP)

    # Messages coming from the API are formatted as an array of JSON objects
    # Thus, I need to break up the array, parse the individual objects, and pass
    # the list of python objects back to the engine
    messageItems = []
    if response.Success:
        for respItem in response.ResponseData:
            # Hopefully this will
            try:
                if respItem.v2messageType and respItem.v2messageType == 'V2Message':
                    detail = msg.MessageDetail(respItem)
                    detail.Sender = user.GetSymphonyUserDetail(
                        detail.FromUserId)
                    detail.ChatRoom = stream.GetStreamInfo(respItem.streamId)
                    botlog.LogSymphonyInfo(detail.GetConsoleLogLine())

                    if detail.Sender and detail.Sender.IsValidSender:
                        detail.InitiateCommandParsing()

                    messageItems.append(detail)
                elif respItem.v2messageType != 'V2Message':
                    botlog.LogConsoleInfo('Non-chat Message Type: ' +
                                          respItem.v2messageType)
                else:
                    botlog.LogConsoleInfo('Non-chat Message Type: unknown')

            except SystemExit:
                botlog.LogConsoleInfo('Exiting Symphony Zendesk Bot.')
                #messaging.SendSymphonyMessage(_configDef['BotStreamForPing'], "Exiting Symphony Zendesk Bot.")
            except Exception as ex:
                errorStr = "Symphony REST Exception (system): " + str(ex)
                #messaging.SendSymphonyMessage(_configDef['BotStreamForPing'], "Symphony REST Exception (system): " + str(ex))
                # stackTrace = 'Stack Trace: ' + ''.join(traceback.format_stack())
                exInfo = sys.exc_info()
                stackTrace = 'Stack Trace: ' + ''.join(
                    traceback.format_exception(exInfo[0], exInfo[1],
                                               exInfo[2]))
                botlog.LogSystemError(errorStr)
                botlog.LogSystemError(stackTrace)
                botlog.LogConsoleInfo(response.ResponseText)
                #messaging.SendSymphonyMessage(_configDef['BotStreamForPing'], response.ResponseText)

    elif response.ResponseCode == 204:
        return []
    else:
        botlog.LogConsoleInfo("datafeed.py error - Response Code: " +
                              str(response.ResponseCode))
        botlog.LogConsoleInfo("Response Message: " + response.ResponseText)
        #messaging.SendSymphonyMessage(_configDef['BotStreamForPing'], "datafeed.py error - Response Code: " + str(response.ResponseCode) + " Response Message: " + response.ResponseText)

        # if the response is not successful, return None. This way, I can tell the datafeed call was bad
        # and attempt to reconnect to the server.
        return None

    return messageItems
Ejemplo n.º 9
0
    def ConnectDatafeed(self):
        self.BotUserId = user.GetBotUserId()
        botlog.LogSymphonyInfo('Bot User Id: ' + str(self.BotUserId))

        if self.DataFeedId == '':
            botlog.LogSymphonyInfo('Creating Datafeed...')
            self.DataFeedId = datafeed.CreateDataFeed()
        else:
            botlog.LogSymphonyInfo('Attempting to Reuse Existing Datafeed in 5 seconds...')
            for sleepIndex in range(0, 5):
                botlog.LogConsoleInfo(str(sleepIndex) + '...')
                time.sleep(1)

            botlog.LogSymphonyInfo('Reconnecting to Datafeed...')

        if self.DataFeedId != '':
            botlog.LogSymphonyInfo('Datafeed Connected! Id: ' + self.DataFeedId)
            self.IsDatafeedConnected = True
        else:
            botlog.LogSymphonyError('Failed to connect to Datafeed.')
    def __init__(self, respItem):
        self.MessageId = msg.FormatSymphonyId(respItem.id) if hasattr(
            respItem, 'id') else '-1'
        #self.MessageId = msg.FormatSymphonyId(respItem.messageId) if hasattr(respItem, 'messageId') else '-1'
        # I REALLY don't like the idea of EAFP. Sometimes it's just better to check things first
        # instead of just throwing an exception like a big 'ol tantrum.
        self.FromUserId = str(respItem.fromUserId) if hasattr(
            respItem, 'fromUserId') else '-1'
        #self.FromUserId = str(respItem.initiator.user.userId) if hasattr(respItem, 'initiator') else '-1'
        self.StreamId = msg.FormatSymphonyId(respItem.streamId) if hasattr(
            respItem, 'streamId') else '-1'
        #self.StreamId = msg.FormatSymphonyId(respItem.payload.messageSent.message.stream.streamId) if hasattr(respItem, 'payload') else '-1'
        #self.externalRecipients = str(respItem.payload.messageSent.message.externalRecipients) if hasattr(respItem, 'payload') else '-1'
        # Some of the message types (like room additions) have no message
        self.MessageRaw = respItem.message if hasattr(respItem,
                                                      'message') else None
        # if hasattr(respItem, 'payload'):
        #     test = str(respItem.payload.messageSent.message.message)
        #     soup = BeautifulSoup(test, "lxml")
        #     for hit in soup.findAll('div'):
        #         hit = hit.text.strip()
        #         hit = hit.replace('<', '&lt;')
        #     # test = re.search("(?<=<p>)(.*?)(?=</p>)", test, flags=re.IGNORECASE).group(0)
        #     hit = "<messageML>" + hit + "</messageML>"
        #     self.MessageRaw = hit
        # else: None
        self.Type = respItem.v2messageType if hasattr(respItem,
                                                      'v2messageType') else ''

        self.Attachments = self.ParseAttachments(respItem)
        # respItem.attachments if hasattr(respItem, 'attachments') else []

        self.IsValid = self.Type == 'V2Message'
        #self.IsValid = self.Type == 'MESSAGESENT'
        self.Sender = None
        self.ChatRoom = None
        self.Command = None

        if len(self.Attachments) > 0:
            log.LogConsoleInfo(respItem)
Ejemplo n.º 11
0
def GetKeyManagerToken():
    botlog.LogConsoleInfo('Getting Key Manager Token...')
    return GetSymphonyAuthToken(config.KeyManagerEP)
Ejemplo n.º 12
0
def GetSessionToken():
    botlog.LogConsoleInfo('Getting Session Token...')
    return GetSymphonyAuthToken(config.SessionAuthEP)
Ejemplo n.º 13
0
def SubmitFeedbackJIRAv2(messageDetail):
    try:
        issueFieldsDict = {}
        watcherList = []
        labelSet = set(messageDetail.Command.Hashtags)

        reporter_field = {
            "name": util.FindJIRAUserByEmailV2(messageDetail.Sender.Email)
        }

        issueFieldsDict['reporter'] = reporter_field

        project = 'SFDC'
        type_name = 'Unknown'
        bodyDetail: str = messageDetail.Command.MessageFlattened

        # Conduct Epic Search
        epic_item = fbmatch.MatchEpic(bodyDetail)

        if epic_item is not None:
            issueFieldsDict['assignee'] = {"name": epic_item['assignTo']}

            if epic_item['epic'] != "":
                issueFieldsDict['customfield_10200'] = epic_item['epic']

            # Union (|=) the epic specific labels with the hashtag labels
            labelSet |= set(epic_item['labels'])

            watcherList = epic_item['mention']
        else:
            log.LogConsoleInfo('No epic match was returned!')

        # convert label set to list for JSON serialization
        issueFieldsDict['labels'] = list(labelSet)

        # Determine what type the feedback is
        type_dict = {
            "bug": "Bug",
            'bugs': 'Bug',
            'defect': 'Bug',
            'defects': 'Bug',
            'problem': 'Bug',
            'problems': 'Bug',
            'feature': 'New Feature',
            'features': 'New Feature',
            'featurerequest': 'New Feature',
            'missing': 'New Feature',
            'needed': 'New Feature',
            'required': 'New Feature',
            'newfeature': 'New Feature',
            'newfeaturerequest': 'New Feature',
            'usability': 'Usability Issue',
            'useability': 'Usability Issue',
            'performance': 'Usability Issue',
            'unstable': 'Usability Issue',
            'awkward': 'Usability Issue'
        }

        for tag in messageDetail.Command.Hashtags:
            if tag.lower() in type_dict:
                type_name = type_dict[tag.lower()]
                break

        # Regex to identify hash tags.
        regexHashtags = r"(\#[a-zA-Z]+\b)"
        summary = re.sub(regexHashtags, '',
                         messageDetail.Command.MessageFlattened)

        # Build dict of UID/Users
        for uid in messageDetail.Command.Mentions:
            try:
                userStr = '_u_' + uid
                userObj = user.GetSymphonyUserDetail(uid)

                if userObj.Id != '-1':
                    bodyReplace = userObj.FullName + '(' + userObj.Email + ')'
                    bodyDetail = bodyDetail.replace(userStr, bodyReplace)

                    # no need to include the mentioned users in the Summary
                    summary = summary.replace(userStr, '')

                    jiraUser = util.FindJIRAUserByEmailV2(userObj.Email)

                    if jiraUser is not None:
                        watcherList.append(jiraUser)

            except Exception as ex:
                log.LogSystemError(str(ex))

        # clean up summary
        # Regex to replace extra spaces with single space
        regexSpace = "\s\s+"
        summary = re.sub(regexSpace, ' ', summary)[:100]

        if messageDetail.Command.CommandRaw is not None:
            summary = summary.replace(messageDetail.Command.CommandRaw, '')
            summary = summary.strip()

        nosubmit = False
        debug = False
        for tag in messageDetail.Command.Hashtags:
            if tag.lower() == 'nosubmit':
                nosubmit = True
            elif tag.lower() == 'debug':
                debug = True

        if not nosubmit:
            new_issue = util.CreateIssueV2(projectKey=project,
                                           summary=summary,
                                           desc=bodyDetail,
                                           issueTypeName=type_name,
                                           jiraFields=issueFieldsDict)

            # add watchers
            util.AddWatchersV2(new_issue, watcherList)

            msg = 'JIRA created successfully.<br/>Key: ' + new_issue.key + "<br/>JIRA Link: <a href='" + \
                  new_issue.permalink() + "'/>"

            messageDetail.ReplyToSenderv2(msg)
        else:
            msg = 'Feedback received but #nosubmit was included. Issue not sent to JIRA.'
            messageDetail.ReplyToSenderv2(msg)

        if debug:
            issueFieldsDict['project'] = project
            issueFieldsDict['summary'] = summary
            issueFieldsDict['description'] = bodyDetail
            issueFieldsDict['issueType'] = type_name

            from modules.symphony.messaging import FormatDicttoMML2 as json_format
            json_str = json_format(issueFieldsDict)

            messageDetail.ReplyToSenderv2(json_str)

    except Exception as ex:
        errStr = 'Unable to submit JIRA. Error: ' + str(ex)
        messageDetail.ReplyToSenderv2(errStr)
        stackTrace = 'Stack Trace: ' + ''.join(traceback.format_exc())
        log.LogSymphonyError(errStr)
        log.LogSymphonyError(stackTrace)
Ejemplo n.º 14
0
def LogSearchEnd(s_index: int):
    log.LogConsoleInfo("(" + str(s_index) + ") Search Complete.")