I'd like to create a modal that instantly pops up when a new user joins the channel. My thought process was to use an #app.event to trigger when a new member joins, then somehow activate my slash command. But unfortunately app.event doesn't have a trigger_id so i can't just create a modal in an event method. I'm not married to using a slash command either, but it was all I found that could get users to use checkboxes and submit the checked responses for a modal. Any help connecting the two would be great, or other suggestions would be appreciated.
#app.event("member_joined_channel")
def modal_event(event, say, body):
usr_id = event["user"],
user_id = usr_id[0]
channel_id = event["channel"]
pprint.pprint(body)
say(text=f"Welcome to the channel, <#{user_id}>! 🎉 You can introduce yourself in this channel.")
app.client.chat_postMessage(
channel=channel_id,
)
#app.command("/cmd")
def modal(body):
pprint.pprint(body)
result = app.client.views_open(
trigger_id=body['trigger_id'],
view={
"title": {
"type": "plain_text",
"text": "My App",
"emoji": True
},
"submit": {
"type": "plain_text",
"text": "Submit",
"emoji": True
},
"type": "modal",
"close": {
"type": "plain_text",
"text": "Cancel",
"emoji": True
},
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Hello, Assistant to the Regional Manager Dwight! *Michael Scott* wants to know where you'd like to take the Paper Company investors to dinner tonight.\n\n"
}
},
{
"type": "input",
"element": {
"type": "checkboxes",
"options": [
{
"text": {
"type": "plain_text",
"text": "Gary Danko",
"emoji": True
},
"value": "value-0"
},
{
"text": {
"type": "plain_text",
"text": "Chipotle",
"emoji": True
},
"value": "value-1"
},
{
"text": {
"type": "plain_text",
"text": "Slack Cafe",
"emoji": True
},
"value": "value-2"
}
]
},
"label": {
"type": "plain_text",
"text": "Please select all restaurants you'd be willing to eat at:",
"emoji": True
}
}
]
}
)
Unfortunately, you need a trigger_id to open a modal. I don't know of a way you can open one without it. What you could do is listen for the [member_joined_channel][1]event and then have your app send the user an ephemeral message in the channel prompting them to click a button which would then open a modal.
Related
Hi i have been learning to create modals in slack using python flask. Can anybody help me with opening a model, basic enough using a /command.
Thankyou !
##app.route("/raise_issue", methods=\["POST"\])
def open_modal():
trigger_id = request.form\['trigger_id'\]
client.views_open(trigger_id=trigger_id, view={
"type": "modal",
'callback_id': 'first_view',
"title": {
"type": "plain_text",
"text": "First View"
},
"submit": {
"type": "plain_text",
"text": "Submit"
},
"close": {
"type": "plain_text",
"text": "Cancel"
},
'blocks': []
} )
return '', 200
Ok so im making this discord bot that uses the Google Calendar API to get my events, when I call the command in discord it will give me a list of my events for the week. It works fine for getting only one event, but since each event has the same key names in the json im finding it hard to find if multiple keys exist within the json file, exp.
[
{
"created": "2020-05-05T18:30:24.000Z",
"creator": {
"email": "email goes here",
"self": true
},
"end": {
"dateTime": "2020-05-05T15:00:00-04:00"
},
"etag": "\"3177446035674000\"",
"htmlLink": "https://www.google.com/calendar/event?eid=MWZqdXRqZW9panZ0YmZycDVnZ2R1OG1kbnAgcHJvamVjdG5vdGlmeWNhbEBt",
"iCalUID": "1fjutjeoijvtbfrp5ggdu8mdnp#google.com",
"id": "1fjutjeoijvtbfrp5ggdu8mdnp",
"kind": "calendar#event",
"organizer": {
"email": "email goes here",
"self": true
},
"reminders": {
"useDefault": true
},
"sequence": 0,
"start": {
"dateTime": "2020-05-05T14:00:00-04:00"
},
"status": "confirmed",
"summary": "Event title 1",
"updated": "2020-05-05T23:56:57.837Z"
},
{
"created": "2020-05-06T17:48:42.000Z",
"creator": {
"email": "email goes here",
"self": true
},
"end": {
"dateTime": "2020-05-06T15:00:00-04:00"
},
"etag": "\"3177575538452000\"",
"htmlLink": "https://www.google.com/calendar/event?eid=MmtzdDVyb29mZzhydGhyb25ja2UxazVkbmcgcHJvamVjdG5vdGlmeWNhbEBt",
"iCalUID": "2kst5roofg8rthroncke1k5dng#google.com",
"id": "2kst5roofg8rthroncke1k5dng",
"kind": "calendar#event",
"organizer": {
"email": "email goes here",
"self": true
},
"reminders": {
"useDefault": true
},
"sequence": 1,
"start": {
"dateTime": "2020-05-06T14:00:00-04:00"
},
"status": "confirmed",
"summary": "Event title 2",
"updated": "2020-05-06T17:56:09.226Z"
}
So as you can see there are 2 keys for each event, the key I want to use is the "summary" key to get the event name.
In my code, its fine for getting the first key, but in the nature of the program, there may be lots of events for a given week, so how can I test if there are multiple keys, then if there are, print the others, if there arent, print saying there arent any more events. This is what I have so far:
#use google calendar api token
import pickle
credentials = pickle.load(open('token.pickle', 'rb'))
service = build('calendar', 'v3', credentials=credentials)
#get id (aka calendar name)
calendar_list = service.calendarList().list().execute()
calendar_id = calendar_list['items'][0]['id']
#get items from id
calendar_list = service.events().list(calendarId=calendar_id).execute()
#print(calendar_list['items'])
#making json
loadjson = json.dumps(calendar_list['items'])
info = json.loads(loadjson)
with open("formatteddata.json", "w") as formatted_data:
json.dump(info, formatted_data, indent=4, sort_keys=True)
#print title of event (item name)
itemtitle = info[0]["summary"]
print (itemtitle)
if ["summary"][1] in loadjson:
print("2 exist")
else:
print('does not exist')
The end portion is what Im having trouble with. I get a list index out of range error, not sure if I have the right idea or if im super far off
Hope this is what you need:
inputData = [
{
"created": "2020-05-05T18:30:24.000Z",
"creator": {
"email": "email goes here",
"self": "true"
},
"end": {
"dateTime": "2020-05-05T15:00:00-04:00"
},
"etag": "\"3177446035674000\"",
"htmlLink": "https://www.google.com/calendar/event?eid=MWZqdXRqZW9panZ0YmZycDVnZ2R1OG1kbnAgcHJvamVjdG5vdGlmeWNhbEBt",
"iCalUID": "1fjutjeoijvtbfrp5ggdu8mdnp#google.com",
"id": "1fjutjeoijvtbfrp5ggdu8mdnp",
"kind": "calendar#event",
"organizer": {
"email": "email goes here",
"self": "true"
},
"reminders": {
"useDefault": "true"
},
"sequence": 0,
"start": {
"dateTime": "2020-05-05T14:00:00-04:00"
},
"status": "confirmed",
"summary": "Event title 1",
"updated": "2020-05-05T23:56:57.837Z"
},
{
"created": "2020-05-06T17:48:42.000Z",
"creator": {
"email": "email goes here",
"self": "true"
},
"end": {
"dateTime": "2020-05-06T15:00:00-04:00"
},
"etag": "\"3177575538452000\"",
"htmlLink": "https://www.google.com/calendar/event?eid=MmtzdDVyb29mZzhydGhyb25ja2UxazVkbmcgcHJvamVjdG5vdGlmeWNhbEBt",
"iCalUID": "2kst5roofg8rthroncke1k5dng#google.com",
"id": "2kst5roofg8rthroncke1k5dng",
"kind": "calendar#event",
"organizer": {
"email": "email goes here",
"self": "true"
},
"reminders": {
"useDefault": "true"
},
"sequence": 1,
"start": {
"dateTime": "2020-05-06T14:00:00-04:00"
},
"status": "confirmed",
"summary": "Event title 2",
"updated": "2020-05-06T17:56:09.226Z"
}
]
#print title of event (item name)
itemtitle = inputData[0]["summary"]
print (itemtitle)
counter = 0
for event in inputData:
if "summary" in event:
counter = counter + 1
if counter > 0:
outputMsg = str(counter) + " exist"
else:
outputMsg = "does not exist"
print(outputMsg)
I am currently making a scraper app, but before going full out with the app, using other frameworks like Discord.py, I had to first scrape the site first. It proved quite difficult to scrape the site. The site that I am trying to scrape from is Fiverr. Anyways, long story short, I had to get some cookies to login with Python Requests. The big issue now is that the data I need to scrape comes in the form of JSON, which I don't know much about. I managed to select the javascript in question, but once I load it it gives an error: "TypeError: the JSON object must be str, bytes or bytearray, not Tag". I specifically need the "rows" part which is part of the JSON data.
I'm not quite certain how to fix this and have read and tried some similar questions here. I will appreciate any help.
import requests
from bs4 import BeautifulSoup
import re
import json
# Irrelevant to the question
class JobClass:
def __init__(self, date=None, buyer=None, request=None, duration=None, budget=None, link="https://www.fiverr.com/users/myusername/requests", id=None):
self.date = date
self.buyer = buyer
self.request = request
self.duration = duration
self.budget = budget
self.link = link
self.id = id
# Irrelevant to the question
duplicateSet = set()
scrapedSet = set()
jobObjArr = []
headers = {
# Some private cookies. To get them you just need to use a site like https://curl.trillworks.com/ it is really a life saver
# This is used to tell the site who you are to be logged in (which is why I deleted this part out of the code)
}
# Please note that I used "myusername" in the URL. This is going to be different depending on user
# Using the requests module, we use the "get" function
# provided to access the webpage provided as an
# argument to this function:
result = requests.get(
'https://www.fiverr.com/users/myusername/requests', headers=headers)
# Now, let us store the page content of the website accessed
# from requests to a variable:
src = result.content
# Now that we have the page source stored, we will use the
# BeautifulSoup module to parse and process the source.
# To do so, we create a BeautifulSoup object based on the
# source variable we created above:
soup = BeautifulSoup(src, "lxml")
data = soup.select("[type='text/javascript']")[1]
print(data)
# TypeError: the JSON object must be str, bytes or bytearray, not Tag
jsonObject = json.loads(data)
# Here is the output of print(data):
<script type="text/javascript">
document.viewData = {
"dds": {
"subCats": {
"current": {
"text": "All Subcategories",
"val": "-1"
},
"options": [{
"text": "Web \u0026 Mobile Design",
"val": 151
}, {
"text": "Web Programming",
"val": 140
}]
}
},
"results": {
"rows": [{
"type": "none",
"identifier": "5cf132b55e08360011efe633",
"cells": [{
"text": "May 31, 2019",
"type": "date",
"withText": true
}, {
"userPict": "\u003cspan class=\"missing-image-user \"\u003ec\u003c/span\u003e",
"type": "profile-40",
"cssClass": "height95"
}, {
"hintBottom": false,
"text": "My website was hacked and deleted. Need to have it recreated ",
"type": "text-wide",
"tags": [],
"attachment": false
}, {
"text": 1,
"type": "applications",
"alignCenter": true
}, {
"text": "3 days",
"type": "hidden-action",
"actionVisible": false,
"alignCenter": true,
"withText": true,
"buttons": [{
"type": "span",
"text": "3 days",
"class": "duration"
}, {
"type": "button",
"text": "Remove Request",
"class": "remove-request js-remove-request",
"meta": {
"requestId": "5cf132b55e08360011efe633",
"isProfessional": false
}
}]
}, {
"text": "---",
"type": "hidden-action",
"actionVisible": false,
"alignCenter": true,
"withText": true,
"buttons": [{
"type": "span",
"text": "---",
"class": "budget"
}, {
"type": "button",
"text": "Send Offer",
"class": "btn-standard btn-green-grad js-send-offer",
"meta": {
"username": "conto217",
"category": 3,
"subCategory": 151,
"requestId": "5cf132b55e08360011efe633",
"requestText": "My website was hacked and deleted. Need to have it recreated ",
"userPict": "\u003cspan class=\"missing-image-user \"\u003ec\u003c/span\u003e",
"isProfessional": false,
"buyerId": 32969684
}
}]
}]
}, {
"type": "none",
"identifier": "5cf12f641b6e99000edf1b60",
"cells": [{
"text": "May 31, 2019",
"type": "date",
"withText": true
}, {
"userPict": "\u003cimg src=\"https://fiverr-res.cloudinary.com/t_profile_small,q_auto,f_auto/attachments/profile/photo/648ceb417a85844b25e8bf070a70d9a0-254781561534997516.9743/MyFileName\" alt=\"muazamkhokher\" width=\"40\" height=\"40\"\u003e",
"type": "profile-40",
"cssClass": "height95"
}, {
"hintBottom": false,
"text": "Need mobile ui/ux designer from marvel wireframes",
"type": "text-wide",
"tags": [],
"attachment": false
}, {
"text": 4,
"type": "applications",
"alignCenter": true
}, {
"text": "5 days",
"type": "hidden-action",
"actionVisible": false,
"alignCenter": true,
"withText": true,
"buttons": [{
"type": "span",
"text": "5 days",
"class": "duration"
}, {
"type": "button",
"text": "Remove Request",
"class": "remove-request js-remove-request",
"meta": {
"requestId": "5cf12f641b6e99000edf1b60",
"isProfessional": false
}
}]
}, {
"text": "$50",
"type": "hidden-action",
"actionVisible": false,
"alignCenter": true,
"withText": true,
"buttons": [{
"type": "span",
"text": "$50",
"class": "budget"
}, {
"type": "button",
"text": "Send Offer",
"class": "btn-standard btn-green-grad js-send-offer",
"meta": {
"username": "muazamkhokher",
"category": 3,
"subCategory": 151,
"requestId": "5cf12f641b6e99000edf1b60",
"requestText": "Need mobile ui/ux designer from marvel wireframes",
"userPict": "\u003cimg src=\"https://fiverr-res.cloudinary.com/t_profile_small,q_auto,f_auto/attachments/profile/photo/648ceb417a85844b25e8bf070a70d9a0-254781561534997516.9743/MyFileName\" alt=\"muazamkhokher\" width=\"100\" height=\"100\"\u003e",
"isProfessional": false,
"buyerId": 25478156
}
}]
}]
....
I expect the JSON to be loaded in jsonObject, but I get an error: "TypeError: the JSON object must be str, bytes or bytearray, not Tag"
Edit: Here is some code at the end of the print statement. It randomly cuts off for some reason with no ending script tag:
}, {
"type": "none",
"identifier": "5cf1236a959aa5000f1ce094",
"cells": [{
"text": "May 31, 2019",
"type": "date",
"withText": true
}, {
"userPict": "\u003cimg src=\"https://fiverr-res.cloudinary.com/t_profile_small,q_auto,f_auto/profile/photos/30069758/original/Universalco_2a_Cloud.png\" alt=\"clarky2000\" width=\"40\" height=\"40\"\u003e",
"type": "profile-40",
"cssClass": "height95"
}, {
"hintBottom": false,
"text": "Slider revolution slider. 3 slides for a music festival. I can supply a copy what each slide should look like (see attached) and all the individual objects. Anyone can create basic RS slides, but I want this to be dynamic as its for a music festival. We are using the free version of RS if were are required to use the paid version of SL for addons please let us know. Bottom line this must be 3 dynamic slides (using the same background) for a music festival audience. Unlimited revisions is a must.",
"type": "see-more",
"tags": [{
"text": "Graphic UI"
}, {
"text": "Landing Pages"
}],
"attachment": {
"url": "/download/file/1559260800%2Fgig_requests%2Fattachment_f2a5f51b9fb473e8fc7f498929f39e3f",
"name": "Outwith Rotator_1920x1080_1.jpg",
"size": "2.68 MB"
}
}, {
"text": 2,
"type": "applications",
"alignCenter": true
}, {
"text": "24 hours",
"type": "hidden-action",
"actionVisible": false,
"alignCenter": true,
"withText": true,
"buttons": [{
"type": "span",
"text": "24 hours",
"class": "duration"
}, {
"type": "button",
"text": "Remove Request",
"class": "remove-request js-remove-request",
"meta": {
"requestId": "5cf1236a959aa5000f1ce094",
"isProfessional": false
}
}]
}, {
"text": "$23",
"type": "hidden-action",
"actionVisible": false,
"alignCenter": true,
"withText": true,
"buttons": [{
"type": "span",
"text": "$23",
"class": "budget"
}, {
"type": "button",
"text": "Send Of
I have the following build_settings_message function and I am a bit confused how should I write a unit test for it. What aspects of it do I need to check?
def build_settings_message(team_id):
team = SlackTeam.objects.find_by_id(team_id)
domain = Site.objects.get_current().domain
attachments = [
_build_manage_admins(),
_build_checks_available(team, domain)
]
return {
'text': "Here is my settings page",
'attachments': attachments
}
def _build_manage_admins():
return {
"fallback": "Manage admins",
"color": "#85cdff",
"callback_id": "admins_controls",
"title": "Admins",
"footer": "Users that could remove and edit any checks ",
"actions": [
{
"name": "manage",
"text": ":key: Manage Admins",
"type": "button",
"value": "manage"
}
]
}
def _build_checks_available(team, domain):
return {
"title": "Items available",
"footer": ("You have got *{} of {}* items for "
"check *available*.").format(
team.checks_used, team.checks_available),
"actions": [
{
"text": "Open Dashboard",
"type": "button",
"url": 'https://' + domain + reverse('dashboard')
}
]
}
You have to mock SlackTeam and Site and return some fake, but real-looking values for team and domain, then verify that the value returned by build_settings_message is correct (based on team and domain).
Be sure to check edge-cases such as no team, duplicate domain, etc.
I've been working on an integration to create a dialog for a Slack bot that uses python 3, AWS API Gateway, and AWS Lambda. I'm currently working on the Slack side for integration versus the end purpose of my function.
I can get my bot running with some responses if I remove the dialog and just have it chat with the user from the tutorials here and here, however once I add a dialog into the mix the bot no longer responds. I've tried basing my code off the the example code from the Slack API's github but it doesn't help. I would appreciate any guidance on how to do this using python 3.
Code below:
import os
import logging
import urllib
import boto3
from slackclient import SlackClient
LOGGER = logging.getLogger()
LOGGER.setLevel(logging.DEBUG)
# Grab the Bot OAuth token from the environment + slack verification
BOT_TOKEN = os.environ["BOT_TOKEN"]
SLACK_VERIFICATION_TOKEN = os.environ["SLACK_VERIFICATION_TOKEN"]
slack_client = SlackClient(BOT_TOKEN)
SLACK_URL = "https://slack.com/api/dialog.open"
def lambda_handler(data, context):
''' Entry point for API Gateway '''
slack_event = data['event']
if "bot_id" in slack_event:
logging.warn("Ignore bot event")
else:
channel_id = slack_event["channel"]
support_form = slack_client.api_call(
"dialog.open",
trigger_id = slack_event["trigger_id"],
dialog = {
"title": "AWS Support Ticket",
"submit_label": "Submit",
"callback_id": "support_form",
"elements": [
{
"label": "Subject",
"type": "text",
"name": "subject",
"placeholder": "Support Case Subject"
},
{
"label": "Description",
"type": "textarea",
"name": "body",
"placeholder": "Describe the issue you would like to open a support case about"
},
{
"type": "select",
"label": "What is your issue type?",
"name": "issueType",
"options": [
{
"label": "Customer Service",
"value": "customerservice"
},
{
"label": "Technical",
"value": "technical"
}
]
},
{
"label": "What is your severity level?",
"type": "select",
"name": "serverity",
"options": [
{
"label": "5 - General Guidance",
"value": "5"
},
{
"label": "4 - System Impaired",
"value": "4"
},
{
"label": "3 - Production System Impaired",
"value": "3"
},
{
"label": "2 - Production System Down",
"value": "2"
},
{
"label": "1 - Business-critical System Down",
"value": "1"
}
]
},
{
"label": "Service Code",
"type": "text",
"name": "serviceCode"
},
{
"label": "Category Code",
"type": "text",
"name": "categoryCode"
},
{
"label": "Please choose your language",
"type": "select",
"name": "language",
"options": [
{
"label": "English",
"value": "english"
},
{
"label": "Japanese",
"value": "japanese"
}
]
},
{
"label": "What is your attachement set id?",
"type": "text",
"name": "attachementSetId"
},
{
"label": "Please enter the emails you want cc'd on this case:",
"type": "textarea",
"name": "ccEmailAddresses"
}
]
}
})
data = urllib.parse.urlencode(
(
("token", BOT_TOKEN),
("channel", channel_id),
("dialog", support_form)
)
)
# Construct the HTTP request that will be sent to the Slack API.
request = urllib.request.Request(
SLACK_URL,
data=data,
method="POST"
)
# Add a header mentioning that the text is URL-encoded.
request.add_header(
"Content-Type",
"application/x-www-form-urlencoded"
)
# Fire off the request!
urllib.request.urlopen(request).read()
# Everything went fine.
return "200 OK"