Jump to content

Problems updating items in PHP, need help, please


BiTeTHeBiGG
Go to solution Solved by roaku,

Recommended Posts

BiTeTHeBiGG

Hi,

I'm trying to get my emby and kodi DB in sync in terms of watched status.

Kodi is now updated and on trying to update also the emby DB I will not get any response from the server on a test for a single item.

I first load the item, change the "PlayCount", "Played" and "LastPlayedDate" parameters and send it back to the API.

Here the PHP code for the POST:

$url = 'http://' . $host . '/emby/Items/' . $itemId . '?api_key=' . $api_key;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_ENCODING, "UTF-8");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($emby_data,true));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json', 'Content-Type: application/json'));
$output = curl_exec($ch);
curl_close($ch);
echo "<pre>".var_export($output,true)."</pre><hr>";

And this is in the server log:

2024-03-26 16:22:46.919 Info Server: http/1.1 POST http://x.x.x.x:8096/emby/Items/461390. UserAgent: 
2024-03-26 16:22:46.927 Info Server: http/1.1 Response 204 to host1. Time: 7ms. http://x.x.x.x:8096/emby/Items/461390

When I try to load again that item, I see there was no change at all.

Anyone with an idea what I'm doing wrong?

I double checked that under "UserData" the parameters are all set the right way before post:

// AFTER LOAD BEFORE POST

echo "<pre>".var_export($emby_data['UserData'],true)."</pre>";

  'UserData' => 
  array (
    'PlaybackPositionTicks' => 0,
    'PlayCount' => 0,
    'IsFavorite' => false,
    'Played' => false,
  )

// CHANGING PARAMETERS
..
..
// BEFORE POST

echo "<pre>".var_export($emby_data['UserData'],true)."</pre>";

  'UserData' => 
  array (
    'PlaybackPositionTicks' => 0,
    'PlayCount' => 1,
    'IsFavorite' => false,
    'Played' => true,
    'LastPlayedDate' => '2016-07-12T22:46:49.0000000Z',
  )
echo json_encode($emby_data['UserData'],true);

{"PlaybackPositionTicks":0,"PlayCount":1,"IsFavorite":false,"Played":true,"LastPlayedDate":"2016-07-12T22:46:49.0000000Z"}

Thank you for any help

Edited by BiTeTHeBiGG
added code to explain array / json output
Link to comment
Share on other sites

roaku

We don't see how you've modified $emby_data from the original Emby response or how you 'load that item again'.

Link to comment
Share on other sites

BiTeTHeBiGG
Posted (edited)

to load the item I use:

$url = 'http://' . $host . '/emby/Users/' . $userId . '/Items/' . $itemId . '?api_key=' . $api_key;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_ENCODING, "UTF-8");
$output = curl_exec($ch);
curl_close($ch);
$emby_data = json_decode($output, true);

I modified the first forum post to add the response of loading.

And this is how I change the parameters, but again in the first post you see how it looks before posting to API:

$emby_data['UserData']['PlayCount'] = 1;
$emby_data['UserData']['Played'] = true;
$emby_data['UserData']['LastPlayedDate'] = date('Y-m-d\TH:i:s.0000000\Z',strtotime('12.07.2016 22:46:49'));

To look if the item is changed I just add an "exit;" after loading and echo of $emby_data and rerun the script ;)

Edited by BiTeTHeBiGG
Link to comment
Share on other sites

roaku
1 hour ago, BiTeTHeBiGG said:

To look if the item is changed I just add an "exit;" after loading and echo of $emby_data and rerun the script ;)

It sounds like you aren't actually reloading the item (making an additional request to GET the item again after update)  and are just expecting the update POST to return you the updated item, which it won't. The 204 response is telling you not to expect any content as part of the update response.

Link to comment
Share on other sites

BiTeTHeBiGG
Posted (edited)

Sorry, when the post is sent then the scriüt is ended.

After that I modify the script to exit after the get request.

What is wrong with that?

To make a change I have to load the item, right? It does not matter if I stop the script just before making changes to the get request response. I don't understand what you are meaning by that.

If I also look in the web gui tho check if the item now is showing as watched, then it isn't.

Edited by BiTeTHeBiGG
Link to comment
Share on other sites

roaku
7 minutes ago, BiTeTHeBiGG said:

Sorry, when the post is sent then the scriüt is ended.

After that I modify the script to exit after the get request.

What is wrong with that?

To make a change I have to load the item, right? It does not matter if I stop the script just before making changes to the get request response. I don't understand what you are meaning by that.

This is the sequence of requests you need and I'm not sure you have:

GET the item (you've shown this)

POST the update to the item (you've shown this)

GET the item *again* (you haven't shown this)

That's three separate requests to the server. Do you have all three of these in this order?

Edited by roaku
Link to comment
Share on other sites

BiTeTHeBiGG
Posted (edited)

hmm ... OK, you say to make the update work I have to GET the datas, make needed changes to the datas, POST back the changed datas and GET again the datas in the same script?

I just tried and there is no change at all. Also in the web gui item is still unwatched.

In the server log still and only the two lines with 204. Sorry but I really don't get it.

Edited by BiTeTHeBiGG
Link to comment
Share on other sites

roaku
5 minutes ago, BiTeTHeBiGG said:

hmm ... OK, you say to make the update work I have to GET the datas, make needed changes to the datas, POST back the changed datas and GET again the datas in the same script?

I just tried and there is no change at all. Also in the web gui item is still unwatched.

In the server log still and only the two lines with 204. Sorry but I really don't get it.

For the update to work, you do not need to do the final GET.

In order to see the updated item, though, you would have to GET it again after updating. The way you described your issue made it sound to me that you were checking a stale version of the item.

 

Putting that aside, are you sure you're hitting the right endpoint? It looks like you may need to POST to /Items, rather than Users/Items

http://swagger.emby.media/?staticview=true#/ItemUpdateService/postItemsByItemid

 

Link to comment
Share on other sites

BiTeTHeBiGG
Posted (edited)

As is the first post I use:

$url = 'http://' . $host . '/emby/Items/' . $itemId . '?api_key=' . $api_key;

so it is the /Items endpoint.

But I found in another post (/Users/{UserId}/Items/{ItemId}/UserData) with another endpoint (undocumented way) to use exactly for watched statuses:

$url = 'http://' . $host . '/emby/Users/' . $userId . '/Items/' . $itemId . '/UserData?api_key=' . $api_key;

... sending only the "UserData" parameters and guess what? It works. I don't know why and it is frustrating.

The same bad behaviour is when I'm using swagger with the Items endpoint. I also get 204 and nothing changes. I think may be is version 4.7.14 broken?

And as the undocumented endpoint is not in swagger could not test there but only directly in my script.

Thank you for your efforts, I really appreciate.

 

Edited by BiTeTHeBiGG
typos
Link to comment
Share on other sites

  • Solution
roaku
Posted (edited)
2 hours ago, BiTeTHeBiGG said:

As is the first post I use:

$url = 'http://' . $host . '/emby/Items/' . $itemId . '?api_key=' . $api_key;

so it is the /Items endpoint.

But I found in another post (/Users/{UserId}/Items/{ItemId}/UserData) with another endpoint (undocumented way) to use exactly for watched statuses:

$url = 'http://' . $host . '/emby/Users/' . $userId . '/Items/' . $itemId . '/UserData?api_key=' . $api_key;

... sending only the "UserData" parameters and guess what? It works. I don't know why and it is frustrating.

The same bad behaviour is when I'm using swagger with the Items endpoint. I also get 204 and nothing changes. I think may be is version 4.7.14 broken?

And as the undocumented endpoint is not in swagger could not test there but only directly in my script.

Thank you for your efforts, I really appreciate.

 

Ok, the next thing is that I'm a little suspicious of is your json encode and decode process.

Based on the documentation, I expect UserData to be an object, not an array, but I see you manipulating the UserData as an array in php.

You may need to use json_encode($emby_data) (remove the 'true' flag) when decoding the response from the initial get, then manipulate $emby_data as a stdObject instead of an array ($emby_data->UserData->PlayCount=1).

It's possible that decoding all/part of the response to a php array as instructed by the associative=true flag is creating a problem for you when you then re-encode that restructured data back to json to POST to Emby.

Edited by roaku
  • Thanks 1
Link to comment
Share on other sites

BiTeTHeBiGG
Posted (edited)
3 hours ago, roaku said:

You may need to use json_encode($emby_data) (remove the 'true' flag) when decoding the response from the initial get, then manipulate $emby_data as a stdObject instead of an array ($emby_data->UserData->PlayCount=1).

It's possible that decoding all/part of the response to a php array as instructed by the associative=true flag is creating a problem for you when you then re-encode that restructured data back to json to POST to Emby.

Thank you for insinsting and pointing me to the json convertions. Indeed there is a problem in PHP if you use a 32 bit version or on a 64 bit an older 7 version. 64 bit and actual version 7 or better version 8 can handle big int and big floating correctly (not loosing precision on some values) ... BUT this was not the issue.

The problem was not on decoding (it does not really matter if associative or as an object and only on decoding you can use true for associative), encoding back to json was problematic as I did a mistake with copy&paste for the second parameter. On encoding the second parameter should be "JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES". That way no conversion or escaping of symbols or slashes will happen as otherwise would cause the API to fail on URLs ( for example "ExternalUrls":[{"Namw":"IMDb","Url":"https://www.imdb.com/title/tt01234567"}] ).

After replacing the parameter in the encode function all is working with the "/Items" endpoint. As the undocumented "/emby/Users/<userId>/Items/<itemId>/UserData" is also working with just the "UserData" portion (even with the wrong json convertion as no concerned fields), is there a possibility to send this as a GET instead of a POST? It would be much faster and simpler for mass mutaions. I tried to add the json part in the URL as a "data=" parameter (also as a "json=") without success. It seems that the API is wanting strict a POST request 🤷‍♂️.

Edited by BiTeTHeBiGG
  • Like 1
Link to comment
Share on other sites

roaku

I'm not sure on updating via GET, but I would assume no.

Emby devs would be able to give a definitive answer.

Link to comment
Share on other sites

The update has to be a POST. Does that answer your question?

Link to comment
Share on other sites

BiTeTHeBiGG

Hi Luke, if you are referring to the "UserData" endpoint, yes.

Thank you.

  • Thanks 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...