closes #9, closes #8, closes #3, closes #4, added new notification features, search torrents, change directory, force seed torrent, updated Readme

This commit is contained in:
2018-02-03 14:22:21 -05:00
parent 3ab66456a1
commit 0abe1620c6
13 changed files with 125 additions and 135 deletions

View File

@@ -26,11 +26,19 @@ Image of the frontend UI
- Automatic stop after seeding ratio reached - Automatic stop after seeding ratio reached
- Pushbullet notification on torrent complete - Pushbullet notification on torrent complete
- Automatic move of completed torrent to new directory (leave symlink behind for seeding) - Automatic move of completed torrent to new directory (leave symlink behind for seeding)
- Doesn't work on Windows yet, have to copy file for now - Symlinks don't work on Windows yet, have to copy file for now
## Roadmap ## Roadmap
- Early-Mid 2018 - Early-Mid 2018
- [X] Ability to modify storage path of torrent after it has been added
- [X] Backend to frontend notification messages
- [X] Global Rate Limiting for Upload/Download Speed
- [X] Add torrents from watch folder (cron job every 5 minutes)
- [ ] Unit testing completed for a large portion of the package - [ ] Unit testing completed for a large portion of the package
- [ ] Stability/bug fixing/Optimization rewrite of some of the core structures of the WebUI and base server - [ ] Stability/bug fixing/Optimization rewrite of some of the core structures of the WebUI and base server
@@ -40,8 +48,8 @@ Image of the frontend UI
- [ ] Ability to set priority for individual files (just added to anacrolix/torrent so coming soon, already added to my UI) - [ ] Ability to set priority for individual files (just added to anacrolix/torrent so coming soon, already added to my UI)
- [ ] Ability to view TOML settings from WebUI (and perhaps change a few as well) - [ ] Ability to view TOML settings from WebUI (and perhaps change a few as well)
- [ ] Ability to modify storage path of torrent after it has been added - [ ] Authentication from client to server
- Late 2018 - Late 2018
@@ -96,6 +104,12 @@ The `config.toml` file contains all of the settings for the server part of the a
SeedRatioStop = 1.50 #automatically stops the torrent after it reaches this seeding ratio SeedRatioStop = 1.50 #automatically stops the torrent after it reaches this seeding ratio
#Relative or absolute path accepted, the server will convert any relative path to an absolute path. #Relative or absolute path accepted, the server will convert any relative path to an absolute path.
DefaultMoveFolder = 'downloaded' #default path that a finished torrent is symlinked to after completion. Torrents added via RSS will default here DefaultMoveFolder = 'downloaded' #default path that a finished torrent is symlinked to after completion. Torrents added via RSS will default here
TorrentWatchFolder = 'torrentUpload' #folder path that is watched for .torrent files and adds them automatically every 5 minutes
#Limits your upload and download speed globally, all are averages and not burst protected (usually burst on start).
#Low = ~.05MB/s, Medium = ~.5MB/s, High = ~1.5MB/s
UploadRateLimit = "Unlimited" #Options are "Low", "Medium", "High", "Unlimited" #Unlimited is default
DownloadRateLimit = "Unlimited"
[notifications] [notifications]

View File

@@ -3,7 +3,7 @@
ServerPort = ":8000" #leave format as is it expects a string with colon ServerPort = ":8000" #leave format as is it expects a string with colon
ServerAddr = "" #blank will bind to default IP address, usually fine to leave be ServerAddr = "" #blank will bind to default IP address, usually fine to leave be
LogLevel = "Info" # Options = Debug, Info, Warn, Error, Fatal, Panic LogLevel = "Warn" # Options = Debug, Info, Warn, Error, Fatal, Panic
LogOutput = "file" #Options = file, stdout #file will print it to logs/server.log LogOutput = "file" #Options = file, stdout #file will print it to logs/server.log
SeedRatioStop = 1.50 #automatically stops the torrent after it reaches this seeding ratio SeedRatioStop = 1.50 #automatically stops the torrent after it reaches this seeding ratio
@@ -19,7 +19,7 @@
[notifications] [notifications]
PushBulletToken = "o.QW6G7F6FUOKXCUKmw948fBceCUn0msFi" #add your pushbullet api token here to notify of torrent completion to pushbullet PushBulletToken = "" #add your pushbullet api token here to notify of torrent completion to pushbullet
[EncryptionPolicy] [EncryptionPolicy]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View File

@@ -2,6 +2,7 @@ package engine
import ( import (
"io/ioutil" "io/ioutil"
"os"
"path/filepath" "path/filepath"
"github.com/anacrolix/torrent" "github.com/anacrolix/torrent"
@@ -46,9 +47,9 @@ func CheckTorrentWatchFolder(c *cron.Cron, db *storm.DB, tclient *torrent.Client
continue continue
} }
//os.Remove(fullFilePathAbs) //delete the torrent after adding it and copying it over os.Remove(fullFilePathAbs) //delete the torrent after adding it and copying it over
Logger.WithFields(logrus.Fields{"Source Folder": fullFilePathAbs, "Destination Folder": fullNewFilePathAbs, "Torrent": file.Name()}).Info("Added torrent from watch folder, and moved torrent file") Logger.WithFields(logrus.Fields{"Source Folder": fullFilePathAbs, "Destination Folder": fullNewFilePathAbs, "Torrent": file.Name()}).Info("Added torrent from watch folder, and moved torrent file")
StartTorrent(clientTorrent, torrentLocalStorage, db, config.TorrentConfig.DataDir, "file", file.Name(), config.DefaultMoveFolder, "default", config.TFileUploadFolder) StartTorrent(clientTorrent, torrentLocalStorage, db, "file", fullNewFilePathAbs, config.DefaultMoveFolder, "default", config)
} }
} }
@@ -84,7 +85,7 @@ func RefreshRSSCron(c *cron.Cron, db *storm.DB, tclient *torrent.Client, torrent
Logger.WithFields(logrus.Fields{"err": err, "Torrent": RSSTorrent.Title}).Warn("Unable to add torrent to torrent client!") Logger.WithFields(logrus.Fields{"err": err, "Torrent": RSSTorrent.Title}).Warn("Unable to add torrent to torrent client!")
break //break out of the loop entirely for this message since we hit an error break //break out of the loop entirely for this message since we hit an error
} }
StartTorrent(clientTorrent, torrentLocalStorage, db, config.TorrentConfig.DataDir, "magnet", "", config.DefaultMoveFolder, "RSS", config.TFileUploadFolder) //TODO let user specify torrent default storage location and let change on fly StartTorrent(clientTorrent, torrentLocalStorage, db, "magnet", "", config.DefaultMoveFolder, "RSS", config) //TODO let user specify torrent default storage location and let change on fly
singleFeed.Torrents = append(singleFeed.Torrents, singleRSSTorrent) singleFeed.Torrents = append(singleFeed.Torrents, singleRSSTorrent)
} }

View File

@@ -1,8 +1,6 @@
package engine package engine
import ( import (
"fmt"
"io"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
@@ -20,22 +18,21 @@ func MoveAndLeaveSymlink(config FullClientSettings, tHash string, db *storm.DB,
tStorage := Storage.FetchTorrentFromStorage(db, tHash) tStorage := Storage.FetchTorrentFromStorage(db, tHash)
Logger.WithFields(logrus.Fields{"Torrent Name": tStorage.TorrentName}).Info("Move and Create symlink started for torrent") Logger.WithFields(logrus.Fields{"Torrent Name": tStorage.TorrentName}).Info("Move and Create symlink started for torrent")
var oldFilePath string var oldFilePath string
if moveDone { if moveDone { //only occurs on manual move
oldFilePathTemp := filepath.Join(oldPath, tStorage.TorrentName) oldFilePathTemp := filepath.Join(oldPath, tStorage.TorrentName)
oldFilePath, err := filepath.Abs(oldFilePathTemp) var err error
oldFilePath, err = filepath.Abs(oldFilePathTemp)
if err != nil { if err != nil {
Logger.WithFields(logrus.Fields{"Torrent Name": tStorage.TorrentName, "Filepath": oldFilePath}).Error("Cannot create absolute file path!") Logger.WithFields(logrus.Fields{"Torrent Name": tStorage.TorrentName, "Filepath": oldFilePath}).Error("Cannot create absolute file path!")
} }
fmt.Println("oldfilepath", oldFilePath)
} else { } else {
oldFilePathTemp := filepath.Join(config.TorrentConfig.DataDir, tStorage.TorrentName) oldFilePathTemp := filepath.Join(config.TorrentConfig.DataDir, tStorage.TorrentName)
oldFilePath, err := filepath.Abs(oldFilePathTemp) var err error
oldFilePath, err = filepath.Abs(oldFilePathTemp)
if err != nil { if err != nil {
Logger.WithFields(logrus.Fields{"Torrent Name": tStorage.TorrentName, "Filepath": oldFilePath}).Error("Cannot create absolute file path!") Logger.WithFields(logrus.Fields{"Torrent Name": tStorage.TorrentName, "Filepath": oldFilePath}).Error("Cannot create absolute file path!")
} }
} }
newFilePathTemp := filepath.Join(tStorage.StoragePath, tStorage.TorrentName) newFilePathTemp := filepath.Join(tStorage.StoragePath, tStorage.TorrentName)
newFilePath, err := filepath.Abs(newFilePathTemp) newFilePath, err := filepath.Abs(newFilePathTemp)
if err != nil { if err != nil {
@@ -55,70 +52,27 @@ func MoveAndLeaveSymlink(config FullClientSettings, tHash string, db *storm.DB,
} }
if oldFilePath != newFilePath { if oldFilePath != newFilePath {
if runtime.GOOS == "windows" { //TODO the windows symlink is broken on windows 10 creator edition, so doing a copy for now until Go 1.11 newFilePathDir := filepath.Dir(newFilePath)
if oldFileInfo.IsDir() { os.Mkdir(newFilePathDir, 0755)
os.Mkdir(newFilePath, 0755) err := folderCopy.Copy(oldFilePath, newFilePath) //copy the folder to the new location
if moveDone { if err != nil {
err := folderCopy.Copy(config.TorrentConfig.DataDir, newFilePath) Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath, "error": err}).Error("Error Copying Folder!")
if err != nil {
Logger.WithFields(logrus.Fields{"Old File Path": config.TorrentConfig.DataDir, "New File Path": newFilePath, "error": err}).Error("Error Copying Folder!")
}
} else {
err := folderCopy.Copy(oldFilePath, newFilePath) //copy the folder to the new location
if err != nil {
Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath, "error": err}).Error("Error Copying Folder!")
}
}
os.Chmod(newFilePath, 0777)
notifyUser(tStorage, config, db)
return
}
srcFile, err := os.Open(oldFilePath)
defer srcFile.Close()
if err != nil {
Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "error": err}).Error("Windows: Cannot open old file for copy")
return
}
destFile, err := os.Create(newFilePath)
defer destFile.Close()
if err != nil {
Logger.WithFields(logrus.Fields{"New File Path": newFilePath, "error": err}).Error("Windows: Cannot open new file for copying into")
return
}
bytesWritten, err := io.Copy(destFile, srcFile)
if err != nil {
Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath, "error": err}).Error("Windows: Cannot copy old file into new")
return
}
err = destFile.Sync()
if err != nil {
Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath, "error": err}).Error("Windows: Error syncing new file to disk")
}
Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath, "bytesWritten": bytesWritten}).Info("Windows Torrent Copy Completed")
notifyUser(tStorage, config, db)
} else {
folderCopy.Copy(oldFilePath, newFilePath)
os.Chmod(newFilePath, 0777) //changing permissions on the new file to be permissive
os.RemoveAll(oldFilePath)
if moveDone {
err := os.Symlink(newFilePath, config.TorrentConfig.DataDir)
if err != nil {
Logger.WithFields(logrus.Fields{"Old File Path": config.TorrentConfig.DataDir, "New File Path": newFilePath, "error": err}).Error("Error creating symlink")
return
}
} else {
err := os.Symlink(newFilePath, oldFilePath) //For all other OS's create a symlink
if err != nil {
Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath, "error": err}).Error("Error creating symlink")
return
}
}
notifyUser(tStorage, config, db)
Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath}).Info("Moving completed torrent")
} }
os.Chmod(newFilePath, 0777)
if runtime.GOOS != "windows" { //TODO the windows symlink is broken on windows 10 creator edition, so on the other platforms create symlink (windows will copy) until Go1.11
os.RemoveAll(oldFilePath)
err = os.Symlink(newFilePath, oldFilePath)
if err != nil {
Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath, "error": err}).Error("Error creating symlink")
}
}
if moveDone == false {
tStorage.TorrentMoved = true //TODO error handling instead of just saying torrent was moved when it was not
notifyUser(tStorage, config, db) //Only notify if we haven't moved yet, don't want to push notify user every time user uses change storage button
}
Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath}).Info("Moving completed torrent")
tStorage.StoragePath = filepath.Dir(newFilePath)
Storage.UpdateStorageTick(db, tStorage)
} }
} }

View File

@@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@@ -128,7 +127,7 @@ func readTorrentFileFromDB(element *Storage.TorrentLocal, tclient *torrent.Clien
} }
//StartTorrent creates the storage.db entry and starts A NEW TORRENT and adds to the running torrent array //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 *storm.DB, dataDir, torrentType, torrentFileName, torrentStoragePath, labelValue, tFileUploadFolder string) { func StartTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage Storage.TorrentLocal, torrentDbStorage *storm.DB, torrentType, torrentFilePathAbs, torrentStoragePath, labelValue string, config FullClientSettings) {
timedOut := timeOutInfo(clientTorrent, 45) //seeing if adding the torrent times out (giving 45 seconds) timedOut := timeOutInfo(clientTorrent, 45) //seeing if adding the torrent times out (giving 45 seconds)
if timedOut { //if we fail to add the torrent return if timedOut { //if we fail to add the torrent return
return return
@@ -147,6 +146,7 @@ func StartTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage Storage.To
torrentLocalStorage.Label = labelValue torrentLocalStorage.Label = labelValue
torrentLocalStorage.DateAdded = time.Now().Format("Jan _2 2006") torrentLocalStorage.DateAdded = time.Now().Format("Jan _2 2006")
torrentLocalStorage.StoragePath = torrentStoragePath torrentLocalStorage.StoragePath = torrentStoragePath
torrentLocalStorage.TempStoragePath = config.TorrentConfig.DataDir
torrentLocalStorage.TorrentName = clientTorrent.Name() torrentLocalStorage.TorrentName = clientTorrent.Name()
torrentLocalStorage.TorrentUploadLimit = true //by default all of the torrents will stop uploading after the global rate is set. torrentLocalStorage.TorrentUploadLimit = true //by default all of the torrents will stop uploading after the global rate is set.
torrentLocalStorage.TorrentMoved = false //by default the torrent has no been moved. torrentLocalStorage.TorrentMoved = false //by default the torrent has no been moved.
@@ -154,8 +154,6 @@ func StartTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage Storage.To
torrentLocalStorage.TorrentType = torrentType //either "file" or "magnet" maybe more in the future torrentLocalStorage.TorrentType = torrentType //either "file" or "magnet" maybe more in the future
torrentLocalStorage.TorrentSize = clientTorrent.Length() //Length will change as we cancel files so store it in DB torrentLocalStorage.TorrentSize = clientTorrent.Length() //Length will change as we cancel files so store it in DB
if torrentType == "file" { //if it is a file read the entire file into the database for us to spit out later if torrentType == "file" { //if it is a file read the entire file into the database for us to spit out later
torrentFilePath := filepath.Join(tFileUploadFolder, torrentFileName)
torrentFilePathAbs, err := filepath.Abs(torrentFilePath)
torrentfile, err := ioutil.ReadFile(torrentFilePathAbs) torrentfile, err := ioutil.ReadFile(torrentFilePathAbs)
torrentLocalStorage.TorrentFileName = torrentFilePathAbs torrentLocalStorage.TorrentFileName = torrentFilePathAbs
if err != nil { if err != nil {
@@ -236,11 +234,10 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
PercentDone := fmt.Sprintf("%.2f", float32(singleTorrent.BytesCompleted())/float32(singleTorrentFromStorage.TorrentSize)) PercentDone := fmt.Sprintf("%.2f", float32(singleTorrent.BytesCompleted())/float32(singleTorrentFromStorage.TorrentSize))
fullClientDB.TorrentHash = TempHash fullClientDB.TorrentHash = TempHash
fullClientDB.PercentDone = PercentDone fullClientDB.PercentDone = PercentDone
fullClientDB.DataBytesRead = fullStruct.ConnStats.DataBytesRead //used for calculations not passed to client calculating up/down speed fullClientDB.DataBytesRead = fullStruct.ConnStats.BytesReadData //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.DataBytesWritten = fullStruct.ConnStats.BytesWrittenData //used for calculations not passed to client calculating up/down speed
fullClientDB.ActivePeers = activePeersString + " / (" + totalPeersString + ")" fullClientDB.ActivePeers = activePeersString + " / (" + totalPeersString + ")"
fullClientDB.TorrentHashString = TempHash.String() fullClientDB.TorrentHashString = TempHash.String()
fullClientDB.StoragePath = singleTorrentFromStorage.StoragePath
fullClientDB.TorrentName = singleTorrentFromStorage.TorrentName fullClientDB.TorrentName = singleTorrentFromStorage.TorrentName
fullClientDB.DateAdded = singleTorrentFromStorage.DateAdded fullClientDB.DateAdded = singleTorrentFromStorage.DateAdded
fullClientDB.TorrentLabel = singleTorrentFromStorage.Label fullClientDB.TorrentLabel = singleTorrentFromStorage.Label
@@ -252,7 +249,7 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
TempHash := singleTorrent.InfoHash() TempHash := singleTorrent.InfoHash()
if previousElement.TorrentHashString == TempHash.String() { //matching previous to new if previousElement.TorrentHashString == TempHash.String() { //matching previous to new
CalculateTorrentSpeed(singleTorrent, fullClientDB, previousElement) CalculateTorrentSpeed(singleTorrent, fullClientDB, previousElement)
fullClientDB.TotalUploadedBytes = singleTorrentFromStorage.UploadedBytes + (fullStruct.ConnStats.DataBytesWritten - previousElement.DataBytesWritten) fullClientDB.TotalUploadedBytes = singleTorrentFromStorage.UploadedBytes + (fullStruct.ConnStats.BytesWrittenData - previousElement.DataBytesWritten)
} }
} }
} }
@@ -276,7 +273,7 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
} }
//CreateFileListArray creates a file list for a single torrent that is selected and sent to the server //CreateFileListArray creates a file list for a single torrent that is selected and sent to the server
func CreateFileListArray(tclient *torrent.Client, selectedHash string, db *storm.DB) TorrentFileList { func CreateFileListArray(tclient *torrent.Client, selectedHash string, db *storm.DB, config FullClientSettings) TorrentFileList {
runningTorrents := tclient.Torrents() //don't need running torrent array since we aren't adding or deleting from storage runningTorrents := tclient.Torrents() //don't need running torrent array since we aren't adding or deleting from storage
torrentFileListStorage := Storage.FetchTorrentFromStorage(db, selectedHash) torrentFileListStorage := Storage.FetchTorrentFromStorage(db, selectedHash)
TorrentFileListSelected := TorrentFileList{} TorrentFileListSelected := TorrentFileList{}
@@ -289,11 +286,7 @@ func CreateFileListArray(tclient *torrent.Client, selectedHash string, db *storm
for _, singleFile := range torrentFilesRaw { for _, singleFile := range torrentFilesRaw {
TorrentFileStruct.TorrentHashString = tempHash TorrentFileStruct.TorrentHashString = tempHash
TorrentFileStruct.FileName = singleFile.DisplayPath() TorrentFileStruct.FileName = singleFile.DisplayPath()
absFilePath, err := filepath.Abs(singleFile.Path()) TorrentFileStruct.FilePath = singleFile.Path()
if err != nil {
Logger.WithFields(logrus.Fields{"file": singleFile.Path()}).Debug("Unable to create absolute path")
}
TorrentFileStruct.FilePath = absFilePath
PieceState := singleFile.State() PieceState := singleFile.State()
var downloadedBytes int64 var downloadedBytes int64
for _, piece := range PieceState { for _, piece := range PieceState {

View File

@@ -62,7 +62,7 @@ func CopyFile(srcFile string, destFile string) {
func CalculateTorrentSpeed(t *torrent.Torrent, c *ClientDB, oc ClientDB) { func CalculateTorrentSpeed(t *torrent.Torrent, c *ClientDB, oc ClientDB) {
now := time.Now() now := time.Now()
bytes := t.BytesCompleted() bytes := t.BytesCompleted()
bytesUpload := t.Stats().DataBytesWritten bytesUpload := t.Stats().BytesWrittenData
dt := float32(now.Sub(oc.UpdatedAt)) // get the delta time length between now and last updated 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 db := float32(bytes - oc.BytesCompleted) //getting the delta bytes
rate := db * (float32(time.Second) / dt) // converting into seconds rate := db * (float32(time.Second) / dt) // converting into seconds

View File

@@ -89,7 +89,10 @@ const inlineStyle = {
{i: 'b', x: 0, y: 1, w: 1, h: 5, static: true}, {i: 'b', x: 0, y: 1, w: 1, h: 5, static: true},
{i: 'c', x: 1, y: 1, w: 5, h: 5, minW: 5, minH: 3, static: true}, {i: 'c', x: 1, y: 1, w: 5, h: 5, minW: 5, minH: 3, static: true},
]; ];
this.state = { layout }; this.state = {
layout ,
textValue: "",
};
}; };
@@ -103,7 +106,6 @@ const inlineStyle = {
} }
handleAddRSSFeed = () => { handleAddRSSFeed = () => {
this.setState({ textValue: "Clear"}) //clearing out the text submitted
let RSSURLSubmit = { let RSSURLSubmit = {
MessageType: "addRSSFeed", MessageType: "addRSSFeed",
Payload: [this.state.textValue] Payload: [this.state.textValue]
@@ -113,20 +115,13 @@ const inlineStyle = {
MessageType: "rssFeedRequest", MessageType: "rssFeedRequest",
} }
ws.send(JSON.stringify(RSSRequest)) //Immediatly request an update of the feed when you add a new URL ws.send(JSON.stringify(RSSRequest)) //Immediatly request an update of the feed when you add a new URL
this.setState({textValue: ""})
} }
setTextValue = (event) => { setTextValue = (event) => {
this.setState({ textValue: event.target.value }); this.setState({ textValue: event.target.value });
} }
componentWillReceiveProps (nextProps) {
console.log("nextprops", nextProps, "Modal", nextProps.RSSModalOpen)
}
componentWillMount () {
console.log("Mounting grid")
}
render() { render() {
return ( return (
<div style={inlineStyle}> <div style={inlineStyle}>

View File

@@ -41,7 +41,7 @@ class DeleteTorrentModal extends React.Component {
let selection = [] let selection = []
let deleteTorrentHashes = { let deleteTorrentHashes = {
MessageType: "deleteTorrents", MessageType: "deleteTorrents",
MessageDetail: "true", MessageDetail: "false", //delete with data
Payload: this.props.selectionHashes Payload: this.props.selectionHashes
} }
console.log("Deleting Torrents", deleteTorrentHashes) console.log("Deleting Torrents", deleteTorrentHashes)
@@ -56,7 +56,7 @@ class DeleteTorrentModal extends React.Component {
let deleteTorrentHashes = { let deleteTorrentHashes = {
MessageType: "deleteTorrents", MessageType: "deleteTorrents",
MessageDetail: "true", MessageDetail: "true", //delete with data
Payload: this.props.selectionHashes, Payload: this.props.selectionHashes,
} }
console.log("Deleting Torrents and Data", deleteTorrentHashes) console.log("Deleting Torrents and Data", deleteTorrentHashes)

46
main.go
View File

@@ -163,7 +163,7 @@ func main() {
case "torrentFileListRequest": //client requested a filelist update case "torrentFileListRequest": //client requested a filelist update
Logger.WithFields(logrus.Fields{"message": msg}).Debug("Client Requested FileList Update") Logger.WithFields(logrus.Fields{"message": msg}).Debug("Client Requested FileList Update")
FileListArray := Engine.CreateFileListArray(tclient, msg.Payload[0], db) FileListArray := Engine.CreateFileListArray(tclient, msg.Payload[0], db, Config)
conn.WriteJSON(FileListArray) //writing the JSON to the client conn.WriteJSON(FileListArray) //writing the JSON to the client
case "torrentDetailedInfo": case "torrentDetailedInfo":
@@ -176,6 +176,21 @@ func main() {
torrentPeerList := Engine.CreatePeerListArray(tclient, msg.Payload[0]) torrentPeerList := Engine.CreatePeerListArray(tclient, msg.Payload[0])
conn.WriteJSON(torrentPeerList) conn.WriteJSON(torrentPeerList)
case "fetchTorrentsByLabel": //TODO test this to make sure it works
Logger.WithFields(logrus.Fields{"message": msg}).Debug("Client Requested Torrents by Label")
label := msg.MessageDetail
torrentsByLabel := Storage.FetchTorrentsByLabel(db, label)
RunningTorrentArray = Engine.CreateRunningTorrentArray(tclient, TorrentLocalArray, PreviousTorrentArray, Config, db)
labelRunningArray := []Engine.ClientDB{}
for _, torrent := range RunningTorrentArray { //Ranging over the running torrents and if the hashes match we have torrents by label
for _, label := range torrentsByLabel {
if torrent.TorrentHashString == label.Hash {
labelRunningArray = append(labelRunningArray, torrent)
}
}
}
conn.WriteJSON(labelRunningArray)
case "changeStorageValue": case "changeStorageValue":
Logger.WithFields(logrus.Fields{"message": msg}).Debug("Client Requested Storage Location Update") Logger.WithFields(logrus.Fields{"message": msg}).Debug("Client Requested Storage Location Update")
newStorageLocation := msg.MessageDetail newStorageLocation := msg.MessageDetail
@@ -183,10 +198,16 @@ func main() {
for _, singleHash := range hashes { for _, singleHash := range hashes {
singleTorrent := Storage.FetchTorrentFromStorage(db, singleHash) singleTorrent := Storage.FetchTorrentFromStorage(db, singleHash)
oldPath := singleTorrent.StoragePath oldPath := singleTorrent.StoragePath
singleTorrent.StoragePath = newStorageLocation newStorageLocationAbs, err := filepath.Abs(filepath.ToSlash(newStorageLocation))
if err != nil {
Logger.WithFields(logrus.Fields{"patherr": err, "path": newStorageLocation}).Warn("Unable to create absolute path for storage location, using default")
singleTorrent.StoragePath = Config.TorrentConfig.DataDir
} else {
singleTorrent.StoragePath = newStorageLocationAbs
}
Storage.UpdateStorageTick(db, singleTorrent) //push torrent to storage Storage.UpdateStorageTick(db, singleTorrent) //push torrent to storage
if singleTorrent.TorrentMoved == true { //If torrent has already been moved and I change path then move it again... TODO, does this work with symlinks? if singleTorrent.TorrentMoved == true { //If torrent has already been moved and I change path then move it again... TODO, does this work with symlinks?
Logger.WithFields(logrus.Fields{"message": msg}).Info("Torrent completed so moving to new location") Logger.WithFields(logrus.Fields{"message": msg}).Info("Change Storage Value called")
Engine.MoveAndLeaveSymlink(Config, singleHash, db, true, oldPath) Engine.MoveAndLeaveSymlink(Config, singleHash, db, true, oldPath)
} }
} }
@@ -283,7 +304,7 @@ func main() {
} }
Logger.WithFields(logrus.Fields{"clientTorrent": clientTorrent, "magnetLink": magnetLink}).Info("Adding torrent to client!") Logger.WithFields(logrus.Fields{"clientTorrent": clientTorrent, "magnetLink": magnetLink}).Info("Adding torrent to client!")
Engine.CreateServerPushMessage(Engine.ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "info", Payload: "Received MagnetLink"}, conn) Engine.CreateServerPushMessage(Engine.ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "info", Payload: "Received MagnetLink"}, conn)
Engine.StartTorrent(clientTorrent, torrentLocalStorage, db, Config.TorrentConfig.DataDir, "magnet", "", storageValue, labelValue, Config.TFileUploadFolder) //starting the torrent and creating local DB entry Engine.StartTorrent(clientTorrent, torrentLocalStorage, db, "magnet", "", storageValue, labelValue, Config) //starting the torrent and creating local DB entry
} }
@@ -296,8 +317,6 @@ func main() {
Engine.CreateServerPushMessage(Engine.ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "error", Payload: "Unable to decode base64 string to file"}, conn) Engine.CreateServerPushMessage(Engine.ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "error", Payload: "Unable to decode base64 string to file"}, conn)
} }
FileName := msg.MessageDetail FileName := msg.MessageDetail
fmt.Println("Full Message", msg.MessageType, msg.MessageDetail, msg.MessageDetailTwo, msg.MessageDetailThree)
fmt.Println("FileName", msg.MessageDetail)
storageValue := msg.MessageDetailTwo storageValue := msg.MessageDetailTwo
labelValue := msg.MessageDetailThree labelValue := msg.MessageDetailThree
if storageValue == "" { if storageValue == "" {
@@ -314,21 +333,22 @@ func main() {
storageValue, _ = filepath.Abs(filepath.ToSlash(Config.DefaultMoveFolder)) storageValue, _ = filepath.Abs(filepath.ToSlash(Config.DefaultMoveFolder))
} }
} }
filePath := filepath.Join(Config.TFileUploadFolder, FileName) //creating a full filepath to store the .torrent files filePath := filepath.Join(Config.TFileUploadFolder, FileName)
filePathAbs, err := filepath.Abs(filePath) //creating a full filepath to store the .torrent files
err = ioutil.WriteFile(filePath, file, 0755) //Dumping our received file into the filename err = ioutil.WriteFile(filePathAbs, file, 0755) //Dumping our received file into the filename
if err != nil { if err != nil {
Logger.WithFields(logrus.Fields{"filepath": filePath, "file Name": FileName, "Error": err}).Error("Unable to write torrent data to file") Logger.WithFields(logrus.Fields{"filepath": filePathAbs, "file Name": FileName, "Error": err}).Error("Unable to write torrent data to file")
Engine.CreateServerPushMessage(Engine.ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "error", Payload: "Unable to write torrent data to file"}, conn) Engine.CreateServerPushMessage(Engine.ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "error", Payload: "Unable to write torrent data to file"}, conn)
} }
clientTorrent, err := tclient.AddTorrentFromFile(filePath) clientTorrent, err := tclient.AddTorrentFromFile(filePathAbs)
if err != nil { if err != nil {
Logger.WithFields(logrus.Fields{"filepath": filePath, "Error": err}).Error("Unable to add Torrent to torrent server") Logger.WithFields(logrus.Fields{"filepath": filePathAbs, "Error": err}).Error("Unable to add Torrent to torrent server")
Engine.CreateServerPushMessage(Engine.ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "error", Payload: "Unable to add Torrent to torrent server"}, conn) Engine.CreateServerPushMessage(Engine.ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "error", Payload: "Unable to add Torrent to torrent server"}, conn)
} }
Logger.WithFields(logrus.Fields{"clienttorrent": clientTorrent.Name(), "filename": filePath}).Info("Added torrent") Logger.WithFields(logrus.Fields{"clienttorrent": clientTorrent.Name(), "filename": filePathAbs}).Info("Added torrent")
Engine.StartTorrent(clientTorrent, torrentLocalStorage, db, Config.TorrentConfig.DataDir, "file", filePath, storageValue, labelValue, Config.TFileUploadFolder) Engine.StartTorrent(clientTorrent, torrentLocalStorage, db, "file", filePathAbs, storageValue, labelValue, Config)
case "stopTorrents": case "stopTorrents":
TorrentListCommands := msg.Payload TorrentListCommands := msg.Payload

View File

@@ -97281,7 +97281,6 @@ var RSSModalLayout = function (_React$Component) {
}; };
_this.handleAddRSSFeed = function () { _this.handleAddRSSFeed = function () {
_this.setState({ textValue: "Clear" }); //clearing out the text submitted
var RSSURLSubmit = { var RSSURLSubmit = {
MessageType: "addRSSFeed", MessageType: "addRSSFeed",
Payload: [_this.state.textValue] Payload: [_this.state.textValue]
@@ -97291,6 +97290,7 @@ var RSSModalLayout = function (_React$Component) {
MessageType: "rssFeedRequest" MessageType: "rssFeedRequest"
}; };
ws.send(JSON.stringify(RSSRequest)); //Immediatly request an update of the feed when you add a new URL ws.send(JSON.stringify(RSSRequest)); //Immediatly request an update of the feed when you add a new URL
_this.setState({ textValue: "" });
}; };
_this.setTextValue = function (event) { _this.setTextValue = function (event) {
@@ -97298,7 +97298,10 @@ var RSSModalLayout = function (_React$Component) {
}; };
var layout = [{ i: 'a', x: 0, y: 0, w: 6, h: 1, static: true }, { i: 'b', x: 0, y: 1, w: 1, h: 5, static: true }, { i: 'c', x: 1, y: 1, w: 5, h: 5, minW: 5, minH: 3, static: true }]; var layout = [{ i: 'a', x: 0, y: 0, w: 6, h: 1, static: true }, { i: 'b', x: 0, y: 1, w: 1, h: 5, static: true }, { i: 'c', x: 1, y: 1, w: 5, h: 5, minW: 5, minH: 3, static: true }];
_this.state = { layout: layout }; _this.state = {
layout: layout,
textValue: ""
};
return _this; return _this;
} }
@@ -97308,16 +97311,6 @@ var RSSModalLayout = function (_React$Component) {
value: function onLayoutChange(layout) { value: function onLayoutChange(layout) {
this.props.onLayoutChange(layout); this.props.onLayoutChange(layout);
} }
}, {
key: 'componentWillReceiveProps',
value: function componentWillReceiveProps(nextProps) {
console.log("nextprops", nextProps, "Modal", nextProps.RSSModalOpen);
}
}, {
key: 'componentWillMount',
value: function componentWillMount() {
console.log("Mounting grid");
}
}, { }, {
key: 'render', key: 'render',
value: function render() { value: function render() {
@@ -116880,7 +116873,7 @@ var DeleteTorrentModal = function (_React$Component) {
var selection = []; var selection = [];
var deleteTorrentHashes = { var deleteTorrentHashes = {
MessageType: "deleteTorrents", MessageType: "deleteTorrents",
MessageDetail: "true", MessageDetail: "false", //delete with data
Payload: _this.props.selectionHashes Payload: _this.props.selectionHashes
}; };
console.log("Deleting Torrents", deleteTorrentHashes); console.log("Deleting Torrents", deleteTorrentHashes);
@@ -116893,7 +116886,7 @@ var DeleteTorrentModal = function (_React$Component) {
var deleteTorrentHashes = { var deleteTorrentHashes = {
MessageType: "deleteTorrents", MessageType: "deleteTorrents",
MessageDetail: "true", MessageDetail: "true", //delete with data
Payload: _this.props.selectionHashes Payload: _this.props.selectionHashes
}; };
console.log("Deleting Torrents and Data", deleteTorrentHashes); console.log("Deleting Torrents and Data", deleteTorrentHashes);

View File

@@ -46,14 +46,15 @@ type TorrentLocal struct {
Hash string `storm:"id,unique"` //Hash should be unique for every torrent... if not we are re-adding an already added torrent Hash string `storm:"id,unique"` //Hash should be unique for every torrent... if not we are re-adding an already added torrent
InfoBytes []byte InfoBytes []byte
DateAdded string DateAdded string
StoragePath string StoragePath string //The absolute value of the path where the torrent will be moved when completed
TempStoragePath string //The absolute path of where the torrent is temporarily stored as it is downloaded
TorrentMoved bool TorrentMoved bool
TorrentName string TorrentName string
TorrentStatus string TorrentStatus string
TorrentUploadLimit bool //if true this torrent will bypass the upload storage limit (effectively unlimited) TorrentUploadLimit bool //if true this torrent will bypass the upload storage limit (effectively unlimited)
MaxConnections int MaxConnections int
TorrentType string //magnet or .torrent file TorrentType string //magnet or .torrent file
TorrentFileName string //Should be absolute path TorrentFileName string //Should be just the name of the torrent
TorrentFile []byte TorrentFile []byte
Label string Label string
UploadedBytes int64 UploadedBytes int64
@@ -144,6 +145,22 @@ func FetchTorrentFromStorage(torrentStorage *storm.DB, selectedHash string) Torr
return singleTorrentInfo return singleTorrentInfo
} }
//FetchTorrentsByLabel fetches a list of torrents that have a specific label
func FetchTorrentsByLabel(torrentStorage *storm.DB, label string) []TorrentLocal {
allTorrents := []*TorrentLocal{}
torrentsByLabel := []TorrentLocal{}
err := torrentStorage.All(&allTorrents)
if err != nil {
Logger.WithFields(logrus.Fields{"database": torrentStorage, "error": err}).Error("Unable to read Database into torrentLocalArray!")
}
for _, torrent := range allTorrents {
if torrent.Label == label {
torrentsByLabel = append(torrentsByLabel, *torrent)
}
}
return torrentsByLabel
}
//FetchHashHistory fetches the infohash of all torrents added into the client. The cron job checks this so as not to add torrents from RSS that were already added before //FetchHashHistory fetches the infohash of all torrents added into the client. The cron job checks this so as not to add torrents from RSS that were already added before
func FetchHashHistory(db *storm.DB) TorrentHistoryList { func FetchHashHistory(db *storm.DB) TorrentHistoryList {
torrentHistory := TorrentHistoryList{} torrentHistory := TorrentHistoryList{}

View File

@@ -0,0 +1,3 @@
[LocalizedFileNames]
Plan_9_from_Outer_Space_1959_archive.torrent=@Plan_9_from_Outer_Space_1959_archive.torrent,0
Return_of_the_Street_Fighter.avi.torrent=@Return_of_the_Street_Fighter.avi.torrent,0