gapi

package
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 7, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package gapi is a thin raw REST client for the Google Docs and Drive APIs. Requests are built by hand so Developer Preview fields that the generated client lacks can be sent; responses decode into the generated types where they exist. No MCP imports live here.

Index

Constants

View Source
const (
	DefaultDocsBaseURL  = "https://docs.googleapis.com"
	DefaultDriveBaseURL = "https://www.googleapis.com/drive/v3"
)

Default endpoints.

View Source
const (
	SuggestionsInline          = "SUGGESTIONS_INLINE"
	SuggestionsPreviewAccepted = "PREVIEW_SUGGESTIONS_ACCEPTED"
	CommentsIncluded           = "COMMENTS_VIEW_MODE_INCLUDED" // Developer Preview
)

View modes for documents.get.

View Source
const CommentFields = "id,content,htmlContent,author(displayName,emailAddress),createdTime,modifiedTime,resolved,deleted,anchor,quotedFileContent,replies(" + ReplyFields + ")"

CommentFields is what the comment calls ask for.

View Source
const DocumentMimeType = "application/vnd.google-apps.document"

DocumentMimeType is the Drive MIME type of a Google Doc.

View Source
const FileFields = "" /* 188-byte string literal not displayed */

FileFields is what GetFile asks Drive for.

View Source
const ReplyFields = "id,content,author(displayName,emailAddress),createdTime,action,deleted"

ReplyFields is what reply calls ask for.

View Source
const RevisionFields = "id,mimeType,modifiedTime,keepForever,lastModifyingUser(displayName,emailAddress)"

RevisionFields is what ListRevisions asks for per revision.

View Source
const SearchFields = "" /* 151-byte string literal not displayed */

SearchFields is what SearchFiles asks for per file.

Variables

View Source
var (
	ErrUnauthorized = errors.New("unauthorized")
	ErrMissingScope = errors.New("missing scope")
	ErrForbidden    = errors.New("forbidden")
	ErrNotFound     = errors.New("not found")
	ErrRateLimited  = errors.New("rate limited")
	ErrServer       = errors.New("server error")
	ErrInvalid      = errors.New("invalid request")
	ErrConflict     = errors.New("revision conflict")
	ErrNetwork      = errors.New("network error")
	ErrAmbiguous    = errors.New("ambiguous outcome")
	ErrUnexpected   = errors.New("unexpected response")
	// ErrNoCredentials is the token-source error when no login exists.
	ErrNoCredentials = errors.New("no credentials stored; run `google-docs-mcp login`")
)

Sentinel error classes. Every error returned by the client wraps exactly one of them so callers can branch with errors.Is.

View Source
var ExportMimeTypes = map[string]string{
	"pdf":  "application/pdf",
	"docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
	"odt":  "application/vnd.oasis.opendocument.text",
	"rtf":  "application/rtf",
	"txt":  "text/plain",
	"html": "text/html",
	"md":   "text/markdown",
	"epub": "application/epub+zip",
}

ExportMimeTypes maps short format names to Drive export MIME types.

Functions

func Class

func Class(err error) string

Class returns a short lower-case class name for an error, for LLM-facing messages. Every value it returns is in Classes, and service.Classes is the whole vocabulary this server speaks.

func Classes added in v0.9.3

func Classes() []string

Classes lists every class Class can return, so a test can check this half of the vocabulary against the service's list rather than trusting two comments to agree.

func QuoteDriveValue

func QuoteDriveValue(s string) string

QuoteDriveValue escapes a string for use inside single quotes in a Drive query.

func ShortID

func ShortID(id string) string

ShortID shortens a document or file id. It is for a filename a person has to recognise, never for a log: §12 promises a log carries nothing about the document, and six characters of an id is still six characters of an id.

It used to end a shortened id with U+2026, which reads well in prose and badly in a filename: an outside user reported it, and they were right. A character outside ASCII in a name a person has to type, tab complete, quote in a shell or move between filesystems buys nothing here — the id fragment is there to tell two exports of the same title apart, and it does that without announcing that it is short.

Types

type APIError

type APIError struct {
	Status  int
	RPC     string // e.g. NOT_FOUND, PERMISSION_DENIED
	Reason  string // e.g. ACCESS_TOKEN_SCOPE_INSUFFICIENT
	Message string
	Method  string
	Path    string
}

APIError is a non-2xx response from Google, decoded from the standard error envelope.

func (*APIError) Error

func (e *APIError) Error() string

func (*APIError) Unwrap

func (e *APIError) Unwrap() error

Unwrap maps the response onto a sentinel class.

type About

type About struct {
	User *User `json:"user,omitempty"`
}

About is the about.get response subset we read.

type AuthError

type AuthError struct {
	Code string
	Msg  string
}

AuthError is a failure to obtain an access token (revoked or expired refresh token, bad client secret).

func (*AuthError) Error

func (e *AuthError) Error() string

func (*AuthError) Unwrap

func (e *AuthError) Unwrap() error

Unwrap classifies every auth failure as unauthorized.

type BatchUpdateRequest

type BatchUpdateRequest struct {
	Requests     []json.RawMessage `json:"requests"`
	WriteControl *WriteControl     `json:"writeControl,omitempty"`
}

BatchUpdateRequest is the body of documents.batchUpdate. Requests are pre-marshalled so GA and preview request types share one path.

type BatchUpdateResponse

type BatchUpdateResponse struct {
	DocumentID   string            `json:"documentId"`
	Replies      []json.RawMessage `json:"replies"`
	WriteControl *WriteControl     `json:"writeControl"`
	Raw          json.RawMessage   `json:"-"`
}

BatchUpdateResponse is the decoded reply.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client talks to Google with one user's credentials.

func New

func New(ts oauth2.TokenSource, o Options) *Client

New builds a client whose requests carry tokens from ts.

func (*Client) About

func (c *Client) About(ctx context.Context) (*User, error)

About returns the signed-in user, the cheapest authenticated call.

func (*Client) BatchUpdate

func (c *Client) BatchUpdate(ctx context.Context, id string, req *BatchUpdateRequest) (*BatchUpdateResponse, error)

BatchUpdate applies requests atomically. A network failure after the request was sent is reported as ErrAmbiguous, never retried blindly.

func (*Client) CreateComment

func (c *Client) CreateComment(ctx context.Context, fileID, content, quote string) (*DriveComment, error)

CreateComment adds a Drive comment quoting text. The Docs UI shows it unanchored (with the quote) because Drive anchors are opaque to Docs.

func (*Client) CreateDocument

func (c *Client) CreateDocument(ctx context.Context, title string) (*gdocs.Document, error)

CreateDocument creates an empty document with the title and returns it.

func (*Client) CreateReply added in v0.2.0

func (c *Client) CreateReply(ctx context.Context, fileID, commentID, content, action string) (*DriveReply, error)

CreateReply posts a reply on a comment thread. action is "" for a plain reply, "resolve" to resolve the thread or "reopen" to reopen it.

func (*Client) DeleteComment added in v0.2.0

func (c *Client) DeleteComment(ctx context.Context, fileID, commentID string) error

DeleteComment deletes a comment thread. Drive keeps it listable with includeDeleted=true.

func (*Client) DeleteReply added in v0.2.0

func (c *Client) DeleteReply(ctx context.Context, fileID, commentID, replyID string) error

DeleteReply deletes one reply of a thread.

func (*Client) Export

func (c *Client) Export(ctx context.Context, id, mimeType string) ([]byte, error)

Export downloads the document converted to the MIME type. Google caps exports at 10 MB.

func (*Client) ExportRevision added in v0.2.0

func (c *Client) ExportRevision(ctx context.Context, fileID, revisionID, mimeType string) ([]byte, error)

ExportRevision exports one revision of a document through files.download, the only Drive method that takes a revisionId for Docs files. It starts a long-running operation, polls it, then fetches the content it names. The content URL must stay on Google's hosts.

The POST that starts it is a read: it creates nothing in the person's Drive, so repeating it costs an export, not a duplicate. That is what kindRead now means — retryable on any transient failure — so a POST that does change something must not borrow it.

func (*Client) GetComment added in v0.2.0

func (c *Client) GetComment(ctx context.Context, fileID, commentID string) (*DriveComment, error)

GetComment returns one comment thread with its replies.

func (*Client) GetDocument

func (c *Client) GetDocument(ctx context.Context, id string, o GetOptions) (*DocumentResult, error)

GetDocument fetches a document with tabs content.

func (*Client) GetFile

func (c *Client) GetFile(ctx context.Context, id string) (*File, error)

GetFile returns Drive metadata for a document.

func (*Client) ListComments

func (c *Client) ListComments(ctx context.Context, fileID string, includeDeleted bool) ([]*DriveComment, error)

ListComments returns every comment thread on the file.

func (*Client) ListRevisions added in v0.2.0

func (c *Client) ListRevisions(ctx context.Context, fileID string) ([]*Revision, error)

ListRevisions returns every revision of the file, oldest first as Drive orders them.

func (*Client) SearchFiles

func (c *Client) SearchFiles(ctx context.Context, q string, limit int, pageToken string) (*FileList, error)

SearchFiles runs a Drive query (the caller builds and escapes q) across My Drive and shared drives, newest first.

func (*Client) UpdateComment added in v0.4.0

func (c *Client) UpdateComment(ctx context.Context, fileID, commentID, content string) (*DriveComment, error)

UpdateComment rewrites a comment's own text. Only its author may; Drive answers 403 otherwise.

func (*Client) UpdateReply added in v0.4.0

func (c *Client) UpdateReply(ctx context.Context, fileID, commentID, replyID, content string) (*DriveReply, error)

UpdateReply rewrites one reply's text, with the same author rule.

type DocumentResult

type DocumentResult struct {
	Document *gdocs.Document
}

DocumentResult is a decoded documents.get response. Comment and suggestion threads (Developer Preview) are on the document itself.

type DriveComment

type DriveComment struct {
	ID                string        `json:"id,omitempty"`
	Content           string        `json:"content,omitempty"`
	HTMLContent       string        `json:"htmlContent,omitempty"`
	Author            *User         `json:"author,omitempty"`
	CreatedTime       string        `json:"createdTime,omitempty"`
	ModifiedTime      string        `json:"modifiedTime,omitempty"`
	Resolved          bool          `json:"resolved,omitempty"`
	Deleted           bool          `json:"deleted,omitempty"`
	Anchor            string        `json:"anchor,omitempty"`
	QuotedFileContent *QuotedText   `json:"quotedFileContent,omitempty"`
	Replies           []*DriveReply `json:"replies,omitempty"`
}

DriveComment is a Drive API comment thread on a file.

type DriveReply

type DriveReply struct {
	ID          string `json:"id,omitempty"`
	Content     string `json:"content,omitempty"`
	Author      *User  `json:"author,omitempty"`
	CreatedTime string `json:"createdTime,omitempty"`
	Action      string `json:"action,omitempty"`
	Deleted     bool   `json:"deleted,omitempty"`
}

DriveReply is one reply in a thread.

type File

type File struct {
	ID                string            `json:"id,omitempty"`
	Name              string            `json:"name,omitempty"`
	MimeType          string            `json:"mimeType,omitempty"`
	CreatedTime       string            `json:"createdTime,omitempty"`
	ModifiedTime      string            `json:"modifiedTime,omitempty"`
	Owners            []*User           `json:"owners,omitempty"`
	LastModifyingUser *User             `json:"lastModifyingUser,omitempty"`
	WebViewLink       string            `json:"webViewLink,omitempty"`
	Version           string            `json:"version,omitempty"`
	Trashed           bool              `json:"trashed,omitempty"`
	Capabilities      *FileCapabilities `json:"capabilities,omitempty"`
}

File is the files.get response subset we read.

type FileCapabilities

type FileCapabilities struct {
	CanEdit    bool `json:"canEdit,omitempty"`
	CanComment bool `json:"canComment,omitempty"`
	CanShare   bool `json:"canShare,omitempty"`
}

FileCapabilities are the caller's rights on a file.

type FileList

type FileList struct {
	Files         []*File `json:"files"`
	NextPageToken string  `json:"nextPageToken,omitempty"`
}

FileList is a page of files.list results.

type GetOptions

type GetOptions struct {
	SuggestionsViewMode string
	CommentsViewMode    string
}

GetOptions select what documents.get returns. Tabs content is always requested because every other choice loses information.

type NoCredentials

type NoCredentials struct{ Reason error }

NoCredentials is a token source that always fails with ErrNoCredentials so a server without a login still starts and answers every call with an actionable auth error.

func (NoCredentials) Token

func (n NoCredentials) Token() (*oauth2.Token, error)

Token implements oauth2.TokenSource.

type Options

type Options struct {
	// BaseTransport sits under the OAuth transport. nil uses http.DefaultTransport.
	BaseTransport http.RoundTripper
	DocsBaseURL   string
	DriveBaseURL  string
	Logger        *slog.Logger
	// Timeout applies per attempt.
	Timeout time.Duration
	Retry   RetryPolicy
	// Limiters stay under the per-user quotas (300 reads and 60 writes per minute).
	ReadLimiter  *rate.Limiter
	WriteLimiter *rate.Limiter
	UserAgent    string
	// Sleep is replaced in tests.
	Sleep func(context.Context, time.Duration) error
	// AllowURL decides which URLs receive credentials; nil means HTTPS to
	// Google's API and content hosts only. Tests point it at their server.
	AllowURL func(u *url.URL) bool
}

Options configure a Client. Zero values are production defaults.

type QuotedText

type QuotedText struct {
	MimeType string `json:"mimeType,omitempty"`
	Value    string `json:"value,omitempty"`
}

QuotedText is the text a comment refers to.

type RetryPolicy

type RetryPolicy struct {
	MaxAttempts int
	BaseDelay   time.Duration
	MaxDelay    time.Duration
}

RetryPolicy bounds retries for transient failures.

func DefaultRetry

func DefaultRetry() RetryPolicy

DefaultRetry is exponential backoff with jitter, capped at 30 seconds.

type Revision added in v0.2.0

type Revision struct {
	ID                string `json:"id,omitempty"`
	MimeType          string `json:"mimeType,omitempty"`
	ModifiedTime      string `json:"modifiedTime,omitempty"`
	KeepForever       bool   `json:"keepForever,omitempty"`
	LastModifyingUser *User  `json:"lastModifyingUser,omitempty"`
}

Revision is a Drive revision (version history entry) of a document.

type User

type User struct {
	DisplayName  string `json:"displayName,omitempty"`
	EmailAddress string `json:"emailAddress,omitempty"`
}

User is a Drive user reference.

type WriteControl

type WriteControl struct {
	RequiredRevisionID string `json:"requiredRevisionId,omitempty"`
	TargetRevisionID   string `json:"targetRevisionId,omitempty"`
	WriteMode          string `json:"writeMode,omitempty"` // "SUGGEST" (preview)
}

WriteControl guards a batchUpdate against concurrent edits and, in Developer Preview, selects suggestion mode.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL