diff options
-rw-r--r-- | message/message.go | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/message/message.go b/message/message.go index 14e9cac..c50310e 100644 --- a/message/message.go +++ b/message/message.go @@ -1,9 +1,15 @@ package message import ( + "context" "crypto/sha256" + "database/sql" + "encoding/json" "fmt" "math/bits" + + ipfs "github.com/ipfs/go-ipfs-api" + pubsub "github.com/libp2p/go-libp2p-pubsub" ) // Messages on Infodump use a "stamp" using the hashcash algorithm to prevent spam and enable storing messages by importance @@ -70,3 +76,82 @@ func New(msg string, n int) *Message { m.ProofOfWork(n) return &m } + +// Datatype Messages that contains a slice of message.Message that is to be stored on IPFS as JSON +type Messages struct { + Messages []message.Message `json:"messages"` +} + +// JSON encodes the Messages struct into a JSON string +func (m *Messages) JSON() string { + json, _ := json.Marshal(m) + return string(json) +} + +// Push the JSON string to IPFS and return the hash +func (m *Messages) Push(ipfs *ipfs.IpfsApi) (string, error) { + hash, err := ipfs.BlockPut(m.JSON()) + return hash, err +} + +// Read the JSON string from IPFS and return the Messages struct +func (m *Messages) Read(ipfs *ipfs.IpfsApi, hash string) error { + json, err := ipfs.BlockGet(hash) + if err != nil { + return err + } + err = json.Unmarshal([]byte(json), &m) + return err +} + +// Save the Messages struct to the database +func (m *Messages) Save(db *sql.DB) error { + stmt, err := db.Prepare("INSERT INTO messages (hash) VALUES (?)") + if err != nil { + return err + } + _, err = stmt.Exec(m.JSON()) + if err != nil { + return err + } + return nil +} + +// Push the Messages struct to IPFS and send the hash to the PubSub topic +func (m *Messages) Publish(ipfs *ipfs.IpfsApi, ps *pubsub.PubSub, topic string) error { + hash, err := m.Push(ipfs) + if err != nil { + return err + } + err = ps.Publish(topic, []byte(hash)) + return err +} + +// ListenAndSave takes an IPFS instance, a PubSub instance, a database and a topic +// Listen on the PubSub topic, look up the hash and read the Messages struct +// On first receipt, save the Messages struct to the database +func ListenAndSave(ipfs *ipfs.IpfsApi, ps *pubsub.PubSub, db *sql.DB, topic string) error { + // Subscribe to the topic + sub, err := ps.Subscribe(topic) + if err != nil { + return err + } + // Listen for messages on the topic + for { + msg, err := sub.Next(context.Background()) + if err != nil { + return err + } + // Read the Messages struct from IPFS + m := Messages{} + err = m.Read(ipfs, string(msg.Data)) + if err != nil { + return err + } + // Save the Messages struct to the database + err = m.Save(db) + if err != nil { + return err + } + } +} |