Gmail API - How can I retrieve a thread/message with just the unique id from the gmail address bar? - go

I'm working on a project, with the gmail api, and I need to read a message in a thread to get some information (like message body and bottom part).
So I'm able to access my inbox, everything is set up and ready to work.
But I struggle with the next step: the only info I have to find my message/thread is the unique id you can find on the gmail url (e.g: https://mail.google.com/mail/u/0/d/xxxxxxx/#inbox/**uniqueID**)
I read the golang documentation for the google gmail api, and I couldn't find any way to get the thread or a message with just this information. Am I wrong?
If not, what could be my solution to this problem?
Scrapping? to retrieve the messageID?
Or is there another library that I could use maybe?
I tried to use the following functions:
`
message, err := srv.Users.Messages.Get(user, uniqueID).Do()
if err != nil {
return fmt.Sprintf("Unable to retrieve message: %v", err)
}
`
and
`
thread, err := srv.Users.Threads.Get(user, uniqueID).Do()
if err != nil {
return fmt.Sprintf("Unable to retrieve thread: %v", err)
}
`
But the uniqueID doesn't work for them, they're expecting the MessageID or ThreadID (IDs that you can find when you click on "Show Original" from a message in Gmail).
Unable to retrieve message: googleapi: Error 400: Invalid id value, invalidArgument
Any suggestion is welcome! ^^
Thanks

If you already have the threadId or the id (MessageID or ThreadID that you get using the method users.messages.list,) your case use the method users.messages.get to get the "Message-ID" under the payload field.
It shows in this format:
{
"name": "Message-ID",
"value": "\u003cMessage-ID\u003e"
},
To get the actual Message-ID (the one under Show original, you will need to trim \u003c at the start of the value, and \u003e at the end.
something like this maybe:
gmailMessageResposne, _ := gmail.Service.Users.Messages.Get("user#email.com", "rfc822msgid").Format("full").Do()
Reference:
Method: users.messages.list
Method: users.messages.get

Related

Unable to add 'Price' field to SubscriptionItemsParams

I am trying to update the price of a Stripe subscription with Golang as shown here:
https://stripe.com/docs/billing/subscriptions/upgrade-downgrade
I copied and pasted the following code from the docs, but substituted in the correct Stripe key, subscription ID, and price ID:
// Set your secret key. Remember to switch to your live secret key in production.
// See your keys here: https://dashboard.stripe.com/apikeys
stripe.Key = "sk_test_51LsirAKpk5W1QCoV3cKpwMabHz8VzurJnNNSmvBkr4zRaicCJFsz8NL7HyvJ7EC61CuKc7eHjMLHqjK1C9Xl6RpD00X5YHcRBk"
subscription, err := sub.Get("sub_49ty4767H20z6a", nil)
params := &stripe.SubscriptionParams{
CancelAtPeriodEnd: stripe.Bool(false),
ProrationBehavior: stripe.String(string(stripe.SubscriptionProrationBehaviorCreateProrations)),
Items: []*stripe.SubscriptionItemsParams{
{
ID: stripe.String(subscription.Items.Data[0].ID),
Price: stripe.String("price_CBb6IXqvTLXp3f"),
},
},
}
subscription, err = sub.Update(subscription.ID, params)
This yields the following error:
unknown field 'Price' in struct literal of type "github.com/stripe/stripe-go".SubscriptionItemsParams
Any ideas where else the Price field might go?
I solved this by specifying a Stripe version in the import by changing this:
import (
"github.com/stripe/stripe-go"
"github.com/stripe/stripe-go/customer"
"github.com/stripe/stripe-go/sub"
)
to this:
import (
stripe "github.com/stripe/stripe-go/v74"
"github.com/stripe/stripe-go/v74/customer"
"github.com/stripe/stripe-go/v74/subscription"
)
It also appears that for v74,
ProrationBehavior: stripe.String(string(stripe.SubscriptionProrationBehaviorCreateProrations)),
should be changed to
ProrationBehavior: stripe.String(string(stripe.SubscriptionSchedulePhaseProrationBehaviorCreateProrations)),

How to return value from the Looker Golang sdk

I'm attempting to perform the run inline query api endpoint using the Looker Golang SDK. https://github.com/looker-open-source/sdk-codegen/blob/474ee9365dafe6549826a9f627ac0a79dc0e9a56/go/sdk/v4/models.go
https://developers.looker.com/api/explorer/4.0/methods/Query/run_inline_query
However when I execute this I get a blank response back not the expected data from fmt.Println(response). I also attempted to create and run, a sql query, while it looked like the API call executed I didn't receive any results in a very similar fashion. I feel like i'm missing something in getting results. I've validated these queries run in Looker.
Massive disclaimer, I'm a beginner to Golang. I'd really appreciate anyone being able to tell me what i'm doing wrong here.
func getDashboards(sdk *looker.LookerSDK) error {
fields := []string{
"dashboard.id",
"dashboard_element.id",
"dashboard_element.type",
"dashboard_element.result_source",
"query.model",
"query.view",
"query.formatted_fields",
"query.id",
"dashboard.title",
"look.id"}
limit := "5000"
response, err := sdk.RunInlineQuery(
looker.RequestRunInlineQuery{
ResultFormat: "json",
Body: looker.WriteQuery{
Model: "system__activity",
View: "dashboard",
Fields: &fields,
Limit: &limit,
},
}, nil)
if err != nil {
fmt.Println(err)
}
fmt.Println(response)
return err
}

http: superfluous response.WriteHeader call StatusOK

In my code, I've a loop that processing set of files (based on what available at pre-specified folder), and based on the output of each processed file, some info is sent to the client, so I wrote the below:
for i, file := range files {
uniqueSlice := unique(matches)
output = Output{MSG: "ok", File: file, Skills: uniqueSlice}
data, err := json.Marshal(output)
if err != nil {
panic(err)
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK) // -< Error from here
w.Write(data)
}
Above working correctly if the folder has a single file, but if has more than one, I got the error: http: superfluous response.WriteHeader call
I understood the error is due to using w.WriteHeader(http.StatusOK) which can not be used more than once to be set, but I need it to be set for the client to process the returned data.
How can I fix this code, so that I can return data directly to the client upon processing each file.
UPDATE
If I remove http.StatusOK as recommended in the comments below, then I get the returned as plain text not as JSON!
You can't just concatenate JSON documents together and expect the result to be valid json encoded. You'll have to put your output objects in an array and then output that array once at the end, otherwise the response won't be valid json.
If you output objects individually like your code did, the final data will look like
{"MSG": "ok", "File": "...", "Skills": [...]}{"MSG": "ok", "File": "...", "Skills": [...]}{"MSG": "ok", "File": "...", "Skills": [...]}
Each one of those outputs is valid by itself, but the entire output with the objects just concatenated together, is not.
Ideally, when outputting json to a stream like an HTTP response, instead of storing it in an intermediate buffer (data) for you, use json.NewEncoder(w) where w is the http response writer. Streaming is almost always better than rendering to a variable.
var outputs = make([]Output,0,len(files)
for i, file := range files {
uniqueSlice := unique(matches)
outputs = append(outputs, Output{MSG: "ok", File: file, Skills: uniqueSlice})
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(outputs); err != nil {
panic(err)
}

Programmatically get Account Id from lambda context arn

I have access to
com.amazonaws.services.lambda.runtime.Context;
object and by extension the invoked function Arn. The arn contains the account Id where the lambda resides.
My question is simple, I want the cleanest way to extract the account Id from that.
I was taking a look
com.amazon.arn.ARN;
It has a whole bunch of stuff, but no account ID (which i presume is due to the fact that not all arns have account ids ?)
I want to cleanly extract the account Id, without resorting to parsing the string.
If your lambda is being used as an API Gateway proxy lambda, then you have access to event.requestContext.accountId (where event is the first parameter to your handler function).
Otherwise, you will have to split the ARN up.
From the AWS documentation about ARN formats, here are the valid Lambda ARN formats:
arn:aws:lambda:region:account-id:function:function-name
arn:aws:lambda:region:account-id:function:function-name:alias-name
arn:aws:lambda:region:account-id:function:function-name:version
arn:aws:lambda:region:account-id:event-source-mappings:event-source-mapping-id
In all cases, account-id is the 5th item in the ARN (treating : as a separator). Therefore, you can just do this:
String accountId = arn.split(":")[4];
You no longer need to parse the arn anymore, sts library has introduced get_caller_identity for this purpose.
Its an overkill, but works!.
Excerpts from aws docs.
python
import boto3
client = boto3.client('sts')
response = client.get_caller_identity()['Account']
js
/* This example shows a request and response made with the credentials for a user named Alice in the AWS account 123456789012. */
var params = {
};
sts.getCallerIdentity(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
/*
data = {
Account: "123456789012",
Arn: "arn:aws:iam::123456789012:user/Alice",
UserId: "AKIAI44QH8DHBEXAMPLE"
}
*/
});
More details here & here
I use this:
ACCID: { "Fn::Join" : ["", [{ "Ref" : "AWS::AccountId" }, "" ]] }
golang
import (
"github.com/aws/aws-lambda-go/lambdacontext"
)
func Handler(ctx context.Context) error {
lc, ok := lambdacontext.FromContext(ctx)
if !ok {
return errors.Errorf("could not get lambda context")
}
AwsAccountId := strings.Split(lc.InvokedFunctionArn, ":")[4]

Auth with google sheets API V4 / REST / Go

I have read example https://developers.google.com/sheets/reference/rest/v4/spreadsheets.values/update from Google
Everything is great until I coming to authentication.
I would like to send this Put request to update a spreadsheet from my application from Golang:
key := "my key"
// I think I do not need key, because it have to be OAuth...
spreadsheetId := "myspreadsheetID"
link := fmt.Sprintf("https://sheets.googleapis.com/v4/spreadsheets/%s/values/A1?valueInputOption=RAW&fields=updatedCells&key=%s",
spreadsheetId, key)
request := gorequest.New()
resp, body, errs := request.Put(link).
Send(`{"values": [ ["hello","my", "friends" ] ]}`).
End()
if errs != nil {
fmt.Println(errs)
}
if resp.StatusCode != 200 {
fmt.Println(resp.Status)
}
fmt.Println(body)
The response is
401 Unauthorized
{
"error": {
"code": 401,
"message": "The request does not have valid authentication credentials.",
"status": "UNAUTHENTICATED"
}
}
I tried to grasp the Auth Guide but honestly I am not sure I figured out how can auth the request...
Any help would be appreciated very much.
Key is used for accessing Public data, Oauth2 requires that you authenticate and grant the application permission to access private data.
Worked in V3: If you want to use a key you can set the google sheet you are trying to access public and it will work.
Otherwise you are going to have to implement Oauth2. I cant help with go but a quick search on google turned up a bunch of Oauth2 tutorials for it.
Update:
I just did a quick check in the documentation. Method: spreadsheets.values.update
Authorization
Requires one of the following OAuth scopes:
* https://www.googleapis.com/auth/drive
* https://www.googleapis.com/auth/spreadsheets
which leads me to think that they removed the public trick from the v4 of the api. Looks like you are going to have to implement oauth2 or service accounts

Resources