diff --git a/db.go b/db.go index 47c9878..1b1c176 100644 --- a/db.go +++ b/db.go @@ -7,6 +7,7 @@ import ( "time" "github.com/boltdb/bolt" + "github.com/sergi/go-diff/diffmatchpatch" ) var db *bolt.DB @@ -33,11 +34,13 @@ func Close() { // Data for storing in DB type CowyoData struct { - Title string - Text string + Title string + CurrentText string + Diffs []string + Timestamps []string } -func (p *CowyoData) load() error { +func (p *CowyoData) load(title string) error { if !open { return fmt.Errorf("db must be opened before saving!") } @@ -47,9 +50,14 @@ func (p *CowyoData) load() error { if b == nil { return nil } - k := []byte(p.Title) + k := []byte(title) val := b.Get(k) if val == nil { + // make new one + p.Title = title + p.CurrentText = "" + p.Diffs = []string{} + p.Timestamps = []string{} return nil } err = p.decode(val) @@ -65,7 +73,7 @@ func (p *CowyoData) load() error { return nil } -func (p *CowyoData) save() error { +func (p *CowyoData) save(newText string) error { if !open { return fmt.Errorf("db must be opened before saving") } @@ -74,6 +82,13 @@ func (p *CowyoData) save() error { if err != nil { return fmt.Errorf("create bucket: %s", err) } + // find diffs + dmp := diffmatchpatch.New() + diffs := dmp.DiffMain(p.CurrentText, newText, true) + delta := dmp.DiffToDelta(diffs) + p.CurrentText = newText + p.Timestamps = append(p.Timestamps, time.Now().String()) + p.Diffs = append(p.Diffs, delta) enc, err := p.encode() if err != nil { return fmt.Errorf("could not encode CowyoData: %s", err) diff --git a/main.go b/main.go index 2d37ebe..601a256 100644 --- a/main.go +++ b/main.go @@ -55,10 +55,14 @@ Options:`) defer Close() // Default page - p := CowyoData{"about", about_page} - p.save() + p := CowyoData{"about", about_page, []string{}, []string{}} + p.save(about_page) fmt.Println(about_page) + var q CowyoData + q.load("SpikySeaSlug") + rebuildTexts(q) + r := gin.Default() r.LoadHTMLGlob("templates/*") r.GET("/", newNote) diff --git a/routes.go b/routes.go index 51f682d..6b22abf 100644 --- a/routes.go +++ b/routes.go @@ -56,12 +56,12 @@ func serveStaticFile(c *gin.Context, option string) { } func renderMarkdown(c *gin.Context, title string) { - p := CowyoData{strings.ToLower(title), ""} - err := p.load() + var p CowyoData + err := p.load(strings.ToLower(title)) if err != nil { panic(err) } - unsafe := blackfriday.MarkdownCommon([]byte(p.Text)) + unsafe := blackfriday.MarkdownCommon([]byte(p.CurrentText)) html := bluemonday.UGCPolicy().SanitizeBytes(unsafe) html2 := string(html) @@ -126,13 +126,13 @@ func renderList(c *gin.Context, title string) { if strings.ToLower(title) == "about" { //}&& strings.Contains(AllowedIPs, c.ClientIP()) != true { c.Redirect(302, "/about/view") } - p := CowyoData{strings.ToLower(title), ""} - err := p.load() + var p CowyoData + err := p.load(strings.ToLower(title)) if err != nil { panic(err) } - listItems, _ := reorderList(p.Text) + listItems, _ := reorderList(p.CurrentText) c.HTML(http.StatusOK, "list.tmpl", gin.H{ "Title": title, @@ -144,25 +144,25 @@ func deleteListItem(c *gin.Context) { lineNum, err := strconv.Atoi(c.DefaultQuery("lineNum", "None")) title := c.Query("title") // shortcut for c.Request.URL.Query().Get("lastname") if err == nil { - p := CowyoData{strings.ToLower(title), ""} - err := p.load() + var p CowyoData + err := p.load(strings.ToLower(title)) if err != nil { panic(err) } - _, listItems := reorderList(p.Text) - + _, listItems := reorderList(p.CurrentText) + newText := p.CurrentText for i, lineString := range listItems { // fmt.Println(i, lineString, lineNum) if i+1 == lineNum { // fmt.Println("MATCHED") if strings.Contains(lineString, "~~") == false { // fmt.Println(p.Text, "("+lineString[2:]+"\n"+")", "~~"+lineString[2:]+"~~"+"\n") - p.Text = strings.Replace(p.Text+"\n", lineString[2:]+"\n", "~~"+lineString[2:]+"~~"+"\n", 1) + newText = strings.Replace(newText+"\n", lineString[2:]+"\n", "~~"+lineString[2:]+"~~"+"\n", 1) } else { - p.Text = strings.Replace(p.Text+"\n", lineString[2:]+"\n", lineString[4:len(lineString)-2]+"\n", 1) + newText = strings.Replace(newText+"\n", lineString[2:]+"\n", lineString[4:len(lineString)-2]+"\n", 1) } - p.save() + p.save(newText) break } } diff --git a/static/img/gomascot.png b/static/img/gomascot.png new file mode 100755 index 0000000..c5596ca Binary files /dev/null and b/static/img/gomascot.png differ diff --git a/static/img/raspberrypi.png b/static/img/raspberrypi.png new file mode 100755 index 0000000..12c42b7 Binary files /dev/null and b/static/img/raspberrypi.png differ diff --git a/utils.go b/utils.go index df4bd5f..4cadedc 100644 --- a/utils.go +++ b/utils.go @@ -1,9 +1,12 @@ package main import ( + "fmt" "math/rand" "strings" "time" + + "github.com/sergi/go-diff/diffmatchpatch" ) var animals []string @@ -30,7 +33,7 @@ Be cautious about writing sensitive information in the notes as anyone with the Have fun. -**Powered by Raspberry Pi 2** ![jk](http://kodi.tv/wp-content/uploads/DL_Icons_RaspberryPi-new.png)` +**Powered by Raspberry Pi and Go** ![Raspberry Pi](/static/img/raspberrypi.png) ![Go Mascot](/static/img/gomascot.png)` } @@ -70,3 +73,28 @@ func contentType(filename string) string { } var about_page string + +func diffRebuildtexts(diffs []diffmatchpatch.Diff) []string { + text := []string{"", ""} + for _, myDiff := range diffs { + if myDiff.Type != diffmatchpatch.DiffInsert { + text[0] += myDiff.Text + } + if myDiff.Type != diffmatchpatch.DiffDelete { + text[1] += myDiff.Text + } + } + return text +} + +func rebuildTexts(p CowyoData) { + dmp := diffmatchpatch.New() + current := "" + for i, diff := range p.Diffs { + seq1, _ := dmp.DiffFromDelta(current, diff) + texts_linemode := diffRebuildtexts(seq1) + rebuilt := texts_linemode[len(texts_linemode)-1] + fmt.Println(i, p.Timestamps[i], rebuilt) + current = rebuilt + } +} diff --git a/websockets.go b/websockets.go index af7033d..866c369 100644 --- a/websockets.go +++ b/websockets.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "net/http" - "strings" "github.com/gorilla/websocket" ) @@ -40,21 +39,24 @@ func wshandler(w http.ResponseWriter, r *http.Request) { panic(err) } + var p CowyoData + err = p.load(m.Title) + fmt.Println("LOADED") + fmt.Println(p) + if err != nil { + panic(err) + } if m.UpdateServer { - p := CowyoData{strings.ToLower(m.Title), m.TextData} - err := p.save() + err := p.save(m.TextData) + fmt.Println("SAVED") + fmt.Println(p) if err != nil { panic(err) } } if m.UpdateClient { - p := CowyoData{strings.ToLower(m.Title), ""} - err := p.load() - if err != nil { - panic(err) - } - m.UpdateClient = len(m.TextData) != len(p.Text) - m.TextData = p.Text + m.UpdateClient = len(m.TextData) != len(p.CurrentText) + m.TextData = p.CurrentText } newMsg, err := json.Marshal(m) if err != nil {