diff options
| author | Raymaekers Luca <raymaekers.luca@gmail.com> | 2024-09-27 14:37:29 +0200 | 
|---|---|---|
| committer | Raymaekers Luca <raymaekers.luca@gmail.com> | 2024-09-27 14:43:02 +0200 | 
| commit | 5b2097cd2ed016f78ae2c2bcc068dfe3f42e44bd (patch) | |
| tree | ab047ebe3f342570978b487e4ea4d96bc0d0070c | |
| parent | f340f74e1d06aa588dd075f3922505878915da01 (diff) | |
Added datafile for persistent ideas
The data file uses a version number for debugging and is serialized into
a data file, for now this is good enough but because of encapsulating
the data in a struct there is no convenient way of appending to the
Ideas slice.
- Removed the Rating as it is not really constructive.
- Added handling of SIGINT to keep the data even on exit from air of
  Ctrl-c
- Removed example data
- Use log instaed of fmt everywhere
- Removed Makefile
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | Makefile | 8 | ||||
| -rw-r--r-- | ideas.html | 1 | ||||
| -rw-r--r-- | main.go | 125 | 
4 files changed, 83 insertions, 53 deletions
| @@ -1 +1,3 @@  tmp/ +ideez +ideas.data diff --git a/Makefile b/Makefile deleted file mode 100644 index 4c6863a..0000000 --- a/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -VERSION= $(shell git describe --tags)  -LDFLAGS = -X "main.airVersion=$(VVERSION)" - -build:  -	go build -ldflags '$(LDFLAGS)' - -install:  -	go install -ldflags '$(LDFLAGS)' @@ -45,7 +45,6 @@      {{ range .Ideas }}          <div class="idea">              <h2 class="title">{{.Title}}</h2> -            <p class="rating">{{.Rating}}/5</p>              <p class="description">{{.Description}}</p>              <p class="creation">by <span class="author">{{.Author}}</span> on <span class="date">{{.CreatedAt}}</span></p>          </div> @@ -2,14 +2,21 @@ package main  import (  	_ "embed" -	"fmt" +	"encoding/gob"  	"html/template" +	"io"  	"log"  	"net/http" +	"os" +	"os/signal" +	"runtime/debug"  )  // File for persistent storage -const DataFilename = "main.data" +var DataFilename = "ideas.data" + +// Version number used for debugging compatibility with the .data file +var Version string  // layout for how the date should be output in html  var DateLayout string = "02/01/2006 on 15:04" @@ -19,13 +26,15 @@ var DateLayout string = "02/01/2006 on 15:04"  //go:embed ideas.html  var ideas_html string +var data Store +  // ToDo's  // - [ ] Add a post -// - [ ] Serialize data to a  file  // - [ ] Remove a post -// - [x] Change the date format printing  // - [ ] work with funcmaps in templates  // - [ ] Put a reaction on a post +// - [x] Store ideas to a file (encoder/gob) +// - [x] Change the date format printing  // Represents an idea  // CreatedAt is a formatted date string @@ -38,59 +47,87 @@ type Idea struct {  	CreatedAt   string  } -func main() { -	var ideas []Idea +// Data needed through the programm, this data is written to DataFilename for persistent storage +// Is also the format for the Data file +type Store struct { +	Version string +	Ideas   []Idea +} -	// Create a .data file  in the cache directory -	{ -		// data := os.Getenv("XDG_CACHE_HOME") -		// if data == "" { -		// 	data = "." -		// } -		// data = data + "" -		// -		// file, err := os.Create(data + "/" + DataFilename) -		// if err != nil { -		// 	panic(err) -		// } +func GetVersion() string { +	buildinfo, ok := debug.ReadBuildInfo() +	if !ok { +		log.Fatalln("Could not read buildinfo to know package version.")  	} -	// hardcoded data +	return buildinfo.Main.Version +} + +func main() { +	Version = GetVersion() + +	// Create a .data file  in the cache directory and decode eventual ideas from it  	{ -		ideas = []Idea{ -			{ -				Title:       "Better Keylogger", -				Description: "Keylogger which records statistics about your typing.", -				Author:      "Me", -				CreatedAt:   "26/09/2024 on 14:51", -			}, -			{ -				Title:       "music tracker", -				Description: "An app that can track music across multiple music apps such as spotify, apple music, deezer, etc.", -				Author:      "Me", -				CreatedAt:   "24/09/2024 on 14:32", -			}, -			{ -				Title:       "automated hosting", -				Description: "Service to host a website where people can drag&drop their files and they are hosted, it also provides a subdomain automatically.", -				Author:      "Him", -			}, +		p := os.Getenv("XDG_CACHE_HOME") +		// TODO: remove for testing +		p = "" +		if p == "" { +			p = "." +		} +		DataFilename = p + "/" + DataFilename + +		f, err := os.OpenFile(DataFilename, os.O_RDONLY|os.O_CREATE, 0666) +		if err != nil { +			log.Fatalln("Error while opening data file:", err) +		} + +		dec := gob.NewDecoder(f) +		if err := dec.Decode(&data); err != io.EOF && err != nil { +			log.Fatalln("Error while decoding ideas:", err) +		} +		log.Println(data) + +		if data.Version != Version { +			log.Fatalf("Version mismatch for datafile@%s != package@%s\n", data.Version, Version) +		} + +		log.Printf("Imported @%s: %d ideas\n", data.Version, len(data.Ideas)) +		if err := f.Close(); err != nil { +			log.Fatalln("Error while closing file:", err)  		}  	} -	// // Example of parsing a string into time with the layout -	// CreatedAt: func() string { -	// 	t, _ := time.Parse(DateLayout, "24/09/2024 on 14:40") -	// 	return t.Format(DateLayout) -	tmpl, err := template.New("mytemplate").Parse(ideas_html) +	// Handle SIGINT +	// On program exit it should write all its data to the datafile +	// TODO: Instead of recreating the file the new ideas should be appended, a way to achieve this would be that every time a new idea is added it is appended to the file, this way there is no need to ensure this. +	go func() { +		c := make(chan os.Signal, 1) +		signal.Notify(c, os.Interrupt) +		<-c + +		f, err := os.Create(DataFilename) +		if err != nil { +			log.Fatalln(err) +		} +		defer f.Close() + +		enc := gob.NewEncoder(f) +		if err := enc.Encode(data); err != nil { +			log.Fatalln(err) +		} +		log.Println("data saved.") +		os.Exit(0) +	}() + +	tmpl, err := template.New("ideas_html").Parse(ideas_html)  	if err != nil {  		log.Fatalln(err)  	}  	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { -		tmpl.Execute(w, struct{ Ideas []Idea }{ideas}) +		tmpl.Execute(w, data)  	}) -	fmt.Println("Listening on http://localhost:8080") +	log.Println("Listening on http://localhost:8080")  	err = http.ListenAndServe(":8080", nil)  	if err != nil {  		log.Fatalln(err) | 
