How to use optional parameters in Google Photos API? - php

I am working on project in php with Google Photos API. i have an issue, if i pass optional parameters like pageSize, it doesn't work still get all images.
$optParams = array(
'pageSize' => 1,
);
$response = $photosLibraryClient->listMediaItems($optParams);
foreach ($response->iterateAllElements() as $item) {
$id = $item->getId();
$description = $item->getDescription();
$mimeType = $item->getMimeType();
$productUrl = $item->getProductUrl();
$filename = $item->getFilename();
echo '<br>';
echo $filename;
}

I'm not a 100% sure of this, but it seems the iterateAllElements literally iterates over all elements available in the account, ignoring your specified pageSize (even the default pageSize) by requesting everything from the API without any boundaries.
You can iterate over the returned pages replacing iterateAllElements with iteratePages, but it also doesn't seems to work properly without a albumId, the API returns an irregular page sizing, like the example below:
$optParams = array(
'pageSize' => 5 // Changed
);
$response = $photosLibraryClient->searchMediaItems($optParams); // Changed the method
foreach ($response->iteratePages() as $key => $page) {
echo "Page #{$key}<br>";
foreach ($page as $item) {
$id = $item->getId();
$description = $item->getDescription();
$mimeType = $item->getMimeType();
$productUrl = $item->getProductUrl();
$filename = $item->getFilename();
echo '<br>';
echo $filename;
}
}
if the search or list were called without providing a albumId, the example above would return something like this:
[
[{...},{...},{...}],
[{...},{...},{...},{...},{...}],
[{...}],
[],
[{...},{...},{...},{...},{...}],
[]
]
If you find a good solution for this specific problem, please let me know.
Ps.: Their API behavior and it's documentation are very weird and confusing.

Related

How to MODIFY a Google Docs document via API using search-and-replace?

I need an example of how to modify an existing document with existing text in Google Docs via API. The documentation only shows how to insert and delete text, but not how to update. Have been looking frantically on the web to find examples or a direction on how to do it but without luck.
Finally figured it out myself.
First, follow this video to prepare authentication to the Google Docs API (even though it's about Google Sheets but the process is basically the same). Basically it consists of these steps:
create project in Google Developer Console
enable Google Docs API
create credentials, including a service account for programmatic access
share your document with the service account client email address
install Google API's PHP client: composer require google/apiclient
Then create a script like the following:
require_once(__DIR__ .'/vendor/autoload.php');
$client = new \Google_Client();
$client->setApplicationName('Some name'); //this name doesn't matter
$client->setScopes([\Google_Service_Docs::DOCUMENTS]);
$client->setAccessType('offline');
$client->setAuthConfig(__DIR__ .'/googleapi-credentials.json'); //see https://www.youtube.com/watch?v=iTZyuszEkxI for how to create this file
$service = new \Google_Service_Docs($client);
$documentId = 'YOUR-DOCUMENT-ID-GOES-HERE'; //set your document ID here, eg. "j4i1m57GDYthXKqlGce9WKs4tpiFvzl1FXKmNRsTAAlH"
$doc = $service->documents->get($documentId);
// Collect all pieces of text (see https://developers.google.com/docs/api/concepts/structure to understand the structure)
$allText = [];
foreach ($doc->body->content as $structuralElement) {
if ($structuralElement->paragraph) {
foreach ($structuralElement->paragraph->elements as $paragraphElement) {
if ($paragraphElement->textRun) {
$allText[] = $paragraphElement->textRun->content;
}
}
}
}
// Go through and create search/replace requests
$requests = $textsAlreadyDone = $forEasyCompare = [];
foreach ($allText as $currText) {
if (in_array($currText, $textsAlreadyDone, true)) {
// If two identical pieces of text are found only search-and-replace it once - no reason to do it multiple times
continue;
}
if (preg_match_all("/(.*?)(dogs)(.*?)/", $currText, $matches, PREG_SET_ORDER)) {
//NOTE: for simple static text searching you could of course just use strpos()
// - and then loop on $matches wouldn't be necessary, and str_replace() would be simplified
$modifiedText = $currText;
foreach ($matches as $match) {
$modifiedText = str_replace($match[0], $match[1] .'cats'. $match[3], $modifiedText);
}
$forEasyCompare[] = ['old' => $currText, 'new' => $modifiedText];
$replaceAllTextRequest = [
'replaceAllText' => [
'replaceText' => $modifiedText,
'containsText' => [
'text' => $currText,
'matchCase' => true,
],
],
];
$requests[] = new \Google_Service_Docs_Request($replaceAllTextRequest);
}
$textsAlreadyDone[] = $currText;
}
// you could dump out $forEasyCompare to see the changes that would be made
$batchUpdateRequest = new \Google_Service_Docs_BatchUpdateDocumentRequest(['requests' => $requests]);
$response = $service->documents->batchUpdate($documentId, $batchUpdateRequest);
This is my way - easy one
public function replaceText($search, $replace)
{
$client = $this->getClient();
$service = new \Google_Service_Docs($client);
$documentId = ''; // Put your document ID here
$e = new \Google_Service_Docs_SubstringMatchCriteria();
$e->text = "{{".$search."}}";
$e->setMatchCase(false);
$requests[] = new \Google_Service_Docs_Request(array(
'replaceAllText' => array(
'replaceText' => $replace,
'containsText' => $e
),
));
$batchUpdateRequest = new \Google_Service_Docs_BatchUpdateDocumentRequest(array(
'requests' => $requests
));
$response = $service->documents->batchUpdate($documentId, $batchUpdateRequest);
}

YouTube Data API returns more results than maxResults

I have created this PHP script that print outs the specified number of latest youtube videos from a youtube channel. I'm setting the maxResults to 10 but it returns hundreds of results. Please go through the code and help.
<?php
$API_Url = 'https://www.googleapis.com/youtube/v3/';
$API_Key = '...';
$channelId = 'UCX6OQ3DkcsbYNE6H8uQQuVA';
$parameter = [
'id'=> $channelId,
'part'=> 'contentDetails',
'key'=> $API_Key
];
$channel_URL = $API_Url . 'channels?' . http_build_query($parameter);
$json_details = json_decode(file_get_contents($channel_URL), true);
$playlist=$json_details['items'][0]['contentDetails']['relatedPlaylists']['uploads'];
$parameter = [
'part'=> 'snippet',
'playlistId' => $playlist,
'maxResults'=> 10,
'key'=> $API_Key
];
$channel_URL = $API_Url . 'playlistItems?' . http_build_query($parameter);
$json_details = json_decode(file_get_contents($channel_URL), true);
$my_videos = [];
foreach($json_details['items'] as $video){
//$my_videos[] = $video['snippet']['resourceId']['videoId'];
$my_videos[] = array( 'v_id'=>$video['snippet']['resourceId']['videoId'], 'v_name'=>$video['snippet']['title'] );
}
while(isset($json_details['nextPageToken'])){
$nxt_page_URL = $channel_URL . '&pageToken=' . $json_details['nextPageToken'];
$json_details = json_decode(file_get_contents($nxt_page_URL), true);
foreach($json_details['items'] as $video)
$my_videos[] = $video['snippet']['resourceId']['videoId'];
}
print_r($my_videos);
//foreach($my_videos as $video){
//if(isset($video)){
//echo '<a href="https://www.youtube.com/watch?v='. $video['v_id'] .'">
//<div>'. $video['v_name'] .'</div>
//</a><br><br><br>';
//}
//}
And the extra results it is returning don't even have a title or id. See the image for yourself
Here's a screenshot:
The reason you get so many items is that after the first request, you have a while loop that makes subsequent requests to the YouTube API for the next page of data until nextPageToken is not found in the response payload, meaning you can be making anything from 1 to tens or hundreds of requests depending on how many pages of data are available each bringing back up to 10 additional items.
Each individual request will be bringing back 10 items at a time as you specified, but the cumulative total is obviously a lot more than that. Since you're only interested in the first 10, simply removing the while block should stop the code from making any more requests after the first one and thus won't add them to the array.

Why my second call on url doesn't work (Laravel,Guzzle)?

This is a function where i call 2 api, from first i get client_id which i used in second url. Problem is that after i call second url my page is loading without end.
Page image
public function getDevices(){
$route='http://localhost:8000/api/devices';
$device= new Client();
$answer= $device->request('GET', $route);
$body = $answer->getBody();
$status = 'true';
$message = 'Data found!';
$final= json_decode($body);
$id_array = array();
foreach ($finalas $item) {
// Add each id value in your array
$id_array[]= $item->clientId;
}
foreach($id_array as $my_id) {
$answer2= $client->request('GET', 'http://localhost:8080/api/devices/deviceAvailability/' . $my_id );
$body2 = $response2->getBody();
$final2= json_decode($body2);
}
return view('new.home', ['clients' => $final, 'status'=> $final2]);
I think
return view('new.home', ['clients' => $final, 'status'=> $final2])
is wrong. Because $final is decoded variable, maybe $final contains several types of variables.
In php, you can not set parameter that contains several types of variables.
Please do like that.
return view('new.home', ['clients' => $body, 'status'=> $final2]);
That's because json encoded variable is only a string.
I want your result.

Get total number of members in Discord using PHP

I have a Discord servern with 1361 members and on my website I want to display a total number of joined users.
I have figured out how to get all online Members on the server using:
<?php
$jsonIn = file_get_contents('https://discordapp.com/api/guilds/356230556738125824/widget.json');
$JSON = json_decode($jsonIn, true);
$membersCount = count($JSON['members']);
echo "Number of members: " . $membersCount;
?>
What should I do differently to get a total number of ALL users that have joined the server, and not just display the online members?
Now, I realize I am reviving a pretty old thread here, but I figure some might still use an answer. As jrenk pointed out, you should instead access https://discordapp.com/api/guilds/356230556738125824/members.
Your 404: Unauthorized comes from the fact that you are -you guessed it- not authorized.
If you have created a bot, it is fairly easy: just add a request header Authorization: Bot YOUR_BOT_TOKEN_HERE. If you use a normal Discord account, the whole problem is a bit more tricky:
You will first have to send a POST request to https://discordapp.com/api/auth/login and set the body to {"email": "EMAIL_HERE", "password": "PASSWORD_HERE"}.
You will get a response with the parameter token. Save this token, you will need it later. BUT:
NEVER, UNDER ANY CIRCUMSTANCES show anyone this token, as it is equivalent to your login credentials!
With this token, you can now send a POST request to the same address: https://discordapp.com/api/auth/login, but now add the header Authorization: YOUR_BOT_TOKEN_HERE. Note the missing "Bot" at the beginning.
Also, what you mustn't forget:
If you don't add the parameter ?limit=MAX_USERS, you will only get the first guild member. Take a look here to see details.
You have to count the number of online member
here is the working code
<?php
$members = json_decode(file_get_contents('https://discordapp.com/api/guilds/356230556738125824/widget.json'), true)['members'];
$membersCount = 1;
foreach ($members as $member) {
if ($member['status'] == 'online') {
$membersCount++;
}
}
echo "Number of members: " . $membersCount;
?>
You need a bot on your discord server to get all members. Use the Discord js library for example.
First create a discord bot and get a token, see the following url:
https://github.com/reactiflux/discord-irc/wiki/Creating-a-discord-bot-&-getting-a-token
As #2Kreeper noted, do not reveal your token publicly.
Then use the following code, replacing "enter-bot-token-here" and "enter-guild-id-here" with your own information:
<?php
$json_options = [
"http" => [
"method" => "GET",
"header" => "Authorization: Bot enter-bot-token-here"
]
];
$json_context = stream_context_create($json_options);
$json_get = file_get_contents('https://discordapp.com/api/guilds/enter-guild-id-here/members?limit=1000', false, $json_context);
$json_decode = json_decode($json_get, true);
echo '<h2>Member Count</h2>';
echo count($json_decode);
echo '<h2>JSON Output</h2>';
echo '<pre>';
print_r($json_decode);
echo '</pre>';
?>
For anyone still interested, here's the solution I currently use using RestCord:
use RestCord\DiscordClient;
$serverId = <YourGuildId>;
$discord = new DiscordClient([
'token' => '<YourBotToken>'
]);
$limit = 1000;
$membercnt = 0;
$_ids = array();
function getTotalUsersCount($ids, $limit, $serverId, $discord) {
if( count($ids) > 0 ) {
$last_id = max($ids);
$last_id = (int)$last_id;
} else {
$last_id = null;
}
$members = $discord->guild->listGuildMembers(['guild.id' => $serverId, 'limit' => $limit, 'after' => $last_id]);
$_ids = array();
foreach( $members as $member ) {
$ids[] = $member->user->id;
$_ids[] = $member->user->id;
}
if( count($_ids) > 0 ) {
return getTotalUsersCount($ids, $limit, $serverId, $discord);
} else {
return $ids;
}
}
$ids = getTotalUsersCount($_ids, $limit, $serverId, $discord);
$membercnt = count($ids);
echo "Member Count: " . $membercnt;
In addition to Soubhagya Kumar's answer comment by iTeY you can simply use count(), there is no need to loop if you do not require a loop.
I'm reviving this since it still seems to be relevant and the other answers seem a bit too complex I think (maybe the API used to be bad(?)). So:
Generate a permanent discord invite and keep the code at the end (https://discord.gg/xxxxxxx) and then all you do is this:
<?php
$server_code = "xxxxxxx";
$url = "https://discord.com/api/v9/invites/".$server_code."?with_counts=true&with_expiration=true";
$jsonIn = file_get_contents($url);
$json_obj = json_decode($jsonIn, $assoc = false);
$total = $json_obj ->approximate_member_count;
?>
And there you go, that's the total member count. Keep in mind, this will also count the bots I think so you have to account for that if you want to refine it even more

Instagram API: Get posts from a certain user that also has a certain hashtag

I know of these two endpoints: /users/{user-id}/media/recent and /tags/{tag-name}/media/recent
But I'm trying to get only posts by a certain user that also have a certain hashtag. Is there an easy way of doing this?
Currently I'm using the Instagram PHP API library, doing something like this:
require 'vendor/Instagram-PHP-API/instagram.class.php';
$api = new Instagram('API KEY');
// Get Hashtag Search
$result = $api->getTagMedia('somehashtag', 4); // This brings me back the last 4 posts by any user :/
// Store in a local file for JS consumption
$json = json_encode($result);
$file = TEMPLATEPATH . '/js/instagrams.json';
$fh = fopen($file, 'w');
fwrite($fh, $json);
fclose($fh);
Anyone know of an easy way to do this?
This is what I ended up doing, just getting it down somewhere incase anyone else is trying to do the same thing.
require 'vendor/Instagram-PHP-API/instagram.class.php';
$api = new Instagram('API KEY'); // Client ID
// Get Recent Search
$result = $api->getUserMedia('THE USER ID', 20);
$data = $result->data;
$newresult = new stdClass();
$newdata = array();
foreach($data as $index=>$instagram) {
if (in_array('somehashtag', $instagram->tags)) {
array_push($newdata, $instagram);
}
}
$newresult->data = $newdata;
$json = json_encode($newresult);
$file = TEMPLATEPATH . '/js/instagrams.json';
$fh = fopen($file, 'w');
fwrite($fh, $json);
fclose($fh);
So $newresult is my new object that only has posts from the specified user with the specified hashtag.

Categories