Commit Graph

519 Commits

Author SHA1 Message Date
Peter Steinberger
a92bd6322b fix(live-tests): make live scripts cwd-safe
Some checks failed
ci / test (push) Has been cancelled
ci / worker (push) Has been cancelled
ci / darwin-cgo-build (push) Has been cancelled
2026-02-14 04:32:13 +01:00
Peter Steinberger
6f94feadb7 docs(changelog): cut 0.10.0 section 2026-02-14 04:07:07 +01:00
Peter Steinberger
aa0c9168ff docs(changelog): reorder unreleased notes by user impact 2026-02-14 04:06:26 +01:00
Peter Steinberger
a0427f0657 fix(cli): resolve alias routing and preserve dry-run envelope 2026-02-14 04:05:39 +01:00
salmonumbrella
3371e3f3ad
feat(cli): agent ergonomics + gmail watch exclude labels (#201)
* feat(cli): improve agent ergonomics

* fix(cli): address code review findings

- Fix nil pointer dereference in confirmDestructive when flags is nil
- Deduplicate dry-run logic by delegating to dryRunExit
- Remove deprecated net.Error.Temporary() call (dead since Go 1.18)
- Add unit tests for resolveTasklistID and resolveCalendarID

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve PR #201 conflicts and follow-ups (#201) (thanks @salmonumbrella)

* fix: resolve rebase fallout for PR #201 landing (#201) (thanks @salmonumbrella)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 03:09:49 +01:00
Peter Steinberger
16fdf07618 fix(calendar): make date-like --to inclusive without changing --to now
Land #204 and preserve point-in-time semantics for --to now.

Co-authored-by: Michal Jaskolski <mjaskolski@users.noreply.github.com>
2026-02-14 02:23:52 +01:00
Alex Hillman
2f51319955
feat(docs): add tab support and editing commands (write, insert, delete, find-replace) (#225)
* feat(docs): add tab support for Google Docs

Add support for Google Docs tabs (multi-tab documents):

- `docs list-tabs <docId>`: List all tabs with ID, title, and index
- `docs cat <docId> --all-tabs`: Print all tabs with headers
- `docs cat <docId> --tab <title|id>`: Print a specific tab by title or ID

Key behaviors:
- Default `docs cat` (no flags) is fully backward compatible
- Tab lookup supports both exact ID match and case-insensitive title match
- Nested/child tabs are flattened and included in all operations
- JSON output supported for all tab operations

Uses the Google Docs API `includeTabsContent` parameter to retrieve
tab-aware document content via `Document.Tabs`.

Closes #125

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(docs): add write, insert, delete, find-replace commands

Port custom editing commands from fork to upstream architecture:
- write: append or replace doc content (plain text or markdown)
- insert: insert text at specific character index
- delete: delete text range by start/end index
- find-replace: find and replace text with optional case matching

Also fix lint issues: err shadow in tab support code, goconst for
string literal "true".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(docs): harden tab/write paths and add editing regressions (#225) (thanks @alexknowshtml)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 02:05:58 +01:00
Peter Steinberger
6228856668 fix(sheets): preserve tabs for sheets get --plain
Co-authored-by: salmonumbrella <182032677+salmonumbrella@users.noreply.github.com>
2026-02-14 01:28:54 +01:00
Peter Steinberger
9eaff65f41 fix(gmail): harden quoted-printable detection for URL safety (#186) (thanks @100menotu001) 2026-02-14 01:23:51 +01:00
Agent
19e1832663 fix: use uppercase-only hex detection to avoid URL false positives
Matt's security review caught that URLs like '?foo=bar' would incorrectly
trigger QP detection because '=ba' matches as hex digits.

Changed to only match UPPERCASE hex (0-9, A-F) since:
- RFC 2045 recommends uppercase for QP encoding
- Most encoders use uppercase in practice
- This avoids false positives from lowercase URL params
2026-02-14 01:23:51 +01:00
Agent
da99077a7f fix(gmail): prevent URL corruption in quoted-printable decoding
When Gmail API returns already-decoded content (format=full), the
Content-Transfer-Encoding header may still say 'quoted-printable'.
Previously, we would attempt to QP-decode again, causing raw '='
characters in URLs to be replaced with U+FFFD (replacement char).

This adds looksLikeQuotedPrintable() to detect actual QP sequences
(=XX hex or =CRLF soft breaks) and skip decoding when content appears
pre-decoded.

Fixes #159
2026-02-14 01:23:51 +01:00
Peter Steinberger
12515372fc fix(drive): align upload replace with convert/lint semantics 2026-02-14 01:04:01 +01:00
salmonumbrella
c39d731a5c feat(drive): add upload --replace for in-place updates 2026-02-14 00:59:10 +01:00
Peter Steinberger
bad3c01b56 test(secrets): add keyring label regression coverage 2026-02-14 00:35:38 +01:00
Maksym Mykhailenko
67874b9e8f fix(keychain): label items as gogcli for macOS prompt
macOS keychain dialogs showed an empty item label on access.
 Set the keychain item label to "gogcli" so the prompt is clear.
2026-02-14 00:32:17 +01:00
Chris Parsons
8b08d11777
feat(slides): add add-slide, list-slides, and delete-slide commands (#214)
* feat(slides): add `slides add-slide` command for full-bleed image slides

Adds a new `gog slides add-slide <presentationId> <image>` command that
appends a slide with a full-bleed image and optional speaker notes using
the native Google Slides API (presentations.batchUpdate).

Workflow: create a deck with `gog slides create`, then add slides one at
a time with this command. Supports --notes for inline text and
--notes-file for multiline markdown speaker notes.

Also registers ServiceSlides in the auth layer with proper scopes and
readonly support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(slides): add list-slides and delete-slide commands

list-slides shows all slide object IDs in a presentation.
delete-slide removes a slide by its object ID.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(slides): add --before flag to add-slide for insertion ordering

Allow inserting a slide before a specific existing slide ID instead of
always appending to the end of the presentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(slides): add read-slide, update-notes, and replace-slide commands

Adds three new commands to support in-place editing of existing slides:

- `slides read-slide` — shows slide content including speaker notes,
  text elements, and image references (supports --json output)
- `slides update-notes` — updates speaker notes on an existing slide
  without deleting/re-adding (--notes or --notes-file)
- `slides replace-slide` — atomically swaps the image on an existing
  slide using the ReplaceImage API, optionally updating notes in the
  same batch operation

These eliminate the error-prone delete+add-before workflow when editing
slides in existing decks.

Closes chrismdp/gogcli#1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(slides): rebase PR 214, clear notes semantics, and hard-fail missing placeholders (#214) (thanks @chrismdp)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 00:21:59 +01:00
Gonçalo Alves
7945602f15
feat: add docs update command for editing Google Docs (#219)
* feat: add docs update command for editing Google Docs

* fix: handle document content range correctly for replace

* docs: add Jarbas avatar

* feat(gogcli): add markdown formatting support for Google Docs

Phase 1 & 2 complete:
- Markdown parser supporting headings, lists, code blocks, blockquotes, links
- Google Docs API integration for formatting
- --format markdown flag for docs update command
- Heading styles (H1-H6), horizontal rules, list indentation
- Code blocks with monospace font

Pending (Phase 3):
- Inline formatting (bold, italic, inline code) - index calculation issues
- Links - index calculation issues

Usage:
  gog docs update <docId> --content-file ./doc.md --format markdown

* fix(gogcli): fix inline formatting indices in markdown formatter

- Simplified document generation to avoid index calculation errors
- Fixed ParseInlineFormatting to correctly track positions
- Preserves: headings, code blocks, blockquotes, lists, horizontal rules

Pending: inline formatting (bold, italic, code, links) - indices still need work

* fix(gogcli): use UTF-16 code units for Google Docs API indexing

- Fixed markdown formatter to use UTF-16 code units instead of UTF-8 bytes
- Added utf16Len() helper function for accurate character counting
- Fixed inline formatting indices (bold, italic, code, links)
- Added empty line handling (MDEmptyLine)
- Successfully tested with Docker course doc (21KB, emojis, diagrams)

This resolves index mismatch errors caused by multi-byte characters like emojis
which are 4 bytes in UTF-8 but 2 code units in UTF-16.

* feat(gogcli): add slides commands with markdown support

- Add 'gog slides update' command with markdown formatting
- Create slides_formatter.go for Google Slides API batch updates
- Create slides_markdown.go for markdown parsing (titles, bullets, code)
- Add slides.go with update/create/read operations
- Update googleauth service for Slides scope

Related: PR #219

* fix(gogcli): use shapes for slides text boxes instead of direct insertion

- Fixed slides creation to use CreateShape with TEXT_BOX instead of inserting text directly
- Direct text insertion into slides is not supported by Google Slides API
- Added title text box with bold 36pt font
- Added body text box for content (bullets, paragraphs, code)
- Supports markdown formatting (bold, bullets, code blocks)

Tested: Successfully created 20-slide presentation from Docker course outline

* feat: add markdown table support (formatted text output)

* feat: implement native Google Docs table insertion with multi-step API

* feat(slides): add --template flag for creating presentations from templates

* fix: stabilize docs/slides markdown + auth flow (#219) (thanks @goncaloalves)

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 22:52:17 +01:00
Peter Steinberger
49eb68b412 fix(gmail): harden labels delete id resolution 2026-02-13 20:36:57 +01:00
Helmi
48a2ad6ed5 feat(gmail): add labels delete command 2026-02-13 20:32:57 +01:00
Peter Steinberger
49a394315d fix(docs): harden markdown import cleanup and path resolution 2026-02-13 19:15:02 +01:00
Chris Parsons
7ff05d583a feat(docs): add --file flag to create Google Doc from Markdown
Upload a Markdown file to Google Drive with auto-conversion to native
Docs format. Images are handled in a second pass: markdown image
references are replaced with placeholders during upload, then the
created document is read back via the Docs API to locate placeholder
positions and replace them with inline images (InsertInlineImage).

Local images are uploaded to Drive temporarily with public read access
(required by the Docs API), then cleaned up after insertion. Remote
URLs (http/https) are used directly. Path traversal is prevented by
resolving symlinks and verifying images stay within the markdown
file's directory.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 19:07:34 +01:00
Peter Steinberger
1a19a27f07 fix(googleapi): honor proxy env in custom OAuth transport 2026-02-13 18:36:58 +01:00
Ross Sivertsen - Systems Sherpa
077f9a3620
contacts: support --birthday and --notes in contacts update (#233)
* contacts: allow updating birthday and notes

* fix(cli): unify date parsing + cover contacts birthday/notes (#233) (thanks @rosssivertsen)

---------

Co-authored-by: Ross Sivertsen <ross@canyoncreek.co>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-13 18:16:49 +01:00
Peter Steinberger
2ecdf2f147 feat(drive): add upload conversion flags
Add Drive upload conversion with auto detection (--convert) and explicit targets (--convert-to), preserve explicit --name values, and improve conversion behavior tests/docs for PR #240.

Co-authored-by: Daniel Weber <daniel@suno.com>
2026-02-13 16:38:19 +01:00
Peter Steinberger
f8a92e3232 docs(readme): document manual and split remote auth flows 2026-02-13 14:16:02 +01:00
salmonumbrella
2df8ece2f6
fix(auth): enforce remote manual auth state (#187)
* fix(gmail): fallback to send-as list for display name

* refactor(gmail): remove dead code in primarySendAsDisplayNameFromList

The condition `primary == nil && sa.IsPrimary` inside the email-matching
block can never be true because `primary` is already unconditionally set
to `sa` when `sa.IsPrimary` is true earlier in the same loop iteration.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test(gmail): add --from display name fallback to list test

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(auth): persist manual oauth state

* feat(cli): add remote manual auth flow

* fix(auth): enforce remote manual auth state

* fix(auth): satisfy lint for manual auth flow

* fix(auth): harden remote manual auth state cache

* chore: update changelog for remote manual auth (#187) (thanks @salmonumbrella)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-09 10:38:26 -08:00
Daniel Weber
e3cb940780
feat(drive): add --domain flag to share command (#192)
* feat(drive): add --domain flag to share command

Allow sharing files/folders with an entire Google Workspace domain
(e.g. `gog drive share <id> --domain=example.com --role=writer`).
This creates a "domain" type permission in the Drive API, enabling
the "Anyone in <org> with the link" sharing mode.

Also updates `permissions` output to display domain names.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(drive): add --to target for share (#192) (thanks @Danielkweber)

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-06 16:42:39 -08:00
Peter Steinberger
60762e3619 docs: add changelog for #194 (thanks @salmonumbrella) 2026-02-06 16:04:24 -08:00
salmonumbrella
e593322d79
feat(gmail): add --exclude-labels to watch serve (#194) 2026-02-06 16:02:56 -08:00
Waren Gonzaga
3463597922 docs: update README with GitHub Repo Banner 2026-02-01 05:59:22 +01:00
Peter Steinberger
99d957581f feat(auth): add multi-org login
Some checks failed
ci / test (push) Has been cancelled
ci / worker (push) Has been cancelled
ci / darwin-cgo-build (push) Has been cancelled
2026-01-22 04:04:14 +00:00
Peter Steinberger
417644868a perf(gmail): trim message search fields 2026-01-22 01:46:42 +00:00
Peter Steinberger
b392e4df6a
Merge pull request #88 from mbelinky/feat/gmail-message-search
feat(gmail): add message-level search + body decoding
2026-01-22 01:16:20 +00:00
Peter Steinberger
07a0691d54 feat: harden gmail message search body handling (#88) (thanks @mbelinky) 2026-01-22 01:15:23 +00:00
Mariano Belinky
c340914688 feat(gmail): add message search + decode bodies 2026-01-22 01:12:09 +00:00
Peter Steinberger
c23e489741
Merge pull request #103 from salmonumbrella/fix/gmail-thread-read
fix(gmail): allow read alias for threads
2026-01-22 00:46:43 +00:00
Peter Steinberger
6d37254f20 fix: add gmail thread read alias (#103) (thanks @salmonumbrella) 2026-01-22 00:46:07 +00:00
salmonumbrella
de9854ab51 fix(gmail): allow read alias for threads 2026-01-22 00:45:38 +00:00
Peter Steinberger
16cdb1491e
Merge pull request #100 from salmonumbrella/fix/issue-97-reminders
fix(calendar): force reminders override payload
2026-01-21 23:09:34 +00:00
Peter Steinberger
de683a58e0 fix: force calendar reminders payload (#100) (thanks @salmonumbrella) 2026-01-21 23:09:08 +00:00
salmonumbrella
3f513466e9 docs: add comment explaining ForceSendFields
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:08:44 +00:00
salmonumbrella
e482fbc6d5 fix(calendar): force reminders override payload 2026-01-21 23:08:43 +00:00
Peter Steinberger
ce7c10a3ce
Merge pull request #102 from salmonumbrella/fix/issue-101-birthday
fix(contacts): include birthdays on get
2026-01-21 20:36:16 +00:00
Peter Steinberger
5dda313c74 fix: show contact birthdays (#102) (thanks @salmonumbrella) 2026-01-21 20:35:31 +00:00
salmonumbrella
b8f15931fa fix(contacts): include birthdays on get 2026-01-21 20:35:06 +00:00
Peter Steinberger
b6a19e62a1 feat: show gmail thread message counts (#99) (thanks @jeanregisser) 2026-01-21 19:10:40 +00:00
Peter Steinberger
c2b784a9c0
Merge pull request #99 from jeanregisser/add-thread-count-indicator-new
feat(gmail): Add thread message count to search results
2026-01-21 19:10:17 +00:00
Peter Steinberger
f19a06f2a7
Merge pull request #92 from salmonumbrella/feat/calendar-timezone-display
feat(calendar): add timezone/local time display to event output
2026-01-21 10:58:21 +00:00
Peter Steinberger
eeb16560ce feat: add calendar timezone display (#92) (thanks @salmonumbrella) 2026-01-21 10:58:00 +00:00
salmonumbrella
cb9b240863 fix(lint): remove unused funcs, reduce cyclomatic complexity
- Remove unused wrapEventWithDays and printCalendarEvent functions
- Extract printEventAttendees and printEventReminders helpers
  to reduce printCalendarEventWithTimezone complexity from 51 to ~40

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 10:57:37 +00:00