tagliatelle

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 2bc7f5208cd19650e67c6fb0a35e4819c55564aa
parent a785c24bfe289a232ff0066c8362f044506285b2
Author: breadcat <breadcat@users.noreply.github.com>
Date:   Sun, 19 Apr 2026 14:07:23 +0100

Support !123 for copying all tags from file index 123

Diffstat:
Minclude-viewer.go | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 57 insertions(+), 8 deletions(-)

diff --git a/include-viewer.go b/include-viewer.go @@ -8,6 +8,7 @@ import ( "net" "net/http" "net/url" + "strconv" "strings" ) @@ -66,6 +67,33 @@ func getPreviousFileTags(excludeFileID int) ([]struct{ cat, val string }, error) return tags, nil } +func getFileTagsByID(fileID int) ([]struct{ cat, val string }, error) { + rows, err := db.Query(` + SELECT c.name, t.value + FROM tags t + JOIN categories c ON c.id = t.category_id + JOIN file_tags ft ON ft.tag_id = t.id + WHERE ft.file_id = ? + `, fileID) + if err != nil { + return nil, err + } + defer rows.Close() + + var tags []struct{ cat, val string } + for rows.Next() { + var cat, val string + if err := rows.Scan(&cat, &val); err != nil { + return nil, err + } + tags = append(tags, struct{ cat, val string }{cat, val}) + } + if len(tags) == 0 { + return nil, fmt.Errorf("no tags found on file id %d", fileID) + } + return tags, nil +} + func fileHandler(w http.ResponseWriter, r *http.Request) { idStr := strings.TrimPrefix(r.URL.Path, "/file/") if strings.Contains(idStr, "/") { @@ -116,26 +144,47 @@ func fileHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/file/"+idStr, http.StatusSeeOther) return } + cat := strings.TrimSpace(r.FormValue("category")) val := strings.TrimSpace(r.FormValue("value")) - if cat == "!" { - prevTags, err := getPreviousFileTags(f.ID) - if err != nil { - http.Redirect(w, r, "/file/"+idStr+"?error="+url.QueryEscape("Could not copy tags from previous file: "+err.Error()), http.StatusSeeOther) - return + if cat == "!" || (strings.HasPrefix(cat, "!") && len(cat) > 1) { + var sourceTags []struct{ cat, val string } + var sourceDesc string + + if cat == "!" { + var err error + sourceTags, err = getPreviousFileTags(f.ID) + if err != nil { + http.Redirect(w, r, "/file/"+idStr+"?error="+url.QueryEscape("Could not copy tags from previous file: "+err.Error()), http.StatusSeeOther) + return + } + sourceDesc = "previous file" + } else { + sourceID, err := strconv.Atoi(cat[1:]) + if err != nil { + http.Redirect(w, r, "/file/"+idStr+"?error="+url.QueryEscape("Invalid file ID in category: "+cat), http.StatusSeeOther) + return + } + sourceTags, err = getFileTagsByID(sourceID) + if err != nil { + http.Redirect(w, r, "/file/"+idStr+"?error="+url.QueryEscape(fmt.Sprintf("Could not copy tags from file %d: %s", sourceID, err.Error())), http.StatusSeeOther) + return + } + sourceDesc = fmt.Sprintf("file %d", sourceID) } - for _, tag := range prevTags { + + for _, tag := range sourceTags { _, tagID, err := getOrCreateCategoryAndTag(tag.cat, tag.val) if err != nil { - log.Printf("Error: fileHandler: failed to create tag %s:%s while copying from previous file for file id=%d: %v", tag.cat, tag.val, f.ID, err) + log.Printf("Error: fileHandler: failed to create tag %s:%s while copying from %s for file id=%d: %v", tag.cat, tag.val, sourceDesc, f.ID, err) continue } if _, err = db.Exec("INSERT OR IGNORE INTO file_tags(file_id, tag_id) VALUES (?, ?)", f.ID, tagID); err != nil { log.Printf("Error: fileHandler: failed to add tag %s:%s to file id=%d: %v", tag.cat, tag.val, f.ID, err) } } - http.Redirect(w, r, "/file/"+idStr+"?success="+url.QueryEscape(fmt.Sprintf("Copied %d tag(s) from previous file", len(prevTags))), http.StatusSeeOther) + http.Redirect(w, r, "/file/"+idStr+"?success="+url.QueryEscape(fmt.Sprintf("Copied %d tag(s) from %s", len(sourceTags), sourceDesc)), http.StatusSeeOther) return }