Basic IDEC proto implementation in Go
This commit is contained in:
parent
44c9c8c4b0
commit
5971ff5530
35
idec/messages.go
Normal file
35
idec/messages.go
Normal file
@ -0,0 +1,35 @@
|
||||
package idec
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Message IDEC message structure
|
||||
type Message struct {
|
||||
From string `json:"from"`
|
||||
To string `json:"to"`
|
||||
Address string `json:"address"`
|
||||
Echo string `json:"echo"`
|
||||
Subg string `json:"subg"`
|
||||
ID string `json:"id"`
|
||||
Timestamp int `json:"timestamp"`
|
||||
Body string `json:"body"`
|
||||
Tags string `json:"tags"`
|
||||
Repto string `json:"repto"`
|
||||
}
|
||||
|
||||
// PrepareMessageForSend Make base64 encoded message
|
||||
func PrepareMessageForSend(m Message) string {
|
||||
var result string
|
||||
|
||||
var rawMessage string
|
||||
if m.Repto != "" {
|
||||
rawMessage = strings.Join([]string{m.Echo, m.To, m.Subg, "", m.Repto, m.Body}, "\n")
|
||||
}
|
||||
rawMessage = strings.Join([]string{m.Echo, m.To, m.Subg, "", m.Body}, "\n")
|
||||
|
||||
result = base64.StdEncoding.EncodeToString([]byte(rawMessage))
|
||||
|
||||
return result
|
||||
}
|
56
idec/parser.go
Normal file
56
idec/parser.go
Normal file
@ -0,0 +1,56 @@
|
||||
package idec
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ParseMessage ...
|
||||
func ParseMessage(message string) (Message, error) {
|
||||
var m Message
|
||||
plainMessage, err := base64.StdEncoding.DecodeString(message)
|
||||
if err != nil {
|
||||
return m, err
|
||||
}
|
||||
|
||||
txtMessage := strings.Split(string(plainMessage), "\n")
|
||||
|
||||
var body string
|
||||
for i := 8; i < len(txtMessage); i++ {
|
||||
body = strings.Join([]string{body, txtMessage[i]}, "\n")
|
||||
}
|
||||
|
||||
ts, err := strconv.Atoi(txtMessage[2])
|
||||
if err != nil {
|
||||
return m, err
|
||||
}
|
||||
m.Tags = txtMessage[0]
|
||||
m.Echo = txtMessage[1]
|
||||
m.Timestamp = ts
|
||||
m.From = txtMessage[3]
|
||||
m.Address = txtMessage[4]
|
||||
m.To = txtMessage[5]
|
||||
m.Subg = txtMessage[6]
|
||||
m.Body = body
|
||||
|
||||
return m, err
|
||||
}
|
||||
|
||||
// ParseEchoList parse /list.txt
|
||||
func ParseEchoList(list string) ([]Echo, error) {
|
||||
var echoes []Echo
|
||||
for _, e := range strings.Split(list, "\n") {
|
||||
desc := strings.Split(e, ":")
|
||||
if len(desc) <= 1 {
|
||||
break
|
||||
}
|
||||
count, err := strconv.Atoi(desc[1])
|
||||
if err != nil {
|
||||
return echoes, err
|
||||
}
|
||||
echoes = append(echoes, Echo{desc[0], count, desc[2]})
|
||||
}
|
||||
|
||||
return echoes, nil
|
||||
}
|
183
idec/proto.go
Normal file
183
idec/proto.go
Normal file
@ -0,0 +1,183 @@
|
||||
package idec
|
||||
|
||||
// Base IDEC protocol implementation
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IDEC Extensions. see: https://ii-net.tk/idec-doc/?p=extensions
|
||||
const (
|
||||
listTXT = "list.txt"
|
||||
blacklistTXT = "blacklist.txt"
|
||||
features = "x/features"
|
||||
xcount = "x/c/"
|
||||
echoSchema = "u/e/"
|
||||
messageSchema = "u/m/"
|
||||
)
|
||||
|
||||
// Extensions IDEC extensions
|
||||
type Extensions struct {
|
||||
ListTXT string `json:"list_txt"`
|
||||
BlacklistTXT string `json:"backlist_txt"`
|
||||
Features string `json:"features"`
|
||||
XCount string `json:"xcount"`
|
||||
}
|
||||
|
||||
// NewExtensions ...
|
||||
func NewExtensions() Extensions {
|
||||
e := Extensions{
|
||||
listTXT,
|
||||
blacklistTXT,
|
||||
features,
|
||||
xcount,
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// FetchConfig node, echo, and other connection settings
|
||||
type FetchConfig struct {
|
||||
Node string `json:"node"`
|
||||
Echoes []string `json:"echo"`
|
||||
Num int `json:"count"`
|
||||
Offset int `json:"offset"`
|
||||
Limit int `json:"limit"`
|
||||
}
|
||||
|
||||
// ID ...
|
||||
type ID struct {
|
||||
Echo string `json:"echo"`
|
||||
MsgID string `json:"msgids"`
|
||||
}
|
||||
|
||||
// GetMessagesIDS get message ids from node
|
||||
func (f FetchConfig) GetMessagesIDS() ([]ID, error) {
|
||||
var ids []ID
|
||||
|
||||
var getURI string
|
||||
getEchoes := strings.Join(f.Echoes, "/")
|
||||
|
||||
// Make strings
|
||||
offset := strconv.Itoa(f.Offset)
|
||||
limit := strconv.Itoa(f.Limit)
|
||||
|
||||
getURI = strings.Join([]string{f.Node, echoSchema, getEchoes, "/", offset, ":", limit}, "")
|
||||
|
||||
// Get messages ids
|
||||
response, err := http.Get(getURI)
|
||||
if err != nil {
|
||||
return ids, err
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
c, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return ids, err
|
||||
}
|
||||
|
||||
var i ID
|
||||
var curEcho string
|
||||
rawIDS := strings.Split(string(c), "\n")
|
||||
for _, line := range rawIDS {
|
||||
|
||||
// Match echoarea
|
||||
if strings.Contains(line, ".") {
|
||||
curEcho = line
|
||||
continue
|
||||
}
|
||||
|
||||
// Match message ID
|
||||
if !strings.Contains(line, ".") && !strings.Contains(line, ":") && line != "" {
|
||||
i.Echo = curEcho
|
||||
i.MsgID = line
|
||||
ids = append(ids, i)
|
||||
}
|
||||
}
|
||||
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
// GetRawMessages get messages from node
|
||||
func (f FetchConfig) GetRawMessages(ids []ID) ([]string, error) {
|
||||
var messages []string
|
||||
|
||||
var messagesIDS []string
|
||||
for _, id := range ids {
|
||||
messagesIDS = append(messagesIDS, id.MsgID)
|
||||
}
|
||||
getMessages := strings.Join(messagesIDS, "/")
|
||||
|
||||
getURI := strings.Join([]string{f.Node, messageSchema, getMessages}, "")
|
||||
|
||||
// Get messages ids
|
||||
response, err := http.Get(getURI)
|
||||
if err != nil {
|
||||
return messages, err
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
c, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return messages, err
|
||||
}
|
||||
|
||||
for _, m := range strings.Split(string(c), "\n") {
|
||||
if len(m) == 0 {
|
||||
break
|
||||
}
|
||||
message := strings.Split(m, ":")
|
||||
if len(message) > 0 {
|
||||
messages = append(messages, message[1])
|
||||
}
|
||||
}
|
||||
|
||||
return messages, err
|
||||
}
|
||||
|
||||
// Echo echo description
|
||||
type Echo struct {
|
||||
Name string `json:"name"`
|
||||
Size int `json:"size"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// GetEchoList ...
|
||||
func (f FetchConfig) GetEchoList() ([]Echo, error) {
|
||||
var echoes []Echo
|
||||
|
||||
// Check node features support
|
||||
fres, err := http.Get(strings.Join([]string{f.Node, features}, "/"))
|
||||
if err != nil {
|
||||
return echoes, err
|
||||
}
|
||||
defer fres.Body.Close()
|
||||
|
||||
c, err := ioutil.ReadAll(fres.Body)
|
||||
if err != nil {
|
||||
return echoes, err
|
||||
}
|
||||
|
||||
if !strings.Contains(string(c), listTXT) {
|
||||
err = errors.New("Node does not support echoes list")
|
||||
return echoes, err
|
||||
}
|
||||
|
||||
lres, err := http.Get(strings.Join([]string{f.Node, listTXT}, "/"))
|
||||
if err != nil {
|
||||
return echoes, err
|
||||
}
|
||||
defer lres.Body.Close()
|
||||
|
||||
l, err := ioutil.ReadAll(lres.Body)
|
||||
if err != nil {
|
||||
return echoes, err
|
||||
}
|
||||
|
||||
echoes, err = ParseEchoList(string(l))
|
||||
|
||||
return echoes, err
|
||||
}
|
Loading…
Reference in New Issue
Block a user