Commit 0d772490fa81

Vincent Demeester <vincent@sbr.pm>
2025-10-29 09:06:04
tools: exctracted go-org-readwise out of this repository
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
1 parent 588b37f
pkgs/default.nix
@@ -15,7 +15,6 @@ in
   vde-thinkpad = pkgs.callPackage ./my/vde-thinkpad { };
   bekind = pkgs.callPackage ../tools/bekind { };
   battery-monitor = pkgs.callPackage ../tools/battery-monitor { };
-  go-org-readwise = pkgs.callPackage ../tools/go-org-readwise { };
   ape = pkgs.callPackage ./ape { };
   ram = pkgs.callPackage ./ram { };
   govanityurl = pkgs.callPackage ./govanityurl { };
systems/kyushu/extra.nix
@@ -111,7 +111,7 @@
   environment.systemPackages = with pkgs; [
     kanata
     nixos-rebuild-ng
-    go-org-readwise
+    # go-org-readwise # FIXME: will add it back from its new place.
     battery-monitor
     # backup
     restic # TODO: will probably move this to it's own configuration some day
tools/go-org-readwise/internal/org/testdata/test.org
@@ -1,104 +0,0 @@
-#+title:      denote
-#+date:       [2023-11-20 Mon 12:31]
-#+filetags:   :emacs:notes:orgmode:
-#+identifier: 20231120T123124
-#+category: denote
-
-It is an [[denote:20231120T152341][emacs]] package that allows you to link to files in your org-mode documents.
-
-* Thoughts
-
-The presence of the tags in the filename seem to be both nice and bad at the same time. I
-think time will tell.
-
-* Links
-
-- https://takeonrules.com/2022/10/01/exploring-the-denote-emacs-package/
-  Really interesting, simple take
-- https://takeonrules.com/2022/11/19/project-dispatch-menu-with-org-mode-metadata-denote-and-transient/
-- https://lucidmanager.org/productivity/taking-notes-with-emacs-denote/
-
-** [[https://baty.blog/2022/keeping-my-org-agenda-updated/][Keeping my Org Agenda updated based on Denote keywords - Jack Baty]]
-[2024-02-28 Wed 16:14]
-
-* Dynamic blocks
-
-Old regexp "md\\|org"
-
-#+BEGIN: denote-links :regexp "md"
-- [[denote:20230815T192545][2023-08-15]]
-- [[denote:20230929T113052][Always be quitting - Julio Merino (jmmv.dev)]]
-- [[denote:20230929T113053][Behavior Driven Development]]
-- [[denote:20230929T113054][Blog]]
-- [[denote:20230929T113058][Hyprland]]
-- [[denote:20230929T180738][A Practical Guide to Distributed Scrum]]
-- [[denote:20230929T180739][Culture & Empire]]
-- [[denote:20230929T180740][Debugging Teams]]
-- [[denote:20230929T180741][Getting Things Done]]
-- [[denote:20230929T180742][Inspired]]
-- [[denote:20230929T180743][Remote]]
-- [[denote:20230929T180744][Sleep Smarter]]
-- [[denote:20230929T180745][Staff Engineer]]
-- [[denote:20230929T180746][The Flinch]]
-- [[denote:20230929T180747][The Phoenix Project]]
-- [[denote:20230929T182110][Make Time]]
-- [[denote:20230930T094128][Actually, dark mode can save the planet]]
-- [[denote:20231005T185635][Build Tools Around Workflows, Not Workflows Around Tools]]
-- [[denote:20231006T080429][Counterculture in the Age of Hyperconnectivity]]
-- [[denote:20231006T080435][Don’t Use Stale Bots]]
-- [[denote:20231006T080443][Flake Schemas Making Flake Outputs Extensible · Determinate Systems]]
-- [[denote:20231006T080450][Flexibility]]
-- [[denote:20231006T080643][Beyond customization build tools that grow with us]]
-- [[denote:20231006T080657][40 Questions to Ask Yourself Every Year]]
-- [[denote:20231010T101856][DSLs Are a Waste of Time]]
-- [[denote:20231011T095229][Accept Interfaces Return Struct in Go [2018]]]
-- [[denote:20231016T095412][Choose Boring Technology]]
-- [[denote:20231016T095413][How I Made Peace With Automated Testing. Part 1 — You’re Using Too Many Mocks]]
-- [[denote:20231016T095414][How I Made Peace With Automated Testing. Part 2 - The Fun Tools Are Not Only Javascript]]
-- [[denote:20231017T185415][I Am No Longer Using Flakes]]
-- [[denote:20231019T082509][Concise Explanations Accelerate Progress]]
-- [[denote:20231028T145022][How I Get Things Done]]
-- [[denote:20231114T101657][Fast Path to Burnout - Delaying Deploys]]
-- [[denote:20231123T190449][Joining Getting Things Done and Building a Second Brain Philosophies]]
-- [[denote:20231129T185607][Building a Second Brain]]
-- [[denote:20231201T154535][Donald Knuth on work habits, problem solving, and happiness]]
-- [[denote:20231201T154630][Estimates are about time, so let's cut to the chase]]
-#+END:
-
-#+BEGIN: denote-links :regexp "_notes\\|_emacs"
-- [[denote:20231122T104723][granite, obsidian-like org-mode setup]]
-- [[denote:20231217T094656][Readwise org sync]]
-- [[denote:20231006T080643][Beyond customization build tools that grow with us]]
-- [[denote:20231120T123124][denote]]
-- [[denote:20231120T152341][Emacs]]
-- [[denote:20240119T151128][Obsidian]]
-- [[denote:20240119T151404][Obsidian plugins]]
-- [[denote:20240119T151801][Obsidian publishing]]
-#+END:
-
-#+BEGIN: denote-links :regexp ".*_notes"
-- [[denote:20231120T123124][denote]]
-- [[denote:20231120T152341][Emacs]]
-- [[denote:20240119T151128][Obsidian]]
-- [[denote:20240119T151404][Obsidian plugins]]
-- [[denote:20240119T151801][Obsidian publishing]]
-#+END:
-
-#+BEGIN: denote-links :regexp ".*_emacs"
-- [[denote:20231122T104723][granite, obsidian-like org-mode setup]]
-- [[denote:20231217T094656][Readwise org sync]]
-- [[denote:20231006T080643][Beyond customization build tools that grow with us]]
-- [[denote:20231120T123124][denote]]
-- [[denote:20231120T152341][Emacs]]
-#+END:
-
-* Alternatives
-
-** [[https://github.com/rtrppl/orgrr?tab=readme-ov-file][rtrppl/orgrr: Orgrr is a minimalist but complete note-taking system for Emacs. Its intended purpose is the creation and management of a Zettelkasten-like system.]]
-:PROPERTIES:
-:ID:       baf739dc-66bc-4f50-aff4-1ef6a4bccc7e
-:END:
-[2023-11-22 Wed 16:32]
-
-** [[https://github.com/Kinneyzhang/gkroam][Kinneyzhang/gkroam: A lightweight roam replica on top of emacs org-mode.]]
-[2023-11-22 Wed 16:32]
tools/go-org-readwise/internal/org/org.go
@@ -1,38 +0,0 @@
-package org
-
-// Document is a "full" org-mode document, used for a new "readwise
-// document" containing highlights. The "full" notion here being, what
-// I need to sync from readwise to org, not the full representation of
-// a org file.
-type Document struct {
-	Title       string
-	Author      string
-	Email       string
-	Date        string
-	FileTags    []string
-	Identifier  string
-	Category    string
-	URL         string
-	ReadwiseURL string
-	Summary     string
-	Highlights  []Highlight
-}
-
-// PartialDocument is a subset of org-mode used for an update of a
-// "readwise document", thus containing new highlights.
-type PartialDocument struct {
-	Date       string
-	Highlights []Highlight
-}
-
-// Highlight represent a readwise highlight in org-mode.
-type Highlight struct {
-	ID           string
-	URL          string
-	Location     string
-	LocationType string
-	Date         string
-	Note         string
-	Text         string
-	Tags         []string
-}
tools/go-org-readwise/internal/org/sync.go
@@ -1,200 +0,0 @@
-package org
-
-import (
-	"context"
-	"errors"
-	"fmt"
-	"os"
-	"path/filepath"
-	"regexp"
-	"strings"
-	"time"
-
-	"github.com/vdemeester/home/tools/go-org-readwise/internal/readwise"
-)
-
-const (
-	// denote-id-format "%Y%m%dT%H%M%S"
-	denoteDateFormat = "20060102T150405"
-	// org-date-format 2024-06-17 Mon 12:05
-	orgDateFormat = "2006-01-02 Mon 15:04"
-	// punctionation that is removed from file names.
-	denoteExcludedPunctuationRegexpStr = "[][{}!@#$%^&*()=+'\"?,.|;:~`‘’“”/]*"
-)
-
-var (
-	denoteExcludedPunctuationRegexp = regexp.MustCompile(denoteExcludedPunctuationRegexpStr)
-	replaceHypensRegexp             = regexp.MustCompile("[-]+")
-)
-
-func Sync(ctx context.Context, target string, results []readwise.Result) error {
-	for _, result := range results {
-		// FIXME: handle the case where tags where added after
-		// a sync. In that case, we want to try different
-		// titles (without tags, …) ; most likely we want to
-		// use a regexp to "detect" part of the thing.
-		denotefilename := denoteFilename(result)
-		filename := filepath.Join(target, denotefilename)
-		if _, err := os.Stat(filename); err == nil {
-			// Append to the file
-			p := createPartialOrgDocument(result)
-			content, err := convertPartialDocument(p)
-			if err != nil {
-				return err
-			}
-			f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o600)
-			if err != nil {
-				return err
-			}
-			defer f.Close()
-			if _, err = f.WriteString(string(content)); err != nil {
-				return err
-			}
-		} else if errors.Is(err, os.ErrNotExist) {
-			// Create the file
-			d := createNewOrgDocument(result)
-			content, err := convertDocument(d)
-			if err != nil {
-				return err
-			}
-			if err := os.WriteFile(filename, content, 0o644); err != nil {
-				return err
-			}
-		} else {
-			// Schrodinger: file may or may not exist. See err for details.
-			// Therefore, do *NOT* use !os.IsNotExist(err) to test for file existence
-			return err
-		}
-	}
-	return nil
-}
-
-func createNewOrgDocument(r readwise.Result) Document {
-	var filetags []string
-	if len(r.BookTags) > 0 {
-		filetags = make([]string, len(r.BookTags))
-		for i, t := range r.BookTags {
-			filetags[i] = sluggify(t.Name)
-		}
-	}
-	return Document{
-		Title:       r.Title,
-		Author:      r.Author,
-		ReadwiseURL: r.ReadwiseURL,
-		URL:         r.SourceURL,
-		Email:       "", // Figure out how to get the email
-		Date:        r.FirstHighlightDate().Format(orgDateFormat),
-		Identifier:  r.FirstHighlightDate().Format(denoteDateFormat),
-		FileTags:    filetags,
-		Category:    r.Category,
-		Summary:     r.Summary,
-		Highlights:  transformHighlights(r.Highlights),
-	}
-}
-
-func createPartialOrgDocument(r readwise.Result) PartialDocument {
-	now := time.Now()
-	return PartialDocument{
-		Date: now.Format(orgDateFormat),
-		Highlights: transformHighlights(r.Highlights, func(h readwise.Highlight) bool {
-			if h.HighlightedAt.After(now) {
-				return true
-			}
-			return false
-		}),
-	}
-}
-
-func transformHighlights(highlights []readwise.Highlight, filters ...func(readwise.Highlight) bool) []Highlight {
-	orgHighlights := []Highlight{}
-	for _, h := range highlights {
-		skip := false
-		for _, filter := range filters {
-			// If a filter returns false, skip the item
-			if !filter(h) {
-				skip = true
-				break
-			}
-		}
-		if skip {
-			continue
-		}
-		var tags []string
-		if len(h.Tags) > 0 {
-			tags = make([]string, len(h.Tags))
-			for i, t := range h.Tags {
-				tags[i] = sluggify(t.Name)
-			}
-		}
-		orgHighlights = append(orgHighlights, Highlight{
-			ID:   fmt.Sprintf("%d", h.ID),
-			URL:  h.ReadwiseURL,
-			Date: h.HighlightedAt.Format(orgDateFormat),
-			Note: h.Note,
-			Text: h.Text,
-		})
-	}
-	return orgHighlights
-}
-
-// See https://protesilaos.com/emacs/denote#h:4e9c7512-84dc-4dfb-9fa9-e15d51178e5d
-// DATE==SIGNATURE--TITLE__KEYWORDS.EXTENSION
-// Examples:
-// - 20240611T100401--tuesday-11-june-2024__journal.org
-// - 20240511T100401==readwise--foo__bar_baz.org
-func denoteFilename(result readwise.Result) string {
-	var date, signature, title, keywords string
-	// The DATE field represents the date in year-month-day format
-	// followed by the capital letter T (for “time”) and the
-	// current time in hour-minute-second notation. The
-	// presentation is compact: 20220531T091625. The DATE serves
-	// as the unique identifier of each note and, as such, is also
-	// known as the file’s ID or identifier.
-	date = result.FirstHighlightDate().Format(denoteDateFormat)
-
-	// File names can include a string of alphanumeric characters
-	// in the SIGNATURE field. Signatures have no clearly defined
-	// purpose and are up to the user to define. One use-case is
-	// to use them to establish sequential relations between files
-	// (e.g. 1, 1a, 1b, 1b1, 1b2, …).
-	// We use signature to mark files synced from readwise.
-	signature = "==readwise=" + result.Category
-
-	// The TITLE field is the title of the note, as provided by
-	// the user. It automatically gets downcased by default and is
-	// also hyphenated (Sluggification of file name
-	// components). An entry about “Economics in the Euro Area”
-	// produces an economics-in-the-euro-area string for the TITLE
-	// of the file name.
-	title = sluggify(result.Title)
-
-	// The KEYWORDS field consists of one or more entries
-	// demarcated by an underscore (the separator is inserted
-	// automatically). Each keyword is a string provided by the
-	// user at the relevant prompt which broadly describes the
-	// contents of the entry.
-	if len(result.BookTags) > 0 {
-		tags := make([]string, len(result.BookTags))
-		for i, t := range result.BookTags {
-			tags[i] = sluggify(t.Name)
-		}
-		keywords = "__" + strings.Join(tags, "_")
-	}
-
-	return date + strings.ToLower(fmt.Sprintf("%s--%s%s.org", signature, title, keywords))
-}
-
-func sluggify(s string) string {
-	// Remove punctuation
-	s = denoteExcludedPunctuationRegexp.ReplaceAllString(s, "")
-	// Replace spaces with hypens
-	s = strings.ReplaceAll(s, " ", "-")
-	// Replace underscore with hypens
-	s = strings.ReplaceAll(s, "_", "-")
-	// Replace multiple hypens with a single one
-	s = replaceHypensRegexp.ReplaceAllString(s, "-")
-	// Remove any leading and trailing hypen
-	s = strings.TrimPrefix(s, "-")
-	s = strings.TrimSuffix(s, "-")
-	return s
-}
tools/go-org-readwise/internal/org/sync_test.go
@@ -1,34 +0,0 @@
-package org
-
-import "testing"
-
-func TestSluggify(t *testing.T) {
-	testCases := []struct {
-		input    string
-		expected string
-	}{{
-		input:    "",
-		expected: "",
-	}, {
-		input:    "abcde",
-		expected: "abcde",
-	}, {
-		input:    "abcde---",
-		expected: "abcde",
-	}, {
-		input:    "a-b c--de",
-		expected: "a-b-c-de",
-	}, {
-		input:    "a_bc__de",
-		expected: "a-bc-de",
-	}, {
-		input:    "abcde$[)",
-		expected: "abcde",
-	}}
-	for _, tc := range testCases {
-		output := sluggify(tc.input)
-		if output != tc.expected {
-			t.Errorf("input \"%s\": expected %s, got %s", tc.input, tc.expected, output)
-		}
-	}
-}
tools/go-org-readwise/internal/org/write.go
@@ -1,83 +0,0 @@
-package org
-
-import (
-	"bytes"
-	"fmt"
-	"strings"
-	"text/template"
-)
-
-var (
-	additionnalTemplate = `{{ if .Highlights }}* New Highlights on [{{ .Date }}]
-{{ range $h := .Highlights -}}
-** [{{ $h.Date }}] Highlight [[{{ $h.URL }}][{{ $h.ID }}]]{{ if $h.Tags }} {{ orgtags $h.Tags }}{{ end }}
-{{ $h.Text }}
-{{ if $h.Note }}*** Note
-{{ $h.Note }}
-{{ end -}}
-{{ end }}{{ end }}`
-
-	mainTemplate = `#+title: {{ .Title }}
-#+author: {{ .Author }}
-#+date: {{ .Date }}
-#+identifier: {{ .Identifier }}
-#+category: {{ .Category }}
-{{ if .FileTags }}#+filetags: {{ orgtags .FileTags }}{{ end }}
-#+property: READWISE_URL: {{ .ReadwiseURL }}
-{{ if .URL }}#+property: URL: {{ .URL }}{{ end }}
-
-{{ .Summary }}
-
-* Highlights
-{{ range $h := .Highlights -}}
-** [{{ $h.Date }}] Highlight [[{{ $h.URL }}][{{ $h.ID }}]]{{ if $h.Tags }} {{ orgtags $h.Tags }}{{ end }}
-{{ $h.Text }}
-{{ if $h.Note }}*** Note
-{{ $h.Note }}
-{{ end -}}
-{{ end -}}
-`
-)
-
-func orgtags(tags []string) string {
-	if len(tags) == 0 {
-		return ""
-	}
-	return fmt.Sprintf(":%s:", strings.Join(tags, ":"))
-}
-
-func convertDocument(d Document) ([]byte, error) {
-	var err error
-
-	funcMap := template.FuncMap{
-		"orgtags": orgtags,
-	}
-
-	tmpl, err := template.New("org").Funcs(funcMap).Parse(mainTemplate)
-	if err != nil {
-		return []byte{}, err
-	}
-	var buff bytes.Buffer
-	if err := tmpl.Execute(&buff, d); err != nil {
-		return []byte{}, err
-	}
-	return buff.Bytes(), nil
-}
-
-func convertPartialDocument(d PartialDocument) ([]byte, error) {
-	var err error
-
-	funcMap := template.FuncMap{
-		"orgtags": orgtags,
-	}
-
-	tmpl, err := template.New("org").Funcs(funcMap).Parse(additionnalTemplate)
-	if err != nil {
-		return []byte{}, err
-	}
-	var buff bytes.Buffer
-	if err := tmpl.Execute(&buff, d); err != nil {
-		return []byte{}, err
-	}
-	return buff.Bytes(), nil
-}
tools/go-org-readwise/internal/readwise/readwise.go
@@ -1,75 +0,0 @@
-package readwise
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-	"io"
-	"net/http"
-	"strings"
-	"time"
-)
-
-const (
-	exportEndpoint     = "https://readwise.io/api/v2/export/?"
-	FormatUpdatedAfter = "2006-01-02T15:04:05"
-)
-
-func FetchFromAPI(ctx context.Context, apikey string, updateAfter *time.Time) ([]Result, error) {
-	results := []Result{}
-	httpClient := &http.Client{}
-
-	var e Export
-	var err error
-	var nextPageCursor *int = nil
-	for {
-		e, err = fetchExport(ctx, httpClient, apikey, updateAfter, nextPageCursor)
-		if err != nil {
-			return results, err
-		}
-		results = append(results, e.Results...)
-		nextPageCursor = e.NextPageCursor
-		if nextPageCursor == nil {
-			// No more pages to fetch, we get out
-			break
-		}
-	}
-
-	return results, nil
-}
-
-func fetchExport(ctx context.Context, client *http.Client, apikey string, updateAfter *time.Time, nextPageCursor *int) (Export, error) {
-	export := Export{}
-	endpoint := exportEndpoint
-	params := []string{}
-	if updateAfter != nil {
-		params = append(params, "updatedAfter="+updateAfter.Format(FormatUpdatedAfter))
-	}
-	if nextPageCursor != nil {
-		params = append(params, fmt.Sprintf("pageCursor=%d", *nextPageCursor))
-	}
-	endpoint = endpoint + strings.Join(params, "&&")
-	req, err := http.NewRequestWithContext(ctx, "GET", endpoint, nil)
-	if err != nil {
-		return export, err
-	}
-	req.Header.Add("Authorization", "Token "+apikey)
-	resp, err := client.Do(req)
-	if err != nil {
-		return export, err
-	}
-
-	defer resp.Body.Close()
-
-	body, err := io.ReadAll(resp.Body)
-	if err != nil {
-		return export, err
-	}
-
-	err = json.Unmarshal(body, &export)
-	if err != nil {
-		return export, err
-	}
-
-	return export, nil
-}
tools/go-org-readwise/internal/readwise/types.go
@@ -1,57 +0,0 @@
-package readwise
-
-import "time"
-
-type Export struct {
-	Count          int      `json:"count"`
-	NextPageCursor *int     `json:"nextPageCursor"`
-	Results        []Result `json:"results"`
-}
-
-type Result struct {
-	UserBookId    int         `json:"use_book_id"`
-	Title         string      `json:"title"`
-	ReadableTitle string      `json:"readable_title"`
-	CoverImageURL string      `json:"cover_image_url"`
-	Author        string      `json:"author"`
-	UniqueURL     string      `json:"unique_url"`
-	BookTags      []Tag       `json:"book_tags"`
-	Category      string      `json:"category"`
-	DocumentNote  string      `json:"document_note"`
-	Summary       string      `json:"summary"`
-	ReadwiseURL   string      `json:"readwise_url"`
-	Source        string      `json:"source"`
-	SourceURL     string      `json:"source_url"`
-	Highlights    []Highlight `json:"highlights"`
-}
-
-func (r Result) FirstHighlightDate() *time.Time {
-	if len(r.Highlights) == 0 {
-		return nil
-	}
-	var t time.Time
-	for _, h := range r.Highlights {
-		if h.HighlightedAt.After(t) {
-			t = h.HighlightedAt
-		}
-	}
-	return &t
-}
-
-type Highlight struct {
-	Text          string    `json:"text"`
-	ID            int       `json:"id"`
-	Note          string    `json:"note"`
-	ReadwiseURL   string    `json:"readwise_url"`
-	HighlightedAt time.Time `json:"highlighted_at"`
-	BookID        int       `json:"book_id"`
-	URL           string    `json:"url"`
-	Color         string    `json:"color"`
-	Updated       time.Time `json:"updated"`
-	Tags          []Tag     `json:"tags"`
-}
-
-type Tag struct {
-	ID   int    `json:"id"`
-	Name string `json:"name"`
-}
tools/go-org-readwise/.gitignore
@@ -1,1 +0,0 @@
-/go-org-readwise
\ No newline at end of file
tools/go-org-readwise/default.nix
@@ -1,7 +0,0 @@
-{ buildGoModule }:
-
-buildGoModule rec {
-  name = "go-org-readwise";
-  src = ./.;
-  vendorHash = null;
-}
tools/go-org-readwise/go.mod
@@ -1,3 +0,0 @@
-module github.com/vdemeester/home/tools/go-org-readwise
-
-go 1.22
tools/go-org-readwise/go.sum
tools/go-org-readwise/main.go
@@ -1,63 +0,0 @@
-package main
-
-import (
-	"context"
-	"flag"
-	"log"
-	"os"
-	"path/filepath"
-	"time"
-
-	"github.com/vdemeester/home/tools/go-org-readwise/internal/org"
-	"github.com/vdemeester/home/tools/go-org-readwise/internal/readwise"
-)
-
-func main() {
-	apiKeyFile := flag.String("apiKeyFile", "", "File to load the apiKey from. If empty, it will defer to the READWISE_KEY environment variable")
-	targetFolder := flag.String("targetFolder", "", "Folder to write highlights (in org file) into")
-	flag.Parse()
-
-	if *targetFolder == "" {
-		log.Fatal("-targetFolder is a required flag")
-	}
-
-	apiKeyData, err := os.ReadFile(*apiKeyFile)
-	if err != nil && !os.IsNotExist(err) {
-		log.Fatalf("Error reading apiKeyFile %s: %v", *apiKeyFile, err)
-	}
-	apikey := string(apiKeyData)
-	if apikey == "" {
-		apikey = os.Getenv("READWISE_KEY")
-	}
-
-	stateFile := filepath.Join(*targetFolder, ".readwise-sync.state")
-	updateAfter, err := getUpdateAfterFromFile(stateFile)
-	if err != nil {
-		log.Fatalf("Error reading readwise state file from %s: %v", stateFile, err)
-	}
-	ctx := context.Background()
-	results, err := readwise.FetchFromAPI(ctx, apikey, updateAfter)
-	if err != nil {
-		log.Fatalf("Error while fetching results: %v", err)
-	}
-
-	if err := org.Sync(ctx, *targetFolder, results); err != nil {
-		log.Fatalf("Error syncing readwise and org file in %s folder: %v", *targetFolder, err)
-	}
-}
-
-func getUpdateAfterFromFile(stateFile string) (*time.Time, error) {
-	data, err := os.ReadFile(stateFile)
-	if err != nil && !os.IsNotExist(err) {
-		return nil, err
-	}
-	// If the file doesn't exists, do not fail
-	if os.IsNotExist(err) {
-		return nil, nil
-	}
-	t, err := time.Parse(readwise.FormatUpdatedAfter, string(data))
-	if err != nil {
-		return nil, err
-	}
-	return &t, nil
-}
tools/go-org-readwise/README.org
@@ -1,27 +0,0 @@
-#+TITLE: `go-org-readwise`
-
-This is a very very simple project that sync from readwise API to a
-set of org files in a folder. It implements just what is needed from
-the [readwise API](https://readwise.io/api_deets) to work.
-
-* Readwise API
-
-We are /only/ going to implement the export part of the API as, this should be the only one
-we need.
-
-#+begin_quote
-If you want to pull all of the highlights from a user's account into your service (eg
-notetaking apps, backups, etc) this endpoint is all you need!
-#+end_quote
-
-
-* Tasks
-
-** TODO Explore =v3= API
-
-In theory I could rely on the =v3= API to get documents that are "archived" but have no
-highlights. Not sure this is something I want to do though.
-
-I doesn't have highlight so… I would have to query both.
-
-See https://readwise.io/reader_api.
README.org
@@ -151,7 +151,6 @@
 **** Development Tools
 - =bekind= - CLI tool for managing kind (Kubernetes in Docker) clusters with profile support
 - =battery-monitor= - System battery monitoring utility
-- =go-org-readwise= - Integration between Org mode and Readwise
 - =govanityurl= - Go vanity URL service
 - =manifest-tool= - Container manifest tool