~fkfd/sophon

a112781264786fac2d79a3801eeb5e36f4d1cfa2 — Frederick Yin 3 years ago 1f6bb1d
Edit session keeps a log in history files
2 files changed, 140 insertions(+), 1 deletions(-)

A history.go
M wiki.go
A history.go => history.go +122 -0
@@ 0,0 1,122 @@
package main

import (
	"errors"
	"strings"
	"time"
)

type historyEntry struct {
	Action   string
	Part     string
	Time     time.Time
	ClientIP string
	Message  string
	Diff     string
}

func (entry historyEntry) Marshal() string {
	return strings.Join([]string{
		"-----BEGIN ENTRY-----",
		"ACTION: " + entry.Action,
		"PART: " + entry.Part,
		"TIME: " + entry.Time.Format(time.RFC3339),
		"IP: " + entry.ClientIP,
		"MESSAGE: " + entry.Message,
		"-----BEGIN DIFF-----",
		entry.Diff,
		"-----END DIFF-----",
		"-----END ENTRY-----",
	}, "\n") + "\n"
}

type historyChronicle struct {
	Page    string
	Entries []historyEntry
}

func parseHistoryFile(page, hist string) (historyChronicle, error) {
	lines := strings.Split(hist, "\n")
	var chronicle historyChronicle
	var entries []historyEntry
	if !strings.HasPrefix(lines[0], "sophon ") {
		return chronicle, errors.New("Incorrect history file header")
	}
	if lines[0] == "sophon 0.1" {
		// current version
		diffBlock := false // parser is in a diff block
		ent := historyEntry{}
		for n := 1; n < len(lines); n++ {
			ln := lines[n]
			switch true {
			case ln == "-----BEGIN ENTRY-----":
				ent = historyEntry{}
			case ln == "-----END ENTRY-----":
				// we pushed an extra \n
				ent.Diff = ent.Diff[:len(ent.Diff)-1]
				entries = append(entries, ent)
			case strings.HasPrefix(ln, "ACTION: "):
				ent.Action = ln[8:]
			case strings.HasPrefix(ln, "PART: "):
				ent.Part = ln[6:]
			case strings.HasPrefix(ln, "TIME: "):
				t, err := time.Parse(time.RFC3339, ln[6:])
				if err != nil {
					return chronicle, err
				}
				ent.Time = t
			case strings.HasPrefix(ln, "IP: "):
				ent.ClientIP = ln[4:]
			case strings.HasPrefix(ln, "MESSAGE: "):
				ent.Message = ln[9:]
			case ln == "-----BEGIN DIFF-----":
				diffBlock = true
			case ln == "-----END DIFF-----":
				diffBlock = false
			default:
				if diffBlock {
					ent.Diff += ln + "\n"
				}
			}
		}
	}
	chronicle.Page = page
	chronicle.Entries = entries
	return chronicle, nil
}

func (chronicle historyChronicle) Marshal() string {
	// marshal a historyChronicle to a .hist file
	hist := "sophon " + sophonVersion + "\n"
	for n := 0; n < len(chronicle.Entries); n++ {
		entry := chronicle.Entries[n]
		hist += entry.Marshal()
	}
	return hist
}

func (chronicle historyChronicle) GeminiPage() string {
	// generate Gemini page for chronicle
	page := "# History for page " + chronicle.Page + "\n"
	for n := 0; n < len(chronicle.Entries); n++ {
		entry := chronicle.Entries[n]
		page += strings.Join([]string{
			"## " + entry.Message,
			strings.Join([]string{
				entry.ClientIP,
				entry.Action,
				entry.Part,
				"at",
				entry.Time.Format(time.RFC3339),
			}, " "),
			"-----BEGIN DIFF-----",
			entry.Diff,
			"-----END DIFF-----",
		}, "\n")
	}
	return page
}

func (chronicle historyChronicle) Log(entry historyEntry) {
	chronicle.Entries = append(chronicle.Entries, entry)
}

M wiki.go => wiki.go +18 -1
@@ 220,8 220,16 @@ func commitSession(id, msg string) error {
		return err
	}
	title := manifest.PageTitle
	part := manifest.Part
	if part != "meta" {
		part = "section " + part
	}
	diff, err := ioutil.ReadFile("sessions/" + id + "/" + "DIFF")
	if err != nil {
		return err
	}

	sessionPageFilePath := "sessions/" + id + "/" + title + ".gmi"
	// part := manifest.Part

	// generate page preview
	preview, err := previewPage(id)


@@ 238,5 246,14 @@ func commitSession(id, msg string) error {
	if err != nil {
		return err
	}

	// keep history log
	entry := historyEntry{title, part, time.Now(), manifest.ClientIP, msg, string(diff)}
	histFile, err := os.OpenFile("history/"+title+".hist", os.O_APPEND|os.O_WRONLY|os.O_CREATE, filePerm)
	defer histFile.Close()
	_, err = histFile.WriteString(entry.Marshal())
	if err != nil {
		return err
	}
	return nil
}