"bytes"
"crypto/rand"
"encoding/binary"
- "log"
+ "io"
+ "slices"
"sort"
- "time"
)
+const defaultNewsDateFormat = "Jan02 15:04" // Jun23 20:49
+
+const defaultNewsTemplate = `From %s (%s):
+
+%s
+
+__________________________________________________________`
+
type ThreadedNews struct {
Categories map[string]NewsCategoryListData15 `yaml:"Categories"`
}
type NewsCategoryListData15 struct {
- Type []byte `yaml:"Type"` //Size 2 ; Bundle (2) or category (3)
+ Type [2]byte `yaml:"Type"` // Size 2 ; Bundle (2) or category (3)
+ Count []byte // Article or SubCategory count Size 2
+ NameSize byte
Name string `yaml:"Name"` //
Articles map[uint32]*NewsArtData `yaml:"Articles"` // Optional, if Type is Category
SubCats map[string]NewsCategoryListData15 `yaml:"SubCats"`
- Count []byte // Article or SubCategory count Size 2
+ GUID []byte // Size 16
AddSN []byte // Size 4
DeleteSN []byte // Size 4
- GUID []byte // Size 16
}
func (newscat *NewsCategoryListData15) GetNewsArtListData() NewsArtListData {
var newsArtsPayload []byte
for i, art := range newscat.Articles {
- ID := make([]byte, 4)
- binary.BigEndian.PutUint32(ID, i)
+ id := make([]byte, 4)
+ binary.BigEndian.PutUint32(id, i)
newArt := NewsArtList{
- ID: ID,
+ ID: id,
TimeStamp: art.Date,
ParentID: art.ParentArt,
Flags: []byte{0, 0, 0, 0},
}
nald := NewsArtListData{
- ID: []byte{0, 0, 0, 0},
+ ID: [4]byte{0, 0, 0, 0},
+ Count: len(newsArts),
Name: []byte{},
Description: []byte{},
NewsArtList: newsArtsPayload,
return nald
}
-// NewsArtData repsents a single news article
+// NewsArtData represents single news article
type NewsArtData struct {
Title string `yaml:"Title"`
Poster string `yaml:"Poster"`
- Date []byte `yaml:"Date"` //size 8
- PrevArt []byte `yaml:"PrevArt"` //size 4
- NextArt []byte `yaml:"NextArt"` //size 4
- ParentArt []byte `yaml:"ParentArt"` //size 4
- FirstChildArt []byte `yaml:"FirstChildArtArt"` //size 4
+ Date []byte `yaml:"Date"` // size 8
+ PrevArt []byte `yaml:"PrevArt"` // size 4
+ NextArt []byte `yaml:"NextArt"` // size 4
+ ParentArt []byte `yaml:"ParentArt"` // size 4
+ FirstChildArt []byte `yaml:"FirstChildArtArt"` // size 4
DataFlav []byte `yaml:"DataFlav"` // "text/plain"
Data string `yaml:"Data"`
}
}
type NewsArtListData struct {
- ID []byte `yaml:"ID"` // Size 4
- Name []byte `yaml:"Name"`
- Description []byte `yaml:"Description"` // not used?
- NewsArtList []byte // List of articles Optional (if article count > 0)
+ ID [4]byte `yaml:"ID"` // Size 4
+ Name []byte `yaml:"Name"`
+ Description []byte `yaml:"Description"` // not used?
+ NewsArtList []byte // List of articles Optional (if article count > 0)
+ Count int
}
-func (nald *NewsArtListData) Payload() []byte {
+func (nald *NewsArtListData) Read(p []byte) (int, error) {
count := make([]byte, 4)
- binary.BigEndian.PutUint32(count, uint32(len(nald.NewsArtList)))
-
- out := append(nald.ID, count...)
- out = append(out, []byte{uint8(len(nald.Name))}...)
- out = append(out, nald.Name...)
- out = append(out, []byte{uint8(len(nald.Description))}...)
- out = append(out, nald.Description...)
- out = append(out, nald.NewsArtList...)
-
- return out
-}
-
-// NewsArtList is a summarized ver sion of a NewArtData record for display in list view
+ binary.BigEndian.PutUint32(count, uint32(nald.Count))
+
+ return copy(
+ p,
+ slices.Concat(
+ nald.ID[:],
+ count,
+ []byte{uint8(len(nald.Name))},
+ nald.Name,
+ []byte{uint8(len(nald.Description))},
+ nald.Description,
+ nald.NewsArtList,
+ ),
+ ),
+ io.EOF
+}
+
+// NewsArtList is a summarized version of a NewArtData record for display in list view
type NewsArtList struct {
ID []byte // Size 4
TimeStamp []byte // Year (2 bytes), milliseconds (2 bytes) and seconds (4 bytes)
// Article size 2
}
-func (newscat *NewsCategoryListData15) Payload() []byte {
+func (newscat *NewsCategoryListData15) MarshalBinary() (data []byte, err error) {
count := make([]byte, 2)
binary.BigEndian.PutUint16(count, uint16(len(newscat.Articles)+len(newscat.SubCats)))
- out := append(newscat.Type, count...)
+ out := append(newscat.Type[:], count...)
- if bytes.Equal(newscat.Type, []byte{0, 3}) {
- // Generate a random GUID
+ if bytes.Equal(newscat.Type[:], []byte{0, 3}) {
+ // Generate a random GUID // TODO: does this need to be random?
b := make([]byte, 16)
_, err := rand.Read(b)
if err != nil {
- log.Fatal(err)
+ return data, err
}
out = append(out, b...) // GUID
out = append(out, newscat.nameLen()...)
out = append(out, []byte(newscat.Name)...)
- return out
-}
-
-// ReadNewsCategoryListData parses a byte slice into a NewsCategoryListData15 struct
-// For use on the client side
-func ReadNewsCategoryListData(payload []byte) NewsCategoryListData15 {
- ncld := NewsCategoryListData15{
- Type: payload[0:2],
- Count: payload[2:4],
- }
-
- if bytes.Equal(ncld.Type, []byte{0, 3}) {
- ncld.GUID = payload[4:20]
- ncld.AddSN = payload[20:24]
- ncld.AddSN = payload[24:28]
- ncld.Name = string(payload[29:])
- } else {
- ncld.Name = string(payload[5:])
- }
-
- return ncld
+ return out, err
}
func (newscat *NewsCategoryListData15) nameLen() []byte {
return []byte{uint8(len(newscat.Name))}
}
-type NewsPath struct {
- Paths []string
-}
-
-func (np *NewsPath) Payload() []byte {
- var out []byte
-
- count := make([]byte, 2)
- binary.BigEndian.PutUint16(count, uint16(len(np.Paths)))
-
- out = append(out, count...)
- for _, p := range np.Paths {
- pLen := byte(len(p))
- out = append(out, []byte{0, 0}...) // what is this?
- out = append(out, pLen)
- out = append(out, []byte(p)...)
- }
-
- return out
-}
-
+// TODO: re-implement as bufio.Scanner interface
func ReadNewsPath(newsPath []byte) []string {
if len(newsPath) == 0 {
return []string{}
}
return cats
}
-
-// News article date field contains this structure:
-// Year 2
-// Milliseconds 2 (seriously?)
-// Seconds 4
-func NewsDate() []byte {
- t := time.Now()
- ms := []byte{0, 0}
- seconds := []byte{0, 0, 0, 0}
-
- year := []byte{0, 0}
- binary.BigEndian.PutUint16(year, uint16(t.Year()))
-
- yearStart := time.Date(t.Year(), time.January, 1, 0, 0, 0, 0, time.Local)
-
- binary.BigEndian.PutUint32(seconds, uint32(t.Sub(yearStart).Seconds()))
-
- date := append(year, ms...)
- date = append(date, seconds...)
-
- return date
-}