Browse Source

Spread command over seperate files

main
Joop Kiefte 5 months ago committed by GitHub
parent
commit
4d42a08a16
  1. 168
      db.go
  2. 32
      ipfs.go
  3. 91
      localmessages.go
  4. 373
      main.go
  5. 66
      sync.go
  6. 56
      tags.go

168
db.go

@ -0,0 +1,168 @@ @@ -0,0 +1,168 @@
package main
import (
"database/sql"
"fmt"
"os"
_ "modernc.org/sqlite"
shell "github.com/ipfs/go-ipfs-api"
"git.kiefte.eu/lapingvino/infodump/message"
)
var DatabasePath = "infodump.db"
var DB *sql.DB
// StartOLNListener starts a PubSub listener that listens for messages from the network
// and adds them to LocalMessages
// For this it uses the IPFS gateway and listens on the topic "OLN", as well as
// the list of followed tags from the database
func StartOLNListener() {
// Get the IPFS gateway
gateway := message.IPFSGateway
// Get the database
db := GetDatabase()
// Get the list of followed tags
followedTags := GetFollowedTags(db)
// Create a new IPFS client
myIPFS := shell.NewShell(gateway)
var subs []*shell.PubSubSubscription
olnsub, err := myIPFS.PubSubSubscribe("OLN")
if err != nil {
fmt.Println(err)
return
}
subs = append(subs, olnsub)
for _, tag := range followedTags {
tagssub, err := myIPFS.PubSubSubscribe("oln-" + tag)
if err != nil {
fmt.Println(err)
} else {
subs = append(subs, tagssub)
}
}
// Start a goroutine for each of the subscriptions in subs,
// read the CID from the Next method, look up the CID on IPFS,
// read this in via message.MessagesFromIPFS and add the message to LocalMessages
for _, sub := range subs {
go func(sub *shell.PubSubSubscription) {
for {
msg, err := sub.Next()
if err != nil {
fmt.Println(err)
return
}
msgs, err := message.MessagesFromIPFS(string(msg.Data))
if err != nil {
fmt.Println(err)
return
}
LocalMessages.AddMany(msgs)
}
}(sub)
}
}
// GetDatabase checks if DB is already set and opened, if not it Sets the database first
func GetDatabase() *sql.DB {
if DB == nil {
fmt.Println("Database not set, setting database...")
SetDatabase()
}
return DB
}
func GetMessagesFromDatabase(db *sql.DB) *message.Messages {
// Get all messages from the database
rows, err := db.Query("SELECT hash, message, nonce, timestamp FROM messages")
if err != nil {
fmt.Println(err)
}
defer rows.Close()
// Create a new Messages object
msgs := message.Messages{}
// Loop through all messages
fmt.Println("Getting messages from database...")
for rows.Next() {
var hash, msg string
var nonce int
var timestamp int64
// Get the values from the database
err := rows.Scan(&hash, &msg, &nonce, &timestamp)
if err != nil {
fmt.Println(err)
}
fmt.Println("Got message from database:", hash)
// Create a new message object
m := message.Message{
Message: msg,
Nonce: nonce,
Timestamp: timestamp,
}
// Add the message to the Messages object
fmt.Println("Adding message to Messages object...")
msgs.Add(&m)
}
return &msgs
}
func InitDatabase(db *sql.DB) {
var err error
// Create the table "messages"
_, err = db.Exec("CREATE TABLE messages(hash TEXT PRIMARY KEY, message TEXT, nonce INTEGER, timestamp INTEGER)")
if err != nil {
fmt.Println(err)
}
// Create the table "followed_tags"
_, err = db.Exec("CREATE TABLE followed_tags(tag TEXT)")
if err != nil {
fmt.Println(err)
}
}
// SetDatabase configures DB to be the database to use
// The name used is DatabasePath, but the user will be asked if this correct or if they want to change it
// If the database is already set, it will ask the user if they want to overwrite it
// If the database is not set, it will ask the user if they want to create it
// If the database is set but it doesn't contain the tables "messages" and "followed_tags",
// it will create them
func SetDatabase() {
// First check if the user is okay with the database path
fmt.Println("Database path: ", DatabasePath)
fmt.Println("Is this correct? (y/n)")
answer := Readline()
if answer == "n" {
fmt.Println("Enter the database path: ")
DatabasePath = Readline()
}
// Open the database
db, err := sql.Open("sqlite", DatabasePath)
if err != nil {
fmt.Println(err)
return
}
// Check if the database is already set
if DB != nil {
fmt.Println("Database already set, overwrite? (y/n)")
answer := Readline()
if answer == "n" {
return
}
}
// Check if the database exists
if _, err := os.Stat(DatabasePath); os.IsNotExist(err) {
fmt.Println("Database does not exist, create? (y/n)")
answer := Readline()
if answer == "n" {
return
}
}
// Set the database
DB = db
// Check if the database contains the tables "messages" and "followed_tags"
// If not, create them
InitDatabase(DB)
}

32
ipfs.go

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
package main
import (
"fmt"
"git.kiefte.eu/lapingvino/infodump/message"
shell "github.com/ipfs/go-ipfs-api"
)
func TestIPFSGateway(gateway string) error {
// Test the IPFS gateway
fmt.Println("Testing IPFS gateway...")
ipfs := shell.NewShell(gateway)
_, err := ipfs.ID()
return err
}
func SetIPFSGateway() {
// Set the IPFS gateway
fmt.Println("Enter the IPFS gateway: ")
var gateway string
fmt.Scanln(&gateway)
// Test the IPFS gateway
err := TestIPFSGateway(gateway)
if err != nil {
fmt.Println(err)
return
} else {
fmt.Println("IPFS gateway set to: ", gateway)
message.IPFSGateway = gateway
}
}

91
localmessages.go

@ -0,0 +1,91 @@ @@ -0,0 +1,91 @@
package main
import (
"fmt"
"time"
"git.kiefte.eu/lapingvino/infodump/message"
)
var LocalMessages = message.Messages{}
var MessageCache string
// ReadMessages shows the messages in LocalMessages sorted by importance, 10 at a time
func ReadMessages() {
// Use LocalMessages to get the messages and get the sorted list of messages
// through the MessageList method
msgs := LocalMessages.MessageList()
// Loop through the messages and print them
for i, m := range msgs {
fmt.Println(m)
if i%10 == 9 {
fmt.Println("Press enter to continue... Type anything to stop")
contp := Readline()
if contp != "" {
return
}
}
}
}
func WriteMessage() {
// Get a message and an urgency from the user.
// The urgency is used to set the strength of the Proof of Work
// If there is a message in the MessageCache, ask the user if they want to use it
// If there is no message in the MessageCache, ask the user to write a message
var m string
if MessageCache != "" {
fmt.Println("You wrote a message before that you didn't send yet. Do you want to use that message?")
fmt.Println("The message is:", MessageCache)
fmt.Println("Type 'yes' to use the message, or anything else to write a new message")
usep := Readline()
if usep == "yes" {
fmt.Println("Using message from cache")
m = MessageCache
} else {
fmt.Println("Writing new message")
m = usep
}
} else {
fmt.Println("Write a message:")
m = Readline()
}
fmt.Println("Enter an urgency (higher is stronger but takes longer to produce): ")
var urgency int
fmt.Scanln(&urgency)
fmt.Println("How many seconds should we wait for the POW to be done? (default is 5): ")
var powtime int
fmt.Scanln(&powtime)
if powtime == 0 {
powtime = 5
}
// Create a new message object
msg, err := message.New(m, urgency, time.Now().Unix(), time.Duration(powtime)*time.Second)
if err != nil {
fmt.Println(err)
fmt.Println("Want to try again with another urgency or timeout? (y/n)")
contp := Readline()
if contp == "y" {
MessageCache = m
WriteMessage()
}
return
}
// MessageCache can be discarded after this point
MessageCache = ""
// Add the message to LocalMessages
LocalMessages.Add(msg)
// Ask if the user wants to write another message or save the messages to the database
fmt.Println("Do you want to write another message? (y/n)")
contp := Readline()
if contp == "y" {
WriteMessage()
} else {
fmt.Println("Do you want to save the messages to the database? (y/n)")
contp := Readline()
if contp == "y" {
SaveMessagesToDatabase()
}
}
}

373
main.go

@ -3,23 +3,14 @@ package main @@ -3,23 +3,14 @@ package main
import (
"bufio"
"database/sql"
"fmt"
"net/url"
"os"
"strings"
"time"
"git.kiefte.eu/lapingvino/infodump/message"
shell "github.com/ipfs/go-ipfs-api"
_ "modernc.org/sqlite"
)
var LocalMessages = message.Messages{}
var DatabasePath = "infodump.db"
var DB *sql.DB
var MessageCache string
// Readline reads from a buffered stdin and returns the line
func Readline() string {
reader := bufio.NewReader(os.Stdin)
@ -112,367 +103,3 @@ func SettingsMenu() { @@ -112,367 +103,3 @@ func SettingsMenu() {
{"Back", func() {}},
})
}
// A menu for the several parts of Sync:
// saving messages to the local database
// reading messages from the local database
// reading messages from the network
// writing messages to the network
func SyncMenu() {
// Present the user with a menu
Menu([]MenuElements{
{"Save Messages to Database", SaveMessagesToDatabase},
{"Read Messages from Database", ReadMessagesFromDatabase},
{"Read Messages from Network", ReadMessagesFromNetwork},
{"Write Messages to Network", WriteMessagesToNetwork},
{"Back", func() {}},
})
}
// StartOLNListener starts a PubSub listener that listens for messages from the network
// and adds them to LocalMessages
// For this it uses the IPFS gateway and listens on the topic "OLN", as well as
// the list of followed tags from the database
func StartOLNListener() {
// Get the IPFS gateway
gateway := message.IPFSGateway
// Get the database
db := GetDatabase()
// Get the list of followed tags
followedTags := GetFollowedTags(db)
// Create a new IPFS client
myIPFS := shell.NewShell(gateway)
var subs []*shell.PubSubSubscription
olnsub, err := myIPFS.PubSubSubscribe("OLN")
if err != nil {
fmt.Println(err)
return
}
subs = append(subs, olnsub)
for _, tag := range followedTags {
tagssub, err := myIPFS.PubSubSubscribe("oln-" + tag)
if err != nil {
fmt.Println(err)
} else {
subs = append(subs, tagssub)
}
}
// Start a goroutine for each of the subscriptions in subs,
// read the CID from the Next method, look up the CID on IPFS,
// read this in via message.MessagesFromIPFS and add the message to LocalMessages
for _, sub := range subs {
go func(sub *shell.PubSubSubscription) {
for {
msg, err := sub.Next()
if err != nil {
fmt.Println(err)
return
}
msgs, err := message.MessagesFromIPFS(string(msg.Data))
if err != nil {
fmt.Println(err)
return
}
LocalMessages.AddMany(msgs)
}
}(sub)
}
}
// GetDatabase checks if DB is already set and opened, if not it Sets the database first
func GetDatabase() *sql.DB {
if DB == nil {
fmt.Println("Database not set, setting database...")
SetDatabase()
}
return DB
}
func GetMessagesFromDatabase(db *sql.DB) *message.Messages {
// Get all messages from the database
rows, err := db.Query("SELECT hash, message, nonce, timestamp FROM messages")
if err != nil {
fmt.Println(err)
}
defer rows.Close()
// Create a new Messages object
msgs := message.Messages{}
// Loop through all messages
fmt.Println("Getting messages from database...")
for rows.Next() {
var hash, msg string
var nonce int
var timestamp int64
// Get the values from the database
err := rows.Scan(&hash, &msg, &nonce, &timestamp)
if err != nil {
fmt.Println(err)
}
fmt.Println("Got message from database:", hash)
// Create a new message object
m := message.Message{
Message: msg,
Nonce: nonce,
Timestamp: timestamp,
}
// Add the message to the Messages object
fmt.Println("Adding message to Messages object...")
msgs.Add(&m)
}
return &msgs
}
// ReadMessages shows the messages in LocalMessages sorted by importance, 10 at a time
func ReadMessages() {
// Use LocalMessages to get the messages and get the sorted list of messages
// through the MessageList method
msgs := LocalMessages.MessageList()
// Loop through the messages and print them
for i, m := range msgs {
fmt.Println(m)
if i%10 == 9 {
fmt.Println("Press enter to continue... Type anything to stop")
contp := Readline()
if contp != "" {
return
}
}
}
}
func WriteMessage() {
// Get a message and an urgency from the user.
// The urgency is used to set the strength of the Proof of Work
// If there is a message in the MessageCache, ask the user if they want to use it
// If there is no message in the MessageCache, ask the user to write a message
var m string
if MessageCache != "" {
fmt.Println("You wrote a message before that you didn't send yet. Do you want to use that message?")
fmt.Println("The message is:", MessageCache)
fmt.Println("Type 'yes' to use the message, or anything else to write a new message")
usep := Readline()
if usep == "yes" {
fmt.Println("Using message from cache")
m = MessageCache
} else {
fmt.Println("Writing new message")
m = usep
}
} else {
fmt.Println("Write a message:")
m = Readline()
}
fmt.Println("Enter an urgency (higher is stronger but takes longer to produce): ")
var urgency int
fmt.Scanln(&urgency)
fmt.Println("How many seconds should we wait for the POW to be done? (default is 5): ")
var powtime int
fmt.Scanln(&powtime)
if powtime == 0 {
powtime = 5
}
// Create a new message object
msg, err := message.New(m, urgency, time.Now().Unix(), time.Duration(powtime)*time.Second)
if err != nil {
fmt.Println(err)
fmt.Println("Want to try again with another urgency or timeout? (y/n)")
contp := Readline()
if contp == "y" {
MessageCache = m
WriteMessage()
}
return
}
// MessageCache can be discarded after this point
MessageCache = ""
// Add the message to LocalMessages
LocalMessages.Add(msg)
// Ask if the user wants to write another message or save the messages to the database
fmt.Println("Do you want to write another message? (y/n)")
contp := Readline()
if contp == "y" {
WriteMessage()
} else {
fmt.Println("Do you want to save the messages to the database? (y/n)")
contp := Readline()
if contp == "y" {
SaveMessagesToDatabase()
}
}
}
// Implementing the Sync Menu options
// SaveMessagesToDatabase, ReadMessagesFromDatabase, ReadMessagesFromNetwork and WriteMessagesToNetwork
// SaveMessagesToDatabase saves the messages in LocalMessages to the database
func SaveMessagesToDatabase() {
// Update the database with the messages in LocalMessages
db := GetDatabase()
// Put the messages in the database
LocalMessages.Each(func(m *message.Message) {
_, err := db.Exec("INSERT INTO messages(hash, message, nonce, timestamp) VALUES(?,?,?,?)", m.Stamp(), m.Message, m.Nonce, m.Timestamp)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Message", m.Stamp(), "saved to database")
}
})
}
// ReadMessagesFromDatabase reads the messages from the database and adds them to LocalMessages
func ReadMessagesFromDatabase() {
// Get the messages from the database
messages := GetMessagesFromDatabase(GetDatabase())
// Add the messages to LocalMessages
LocalMessages.AddMany(messages)
}
// ReadMessagesFromNetwork reads the messages from the IPFS network and adds them to LocalMessages
func ReadMessagesFromNetwork() {
// Get the messages from the IPFS network
// TODO: Implement this
}
// WriteMessagesToNetwork writes the messages in LocalMessages to the IPFS network
func WriteMessagesToNetwork() {
// Add the messages to the IPFS network
cid, err := LocalMessages.AddToIPFS()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Messages synced to IPFS: ", cid)
}
}
func TestIPFSGateway(gateway string) error {
// Test the IPFS gateway
fmt.Println("Testing IPFS gateway...")
ipfs := shell.NewShell(gateway)
_, err := ipfs.ID()
return err
}
func SetIPFSGateway() {
// Set the IPFS gateway
fmt.Println("Enter the IPFS gateway: ")
var gateway string
fmt.Scanln(&gateway)
// Test the IPFS gateway
err := TestIPFSGateway(gateway)
if err != nil {
fmt.Println(err)
return
} else {
fmt.Println("IPFS gateway set to: ", gateway)
message.IPFSGateway = gateway
}
}
func InitDatabase(db *sql.DB) {
var err error
// Create the table "messages"
_, err = db.Exec("CREATE TABLE messages(hash TEXT PRIMARY KEY, message TEXT, nonce INTEGER, timestamp INTEGER)")
if err != nil {
fmt.Println(err)
}
// Create the table "followed_tags"
_, err = db.Exec("CREATE TABLE followed_tags(tag TEXT)")
if err != nil {
fmt.Println(err)
}
}
// SetDatabase configures DB to be the database to use
// The name used is DatabasePath, but the user will be asked if this correct or if they want to change it
// If the database is already set, it will ask the user if they want to overwrite it
// If the database is not set, it will ask the user if they want to create it
// If the database is set but it doesn't contain the tables "messages" and "followed_tags",
// it will create them
func SetDatabase() {
// First check if the user is okay with the database path
fmt.Println("Database path: ", DatabasePath)
fmt.Println("Is this correct? (y/n)")
answer := Readline()
if answer == "n" {
fmt.Println("Enter the database path: ")
DatabasePath = Readline()
}
// Open the database
db, err := sql.Open("sqlite", DatabasePath)
if err != nil {
fmt.Println(err)
return
}
// Check if the database is already set
if DB != nil {
fmt.Println("Database already set, overwrite? (y/n)")
answer := Readline()
if answer == "n" {
return
}
}
// Check if the database exists
if _, err := os.Stat(DatabasePath); os.IsNotExist(err) {
fmt.Println("Database does not exist, create? (y/n)")
answer := Readline()
if answer == "n" {
return
}
}
// Set the database
DB = db
// Check if the database contains the tables "messages" and "followed_tags"
// If not, create them
InitDatabase(DB)
}
func ConfigureFollowedTags() {
db := GetDatabase()
fmt.Println("At the moment you follow the following tags:")
// Get the tags that the user is following
tags := GetFollowedTags(db)
// Show the tags
for _, tag := range tags {
fmt.Print(tag, " ")
}
fmt.Println()
fmt.Println("Enter the tags you want to follow, separated by spaces\nTo remove tags, prefix them with a minus sign: ")
newtags := Readline()
// Split the tags into an array and insert them into database DB
// using table "followed_tags"
tagArray := strings.Split(newtags, " ")
for _, tag := range tagArray {
tag = strings.Trim(tag, " \n")
if !strings.HasPrefix(tag, "-") {
_, err := db.Exec("INSERT INTO followed_tags(tag) VALUES(?)", tag)
if err != nil {
fmt.Println(err)
}
} else {
_, err := db.Exec("DELETE FROM followed_tags WHERE tag=?", tag[1:])
if err != nil {
fmt.Println(err)
}
}
}
}
func GetFollowedTags(db *sql.DB) []string {
// Get the tags from the database
rows, err := db.Query("SELECT tag FROM followed_tags")
if err != nil {
fmt.Println(err)
}
var tags []string
for rows.Next() {
var tag string
err = rows.Scan(&tag)
if err != nil {
fmt.Println(err)
}
tags = append(tags, tag)
}
return tags
}

66
sync.go

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
package main
import (
"fmt"
"git.kiefte.eu/lapingvino/infodump/message"
)
// A menu for the several parts of Sync:
// saving messages to the local database
// reading messages from the local database
// reading messages from the network
// writing messages to the network
func SyncMenu() {
// Present the user with a menu
Menu([]MenuElements{
{"Save Messages to Database", SaveMessagesToDatabase},
{"Read Messages from Database", ReadMessagesFromDatabase},
{"Read Messages from Network", ReadMessagesFromNetwork},
{"Write Messages to Network", WriteMessagesToNetwork},
{"Back", func() {}},
})
}
// Implementing the Sync Menu options
// SaveMessagesToDatabase, ReadMessagesFromDatabase, ReadMessagesFromNetwork and WriteMessagesToNetwork
// SaveMessagesToDatabase saves the messages in LocalMessages to the database
func SaveMessagesToDatabase() {
// Update the database with the messages in LocalMessages
db := GetDatabase()
// Put the messages in the database
LocalMessages.Each(func(m *message.Message) {
_, err := db.Exec("INSERT INTO messages(hash, message, nonce, timestamp) VALUES(?,?,?,?)", m.Stamp(), m.Message, m.Nonce, m.Timestamp)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Message", m.Stamp(), "saved to database")
}
})
}
// ReadMessagesFromDatabase reads the messages from the database and adds them to LocalMessages
func ReadMessagesFromDatabase() {
// Get the messages from the database
messages := GetMessagesFromDatabase(GetDatabase())
// Add the messages to LocalMessages
LocalMessages.AddMany(messages)
}
// ReadMessagesFromNetwork reads the messages from the IPFS network and adds them to LocalMessages
func ReadMessagesFromNetwork() {
// Get the messages from the IPFS network
// TODO: Implement this
}
// WriteMessagesToNetwork writes the messages in LocalMessages to the IPFS network
func WriteMessagesToNetwork() {
// Add the messages to the IPFS network
cid, err := LocalMessages.AddToIPFS()
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Messages synced to IPFS: ", cid)
}
}

56
tags.go

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
package main
import (
"database/sql"
"fmt"
"strings"
)
func ConfigureFollowedTags() {
db := GetDatabase()
fmt.Println("At the moment you follow the following tags:")
// Get the tags that the user is following
tags := GetFollowedTags(db)
// Show the tags
for _, tag := range tags {
fmt.Print(tag, " ")
}
fmt.Println()
fmt.Println("Enter the tags you want to follow, separated by spaces\nTo remove tags, prefix them with a minus sign: ")
newtags := Readline()
// Split the tags into an array and insert them into database DB
// using table "followed_tags"
tagArray := strings.Split(newtags, " ")
for _, tag := range tagArray {
tag = strings.Trim(tag, " \n")
if !strings.HasPrefix(tag, "-") {
_, err := db.Exec("INSERT INTO followed_tags(tag) VALUES(?)", tag)
if err != nil {
fmt.Println(err)
}
} else {
_, err := db.Exec("DELETE FROM followed_tags WHERE tag=?", tag[1:])
if err != nil {
fmt.Println(err)
}
}
}
}
func GetFollowedTags(db *sql.DB) []string {
// Get the tags from the database
rows, err := db.Query("SELECT tag FROM followed_tags")
if err != nil {
fmt.Println(err)
}
var tags []string
for rows.Next() {
var tag string
err = rows.Scan(&tag)
if err != nil {
fmt.Println(err)
}
tags = append(tags, tag)
}
return tags
}
Loading…
Cancel
Save