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
def LimitedAuth(self): botlog.LogSymphonyInfo('Authenticating...') for index in range(0, 5): self.Authenticate() if self.IsAuthenticated: return else: botlog.LogSymphonyError('Authentication attmept ' + str(index) + 'failed. Trying again in 5 seconds.') time.sleep(5) botlog.LogSymphonyError('Maximum authentication attempts reached. Halting bot.') exit(1)
def LimitedDatafeedConnect(self): botlog.LogSymphonyInfo('Connecting to the Datafeed...') for index in range(0, 5): self.ConnectDatafeed() if self.IsDatafeedConnected: return else: botlog.LogSymphonyError('Datafeed Connect attmpt ' + str(index) + 'failed. Trying again in 5 seconds.') time.sleep(5) botlog.LogSymphonyError('Maximum datafeed connection attempts reached. Halting bot.') exit(1)
def InitiateCommandParsing(self): if self.MessageRaw is not None: if self.MessageRaw.startswith('<message'): self.Command = tokenizer.CommandParser(self.MessageRaw, True) else: log.LogSymphonyError('Invalid MessageML: ' + self.MessageRaw) self.IsValid = False
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.')
pass for msg in messages: if msg.IsValid and msg.Sender.IsValidSender: hub.ProcessCommand(msg) else: botlog.LogSymphonyInfo( 'Error detected reading datafeed. Invalidating session...') #messaging.SendSymphonyMessage(_configDef['BotStreamForPing'], "Error detected reading datafeed. Invalidating session...") botSession.InvalidateSession() loopControl = False loopControl = botSession.StartBot() while loopCount < 10: try: Main() except SystemExit: loopCount = 99 pass except Exception as ex: botlog.LogSystemError('Error: ' + str(ex)) botlog.LogSymphonyError( 'Unhandled error, probably network difficulties at the Agent. Retrying in 5s.' ) #messaging.SendSymphonyMessage(_configDef['BotStreamForPing'],"There seems to be some network difficulties at the Agent. Please try again in 5s.") time.sleep(5) loopCount += 1
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)