Added the Files tab, fixed peer tab, started adding functionality for the buttons, cleaned up general tab
This commit is contained in:
@@ -15,21 +15,6 @@ type Message struct {
|
||||
Payload []string
|
||||
}
|
||||
|
||||
//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
|
||||
@@ -42,8 +27,8 @@ type TorrentList struct { //helps create the JSON structure that react expects t
|
||||
//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"`
|
||||
TotalFiles int `json:"TotalFiles"`
|
||||
FileList []TorrentFile `json:"FileList"`
|
||||
}
|
||||
|
||||
//PeerFileList returns a slice of peers
|
||||
@@ -53,30 +38,40 @@ type PeerFileList struct {
|
||||
PeerList []torrent.Peer `json:"PeerList"`
|
||||
}
|
||||
|
||||
//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:"StoragePath"`
|
||||
DateAdded string
|
||||
KnownSwarm []torrent.Peer
|
||||
Status string `json:"Status"`
|
||||
BytesCompleted int64
|
||||
UpdatedAt time.Time
|
||||
UploadRatio string
|
||||
AddedAt string
|
||||
ETA string `json:"ETA"`
|
||||
Label string
|
||||
SourceType string `json:"SourceType"`
|
||||
//TorrentFile describes a single file that a torrent client is downloading for a single torrent
|
||||
type TorrentFile struct {
|
||||
TorrentHashString string //Used to tie the file to a torrent //TODO not sure if neededs
|
||||
FileName string
|
||||
FilePath string
|
||||
FileSize string
|
||||
FilePercent string
|
||||
FilePriority string
|
||||
}
|
||||
|
||||
//ClientDB struct contains the struct that is used to compose the torrentlist
|
||||
type ClientDB struct { //TODO maybe seperate out the internal bits into another client struct
|
||||
TorrentHashString string `json:"TorrentHashString"` //Passed to client for displaying hash and is used to uniquly identify all torrents
|
||||
TorrentName string `json:"TorrentName"`
|
||||
DownloadedSize string `json:"DownloadedSize"` //how much the client has downloaded total
|
||||
Size string `json:"Size"` //total size of the torrent
|
||||
DownloadSpeed string `json:"DownloadSpeed"` //the dl speed of the torrent
|
||||
Status string `json:"Status"` //Passed to client for display
|
||||
PercentDone string `json:"PercentDone"` //Passed to client to show percent done
|
||||
ActivePeers string `json:"ActivePeers"` //passed to client
|
||||
UploadSpeed string `json:"UploadSpeed"` //passed to client to show Uploadspeed
|
||||
StoragePath string `json:"StoragePath"` //Passed to client (and stored in stormdb)
|
||||
DateAdded string //Passed to client (and stored in stormdb)
|
||||
ETA string `json:"ETA"` //Passed to client
|
||||
Label string //Passed to client and stored in stormdb
|
||||
SourceType string `json:"SourceType"` //Stores whether the torrent came from a torrent file or a magnet link
|
||||
KnownSwarm []torrent.Peer //Passed to client for Peer Tab
|
||||
UploadRatio string //Passed to client, stores the string for uploadratio stored in stormdb
|
||||
TotalUploadedSize string //Humanized version of TotalUploadedBytes to pass to the client
|
||||
TotalUploadedBytes int64 //includes bytes that happened before reboot (from stormdb)
|
||||
downloadSpeedInt int64 //Internal used for calculating dl speed
|
||||
BytesCompleted int64 //Internal used for calculating the dl speed
|
||||
DataBytesWritten int64 //Internal used for calculating dl speed
|
||||
DataBytesRead int64 //Internal used for calculating dl speed
|
||||
UpdatedAt time.Time //Internal used for calculating speeds of upload and download
|
||||
TorrentHash metainfo.Hash //Used to create string for TorrentHashString... not sure why I have it... make that a TODO I guess
|
||||
}
|
||||
|
@@ -3,12 +3,13 @@ package engine //main file for all the calculations and data gathering needed fo
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/torrent"
|
||||
"github.com/anacrolix/torrent/metainfo"
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/asdine/storm"
|
||||
Storage "github.com/deranjer/goTorrent/storage"
|
||||
)
|
||||
|
||||
@@ -20,7 +21,7 @@ func timeOutInfo(clientTorrent *torrent.Torrent, seconds time.Duration) (deleted
|
||||
}()
|
||||
select {
|
||||
case <-clientTorrent.GotInfo(): //attempting to retrieve info for torrent
|
||||
//fmt.Println("Recieved torrent info for...", clientTorrent.Name())
|
||||
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
|
||||
@@ -32,7 +33,7 @@ func timeOutInfo(clientTorrent *torrent.Torrent, seconds time.Duration) (deleted
|
||||
}
|
||||
|
||||
//StartTorrent creates the storage.db entry and starts A NEW 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) {
|
||||
func StartTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage Storage.TorrentLocal, torrentDbStorage *storm.DB, dataDir string, torrentFile string, torrentFileName string) {
|
||||
|
||||
timeOutInfo(clientTorrent, 45) //seeing if adding the torrrent times out (giving 45 seconds)
|
||||
var TempHash metainfo.Hash
|
||||
@@ -55,7 +56,7 @@ func StartTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage *Storage.T
|
||||
}
|
||||
|
||||
//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) {
|
||||
func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Storage.TorrentLocal, PreviousTorrentArray []ClientDB, config FullClientSettings, db *storm.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
|
||||
|
||||
@@ -94,17 +95,12 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
}
|
||||
}
|
||||
}
|
||||
activePeersString := fmt.Sprintf("%v", fullStruct.ActivePeers) //converting to strings
|
||||
activePeersString := strconv.Itoa(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()
|
||||
|
||||
singleTorrentStorageInfo := Storage.FetchTorrentFromStorage(db, []byte(TempHash.String())) //fetching all the info from the database
|
||||
singleTorrentStorageInfo := Storage.FetchTorrentFromStorage(db, TempHash.String()) //fetching all the info from the database
|
||||
var torrentTypeTemp string
|
||||
torrentTypeTemp = singleTorrentStorageInfo.TorrentType //either "file" or "magnet" maybe more in the future
|
||||
if torrentTypeTemp == "file" {
|
||||
@@ -112,16 +108,19 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
} else {
|
||||
fullClientDB.SourceType = "Magnet Link"
|
||||
}
|
||||
fullClientDB.StoragePath = singleTorrentStorageInfo.StoragePath //grabbed from database
|
||||
|
||||
fullClientDB.StoragePath = singleTorrentStorageInfo.StoragePath
|
||||
totalSizeHumanized := HumanizeBytes(float32(singleTorrent.BytesCompleted())) //convert size to GB if needed
|
||||
downloadedSizeHumanized := HumanizeBytes(float32(singleTorrent.Length()))
|
||||
|
||||
fullClientDB.DownloadedSize = dSize
|
||||
fullClientDB.Size = tSize
|
||||
PercentDone := fmt.Sprintf("%.2f", bytesCompletedMB/totalSizeMB)
|
||||
//grabbed from torrent client
|
||||
fullClientDB.DownloadedSize = downloadedSizeHumanized
|
||||
fullClientDB.Size = totalSizeHumanized
|
||||
PercentDone := fmt.Sprintf("%.2f", float32(singleTorrent.BytesCompleted())/float32(singleTorrent.Length()))
|
||||
fullClientDB.TorrentHash = TempHash
|
||||
fullClientDB.PercentDone = PercentDone
|
||||
fullClientDB.DataBytesRead = fullStruct.ConnStats.DataBytesRead
|
||||
fullClientDB.DataBytesWritten = fullStruct.ConnStats.DataBytesWritten
|
||||
fullClientDB.DataBytesRead = fullStruct.ConnStats.DataBytesRead //used for calculations not passed to client calculating up/down speed
|
||||
fullClientDB.DataBytesWritten = fullStruct.ConnStats.DataBytesWritten //used for calculations not passed to client calculating up/down speed
|
||||
fullClientDB.ActivePeers = activePeersString + " / (" + totalPeersString + ")"
|
||||
fullClientDB.TorrentHashString = TempHash.String()
|
||||
fullClientDB.StoragePath = element.StoragePath
|
||||
@@ -130,21 +129,21 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
fullClientDB.BytesCompleted = singleTorrent.BytesCompleted()
|
||||
CalculateTorrentETA(singleTorrent, fullClientDB) //calculating the ETA for the torrent
|
||||
|
||||
fullClientDB.UploadRatio = CalculateUploadRatio(singleTorrent, fullClientDB, db) //calculate the upload ratio
|
||||
tickUpdateStruct := Storage.TorrentLocal{} //we are shoving the tick updates into a torrentlocal struct to pass to storage
|
||||
fullClientDB.TotalUploadedBytes = singleTorrentStorageInfo.UploadedBytes
|
||||
fullClientDB.TotalUploadedSize = HumanizeBytes(float32(fullClientDB.TotalUploadedBytes))
|
||||
fullClientDB.UploadRatio = CalculateUploadRatio(singleTorrent, fullClientDB) //calculate the upload ratio
|
||||
tickUpdateStruct := Storage.TorrentLocal{} //we are shoving the tick updates into a torrentlocal struct to pass to storage
|
||||
tickUpdateStruct.UploadRatio = fullClientDB.UploadRatio
|
||||
tickUpdateStruct.UploadedBytes = fullClientDB.DataBytesWritten
|
||||
tickUpdateStruct.Hash = fullClientDB.TorrentHashString
|
||||
|
||||
tickUpdateStruct.Hash = fullClientDB.TorrentHashString //needed for index
|
||||
|
||||
Storage.UpdateStorageTick(db, tickUpdateStruct)
|
||||
//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
|
||||
}
|
||||
|
||||
@@ -152,12 +151,23 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
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{}
|
||||
TorrentFileStruct := TorrentFile{}
|
||||
for _, singleTorrent := range runningTorrents {
|
||||
tempHash := singleTorrent.InfoHash().String()
|
||||
if tempHash == selectedHash { // if our selection hash equals our torrent hash
|
||||
TorrentFileListSelected.FileList = singleTorrent.Files()
|
||||
torrentFilesRaw := singleTorrent.Files()
|
||||
for _, singleFile := range torrentFilesRaw {
|
||||
TorrentFileStruct.TorrentHashString = tempHash
|
||||
TorrentFileStruct.FileName = singleFile.DisplayPath()
|
||||
TorrentFileStruct.FilePath = singleFile.Path()
|
||||
TorrentFileStruct.FilePercent = fmt.Sprintf("%.2f", float32(singleFile.Length())/float32(singleFile.Length())) //TODO figure out downloaded size of file
|
||||
TorrentFileStruct.FilePriority = "Normal" //TODO, figure out how to store this per file in storage and also tie a priority to a file
|
||||
TorrentFileStruct.FileSize = HumanizeBytes(float32(singleFile.Length()))
|
||||
TorrentFileListSelected.FileList = append(TorrentFileListSelected.FileList, TorrentFileStruct)
|
||||
}
|
||||
TorrentFileListSelected.MessageType = "torrentFileList"
|
||||
TorrentFileListSelected.TotalFiles = len(singleTorrent.Files())
|
||||
fmt.Println("filelist", TorrentFileListSelected)
|
||||
return TorrentFileListSelected
|
||||
}
|
||||
|
||||
@@ -183,9 +193,9 @@ func CreatePeerListArray(tclient *torrent.Client, selectedHash string) PeerFileL
|
||||
}
|
||||
|
||||
//CreateTorrentDetailJSON creates the json response for a request for more torrent information
|
||||
func CreateTorrentDetailJSON(tclient *torrent.Client, selectedHash string, torrentStorage *bolt.DB) ClientDB {
|
||||
func CreateTorrentDetailJSON(tclient *torrent.Client, selectedHash string, torrentStorage *storm.DB) ClientDB {
|
||||
|
||||
localTorrentInfo := Storage.FetchTorrentFromStorage(torrentStorage, []byte(selectedHash))
|
||||
localTorrentInfo := Storage.FetchTorrentFromStorage(torrentStorage, selectedHash)
|
||||
|
||||
runningTorrents := tclient.Torrents()
|
||||
|
||||
|
@@ -5,7 +5,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/torrent"
|
||||
"github.com/boltdb/bolt"
|
||||
)
|
||||
|
||||
func secondsToMinutes(inSeconds int64) string {
|
||||
@@ -17,34 +16,22 @@ func secondsToMinutes(inSeconds int64) string {
|
||||
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
|
||||
//HumanizeBytes returns a nice humanized version of bytes in either GB or MB
|
||||
func HumanizeBytes(bytes float32) string {
|
||||
if bytes < 1000000 { //if we have less than 1MB in bytes convert to KB
|
||||
pBytes := fmt.Sprintf("%.2f", bytes/1024)
|
||||
pBytes = pBytes + " KB"
|
||||
return pBytes
|
||||
}
|
||||
bytes = bytes / 1024 / 1024 //Converting bytes to a useful measure
|
||||
if bytes > 1024 {
|
||||
pBytes := fmt.Sprintf("%.2f", bytes/1024)
|
||||
pBytes = pBytes + " GB"
|
||||
return pBytes
|
||||
}
|
||||
pBytes := fmt.Sprintf("%.2f", bytes) //If not too big or too small leave it as MB
|
||||
pBytes = pBytes + " MB"
|
||||
return pBytes
|
||||
}
|
||||
|
||||
//CalculateTorrentSpeed is used to calculate the torrent upload and download speed over time c is current clientdb, oc is last client db to calculate speed over time
|
||||
@@ -56,9 +43,6 @@ func CalculateTorrentSpeed(t *torrent.Torrent, c *ClientDB, oc ClientDB) {
|
||||
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
|
||||
@@ -90,18 +74,18 @@ func CalculateTorrentETA(t *torrent.Torrent, c *ClientDB) {
|
||||
}
|
||||
}
|
||||
|
||||
func CalculateUploadRatio(t *torrent.Torrent, c *ClientDB, db *bolt.DB) string {
|
||||
if c.DataBytesWritten > 0 {
|
||||
uploadRatioTemp := c.DataBytesRead / c.DataBytesWritten
|
||||
uploadRatio := fmt.Sprintf("%.2f", uploadRatioTemp)
|
||||
//CalculateUploadRatio calculates the download to upload ratio so you can see if you are being a good seeder
|
||||
func CalculateUploadRatio(t *torrent.Torrent, c *ClientDB) string {
|
||||
if c.TotalUploadedBytes > 0 && t.BytesCompleted() > 0 { //If we have actually started uploading and downloading stuff start calculating our ratio
|
||||
uploadRatio := fmt.Sprintf("%.2f", float64(c.TotalUploadedBytes)/float64(t.BytesCompleted()))
|
||||
return uploadRatio
|
||||
}
|
||||
uploadRatio := fmt.Sprintf("%.2f", 0.00) //we haven't uploaded anything so no upload ratio
|
||||
uploadRatio := "0.00" //we haven't uploaded anything so no upload ratio just pass a string directly
|
||||
return uploadRatio
|
||||
}
|
||||
|
||||
//CalculateTorrentStatus is used to determine what the STATUS column of the frontend will display ll2
|
||||
func CalculateTorrentStatus(t *torrent.Torrent, c *ClientDB) {
|
||||
func CalculateTorrentStatus(t *torrent.Torrent, c *ClientDB) { //TODO redo all of this to allow for stopped torrents
|
||||
if t.Seeding() && t.Stats().ActivePeers > 0 && t.BytesMissing() == 0 {
|
||||
c.Status = "Seeding"
|
||||
} else if t.Stats().ActivePeers > 0 && t.BytesMissing() > 0 {
|
||||
|
29
main.go
29
main.go
@@ -12,7 +12,8 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/anacrolix/torrent"
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/asdine/storm"
|
||||
//"github.com/boltdb/bolt"
|
||||
Engine "github.com/deranjer/goTorrent/engine"
|
||||
Storage "github.com/deranjer/goTorrent/storage"
|
||||
"github.com/gorilla/mux"
|
||||
@@ -43,18 +44,18 @@ func updateClient(torrentstats []Engine.ClientDB, conn *websocket.Conn) { //get
|
||||
|
||||
func main() {
|
||||
//setting up the torrent client
|
||||
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
|
||||
Config := Engine.FullClientSettingsNew() //grabbing from settings.go
|
||||
os.Mkdir(Config.TFileUploadFolder, os.ModeDir) //creating a directory to store uploaded torrent files
|
||||
torrentLocalStorage := Storage.TorrentLocal{} //creating a new struct that stores all of our local storage info
|
||||
|
||||
fmt.Printf("%+v\n", Config)
|
||||
//fmt.Printf("%+v\n", Config)
|
||||
|
||||
tclient, err := torrent.NewClient(&Config.Config) //pulling out the torrent specific config to use
|
||||
if err != nil {
|
||||
log.Fatalf("error creating client: %s", err)
|
||||
}
|
||||
|
||||
db, err := bolt.Open("storage.db", 0600, nil) //initializing the boltDB store that contains all the added torrents
|
||||
db, err := storm.Open("storage.db") //initializing the boltDB store that contains all the added torrents
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -128,11 +129,11 @@ func main() {
|
||||
fmt.Println("Unable to read JSON client message", err)
|
||||
}
|
||||
|
||||
//fmt.Println("MessageFull", msg)
|
||||
fmt.Println("MessageFull", msg)
|
||||
switch msg.MessageType { //first handling data requests
|
||||
|
||||
case "torrentListRequest":
|
||||
fmt.Println("client Requested TorrentList Update")
|
||||
//fmt.Println("client Requested TorrentList Update")
|
||||
TorrentLocalArray = Storage.ReadInTorrents(db)
|
||||
RunningTorrentArray = Engine.CreateRunningTorrentArray(tclient, TorrentLocalArray, PreviousTorrentArray, Config, db) //Updates the RunningTorrentArray with the current client data as well
|
||||
PreviousTorrentArray = RunningTorrentArray
|
||||
@@ -150,6 +151,7 @@ func main() {
|
||||
fmt.Println("client Requested Filelist update")
|
||||
FileListArray := Engine.CreateFileListArray(tclient, msg.Payload[0])
|
||||
conn.WriteJSON(FileListArray) //writing the JSON to the client
|
||||
|
||||
break
|
||||
|
||||
case "torrentDetailedInfo": //TODO Figure out how to get single torrent info correctly
|
||||
@@ -170,9 +172,7 @@ func main() {
|
||||
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([]byte(msg.Payload[0]), &magnetMessage) //unmarshalling the "Payload" from Message into our magnetmessage struct
|
||||
clientTorrent, err := tclient.AddMagnet(magnetMessage.MagnetLink) //reading the payload into the torrent client
|
||||
clientTorrent, err := tclient.AddMagnet(msg.Payload[0]) //reading the payload into the torrent client
|
||||
if err != nil {
|
||||
fmt.Println("Magnet Error", err)
|
||||
}
|
||||
@@ -183,13 +183,13 @@ func main() {
|
||||
break
|
||||
|
||||
case "stopTorrents":
|
||||
TorrentListCommands := Engine.TorrentCommandMessage{}
|
||||
TorrentListCommands := msg.Payload
|
||||
for _, singleTorrent := range runningTorrents {
|
||||
|
||||
for _, singleSelection := range TorrentListCommands.TorrentHashStrings {
|
||||
for _, singleSelection := range TorrentListCommands {
|
||||
if singleTorrent.InfoHash().String() == singleSelection {
|
||||
fmt.Println("Matched for stopping torrents")
|
||||
//singleTorrent.Drop()
|
||||
singleTorrent.SetMaxEstablishedConns(0) //Forcing the max amount of connections allowed to zero effectively stopping it
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,6 +202,7 @@ func main() {
|
||||
if singleTorrent.InfoHash().String() == singleSelection {
|
||||
fmt.Println("Matched for deleting torrents")
|
||||
singleTorrent.Drop()
|
||||
//Storage.DelTorrentLocalStorage(db)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
BIN
storage - Copy.db
Normal file
BIN
storage - Copy.db
Normal file
Binary file not shown.
@@ -1,17 +1,14 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
binary "encoding/binary"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/asdine/storm"
|
||||
)
|
||||
|
||||
//TODO, this entire file need to be rewritten to encode and decode from the struct
|
||||
//TorrentLocal is local storage of the torrents for readd on server restart
|
||||
//TorrentLocal is local storage of the torrents for readd on server restart, marshalled into the database using Storm
|
||||
type TorrentLocal struct {
|
||||
Hash string
|
||||
Hash string `storm:"id,unique"` //Hash should be unique for every torrent... if not we are re-adding an already added torrent \\TODO check for re-add of same torrent
|
||||
DateAdded string
|
||||
StoragePath string
|
||||
TorrentName string
|
||||
@@ -25,204 +22,56 @@ type TorrentLocal struct {
|
||||
}
|
||||
|
||||
//ReadInTorrents is called to read in ALL local stored torrents in the boltdb database (called on server restart)
|
||||
func ReadInTorrents(torrentStorage *bolt.DB) (torrentLocalArray []*TorrentLocal) { //test
|
||||
|
||||
torrentLocalArray = []*TorrentLocal{}
|
||||
|
||||
torrentStorage.View(func(tx *bolt.Tx) error {
|
||||
|
||||
tx.ForEach(func(name []byte, b *bolt.Bucket) error {
|
||||
torrentLocal := new(TorrentLocal) //create a struct to store to an array //TODO clean this the fuck up just read the struct into something that converts them all the byte arrays
|
||||
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("")
|
||||
}
|
||||
|
||||
torrentLocal.DateAdded = string(Dateadded)
|
||||
torrentLocal.StoragePath = string(StoragePath)
|
||||
torrentLocal.Hash = string(Hash) //Converting the byte slice back into the full hash
|
||||
torrentLocal.TorrentName = string(TorrentName)
|
||||
torrentLocal.TorrentStatus = string(TorrentStatus)
|
||||
torrentLocal.TorrentType = string(TorrentType)
|
||||
torrentLocal.TorrentFileName = string(TorrentFileName)
|
||||
|
||||
//fmt.Println("Torrentlocal list: ", torrentLocal)
|
||||
torrentLocalArray = append(torrentLocalArray, torrentLocal) //dumping it into the array
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
})
|
||||
func ReadInTorrents(torrentStorage *storm.DB) (torrentLocalArray []*TorrentLocal) {
|
||||
err := torrentStorage.Init(&TorrentLocal{}) //initializing buckets and indexes since this function runs on start
|
||||
if err != nil {
|
||||
fmt.Println("Error initializing and indexing database....", err)
|
||||
}
|
||||
torrentLocalArray = []*TorrentLocal{} //creating the array of the torrentlocal struct
|
||||
|
||||
err = torrentStorage.All(&torrentLocalArray) //unmarshalling the database into the []torrentlocal
|
||||
if err != nil {
|
||||
fmt.Println("Error reading database into torrentLocalArray", err)
|
||||
}
|
||||
return torrentLocalArray //all done, return the entire Array to add to the torrent client
|
||||
}
|
||||
|
||||
//AddTorrentLocalStorage is called when adding a new torrent via any method, requires the boltdb pointer and the torrentlocal struct
|
||||
func AddTorrentLocalStorage(torrentStorage *bolt.DB, local *TorrentLocal) {
|
||||
func AddTorrentLocalStorage(torrentStorage *storm.DB, local TorrentLocal) {
|
||||
println("Adding Local storage information")
|
||||
|
||||
torrentStorage.Update(func(tx *bolt.Tx) error {
|
||||
b, err := tx.CreateBucketIfNotExists([]byte(local.Hash)) //translating hash into bytes for storage
|
||||
if err != nil {
|
||||
return fmt.Errorf("create bucket %s", err)
|
||||
}
|
||||
err = b.Put([]byte("Date"), []byte(local.DateAdded)) //TODO error checking marshall into JSON
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = b.Put([]byte("StoragePath"), []byte(local.StoragePath))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = b.Put([]byte("InfoHash"), []byte(local.Hash))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = b.Put([]byte("TorrentName"), []byte(local.TorrentName))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = b.Put([]byte("TorrentType"), []byte(local.TorrentType))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = b.Put([]byte("TorrentFileName"), []byte(local.TorrentFileName))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = b.Put([]byte("UploadRatio"), []byte(local.UploadRatio))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
err := torrentStorage.Save(&local)
|
||||
if err != nil {
|
||||
fmt.Println("Error adding new Torrent to database", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//DelTorrentLocalStorage is called to delete a torrent when we fail (for whatever reason to load the information for it). Deleted by HASH matching.
|
||||
func DelTorrentLocalStorage(torrentStorage *bolt.DB, local *TorrentLocal) {
|
||||
func DelTorrentLocalStorage(torrentStorage *storm.DB, local *TorrentLocal) { //TODO do a ONE and purge the torrent that way
|
||||
println("Deleting torrent", local.TorrentFileName)
|
||||
|
||||
torrentStorage.Update(func(tx *bolt.Tx) error {
|
||||
err := tx.DeleteBucket([]byte(local.Hash))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
err := torrentStorage.DeleteStruct(&local)
|
||||
if err != nil {
|
||||
fmt.Println("Error deleting torrent from database", err)
|
||||
}
|
||||
}
|
||||
|
||||
//UpdateStorageTick updates the values in boltdb that should update on every tick (like uploadratio or uploadedbytes, not downloaded since we should have the actual file)
|
||||
func UpdateStorageTick(torrentStorage *bolt.DB, torrentLocal TorrentLocal) {
|
||||
UploadedBytes := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(UploadedBytes, uint64(torrentLocal.UploadedBytes)) //converting int64 into byte slice for storage
|
||||
selectedHash := []byte(torrentLocal.Hash)
|
||||
torrentStorage.Update(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(selectedHash)
|
||||
err := b.Put([]byte("UploadRatio"), []byte(torrentLocal.UploadRatio))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = b.Put([]byte("UploadedBytes"), []byte(UploadedBytes))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
func UpdateStorageTick(torrentStorage *storm.DB, torrentLocal TorrentLocal) {
|
||||
err := torrentStorage.Update(&torrentLocal)
|
||||
if err != nil {
|
||||
fmt.Println("Error performing tick update to database", err)
|
||||
}
|
||||
}
|
||||
|
||||
//FetchTorrentFromStorage grabs the localtorrent info from the bolt database for usage found by torrenthash
|
||||
func FetchTorrentFromStorage(torrentStorage *bolt.DB, selectedHash []byte) TorrentLocal {
|
||||
func FetchTorrentFromStorage(torrentStorage *storm.DB, selectedHash string) 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("")
|
||||
}
|
||||
err := torrentStorage.One("Hash", selectedHash, &singleTorrentInfo)
|
||||
if err != nil {
|
||||
fmt.Println("Failure selecting single torrent!", err)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@ import Select from 'material-ui/Select/Select';
|
||||
var title = document.title; //Set the number of active torrents in the title
|
||||
let torrents= [];
|
||||
let peerList = [];
|
||||
let fileList = [];
|
||||
|
||||
var torrentListRequest = {
|
||||
messageType: "torrentListRequest"
|
||||
@@ -23,7 +24,7 @@ var 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
|
||||
var serverMessage = JSON.parse(evt.data)
|
||||
//console.log("message", serverMessage.MessageType)
|
||||
console.log("message", serverMessage.MessageType)
|
||||
switch (serverMessage.MessageType) {
|
||||
|
||||
case "torrentList":
|
||||
@@ -42,11 +43,13 @@ ws.onmessage = function (evt) { //When we recieve a message from the websocket
|
||||
PercentDone: serverMessage.data[i].PercentDone,
|
||||
StoragePath: serverMessage.data[i].StoragePath,
|
||||
DateAdded: serverMessage.data[i].DateAdded,
|
||||
SourceType: serverMessage.data[i].SourceType,
|
||||
Status: serverMessage.data[i].Status,
|
||||
BytesCompleted: serverMessage.data[i].BytesCompleted,
|
||||
ActivePeers: serverMessage.data[i].ActivePeers,
|
||||
ETA: serverMessage.data[i].ETA,
|
||||
Ratio: serverMessage.data[i].Ratio,
|
||||
TotalUploadedSize: serverMessage.data[i].TotalUploadedSize,
|
||||
Ratio: serverMessage.data[i].UploadRatio,
|
||||
})
|
||||
}
|
||||
var newTitle = '(' + serverMessage.total + ')' + title; //updating the title
|
||||
@@ -70,16 +73,18 @@ ws.onmessage = function (evt) { //When we recieve a message from the websocket
|
||||
break
|
||||
|
||||
case "torrentFileList":
|
||||
console.log("Recieved FileListUpdate", serverMessage.fileList)
|
||||
console.log("Recieved FileListUpdate", evt.data)
|
||||
fileList = [];
|
||||
for (var i = 0; i < serverMessage.total; i++){
|
||||
for (var i = 0; i < serverMessage.TotalFiles; i++){
|
||||
fileList.push({
|
||||
fileList: serverMessage.fileList[i]
|
||||
|
||||
|
||||
FileName: serverMessage.FileList[i].FileName,
|
||||
FilePath: serverMessage.FileList[i].FilePath,
|
||||
FileSize: serverMessage.FileList[i].FileSize,
|
||||
FilePercent: serverMessage.FileList[i].FilePercent,
|
||||
FilePriority: serverMessage.FileList[i].FilePriority,
|
||||
})
|
||||
}
|
||||
|
||||
console.log("filelist", fileList)
|
||||
break
|
||||
|
||||
case "speedTab":
|
||||
@@ -123,11 +128,16 @@ class BackendSocket extends React.Component {
|
||||
MessageType: "torrentPeerListRequest",
|
||||
Payload: selectionHashes,
|
||||
}
|
||||
//console.log("Peers tab information requested", peerListHashes)
|
||||
console.log("Peers tab information requested", peerListHashes)
|
||||
ws.send(JSON.stringify(peerListHashes))
|
||||
break;
|
||||
case 2:
|
||||
console.log("Files tab information requested")
|
||||
let fileListHashes = {
|
||||
MessageType: "torrentFileListRequest",
|
||||
Payload: selectionHashes,
|
||||
}
|
||||
console.log("Files tab information requested", fileListHashes)
|
||||
ws.send(JSON.stringify(fileListHashes))
|
||||
break;
|
||||
case 3:
|
||||
console.log("Speed tab information requested")
|
||||
@@ -166,13 +176,28 @@ class BackendSocket extends React.Component {
|
||||
ws.send(JSON.stringify(torrentListRequest))//talking to the server to get the torrent list
|
||||
console.log("Torrentlist", torrents)
|
||||
this.props.newTorrentList(torrents) //sending the list of torrents to torrentlist.js
|
||||
if (this.props.selectedTab === 1 && this.props.selectionHashes.length === 1){ //if we are on the peerlist tab dispatch a new peerlist
|
||||
let peerListHashes = {
|
||||
MessageType: "torrentPeerListRequest",
|
||||
Payload: this.props.selectionHashes,
|
||||
if (this.props.selectionHashes.length === 1){
|
||||
switch(this.props.selectedTab){
|
||||
case 1:
|
||||
let peerListHashes = {
|
||||
MessageType: "torrentPeerListRequest",
|
||||
Payload: this.props.selectionHashes,
|
||||
}
|
||||
ws.send(JSON.stringify(peerListHashes))
|
||||
this.props.newPeerList(peerList)
|
||||
break;
|
||||
case 2:
|
||||
let fileListHashes = {
|
||||
MessageType: "torrentFileListRequest",
|
||||
Payload: this.props.selectionHashes,
|
||||
}
|
||||
console.log("Files tab information requested", fileList)
|
||||
ws.send(JSON.stringify(fileListHashes))
|
||||
this.props.newFileList(fileList)
|
||||
break;
|
||||
|
||||
}
|
||||
ws.send(JSON.stringify(peerListHashes))
|
||||
this.props.newPeerList(peerList)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +238,8 @@ const mapStateToProps = state => {
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
newTorrentList: (torrentList) => dispatch({type: actionTypes.TORRENT_LIST, torrentList }),
|
||||
newPeerList: (peerList) => dispatch({type: actionTypes.PEER_LIST, peerList})
|
||||
newPeerList: (peerList) => dispatch({type: actionTypes.PEER_LIST, peerList}),
|
||||
newFileList: (fileList) => dispatch({type: actionTypes.FILE_LIST, fileList}),
|
||||
}
|
||||
}
|
||||
|
||||
|
69
torrent-project/src/BottomMenu/Tabs/fileTab.js
Normal file
69
torrent-project/src/BottomMenu/Tabs/fileTab.js
Normal file
@@ -0,0 +1,69 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import {BootstrapTable, TableHeaderColumn} from 'react-bootstrap-table';
|
||||
|
||||
import {
|
||||
SortingState, LocalSorting, VirtualTableLayout, SelectionState,
|
||||
} from '@devexpress/dx-react-grid';
|
||||
|
||||
import {
|
||||
Grid, TableView, TableHeaderRow, PagingPanel, VirtualTableView, TableColumnResizing,
|
||||
DragDropContext, TableColumnReordering,
|
||||
} from '@devexpress/dx-react-grid-material-ui';
|
||||
|
||||
|
||||
import {connect} from 'react-redux';
|
||||
import * as actionTypes from '../../store/actions';
|
||||
|
||||
|
||||
class FileTab extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { //rows are stored in redux they are sent over from the server
|
||||
columns: [
|
||||
{ name: 'FileName', title: 'File Name'},
|
||||
{ name: 'FilePath', title: 'File Path' },
|
||||
{ name: 'FileSize', title: 'File Size'},
|
||||
//{ name: 'Country', title: 'Country of Origin'}, //TODO map IP to country
|
||||
{ name: 'FilePercent', title: 'File Percent'},
|
||||
{ name: 'FilePriority', title: 'File Priority'}, //T=Tracker, I=Incoming, Hg=DHTGetPeers, Ha=DHTAnnouncePeer, X=PEX
|
||||
],
|
||||
sorting: [],
|
||||
columnOrder: ['FileName', 'FilePath', 'FileSize', 'FilePercent', 'FilePriority'],
|
||||
columnWidths: {FileName: 250, FilePath: 450, FileSize: 100, FilePercent: 100, FilePriority: 75},
|
||||
};
|
||||
|
||||
this.changeColumnOrder = columnOrder => this.setState({columnOrder});
|
||||
this.changeColumnWidths = columnWidths => this.setState({columnWidths});
|
||||
this.changeSorting = sorting => this.setState({sorting});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Grid rows={this.props.fileList} columns={this.state.columns}>
|
||||
<SortingState sorting={this.state.sorting} onSortingChange={this.changeSorting} />
|
||||
<LocalSorting />
|
||||
<DragDropContext />
|
||||
<TableView />
|
||||
<TableColumnResizing columnWidths={this.state.columnWidths} onColumnWidthsChange={this.changeColumnWidths}/>
|
||||
<TableColumnReordering order={this.state.columnOrder} onOrderChange={this.changeColumnOrder} />
|
||||
<TableHeaderRow allowSorting allowResizing allowDragging />
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
selectionHashes: state.selectionHashes,
|
||||
fileList: state.fileList,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(FileTab)
|
@@ -64,7 +64,7 @@ class GeneralTab extends React.Component {
|
||||
<Paper className={classes.paper}>Storage Path: <span className={classes.floatRight}>{this.state.selectedTorrent["StoragePath"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Date Added: <span className={classes.floatRight}> {this.state.selectedTorrent["DateAdded"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Source Type: <span className={classes.floatRight}> {this.state.selectedTorrent["SourceType"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Label: <span className={classes.floatRight}> {this.state.selectedTorrent["Status"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Label: <span className={classes.floatRight}> None </span> </Paper>
|
||||
<Paper className={classes.paper}>Torrent Hash: <span className={classes.floatRight}> {this.state.selectedTorrent["TorrentHashString"]} </span> </Paper>
|
||||
|
||||
</Grid>
|
||||
@@ -72,10 +72,9 @@ class GeneralTab extends React.Component {
|
||||
<Paper className={classes.paper}>Status: <span className={classes.floatRight}>{this.state.selectedTorrent["Status"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Percent Done: <span className={classes.floatRight}>{this.state.selectedTorrent["PercentDone"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Torrent DL Amount: <span className={classes.floatRight}>{this.state.selectedTorrent["DownloadedSize"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Total Upload Amount: <span className={classes.floatRight}>{this.state.selectedTorrent["Status"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Seeding Ratio: <span className={classes.floatRight}>{this.state.selectedTorrent["Status"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Total Upload Amount: <span className={classes.floatRight}>{this.state.selectedTorrent["TotalUploadedSize"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Seeding Ratio: <span className={classes.floatRight}>{this.state.selectedTorrent["Ratio"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>ETA: <span className={classes.floatRight}>{this.state.selectedTorrent["ETA"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Status: <span className={classes.floatRight}>{this.state.selectedTorrent["Status"]} </span> </Paper>
|
||||
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
|
@@ -6,6 +6,7 @@ import AppBar from 'material-ui/AppBar';
|
||||
import Tabs, { Tab } from 'material-ui/Tabs';
|
||||
import GeneralTab from './Tabs/generalTab';
|
||||
import PeerTab from './Tabs/peerTab';
|
||||
import FileTab from './Tabs/fileTab';
|
||||
|
||||
|
||||
//Redux
|
||||
@@ -57,7 +58,7 @@ function TabContainer(props) {
|
||||
</div>
|
||||
{this.props.selectedTab === 0 && <TabContainer><GeneralTab /></TabContainer>}
|
||||
{this.props.selectedTab === 1 && <TabContainer><PeerTab /></TabContainer>}
|
||||
{this.props.selectedTab === 2 && <TabContainer>Files</TabContainer>}
|
||||
{this.props.selectedTab === 2 && <TabContainer><FileTab /></TabContainer>}
|
||||
{this.props.selectedTab === 3 && <TabContainer>Speed</TabContainer>}
|
||||
{this.props.selectedTab === 4 && <TabContainer>Logger</TabContainer>}
|
||||
</div>
|
||||
|
@@ -50,7 +50,7 @@ export default class addTorrentPopup extends React.Component {
|
||||
//let magnetLinkSubmit = this.state.textValue;
|
||||
let magnetLinkMessage = {
|
||||
messageType: "magnetLinkSubmit",
|
||||
Payload: { MagnetLink: this.state.textValue}
|
||||
Payload: [this.state.textValue]
|
||||
}
|
||||
console.log("Sending magnet link: ", magnetLinkMessage);
|
||||
ws.send(JSON.stringify(magnetLinkMessage));
|
||||
|
@@ -131,12 +131,12 @@ class SimpleList extends React.Component {
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Seeding Torrents" />
|
||||
</ListItem>
|
||||
<ListItem className={this.state.activeTorrentsClass} button={true} onClick={ () => this.setFilter('Active', this.state.activeID)}>
|
||||
{/* <ListItem className={this.state.activeTorrentsClass} button={true} onClick={ () => this.setFilter('Active', this.state.activeID)}>
|
||||
<ListItemIcon className={classes.icons}>
|
||||
<ActiveTorrentsIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText primary="Active Torrents" />
|
||||
</ListItem>
|
||||
</ListItem> */}
|
||||
<ListItem className={this.state.completedTorrentsClass} button={true} onClick={ () => this.setFilter('Completed', this.state.completedID)}>
|
||||
<ListItemIcon className={classes.inactiveIcon}>
|
||||
<ActiveTorrentsIcon />
|
||||
|
@@ -6,3 +6,4 @@ export const SET_BUTTON_STATE = 'BUTTON_STATE';
|
||||
export const SELECTION_HASHES = 'SELECTION_HASHES';
|
||||
export const SELECTED_TAB = 'SELECTED_TAB';
|
||||
export const PEER_LIST = 'PEER_LIST';
|
||||
export const FILE_LIST = 'FILE_LIST';
|
@@ -3,8 +3,8 @@ import * as actionTypes from './actions';
|
||||
|
||||
|
||||
const initialState = {
|
||||
buttonStateDefault: [{startButton: "default", pauseButton: "default", stopButton: "default", deleteButton: "default", fSeedButton: "default", fRecheckButton: "default"}],
|
||||
buttonState: [{startButton: "default", pauseButton: "default", stopButton: "default", deleteButton: "default", fSeedButton: "default", fRecheckButton: "default"}],
|
||||
buttonStateDefault: [{startButton: "default", stopButton: "default", deleteButton: "default", fSeedButton: "default", fRecheckButton: "default"}],
|
||||
buttonState: [{startButton: "default", stopButton: "default", deleteButton: "default", fSeedButton: "default", fRecheckButton: "default"}],
|
||||
sorting: [],
|
||||
selection: [],
|
||||
selectionHashes: [],
|
||||
@@ -12,6 +12,7 @@ const initialState = {
|
||||
columnName: "Status",
|
||||
torrentList: [],
|
||||
peerList: [],
|
||||
fileList: [],
|
||||
torrentDetailInfo: [],
|
||||
selectedTab: 0,
|
||||
}
|
||||
@@ -56,6 +57,13 @@ const reducer = (state = initialState, action) => {
|
||||
...state,
|
||||
peerList: action.peerList
|
||||
}
|
||||
|
||||
case actionTypes.FILE_LIST:
|
||||
console.log("FILELIST REDUX......", action.fileList)
|
||||
return {
|
||||
...state,
|
||||
fileList: action.fileList
|
||||
}
|
||||
|
||||
case actionTypes.SET_BUTTON_STATE:
|
||||
return {
|
||||
|
@@ -10,7 +10,7 @@ import AddTorrentFilePopup from './addTorrentFileModal';
|
||||
|
||||
|
||||
import StartTorrentIcon from 'material-ui-icons/PlayArrow';
|
||||
import PauseTorrentIcon from 'material-ui-icons/Pause';
|
||||
//import PauseTorrentIcon from 'material-ui-icons/Pause';
|
||||
import StopTorrentIcon from 'material-ui-icons/Stop';
|
||||
import DeleteTorrentIcon from 'material-ui-icons/Delete';
|
||||
import RSSTorrentIcon from 'material-ui-icons/RssFeed';
|
||||
@@ -70,7 +70,7 @@ class IconButtons extends React.Component {
|
||||
|
||||
|
||||
startTorrent = () => {
|
||||
console.log("Starting Torrents", selection)
|
||||
console.log("Starting Torrents", this.props.selectionHashes)
|
||||
let startTorrentHashes = {
|
||||
MessageType: "startTorrents",
|
||||
Payload: this.props.selectionHashes,
|
||||
@@ -79,17 +79,26 @@ class IconButtons extends React.Component {
|
||||
ws.send(JSON.stringify(startTorrentHashes))
|
||||
}
|
||||
|
||||
buttonHandler = (buttonState) => {
|
||||
console.log("BUTTONSTATE", buttonState)
|
||||
stopTorrent = () => {
|
||||
let stopTorrentHashes = {
|
||||
MessageType: "stopTorrents",
|
||||
Payload: this.props.selectionHashes,
|
||||
}
|
||||
console.log("Stopping Torrents", stopTorrentHashes)
|
||||
ws.send(JSON.stringify(stopTorrentHashes))
|
||||
}
|
||||
|
||||
componentWillReceiveProps = (nextProps) => { //if we get a new buttonstate force a button update
|
||||
if (this.props.buttonState != nextProps.buttonState){
|
||||
this.buttonHandler(nextProps.buttonState)
|
||||
deleteTorrent = () => {
|
||||
|
||||
let deleteTorrentHashes = {
|
||||
MessageType: "deleteTorrents",
|
||||
Payload: this.props.selectionHashes,
|
||||
}
|
||||
console.log("B1State", this.props.buttonState[0].startButton)
|
||||
console.log("Deleting Torrents", deleteTorrentHashes)
|
||||
ws.send(JSON.stringify(deleteTorrentHashes))
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
return (
|
||||
@@ -101,15 +110,15 @@ class IconButtons extends React.Component {
|
||||
<ReactTooltip place="top" type="light" effect="float" />
|
||||
<StartTorrentIcon />
|
||||
</IconButton>
|
||||
<IconButton color={this.props.buttonState[0].pauseButton} data-tip="Pause Torrent" className={classes.button} aria-label="Pause Torrent">
|
||||
{/* <IconButton color={this.props.buttonState[0].pauseButton} data-tip="Pause Torrent" className={classes.button} aria-label="Pause Torrent">
|
||||
<ReactTooltip place="top" type="light" effect="float" />
|
||||
<PauseTorrentIcon />
|
||||
</IconButton>
|
||||
<IconButton color={this.props.buttonState[0].stopButton} data-tip="Stop Torrent" className={classes.button} aria-label="Stop Torrent">
|
||||
</IconButton> */}
|
||||
<IconButton color={this.props.buttonState[0].stopButton} data-tip="Stop Torrent" className={classes.button} onClick={this.stopTorrent} aria-label="Stop Torrent">
|
||||
<ReactTooltip place="top" type="light" effect="float" />
|
||||
<StopTorrentIcon />
|
||||
</IconButton>
|
||||
<IconButton color={this.props.buttonState[0].deleteButton} data-tip="Delete Torrent" className={classes.button} aria-label="Delete Torrent">
|
||||
<IconButton color={this.props.buttonState[0].deleteButton} data-tip="Delete Torrent" className={classes.button} onClick={this.deleteTorrent} aria-label="Delete Torrent">
|
||||
<ReactTooltip place="top" type="error" effect="float" />
|
||||
<DeleteTorrentIcon />
|
||||
</IconButton>
|
||||
|
@@ -4,7 +4,7 @@ import styles from '../node_modules/react-bootstrap-table/dist/react-bootstrap-t
|
||||
import {BootstrapTable, TableHeaderColumn} from 'react-bootstrap-table';
|
||||
|
||||
import {
|
||||
SortingState, LocalSorting, PagingState, VirtualTableLayout, SelectionState, FilteringState, LocalFiltering,
|
||||
SortingState, LocalSorting, PagingState, VirtualTableLayout, SelectionState, FilteringState,
|
||||
} from '@devexpress/dx-react-grid';
|
||||
|
||||
import {
|
||||
@@ -57,10 +57,9 @@ class TorrentListTable extends React.Component {
|
||||
{ name: 'ETA', title: 'ETA'},
|
||||
{ name: 'Ratio', title: 'Ratio'},
|
||||
{ name: 'Availability', title: 'Availability'},
|
||||
{ name: 'TorrentHashString', title: 'Torrent Hash' }
|
||||
],
|
||||
columnOrder: ['TorrentName', 'DownloadedSize', 'Size', 'PercentDone', 'Status', 'DownloadSpeed', 'UploadSpeed','ActivePeers', 'ETA', 'Ratio', 'Availability', 'TorrentHashString'],
|
||||
columnWidths: {TorrentName: 250, DownloadedSize: 100, Size: 100, PercentDone: 175, Status: 150, DownloadSpeed: 100, UploadSpeed: 100, ActivePeers: 100, ETA: 100, Ratio: 75, Availability: 75, TorrentHashString: 250,},
|
||||
columnOrder: ['TorrentName', 'DownloadedSize', 'Size', 'PercentDone', 'Status', 'DownloadSpeed', 'UploadSpeed','ActivePeers', 'ETA', 'Ratio', 'Availability'],
|
||||
columnWidths: {TorrentName: 250, DownloadedSize: 100, Size: 100, PercentDone: 175, Status: 150, DownloadSpeed: 100, UploadSpeed: 100, ActivePeers: 100, ETA: 100, Ratio: 75, Availability: 75},
|
||||
prevSelection: [], //just used to pull data from cell (temp Prevcell holder), real selection is in Redux
|
||||
};
|
||||
|
||||
@@ -90,10 +89,10 @@ class TorrentListTable extends React.Component {
|
||||
determineButtonState = (selectedRows) => { //TODO run a filter to corrently determing button status... currently broken
|
||||
selectedRows.forEach(element => {
|
||||
if (element.Status === "Downloading" || "Awaiting Peers" || "Seeding") {
|
||||
let buttonState = [{startButton: "default", pauseButton: "primary", stopButton: "primary", deleteButton: "accent", fSeedButton: "default", fRecheckButton: "primary"}]
|
||||
let buttonState = [{startButton: "default", stopButton: "primary", deleteButton: "accent", fSeedButton: "default", fRecheckButton: "primary"}]
|
||||
this.props.setButtonState(buttonState)
|
||||
} else if (element.Status === "Completed") {
|
||||
let buttonState = [{startButton: "default", pauseButton: "default", stopButton: "default", deleteButton: "accent", fSeedButton: "primary", fRecheckButton: "primary"}]
|
||||
let buttonState = [{startButton: "default", stopButton: "default", deleteButton: "accent", fSeedButton: "primary", fRecheckButton: "primary"}]
|
||||
this.props.setButtonState(buttonState)
|
||||
} else {
|
||||
this.props.setButtonState(this.props.buttonStateDefault)
|
||||
@@ -121,12 +120,8 @@ class TorrentListTable extends React.Component {
|
||||
|
||||
filterHandler = (filter) => { //TODO, figure out how to do multiple filter
|
||||
console.log("Changing FIlter", filter)
|
||||
console.log("Filter Value", filter[0].value)
|
||||
if (filter[0].value === 'Active') {
|
||||
console.log("Active Filter")
|
||||
values = ['Seeding', 'Downloading'].includes
|
||||
this.props.filter == [{columnName: 'Status', value: values}]
|
||||
return['Downloading', 'Seeding'].includes(row[filter.columnName]);
|
||||
if (filter.value ==="Active"){
|
||||
console.log("This filter doesn't fucking work")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +132,6 @@ class TorrentListTable extends React.Component {
|
||||
<SortingState sorting={this.props.sorting} onSortingChange={this.props.changeSorting} />
|
||||
<LocalSorting />
|
||||
<FilteringState filters={this.props.filter} />
|
||||
<LocalFiltering />
|
||||
<SelectionState onSelectionChange={this.changeSelection} selection={this.props.selection}/>
|
||||
<TableView tableCellTemplate={({ row, column, style }) => {
|
||||
if (column.name === 'PercentDone') {
|
||||
|
Reference in New Issue
Block a user