From 8a5f7eaa09f152cf593cb5bdec369ec9b227b11d Mon Sep 17 00:00:00 2001 From: deranjer Date: Sun, 24 Dec 2017 10:42:12 -0500 Subject: [PATCH] started adding the back to front api via websocket and json --- engine/clientStructs.go | 82 +++++ engine/engine.go | 245 ++++++++++----- engine/engineMaths.go | 105 +++++++ engine/settings.go | 32 ++ main.go | 282 ++++++------------ public/static/images/draghandle.png | Bin 3003 -> 0 bytes public/static/images/iconActiveTorrents.png | Bin 546 -> 0 bytes public/static/images/iconAddTorrent.png | Bin 913 -> 0 bytes public/static/images/iconAddTorrentLink.png | Bin 527 -> 0 bytes public/static/images/iconDelete.png | Bin 794 -> 0 bytes public/static/images/iconDownList.png | Bin 753 -> 0 bytes public/static/images/iconDownload.png | Bin 506 -> 0 bytes public/static/images/iconInactiveTorrents.png | Bin 787 -> 0 bytes public/static/images/iconPause.png | Bin 251 -> 0 bytes public/static/images/iconRSS.png | Bin 850 -> 0 bytes public/static/images/iconScrollDown.png | Bin 565 -> 0 bytes public/static/images/iconScrollUp.png | Bin 579 -> 0 bytes public/static/images/iconSettings.png | Bin 1450 -> 0 bytes public/static/images/iconStart.png | Bin 524 -> 0 bytes public/static/images/iconStop.png | Bin 219 -> 0 bytes public/static/images/iconTorrent.png | Bin 539 -> 0 bytes public/static/images/iconUpList.png | Bin 728 -> 0 bytes public/static/images/iconUpload.png | Bin 470 -> 0 bytes public/static/images/testicon.png | Bin 1014 -> 0 bytes public/static/js/addTorrents.js | 49 --- public/static/js/bundle.js | 105 ++++--- public/static/js/frontend-websocket.go | 74 ----- public/static/js/includes.go | 102 ------- public/static/js/kickwebsocket.js | 9 +- public/static/js/tabControl.js | 13 - public/static/js/websocket.js | 65 ---- settings/settings.go | 2 +- storage/storage.go | 65 +++- .../src/BackendComm/backendWebsocket.js | 79 ++--- torrent-project/src/addTorrentLinkModal.js | 14 +- torrent-project/src/topMenu.js | 16 +- torrent-project/src/torrentlist.js | 3 - 37 files changed, 676 insertions(+), 666 deletions(-) create mode 100644 engine/clientStructs.go create mode 100644 engine/engineMaths.go create mode 100644 engine/settings.go delete mode 100644 public/static/images/draghandle.png delete mode 100644 public/static/images/iconActiveTorrents.png delete mode 100644 public/static/images/iconAddTorrent.png delete mode 100644 public/static/images/iconAddTorrentLink.png delete mode 100644 public/static/images/iconDelete.png delete mode 100644 public/static/images/iconDownList.png delete mode 100644 public/static/images/iconDownload.png delete mode 100644 public/static/images/iconInactiveTorrents.png delete mode 100644 public/static/images/iconPause.png delete mode 100644 public/static/images/iconRSS.png delete mode 100644 public/static/images/iconScrollDown.png delete mode 100644 public/static/images/iconScrollUp.png delete mode 100644 public/static/images/iconSettings.png delete mode 100644 public/static/images/iconStart.png delete mode 100644 public/static/images/iconStop.png delete mode 100644 public/static/images/iconTorrent.png delete mode 100644 public/static/images/iconUpList.png delete mode 100644 public/static/images/iconUpload.png delete mode 100644 public/static/images/testicon.png delete mode 100644 public/static/js/addTorrents.js delete mode 100644 public/static/js/frontend-websocket.go delete mode 100644 public/static/js/includes.go delete mode 100644 public/static/js/tabControl.js delete mode 100644 public/static/js/websocket.js diff --git a/engine/clientStructs.go b/engine/clientStructs.go new file mode 100644 index 00000000..07cbcd52 --- /dev/null +++ b/engine/clientStructs.go @@ -0,0 +1,82 @@ +package engine + +import ( + "encoding/json" + "time" + + "github.com/anacrolix/torrent" + "github.com/anacrolix/torrent/metainfo" +) + +//All the message types are first, first the server handling messages from the client + +//Message contains the JSON messages from the client, we first unmarshal to get the messagetype, then each module unmarshalls the actual message once we know the type +type Message struct { + MessageType string + Payload json.RawMessage +} + +//GenericPayload is for any request to the server that only requires the TorrentHashString for matching (which is a lot of requests) +type GenericPayload struct { + TorrentHashString string +} + +//MagnetMessage contains the magnet link entered by the user under ADD MAGNET link on the top toolbar +type MagnetMessage struct { + MagnetLink string `json:MagnetLink` +} + +//TorrentCommandMessage contains a slice of strings that has the list of torrents to be acted on. +type TorrentCommandMessage struct { + TorrentHashStrings []string +} + +//Next are the messages the server sends to the client + +//TorrentList struct contains the torrent list that is sent to the client +type TorrentList struct { //helps create the JSON structure that react expects to recieve + MessageType string `json:"MessageType"` + Totaltorrents int `json:"total"` + ClientDBstruct []ClientDB `json:"data"` +} + +//TorrentFileList supplies a list of files attached to a single torrent along with some additional information +type TorrentFileList struct { + MessageType string + TotalFiles int `json:"total"` + FileList []torrent.File `json:"fileList"` +} + +//PeerFileList returns a slice of peers +type PeerFileList struct { + MessageType string + TotalPeers int + PeerList []torrent.Peer +} + +//ClientDB struct contains the struct that is used to compose the torrentlist +type ClientDB struct { + TorrentName string `json:"TorrentName"` + DownloadedSize string `json:"DownloadedSize"` + Size string `json:"Size"` + DownloadSpeed string `json:"DownloadSpeed"` + downloadSpeedInt int64 + UploadSpeed string `json:"UploadSpeed"` + //UploadSpeedInt int64 + DataBytesWritten int64 + DataBytesRead int64 + ActivePeers string `json:"ActivePeers"` + TorrentHashString string `json:"TorrentHashString"` + PercentDone string `json:"PercentDone"` + TorrentHash metainfo.Hash + StoragePath string `json:"StorageLocation"` + DateAdded string + KnownSwarm []torrent.Peer + Status string `json:"Status"` + BytesCompleted int64 + UpdatedAt time.Time + AddedAt string + ETA string `json:"ETA"` + Label string + SourceLocation string +} diff --git a/engine/engine.go b/engine/engine.go index 02bf28ed..9db8685e 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -1,104 +1,185 @@ -package engine //main file for all the calculations and data gathering needed for creating the running torrent array +package engine //main file for all the calculations and data gathering needed for creating the running torrent arrays import ( "fmt" + "os" "time" "github.com/anacrolix/torrent" - Main "github.com/deranjer/goTorrent" + "github.com/anacrolix/torrent/metainfo" + "github.com/boltdb/bolt" + Storage "github.com/deranjer/goTorrent/storage" ) -func secondsToMinutes(inSeconds int64) string { - minutes := inSeconds / 60 - seconds := inSeconds % 60 - minutesString := fmt.Sprintf("%d", minutes) - secondsString := fmt.Sprintf("%d", seconds) - str := minutesString + " Min/ " + secondsString + " Sec" - return str +func timeOutInfo(clientTorrent *torrent.Torrent, seconds time.Duration) (deleted bool) { //forcing a timeout of the torrent if it doesn't load + timeout := make(chan bool, 1) //creating a timeout channel for our gotinfo + go func() { + time.Sleep(seconds * time.Second) + timeout <- true + }() + select { + case <-clientTorrent.GotInfo(): //attempting to retrieve info for torrent + fmt.Println("Recieved torrent info for...", clientTorrent.Name()) + clientTorrent.DownloadAll() + return false + case <-timeout: // getting info for torrent has timed out so purging the torrent + fmt.Println("Dropping Torrent") + clientTorrent.Drop() + return true + } + } -func convertSizetoGB(t float32, d float32) (tDelta string, dDelta string) { //converting sizes to MB or GB as needed and adding string - if t > 1024 && d > 1024 { - t := fmt.Sprintf("%.2f", t/1024) - t = t + " GB" - d := fmt.Sprintf("%.2f", d/1024) - d = d + " GB" - return t, d - } else if d > 1024 || t > 1024 { - if d > 1024 { - d := fmt.Sprintf("%.2f", d/1024) - d = d + " GB" - t := fmt.Sprintf("%.2f", t) - t = t + " MB" - return t, d +//StartTorrent creates the storage.db entry and starts the torrent and adds to the running torrent array +func StartTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage *Storage.TorrentLocal, torrentDbStorage *bolt.DB, dataDir string, torrentFile string, torrentFileName string) { + + timeOutInfo(clientTorrent, 45) //seeing if adding the torrrent times out (giving 45 seconds) + var TempHash metainfo.Hash + TempHash = clientTorrent.InfoHash() + fmt.Println(clientTorrent.Info().Source) + torrentLocalStorage.Hash = TempHash.String() // we will store the infohash to add it back later on client restart (if needed) + torrentLocalStorage.DateAdded = time.Now().Format("Jan _2 2006") + torrentLocalStorage.StoragePath = dataDir //TODO check full path information for torrent storage + torrentLocalStorage.TorrentName = clientTorrent.Name() + torrentLocalStorage.TorrentStatus = "downloading" //by default start all the torrents as downloading. + torrentLocalStorage.TorrentType = torrentFile //either "file" or "magnet" maybe more in the future + if torrentFile == "file" { + torrentLocalStorage.TorrentFileName = torrentFileName + } else { + torrentLocalStorage.TorrentFileName = "" + } + fmt.Printf("%+v\n", torrentLocalStorage) + Storage.AddTorrentLocalStorage(torrentDbStorage, torrentLocalStorage) //writing all of the data to the database + clientTorrent.DownloadAll() //starting the download +} + +//CreateRunningTorrentArray creates the entire torrent list to pass to client +func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Storage.TorrentLocal, PreviousTorrentArray []ClientDB, config FullClientSettings, db *bolt.DB) (RunningTorrentArray []ClientDB) { + + for _, element := range TorrentLocalArray { //re-adding all the torrents we had stored from last shutdown or just added via file or magnet link + + var singleTorrent *torrent.Torrent + + if element.TorrentType == "file" { //if it is a file pull it from the uploaded torrent folder + //fmt.Println("Filename", element.TorrentFileName) + if _, err := os.Stat(element.TorrentFileName); err == nil { //if we CAN find the torrent, add it + //fmt.Println("Adding file name...", element.TorrentFileName) + singleTorrent, _ = tclient.AddTorrentFromFile(element.TorrentFileName) + } else { //if we cant find the torrent delete it + fmt.Println("File Error", err) + Storage.DelTorrentLocalStorage(db, element) + continue + } + + } else { + elementMagnet := "magnet:?xt=urn:btih:" + element.Hash //For magnet links just need to prepend the magnet part to the hash to readd + singleTorrent, _ = tclient.AddMagnet(elementMagnet) } - d := fmt.Sprintf("%.2f", d) - d = d + " MB" - t := fmt.Sprintf("%.2f", t/1024) - t = t + " GB" - return t, d - } else { - d := fmt.Sprintf("%.2f", d) - t := fmt.Sprintf("%.2f", t) - t = t + " MB" - d = d + " MB" - return t, d + + timeOut := timeOutInfo(singleTorrent, 45) + if timeOut == true { // if we did timeout then drop the torrent from the boltdb database + Storage.DelTorrentLocalStorage(db, element) //purging torrent from the local database + } + + fullClientDB := new(ClientDB) + fullStruct := singleTorrent.Stats() + + //ranging over the previous torrent array to calculate the speed for each torrent + if len(PreviousTorrentArray) > 0 { //if we actually have a previous array + for _, previousElement := range PreviousTorrentArray { + TempHash := singleTorrent.InfoHash() + if previousElement.TorrentHashString == TempHash.AsString() { //matching previous to new + CalculateTorrentSpeed(singleTorrent, fullClientDB, previousElement) + } + } + } + activePeersString := fmt.Sprintf("%v", fullStruct.ActivePeers) //converting to strings + totalPeersString := fmt.Sprintf("%v", fullStruct.TotalPeers) + bytesCompletedMB := float32(singleTorrent.BytesCompleted() / 1024 / 1024) + totalSizeMB := float32(singleTorrent.Length() / 1024 / 1024) + //downloadSizeString := fmt.Sprintf("%d", bytesCompletedMB) + + tSize, dSize := ConvertSizetoGB(totalSizeMB, bytesCompletedMB) //convert size to GB if needed + var TempHash metainfo.Hash + TempHash = singleTorrent.InfoHash() + + fullClientDB.DownloadedSize = dSize + fullClientDB.Size = tSize + PercentDone := fmt.Sprintf("%.2f", bytesCompletedMB/totalSizeMB) + fullClientDB.TorrentHash = TempHash + fullClientDB.PercentDone = PercentDone + fullClientDB.DataBytesRead = fullStruct.ConnStats.DataBytesRead + fullClientDB.DataBytesWritten = fullStruct.ConnStats.DataBytesWritten + fullClientDB.ActivePeers = activePeersString + " / (" + totalPeersString + ")" + fullClientDB.TorrentHashString = TempHash.AsString() + fullClientDB.StoragePath = element.StoragePath + fullClientDB.TorrentName = element.TorrentName + fullClientDB.DateAdded = element.DateAdded + fullClientDB.BytesCompleted = singleTorrent.BytesCompleted() + CalculateTorrentETA(singleTorrent, fullClientDB) //calculating the ETA for the torrent + //fmt.Println("Download Speed: ", fullClientDB.DownloadSpeed) + //fmt.Println("Percent Done: ", fullClientDB.PercentDone) + //tclient.WriteStatus(os.Stdout) + CalculateTorrentStatus(singleTorrent, fullClientDB) //calculate the status of the torrent, ie downloading seeding etc + + RunningTorrentArray = append(RunningTorrentArray, *fullClientDB) + } + fmt.Println("RunningTorrentArrayCreated...") + return RunningTorrentArray } -func CalculateTorrentSpeed(t *torrent.Torrent, c *Main.ClientDB, oc Main.ClientDB) { - now := time.Now() - bytes := t.BytesCompleted() - bytesUpload := t.Stats().DataBytesWritten - dt := float32(now.Sub(oc.UpdatedAt)) // get the delta time length between now and last updated - db := float32(bytes - oc.BytesCompleted) //getting the delta bytes - rate := db * (float32(time.Second) / dt) // converting into seconds - dbU := float32(bytesUpload - oc.DataBytesWritten) - fmt.Println("BytesWritten", bytesUpload) - fmt.Println("WireBytes", t.Stats().DataBytesWritten) - fmt.Println("ChunksWritten", t.Stats().ChunksWritten) - rateUpload := dbU * (float32(time.Second) / dt) - if rate >= 0 { - rate = rate / 1024 / 1024 //creating integer to calculate ETA - c.DownloadSpeed = fmt.Sprintf("%.2f", rate) - c.DownloadSpeed = c.DownloadSpeed + " MB/s" - c.downloadSpeedInt = int64(rate) +//CreateFileListArray creates a file list for a single torrent that is selected and sent to the server +func CreateFileListArray(tclient *torrent.Client, selectedHash string) TorrentFileList { + runningTorrents := tclient.Torrents() //don't need running torrent array since we aren't adding or deleting from storage + TorrentFileListSelected := TorrentFileList{} + for _, singleTorrent := range runningTorrents { + tempHash := singleTorrent.InfoHash() + if tempHash.AsString() == selectedHash { // if our selection hash equals our torrent hash + TorrentFileListSelected.FileList = singleTorrent.Files() + TorrentFileListSelected.MessageType = "torrentFileList" + TorrentFileListSelected.TotalFiles = len(singleTorrent.Files()) + return TorrentFileListSelected + } + } - if rateUpload >= 0 { - rateUpload = rateUpload / 1024 / 1024 - c.UploadSpeed = fmt.Sprintf("%.2f", rateUpload) - c.UploadSpeed = c.UploadSpeed + " MB/s" - //c.UploadSpeedInt = int64(rateUpload) - } - //c.DownloadSpeed = fmt.Sprintf("%.2f", rate) //setting zero for download speed - //c.DownloadSpeed = c.DownloadSpeed + " MB/s" - c.UpdatedAt = now + return TorrentFileListSelected } -func calculateTorrentETA(t *torrent.Torrent, c *Main.ClientDB) { - missingBytes := t.Length() - t.BytesCompleted() - missingMB := missingBytes / 1024 / 1024 - if missingMB == 0 { - c.ETA = "Done" - } else if c.downloadSpeedInt == 0 { - c.ETA = "N/A" - } else { - ETASeconds := missingMB / c.downloadSpeedInt - str := secondsToMinutes(ETASeconds) //converting seconds to minutes + seconds - c.ETA = str +//CreatePeerListArray create a list of peers for the torrent and displays them +func CreatePeerListArray(tclient *torrent.Client, selectedHash string) PeerFileList { + runningTorrents := tclient.Torrents() + + TorrentPeerList := PeerFileList{} + for _, singleTorrent := range runningTorrents { + tempHash := singleTorrent.InfoHash() + if tempHash.AsString() == selectedHash { + TorrentPeerList.MessageType = "torrentPeerList" + TorrentPeerList.TotalPeers = len(TorrentPeerList.PeerList) + TorrentPeerList.PeerList = singleTorrent.KnownSwarm() + return TorrentPeerList + break //only looking for one result + } } + return TorrentPeerList + } -func calculateTorrentStatus(t *torrent.Torrent, c *Main.ClientDB) { - if t.Seeding() && t.Stats().ActivePeers > 0 && t.BytesMissing() == 0 { - c.Status = "Seeding" - } else if t.Stats().ActivePeers > 0 && t.BytesMissing() > 0 { - c.Status = "Downloading" - } else if t.Stats().ActivePeers == 0 && t.BytesMissing() == 0 { - c.Status = "Completed" - } else if t.Stats().ActivePeers == 0 && t.BytesMissing() > 0 { - c.Status = "Awaiting Peers" - } else { - c.Status = "Unknown" +//CreateTorrentDetailJSON creates the json response for a request for more torrent information +func CreateTorrentDetailJSON(tclient *torrent.Client, selectedHash string, torrentStorage *bolt.DB) ClientDB { + + localTorrentInfo := Storage.FetchTorrentFromStorage(torrentStorage, []byte(selectedHash)) + + runningTorrents := tclient.Torrents() + + TorrentDetailStruct := ClientDB{} + for _, singleTorrent := range runningTorrents { //ranging through the running torrents to find the one we are looking for + tempHash := singleTorrent.InfoHash() + if tempHash.AsString() == selectedHash { + fmt.Println("CreateTorrentDetail", localTorrentInfo) + return TorrentDetailStruct + break //only looking for one result + } } + return TorrentDetailStruct } diff --git a/engine/engineMaths.go b/engine/engineMaths.go new file mode 100644 index 00000000..06759c62 --- /dev/null +++ b/engine/engineMaths.go @@ -0,0 +1,105 @@ +package engine + +import ( + "fmt" + "time" + + "github.com/anacrolix/torrent" +) + +func secondsToMinutes(inSeconds int64) string { + minutes := inSeconds / 60 + seconds := inSeconds % 60 + minutesString := fmt.Sprintf("%d", minutes) + secondsString := fmt.Sprintf("%d", seconds) + str := minutesString + " Min/ " + secondsString + " Sec" + return str +} + +//ConvertSizetoGB changes the sizes +func ConvertSizetoGB(t float32, d float32) (tDelta string, dDelta string) { //converting sizes to MB or GB as needed and adding string + if t > 1024 && d > 1024 { + t := fmt.Sprintf("%.2f", t/1024) + t = t + " GB" + d := fmt.Sprintf("%.2f", d/1024) + d = d + " GB" + return t, d + } else if d > 1024 || t > 1024 { + if d > 1024 { + d := fmt.Sprintf("%.2f", d/1024) + d = d + " GB" + t := fmt.Sprintf("%.2f", t) + t = t + " MB" + return t, d + } + d := fmt.Sprintf("%.2f", d) + d = d + " MB" + t := fmt.Sprintf("%.2f", t/1024) + t = t + " GB" + return t, d + } else { + d := fmt.Sprintf("%.2f", d) + t := fmt.Sprintf("%.2f", t) + t = t + " MB" + d = d + " MB" + return t, d + } +} + +//CalculateTorrentSpeed is used to calculate the torrent upload and download speed over time +func CalculateTorrentSpeed(t *torrent.Torrent, c *ClientDB, oc ClientDB) { + now := time.Now() + bytes := t.BytesCompleted() + bytesUpload := t.Stats().DataBytesWritten + dt := float32(now.Sub(oc.UpdatedAt)) // get the delta time length between now and last updated + db := float32(bytes - oc.BytesCompleted) //getting the delta bytes + rate := db * (float32(time.Second) / dt) // converting into seconds + dbU := float32(bytesUpload - oc.DataBytesWritten) + //fmt.Println("BytesWritten", bytesUpload) + //fmt.Println("WireBytes", t.Stats().DataBytesWritten) + //fmt.Println("ChunksWritten", t.Stats().ChunksWritten) + rateUpload := dbU * (float32(time.Second) / dt) + if rate >= 0 { + rate = rate / 1024 / 1024 //creating integer to calculate ETA + c.DownloadSpeed = fmt.Sprintf("%.2f", rate) + c.DownloadSpeed = c.DownloadSpeed + " MB/s" + c.downloadSpeedInt = int64(rate) + } + if rateUpload >= 0 { + rateUpload = rateUpload / 1024 / 1024 + c.UploadSpeed = fmt.Sprintf("%.2f", rateUpload) + c.UploadSpeed = c.UploadSpeed + " MB/s" + + } + c.UpdatedAt = now +} + +//CalculateTorrentETA is used to estimate the remaining dl time of the torrent based on the speed that the MB are being downloaded +func CalculateTorrentETA(t *torrent.Torrent, c *ClientDB) { + missingBytes := t.Length() - t.BytesCompleted() + missingMB := missingBytes / 1024 / 1024 + if missingMB == 0 { + c.ETA = "Done" + } else if c.downloadSpeedInt == 0 { + c.ETA = "N/A" + } else { + ETASeconds := missingMB / c.downloadSpeedInt + str := secondsToMinutes(ETASeconds) //converting seconds to minutes + seconds + c.ETA = str + } +} + +//CalculateTorrentStatus is used to determine what the STATUS column of the frontend will display ll2 +func CalculateTorrentStatus(t *torrent.Torrent, c *ClientDB) { + if t.Seeding() && t.Stats().ActivePeers > 0 && t.BytesMissing() == 0 { + c.Status = "Seeding" + } else if t.Stats().ActivePeers > 0 && t.BytesMissing() > 0 { + c.Status = "Downloading" + } else if t.Stats().ActivePeers == 0 && t.BytesMissing() == 0 { + c.Status = "Completed" + } else if t.Stats().ActivePeers == 0 && t.BytesMissing() > 0 { + c.Status = "Awaiting Peers" + } else { + c.Status = "Unknown" + } +} diff --git a/engine/settings.go b/engine/settings.go new file mode 100644 index 00000000..6027b189 --- /dev/null +++ b/engine/settings.go @@ -0,0 +1,32 @@ +package engine //Settings.go contains all of the program settings + +import ( + "github.com/anacrolix/dht" + "github.com/anacrolix/torrent" +) + +//FullCLientSettings struct is a struct that can be read into anacrolix/torrent to setup a torrent client +type FullClientSettings struct { + Version int + torrent.Config + TFileUploadFolder string +} + +//FullClientSettingsNew creates a new torrent client config TODO read from a TOML file +func FullClientSettingsNew() FullClientSettings { + //Config := fullClientSettings //generate a new struct + + var Config FullClientSettings + + Config.Version = 1.0 + Config.DataDir = "downloads" //the full OR relative path of the default download directory for torrents + Config.TFileUploadFolder = "uploadedTorrents" + Config.Seed = true + + Config.DHTConfig = dht.ServerConfig{ + StartingNodes: dht.GlobalBootstrapAddrs, + } + + return Config + +} diff --git a/main.go b/main.go index 4cabf7e9..9ef1ef23 100644 --- a/main.go +++ b/main.go @@ -10,17 +10,13 @@ import ( "net/http" "os" "path/filepath" - "strings" - "time" "github.com/anacrolix/torrent" "github.com/gorilla/mux" "github.com/gorilla/websocket" - "github.com/anacrolix/torrent/metainfo" "github.com/boltdb/bolt" Engine "github.com/deranjer/goTorrent/engine" - Settings "github.com/deranjer/goTorrent/settings" Storage "github.com/deranjer/goTorrent/storage" ) @@ -37,160 +33,18 @@ var upgrader = websocket.Upgrader{ WriteBufferSize: 1024, } -type torrentList struct { //helps create the JSON structure that react expects to recieve - Totaltorrents int `json:"total"` - ClientDBstruct []ClientDB `json:"data"` -} - -type ClientDB struct { - TorrentName string `json:"TorrentName"` - DownloadedSize string `json:"DownloadedSize"` - Size string `json:"Size"` - DownloadSpeed string `json:"DownloadSpeed"` - downloadSpeedInt int64 - UploadSpeed string `json:"UploadSpeed"` - //UploadSpeedInt int64 - DataBytesWritten int64 - DataBytesRead int64 - ActivePeers string `json:"ActivePeers"` - TorrentHashString string `json:"TorrentHashString"` - PercentDone string `json:"PercentDone"` - TorrentHash metainfo.Hash - StoragePath string `json:"StorageLocation"` - DateAdded string - KnownSwarm []torrent.Peer - Status string `json:"Status"` - BytesCompleted int64 - UpdatedAt time.Time - ETA string `json:"ETA"` -} - func serveHome(w http.ResponseWriter, r *http.Request) { s1, _ := template.ParseFiles("templates/home.tmpl") s1.ExecuteTemplate(w, "base", map[string]string{"APP_ID": APP_ID}) } -func timeOutInfo(clientTorrent *torrent.Torrent, seconds time.Duration) (deleted bool) { //forcing a timeout of the - timeout := make(chan bool, 1) //creating a timeout channel for our gotinfo - go func() { - time.Sleep(seconds * time.Second) - timeout <- true - }() - select { - case <-clientTorrent.GotInfo(): //attempting to retrieve info for torrent - fmt.Println("Recieved torrent info..") - clientTorrent.DownloadAll() - return false - case <-timeout: // getting info for torrent has timed out so purging the torrent - fmt.Println("Dropping Torrent") - clientTorrent.Drop() - return true - } - -} - -func startTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage *Storage.TorrentLocal, torrentDbStorage *bolt.DB, dataDir string, torrentFile string, torrentFileName string) { - - timeOutInfo(clientTorrent, 45) //seeing if adding the torrrent times out (giving 45 seconds) - var TempHash metainfo.Hash - TempHash = clientTorrent.InfoHash() - fmt.Println(clientTorrent.Info().Source) - torrentLocalStorage.Hash = TempHash.String() // we will store the infohash to add it back later on client restart (if needed) - torrentLocalStorage.DateAdded = time.Now().Format("Jan _2 2006") - torrentLocalStorage.StoragePath = dataDir //TODO check full path information for torrent storage - torrentLocalStorage.TorrentName = clientTorrent.Name() - torrentLocalStorage.TorrentStatus = "downloading" //by default start all the torrents as downloading. - torrentLocalStorage.TorrentType = torrentFile //either "file" or "magnet" maybe more in the future - if torrentFile == "file" { - torrentLocalStorage.TorrentFileName = torrentFileName - } else { - torrentLocalStorage.TorrentFileName = "" - } - fmt.Printf("%+v\n", torrentLocalStorage) - Storage.AddTorrentLocalStorage(torrentDbStorage, torrentLocalStorage) //writing all of the data to the database - clientTorrent.DownloadAll() //starting the download -} - -func createRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Storage.TorrentLocal, PreviousTorrentArray []clientDB, config Settings.FullClientSettings, db *bolt.DB) (RunningTorrentArray []clientDB) { - for _, element := range TorrentLocalArray { //re-adding all the torrents we had stored from last shutdown - - var singleTorrent *torrent.Torrent - - if element.TorrentType == "file" { //if it is a file pull it from the uploaded torrent folder - //fmt.Println("Filename", element.TorrentFileName) - if _, err := os.Stat(element.TorrentFileName); err == nil { //if we CAN find the torrent, add it - //fmt.Println("Adding file name...", element.TorrentFileName) - singleTorrent, _ = tclient.AddTorrentFromFile(element.TorrentFileName) - } else { //if we cant find the torrent delete it - fmt.Println("File Error", err) - Storage.DelTorrentLocalStorage(db, element) - continue - } - - } else { - elementMagnet := "magnet:?xt=urn:btih:" + element.Hash //For magnet links just need to prepend the magnet part to the hash to readd - singleTorrent, _ = tclient.AddMagnet(elementMagnet) - } - - timeOut := timeOutInfo(singleTorrent, 45) - if timeOut == true { // if we did timeout then drop the torrent from the boltdb database - Storage.DelTorrentLocalStorage(db, element) //purging torrent from the local database - } - - fullClientDB := new(ClientDB) - fullStruct := singleTorrent.Stats() - - //ranging over the previous torrent array to calculate the speed for each torrent - if len(PreviousTorrentArray) > 0 { //if we actually have a previous array - for _, previousElement := range PreviousTorrentArray { - TempHash := singleTorrent.InfoHash() - if previousElement.TorrentHashString == TempHash.AsString() { //matching previous to new - Engine.CalculateTorrentSpeed(singleTorrent, fullClientDB, previousElement) - } - } - } - activePeersString := fmt.Sprintf("%v", fullStruct.ActivePeers) //converting to strings - totalPeersString := fmt.Sprintf("%v", fullStruct.TotalPeers) - bytesCompletedMB := float32(singleTorrent.BytesCompleted() / 1024 / 1024) - totalSizeMB := float32(singleTorrent.Length() / 1024 / 1024) - //downloadSizeString := fmt.Sprintf("%d", bytesCompletedMB) - - tSize, dSize := convertSizetoGB(totalSizeMB, bytesCompletedMB) //convert size to GB if needed - var TempHash metainfo.Hash - TempHash = singleTorrent.InfoHash() - - fullClientDB.DownloadedSize = dSize - fullClientDB.Size = tSize - PercentDone := fmt.Sprintf("%.2f", bytesCompletedMB/totalSizeMB) - fullClientDB.TorrentHash = TempHash - fullClientDB.PercentDone = PercentDone - fullClientDB.DataBytesRead = fullStruct.ConnStats.DataBytesRead - fullClientDB.DataBytesWritten = fullStruct.ConnStats.DataBytesWritten - fullClientDB.ActivePeers = activePeersString + " / (" + totalPeersString + ")" - fullClientDB.TorrentHashString = TempHash.AsString() - fullClientDB.StoragePath = element.StoragePath - fullClientDB.TorrentName = element.TorrentName - fullClientDB.DateAdded = element.DateAdded - fullClientDB.BytesCompleted = singleTorrent.BytesCompleted() - calculateTorrentETA(singleTorrent, fullClientDB) //calculating the ETA for the torrent - //fmt.Println("Download Speed: ", fullClientDB.DownloadSpeed) - //fmt.Println("Percent Done: ", fullClientDB.PercentDone) - //tclient.WriteStatus(os.Stdout) - calculateTorrentStatus(singleTorrent, fullClientDB) //calculate the status of the torrent, ie downloading seeding etc - - RunningTorrentArray = append(RunningTorrentArray, *fullClientDB) - - } - return RunningTorrentArray -} - -func updateClient(torrentstats []clientDB, conn *websocket.Conn) { //get the torrent client and the websocket connection to write msg +func updateClient(torrentstats []Engine.ClientDB, conn *websocket.Conn) { //get the torrent client and the websocket connection to write msg conn.WriteJSON(torrentstats) //converting to JSON and writing to the client } func main() { //setting up the torrent client - Config := Settings.FullClientSettingsNew() //grabbing from settings.go + Config := Engine.FullClientSettingsNew() //grabbing from settings.go os.Mkdir(Config.TFileUploadFolder, os.ModeDir) //creating a directory to store uploaded torrent files torrentLocalStorage := new(Storage.TorrentLocal) //creating a new struct that stores all of our local storage info @@ -208,13 +62,13 @@ func main() { defer db.Close() //defering closing the database until the program closes var TorrentLocalArray = []*Storage.TorrentLocal{} //this is an array of ALL of the local storage torrents, they will be added back in via hash - var RunningTorrentArray = []clientDB{} //this stores ALL of the torrents that are running, used for client update pushes combines Local Storage and Running tclient info - var PreviousTorrentArray = []clientDB{} + var RunningTorrentArray = []Engine.ClientDB{} //this stores ALL of the torrents that are running, used for client update pushes combines Local Storage and Running tclient info + var PreviousTorrentArray = []Engine.ClientDB{} TorrentLocalArray = Storage.ReadInTorrents(db) //pulling in all the already added torrents if TorrentLocalArray != nil { //the first creation of the running torrent array - RunningTorrentArray = createRunningTorrentArray(tclient, TorrentLocalArray, PreviousTorrentArray, Config, db) //Updates the RunningTorrentArray with the current client data as well + RunningTorrentArray = Engine.CreateRunningTorrentArray(tclient, TorrentLocalArray, PreviousTorrentArray, Config, db) //Updates the RunningTorrentArray with the current client data as well } else { fmt.Println("Database is empty!") @@ -224,12 +78,14 @@ func main() { router.HandleFunc("/", serveHome) //Serving the main page for our SPA http.Handle("/static/", http.FileServer(http.Dir("public"))) http.Handle("/", router) - http.HandleFunc("/uploadTorrent", func(w http.ResponseWriter, r *http.Request) { //grabbing the uploaded Torrent File and adding it to the client - defer http.Redirect(w, r, "/", 301) + http.HandleFunc("/uploadTorrent", func(w http.ResponseWriter, r *http.Request) { //grabbing the uploaded Torrent File and adding it to the client TODO figure out websocket + defer http.Redirect(w, r, "/", 301) //forcing redirect to home page after file is processed file, header, err := r.FormFile("fileTest") if err != nil { fmt.Println("Error with fetching file or request issue", file) } + //torrentFileBytes, err := ioutil.ReadAll(file) TODO dump a byte slice directly into the filename + defer file.Close() //defer closing the file until we are done manipulating it var filePath = filepath.Join(Config.TFileUploadFolder, header.Filename) //creating a full filepath to store the .torrent files fileName, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666) //generating the fileName @@ -242,15 +98,16 @@ func main() { fmt.Println("Error adding Torrent from file: ", fileName.Name()) } else { fmt.Println("Adding Torrent via file", fileName) - startTorrent(clientTorrent, torrentLocalStorage, db, Config.DataDir, "file", fileName.Name()) + Engine.StartTorrent(clientTorrent, torrentLocalStorage, db, Config.DataDir, "file", fileName.Name()) } }) http.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) { //exposing the data to the TorrentLocalArray = Storage.ReadInTorrents(db) - RunningTorrentArray = createRunningTorrentArray(tclient, TorrentLocalArray, PreviousTorrentArray, Config, db) //Updates the RunningTorrentArray with the current client data as well - var torrentlistArray = new(torrentList) //the full JSON that includes the number of torrents as the root - torrentlistArray.ClientDBstruct = RunningTorrentArray + RunningTorrentArray = Engine.CreateRunningTorrentArray(tclient, TorrentLocalArray, PreviousTorrentArray, Config, db) //Updates the RunningTorrentArray with the current client data as well + var torrentlistArray = new(Engine.TorrentList) + torrentlistArray.MessageType = "torrentList" //setting the type of message + torrentlistArray.ClientDBstruct = RunningTorrentArray //the full JSON that includes the number of torrents as the root torrentlistArray.Totaltorrents = len(RunningTorrentArray) torrentlistArrayJSON, _ := json.Marshal(torrentlistArray) w.Header().Set("Content-Type", "application/json") @@ -261,60 +118,113 @@ func main() { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { - log.Println(err) + log.Println("Generic websocket error", err) return } - for { - msgType, msg, err := conn.ReadMessage() - if err != nil { - fmt.Println("Read Message Error", err) - return + runningTorrents := tclient.Torrents() //getting running torrents here since multiple cases ask for the running torrents + msg := Engine.Message{} + readJSONError := conn.ReadJSON(&msg) + if readJSONError != nil { + fmt.Println("Unable to read JSON client message", err) } - if string(msg) == "clientUpdateRequest" { //6 second update ping - fmt.Println("client Requested Update") - //time.Sleep(6 * time.Second) - err = conn.WriteMessage(msgType, []byte("clientUpdate")) - if err != nil { - fmt.Println("Websocket Write err", err) - return - } + fmt.Println("MessageType", msg.MessageType) + switch msg.MessageType { //first handling data requests + + case "torrentListRequest": + fmt.Println("client Requested TorrentList Update") TorrentLocalArray = Storage.ReadInTorrents(db) - RunningTorrentArray = createRunningTorrentArray(tclient, TorrentLocalArray, PreviousTorrentArray, Config, db) //Updates the RunningTorrentArray with the current client data as well + RunningTorrentArray = Engine.CreateRunningTorrentArray(tclient, TorrentLocalArray, PreviousTorrentArray, Config, db) //Updates the RunningTorrentArray with the current client data as well PreviousTorrentArray = RunningTorrentArray - var torrentlistArray = new(torrentList) + var torrentlistArray = new(Engine.TorrentList) + torrentlistArray.MessageType = "torrentList" torrentlistArray.ClientDBstruct = RunningTorrentArray torrentlistArray.Totaltorrents = len(RunningTorrentArray) //fmt.Printf("%+v\n", torrentlistArray) conn.WriteJSON(torrentlistArray) + break //updateClient(RunningTorrentArray, conn) // sending the client update information over the websocket - } else if strings.HasPrefix(string(msg), "magnet:") { - fmt.Println(string(msg)) - clientTorrent, err := tclient.AddMagnet(string(msg)) + case "torrentFileListRequest": //client requested a filelist update + fmt.Println("client Requested Filelist update") + fileListRequest := Engine.GenericPayload{} + json.Unmarshal(msg.Payload, &fileListRequest) //unmarshal into the generic payload + FileListArray := Engine.CreateFileListArray(tclient, fileListRequest.TorrentHashString) + conn.WriteJSON(FileListArray) //writing the JSON to the client + break + + case "torrentDetailedInfo": //TODO Figure out how to get single torrent info correctly + fmt.Println("client requested detailed Torrent Info") + torrentDetailRequest := Engine.GenericPayload{} + json.Unmarshal(msg.Payload, &torrentDetailRequest) + torrentDetailArray := Engine.CreateTorrentDetailJSON(tclient, torrentDetailRequest.TorrentHashString, db) + conn.WriteJSON(torrentDetailArray) + break + + case "magnetLinkSubmit": //if we detect a magnet link we will be adding a magnet torrent + magnetMessage := Engine.MagnetMessage{} //grabbing a magnetMessage struct from engine->clientstructs + json.Unmarshal(msg.Payload, &magnetMessage) //unmarshalling the "Payload" from Message into our magnetmessage struct + clientTorrent, err := tclient.AddMagnet(magnetMessage.MagnetLink) //reading the payload into the torrent client if err != nil { fmt.Println("Magnet Error", err) } fmt.Println(clientTorrent) fmt.Printf("Adding Magnet Link") - startTorrent(clientTorrent, torrentLocalStorage, db, Config.DataDir, "magnet", "") //starting the torrent and creating local DB entry + Engine.StartTorrent(clientTorrent, torrentLocalStorage, db, Config.DataDir, "magnet", "") //starting the torrent and creating local DB entry + break - } else if string(msg) == "torrentFileListRequest" { //client requested a filelist update - fmt.Println("client Requested Filelist update") - err = conn.WriteMessage(msgType, []byte("fileListUpdate")) - if err != nil { - fmt.Println("Websocket Write err", err) - return + case "stopTorrents": + TorrentListCommands := Engine.TorrentCommandMessage{} + json.Unmarshal(msg.Payload, &TorrentListCommands) + for _, singleTorrent := range runningTorrents { + + for _, singleSelection := range TorrentListCommands.TorrentHashStrings { + if singleTorrent.InfoHash().AsString() == singleSelection { + fmt.Println("Matched for stopping torrents") + //singleTorrent.Drop() + } + } } + break - } else { - conn.Close() - fmt.Println(string(msg)) + case "deleteTorrents": + TorrentListCommands := Engine.TorrentCommandMessage{} + json.Unmarshal(msg.Payload, &TorrentListCommands) + for _, singleTorrent := range runningTorrents { + + for _, singleSelection := range TorrentListCommands.TorrentHashStrings { + if singleTorrent.InfoHash().AsString() == singleSelection { + fmt.Println("Matched for deleting torrents") + singleTorrent.Drop() + } + } + } + break + + case "startTorrents": + fmt.Println("Starting torrents") + TorrentListCommands := Engine.TorrentCommandMessage{} + json.Unmarshal(msg.Payload, &TorrentListCommands) + for _, singleTorrent := range runningTorrents { + + for _, singleSelection := range TorrentListCommands.TorrentHashStrings { + if singleTorrent.InfoHash().AsString() == singleSelection { + fmt.Println("Matched for starting torrents") + singleTorrent.DownloadAll() + } + } + } + break + + default: + //conn.Close() + fmt.Println("Message not found, message recieved is: ", msg) return } } + }) if err := http.ListenAndServe(*httpAddr, nil); err != nil { log.Fatalf("Error listening, %v", err) diff --git a/public/static/images/draghandle.png b/public/static/images/draghandle.png deleted file mode 100644 index ceba4cbea51fdcb30a8215d9a54235a4c1a054be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3003 zcmb7Gc{~#i8{f?4-rOYDSdns<9Fg$LHY&M7xpUuVuC&RJbCycpaxSS{lUUB>)+7{` zbA?HhGeK@ zCxZfNnpCY%h*F=`sk)R3Wg@$H>v3x)wpN+w9}|KZk|=(jlmcG`6<}VmTX9vnOX`pdiIikJt=2 zq1|Nz)4}#(uk;u|V+aXGwrxRTKX0#Pzf(_$ZCEhA zcJvKeV4!rWupFy1rJ0%&0Q%f4Y#>X3=n2!ze#zZU&Ne;k9E6EJXkAQzG}bKE@*lNs^C_f~0+FiDlvvum zVFBsG(g7KYlN(Q{HI%9jZjx??bx64t^zJi&>al~`X2u&X*#|WBE>1dnf@$9-;ebhW zEd7L?O$|7<)T9%?217jtp77VRcYjn)6zCa>=F(8y8nJM{+|xQ-_^wUnlM`KYRSRVO zD|~*m0kl|u^|>frYwGB7691;_f+nku<1g~%4>m*l^GQ8N^hQdYkmO_c!$n<&tG)4i zhwPR~AYJ5$zuKjz&9OPRTG}86+(F~hv=nGnI&~Ph&)JMP?;i#2L-aDQ_&j0Bek0eE zzNBi3H~XHZ*0_ExRZ}Y)&K}=ktjWfQ=bPJ?Je)((7hBeQYP7L@*f8167^P62P}8HU z>POygPg8Y`DyZ@N!3LO*_gi*`1*U%JwX4!l1InYZ5*8bcV!GhwQ$|bV1+QiC`EJ?G zCy*yaZ|jnj<-ak{EVuNhh_WISL*Mj976rd575-a|r&YE3sR9ebEh8YgGZoJ;X*ovp zKRT>ia?xI)1QP85Z1}2iSFh7DxzxEa)>8Xq=RRK;-sS*g;qDOrwHkS{)(nzV*lD)GSl6c z;5Yz$ysG&ji>GFqcYj6W&MH?NmQ`<)hdgz7aU&wHu*b06>POP>ckl-M9!J2_!-0 zKV*+L=6<9Q6z;KElD*7k^a~Ry^)U?j#}D;qynZbXAO&IY{}wESD#oNCtc=ar*QLNC zDwxapfBP?f2@IR|KS{`N0M*T|H!*`vb8mD>;it35l^$8+=3fxn|F8!h>t))6&1x%z z9a)T--g+i!Rta2x`*d3dcMTpJF5tTEf5MI^8em+wme0uRc!h6?q(l1#wRlk{$1vx( zTE69b2Oq&9)q1`fL59_lysGq?Y(ECb)1u;^y7-LV)4WLZEj<@GSVBvt3F5VgVfpZD zf{i|Q-rTMM!&TwCrtTo$xu`B2%)kJwv%TkN;bJb_BFd$-RzM4bsevx1QZFmNhX!mScJ+s(S{ zng*DLjX$;uU~s;?nzD0dYI1PV?~p(bpE~&#Cor`%G5a9=Aa_2fL1@d&TZgw@wn|(l zuF6C>b)6zhXdEAL8yy|!r?`j`RDPdY3EFzh&W9w{`O?@7gRl^#aW@pfglo-|jpt`? zsT~h0ichk;=BY?p|0qTvJKu|+`~`Vc&A13^EW>yGxJ1c7gxqiaKDK0%bpd{F)QjBM zTa#orF3*cfxCr_99HPaG zJice+aD~WOj8Be`N@OOuS8#MIBNmRP%3LFlZD|`{E0*#S#1U^;tY81gXCkH?Ld55F zE+%z}M{nIVy9hsF58JkM9*>(A7~r-o( zr7Vwvt^5Kojg-8q-vrwU4X_p}!-x_2P<#$N(jvt(T3H>kJO$pZ=OB@(%J%8n9OUd@ z@Gszm2XQXfBc*GzBbjr0KUmL(eKW9$BU}q%f!rzj%h6fDhji9H3A-&Cm*A^7(7BpY z)cGcg;%IwTc@ud{-e^d+D~?Qr&p<1mx8mzDdsx1To-cDyx}}@yPgSP>RM|LMAgkL@ zh43l}Qmrs}uyHxCaV>Gewav@nO7Ur00v%ijUI6IGFDWb+{=~=CuG=48+M~Wcx_jdb z&Z4CWyKs}Q-*8c^IaUeqYGO_pEwMfI{FU-H>2WjW5=DpZRp}F? zUJIM_`i}-t2KTgC`P)WzD#oJL)ksKvn&#+T)V%a^BAUasT&gup_=RGvdxh(47c$E1OkPXi6ivH9@N<9`S6Zq7j=F3pS5gNuhv7INL jp8PK!*0i+wg*#`H-F2TS$osIrZvg6_%VyOkZb|&A;=uL1pr-zBX{a4o?S}h_qAQ6waF%`w>e-uDh{Erhnh|W_enim-Y#GHr_ zKrYfS(dpAEKs4Jf5V2bCxepO7#dJ7P_3I44MEpTvD|g&O`HI5p){$fuA`A?^>j#r8IS zO;|;2QF}F%bAVGPjON=V0^XSffPh{^I{dRoXE|^xfD~>5(I#Gw>kQx+~s?$CV2p#e46jF)P{VorS5qCKN zUN!fjccMY8bK=c%z@&)lLfawq#j_o-2~ZWag$tA39N0TzdS%r+K;?wNr6CJIw@6*K k^8hZR-87eXpl=7h05a`fK*D~wEC2ui07*qoM6N<$g0+w6V*mgE diff --git a/public/static/images/iconAddTorrent.png b/public/static/images/iconAddTorrent.png deleted file mode 100644 index 6e2653dcbd49ffd61c9fca8c3f787693be681abd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 913 zcmV;C18)3@P)5s3f*10G34 zK~!ko?U&0>6Hye#zjIqlJ5Z_Ch)D&iESiYn5g*ZwxM1PJ2kgXuz=aTTBl;h>FcA|L zZVZVF;tq6S*k}w(O@uU(CW6=|qM@cxV(HM*nd5>|+M!R|X(5>}>0+jLI^XY}dmaT0 z88T$3mZE%LUYqQ5n}KHxbP?dLrZEQm1k5FX2h;si{*nQb=4SyoYP`we1kjxeLgaeN z#2DQN<^jNw^n#KAh|sf-4ti(F0F~H%o7oCiLsKOZ)%`yJWt+d(F@V92fr>y>6=28w z$%ZD_%vN0?gr4Tp@9700^fs?Igs6sjJt0K3%n0KNih-~JCqT=;cPMG{TxquUHZn1Ceh2*s6@19|CCqv7Q;t?|)OD%(Eh#LeOB;ZM&gc z70L&pP1sA`AkHqV=Kn#fO#?wLg18%Q!4cicXf}v!)uzk$2ZwTG8LMjU7Z6{lqq#b<3^)i#`H3@3b_JPz9Y_n_fhPR+%L<(#?CqS(!00ShurH2f9OoEC!rp)|G zQaA2X0O6WPUf&GV}OWLV4l%8CxuBn5(8DZmAQ%Edup|(46Kx nLW~(^elG>&N$ntKXg}y5V~BT_mn_}O00000NkvXXu0mjf3`m?l diff --git a/public/static/images/iconAddTorrentLink.png b/public/static/images/iconAddTorrentLink.png deleted file mode 100644 index f7929c3c01364034ce55461ee695b748f5b44f63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 527 zcmV+q0`UEbP)7T3?q3St_lwf};v86z@X|$TLwLyY*ROrD@reGg^7>nFn_Ay!lW@a42X2p{R6pTT%7jp RtStZl002ovPDHLkV1h?V)B*qi diff --git a/public/static/images/iconDelete.png b/public/static/images/iconDelete.png deleted file mode 100644 index 666dc00f74236c339d49120177b487749f37ad92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 794 zcmV+#1LgdQP)lbK^-_p86QS7z z&16$%ab!v7<9%n|O~5wi$-MK-_s4SfLVo;(IM}}lx!&7*z1eEr&$<;MaltKeb#U-4 zW$aB^h}~IYE*p&##`))XJbu5`YPC(32!coii{qox!ouUjVDNKRm?uPYsa9i2uQ!N< z*fC+85QSLZ-i}`_F0voz=fhcG6k=^-gVk17*{^n+^*S9R#tO+J%GGMts_AG{IA$85 zx|0oKgy;||!y+*zgbSmETs9ibs8l+Z-AT2?^dKt&<3dbfl1PZRYRs4*a;9ji{%M*i zC^1k(7W3j__>d$wWg*_F8PwRdP#FhK0H|0Rgsf=mU`GY;#Gqmr5Kf3pfC_}fpz^jL zK#-y^ln5|{8bgghL8vfAAkdIdOi>6gh%aW6rl*|qPoTBQF|c*(nsd`=S`1OOD`&GL zsT76qZV`pUV1D1-vFgf-@l0k~v7v`J?-s#gYy}EM1h)tUh5|tb!At=8mZ3tBLa-Q0 z#QY)1y_s#C1rPR+aYA{XA%Q@rVO@<7X*z+lAB4Ieg$tDJuqm94?^8`p#F=*pdhG%7`Ec5JP;T#1XTdXc>1sxJWjiI?R^+Zr&!Y{D{5mXpGWPkrGisO&#^}798 zfe3-cWDh>Kw}WUjdVY#CKlB_PerKG2&|#<#MfqK^YjTl@Zl^Phg{bG>6YWoL8cdN0 zSId|XpcCR%4wF5G5_c!)y_pRGg2+S)Q>s)Rr(cSo_f9_PR5x2%US|Dn_pk1h&(pae zs>BkLPA2k$f#>HgpTc4P^Mv^lkH@>g9}KAAkWVSF1%;%C#09qqB;Y*L{D;i5_I0uU Y0IW08Z_OG}od5s;07*qoM6N<$f`H6p4gdfE diff --git a/public/static/images/iconDownList.png b/public/static/images/iconDownList.png deleted file mode 100644 index c438dbe213310938cb6464f3f399c5589b30e105..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 753 zcmV<=9F&GR6 zgHlS8{OVQrsoRt1`F!r@bMGfT-LpKybMHClectDsd(LN$8Iide!9fM`zcE=Esf-kg zKuxVef$gleGSWG8g)UY`3I(>a+R8}h&=tBk(~MjLE*A=1F16QzE3vXkjNAY&Ndhfn{I=@Dw--{F-#BP1jltJOK^@AAvo< z`z9}X{=WrS1U3QBfFr<e;JSo8L_$8WNbE#k^)3!7TprC4R{Oe4Yku~sKo(mK?bZ1b?**Mro~k{ zeGb|fqNYK+nBB~-)<+DG-N`OxGqDbn*iL0+&}$5sU%5P zAR37~i_tvPrYOg}irCm5-WBm`@a jqm_|C!kl1aW*GSk1fyv)R+IA<00000NkvXXu0mjfFa%Bh diff --git a/public/static/images/iconDownload.png b/public/static/images/iconDownload.png deleted file mode 100644 index 2349d89175dc0915444d6aa7c4be6a0af55e56e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 506 zcmVB!wh8d>4a5`JJ%QdpOxnahJ%UHjKa)1G-at>V^#tM#{0EZyjWT96jidqE z-Okn&wm(h7?0fU(O=$Tz#vR%lc-7LvvRV6sm7fE&7E`(Xbz0M zoZSKT4od*p1-O@3(?aJ!abT@qADH(6>tfWs1DYGK zn=v{FWCDoin#0;$PV_j5#Yh*^*nxg1Qv^KGC0tccKrhos_$FA!0=$v*x?M;C@W_Pt z?+m@o=iq0F$V_mI1^oU3A%_H@oH#HcC!h}m@F$TNo19l?Y6-|i0N|@x19V)cc@_Z* zq!-Fj2k=2h!~*DI7KudX%&OYj4&h0%sOM=ce(p9dYYy0Gws8lV5V5@ulzla9V!F#5>;79? w>wpu$Y|-vHz&t=}aNCm0-#Am zK~!ko?O3sH+b|HlC)9zIX7g%z^5zdnx8^texy{r7>1d!Cyft1^fN~q4fnEnv5-F*H zB$Ad3=msOUqw~GHckhlAnQgY&{%ga?=ji#oc0#fb*qk?u5)SAnv~guttXbp_a%j+EE{T2pyE1eL4Cip97T zO4HO43VH&_Rc`SgXKLcA2k1S7TNH{v2U4*&2;W6Qsobg~M=^5X9LV&@2Yu;psgTL~ z$ZQOh(QETV6lW{-nFFLX35NR{PNAyc7^i!!Rl=G9h)ki~ZWna#*OS=de-W8Nq0Me$ z>x>ug3grIFJ!zT_RxfObax_kKbT(U>J*(ci%10l+JtDw)pgfKBC+)+- zS8TUic1~N;$v?%cC=^Gbp1waJjEuH^w4d$wd#u-MYXLE#I(JP?anSFdpMN0uk+Lp2 z2R1D`Za1WL<(kn-`)K?-i$zuL4hN^io_sA4hN`gK5<|Do$(BTC~=sK-F7E)y=oUY8ZRR z8Fq%9VQ1J2Klz~6TPQD{!7um)zu*`ACKd4FRpo002ovPDHLkV1o84 BYV803 diff --git a/public/static/images/iconRSS.png b/public/static/images/iconRSS.png deleted file mode 100644 index 59f1f01954c71daa06e43af8c6323d047797c713..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 850 zcmV-Y1FigtP)WpVMHQY- ziy5E+TKIHK09vA|4`DOFF8r|&-xVQV>3dc>fQ>HGuXEtxEEwgSxD zHwVnWtH2Gy3_0uq=tN9S1EmUZZwOhB_5fi~bmU1LxPG@^DqWx(bS1@b z3m}EfZ2=2!`(?619WJJV$OnMZnJ>>hVCrTRgid(ti9N^ph#7uHFwSl`q@T^O#FV zFO2DI7eJkc-FKm$u2d3!Nx9);E*N&P*#Z#ARAu5yC96_++YxhY_5dabCieT1zRc3O zGM^iC2UnjiXoedA3BmXdcV1JKp=;~EqjC+&Y!863JGU8Zqj@{|Z3kcihKIVc{NMg9 zy$kFM;pS#&Y<2*2iAQm)9x8-dWpu~z+{ZQG(VHH=ArI^TsH-KXGtB!67f{H#*PdYtG*l_-Jun(~AwMZ}OHh*YM&NBX0qt&OZSdbp=N~ czwi$H2gem?K$;>VyZ`_I07*qoM6N<$f3 zEPo2tvyaVK%`X+a<#!f7;N>iM+Uw>(So#vY;5x99>!}IG-G?j2yW`+_w=V^u{2m~; zl5T3JXTG!NI>hk6My4R#-jnoSh`EMw9e6H9`3v(ztM-GWFnqq>V>3vtjN8R zMbk=5T0w;2E1Weo2oK0IvJ20Kq!q*&^N@`*gZhO+3di6vpxyz4UL_r7vM}e_7!do> ze=~^qAe5F=cvobPr36a#V*RB-9aYj%280o;8z$t!;FLHT1SndpOnO~S`{hQIu35F-WUb2B(C0{Zl1Y*1dQT}GVNll7(&Y@^}D87 z>aaXAV7PxZqQf#@kXS(CN1g>?0D%NT6GXVC(xl@F$yJ~0Vr{Mcw@g9I0r9j07?0C( zMRsv*+1S-Uj*llD&vk%3c6qMLO-OxwTR~$JVnhEA0`QAjZ&4=500000NkvXXu0mjf D`PT$f diff --git a/public/static/images/iconScrollUp.png b/public/static/images/iconScrollUp.png deleted file mode 100644 index 99fca2e19a5bc8460bec1a1e10f528b1bdbc3921..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 579 zcmV-J0=)f+P)a4TC6_)^kiWU~aq z^QYuJ>sXA}{Dwlb{Laz`qMW5jd))|xr>`jr(t($xrzSXepHfV8$0_n|-4KNGM}pi+ zx~W+YzO&{!?csr)9D)dYPf`uS-pxmxFbsRZRw82YL#iHfUJ?N82mco%dh92aiq1Tb zh`dro(~&(f#P-KvY{Pf5H8qF`s4}XH$RZg+T3}u?GpK)2C}Dr+4CQCX&!x!v01SGQ zbQn}2UgwabRF#f~jb<(I66{aXyFu&^LTeccig*r$D&pC~dd{6;(YZu_;SU`(85@Fd z!VtaT+YHh$7%x z)wP_XTIwRu+Brh0r8AU@A%eIw{BmLD<>+2VkK#TlNo(qgy$-{z-Mdx*?%rR%Jfr&v z7$+TNu8U2@5Dqy^)O;a_cV!!ln`Sa~Pu937h(fN%*SR8MKr@r2~APr7)w za{aeVLCgVp#|BKqw543AF47j>yfu&wdD8J*2iRkm=elS@>K$nXZCVg(`v0cqi&-*Y Rj^h9T002ovPDHLkV1g3g08sz{ diff --git a/public/static/images/iconSettings.png b/public/static/images/iconSettings.png deleted file mode 100644 index 045dd943b737a979dbe26d725e32ba19ce7e92d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1450 zcmV;b1y%ZqP);F_@ym`iH7K0ZJYt}{$?CQp6*!i&-VQXlV`rEDn#(o&Kj$G-7m2UOd zHxwjqtPUh#Q!<4E{H)viSwZ*GWpCYYHzL`UHAfM#0d}H~2)$V`#t_d*19^`|IfC)L zs$lbbuZm|t(w8^{F-*q_5JoZP&rLs#7V`|x*%qkg60UhbzUt1lmEI~+X_283~1s+-9Uq3>zY=D=Co z<{=2{`A%a4JPJV6=qcZim@#rD0Q~NQ{q99;3j|k(O-P1J@b9RH#9M7jnJ?AMXV|Eo ztVhydL57GD=j~}UtY^J^%s1|j%>g0>u#SAiI4jLB`lodUqikm58OwwP8DZZ<{)pP! zl(N2*ME7@&j1eikm0rm$vpO|_7L z&09i9S|+{FFh@wWoKaQ)T?L3m+PuC5h%^n5-45QNy9y9FjpNhIW~mj!+FO&GrB;gF z1`&Ekp`8`G-lKu-6}tv2n)dbK5Olh7E@78qS9_fFpx8rYj4-fP=+}mO^xHN{^lKhN z<$rG&1F$2YQn969&(4ku=CLjGo2#b#)E+fN5A#w$J>csuOg3k9tCbY8$jV<)OVa|< zclPAT_DCE9N2kB``jt#-``fS~j#4SzSmzx{l+boB>=^AkjjkQi$KM$M6dkt5Qeijg z-a6$OTaUC>CPc=MRB9x|2q*%GT44NH(MWCRHM3jGdqAr|_E?6oITG`>=(NN41`xS` zQ=qv<^0(1JD=c_58E?VJ_?c%~Fg)KzE(a`im!tFQxkV;K#$SA}I&;)j#374BrB%Nn z4o0n9Vqfj38xJbdm5oP)kw$o?W4G%>9ba_$fch+uOM{~(d5iC*vvgJX(>GoJiwn9l zSEjtSa)ud2Y<2F%SEhSc`ihYRPx#ft-b~NL00*|`Hw(0CjpW)8s z2!L$JYXwKpmAAH$9gf82=6#F8M$K(>XRkIMM0cej_F&wO*jVo%9i(75KF_Ya=xI-q z*0K&oYb}x02$w)Wv;w4!OuRsK0&|O3Z$Pwyb?^PmX^CP20hhwudzrKHGE_=Nx{L^5 zb+1POS?v+I?wQ>Vk~{9g9@}7tcC4n>DhSU#H~(QEvZj4&8%JO|we_F)FB}nuZNat? zU3u$!CIjxCy+vxph{*QVsGQMH8+tV1mOzg7zUue?0)}UgLIEz`U;qFB07*qoM6N<$ Ef{RSLCjbBd diff --git a/public/static/images/iconStart.png b/public/static/images/iconStart.png deleted file mode 100644 index e76a660bd1ac016224fe7117e9458441c489ca19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 524 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPtC%ZT=*I7xamkbPyGd*1#Ln>~)o$biiWFX*ryR-29 z-k1ZDHl6BCtn42(*7drDtF#5MBtH9pX(n%H_o4c^Kc^Y-9y|;Li|=$~vs;*7t^N@m zzI`JHL-M2IW`!tb|ARMU*=o*z3$UnG%bCaMeDL|QD&zEKFV3E`R@yA4{3lqOGWg~( zvs~Qg7{0ymjCdF0fxNz?O5+V$P@A87dTv@8!|!VG3udQd89kQ%ye1#Vx0B<#fIoY}yEXZlEkT&W~-=k1lh3U+~N9AXJ`~UB>AsNnZry24!81NjK)c&zb zE{sjgA;}|#GjzsGm$h@}P1^WldiQ+$JqNC{nJ!@TI3U=>P`H!L!0Cnqvw(u$|MiU< zj~@7;$6NINZE7xa+=GSw%vUSRT4WYZZqN*=wa))P+bML?vI&|gTswR3#Wfmc^@MRs zEH-dc{E+$dZEnde&IDzB2F6E4ya_EE8rc*aV%9PC2$)@9VCgt*+8}s{jeYK98^eI* ShT1^aGI+ZBxvXh56WF0crwjrM zRwl+YB4%`FK4(^Ayzb7<@ArKl-#9Z2Oa5a^&JQn;b_RV07CHlmtuUVft~gL+K;9)R z2YL+X#K8G|CF-f>R+i8h{t>{MOK{0t{TSF+Nhk$M%`jpNM=8UPrso{D?P?UtSd;?g zR`|LA(f<|zdhJTIrz^mz(O=DEv7Qa^{Qg4y6z(dKG}zNJKoSt}r-fr|WCJw1H)IK? z0u%V1+}0@agZP6i;Y{E!{G@iM5>5nE@bi$cE-(w8Dq&S1DLh5Ont(36se}~)Q+N{z zD*~$3seW)FeN=n6G+xlWfKKRq1|-q)CFDy8fbT+*GO)5A@LkAvApqr8ICD!W{tKNI zPOzQZ)M-*b?+)TmG`iP`wwu=00aFPbcwuZ!Kzv+RLKoh;fR2O-yc2;W5~lFZ1g1$) z;GGJ{B&hJt1%6A2qs64Ha#}Ce?n0$z*k=rZQG*{3n%CJV=Xh#YBkBFb|2yhsC~g929G7`5LZkLyHpsR@uF-1bcPHyqbnwz$nAj*%1{8}|B*I{^7z_r3K`CXB z{OVKJEj^x|>&JaxcY3oK%wu-chRLVf3R;9!i zf3{VmICYf_TSYPwdp77^$gs&)tzD7Rz{L>N8Q@ZOgoy?1$6#EGr18!zTnV?()$UfjMuryFfN-0uIs{H^C0QVE(OI8^g$X?(cupGDo zoSKN_GH??32J8nGlOv5N4hdu%@CaBDsB;wfHQ`@>Hvp;k71#s37y`^tK(+vnfmOh5 z;BcVOv>2t_E#MIF1=tO|>I-HFAe(^a!0N#JgTVJlV9S6zfc^9t*bcnu1Ew#KjleTt zZQ#4Sm;WhZA3Xqe0Uv=Kz}pnVX*zv?tOs5K>jKZ^yS&elmB2&5{`vrH1>Wa;pwle{ zV(?aCL*TbOm+vKFU)f*w*}G5~L1jq^5NRX`Y4ti#L!S2$`|Am?InYa*Nw;Ll1)@V6 z+XlBecLJZ1z0Fo!6DVqe{I&xiIYBu}*P#(b5++Wdaz7 zh}8Ah$1-V%qyTYDx^}pJ*o1{1QQax#G;_$f`g;O+3j8CpfOr&n91XS)6#&u1_eC&1o*rc$ zXURai+o8~RRWr}!?#B7!Xj()^ZfWley&*T5cmUty zl1d?vO!WcE5~nH*GnwiGB;gD&r&V>9)Xm`fPMy8#0VH7xn2S0G7Ot^K;rS!#p7j8J zI;HGiy5P@>DtuF~06U#i2WZ2jBcvllo0y$y9U*1|*~{e}U`wKHAP=DL0d;`Zfxq`2 zVDeL!%Rj_a1w_!?yjqAr(z2B->{^_>U!0MJ#6F|JY5fdBvi M07*qoM6N<$f)VY^b^rhX diff --git a/public/static/images/testicon.png b/public/static/images/testicon.png deleted file mode 100644 index c08f5bed7724636b7bf6bc3b64f0a6871d774514..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1014 zcmVJ9 zvU>33K@WljJt%DG#hU?hNHCyy2;{0kFPlS3QrPl(n0Mp2+04$oGrP$^zVH&5d4GI9 zZ{DA?z)>7UreKbB)d0)_m;o>eU>rc%z1sq?0bm`#Du6`*PY*)}Q~}%p&;(#prlu=f zJt**o2lRfaF-Vbmj^LfC-cRr;0Ly)ZZ>MF~R<2R=9Ou5N>DtU?6{-RF2SDk}<8uQU zqYLMs06+`C54~0^B^Wjj0hD||J}(X7Sov#TkCJP9s#m7CxC>y^7yg&&OZakV1h-%Q zjW=8GQf*HXA#s#6cO`x+5v0QBG@uAcu>y4fr?bExcfJ4X^rci1K~RAd!jd{IsV?d| zMNonm!jl5O8XJRQ_=4>hQdQ*hNF|Vj6Mvmd4d0IK)=pxH&+dniG=d<=2qeE3xg?p8 z(-5Qq=jP^|4Pj&e5h5Fs&U6a=e}!J~X(hf{IrXtKNk|3~7et+9$Ojn%kl_6MJU#)X zs+68f0A<3SaFxCOZp|A$jl{)&e}pJETm%USdtUCpAkguaDnamZOoaumN(?87>v<~t z`xKDWoaQuo z=%Z6$s{qVfaRM6!5ZH(lSTBIUdYr&&0R&d#1QrV*uo!oxdrsl zJC7LKt^aWQ<%2ZW&CSkBez#@xQJS+*2=G32H+sN#W$PwzFYSRYt%N6hSGH~fO8^%7 zC6NJs!LcR!F7!wGA<B`w1)oxS6L!M);fEdcW6M=sJLvJR~y0uQ(R3Pm9;w z(&a6Y5q{G#cz;@a1>h&RkGnn+Ukr`-!na)8uVQmqYm=m!wYF&o7fsh@Pqw52u+~ml zYnKNAzwFvV-U97Z?<0IYEsu`?thH5ZZ6inUhN}~U5{Qc2@thw`SGJmkf!5l*j=2Z& kLwBA6hvHIyBrxds0QHs4GU-?qoB#j-07*qoM6N<$f&kOIhX4Qo diff --git a/public/static/js/addTorrents.js b/public/static/js/addTorrents.js deleted file mode 100644 index dc392aa5..00000000 --- a/public/static/js/addTorrents.js +++ /dev/null @@ -1,49 +0,0 @@ -// Get the modal -var modal = document.getElementById('addTorrentModal'); - -// Get the button that opens the modal -var btn = document.getElementById("addTorrentLink"); - -// Get the element that closes the modal -var span = document.getElementsByClassName("addTorrentModalClose")[0]; - - -// When the user clicks the button, open the modal -btn.onclick = function() { - modal.style.display = "block"; -} - -// When the user clicks on (x), close the modal -span.onclick = function() { - modal.style.display = "none"; -} - -// When the user clicks anywhere outside of the modal, close it -window.onclick = function(event) { - if (event.target == modal) { - modal.style.display = "none"; - } -} - -var torrentFileModal = document.getElementById('addTorrentFileModal'); - -var btnTorrentFile = document.getElementById("addTorrentFile"); - -var spanTorrentFile = document.getElementsByClassName("addTorrentFileModalClose")[0]; - - -btnTorrentFile.onclick = function() { - torrentFileModal.style.display = "block"; -} - -// When the user clicks on (x), close the modal -spanTorrentFile.onclick = function() { - torrentFileModal.style.display = "none"; -} - -// When the user clicks anywhere outside of the modal, close it -window.onclick = function(event) { - if (event.target == torrentFileModal) { - torrentFileModal.style.display = "none"; - } -} diff --git a/public/static/js/bundle.js b/public/static/js/bundle.js index 47e90128..edb1ce6b 100644 --- a/public/static/js/bundle.js +++ b/public/static/js/bundle.js @@ -73459,7 +73459,6 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // contains the font for material UI -//import PhotoCamera from 'material-ui-icons/PhotoCamera'; //Redux @@ -73504,6 +73503,16 @@ var IconButtons = function (_React$Component) { var _this = _possibleConstructorReturn(this, (IconButtons.__proto__ || Object.getPrototypeOf(IconButtons)).call(this, props)); + _this.startTorrentState = { + messageType: "startTorrents", + Payload: _this.props.selection + }; + + _this.startTorrent = function (selection) { + console.log("Starting Torrents", selection); + ws.send(); + }; + _this.buttonHandler = function (buttonState) { console.log("BUTTONSTATE", buttonState); }; @@ -73582,15 +73591,14 @@ IconButtons.propTypes = { var mapStateToProps = function mapStateToProps(state) { return { - buttonState: state.buttonState + buttonState: state.buttonState, + selection: state.selection }; }; var mapDispatchToProps = function mapDispatchToProps(dispatch) { return { - changeSelection: function changeSelection(selection) { - return dispatch({ type: actionTypes.CHANGE_SELECTION, selection: selection }); - } + //changeSelection: (selection) => dispatch({type: actionTypes.CHANGE_SELECTION, selection: selection}) }; }; @@ -81221,9 +81229,13 @@ var addTorrentPopup = function (_React$Component) { _this.setState({ open: false }); }, _this.handleSubmit = function () { _this.setState({ open: false }); - var magnetLinkSubmit = _this.state.textValue; - console.log("Sending magnet link: ", magnetLinkSubmit); - ws.send(magnetLinkSubmit); + //let magnetLinkSubmit = this.state.textValue; + var magnetLinkMessage = { + messageType: "magnetLinkSubmit", + Payload: { MagnetLink: _this.state.textValue } + }; + console.log("Sending magnet link: ", magnetLinkMessage); + ws.send(JSON.stringify(magnetLinkMessage)); }, _this.setTextValue = function (event) { _this.setState({ textValue: event.target.value }); }, _temp), _possibleConstructorReturn(_this, _ret); @@ -89953,38 +89965,45 @@ function _inherits(subClass, superClass) { if (typeof superClass !== "function" var title = document.title; //Set the number of active torrents in the title var torrents = []; -//websocket is started in kickwebsocket.js and is picked up here so "ws" is already defined -ws.onmessage = function (evt) { - //When we recieve a message from the websocket - if (evt.data == "clientUpdate") { - console.log("Client Update Incoming..."); - } else { - // recieving data - console.log("Recieved Client Update..."); - var clientUpdate = JSON.parse(evt.data); - if (clientUpdate.total) { - // if it has a total field it is a torrentlist update - torrents = []; //clearing out the torrent array to make room for new (so that it does keep adding) - for (var i = 0; i < clientUpdate.total; i++) { - torrents.push({ - TorrentHashString: clientUpdate.data[i].TorrentHash, - TorrentName: clientUpdate.data[i].TorrentName, - DownloadedSize: clientUpdate.data[i].DownloadedSize, - Size: clientUpdate.data[i].Size, - DownloadSpeed: clientUpdate.data[i].DownloadSpeed, - UploadSpeed: clientUpdate.data[i].UploadSpeed, - PercentDone: clientUpdate.data[i].PercentDone, - StoragePath: clientUpdate.data[i].StoragePath, - DateAdded: clientUpdate.data[i].DateAdded, - Status: clientUpdate.data[i].Status, - BytesCompleted: clientUpdate.data[i].BytesCompleted, - ActivePeers: clientUpdate.data[i].ActivePeers, - ETA: clientUpdate.data[i].ETA - }); - } +var torrentListRequest = { + messageType: "torrentListRequest" - var newTitle = '(' + clientUpdate.total + ')' + title; //updating the title - document.title = newTitle; + //websocket is started in kickwebsocket.js and is picked up here so "ws" is already defined 22 +};ws.onmessage = function (evt) { + //When we recieve a message from the websocket + var serverMessage = JSON.parse(evt.data); + if (serverMessage.MessageType == "torrentList") { + console.log("Recieved Client Update..."); + //var serverMessage = JSON.parse(evt.data); + + torrents = []; //clearing out the torrent array to make room for new (so that it does keep adding) + for (var i = 0; i < serverMessage.total; i++) { + torrents.push({ + TorrentHashString: serverMessage.data[i].TorrentHash, + TorrentName: serverMessage.data[i].TorrentName, + DownloadedSize: serverMessage.data[i].DownloadedSize, + Size: serverMessage.data[i].Size, + DownloadSpeed: serverMessage.data[i].DownloadSpeed, + UploadSpeed: serverMessage.data[i].UploadSpeed, + PercentDone: serverMessage.data[i].PercentDone, + StoragePath: serverMessage.data[i].StoragePath, + DateAdded: serverMessage.data[i].DateAdded, + Status: serverMessage.data[i].Status, + BytesCompleted: serverMessage.data[i].BytesCompleted, + ActivePeers: serverMessage.data[i].ActivePeers, + ETA: serverMessage.data[i].ETA + }); + } + var newTitle = '(' + serverMessage.total + ')' + title; //updating the title + document.title = newTitle; + } else if (serverMessage.MessageType == "fileList") { + console.log("Recieved FileListUpdate", serverMessage.fileList); + fileList = []; + for (var i = 0; i < serverMessage.total; i++) { + fileList.push({ + FileList: serverMessage.fileList[i] + + }); } } }; @@ -90029,11 +90048,8 @@ var BackendSocket = function (_React$Component) { }, { key: 'tick', value: function tick() { - ws.send("clientUpdateRequest"); //talking to the server to get the torrent list + ws.send(JSON.stringify(torrentListRequest)); //talking to the server to get the torrent list this.props.newTorrentList(torrents); - - //console.log("STATE:", this.state.torrentList) - //console.log("Torrents", torrents); } }, { key: 'render', @@ -92541,13 +92557,10 @@ var TorrentListTable = function (_React$Component) { if (selection.length === 0) { //if selection is empty buttons will be default - console.log("No Selection"); _this.props.setButtonState(_this.props.buttonStateDefault); //if no selection dispatch that to redux } else { // if we have selection continue on with logic to determine button state - var selectedRows = []; //array of all the selected Rows - selection.forEach(function (element) { selectedRows.push(_this.props.torrentList[element]); //pushing the selected rows out of torrentlist }); diff --git a/public/static/js/frontend-websocket.go b/public/static/js/frontend-websocket.go deleted file mode 100644 index e0709b78..00000000 --- a/public/static/js/frontend-websocket.go +++ /dev/null @@ -1,74 +0,0 @@ -package main - -import ( - "honnef.co/go/js/dom" - "github.com/gopherjs/websocket/websocketjs" - "github.com/gopherjs/gopherjs/js" - "github.com/johanbrandhorst/gopherjs-json" - "time" - //"honnef.co/go/js/dom" - -) - -var ( - //d = dom.GetWindow().Document() //getting the dom to manipulate it - document = dom.GetWindow().Document().(dom.HTMLDocument) - //conn = func(){websocketjs.New("ws://192.168.1.141:8000/websocket")}//creating a global JS websocket connection -) - - -func main(){ - document.AddEventListener("DOMContentLoaded", false, func(_ dom.Event){ - println("DOMLoaded...") - go ready() - }) -} - -func ready(){ - - //conn := conn() - conn, err := websocketjs.New("ws://192.168.1.141:8000/websocket") // Blocks until connection is established. - - if err != nil { - println("Error creating client websocket connection") // handle error - } - onOpen := func(ev *js.Object){ - err := conn.Send("ping!") //on startup send the ping message - if err != nil { - println("Cannot send ping message") - } - } - - onMessage := func(ev *js.Object){ - messageData := ev.Get("data").String() - if messageData == "pong"{ //if the server says a pong, send a ping back - time.Sleep(6 * time.Second) - conn.Send("ping") - } else { - clientData, err := json.Unmarshal(messageData) - if err != nil { - println("Error unmarshalling server message") - } - - println(clientData.String()) - - } - } - - onClose := func(ev *js.Object){ - println("Closing Connection....") - } - - - onError := func(ev *js.Object){ - println("Error....") - } - - conn.AddEventListener("open", false, onOpen) - conn.AddEventListener("message", false, onMessage) - conn.AddEventListener("close", false, onClose) - conn.AddEventListener("error", false, onError) - - - err = conn.Close() -} \ No newline at end of file diff --git a/public/static/js/includes.go b/public/static/js/includes.go deleted file mode 100644 index 9b85bf79..00000000 --- a/public/static/js/includes.go +++ /dev/null @@ -1,102 +0,0 @@ -d := dom.GetWindow().Document() //getting the dom to manipulate it - -logTextArea := d.GetElementByID("loggerData") - -torrentLinkSubmit := d.GetElementByID("torrentLinkSubmit") -magnetLink := d.GetElementByID("magnetLink") - -addTorrentModal := d.GetElementByID("addTorrentModal") -addTorrentLinkBtn := d.GetElementByID("addTorrentLink") // Get the button that opens the modal - -addTorrentFileModal := d.GetElementByID("addTorrentFile") -addTorrentFileModalClose := d.GetElementsByClassName("addTorrentFileModalClose") - -addTorrentModalClose := d.GetElementsByClassName("addTorrentModalClose") // Get the element that closes the modal - - - -//add magnet link modal -addTorrentLinkBtn.AddEventListener("click", false, func(event dom.Event){ - addTorrentModal.SetAttribute("display", "block") - -}) -//close torrent link modal -addTorrentModalClose[0].AddEventListener("click", false, func(event dom.Event){ - addTorrentModal.SetAttribute("display", "none") -}) -//show torrent file modal -addTorrentFileModal.AddEventListener("click", false, func(event dom.Event){ - addTorrentFileModal.SetAttribute("display", "block") -}) -//hide torrent file modal -addTorrentFileModalClose[0].AddEventListener("click", false, func(event dom.Event){ - addTorrentFileModal.SetAttribute("display", "none") -}) - -// When the user clicks anywhere outside of the modal, close it -d.AddEventListener("click", false, func(event dom.Event){ - addTorrentModal.SetAttribute("display", "none") - addTorrentLinkBtn.SetAttribute("display", "none") -}) - - - -//websocket logic -conn, err := websocketjs.New("ws://192.168.1.141:8000/websocket") // Blocks until connection is established. -if err != nil { - println("Error creating client websocket connection") // handle error -} - -onOpen := func(ev *js.Object){ - err := conn.Send("ping!") //on startup send the ping message - if err != nil { - println("Cannot send ping message") - } -} - -onMessage := func(ev *js.Object){ - messageData := ev.Get("data").String() - if messageData == "pong"{ //if the server says a pong, send a ping back - time.Sleep(6 * time.Second) - conn.Send("ping") - } else { - clientData, err := json.Unmarshal(messageData) - if err != nil { - println("Error unmarshalling server message") - } - - logTextArea.SetInnerHTML(logTextArea.InnerHTML() + "
" + "Client Update Event....") - logTextArea.SetInnerHTML(logTextArea.InnerHTML() + "
" + clientData.String()) - - } -} - -onClose := func(ev *js.Object){ - logTextArea.SetInnerHTML(logTextArea.InnerHTML() + "
" + "Connection closed") -} - - -onError := func(ev *js.Object){ - logTextArea.SetInnerHTML(logTextArea.InnerHTML() + "
" + "Error opening websocket") -} - -conn.AddEventListener("open", false, onOpen) -conn.AddEventListener("message", false, onMessage) -conn.AddEventListener("close", false, onClose) -conn.AddEventListener("error", false, onError) - - -err = conn.Close() - -torrentLinkSubmit.AddEventListener("click", false, func(event dom.Event){ //listening to the submit button for magnet link - - - - conn.Send(magnetLink.TextContent()) - logTextArea.SetInnerHTML(logTextArea.InnerHTML() + "
" + "Adding Magnet Link: " + magnetLink.TextContent()) //adding the magnet link to the log - addTorrentModal.SetAttribute("display", "none") - magnetLink.SetTextContent("") - - }) - -} \ No newline at end of file diff --git a/public/static/js/kickwebsocket.js b/public/static/js/kickwebsocket.js index 7f71bb87..68a754be 100644 --- a/public/static/js/kickwebsocket.js +++ b/public/static/js/kickwebsocket.js @@ -1,7 +1,12 @@ var ws = new WebSocket("ws://192.168.1.141:8000/websocket"); //creating websocket +var kickStart = { + messageType: "torrentListRequest" +} + ws.onopen = function() { - ws.send("clientUpdateRequest"); //sending out the first ping - console.log("Kicking off websocket to server on 192.168.1.141.....") + + ws.send(JSON.stringify(kickStart)); //sending out the first ping + console.log("Kicking off websocket to server on 192.168.1.141.....", JSON.stringify(kickStart)) }; \ No newline at end of file diff --git a/public/static/js/tabControl.js b/public/static/js/tabControl.js deleted file mode 100644 index e3d2416b..00000000 --- a/public/static/js/tabControl.js +++ /dev/null @@ -1,13 +0,0 @@ -function openTab(evt, tabName) { - var i, x, tablinks; - x = document.getElementsByClassName("tab"); - for (i = 0; i < x.length; i++) { - x[i].style.display = "none"; - } - tablinks = document.getElementsByClassName("tablink"); - for (i = 0; i < x.length; i++) { - tablinks[i].className = tablinks[i].className.replace(" activeButton", ""); - } - document.getElementById(tabName).style.display = "block"; - evt.currentTarget.className += " activeButton"; -} diff --git a/public/static/js/websocket.js b/public/static/js/websocket.js deleted file mode 100644 index a8910252..00000000 --- a/public/static/js/websocket.js +++ /dev/null @@ -1,65 +0,0 @@ -function myWebsocketStart() -{ - - var torrentLinkSubmit = document.getElementById('torrentLinkSubmit'); - var magnetLink = document.getElementById('magnetLink'); - var addTorrentModal = document.getElementById('addTorrentModal'); - var myTextArea = document.getElementById("loggerData"); - var torrentHash = document.getElementById("hash"); - - - var ws = new WebSocket("ws://192.168.1.141:8000/websocket"); //creating websocket - - ws.onopen = function() - { - // Web Socket is connected, send data using send() - ws.send("ping"); - - myTextArea.innerHTML = myTextArea.innerHTML + "
" + "First message sent"; - }; - - ws.onmessage = function (evt) - { - var myTextArea = document.getElementById("loggerData"); - if(evt.data == "pong") { - setTimeout(function(){ws.send("ping");}, 2000); - } else { - - var clientUpdate = JSON.parse(evt.data); - myTextArea.innerHTML = myTextArea.innerHTML + "
" + "Client Update Event..."; - //myTextArea.innerHTML = myTextArea.innerHTML + "
" + clientUpdate.LocalTorrentInfo.DateAdded; - myTextArea.innerHTML = myTextArea.innerHTML + "
" + evt.data; - //myTextArea.innerHTML = myTextArea.innerHTML + "
" + clientUpdate[0].TorrentHashString; - - //torrentHash.innerHTML = "Hash: " + clientUpdate[0].TorrentHashString; - - - - } - }; - - ws.onclose = function() - { - var myTextArea = document.getElementById("loggerData"); - myTextArea.innerHTML = myTextArea.innerHTML + "
" + "Connection closed"; - }; - - - torrentLinkSubmit.onclick = function(e) { - e.preventDefault(); - - var magnetLinkjs = magnetLink.value; - - ws.send(magnetLinkjs); - myTextArea.innerHTML = myTextArea.innerHTML + "
Send:" + magnetLinkjs - addTorrentModal.style.display = "none"; - magnetLink.value = ''; - } - - -} - -function sendEvent(message) -{ - ws.send(message); -} diff --git a/settings/settings.go b/settings/settings.go index 7c049f68..7a9afa21 100644 --- a/settings/settings.go +++ b/settings/settings.go @@ -1,4 +1,4 @@ -package settings +package engine import ( "github.com/anacrolix/dht" diff --git a/storage/storage.go b/storage/storage.go index 03ab57f6..87d19bca 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -16,6 +16,7 @@ type TorrentLocal struct { TorrentStatus string TorrentType string //magnet or .torrent file TorrentFileName string + Label string //for labeling torrent files } //ReadInTorrents is called to read in ALL local stored torrents in the boltdb database (called on server restart) @@ -55,7 +56,7 @@ func ReadInTorrents(torrentStorage *bolt.DB) (torrentLocalArray []*TorrentLocal) } TorrentStatus = b.Get([]byte("TorrentStatus")) if TorrentStatus == nil { - fmt.Println("Torrent Status not found in local storage") + //fmt.Println("Torrent Status not found in local storage") TorrentStatus = []byte("") } TorrentType = b.Get([]byte("TorrentType")) @@ -77,7 +78,7 @@ func ReadInTorrents(torrentStorage *bolt.DB) (torrentLocalArray []*TorrentLocal) torrentLocal.TorrentType = string(TorrentType) torrentLocal.TorrentFileName = string(TorrentFileName) - fmt.Println("Torrentlocal list: ", torrentLocal) + //fmt.Println("Torrentlocal list: ", torrentLocal) torrentLocalArray = append(torrentLocalArray, torrentLocal) //dumping it into the array return nil }) @@ -137,3 +138,63 @@ func DelTorrentLocalStorage(torrentStorage *bolt.DB, local *TorrentLocal) { }) } + +//FetchTorrentFromStorage grabs the localtorrent info from the bolt database for usage found my torrenthash +func FetchTorrentFromStorage(torrentStorage *bolt.DB, selectedHash []byte) TorrentLocal { + singleTorrentInfo := TorrentLocal{} + torrentStorage.View(func(tx *bolt.Tx) error { + b := tx.Bucket(selectedHash) + var Dateadded []byte + var StoragePath []byte + var Hash []byte + var TorrentName []byte + var TorrentStatus []byte + var TorrentType []byte + var TorrentFileName []byte + Dateadded = b.Get([]byte("Date")) + if Dateadded == nil { + fmt.Println("Date added error!") + Dateadded = []byte(time.Now().Format("Jan _2 2006")) + } + StoragePath = b.Get([]byte("StoragePath")) + if StoragePath == nil { + fmt.Println("StoragePath error!") + StoragePath = []byte("downloads") + } + Hash = b.Get([]byte("InfoHash")) + if Hash == nil { + fmt.Println("Hash error!") + } + TorrentName = b.Get([]byte("TorrentName")) + if TorrentName == nil { + fmt.Println("Torrent Name not found") + TorrentName = []byte("Not Found!") + } + TorrentStatus = b.Get([]byte("TorrentStatus")) + if TorrentStatus == nil { + //fmt.Println("Torrent Status not found in local storage") + TorrentStatus = []byte("") + } + TorrentType = b.Get([]byte("TorrentType")) + if TorrentType == nil { + fmt.Println("Torrent Type not found in local storage") + TorrentStatus = []byte("") + } + TorrentFileName = b.Get([]byte("TorrentFileName")) + if TorrentFileName == nil { + fmt.Println("Torrent File Name not found in local storage") + TorrentFileName = []byte("") + } + + singleTorrentInfo.DateAdded = string(Dateadded) + singleTorrentInfo.StoragePath = string(StoragePath) + singleTorrentInfo.Hash = string(Hash) //Converting the byte slice back into the full hash + singleTorrentInfo.TorrentName = string(TorrentName) + singleTorrentInfo.TorrentStatus = string(TorrentStatus) + singleTorrentInfo.TorrentType = string(TorrentType) + singleTorrentInfo.TorrentFileName = string(TorrentFileName) + + return nil + }) + return singleTorrentInfo +} diff --git a/torrent-project/src/BackendComm/backendWebsocket.js b/torrent-project/src/BackendComm/backendWebsocket.js index e1d505e0..1c5295be 100644 --- a/torrent-project/src/BackendComm/backendWebsocket.js +++ b/torrent-project/src/BackendComm/backendWebsocket.js @@ -14,45 +14,58 @@ var title = document.title; //Set the number of active torrents in the title let torrents= []; - +var torrentListRequest = { + messageType: "torrentListRequest" +} //websocket is started in kickwebsocket.js and is picked up here so "ws" is already defined 22 ws.onmessage = function (evt) { //When we recieve a message from the websocket - if(evt.data == "clientUpdate") { - console.log("Client Update Incoming...") - } else { // recieving data + var serverMessage = JSON.parse(evt.data) + if (serverMessage.MessageType == "torrentList"){ console.log("Recieved Client Update...") - var clientUpdate = JSON.parse(evt.data); - if (clientUpdate.total) { // if it has a total field it is a torrentlist update - torrents = []; //clearing out the torrent array to make room for new (so that it does keep adding) - for(var i = 0; i < clientUpdate.total; i++){ - torrents.push({ - TorrentHashString: clientUpdate.data[i].TorrentHash, - TorrentName: clientUpdate.data[i].TorrentName, - DownloadedSize: clientUpdate.data[i].DownloadedSize, - Size: clientUpdate.data[i].Size, - DownloadSpeed: clientUpdate.data[i].DownloadSpeed, - UploadSpeed: clientUpdate.data[i].UploadSpeed, - PercentDone: clientUpdate.data[i].PercentDone, - StoragePath: clientUpdate.data[i].StoragePath, - DateAdded: clientUpdate.data[i].DateAdded, - Status: clientUpdate.data[i].Status, - BytesCompleted: clientUpdate.data[i].BytesCompleted, - ActivePeers: clientUpdate.data[i].ActivePeers, - ETA: clientUpdate.data[i].ETA, - }) - } - var newTitle = '(' + clientUpdate.total + ')' + title; //updating the title - document.title = newTitle; - } else if (clientUpdate) { + //var serverMessage = JSON.parse(evt.data); + + torrents = []; //clearing out the torrent array to make room for new (so that it does keep adding) + for(var i = 0; i < serverMessage.total; i++){ + torrents.push({ + TorrentHashString: serverMessage.data[i].TorrentHash, + TorrentName: serverMessage.data[i].TorrentName, + DownloadedSize: serverMessage.data[i].DownloadedSize, + Size: serverMessage.data[i].Size, + DownloadSpeed: serverMessage.data[i].DownloadSpeed, + UploadSpeed: serverMessage.data[i].UploadSpeed, + PercentDone: serverMessage.data[i].PercentDone, + StoragePath: serverMessage.data[i].StoragePath, + DateAdded: serverMessage.data[i].DateAdded, + Status: serverMessage.data[i].Status, + BytesCompleted: serverMessage.data[i].BytesCompleted, + ActivePeers: serverMessage.data[i].ActivePeers, + ETA: serverMessage.data[i].ETA, + }) + } + var newTitle = '(' + serverMessage.total + ')' + title; //updating the title + document.title = newTitle; + } else if (serverMessage.MessageType == "fileList"){ + console.log("Recieved FileListUpdate", serverMessage.fileList) + fileList = []; + for (var i = 0; i < serverMessage.total; i++){ + fileList.push({ + FileList: serverMessage.fileList[i] + + + }) } - + + + } + } + ws.onclose = function() { console.log('Closing connection') }; @@ -76,19 +89,15 @@ class BackendSocket extends React.Component { 2000 ); - } + } componentWillUnmount() { clearInterval(this.timerID); } tick() { - ws.send("clientUpdateRequest")//talking to the server to get the torrent list - this.props.newTorrentList(torrents) - - //console.log("STATE:", this.state.torrentList) - //console.log("Torrents", torrents); - + ws.send(JSON.stringify(torrentListRequest))//talking to the server to get the torrent list + this.props.newTorrentList(torrents) } render() { diff --git a/torrent-project/src/addTorrentLinkModal.js b/torrent-project/src/addTorrentLinkModal.js index 31843e51..ac3341fe 100644 --- a/torrent-project/src/addTorrentLinkModal.js +++ b/torrent-project/src/addTorrentLinkModal.js @@ -16,6 +16,8 @@ import Icon from 'material-ui/Icon'; import IconButton from 'material-ui/IconButton'; + + const button = { fontSize: '60px', paddingRight: '20px', @@ -29,6 +31,8 @@ const inlineStyle = { export default class addTorrentPopup extends React.Component { + + state = { open: false, }; @@ -43,9 +47,13 @@ export default class addTorrentPopup extends React.Component { handleSubmit = () => { this.setState({ open: false }); - let magnetLinkSubmit = this.state.textValue; - console.log("Sending magnet link: ", magnetLinkSubmit); - ws.send(magnetLinkSubmit); + //let magnetLinkSubmit = this.state.textValue; + let magnetLinkMessage = { + messageType: "magnetLinkSubmit", + Payload: { MagnetLink: this.state.textValue} + } + console.log("Sending magnet link: ", magnetLinkMessage); + ws.send(JSON.stringify(magnetLinkMessage)); } setTextValue = (event) => { diff --git a/torrent-project/src/topMenu.js b/torrent-project/src/topMenu.js index 10684825..0b8a9876 100644 --- a/torrent-project/src/topMenu.js +++ b/torrent-project/src/topMenu.js @@ -21,7 +21,6 @@ import ReactTooltip from 'react-tooltip' import DeleteIcon from 'material-ui-icons/Delete'; import AddShoppingCartIcon from 'material-ui-icons/AddShoppingCart'; -//import PhotoCamera from 'material-ui-icons/PhotoCamera'; import BackendSocket from './BackendComm/backendWebsocket'; @@ -63,12 +62,22 @@ const styles = theme => ({ - class IconButtons extends React.Component { constructor(props){ super(props); } + + startTorrentState = { + messageType: "startTorrents", + Payload: this.props.selection, + } + + + startTorrent = (selection) => { + console.log("Starting Torrents", selection) + ws.send() + } buttonHandler = (buttonState) => { console.log("BUTTONSTATE", buttonState) @@ -128,12 +137,13 @@ IconButtons.propTypes = { const mapStateToProps = state => { return { buttonState: state.buttonState, + selection: state.selection, }; } const mapDispatchToProps = dispatch => { return { - changeSelection: (selection) => dispatch({type: actionTypes.CHANGE_SELECTION, selection: selection}) + //changeSelection: (selection) => dispatch({type: actionTypes.CHANGE_SELECTION, selection: selection}) } } diff --git a/torrent-project/src/torrentlist.js b/torrent-project/src/torrentlist.js index 1aa858e4..0a390a28 100644 --- a/torrent-project/src/torrentlist.js +++ b/torrent-project/src/torrentlist.js @@ -95,12 +95,9 @@ class TorrentListTable extends React.Component { this.props.changeSelection(selection) //dispatch selection to redux if (selection.length === 0) { //if selection is empty buttons will be default - console.log("No Selection") this.props.setButtonState(this.props.buttonStateDefault) //if no selection dispatch that to redux } else { // if we have selection continue on with logic to determine button state - const selectedRows = [] //array of all the selected Rows - selection.forEach(element => { selectedRows.push(this.props.torrentList[element]) //pushing the selected rows out of torrentlist });