我一直在使用谷歌日历来跟踪事件。简而言之,我想获取这些事件并下载与它们相关的附件。我正在 Go 中执行此操作,但我对任何可行的解决方案持开放态度..
我正在尝试做的是:
credentials.json [Where ServiceAccount and GoogleProject are my service account and google projects.]
{
"type": "service_account",
"project_id": "GoogleProject",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----...\n-----END PRIVATE KEY-----\n",
"client_email": "[email protected]",
"client_id": "...",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/ServiceAccount%40GoogleProject.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}
并创建一个 google.HTTPClient
import (
"context"
"flag"
"fmt"
"net/http"
"net/http/httputil"
"os"
"os/signal"
"syscall"
"time"
...... // Other imports
gCalendar "google.golang.org/api/calendar/v3"
gDrive "google.golang.org/api/drive/v3"
)
var googleCalendarID := "..."// The ID of SOMEONES google calendar
var googleCredentialsJson []byte
if googleCredentialsJson, err := os.ReadFile(
"google_application_credentials.json",
); err != nil || googleCredentialsJson == nil || len(googleCredentialsJson) == 0 {
log.Errorf("failed to read google_application_credentials.json:\n%v", err)
}
var googleJWTConf *jwt.Config
if googleJWTConf, err = google.JWTConfigFromJSON([]byte("GOOGLE_APPLICATION_CREDENTIALS"),
gCalendar.CalendarScope,
gCalendar.CalendarEventsScope,
gDrive.DriveScope,
"https://www.googleapis.com/auth/cloud-platform",
); err != nil {
log.Fatalf("error loading google credentials\n%+v", err)
}
googleCtx := context.Background()
googleHTTPClient := googleJWTConf.Client(googleCtx)
var googleCalendarService *gCalendar.Service
if googleCalendarService, err = gCalendar.NewService(googleCtx, option.WithHTTPClient(googleHTTPClient)); err != nil {
log.Fatalf("failed to start google calendar client\n%+v", err)
}
calEvents, err := googleCalendarService.Events.
List(googleCalendarID).
TimeMin(time.Now().Format(time.RFC3339)).
TimeMax(time.Now().Add(24 * 30 * time.Hour).Format(time.RFC3339)).
Context(googleCtx).Do()
if err != nil {
return nil, errors.Wrapf(err, "failed to list events for calendar %v", googleCalendarID)
}
calEvent := calEvents[0] // Just grab the first one until this works..
if len(calEvent.Attachments) > 0 {
rFileUrl = calEvent.Attachments[0].FileUrl // Just grab the first one until this works..
var request *http.Request
var err error
if request, err = http.NewRequestWithContext(ctx, "GET", rFileUrl, nil); err != nil {
return "", errors.Wrapf(err, "error creating request for file '%v'", rFileUrl)
}
var response *http.Response
if response, err = googleHTTPClient.Get(request); err != nil {
return "", errors.Wrapf(err, "error retrieving file '%v'", rFileUrl)
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK || "DENY" == response.Header.Get("X-Frame-Options") {
if tmpDump, err = httputil.DumpResponse(response, false); err != nil {
return "", errors.Wrapf(err, "error processing response code %v", response.StatusCode)
}
log.Errorf("dump:\n%+v", string(tmpDump))
return "", errors.Errorf("response code %v", response.StatusCode)
}
}
我已经尝试了从谷歌搜索中可以找到的几乎所有网址格式..但是每次尝试我都会遇到重定向到谷歌登录的情况。这种情况会发生即使文件是公开的(有趣的是,我可以访问它在未登录谷歌的浏览器会话中使用相同的网址)。我可以找到大量有关从您的驱动器下载文件的材料...但关于日历附件的资料却很少(手动添加或从驱动器添加)。我不太清楚附加到日历事件时文件存储在哪里。在图像最终加载之前似乎有一堆重定向?
FileUrl
具有如下所示的格式,它使用基于浏览器的云端硬盘客户端并且需要基于浏览器的身份验证:
https://drive.google.com/open?id={FileId}"
您想要的是使用 Drive API
URL(带有
?alt=media
),它接受 HTTP 客户端提供的 Authorization
标头:https://www.googleapis.com/drive/v3/files/{FileId}?alt=media
所以,尝试一下:
const endpoint string = "https://www.googleapis.com/drive/v3"
rFileID = calEvent.Attachments[0].FileId
rFileURL = fmt.Sprintf("%s/files/%s?alt=media", endpoint, rFileID)