~netlandish/links-dev

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch
1

[PATCH links] Fixing bug where tag issues would fail due to stupid use of regexp. Instead we now parse the valid JSON and strip out null entries.

Details
Message ID
<20250614193711.19112-1-peter@netlandish.com>
Sender timestamp
1749908229
DKIM signature
missing
Download raw message
Patch: +57 -61
I don't really remember what lead us to use the regexp pattern to strip
out null entries initially but it was a dumb decision.

Changelog-fixed: No longer using regexp to parse null entries from json
  (no clue wtf we were thinking there)
---
 models/base_url.go   | 13 +++++--------
 models/link_short.go | 24 +++++++++---------------
 models/listing.go    | 34 ++++++++++++----------------------
 models/org_link.go   | 24 ++++++++----------------
 models/utils.go      | 23 +++++++++++++++++++++++
 5 files changed, 57 insertions(+), 61 deletions(-)

diff --git a/models/base_url.go b/models/base_url.go
index affaa04..18c6560 100644
--- a/models/base_url.go
+++ b/models/base_url.go
@@ -8,7 +8,6 @@ import (
	"errors"
	"fmt"
	"net/url"
	"regexp"
	"time"

	sq "github.com/Masterminds/squirrel"
@@ -90,14 +89,12 @@ func GetBaseURLs(ctx context.Context, opts *database.FilterOptions) ([]*BaseURL,
				&url.LastParseAttempt, &url.CreatedOn, &tags); err != nil {
				return err
			}
			re := regexp.MustCompile(`(,\s)?null,?`)
			tags = re.ReplaceAllString(tags, "")
			if tags != "[]" {
				err = json.Unmarshal([]byte(tags), &url.Tags)
				if err != nil {
					return err
				}

			url.Tags, err = BuildSliceFromJSONString[Tag](tags)
			if err != nil {
				return err
			}

			err = url.ToLocalTZ(tz)
			if err != nil {
				return err
diff --git a/models/link_short.go b/models/link_short.go
index cda1a20..31a38b0 100644
--- a/models/link_short.go
+++ b/models/link_short.go
@@ -5,7 +5,6 @@ import (
	"database/sql"
	"encoding/json"
	"fmt"
	"regexp"
	"time"

	sq "github.com/Masterminds/squirrel"
@@ -48,14 +47,11 @@ func GetLinkShorts(ctx context.Context, opts *database.FilterOptions) ([]*LinkSh
				&ls.OrgID, &ls.UserID, &ls.CreatedOn, &ls.UpdatedOn, &ls.LookupName, &tags); err != nil {
				return err
			}
			re := regexp.MustCompile(`(,\s)?null,?`)
			tags = re.ReplaceAllString(tags, "")
			if tags != "[]" {
				err = json.Unmarshal([]byte(tags), &ls.Tags)
				if err != nil {
					return err
				}
			ls.Tags, err = BuildSliceFromJSONString[Tag](tags)
			if err != nil {
				return err
			}

			err = ls.ToLocalTZ(tz)
			if err != nil {
				return err
@@ -263,14 +259,12 @@ func ExportLinkShorts(ctx context.Context, opts *database.FilterOptions) ([]*Exp
			if err = rows.Scan(&ls.ID, &ls.Title, &ls.URL, &ls.ShortCode, &ls.CreatedOn, &tags); err != nil {
				return err
			}
			re := regexp.MustCompile(`(,\s)?null,?`)
			tags = re.ReplaceAllString(tags, "")
			if tags != "[]" {
				err = json.Unmarshal([]byte(tags), &ls.Tags)
				if err != nil {
					return err
				}
			ls.Tags, err = BuildSliceFromJSONString[ExportTag](tags)
			err = json.Unmarshal([]byte(tags), &ls.Tags)
			if err != nil {
				return err
			}

			linkShorts = append(linkShorts, &ls)
		}
		return nil
diff --git a/models/listing.go b/models/listing.go
index fa3c778..7e58ce8 100644
--- a/models/listing.go
+++ b/models/listing.go
@@ -3,9 +3,7 @@ package models
import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"regexp"
	"time"

	sq "github.com/Masterminds/squirrel"
@@ -43,7 +41,6 @@ func GetListings(ctx context.Context, opts *database.FilterOptions) ([]*Listing,
		}
		defer rows.Close()

		re := regexp.MustCompile(`(,\s)?null,?`)
		for rows.Next() {
			var ls Listing
			var tags string
@@ -51,13 +48,12 @@ func GetListings(ctx context.Context, opts *database.FilterOptions) ([]*Listing,
				&ls.UserID, &ls.IsDefault, &ls.IsActive, &ls.CreatedOn, &ls.UpdatedOn, &ls.LookupName, &tags); err != nil {
				return err
			}
			tags = re.ReplaceAllString(tags, "")
			if tags != "[]" {
				err = json.Unmarshal([]byte(tags), &ls.Tags)
				if err != nil {
					return err
				}

			ls.Tags, err = BuildSliceFromJSONString[Tag](tags)
			if err != nil {
				return err
			}

			err = ls.ToLocalTZ(tz)
			if err != nil {
				return err
@@ -249,22 +245,16 @@ func ExportListings(ctx context.Context, opts *database.FilterOptions) ([]*Expor
			if err = rows.Scan(&ls.ID, &ls.Title, &ls.Slug, &ls.CreatedOn, &tags, &links); err != nil {
				return err
			}
			re := regexp.MustCompile(`(,\s)?null,?`)
			links = re.ReplaceAllString(links, "")
			if links != "[]" {
				err = json.Unmarshal([]byte(links), &ls.Links)
				if err != nil {
					return err
				}
			ls.Links, err = BuildSliceFromJSONString[ExportLink](links)
			if err != nil {
				return err
			}

			tags = re.ReplaceAllString(tags, "")
			if tags != "[]" {
				err = json.Unmarshal([]byte(tags), &ls.Tags)
				if err != nil {
					return err
				}
			ls.Tags, err = BuildSliceFromJSONString[ExportTag](tags)
			if err != nil {
				return err
			}

			listings = append(listings, &ls)
		}
		return nil
diff --git a/models/org_link.go b/models/org_link.go
index acf6da1..d46657c 100644
--- a/models/org_link.go
+++ b/models/org_link.go
@@ -3,10 +3,8 @@ package models
import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"net/url"
	"regexp"
	"time"

	sq "github.com/Masterminds/squirrel"
@@ -69,14 +67,11 @@ func GetOrgLinks(ctx context.Context, opts *database.FilterOptions) ([]*OrgLink,
				&o.BaseURLData, &o.BaseURLCounter, &o.BaseURLHash); err != nil {
				return err
			}
			re := regexp.MustCompile(`(,\s)?null,?`)
			tags = re.ReplaceAllString(tags, "")
			if tags != "[]" {
				err = json.Unmarshal([]byte(tags), &o.Tags)
				if err != nil {
					return err
				}
			o.Tags, err = BuildSliceFromJSONString[Tag](tags)
			if err != nil {
				return err
			}

			err = o.ToLocalTZ(tz)
			if err != nil {
				return err
@@ -349,14 +344,11 @@ func ExportOrgLinks(ctx context.Context, opts *database.FilterOptions) ([]*Expor
				&o.Unread, &o.Starred, &o.Hash, &o.CreatedOn, &tags); err != nil {
				return err
			}
			re := regexp.MustCompile(`(,\s)?null,?`)
			tags = re.ReplaceAllString(tags, "")
			if tags != "[]" {
				err = json.Unmarshal([]byte(tags), &o.Tags)
				if err != nil {
					return err
				}
			o.Tags, err = BuildSliceFromJSONString[ExportTag](tags)
			if err != nil {
				return err
			}

			links = append(links, &o)
		}
		return nil
diff --git a/models/utils.go b/models/utils.go
index 0255066..f8d787e 100644
--- a/models/utils.go
+++ b/models/utils.go
@@ -3,6 +3,8 @@ package models
import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	mrand "math/rand"
	"strings"
	"time"
@@ -96,3 +98,24 @@ func ShowLinkCounter(obj any) bool {
		return false
	}
}

// SliceNilRemover will remove any nil values from a given slice
func SliceNilRemover[T any](in []*T) []T {
	out := make([]T, 0, len(in))
	for _, item := range in {
		if item != nil {
			out = append(out, *item)
		}
	}
	return out
}

// BuildSliceFromString will build slice from a json_agg PostgreSQL value.
func BuildSliceFromJSONString[T any](jsonInput string) ([]T, error) {
	var dval []*T
	err := json.Unmarshal([]byte(jsonInput), &dval)
	if err != nil {
		return nil, fmt.Errorf("invalid JSON array: %w", err)
	}
	return SliceNilRemover(dval), nil
}
-- 
2.47.2
Details
Message ID
<DAMIGUAPWLBJ.2QT9XEXY8FDPQ@netlandish.com>
In-Reply-To
<20250614193711.19112-1-peter@netlandish.com> (view parent)
Sender timestamp
1749908553
DKIM signature
missing
Download raw message
Applied.

To git@git.code.netlandish.com:~netlandish/links
   dbf83fe..9ed99a4  master -> master
Reply to thread Export thread (mbox)