def test_close_in_home_tab(self): modal_view = View( type="home", callback_id="home-tab-id", close=PlainTextObject(text="Cancel"), blocks=[DividerBlock()], ) with self.assertRaises(SlackObjectFormationError): modal_view.validate_json()
def test_eq(self): input = { "type": "modal", "blocks": [DividerBlock()], } another_input = { "type": "modal", "blocks": [DividerBlock(), DividerBlock()], } self.assertEqual(View(**input), View(**input)) self.assertNotEqual(View(**input), View(**another_input))
def test_home_tab_construction(self): home_tab_view = View( type="home", blocks=[ SectionBlock( text=MarkdownTextObject( text="*Here's what you can do with Project Tracker:*" ), ), ActionsBlock( elements=[ ButtonElement( text=PlainTextObject(text="Create New Task", emoji=True), style="primary", value="create_task", ), ButtonElement( text=PlainTextObject(text="Create New Project", emoji=True), value="create_project", ), ButtonElement( text=PlainTextObject(text="Help", emoji=True), value="help", ), ], ), ContextBlock( elements=[ ImageElement( image_url="https://api.slack.com/img/blocks/bkb_template_images/placeholder.png", alt_text="placeholder", ), ], ), SectionBlock( text=MarkdownTextObject(text="*Your Configurations*"), ), DividerBlock(), SectionBlock( text=MarkdownTextObject( text="*#public-relations*\n<fakelink.toUrl.com|PR Strategy 2019> posts new tasks, comments, and project updates to <fakelink.toChannel.com|#public-relations>" ), accessory=ButtonElement( text=PlainTextObject(text="Edit", emoji=True), value="public-relations", ), ), ], ) home_tab_view.validate_json()
def open_modal(trigger_id: str): try: view = View( type="modal", callback_id="modal-id", title=PlainTextObject(text="Awesome Modal"), submit=PlainTextObject(text="Submit"), close=PlainTextObject(text="Cancel"), blocks=[ InputBlock( block_id="b-id-1", label=PlainTextObject(text="Input label"), element=ConversationSelectElement( action_id="a", default_to_current_conversation=True, ), ), InputBlock( block_id="b-id-2", label=PlainTextObject(text="Input label"), element=ConversationMultiSelectElement( action_id="a", max_selected_items=2, default_to_current_conversation=True, ), ), ], ) api_response = client.views_open(trigger_id=trigger_id, view=view) return make_response("", 200) except SlackApiError as e: code = e.response["error"] return make_response(f"Failed to open a modal due to {code}", 200)
async def test_view_update_2(self): ack = AsyncAck() response: BoltResponse = await ack( response_action="update", view=View( type="modal", callback_id="view-id", title=PlainTextObject(text="My App"), close=PlainTextObject(text="Cancel"), blocks=[DividerBlock(block_id="b")], ), ) assert (response.status, response.body) == ( 200, "" '{"response_action": "update", ' '"view": {' '"blocks": [{"block_id": "b", "type": "divider"}], ' '"callback_id": "view-id", ' '"close": {"text": "Cancel", "type": "plain_text"}, ' '"title": {"text": "My App", "type": "plain_text"}, ' '"type": "modal"' "}" "}", )
def test_invalid_type_value(self): modal_view = View( type="modallll", callback_id="modal-id", title=PlainTextObject(text="Awesome Modal"), submit=PlainTextObject(text="Submit"), close=PlainTextObject(text="Cancel"), blocks=[ InputBlock( block_id="b-id", label=PlainTextObject(text="Input label"), element=PlainTextInputElement(action_id="a-id"), ), ], ) with self.assertRaises(SlackObjectFormationError): modal_view.validate_json()
def slack_app(): if not signature_verifier.is_valid_request(request.get_data(), request.headers): return make_response("invalid request", 403) if "payload" in request.form: payload = json.loads(request.form["payload"]) if (payload["type"] == "shortcut" and payload["callback_id"] == "open-modal-shortcut"): # Open a new modal by a global shortcut try: view = View( type="modal", callback_id="modal-id", title=PlainTextObject(text="Awesome Modal"), submit=PlainTextObject(text="Submit"), close=PlainTextObject(text="Cancel"), blocks=[ InputBlock( block_id="b-id", label=PlainTextObject(text="Input label"), element=PlainTextInputElement(action_id="a-id"), ) ], ) api_response = client.views_open( trigger_id=payload["trigger_id"], view=view, ) return make_response("", 200) except SlackApiError as e: code = e.response["error"] return make_response(f"Failed to open a modal due to {code}", 200) if (payload["type"] == "view_submission" and payload["view"]["callback_id"] == "modal-id"): # Handle a data submission request from the modal submitted_data = payload["view"]["state"]["values"] print( submitted_data ) # {'b-id': {'a-id': {'type': 'plain_text_input', 'value': 'your input'}}} return make_response("", 200) return make_response("", 404)
async def shortcuts(request: Request): form = await request.form() payload = Payload.parse_raw(form['payload']) try: team_conf = TeamConf.get(payload.team.id) except TeamConf.DoesNotExist: return Response(status_code=HTTPStatus.BAD_REQUEST) client = WebClient(team_conf.access_token) if payload.callback_id == 'edit_emoji_set': emoji_set = team_conf.emoji_set # 登録できるemojiは3つまで if emoji_set is None: emoji_count = 0 external_input = 3 blocks = [] else: emoji_count = len(emoji_set) external_input = 3 - emoji_count blocks = [ InputBlock( block_id=f'emoji_{index}', label=f':{item}:', element=PlainTextInputElement( action_id=f'emoji_{index}', initial_value=item, placeholder=':atodeyomu:', ), optional=True, ) for index, item in enumerate(emoji_set) ] blocks += [ InputBlock( block_id=f'emoji_{emoji_count + i}', label=f'追加するemoji({emoji_count + i}つ目)', element=PlainTextInputElement(action_id=f'emoji_{emoji_count + i}', placeholder=':atodeyomu:'), optional=True, ) for i in range(external_input) ] view = View(title='emojiを追加する', type='modal', callback_id='edit_emoji_set', blocks=blocks, submit='送信') if payload.trigger_id: client.views_open(trigger_id=payload.trigger_id, view=view) return Response()
def __init__(self, ack: Ack, client: WebClient, context: BoltContext, logger: logger, request: BoltRequest, view: View): logger.info("Updating Zotero config...") super().__init__(context.get('user_id')) state: dict = view.get('state') form_fields: dict = state['values'] sql_fields: dict = {'user_id': context.get('user_id')} for i in form_fields: form_field: dict = form_fields[i] for t in form_field: field_name: str = t field = form_field[t] field_type = field.get('type') field_value: dict = field.get('value') if field_type == 'static_select': field_value = field.get('selected_option').get('value') if field_value is None and hasattr(self, field_name): field_value = getattr(self, field_name) if field_name == 'zotero_api_key': field_value = self.db.cipher.encrypt( field_value.encode('utf-8')) sql_fields[field_name] = field_value placeholders: list = [] for i in range(0, len(sql_fields)): placeholders.append("?") placeholder: str = ','.join(placeholders) field_names: str = ', '.join(sql_fields.keys()) insert_query = f"INSERT OR REPLACE INTO {self.table_name} ({field_names}) VALUES({placeholder})" self.db.cursor.execute(insert_query, list(sql_fields.values())) self.db.connection.commit() ack()
def test_valid_construction(self): modal_view = View( type="modal", callback_id="modal-id", title=PlainTextObject(text="Awesome Modal"), submit=PlainTextObject(text="Submit"), close=PlainTextObject(text="Cancel"), blocks=[ InputBlock( block_id="b-id", label=PlainTextObject(text="Input label"), element=PlainTextInputElement(action_id="a-id"), ), InputBlock( block_id="cb-id", label=PlainTextObject(text="Label"), element=CheckboxesElement( action_id="a-cb-id", options=[ Option( text=PlainTextObject( text="*this is plain_text text*"), value="v1", ), Option( text=MarkdownTextObject( text="*this is mrkdwn text*"), value="v2", ), ], ), ), SectionBlock( block_id="sb-id", text=MarkdownTextObject( text="This is a mrkdwn text section block."), fields=[ PlainTextObject(text="*this is plain_text text*", emoji=True), MarkdownTextObject(text="*this is mrkdwn text*"), PlainTextObject(text="*this is plain_text text*", emoji=True), ], ), DividerBlock(), SectionBlock( block_id="rb-id", text=MarkdownTextObject( text= "This is a section block with radio button accessory"), accessory=RadioButtonsElement( initial_option=Option( text=PlainTextObject(text="Option 1"), value="option 1", description=PlainTextObject( text="Description for option 1"), ), options=[ Option( text=PlainTextObject(text="Option 1"), value="option 1", description=PlainTextObject( text="Description for option 1"), ), Option( text=PlainTextObject(text="Option 2"), value="option 2", description=PlainTextObject( text="Description for option 2"), ), ], ), ), ], ) modal_view.validate_json()
def verify_loaded_view_object(self, file): input = json.load(file) view = View(**input) self.assertDictEqual(input, view.to_dict())
def handle_command(body: dict, ack: Ack, respond: Respond, client: WebClient, logger: Logger) -> None: logger.info(body) ack( text="Accepted!", blocks=[ SectionBlock( block_id="b", text=MarkdownTextObject(text=":white_check_mark: Accepted!"), ) ], ) respond(blocks=[ SectionBlock( block_id="b", text=MarkdownTextObject( text="You can add a button alongside text in your message. "), accessory=ButtonElement( action_id="a", text=PlainTextObject(text="Button"), value="click_me_123", ), ), ]) res = client.views_open( trigger_id=body["trigger_id"], view=View( type="modal", callback_id="view-id", title=PlainTextObject(text="My App"), submit=PlainTextObject(text="Submit"), close=PlainTextObject(text="Cancel"), blocks=[ InputBlock( element=PlainTextInputElement(action_id="text"), label=PlainTextObject(text="Label"), ), InputBlock( block_id="es_b", element=ExternalDataSelectElement( action_id="es_a", placeholder=PlainTextObject(text="Select an item"), min_query_length=0, ), label=PlainTextObject(text="Search"), ), InputBlock( block_id="mes_b", element=ExternalDataMultiSelectElement( action_id="mes_a", placeholder=PlainTextObject(text="Select an item"), min_query_length=0, ), label=PlainTextObject(text="Search (multi)"), ), ], ), ) logger.info(res)
def verify_loaded_view_object(self, file): input = json.load(file) view = View(**input) self.assertTrue(view.state is None or isinstance(view.state, ViewState)) self.assertDictEqual(input, view.to_dict())