Spotify API Add to playlist - api

Is it possible to manipulate (add to) a Spotify playlist via server side functionality?
The web API seems limited to search (https://developer.spotify.com/technologies/web-api/) and the JavaScript API Reference which has the function seems limited to actually building an app inside Spotify itself...

Yes you can , but you need an authorization process involving the user which is quite painful.
You'll need to use the right API.
Source:
https://developer.spotify.com/web-api/console/playlists/
For example for adding a track, you'll need this end-point
https://api.spotify.com/v1/users/{user_id}/playlists/{playlist_id}/tracks
This codes works on AppleScript, just to prove the concept:
set userID to "XXXXX"
-- your userID can be retrieved with https://developer.spotify.com/web-api/console/get-current-user/#complete
set SelectedPlaylistID to "YYYY"
-- your target playlist can be retrieved with https://developer.spotify.com/web-api/console/get-playlists/#complete
set BearerID to "ZZZZ"
-- ZZZZ can be retrieved manually on page https://developer.spotify.com/web-api/console/post-playlist-tracks/
tell application "Spotify"
set currentSpotifyID to id of current track as string
end tell
set currentlyPlayingTrack to trim_line(currentSpotifyID, "spotify:track:", 0)
set theURL to "'https://api.spotify.com/v1/users/" & userID & "/playlists/" & SelectedPlaylistID & "/tracks?uris=spotify%3Atrack%3A" & currentlyPlayingTrack & "' -H 'Accept: application/json' -H 'Authorization: Bearer " & BearerID & "'"
-- obtenu de https://developer.spotify.com/web-api/console/post-playlist-tracks/#complete
set theCommand to "curl -X POST " & theURL
do shell script theCommand
BUT there is a big caveat : you'll need to refresh the BearerID every hour.
Which is where the authorization process is needed, and where it becomes complicated if you want to bypass the refreshing limit.

Unfortunately, this isn't possible at this time without building a Spotify application either inside the client using the JS API or a standalone app using libSpotify.

Related

Recieving an "errorCode: ERROR_RESOURCE_GONE" when trying to send play command

I have been trying to figure out the sonos api over the past few days, but unfortuanetly have hit a road block. I have already gotten my tokens and room names and and favorites Id, but when I send the curl request to play a song I get the error described above.
Curl Code :
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer {TOKEN}" "https://api.ws.sonos.com/control/api/v1/groups/RINCON_48A6B88A5B14014XX:XXXXXXXXXX/favorites" --data #play.json
I keep the body in a .json file called play which contains the code:
{
"favoriteId":2,
"playOnCompletion":true
}
I have not been able to find any documentation on this issue online, so any and all help is very appreciated.
The "ERROR_RESOURCE_GONE" HTTP 410 response indicates that the
groupID you are using in your request (RINCON_48A6B88A5B14014XX:XXXXXXXXXX) no longer exists. Group IDs are not static and may change depending on a number of factors - grouping and ungrouping, power cycling, etc.
If you re-run the request to get groups, you should get an up-to-date list of group IDs. Try doing that and using a returned Group ID in your favorites request.
The "Subscribe" section of the documentation describes how to automatically listen for group ID changes: https://developer.sonos.com/build/direct-control/connect/
Have you made sure that the groupId or the favoriteId are still valid? Based on the ERROR_RESOURCE_GONE, it seems one of those has likely changed.

How do I get sorted results from the Google Photos search API?

I'm using the search API for Google Photos documented here. I'd like the results in the response to be sorted from newest to oldest, but by default, the results are sorted from oldest to newest. Is there a way to reverse the sorting?
I believe your goal as follows.
You want to sort the result values from the method of "Method: mediaItems.search".
You want to sort the values from oldest to newest.
Issue and workaround:
Unfortunately, in the current stage, it seems that there is no parameter for sorting the returned values for the the method of "Method: mediaItems.search" in Google Photos API. Also, it seems that such parameter is not existing in the method of "mediaItems.list".
By the way, it was found that when albumId is used in the request body for the method of "Method: mediaItems.search", the returned values are sorted as the ascending order. If you use the albumn ID, I think that your goal can be achieve by this.
On the other hand, when albumId is NOT used in the request body, the returned values are sorted as the descending order. And also, it seems that when filteres is used in the request body, the returned values are sorted as the descending order.
From your question, I thought that in your situation, albumId might be not used. So in this case, as the current workaround, how about sorting the values using a script after the values are retrieved? In this answer, I would like to propose to use the Web Apps created by Google Apps Script as a wrapper API.
Usage:
1. Create new project of Google Apps Script.
Sample script of Web Apps is a Google Apps Script. So please create a project of Google Apps Script.
If you want to directly create it, please access to https://script.new/. In this case, if you are not logged in Google, the log in screen is opened. So please log in to Google. By this, the script editor of Google Apps Script is opened.
2. Linking Cloud Platform Project to Google Apps Script Project.
About this, you can see the detail flow at here.
And also, please enable Google Photos API at API console.
3. Add scope.
In this case, please addt the scope of https://www.googleapis.com/auth/photoslibrary to the manifest file (appsscript.json).
4. Script.
Please copy and paste the following script (Google Apps Script) to the script editor. This script is for the Web Apps. This Web Apps is used as an API.
function doGet(e) {
const key = "sampleKey"; // This is used for using this Web Apps.
try {
if (e.parameter.key != key) throw new Error("Invalid key.");
const albumId = e.parameter.albumId;
const filters = e.parameter.filters;
const sort = e.parameter.sort;
const headers = {"Authorization": "Bearer " + ScriptApp.getOAuthToken()};
const url = "https://photoslibrary.googleapis.com/v1/mediaItems:search";
let mediaItems = [];
let pageToken = "";
const metadata = {pageSize: 100, pageToken: pageToken};
if (albumId) metadata.albumId = albumId;
if (filters) metadata.filters = JSON.parse(filters);
do {
const params = {
method: "post",
headers: headers,
contentType: "application/json",
payload: JSON.stringify(metadata),
}
const res = UrlFetchApp.fetch(url, params);
const obj = JSON.parse(res.getContentText());
mediaItems = mediaItems.concat(obj.mediaItems);
pageToken = obj.nextPageToken || "";
} while (pageToken);
if (mediaItems.length > 0) {
if (sort && sort == "ascending") {
mediaItems.sort((a, b) => new Date(a.mediaMetadata.creationTime) < new Date(b.mediaMetadata.creationTime) ? -1 : 1);
}
return ContentService.createTextOutput(JSON.stringify({values: mediaItems}));
}
return ContentService.createTextOutput(JSON.stringify({error: "No values."}));
} catch(err) {
return ContentService.createTextOutput(JSON.stringify({error: err.message}));
}
}
5. Deploy Web Apps.
The detail information can be seen at the official document.
On the script editor, at the top right of the script editor, please click "click Deploy" -> "New deployment".
Please click "Select type" -> "Web App".
Please input the information about the Web App in the fields under "Deployment configuration".
Please select "Me" for "Execute as".
This is the important of this workaround.
Please select "Anyone" for "Who has access".
In this case, the user is not required to use the access token. So please use this as a test case.
When you want to use the access token, please set it to Anyone with Google account or Only myself. By this, the user can access to the Web Apps using the access token. When you use the access token, please include the scope of https://www.googleapis.com/auth/drive.readonly or https://www.googleapis.com/auth/drive.
Please click "Deploy" button.
When "The Web App requires you to authorize access to your data" is shown, please click "Authorize access".
Automatically open a dialog box of "Authorization required".
Select own account.
Click "Advanced" at "This app isn't verified".
Click "Go to ### project name ###(unsafe)"
Click "Allow" button.
Copy the URL of Web App. It's like https://script.google.com/macros/s/###/exec.
When you modified the Google Apps Script, please redeploy as new version. By this, the modified script is reflected to Web Apps. Please be careful this.
6. Testing.
As the test of this Web Apps, I would like to propose to use the following curl command. Please replace https://script.google.com/macros/s/###/exec with your Web Apps URL.
Simple use:
In this curl command, the result value is returned as the ascending order of oldest to newest.
$ curl -GL -d "key=sampleKey" -d "sort=ascending" https://script.google.com/macros/s/###/exec
Use albumId:
When you want to use the album ID, please use the following curl command.
$ curl -GL -d "albumId=###" -d "key=sampleKey" -d "sort=ascending" https://script.google.com/macros/s/###/exec
In this case, even when -d "sort=ascending" is not used, the result value is returned as the ascending order of oldest to newest.
Use filters:
When you want to use the filters, please use the following curl command.
$ curl -GL -d 'filters={"dateFilter":{"ranges":[{"startDate":{"year":2020},"endDate":{"year":2021}}]}}' -d "key=sampleKey" -d "sort=ascending" https://script.google.com/macros/s/###/exec
In this command, the values of 2020 - 2021 are returned as the ascending order of oldest to newest.
Note:
Although when I searched this at the Google issue tracker, I couldn't find about it. So how about reporting this as the future request? Ref
References:
Method: mediaItems.search
Related thread.
How to use Google Photos API Method: mediaItems.search in Google apps script for a spreadsheet
Google photos api adding photos not working, upload seems to work
Google Apps Scripts: import (upload) media from Google Drive to Google Photos?

API call works on postman but not on filemaker

I am trying to program an app in filemaker that uses data from an API service. The problem is that when I test an url using postman it returns the JSON file I want without problems, but when i use the insert from url command from Filemaker, the result is a 405 method not allowed error.
As additional information: I'm trying to get a JSON object from the API to a text field inside my Filemaker database, using a script to fill it up.
Here's the script I have in filemaker:
Insert from URL[Select; With Dialog: Off; Projects::JSONdata;
"https://soporte.adasoft.es/rest/api/2/search?jql=project=****&maxResults=10&fields=Id,key,status,name,startdate,details,lastupudated";
Curl Options:"-X GET" &
"-H 'Authorization: Basic
************'" &
"-H 'Cache-Control: no-cache'"]
OBSERVATIONS: I've replaced the sensible data (such as the encrypted simple authentication login) with '*'.
Try this
Insert from URL[Select; With Dialog: Off; Projects::JSONdata;
"https://soporte.adasoft.es/rest/api/2/search?jql=project=****&maxResults=10&fields=Id,key,status,name,startdate,details,lastupudated";
cURL options:
"-X GET" & "--header \"Authorization: Basic *******\"" & "--header \"Cache-Control: no-cache\""]
Reference : https://fmhelp.filemaker.com/help/16/fmp/en/index.html#page/FMP_Help/insert-from-url.html

SoftLayer API unable to get networkComponents in time after createObject

In the past, Using getObject method to get networkComponents(PrimaryBackendNetworkComponent, PrimaryNetworkComponent) in time after createObject.
The curl URL is below with appropriate object mask.
$ curl 'https://{username}:{api_key}#api.softlayer.com/rest/v3.1/SoftLayer_Virtual_Guest/{vid}.json?objectMask=mask%5Bid%2C+globalIdentifier%2C+hostname%2C+domain%2C+fullyQualifiedDomainName%2C+status.name%2C+powerState.name%2C+activeTransaction%2C+datacenter.name%2C+operatingSystem%5BsoftwareLicense%5BsoftwareDescription%5Bname%2Cversion%5D%5D%2Cpasswords%5Busername%2Cpassword%5D%5D%2C++maxCpu%2C+maxMemory%2C+primaryIpAddress%2C+primaryBackendIpAddress%2C+privateNetworkOnlyFlag%2C+dedicatedAccountHostOnlyFlag%2C+createDate%2C+modifyDate%2C+billingItem%5BnextInvoiceTotalRecurringAmount%2C+children%5BnextInvoiceTotalRecurringAmount%5D%5D%2C+notes%2C+tagReferences.tag.name%2C+networkVlans%5Bid%2CvlanNumber%2CnetworkSpace%5D%2C+primaryBackendNetworkComponent%5BprimaryIpAddress%2C+networkVlan%5Bid%2Cname%2CvlanNumber%2CprimaryRouter%5D%2C+subnets%5Bnetmask%2CnetworkIdentifier%5D%5D%2C+primaryNetworkComponent%5BprimaryIpAddress%2C+networkVlan%5Bid%2Cname%2CvlanNumber%2CprimaryRouter%5D%2C+subnets%5Bnetmask%2CnetworkIdentifier%5D%5D%5D'
And readable object mask is below:
INSTANCE_DETAIL_MASK = "id, globalIdentifier, hostname, domain, fullyQualifiedDomainName, status.name, " +
"powerState.name, activeTransaction, datacenter.name, " +
"operatingSystem[softwareLicense[softwareDescription[name,version]],passwords[username,password]], " +
" maxCpu, maxMemory, primaryIpAddress, primaryBackendIpAddress, " +
"privateNetworkOnlyFlag, dedicatedAccountHostOnlyFlag, createDate, modifyDate, " +
"billingItem[nextInvoiceTotalRecurringAmount, children[nextInvoiceTotalRecurringAmount]], notes, tagReferences.tag.name, networkVlans[id,vlanNumber,networkSpace], " +
"primaryBackendNetworkComponent[primaryIpAddress, networkVlan[id,name,vlanNumber,primaryRouter], subnets[netmask,networkIdentifier]], primaryNetworkComponent[primaryIpAddress, networkVlan[id,name,vlanNumber,primaryRouter], subnets[netmask,networkIdentifier]]"
But about 18 hours ago, This way is not working because two primary network components stay null. And I have to wait about 30 seconds to call in the workaround.
The question is that I want to know that this situation is temporary or permanent change. We programmatically request these API requests. So it is risky if not to find the root cause.
Please tell me if anyone knows the details of Softlayer.
the createObject method does not create a Virtual server immediately, you need to check first if the server has been provisioned properly, for that propourse you can see the provisionDate property as it is detailed here: https://sldn.softlayer.com/blog/phil/simplified-cci-creation Once the server has been provisioned properly you should be able to see all the information that you want to

Using Twitter API on shared server - Rate limit exceeded even though I am caching the response

I have written a php script which gets the latest status update for 12 different twitter accounts by pulling an xml for each and caching it on my server. This currently runs every 30 minutes.
Unfortunately I keep getting the "Rate limit exceeded. Clients may not make more than 150 requests per hour." error event though i'm only making 24 requests from the 150 I should have.
I assume this is because my domain is on a shared server and twitter is counting other requests against me.
How can I authorise my requests so i'm not restriced by the standard IP limit?
I have no experience of OAuth so need step by step instructions if possible.
Thanks in advance!
OK so I managed to get the most of this working with no previous experience of API's etc.
Here is my step by step guide:
Step 1.
Create a Twitter list.
Go to: https://twitter.com/username/lists
Click "Create list"
Enter details and save.
Go to a twitter user you wish to add to the list and click the gear dropdown and select "Add or remove from lists". Tick the checkbox next to your list.
Step 2.
Create a Twitter App via: https://dev.twitter.com/apps/new
Log in using your Twitter credentials.
Give your app a name, description etc.
Go to the Settings tab and change the Access type to Read and Write then click "Update this Twitter application's settings".
Click "Create my access token" at the bottom of the page.
You will now have a Consumer Key, Consumer secret, Access token and Access token secret. Make a note of these.
Step 3. Create API tokens.
Download and install onto your server the Abraham Twitter oAuth library from: https://github.com/abraham/twitteroauth (I'll use a folder called "twitter").
Create a new file, name it authorise.php in the oAuth folder and put the following code inside (with your generated keys in place of the named text). (Put the code between < ? PHP and ?> brackets).
// Create our twitter API object
require_once("twitteroauth/twitteroauth.php");
$oauth = new TwitterOAuth('Put-Consumer-Key-here', 'Put-Consumer-secret-here',
'Put-Access-Token-here', 'Put-Access-token-secret-here');
// Send an API request to verify credentials
$credentials = $oauth->get("account/verify_credentials");
echo "Connected as #" . $credentials->screen_name;
// Post our new "hello world" status
$oauth->post('statuses/update', array('status' => "hello world"));
This has now authorised your twitter App for the API and posted a "hello world" status on your twitter account.
Note: The Read / Write access change we did earlier alowed the code to post the status update, it's not actually needed to pull the list from the API but I did it to make sure it was working OK. (You can turn this off again by going back to the Settings).
Step 4.
Create PHP file to pull your list and cache the file.
Create an XML file (YOUR-FILE-NAME.xml) and save it in the oAuth folder.
Create a PHP file (YOUR-PHP-FILE.php) and save it in the oAuth folder
Edit the below code with your twitter API keys, file name and twitter list details and save it in your PHP file. (Put the code within < ? PHP and ?> brackets).
/* Twitter keys & secrets here */
$consumer_key = 'INSERT HERE';
$consumer_secret = 'INSERT HERE';
$access_token = 'INSERT HERE';
$access_token_secret = 'INSERT HERE';
// Create Twitter API object
require_once('twitteroauth/twitteroauth.php');
// get access token and secret from Twitter
$oauth = new TwitterOAuth($consumer_key, $consumer_secret, $access_token, $access_token_secret);
// fake a user agent to have higher rate limit
$oauth->useragent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.9) Gecko/20071025 Firefox/2.0.0.9';
// Send an API request to verify credentials
$credentials = $oauth->get('account/verify_credentials');
echo 'Connected as #' . $credentials->screen_name . '\n';
// Show API hits remaining
$remaining = $oauth->get('account/rate_limit_status');
echo "Current API hits remaining: {$remaining->remaining_hits}.\n";
$ch = curl_init();
$file = fopen("YOUR-FILE-NAME.xml", "w+");
curl_setopt($ch, CURLOPT_URL,'https://api.twitter.com/1/lists/statuses.xml?slug=INSERT-LIST-NAME&owner_screen_name=INSERT-YOUR-TWITTER-USERNAME-HERE&include_entities=true');
curl_setopt($ch, CURLOPT_FILE, $file);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
fclose($file);?>
Copy the file path into your browser and test it. (e.g. http://www.yourwebsite.com/twitter/YOUR-PHP-FILE.php)
This should contact twitter, pull the list as an XMl file and save it into YOUR-FILE-NAME.xml. Test it by opening the XML file, it should have the latest statuses from the users in your twitter list.
Step 5.
Automate the PHP script to run as often as you like (up to 350 times per hour) via a Cron job.
Open your Cpanel and click "Cron jobs" (usually under Advanced).
You can choose the regularity of your script using the common settings.
In the command field add the following code:
php /home/CPANEL-USERNAME/public_html/WEBSITE/twitter/YOUR-PHP-FILE.php >/dev/null 2>&1
Your script will now run as often as you have chosen, pull the list from twitter and save it into YOUR-FILE-NAME.xml.
Step 6.
You can now pull statuses from the cached XML file meaning your visitors will not be making unnecessary calls to the API.
I've not worked out how to target a specific screen_name yet if anyone can help there?
a) don't check 12 different accounts, create a [public] list https://twitter.com/lists and check only the it => 12 times less requests
b) use this awesome oAuth lib: https://github.com/abraham/twitteroauth and use oAuth requests instead of unsigned => you will get 350 requests and they will not be affected by IP limit