tagliatelle

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

include-general.go (3683B)


      1 package main
      2 
      3 import (
      4     "log"
      5     "net/http"
      6     "net/url"
      7     "strings"
      8 )
      9 
     10 type TagDisplay struct {
     11 	Value string
     12 	Count int
     13 }
     14 
     15 type ListData struct {
     16 	Tagged      []File
     17 	Untagged    []File
     18 	Breadcrumbs []Breadcrumb
     19 }
     20 
     21 type PageData struct {
     22 	Title          string
     23 	Data           interface{}
     24 	Query          string
     25 	IP             string
     26 	Port           string
     27 	Files          []File
     28 	Tags           map[string][]TagDisplay
     29 	Properties     map[string][]PropertyDisplay
     30 	Breadcrumbs    []Breadcrumb
     31 	Pagination     *Pagination
     32 	GallerySize    string
     33 	UntaggedCount  int
     34 }
     35 
     36 type File struct {
     37 	ID              int
     38 	Filename        string
     39 	EscapedFilename string
     40 	Path            string
     41 	Description     string
     42 	Tags            map[string][]string
     43 }
     44 
     45 func sanitizeFilename(filename string) string {
     46 	if filename == "" {
     47 		return "file"
     48 	}
     49 	filename = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(filename, "/", "_"), "\\", "_"), "..", "_")
     50 	if filename == "" {
     51 		return "file"
     52 	}
     53 	return filename
     54 }
     55 
     56 func renderError(w http.ResponseWriter, message string, statusCode int) {
     57 	http.Error(w, message, statusCode)
     58 }
     59 
     60 func renderTemplate(w http.ResponseWriter, tmplName string, data PageData) {
     61 	if err := tmpl.ExecuteTemplate(w, tmplName, data); err != nil {
     62 		log.Printf("Error: renderTemplate: failed to execute template %s: %v", tmplName, err)
     63 		renderError(w, "Template rendering failed", http.StatusInternalServerError)
     64 	}
     65 }
     66 
     67 func redirectWithWarning(w http.ResponseWriter, r *http.Request, baseURL, warningMsg string) {
     68 	redirectURL := baseURL
     69 	if warningMsg != "" {
     70 		redirectURL += "?warning=" + url.QueryEscape(warningMsg)
     71 	}
     72 	http.Redirect(w, r, redirectURL, http.StatusSeeOther)
     73 }
     74 
     75 func errorString(err error) string {
     76 	if err != nil {
     77 		return err.Error()
     78 	}
     79 	return ""
     80 }
     81 
     82 func successString(err error, msg string) string {
     83 	if err == nil {
     84 		return msg
     85 	}
     86 	return ""
     87 }
     88 
     89 func buildPageData(title string, data interface{}) PageData {
     90 	tagMap, err := getTagData()
     91 	if err != nil {
     92 		log.Printf("Warning: buildPageData: failed to load tag data for page %q: %v", title, err)
     93 	}
     94 	propMap, err := getPropertyNav()
     95 	if err != nil {
     96 		log.Printf("Warning: buildPageData: failed to load property nav for page %q: %v", title, err)
     97 	}
     98 	return PageData{
     99 		Title:            title,
    100 		Data:             data,
    101 		Tags:             tagMap,
    102 		Properties:       propMap,
    103 		GallerySize:      config.GallerySize,
    104 		UntaggedCount: getUntaggedCount(),
    105 	}
    106 }
    107 
    108 func getTagData() (map[string][]TagDisplay, error) {
    109 	rows, err := db.Query(`
    110 		SELECT c.name, t.value, COUNT(ft.file_id)
    111 		FROM tags t
    112 		JOIN categories c ON c.id = t.category_id
    113 		LEFT JOIN file_tags ft ON ft.tag_id = t.id
    114 		GROUP BY t.id
    115 		HAVING COUNT(ft.file_id) > 0
    116 		ORDER BY c.name, t.value`)
    117 	if err != nil {
    118 		return nil, err
    119 	}
    120 	defer rows.Close()
    121 
    122 	tagMap := make(map[string][]TagDisplay)
    123 	for rows.Next() {
    124 		var cat, val string
    125 		var count int
    126 		if err := rows.Scan(&cat, &val, &count); err != nil {
    127 			log.Printf("Warning: getTagData: failed to scan row: %v", err)
    128 			continue
    129 		}
    130 		tagMap[cat] = append(tagMap[cat], TagDisplay{Value: val, Count: count})
    131 	}
    132 	if err := rows.Err(); err != nil {
    133 		return tagMap, err
    134 	}
    135 	return tagMap, nil
    136 }
    137 
    138 func tagsHandler(w http.ResponseWriter, r *http.Request) {
    139 	pageData := buildPageData("All Tags", nil)
    140 	pageData.Data = pageData.Tags
    141 	renderTemplate(w, "tags.html", pageData)
    142 }
    143 
    144 func getUntaggedCount() int {
    145 	var count int
    146 
    147 	err := db.QueryRow(`
    148 		SELECT COUNT(*)
    149 		FROM files f
    150 		LEFT JOIN file_tags ft ON ft.file_id = f.id
    151 		WHERE ft.file_id IS NULL
    152 	`).Scan(&count)
    153 
    154 	if err != nil {
    155 		log.Printf("Warning: getUntaggedCount: %v", err)
    156 		return 0
    157 	}
    158 	return count
    159 }