I registered my first app, and it looks like this:
All of the fields are populated below the screen shot.
Now, I have some basic python code using the examples found on their repo.
I create the following test script:
import traceback
app_id = 'FAKE.VALUE'
client_id = 'FAKE.VALUE'
client_secret = 'FAKE.VALUE'
signin_secret = 'FAKE.VALUE'
verification_token = 'FAKE.VALUE'
items = locals()
import os
import slack
items = locals().copy()
for k in items:
if '__' not in k:
val = items[k]
try:
client = slack.WebClient(token=val)
response = client.chat_postMessage(
channel='CE476K9HT',
text='Hello-----' + str(val))
print(response)
except:
print(k)
traceback.print_exc()
print('-'*50)
But all of the responses I get say:
The server responses with: {'ok':False,'error':'invalid_auth'}
For some reason, is it necessary to use path variables?
It is unclear to me what type of auth is required here.
After doing what Erik suggested,
I have a xoxp code and registered the redirect url to http://localhost.
and added the following scopes:
and updated my code to look like:
oauth_token ='xoxp-*****************'
import os
import slack
items = locals().copy()
client = slack.WebClient(token=oauth_token)
response = client.chat_postMessage(
channel='my_channel_id',
text='Hello-----')
I got my channel ID from the url:
https://app.slack.com/client/FOO/my_channel_id
When I run my code, I get the following back:
Traceback (most recent call last):
File "/home/usr/git/slack_messaging/slack_messaging.py", line 20, in <module>
text='Hello-----')
File "/home/usr/git/python-slackclient/slack/web/client.py", line 382, in chat_postMessage
return self.api_call("chat.postMessage", json=kwargs)
File "/home/usr/git/python-slackclient/slack/web/base_client.py", line 172, in api_call
return self._event_loop.run_until_complete(future)
File "/home/usr/anaconda2/envs/beer/lib/python3.7/asyncio/base_events.py", line 573, in run_until_complete
return future.result()
File "/home/usr/git/python-slackclient/slack/web/base_client.py", line 241, in _send
return SlackResponse(**{**data, **res}).validate()
File "/home/usr/git/python-slackclient/slack/web/slack_response.py", line 176, in validate
raise e.SlackApiError(message=msg, response=self)
slack.errors.SlackApiError: The request to the Slack API failed.
The server responded with: {'ok': False, 'error': 'missing_scope', 'needed': 'chat:write:user', 'provided': 'admin,identify'}
Process finished with exit code 1
You need two things to make your script work.
1. OAuth token
You need a valid OAuth token and provide it when initializing the Slack Client:
client = slack.WebClient(token="xoxb-xxx")
To get a token you need to install your Slack app to a workspace. You can do that on the app management page under "Install App". Your OAuth token will also be displayed on that page once you installed it.
2. Permissions
Your Oauth Token / Slack app needs to have the permission to post messages. On the app management pages go to "OAuth & permission" and add the needed permission to your app:. e.g. chat:write:user for user tokens.
Note that you need to reinstall your app every time to add a permission.
Related
why did i get this error on the script given below:
Traceback (most recent call last):
File "C:\Path\YoutubeApi\main.py", line 54, in <module>
main()
File "C:\Path\YoutubeApi\main.py", line 49, in main
response = request.execute()
File "C:\Users\$user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\googleapiclient\_helpers.py", line 131, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Users\$user\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\googleapiclient\http.py", line 937, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 400 when requesting https://youtube.googleapis.com/youtube/v3/videos?part=snippet&alt=json returned "The <code>snippet.categoryId</code> property specifies an invalid category ID. Use the <code>videoCategories.list</code> method to retrieve supported categories.". Details: "[{'message': 'The <code>snippet.categoryId</code> property specifies an invalid category ID. Use the <code>videoCategories.list</code> method to retrieve supported categories.', 'domain': 'youtube.video', 'reason': 'invalidCategoryId', 'location': 'body.snippet.categoryId', 'locationType': 'other'}]">
Main.py
import os
import pickle
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
def main():
credentials = None
# token.pickle stores the user's credentials from previously successful logins
if os.path.exists('token.pickle'):
print('Loading Credentials From File...')
with open('token.pickle', 'rb') as token:
credentials = pickle.load(token)
if not credentials or not credentials.valid:
if credentials and credentials.expired and credentials.refresh_token:
print('Refreshing Access Token...')
credentials.refresh(Request())
else:
print('Fetching New Tokens...')
flow = InstalledAppFlow.from_client_secrets_file(
'client_secrets.json',
scopes=[
'https://www.googleapis.com/auth/youtube.force-ssl'
]
)
flow.run_local_server(port=8080, prompt='consent',
authorization_prompt_message='')
credentials = flow.credentials
# Save the credentials for the next run
with open('token.pickle', 'wb') as f:
print('Saving Credentials for Future Use...')
pickle.dump(credentials, f)
youtube = build('youtube','v3',credentials=credentials)
request = youtube.videos().update(
part = 'snippet',
body={
"id": "OSxK-tscmVA",
"snippet":{
"title":"It's changed",
}
}
)
response = request.execute()
print(response)
if __name__ == '__main__':
main()
Script Explanation:
What the script does is that if there's no file named token.pickle it will ask the user to authorize the application and the script will store the user credentials in token.pickle file so that the user doesn't have to authorize the application on every single run and the part 2 of the script changes my YouTube video's title.
Unfortunately, you seem not inclined to make use of the official specification of the Videos.update API endpoint:
The request body of your call to the endpoint needs to specify the video category ID too for to be accepted by the API back-end.
Note that the update_video.py sample code from Google -- that I indicated you at the beginning of your series of posts as valuable source of information -- has all these required things in it.
Again, please acknowledge that you have to absorb (i.e. understand) that code. There's no other way than going through reading carefully the official documentation.
I am trying to create a simple Python bot for my project. Everything is working fine on my localhost, but the same code stops working behind the network firewall which needs environment proxy to be set.
from slack import RTMClient
proxy='http://XXXX:NNNN'
token='XXXX'
class Botso():
def __init__(self):
self.proxy=self.get_proxy()
self.rt= RTMClient(
token=token,
connect_method='rtm.start',
proxy=self.proxy
)
def get_proxy(self):
host=socket.gethostname()
if "internal" in host:
return None
elif "XXX" in host:
return proxy
#RTMClient.run_on(event="message")
def say_hello(**payload):
data = payload['data']
web_client = payload['web_client']
if 'text' in data and 'hii' in data['text']:
channel_id = data['channel']
thread_ts = data['ts']
user = data['user'] # This is not username but user ID (the format is either U*** or W***)
web_client.chat_postMessage(
channel=channel_id,
text=f"Hi <#{user}>!"
#thread_ts=thread_ts
)
if __name__ == '__main__':
botso=Botso()
botso.rt.start()
The error I am getting while initializing the RTMClient is
Traceback (most recent call last):
File "botso.py" , in <module>
botso.rt.start()
File "/usr/lib64/python3.6/http/client.py", line 974, in send
self.connect()
File "/usr/lib64/python3.6/http/client.py", line 1407, in connect
super().connect()
File "/usr/lib64/python3.6/http/client.py", line 950, in connect
self._tunnel()
File "/usr/lib64/python3.6/http/client.py", line 929, in _tunnel
message.strip()))
OSError: Tunnel connection failed: 403 Forbidden
I have other code in the same environment which uses the same proxy to send slack messages and works fine bu using request api.
params={
'token': self.slack_token,
'types': ['public_channel','private_channel']
}
slack_url='https://slack.com/api/conversations.list'
response = requests.get(url=slack_url,params=params,proxies=self.proxy).json()
How can we make the RTMClient work with proxy and Python3.
Couldn't find much help in slack API documents.
I am new in Python and trying use Google Drive Apis, but facing this issue. Error I am getting after running python quickstart.py
Traceback (most recent call last):
File "quickstart.py", line 9, in <module>
creds = store.get()
File "/usr/local/lib/python3.6/site-packages/oauth2client/client.py", line 407, in get
return self.locked_get()
File "/usr/local/lib/python3.6/site-packages/oauth2client/file.py", line 54, in locked_get
credentials = client.Credentials.new_from_json(content)
File "/usr/local/lib/python3.6/site-packages/oauth2client/client.py", line 302, in new_from_json
module_name = data['_module']
KeyError: '_module'
I have generated client_secret.json file as per the Python Quickstart tutorial.
All the file are in the same directory as that of quickstart.py.
Here is how my quickstart.py file looks.
from __future__ import print_function
from apiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
# Setup the Drive v3 API
SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly'
store = file.Storage('credentials.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
creds = tools.run_flow(flow, store)
service = build('drive', 'v3', http=creds.authorize(Http()))
# Call the Drive v3 API
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print('{0} ({1})'.format(item['name'], item['id']))
UPDATE:
I checked and it turns out that credentials.json file is auto-generated on the first run and for some reason, this is not happening.
KeyError: '_module'
This key _module is suppose to be present in credentials.json file and that is why this error is thrown. Not sure what is missing. Can someone please tell me how to resolve this issue.
Similar issue here Try to remove both files from your directory - "credentials.json" and "client_secret.json". Then re-generate your credentials and re-create "client_secret.json", this worked for me.
Hi I am trying to access my Data Lake Store from a python program locally from my desktop. I get this strange error while executing the line
adl.ls('/')
The output is
Traceback (most recent call last): File
"C:\Users\StefanFrost\adltest.py", line 31, in
adl.ls('/') File "C:\Python34\lib\site-packages\azure\datalake\store\core.py", line
124, in ls
files = self._ls(path) File "C:\Python34\lib\site-packages\azure\datalake\store\core.py", line
115, in _ls
out = self.azure.call('LISTSTATUS', key) File "C:\Python34\lib\site-packages\azure\datalake\store\lib.py", line 362,
in call
self.log_response_and_raise(r, err) File "C:\Python34\lib\site-packages\azure\datalake\store\lib.py", line 290,
in log_response_and_raise
raise exception azure.datalake.store.exceptions.DatalakeRESTException: Data-lake REST
exception: LISTSTATUS, .
I know that the firewall is open because the service is responding and I know that the supplied correct credentials, because I get unauthorized output when using the incorrect credentials. Below is the complete code.
from azure.datalake.store import core, lib, multithread
import logging, getpass, pprint, uuid, time
tenant_id = '<My Tenant Id>'
client_id = '<My Azure User Id>'
app_pwd = '<My Azure Password>'
datalake_nm = '<My Data Lake Store Name>'
token = lib.auth(tenant_id, client_id, app_pwd)
adl = core.AzureDLFileSystem(token, store_name=datalake_nm)
adl.ls('/')
I am using python 3.4 to leverage the Google API to access and read files from a users google drive. If a user has already used the app before they should have a credentials file so I was hoping to be able to test if the credentials are still valid by attempting to list the files on the users drive. The idea being if this errors then the app knows it needs to ask for access again.
After a lot of searching I've tried to piece together code from the following Examples:
Google API commands
Google Example
I currently have the following pieces of code:
import httplib2
from apiclient.discovery import build
from oauth2client.file import Storage
from oauth2client.client import AccessTokenRefreshError
from oauth2client.client import OAuth2WebServerFlow
def getAccess():
flow = OAuth2WebServerFlow(client_id, client_secret, scope, redirect_uri="urn:ietf:wg:oauth:2.0:oob")
auth_uri = flow.step1_get_authorize_url()
print("Please go to the following webpage and copy and paste the access key onto the command line:\n" + auth_uri + "\n")
code = input("Please enter your access code:\n")
credentials = flow.step2_exchange(code)
storage.put(credentials)
client_id = MYCLIENT_ID
client_secret = MYCLIENT_SECRET
scope = "https://www.googleapis.com/auth/drive"
storage = Storage('~/credentials.dat')
credentials = storage.get()
if credentials is None or credentials.invalid:
getAccess()
else:
try:
http = httplib2.Http()
http = credentials.authorize(http)
service = build('drive', 'v2', http=http)
param = {}
service.files().list(**param).execute()
except:
getAccess()
However the service.files().list(**param).execute() line produces the following error message:
Traceback (most recent call last):
File "GoogleAuth.py", line 64, in <module>
service.files().list(**param).execute()
File "C:\Anaconda3\lib\site-packages\oauth2client\util.py", line 137, in positional_wrapper
return wrapped(*args, **kwargs)
File "C:\Anaconda3\lib\site-packages\googleapiclient\http.py", line 729, in execute
raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError
I've tried playing around with a few different combinations such as:
service.files().list().execute()
service.apps().list().execute()
However I still get the same error message. Any idea what's going on ?
Issue was that
service = build('drive', 'v2')
Should have been
service = build('drive', 'v2', http=http)