Create a folder inside another with parents argument in java desktop application - google-drive-api

I am trying to create a folder inside another folder by setting the id of parents property, but the folder is not created inside it.I need a solution for a java desktop application but i cant found the right syntax for the parents property in order to perform my post request correctly (HttpPost object is the org.apache.http.client.methods.HttpPost)
HttpPost post2 = new HttpPost("https://www.googleapis.com/drive/v2/files");
post2.addHeader("Content-Type", "application/json");
post2.addHeader("Authorization","Bearer XXXXXX");
JsonObject jsonObject2 = new JsonObject();
jsonObject2.addProperty("title", userid);
jsonObject2.addProperty("parents", "['kind': 'drive#parentReference',
{'id': '"+MY_PARENT_FILE_ID+"'}]");
jsonObject2.addProperty("mimeType", "application/vnd.google-apps.folder");
post2.setEntity(new StringEntity(jsonObject2.toString()));
HttpResponse response2 = httpClient.execute(post2);
Can anyone tell me what I am doing wrong, or suggest a solution?

I use the Google API Ruby Client gem found at https://github.com/google/google-api-ruby-client.
authenticated_client_and_drive
is a method that returns and authenticated client and drive instance. Essentially, you make a post request to https://accounts.google.com/o/oauth2/token with a token that looks like:
{'refresh_token' => USERS_EXISTING_REFRESH_TOKEN,
'client_id' => 'YOUR_CLIENT_ID',
'client_secret' => 'YOUR_CLIENT_SECRET',
'grant_type' => 'refresh_token'}
Then it's as simple as implementing a method like:
def create_folder_within_folder(title, parent_folder_id)
# INPUTS: a folder title (string) and parent_folder_id (string)
# OUTPUT: the file_id (string) of the newly created folder
#client, #drive = authenticated_client_and_drive
#folder = #drive.files.insert.request_schema.new({
'title' => title,
'description' => 'Your Description Here',
'mimeType' => 'application/vnd.google-apps.folder',
'parents' => [{"id" => parent_folder_id}]
})
#result = #client.execute(
:api_method => #drive.files.insert,
:body_object => #folder)
return #result.data.id
end
Hope this points you in the right direction!

Related

How to query .tab pages from local wikidata instance using API

I am using the Extension:JsonConfig on my docker instance of wikidata that has some tables loaded onto it. The configuration for the extension in my LocalSettings.php is as follows,
$wgJsonConfigEnableLuaSupport = true;
$wgJsonConfigModels['Tabular.JsonConfig'] = 'JsonConfig\JCTabularContent';
$wgJsonConfigs['Tabular.JsonConfig'] = [
'namespace' => 486,
'nsName' => 'Data',
// page name must end in ".tab", and contain at least one symbol
'pattern' => '/.\.tab$/',
'license' => 'CC0-1.0',
'isLocal' => true,
'store' => true,
];
When i query the local instance using the following url,
http://<DOMAIN_HERE>/w/api.php?action=query&list=search&srsearch=tab contentmodel:Tabular.JsonConfig &srnamespace=486&srlimit=10&format=json
i receive the following response
{"batchcomplete":"","limits":{"search":10},"query":{"searchinfo":{"totalhits":0},"search":[]}}
which means that no matches have been found even though tables that match the query statement do exist.
This same query works with commons database when the following is done
https://commons.wikimedia.org/w/api.php?action=query&list=search&srsearch=tab%20contentmodel:Tabular.JsonConfig%20&srnamespace=486&srlimit=10&format=json
Can anyone point me out as to what i am doing wrong here?

Google Drive API Notifications - File Watch not Sending Add Notifications - possible reasons?

I just set up Google Drive API Change Notifications, specifying the folderId of a certain shared folder that I have on My Drives. It sends notifications if I change the folder name, but doesn't send notifications if I add files.
I set up the channel successfully, as upon issuing these PHP commands
$client = new Google_Client();
$client->setApplicationName('Some Name');
$client->setAuthConfig( __DIR__ . '/service_account.json');
$client->setScopes(Google_Service_Drive::DRIVE);
$client->fetchAccessTokenWithAssertion();
$token = $client->getAccessToken();
$service = new Google\Service\Drive($client);
$httpclient = new \GuzzleHttp\Client();
$folderid = $someid;
$body = [
'kind' => "api#channel",
'id' => uniqid(),
'type' => 'web_hook',
'resourceId' => $folderid,
'resourceUri' => 'https://www.googleapis.com/drive/v3/files/'.$folderid,
'address' => 'myendpoint'
];
$apiendpoint = 'https://www.googleapis.com/drive/v3/files/' . $folderid . '/watch';
$result = $httpclient->post($apiendpoint, [
'headers' => ['Content-Type' => 'application/json', 'Authorization' => "Bearer {$token['access_token']}"],
'body' => json_encode($body),
"http_errors" => false]);
I see a successful return, and my channel immediately sends a sync message to my endpoint, where I have this
function myendpoint (WP_REST_Request $request) {
$headers= getallheaders();
write_log('in google drive webhook with headers '.print_r($headers, true));
$body = $request->get_body();
write_log('in google drive webhook with body '.print_r($body, true));
global $wpdb;
return http_response_code(200);
}
Via my logging, I see
[07-Nov-2021 12:52:35 UTC] in google drive webhook with headers Array
(
[Host] => courses-test.com
[User-Agent] => APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)
[Content-Length] => 0
[Accept] => */*
[Accept-Encoding] => gzip, deflate, br
[X-Forwarded-For] => 66.102.8.121
[X-Forwarded-Proto] => https
[X-Goog-Channel-Expiration] => Sun, 07 Nov 2021 13:51:26 GMT
[X-Goog-Channel-Id] => 6187cbc82a08e
[X-Goog-Message-Number] => 1
[X-Goog-Resource-Id] => resid
[X-Goog-Resource-State] => sync
[X-Goog-Resource-Uri] => https://www.googleapis.com/drive/v3/files/folderid?acknowledgeAbuse=false&supportsAllDrives=false&supportsTeamDrives=false&alt=json
[X-Original-Host] => mydomain
)
I read here
https://developers.google.com/drive/api/v3/push
where it says
"To indicate success, you can return any of the following status codes: 200, 201, 202, 204, or 102."
and hence I am returning return http_response_code(200);
and also read here
https://developers.google.com/drive/api/v3/reference/files/watch
and I don't see anything obvious going on here.
Here
https://developers.google.com/search/docs/advanced/crawling/apis-user-agent?visit_id=637718909398077288-2640249237&rd=1
there is this remark
"Avoid unnecessary retry requests by ensuring that your application is well-designed and responds promptly to notification messages (within seconds)."
Now, when I first set up the channel, my endpoint returns right away, so that would seem to negate the above point.
Also, after I get channel set up, I also run these lines
$optParams = array(
'pageSize' => 10,
'fields' => 'nextPageToken, files(id, name)'
);
$results = $service->files->listFiles($optParams);
and indeed see a listing of files.
So I truly at a loss. When I go into the folder, whose folderId I specified to set up the watch channel, and add a file, or edit a file, I don't receive any notifications. The folder in question is shared, but as I understand, sharing only becomes an issue when dealing with shared drives, which is not my case.
And I read here,
https://developers.google.com/drive/api/v3/push#understanding-drive-api-notification-events
that watching for files being added should indeed work on a file watch, when the file is a folder, since add is one of the events for a resource, and it applies to Files.
**Update:
Ok, I seem to have things working, but not based on an add event. The only thing I changed, is that instead of using Guzzle to make the POST, as I show above, I use this
$channel->setId(uniqid());
$channel->setAddress($body['address']);
$channel->setType('web_hook');
$test = $service->files->watch($folderid, $channel);
Maybe adding some of those extra params in the $body like kind, resourceId, was messing things up when I was using POST via Guzzle. Or now that I know resourceId is not same as folderid, maybe that threw a flag on google's end so that a limited number of notifications were being sent. In any case, just using id', address and type seems to be the way to go, which I think is in the Google Drive Push docs. Just that in those docs, also mention of adding those other params in the request, like 'resourceId'. I suspect if I redo using Guzzle, but specify correct resourceId, or just leave it out and use id', address and type, that it would work.
So now, I get this sort of header in my endpoint when I add a file:
(
[Host] => courses-test.com
[User-Agent] => APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)
[Content-Length] => 0
[Accept] => */*
[Accept-Encoding] => gzip, deflate, br
[X-Forwarded-For] => someip
[X-Forwarded-Proto] => https
[X-Goog-Changed] => children
[X-Goog-Channel-Expiration] => Mon, 08 Nov 2021 09:46:10 GMT
[X-Goog-Channel-Id] => chanid
[X-Goog-Message-Number] => num
[X-Goog-Resource-Id] => someid
[X-Goog-Resource-State] => update
[X-Goog-Resource-Uri] => https://www.googleapis.com/drive/v3/files/folderid?acknowledgeAbuse=false&supportsAllDrives=false&supportsTeamDrives=false&alt=json
[X-Original-Host] => mydomain
)
So I can detect [X-Goog-Changed] as being children and just keep track of my current uploaded files and see what the new file is. Or maybe using the fields query string somehow I can directly get the new file id?
Still seems odd that getting info about a new file is such a pain. Maybe it is easier in Google Cloud API and Google wants more people signing up for Cloud. In fact that add event only seems to apply to Cloud buckets.
In short: When watching a folder with files().watch() it is currently not possible to receive notifications about new files added to this folder
There are several workarounds that you can find along with explanations in answers to similar questions:
Use changes().watch():
https://stackoverflow.com/a/26551651/11599789 and https://stackoverflow.com/a/67787626/11599789
Pass the folderId to the token:
https://stackoverflow.com/a/33896300/11599789
Make copy of all file's metadata and query for changes:
https://stackoverflow.com/a/18151189/11599789
Also: There is a relevant feature request on Google's Issue Tracker.
It has been closed due to inactivity, but it is worth "starring" and commenting on it to increase visibility.

Retrieve specific data using JSON decode Laravel

I'm new to Laravel. I need to retrieve specific data from the database using the JSON decode. I am currently using $casts to my model to handle the JSON encode and decode.
This is my insert query with json encode:
$request->validate([
'subject' => 'required|max:255',
'concern' => 'required'
]);
$issue = new Issue;
$issue->subject = $request->subject;
$issue->url = $request->url;
$issue->details = $request->concern;
$issue->created_by = $request->userid;
$issue->user_data = $request->user_data; //field that use json encode
$issue->status = 2; // 1 means draft
$issue->email = $request->email;
$issue->data = '';
$issue->save();
The user_data contains {"id":37,"first_name":"Brian","middle_name":"","last_name":"Belen","email":"arcega52#gmail.com","username":"BLB-Student1","avatar":"avatars\/20170623133042-49.png"}
This is my output:
{{$issue->user_data}}
What I need to retrieve is only the first_name, middle_name, and last_name. How am I supposed to achieve that? Thank you in ADVANCE!!!!!
As per the above code shown by you it will only insert data into the database.For retrieving data you can make use of Query Builder as i have written below and also you can check the docs
$users = DB::table('name of table')->select('first_name', 'middle_name', 'last_name')->get();
I will recommend using Resources. It really very helpful laravel feature. Check it out. It is a reusable class. You call anywhere and anytime.
php artisan make:resource UserResource
Go to your the newly created class App/Http/Resources/UserResource.php and drfine the column you want to have in your response.
public function toArray($request) {
return [
"first_name" => $this->first_name,
"middle_name" => $this->middle_name,
"last_name" => $this->last_name
]
}
Now is your controller you can use the UserResource like folow:
public function index()
{
return UserResource::collection(User::all());
}
Or after inserting data you can return the newly added data(f_name, l_name...)
$user = new User;
$user->first_name= $request->first_name;
$user->middle_name= $request->middle_name;
$user->last_name= $request->last_name;
$user->save();
$user_data= new UserResource($user);
return $user_data;

Create an elsif statement in Rails API?

I am trying to receive a JSON post to my Rails 3 application. The JSON post is just an email with a subject which will be one of the following:
BACKUP_PASS/VERIFY_PASS
BACKUP_FAIL/VERIFY_FAIL
BACKUP_FAIL/VERIFY_PASS
etc..
I have the following code in my controller:
def backupnotification
email_payload = JSON.parse(params[:payload])
Activity.create(:action => 'failed to backup', :details => email_payload['recipient'], :user_id => '28')
end
I've also added the following to my routes file:
post '/api/activity/backupnotification' => 'activities#backupnotification'
Obviously, this would create a new Activity record regardless of the backup status. What I would like to do is create an activity with an action of failed to backup if the term FAIL appears anywhere in the subject, and successfully backed up if the term FAIL does not exist.
The JSON post (email_payload) includes an attribute called subject. I was wondering if I could do something like this:
if email_payload['subject'] => "FAIL"
...
else
...
end
What would be the best way of doing this?
Assuming you can access your subject in a similar way as your recipient, you can try something like this.
def backupnotification
email_payload = JSON.parse(params[:payload])
if email_payload['subject'].include?('FAIL')
action_message = 'failed to backup'
else
action_message = 'successfully backed up'
end
Activity.create(
:action => action_message,
:details => email_payload['recipient'],
:user_id => '28')
end

Extract data from array in DB (rails)

I am trying to extract some data from an array with the following syntax:
#entries_from_db = XrEntry.find(:all, :conditions => [:FeedURI => uri ], :select => 'json')
The :FeedURI is the record that contains an array with uri's ["123456", "23345", "4453"]
The uri is the variable wich contains the current uri.
The statement I'm trying to make is 'select JSON from XrEntry where FeedURI contains uri'
Im stuck on the part to access the array and always get several error msg's when I'm trying different code.
Does anyone has an idea?
Thanks!
I solved it with this syntax
#entries_from_db = XrEntry.find(:all, :conditions => ["FeedURI like ?", "%#{uri}%"] , :select => 'json')
the "%#{your_rails_variable}%" is needed to read in an array
You seem to have switched the condition syntax. you chould start with the db attribute and then the variable.
#entries_from_db = XrEntry.find(:all,
:conditions => { :uri => FeedURI },
:select => 'json')
That will return an array of XrEntry objects with only the json attribute present. To get an array of only the json data you could map it like this:
#json_array = #entries_from_db.map(&:json)