๐พ Archived View for source.community โบ ckaznocha โบ cliftons-capsule โบ blob โบ main โบ gemlog.go captured on 2023-07-10 at 13:33:57. Gemini links have been rewritten to link to archived content
โฌ ๏ธ Previous capture (2023-01-29)
โก๏ธ Next capture (2024-02-05)
-=-=-=-=-=-=-
. ,-. ,-. . . ,-. ,-. ,-. ,-. ,-. ,-,-. ,-,-. . . ,-. . |- . . `-. | | | | | | |-' | | | | | | | | | | | | | | | | | `-' `-' `-^ ' `-' `-' :: `-' `-' ' ' ' ' ' ' `-^ ' ' ' `' `-| /| `-'
git clone https://source.community/ckaznocha/cliftons-capsule.git
View raw contents of /gemlog.go (main)
โโโโโฎ 1โ package main 2โ 3โ import ( 4โ "bufio" 5โ "bytes" 6โ "fmt" 7โ "io/fs" 8โ "net/url" 9โ "sort" 10โ "strings" 11โ "sync" 12โ "time" 13โ ) 14โ 15โ type entryMetadata struct { 16โ Filename string 17โ Date time.Time 18โ Title []byte 19โ } 20โ 21โ type entry struct { 22โ Metadata *entryMetadata 23โ Body []byte 24โ } 25โ 26โ type gemlog struct { 27โ gemlogFS fs.FS 28โ entrySet map[string]*entryMetadata 29โ entryList []*entryMetadata 30โ mu sync.RWMutex 31โ } 32โ 33โ func (g *gemlog) list() ([]*entryMetadata, error) { 34โ g.mu.Lock() 35โ defer g.mu.Unlock() 36โ 37โ if err := g.populate(); err != nil { 38โ return nil, err 39โ } 40โ 41โ return g.entryList, nil 42โ } 43โ 44โ func (g *gemlog) entry(path string) (*entry, bool) { 45โ g.mu.RLock() 46โ defer g.mu.RUnlock() 47โ 48โ path, err := url.QueryUnescape(strings.TrimPrefix(path, "/")) 49โ if err != nil { 50โ return nil, false 51โ } 52โ 53โ metadata, ok := g.entrySet[path] 54โ if !ok { 55โ return nil, false 56โ } 57โ 58โ f, err := fs.ReadFile(g.gemlogFS, path) 59โ if err != nil { 60โ return nil, false 61โ } 62โ 63โ return &entry{ 64โ Metadata: metadata, 65โ Body: bytes.TrimSpace(f[bytes.Index(f, []byte{'\n'})+1:]), 66โ }, true 67โ } 68โ 69โ func (g *gemlog) populate() error { 70โ dirInfo, err := fs.ReadDir(g.gemlogFS, "gemlog") 71โ if err != nil { 72โ return fmt.Errorf("cannot read gemlog dir: %w", err) 73โ } 74โ 75โ if len(g.entryList) == len(dirInfo) { 76โ return nil 77โ } 78โ 79โ g.entryList = []*entryMetadata{} 80โ g.entrySet = map[string]*entryMetadata{} 81โ 82โ if err := fs.WalkDir(g.gemlogFS, "gemlog", g.walkFS); err != nil { 83โ return fmt.Errorf("cannot walk gemlog dir: %w", err) 84โ } 85โ 86โ sort.Stable(g) 87โ 88โ return nil 89โ } 90โ 91โ func (g *gemlog) Len() int { return len(g.entryList) } 92โ func (g *gemlog) Swap(i, j int) { g.entryList[i], g.entryList[j] = g.entryList[j], g.entryList[i] } 93โ func (g *gemlog) Less(i, j int) bool { return g.entryList[i].Filename >= g.entryList[j].Filename } 94โ 95โ func (g *gemlog) walkFS(path string, d fs.DirEntry, e error) error { 96โ if e != nil { 97โ return e 98โ } 99โ 100โ if d.IsDir() { 101โ return nil 102โ } 103โ 104โ t, err := time.Parse(time.RFC3339[:10], d.Name()[:10]) 105โ if err != nil { 106โ return fmt.Errorf("unable to parse time stamp: %w", err) 107โ } 108โ 109โ f, err := g.gemlogFS.Open(path) 110โ if err != nil { 111โ return fmt.Errorf("unable to open file: %w", err) 112โ } 113โ 114โ title, err := bufio.NewReader(f).ReadBytes('\n') 115โ if err != nil { 116โ return fmt.Errorf("unable to read title: %w", err) 117โ } 118โ 119โ metadata := &entryMetadata{ 120โ Filename: d.Name(), 121โ Date: t, 122โ Title: bytes.TrimSpace(bytes.TrimPrefix(title, []byte{'#'})), 123โ } 124โ 125โ g.entrySet[path] = metadata 126โ g.entryList = append(g.entryList, metadata) 127โ 128โ return nil 129โ } โโโโโฏ
ยท ยท ยท
ยฉ 2023 source.community