I am trying to make a program that will remove songs from spotify playlists. Currently I am unable to refresh the auth tokens despite having them saved on my hard drive and specifying the cache paths when making oauth objects.
from bottle import route, run, request
import spotipy
from spotipy import oauth2
import time
PORT_NUMBER = 8080
SPOTIPY_CLIENT_ID = 'e1bb48ed8b594aeb9faf74f7e8915de7'
SPOTIPY_CLIENT_SECRET = 'dd6de8b7a0324d6ebf1fc0591e8e3220'
SPOTIPY_REDIRECT_URI = 'http://localhost:8080'
SCOPE = 'playlist-modify-public'
tracks = ['6DCZcSspjsKoFjzjrWoCdn']
def remove(sp_oauth):
access_token = ""
token_info = sp_oauth.get_cached_token()
if token_info:
if sp_oauth.is_token_expired:
token_info = sp_oauth.refresh_access_token(token_info['refresh_token'])
access_token = token_info['access_token']
else:
print ("Found cached token!")
access_token = token_info['access_token']
if access_token:
print ("Access token available! Trying to get user information...")
sp = spotipy.Spotify(access_token)
results = sp.current_user_playlists()
userinfo = sp.current_user()
userid = userinfo['id']
for items in results['items']:
if userid == items['owner']['id']:
sp.user_playlist_remove_all_occurrences_of_tracks(items['owner']['id'],items['id'],tracks)
print("removed from " + items['owner']['display_name'] + " s list " + items['name'])
example =oauth2.SpotifyOAuth( SPOTIPY_CLIENT_ID, SPOTIPY_CLIENT_SECRET,SPOTIPY_REDIRECT_URI,scope=SCOPE,cache_path=r'C:\Users\rrako\AppData\Local\Programs\Python\Python38-32\Caches\example')
remove(example)
The error I get is
Traceback (most recent call last):
File "C:\Users\rrako\AppData\Local\Programs\Python\Python38-32\unfollowLists.py", line 212, in <module>
remove(blake)
File "C:\Users\rrako\AppData\Local\Programs\Python\Python38-32\unfollowLists.py", line 63, in remove
if sp_oauth.is_token_expired:
AttributeError: 'SpotifyOAuth' object has no attribute 'is_token_expired'
The version of spotipy I have is 2.4.4
Update your version of spotipy and the token should be refreshed automatically
pip3 install spotipy --upgrade
Related
This code is taken almost verbatim from mastodon.py's README.md
it always returns
Traceback (most recent call last): File
"C:\Users\matth\GitHub\feed_thing\again.py", line 32, in
mastodon.log_in( File "C:\Users\matth.virtualenvs\feed_thing-LXMa84iN\lib\site-packages\mastodon\Mastodon.py",
line 568, in log_in
raise MastodonIllegalArgumentError('Invalid user name, password, or redirect_uris: %s' % e)
mastodon.Mastodon.MastodonIllegalArgumentError: Invalid user name,
password, or redirect_uris: ('Mastodon API returned error', 400, 'Bad
Request', 'invalid_grant')
UPDATE: I get this failure from mastodon.social, but not mstdn.social and not ohai.social.
It turns out to be because of 2 factor auth and the sample code below is not a OAUTH2 dance.
How would I replace the code below with an OAUTH2 dance?
import os
from mastodon import Mastodon
USERNAME_AS_EMAIL = os.environ["USERNAME_AS_EMAIL"]
PASSWORD = os.environ["PASSWORD"]
APP_NAME = "APP_NAME"
Mastodon.create_app(
APP_NAME,
api_base_url = 'https://mastodon.social',
to_file = 'pytooter_clientcred.secret'
)
mastodon = Mastodon(
client_id = 'pytooter_clientcred.secret',
api_base_url = 'https://mastodon.social'
)
mastodon.log_in(
USERNAME_AS_EMAIL,
PASSWORD,
to_file = 'pytooter_usercred.secret'
)
mastodon = Mastodon(
client_id = 'pytooter_clientcred.secret',
access_token = 'pytooter_usercred.secret',
api_base_url = 'https://mastodon.social'
)
I found part of the solution. If 2 factor auth is enabled on your account, mastodon.py (as of today) can't handle login. If you disable 2 factor auth, then you can login as expected.
Another hint for people who find this, sometimes you need to delete the *.secret files for mastodon.py to work (i.e. if you've changed server names but didn't change the .secret files)
I'm using the python-twitter (not tweepy) module in my application.
I have a script set up (maketweet.py) that, when I run it from bash / console, works successfully (i.e. it makes a tweet).
The problem I'm having is that when I run the same script as a scheduled task, I get an error:
Traceback (most recent call last):
File "/home/dir1/dir2/proj/maketweet.py", line 21, in <module>
api = create_api()
File "/home/dir1/dir2/proj/config.py", line 31, in create_api
if api.VerifyCredentials():
File "/home/dir1/.local/lib/python3.8/site-packages/twitter/api.py", line 4699, in VerifyCredentials
resp = self._RequestUrl(url, 'GET', data)
File "/home/dir1/.local/lib/python3.8/site-packages/twitter/api.py", line 4959, in _RequestUrl
raise TwitterError("The twitter.Api instance must be authenticated.")
twitter.error.TwitterError: The twitter.Api instance must be authenticated.
The other problem I'm having is that I can't conceive why it would make a difference that I'm using a scheduled task, rather than running the file directly from bash. Here are the contents of config.py:
#!/usr/bin/python3.8
import twitter
import os
import logging
from dotenv import load_dotenv
logger = logging.getLogger()
# project folder is one level up from file location
project_folder = pathlib.Path(__file__).parent.absolute()
load_dotenv(os.path.join(project_folder, '.env'))
# Authenticate to Twitter and create API object
TWITTER_CONSUMER_API_KEY = os.getenv("TWITTER_CONSUMER_API_KEY")
TWITTER_CONSUMER_API_SECRET = os.getenv("TWITTER_CONSUMER_API_SECRET")
TWITTER_ACCESS_TOKEN = os.getenv("TWITTER_ACCESS_TOKEN")
TWITTER_ACCESS_SECRET = os.getenv("TWITTER_ACCESS_SECRET")
def create_api():
# Create API object
api = twitter.Api(
access_token_key = TWITTER_ACCESS_TOKEN,
access_token_secret = TWITTER_ACCESS_SECRET,
consumer_key = TWITTER_CONSUMER_API_KEY,
consumer_secret = TWITTER_CONSUMER_API_SECRET,
sleep_on_rate_limit=True)
# test API object
if api.VerifyCredentials():
pass
else:
logger.error("Error creating API", exc_info=True)
raise Exception("Twitter user authentication error")
logger.info("API created")
return api
Obviously there's an error in creating the API. I imagine this has something to do with the environment variables and how they are accessed through scheduled tasks vs. bash. Just really not sure how to figure this one out...
I've been trying to get my authorization working using the Authorization Code Flow with the example from Spotipy API, as seen below.
import sys
import spotipy
import spotipy.util as util
scope = 'user-library-read playlist-read-private' # or else
if len(sys.argv) > 1:
username = sys.argv[1]
else:
print("Usage: %s username" % (sys.argv[0],))
sys.exit()
token = util.prompt_for_user_token(username, scope)
if token:
sp = spotipy.Spotify(auth=token)
results = sp.current_user_saved_tracks()
for item in results['items']:
track = item['track']
print(track['name'] + ' - ' + track['artists'][0]['name'])
else:
print("Can't get token for", username)
I managed to get it working just fine with the scope being 'user-library-read', but upon changing the scope or adding another, I get the request to re-authenticate. I copy the redirect URL in the editor as usual and get the following error:
Traceback (most recent call last):
File "C:/Users/Joel/PycharmProjects/untitled1/test.py", line 13, in <module>
token = util.prompt_for_user_token(username, scope)
File "C:\Users\Joel\.virtualenvs\untitled1-1cFj5f_i\lib\site-packages\spotipy\util.py", line 86, in prompt_for_user_token
token_info = sp_oauth.get_access_token(code)
File "C:\Users\Joel\.virtualenvs\untitled1-1cFj5f_i\lib\site-packages\spotipy\oauth2.py", line 217, in get_access_token
raise SpotifyOauthError(response.reason)
spotipy.oauth2.SpotifyOauthError: Bad Request
Any ideas what I'm doing wrong here? I'm stumped, since it works just fine with that one specific scope (and doesn't require me to authorize since I've already done it), but with others I get this.
Also, when running the code in my terminal, it requires me to authorize as well, only I get the following error in the browser: INVALID_CLIENT: Invalid redirect URI
We are busy upgrading from the Marketing API to the Business API (not graph API and not marketing API) for Facebook. The documentation states that one should be able to create a test.py with the following code:
import sys
sys.path.append('/opt/homebrew/lib/python2.7/site-packages')
sys.path.append('/opt/homebrew/lib/python2.7/site-packages/facebook_business-3.0.0-py2.7.egg-info')
from facebook_business.api import FacebookAdsApi
from facebook_business.adobjects.adaccount import AdAccount
my_app_id = 'your-app-id'
my_app_secret = 'your-appsecret'
my_access_token = 'your-access-token'
FacebookAdsApi.init(my_app_id, my_app_secret, my_access_token)
my_account = AdAccount('your-adaccount-id')
campaigns = my_account.get_campaigns()
print(campaigns)
This requires an app secret proof which I am obtaining with the following hash:
facebook_app_id = 'xxxxx'
facebook_app_secret = 'xxxxx'
facebook_app_token = 'xxxxx|xxxxx'.format(facebook_app_id,facebook_app_secret)
import hmac,hashlib
app_secret_proof = hmac.new(facebook_app_secret.encode('utf-8'),
msg=facebook_app_token.encode('utf-8'),
digestmod=hashlib.sha256).hexdigest()
print(app_secret_proof)
The is the error I get:
Traceback (most recent call last):
File "test.py", line 12, in <module>
FacebookAdsApi.init(my_app_id,my_app_secret,my_access_token,my_appsecret_proof)
File "/Users/facebook_business/api.py", line 202, in init
cls.set_default_account_id(account_id)
File "/Users/facebook_business/api.py", line 225, in set_default_account_id
"Account ID provided in FacebookAdsApi.set_default_account_id "
ValueError: Account ID provided in FacebookAdsApi.set_default_account_id expects a string that begins with 'act_'
None of the ID's start with act_, I am currently using the App ID that is at the top left of the app dashboard which one should I be using?
Marketing API
The Ad account number in business manager is obtained on the front log in screen.
From Business Manager
This code is available online to run a map of your connections in linkedin
This uses linkedin api.
I'm able to connect fine and everything runs okay till the last script of actually writing the data to a csv.
Whenever I run the code
import oauth2 as oauth
import urlparse
import simplejson
import codecs
CONSUMER_KEY = "xxx"
CONSUMER_SECRET = "xxx"
OAUTH_TOKEN = "xxx"
OAUTH_TOKEN_SECRET = "xxx"
OUTPUT = "linked.csv"
def linkedin_connections():
# Use your credentials to build the oauth client
consumer = oauth.Consumer(key=CONSUMER_KEY, secret=CONSUMER_SECRET)
token = oauth.Token(key=OAUTH_TOKEN, secret=OAUTH_TOKEN_SECRET)
client = oauth.Client(consumer, token)
# Fetch first degree connections
resp, content = client.request('http://api.linkedin.com/v1/people/~/connections?format=json')
results = simplejson.loads(content)
# File that will store the results
output = codecs.open(OUTPUT, 'w', 'utf-8')
# Loop thru the 1st degree connection and see how they connect to each other
for result in results["values"]:
con = "%s %s" % (result["firstName"].replace(",", " "), result["lastName"].replace(",", " "))
print >>output, "%s,%s" % ("John Henry", con)
# This is the trick, use the search API to get related connections
u = "https://api.linkedin.com/v1/people/%s:(relation-to-viewer:(related-connections))?format=json" % result["id"]
resp, content = client.request(u)
rels = simplejson.loads(content)
try:
for rel in rels['relationToViewer']['relatedConnections']['values']:
sec = "%s %s" % (rel["firstName"].replace(",", " "), rel["lastName"].replace(",", " "))
print >>output, "%s,%s" % (con, sec)
except:
pass
if __name__ == '__main__':
linkedin_connections()
for result in results["values"]:
KeyError: 'values'
When I run this I get an error message:
Traceback (most recent call last):
File "linkedin-2-query.py", line 51, in <module>
linkedin_connections()
File "linkedin-2-query.py", line 35, in linkedin_connections
for result in results["values"]:
KeyError: 'values'
Any suggestions or help would be greatly appreciated!
I encountered the same issue working through the post Visualizing your LinkedIn graph using Gephi – Part 1.
Python raises a KeyError whenever a dict() object is requested (using the format a = adict[key]) and the key is not in the dictionary. KeyError - Python Wiki
After searching a bit and adding some print statements, I realize that my OAuth session has expired, so the OAuth token in my linkedin-2-query.py script was is longer valid.
Since the OAuth token is invalid, the LinkedIn API does not return a dictionary with the key "values" like the script expects. Instead, the API returns the string 'N'. Python tries to find the dict key "values"in the string 'N', fails, and generates the KeyError: 'values'.
So a new, valid OAuth token & secret should get the API to return a dict containing connection data.
I run the linkedin-1-oauth.py script again, and then visit the LinkedIn Application details page to find my new OAuth token. (The screenshot omits the values for my app. You should see alphanumeric values for each Key, Token, & Secret.)
...
I then update my linkedin-2-query.py script with the new OAuth User Token and OAuth User Secret
OAUTH_TOKEN = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # your updated OAuth User Token
OAUTH_TOKEN_SECRET = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # your updated OAuth User Secret
After updating the OAuth token & secret, I immediately run my linkedin-2-query.py script. Hooray, it runs without errors and retrieves my connection data from the API.