def _save_graph_and_send_slack_message(team_id, channel, graph, graph_name): if channel: new_graph_name = Graph_Filters._save_graph(graph) text = ':point_right: Created new graph called `{0}` with `{1}` nodes and `{2}` edges (based on data from graph `{3}`) ' \ .format(new_graph_name, len(graph.nodes), len(graph.edges), graph_name) slack_message(text, [], channel, team_id) sleep(1) Lambda('osbot_jira.lambdas.graph').invoke_async({ "params": ["show", new_graph_name, "viva_graph"], "data": { "channel": channel, "team_id": team_id } }) return graph
def jira_create_issue_from_slack_message(self): if self.message: slack_message( ':point_right: in jira_create_issue_from_slack_message') summary = self.message.get('text') description = "{0}".format(self.message) if summary: summary = summary.replace('+', ' ') if description: description = description.replace('+', ' ') slack_dialog = Jira_Create_Issue( summary=summary, description=description).setup().render() API_Slack(self.channel, self.team_id).slack.dialog_open( trigger_id=self.trigger_id, dialog=slack_dialog) return { "text": "in jira_create_issue_from_slack_message", "attachments": [], 'replace_original': False }
def run(event, context): load_dependencies('syncer,requests,pyppeteer,websocket-client') from osbot_aws.helpers.Lambda_Helpers import slack_message from osbot_browser.browser.sites.Web_Slack import Web_Slack from osbot_browser.browser.Browser_Lamdba_Helper import Browser_Lamdba_Helper target = event.get('target') channel = event.get('channel') team_id = event.get('team_id') width = event.get('width') height = event.get('height') scroll_by = event.get('scroll_by') delay = event.get('delay') try: if width is None: width = 1200 if height is None: height = 1000 web_slack = Web_Slack(team_id=team_id).setup() web_slack.login() web_slack.page.width(width, height) if target: web_slack.open(target) if scroll_by: web_slack.scroll_messages_by(scroll_by) if delay: web_slack.wait(delay) web_slack.fix_ui_for_screenshot() png_data = web_slack.screenshot() slack_message( ':information_source: got screenshot with size `{0}` | :point_right: sending screeenshot to slack channel `{1}`' .format(len(png_data), channel), [], channel=channel, team_id=team_id) browser_helper = Browser_Lamdba_Helper() return browser_helper.send_png_data_to_slack(team_id, channel, target, png_data) except Exception as error: return slack_message( ':red_circle: Error in `slack_web` lambda: {0}'.format(error), [], channel=channel, team_id=team_id)
def search_by_field(team_id=None, channel=None, params=None): results = [] (graph_name, graph, params) = Graph_Filters._get_graph_from_params( team_id, channel, params) if graph: # todo : add better error handling for passing to correct params for the search params = params.pop( ) # todo : add better error handling for passing to correct params for the search issues = graph.get_nodes_issues() if "=" in params: field_name, value_to_find = "".join(params).split('=') for key, issue in issues.items(): if value_to_find.lower().strip() == issue.get( field_name.strip()).lower().strip(): results.append(key) #results.append(issue.get(field_name)) if "~" in params: field_name, value_to_find = "".join(params).split('~') #field_name = params.pop(0) for key, issue in issues.items(): if value_to_find.lower().strip() in issue.get( field_name.strip()).lower().strip(): results.append(key) #results.append(issue.get(field_name)) if "!" in params: field_name, value_to_find = "".join(params).split('!') #field_name = params.pop(0) for key, issue in issues.items(): if value_to_find.lower().strip() not in issue.get( field_name.strip()).lower().strip(): results.append(key) #results.append(issue.get(field_name.strip())) if len(results) > 0: graph.set_nodes(results).remove_no_links_with_no_nodes( ) # replace with filter only_edges_with_both_nodes return Graph_Filters._save_graph_and_send_slack_message( team_id, channel, graph, graph_name) else: text = ':red_circle: no matches for the search query provided' slack_message(text, [], channel, team_id)
def screenshot(team_id=None, channel=None, params=None): params = params or [] try: url = None if len(params) > 0: url = params.pop(0).replace('<', '') \ .replace('>', '') # fix extra chars added by Slack and the u00a0 unicode char. if url == '_': # special mode to not render url = None else: message = ":point_right: taking screenshot of url: {0}".format( url) if url is None: message = ':point_right: no url provided, so showing what is currently on the browser' width = to_int(Misc.array_pop(params, 0)) height = to_int(Misc.array_pop(params, 0)) delay = to_int(Misc.array_pop(params, 0)) if width: message += ", with width `{0}`".format(width) if height: message += ", with height `{0}` (min height)".format(height) if delay: message += ", with delay of `{0}` seconds".format(delay) slack_message(message, [], channel) browser_helper = Browser_Lamdba_Helper().setup() if width: browser_helper.api_browser.sync__browser_width(width, height) png_data = browser_helper.get_screenshot_png(url, full_page=True, delay=delay) slack_message( f':point_right: got screenshot of size {len(png_data)}, sending it to Slack...', [], channel) return browser_helper.send_png_data_to_slack( team_id, channel, url, png_data) except Exception as error: import traceback message = f':red_circle: Browser Error: {error} \n {traceback.format_exc()}' #message = f':red_circle: Browser Error: {error}' return slack_message(message, [], channel, team_id)
def mindmap(team_id, channel, params, data=None): if len(params) < 1: text = ':red_circle: Hi, for the `mindmap` command, you need to provide an `graph_name`' slack_message(text, [], channel, team_id) return graph_name = params.pop(0) if len( graph_name.split('-') ) == 2: # hacked way to see if it is an issue (vs a saved graph name) action = 'mindmap_issue' else: action = 'mindmap' graph_params = ['go_js', graph_name, action] graph_params.extend(params) Lambda('osbot_browser.lambdas.lambda_browser').invoke_async({ "params": graph_params, 'data': { 'team_id': team_id, 'channel': channel } })
def test_send_menu(self): text = 'an dynamic menu' attachments = [{ "fallback": "Upgrade your Slack client to use messages like these.", "color": "3AA3E3", "attachment_type": "default", "callback_id": "select_remote_1234", "actions": [{ "name": "bugs_list", "text": "Which random bug do you want to resolve?", "type": "select", "data_source": "external", "min_query_length": 1, }] }] self.test_lambda_update() slack_message("one message", attachments, 'DDKUZTK6X')
def group_by_field(team_id=None, channel=None, params=None): if len(params) < 2: return slack_message( ':red_circle: For this filter, you need to provide a `graph_name` and a `field` name: ', [], channel, team_id) graph_name = params.pop(0) field_name = ' '.join(params) slack_message( ":point_right: Creating new graph using the `group_by_field` filter on the `{0}` field of the `{1}` graph" .format(field_name, graph_name), [], channel, team_id) graph = Graph_Filters._get_graph(graph_name) if graph: Filters().setup(graph).group_by_field(graph_name, field_name) return Graph_Filters._save_graph_and_send_slack_message( team_id, channel, graph, graph_name) else: slack_message(f':red_circle: graph *{graph_name}* not found', [], channel)
def handle_dialog_submission(self, data): callback_id = data['callback_id'] channel = data['channel']['id'] user_id = data['user']['id'] if callback_id =='jira-graph-chooser': graph_name = data['submission'].get('graph_name') Lambda('pbx_gs_python_utils.lambdas.gs.elastic_jira').invoke_async({"params": ["graph", graph_name], "user": user_id, "channel": channel}) elif callback_id == 'jira-view-issue-links': self.handle_callback_jira_view_issue_links(data) elif callback_id == 'jira-view-issue-dialogue': slack_message('jira-view-issue-dialogue: {0}'.format(data),[], channel) key = data.get('submission').get('key') result = Lambda('pbx_gs_python_utils.lambdas.gs.elastic_jira').invoke({"params": ["issue", key], "user": user_id, "channel": channel}) slack_message(result.get('text'), result.get('attachments'), channel) # elif callback_id == 'issue-search-dialog': # self.(data) else: error_message = ":red_circle: Dialog callback_id not supported: {0}".format(callback_id) slack_message(error_message, [], channel) #self.api_slack.send_message(error_message, channel=channel) return None
def render_view(self, view_name, slack_channel=None, team_id=None, graph_name=None): if self.graph: try: method_name = "view_{0}".format(view_name) method = getattr(Graph_View, method_name) try: if slack_channel: slack_message( "Generating view `{0}` for graph with `{1}` nodes and `{2}` edges" .format(view_name, len(self.graph.nodes), len(self.graph.edges)), [], slack_channel, team_id) method(self) if slack_channel: saved_graph = Lambda_Graph().save_gs_graph( self.graph, None, "{0} - {0}".format(view_name, graph_name), slack_channel) slack_message( "Saved view `{0}` as new graph `{1}`".format( view_name, saved_graph), [], slack_channel, team_id) except Exception as error: slack_message( ":red_circle: Error executing view `{0}`".format( view_name), [{ "text": "{0}".format(error) }], slack_channel, team_id) except Exception: slack_message( ":red_circle: view not found: `{0}`".format(view_name), [], slack_channel, team_id) slack_message(self.bad_params_message(), [], slack_channel, team_id) return self
def plantuml(team_id, channel, params, data): puml = '' attachments = [] if len(params) < 1: text = ':red_circle: Hi, for the `plantuml` command, you need to provide a graph name' else: graph_name = params.pop() graph = Lambda_Graph().get_gs_graph___by_name(graph_name) if graph: puml = graph.puml.puml text = 'Here is the PlantUml code for `{0}`'.format(graph_name) attachments = [{ "color": "good", "text": "```{0}```".format(puml) }] else: text = ':red_circle: Graph with name `{0}` not found! Use the command `graph last` to see a list of the latest graphs generated'.format( graph_name) slack_message(text, attachments, channel, team_id) return puml
def handle_request(self, event): event = self.fix_slack_encoding(event) channel = event.get('channel', {}).get('id') team_id = event.get('team' , {}).get('id') #slack_message('in handle request',[] , channel, team_id) event_type = event.get('type') if event_type == 'interactive_message' : return self.handle_interactive_message (event) elif event_type == 'dialog_submission' : return self.handle_dialog_submission (event) elif event_type == 'message_action' : return self.handle_message_action(event) elif event_type == 'block_actions' : return self.handle_block_action(event) elif event_type == 'dialog_cancellation' : return {} #elif event_type == 'dialog_suggestion' : return self.handle_dialog_suggestion(event) #elif 'type%22%3A%22dialog_submission' in body: return self.process_dialog_submission (self.decode_body_with_payload(body)) #elif 'type%22%3A%22message_action' in body: return self.process_interactive_action(self.decode_body_with_payload(body)) #elif 'type%22%3A%22dialog_suggestion' in body: return self.process_dialog_suggestion (self.decode_body_with_payload(body), "label") else: #slack_message("Event_Type: {0} ```{1}```".format(event_type, event), [], channel, team_id) slack_message(":red_circle: Unsupported slack action type: {0}".format(event_type), [], channel, team_id) return ":red_circle: Unsupported slack action type: {0}".format(event_type)
def handle_callback_issue_search_dialog(self, data): channel = data['channel']['id'] key = data.get('submission').get('key') if key is None: key = data.get('submission').get('key_direct') view_type = data.get('submission').get('view-type') view_engine = data.get('submission').get('view-engine') user_id = data['user']['id'] if view_type == 'table': slack_message("Generating table for key: {0}".format(key), [], channel) Lambda('pbx_gs_python_utils.lambdas.gs.elastic_jira').invoke_async({"params": ["issue", key], "user": user_id, "channel": channel}) #slack_message(result.get('text'), result.get('attachments'), channel) elif view_type == 'issue-links-vuln-path': path = 'is parent of, supports RISK, creates R3, creates R2, creates R1, has Stakeholder' view_engine = view_engine self.call_lambda_jira_view_issue_links(data, key, path, view_engine, channel) elif view_type == 'issue-links-stakeholder-path': path = 'is Stakeholder,is created by R3, is created by R2, is created by R1' view_engine = view_engine self.call_lambda_jira_view_issue_links(data, key, path, view_engine, channel) elif view_engine == 'issue-links-all-depth-1': view_engine = view_engine self.call_lambda_jira_view_issue_links(data, key, "", view_engine, channel) # elif view_type == 'issue-links-view-all': # path = 'is parent of, supports RISK, creates R3, creates R2, creates R1, has Stakeholder' # view_engine = view_engine # self.call_lambda_jira_view_issue_links(data, key, path, view_engine, channel) #Lambdas('pbx_gs_python_utils.lambdas.gs.elastic_jira').invoke_async({"params": ["issue-links", key], "channel": channel}) else: log_to_elk("Error: un-supported view engine `{0}` for key `{1}`".format(view_type,key),level= 'error')
def render(team_id, channel, params): load_dependencies('syncer,requests,pyppeteer,websocket-client') if params: target = params.pop(0) delay = Misc.to_int(Misc.array_pop(params, 0)) if len(params) == 4: clip = { 'x': int(params[0]), 'y': int(params[1]), 'width': int(params[2]), 'height': int(params[3]) } else: clip = None else: return None slack_message(":point_right: rendering file `{0}`".format(target), [], channel, team_id) return Browser_Lamdba_Helper().setup().render_file(team_id, channel, target, clip=clip, delay=delay)
def last(team_id, channel, params, data=None): n = 10 if len(params) == 1: n = int(params.pop()) graphs = Lambda_Graph().get_last_n_graphs_of_type('lambda_graph', n) row_separator = '|{0}|\n'.format("-" * 72) row_format = '| {0:2} | {1:9} | {2:5} | {3:5} | {4:24} | {5:10} |\n' graphs_text = '```' graphs_text += row_format.format('#', ' who ', 'nodes', 'edges', ' type', ' name') graphs_text += row_separator count = 1 for graph in graphs: graph_value = graph.get('value') graph_name = graph_value.get('doc_data').get('name') graph_type = graph_value.get('doc_data').get('type') extra_data = graph_value.get('doc_data').get('extra_data') user = extra_data.get('user') nodes = extra_data.get('stats').get('count_nodes') edges = extra_data.get('stats').get('count_edges') if user is None: user = "******" if graph_type is None: graph_type = "...." if graph_name is None: graph_name = "" graphs_text += row_format.format(count, user, nodes, edges, graph_type[0:24], graph_name[0:10]) count += 1 graphs_text += '```' attachments = API_Slack_Attachment(graphs_text, 'good').render() if channel: slack_message( '*Here are the last {0} graphs generated* (use `graph last n` to see more results)' .format(n), attachments, channel, team_id) else: return attachments
def send_slack_message(message): slack_message(str(message),[],'GH4L1N6PN', 'T7F3AUXGV') # send logs to gsbot-logs-gs-jira
def cmd_version(self, params, team_id=None, channel=None): if channel: slack_message(self.version, [], channel, team_id) else: return {"text": self.version, "attachments": []}
def test_get_drop_box_ui(self): channel = 'DRE51D4EM' (text, attachments) = Slack_Jira_Search().get_drop_box_ui() slack_message(text, attachments, channel)
def version(team_id, channel, params, data): if channel: slack_message(Lambda_Graph_Commands_version, [], channel, team_id) else: return Lambda_Graph_Commands_version
def log_message(message): slack_message(':point_right: {0}'.format(message), [], channel, team_id)
def show(team_id, channel, params, data=None): if len(params) < 1: text = ':red_circle: Hi, for the `show` command, you need to provide an `graph_name`' slack_message(text, [], channel, team_id) return graph_name = Misc.array_pop(params, 0) graph = Lambda_Graph().get_gs_graph___by_name(graph_name) if graph is None: text = ':red_circle: Graph with name `{0}` not found'.format( graph_name) slack_message(text, [], channel, team_id) else: default_engine = 'viva_graph' engines = Misc.array_pop(params, 0) if engines is None: engines = default_engine if engines != default_engine: # only show in case there is more than one engine text = f":point_right: Showing graph with name `{graph_name}`, with `{len(graph.nodes)}` nodes and `{len(graph.edges)}` edges)" slack_message(text, [], channel, team_id) if 'plantuml' in engines: slack_message('...using `plantuml`', [], channel, team_id) Lambda('gw_bot.lambdas.puml_to_slack').invoke_async({ "puml": graph.get_puml(), "channel": channel, "team_id": team_id }) if 'vis_js' in engines: slack_message('...using `vis_js`', [], channel, team_id) params = ['graph', graph_name, 'default'] Lambda('osbot_browser.lambdas.lambda_browser').invoke_async({ "params": params, 'data': { 'team_id': team_id, 'channel': channel } }) if 'viva_graph' in engines: if engines != default_engine: # only show in case there is more than one engine slack_message('...using `viva_graph`', [], channel, team_id) params = ['viva_graph', graph_name, 'default'] Lambda('osbot_browser.lambdas.lambda_browser').invoke_async({ "params": params, 'data': { 'team_id': team_id, 'channel': channel } }) if 'go_js' in engines: slack_message('...using `go_js`', [], channel, team_id) params = ['go_js', graph_name, 'circular'] Lambda('osbot_browser.lambdas.lambda_browser').invoke_async({ "params": params, 'data': { 'team_id': team_id, 'channel': channel } })
def test_handle_dialogue_suggestions(self): #self.test__update_lambda_slack_actions() channel = 'DDKUZTK6X' (text, attachments) = Slack_Jira_Search().get_drop_box_ui() slack_message(text, attachments, channel)
def test_get_actions_ui(self): text, attachments = self.slack_actions.get_actions_ui() slack_message(text, attachments, 'DDKUZTK6X')
def cmd_links(self, params, team_id=None, channel=None, user=None, only_create=False, save_graph=True): if len(params) < 2: text = ':point_right: Hi, here are the valid parameters for the `jira links` command: ' \ '\n\t\t - `jira key` ' \ '\n\t\t - `depth` (default to 1)' \ '\n\t\t - `view engine`: viva_graph (default), or plantuml' \ '\n\t\t - `width` (of graph)' \ '\n\t\t - `delay` (before screenshot)' return {"text": text, "attachments": []} target = array_get(params, 1) depth = to_int(array_get(params, 2), 1) # default to depth 1 view_engine = array_get(params, 3, 'viva_graph') width = to_int(array_get(params, 4), None) delay = to_int(array_get(params, 5), None) if depth > 5: text = f':red_circle: sorry depths bigger than 5 are not supported (since 5 will already give you the only graph)' return {"text": text, "attachments": []} #direction = 'all' # change behaviour to only show all graph = Lambda_Graph().graph_links(target, depth) if graph is None: text = f':red_circle: graph not created for target `{target}`' return {"text": text, "attachments": []} if len(graph.edges) == 0: text = f':red_circle: no graph created from `{target}` (please double check that the issue ID exists)' return {"text": text, "attachments": []} graph_type = f"{target}___depth_{depth}" if save_graph is False: return graph graph_name = graph.render_and_save_to_elk(None, graph_type, channel, user) if only_create: return graph, graph_name, depth, target if channel: message = f':point_right: Created graph with *name* `{graph_name}` *from* `{target}` *depth* `{depth}`' slack_message(message, [], channel) if view_engine == 'plantuml': params = ['show', graph_name, view_engine] Lambda('osbot_jira.lambdas.graph').invoke_async({ "params": params, 'data': { 'team_id': team_id, 'channel': channel } }) else: params = [view_engine, graph_name, 'default', width, delay] Lambda('osbot_browser.lambdas.lambda_browser').invoke_async({ "params": params, 'data': { 'team_id': team_id, 'channel': channel } }) else: return graph, graph_name, depth, target
def send_message(message, channel, team_id): if channel: slack_message(message, [], channel, team_id) else: print(message) return message
def log_status(self,message): if self.team_id and self.channel: slack_message(message, [], self.channel, self.team_id)
def send_message(self, message): if self.channel: slack_message(message, [], self.channel, self.team_id) return message
def log_error(message): slack_message(':red_circle: {0}'.format(message), [], channel, team_id)
def expand(team_id=None, channel=None, params=None, data=None, only_create=False, save_graph=True): if len(params) < 3: text = ':red_circle: Hi, for the `expand` command, you need to provide the following parameters: ' attachment_text = '- *graph_name*: the graph to expand\n' \ '- *depth* : how many cycles to expand\n' \ '- *links to expand*: as a comma-delimited list ' slack_message(text, [{'text': attachment_text}], channel, team_id) return create_params = ["expand"] + list( params ) # create copy of array so that we don't lose data with the pops below graph_or_key = params.pop(0) depth = int(params.pop(0)) link_types_to_add = ' '.join(params).split(',') graph = Lambda_Graph().get_gs_graph___by_name(graph_or_key) if graph is None: graph = GS_Graph() # if it wasn't a graph graph.add_node(graph_or_key) # use it as key (graph.set_puml_link_types_to_add( link_types_to_add).add_all_linked_issues( [], depth).set_create_params(create_params)) if save_graph: new_graph_name = graph.reset_puml().render_and_save_to_elk() else: return graph if only_create: return graph, new_graph_name, graph_or_key, depth, link_types_to_add if channel: # if the channel value is provided render the new graph and send it to slack, if not, just return the new graph data text = "Rendering new graph called `{0}`,\n Which was created by expanding the graph/key `{1}` with depth `{2}`, for link types `{3}` (`{4}` nodes, `{5}` edges)"\ .format(new_graph_name, graph_or_key, depth, link_types_to_add, len(graph.nodes), len(graph.edges)) slack_message(text, [], channel, team_id) Lambda('gw_bot.lambdas.puml_to_slack').invoke({ "puml": graph.get_puml(), "channel": channel, "team_id": team_id }) else: data = { "graph_or_key": graph_or_key, "depth": depth, "nodes": graph.nodes, "edges": graph.edges, "puml": graph.puml.puml, "graph_name": new_graph_name } return json.dumps(data, indent=4)