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:
18
README.md
18
README.md
@@ -26,11 +26,19 @@ Image of the frontend UI
|
||||
- Automatic stop after seeding ratio reached
|
||||
- Pushbullet notification on torrent complete
|
||||
- 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
|
||||
- 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
|
||||
|
||||
- [ ] Stability/bug fixing/Optimization rewrite of some of the core structures of the WebUI and base server
|
||||
@@ -41,7 +49,7 @@ Image of the frontend UI
|
||||
|
||||
- [ ] 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
|
||||
|
||||
@@ -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
|
||||
#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
|
||||
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]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
SeedRatioStop = 1.50 #automatically stops the torrent after it reaches this seeding ratio
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
[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]
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 63 KiB |
@@ -2,6 +2,7 @@ package engine
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/anacrolix/torrent"
|
||||
@@ -46,9 +47,9 @@ func CheckTorrentWatchFolder(c *cron.Cron, db *storm.DB, tclient *torrent.Client
|
||||
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")
|
||||
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!")
|
||||
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)
|
||||
|
||||
}
|
||||
|
@@ -1,8 +1,6 @@
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
@@ -20,22 +18,21 @@ func MoveAndLeaveSymlink(config FullClientSettings, tHash string, db *storm.DB,
|
||||
tStorage := Storage.FetchTorrentFromStorage(db, tHash)
|
||||
Logger.WithFields(logrus.Fields{"Torrent Name": tStorage.TorrentName}).Info("Move and Create symlink started for torrent")
|
||||
var oldFilePath string
|
||||
if moveDone {
|
||||
if moveDone { //only occurs on manual move
|
||||
oldFilePathTemp := filepath.Join(oldPath, tStorage.TorrentName)
|
||||
oldFilePath, err := filepath.Abs(oldFilePathTemp)
|
||||
var err error
|
||||
oldFilePath, err = filepath.Abs(oldFilePathTemp)
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"Torrent Name": tStorage.TorrentName, "Filepath": oldFilePath}).Error("Cannot create absolute file path!")
|
||||
}
|
||||
|
||||
fmt.Println("oldfilepath", oldFilePath)
|
||||
} else {
|
||||
oldFilePathTemp := filepath.Join(config.TorrentConfig.DataDir, tStorage.TorrentName)
|
||||
oldFilePath, err := filepath.Abs(oldFilePathTemp)
|
||||
var err error
|
||||
oldFilePath, err = filepath.Abs(oldFilePathTemp)
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"Torrent Name": tStorage.TorrentName, "Filepath": oldFilePath}).Error("Cannot create absolute file path!")
|
||||
}
|
||||
}
|
||||
|
||||
newFilePathTemp := filepath.Join(tStorage.StoragePath, tStorage.TorrentName)
|
||||
newFilePath, err := filepath.Abs(newFilePathTemp)
|
||||
if err != nil {
|
||||
@@ -55,70 +52,27 @@ func MoveAndLeaveSymlink(config FullClientSettings, tHash string, db *storm.DB,
|
||||
}
|
||||
|
||||
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
|
||||
if oldFileInfo.IsDir() {
|
||||
os.Mkdir(newFilePath, 0755)
|
||||
if moveDone {
|
||||
err := folderCopy.Copy(config.TorrentConfig.DataDir, newFilePath)
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"Old File Path": config.TorrentConfig.DataDir, "New File Path": newFilePath, "error": err}).Error("Error Copying Folder!")
|
||||
}
|
||||
} else {
|
||||
newFilePathDir := filepath.Dir(newFilePath)
|
||||
os.Mkdir(newFilePathDir, 0755)
|
||||
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
|
||||
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)
|
||||
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
|
||||
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")
|
||||
return
|
||||
}
|
||||
}
|
||||
notifyUser(tStorage, config, db)
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"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
|
||||
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)
|
||||
if timedOut { //if we fail to add the torrent return
|
||||
return
|
||||
@@ -147,6 +146,7 @@ func StartTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage Storage.To
|
||||
torrentLocalStorage.Label = labelValue
|
||||
torrentLocalStorage.DateAdded = time.Now().Format("Jan _2 2006")
|
||||
torrentLocalStorage.StoragePath = torrentStoragePath
|
||||
torrentLocalStorage.TempStoragePath = config.TorrentConfig.DataDir
|
||||
torrentLocalStorage.TorrentName = clientTorrent.Name()
|
||||
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.
|
||||
@@ -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.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
|
||||
torrentFilePath := filepath.Join(tFileUploadFolder, torrentFileName)
|
||||
torrentFilePathAbs, err := filepath.Abs(torrentFilePath)
|
||||
torrentfile, err := ioutil.ReadFile(torrentFilePathAbs)
|
||||
torrentLocalStorage.TorrentFileName = torrentFilePathAbs
|
||||
if err != nil {
|
||||
@@ -236,11 +234,10 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
PercentDone := fmt.Sprintf("%.2f", float32(singleTorrent.BytesCompleted())/float32(singleTorrentFromStorage.TorrentSize))
|
||||
fullClientDB.TorrentHash = TempHash
|
||||
fullClientDB.PercentDone = PercentDone
|
||||
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.DataBytesRead = fullStruct.ConnStats.BytesReadData //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.TorrentHashString = TempHash.String()
|
||||
fullClientDB.StoragePath = singleTorrentFromStorage.StoragePath
|
||||
fullClientDB.TorrentName = singleTorrentFromStorage.TorrentName
|
||||
fullClientDB.DateAdded = singleTorrentFromStorage.DateAdded
|
||||
fullClientDB.TorrentLabel = singleTorrentFromStorage.Label
|
||||
@@ -252,7 +249,7 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
TempHash := singleTorrent.InfoHash()
|
||||
if previousElement.TorrentHashString == TempHash.String() { //matching previous to new
|
||||
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
|
||||
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
|
||||
torrentFileListStorage := Storage.FetchTorrentFromStorage(db, selectedHash)
|
||||
TorrentFileListSelected := TorrentFileList{}
|
||||
@@ -289,11 +286,7 @@ func CreateFileListArray(tclient *torrent.Client, selectedHash string, db *storm
|
||||
for _, singleFile := range torrentFilesRaw {
|
||||
TorrentFileStruct.TorrentHashString = tempHash
|
||||
TorrentFileStruct.FileName = singleFile.DisplayPath()
|
||||
absFilePath, err := filepath.Abs(singleFile.Path())
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"file": singleFile.Path()}).Debug("Unable to create absolute path")
|
||||
}
|
||||
TorrentFileStruct.FilePath = absFilePath
|
||||
TorrentFileStruct.FilePath = singleFile.Path()
|
||||
PieceState := singleFile.State()
|
||||
var downloadedBytes int64
|
||||
for _, piece := range PieceState {
|
||||
|
@@ -62,7 +62,7 @@ func CopyFile(srcFile string, destFile string) {
|
||||
func CalculateTorrentSpeed(t *torrent.Torrent, c *ClientDB, oc ClientDB) {
|
||||
now := time.Now()
|
||||
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
|
||||
db := float32(bytes - oc.BytesCompleted) //getting the delta bytes
|
||||
rate := db * (float32(time.Second) / dt) // converting into seconds
|
||||
|
@@ -89,7 +89,10 @@ const inlineStyle = {
|
||||
{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 };
|
||||
this.state = {
|
||||
layout ,
|
||||
textValue: "",
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
@@ -103,7 +106,6 @@ const inlineStyle = {
|
||||
}
|
||||
|
||||
handleAddRSSFeed = () => {
|
||||
this.setState({ textValue: "Clear"}) //clearing out the text submitted
|
||||
let RSSURLSubmit = {
|
||||
MessageType: "addRSSFeed",
|
||||
Payload: [this.state.textValue]
|
||||
@@ -113,20 +115,13 @@ const inlineStyle = {
|
||||
MessageType: "rssFeedRequest",
|
||||
}
|
||||
ws.send(JSON.stringify(RSSRequest)) //Immediatly request an update of the feed when you add a new URL
|
||||
this.setState({textValue: ""})
|
||||
}
|
||||
|
||||
setTextValue = (event) => {
|
||||
this.setState({ textValue: event.target.value });
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
console.log("nextprops", nextProps, "Modal", nextProps.RSSModalOpen)
|
||||
}
|
||||
componentWillMount () {
|
||||
console.log("Mounting grid")
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div style={inlineStyle}>
|
||||
|
@@ -41,7 +41,7 @@ class DeleteTorrentModal extends React.Component {
|
||||
let selection = []
|
||||
let deleteTorrentHashes = {
|
||||
MessageType: "deleteTorrents",
|
||||
MessageDetail: "true",
|
||||
MessageDetail: "false", //delete with data
|
||||
Payload: this.props.selectionHashes
|
||||
}
|
||||
console.log("Deleting Torrents", deleteTorrentHashes)
|
||||
@@ -56,7 +56,7 @@ class DeleteTorrentModal extends React.Component {
|
||||
|
||||
let deleteTorrentHashes = {
|
||||
MessageType: "deleteTorrents",
|
||||
MessageDetail: "true",
|
||||
MessageDetail: "true", //delete with data
|
||||
Payload: this.props.selectionHashes,
|
||||
}
|
||||
console.log("Deleting Torrents and Data", deleteTorrentHashes)
|
||||
|
46
main.go
46
main.go
@@ -163,7 +163,7 @@ func main() {
|
||||
|
||||
case "torrentFileListRequest": //client requested a 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
|
||||
|
||||
case "torrentDetailedInfo":
|
||||
@@ -176,6 +176,21 @@ func main() {
|
||||
torrentPeerList := Engine.CreatePeerListArray(tclient, msg.Payload[0])
|
||||
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":
|
||||
Logger.WithFields(logrus.Fields{"message": msg}).Debug("Client Requested Storage Location Update")
|
||||
newStorageLocation := msg.MessageDetail
|
||||
@@ -183,10 +198,16 @@ func main() {
|
||||
for _, singleHash := range hashes {
|
||||
singleTorrent := Storage.FetchTorrentFromStorage(db, singleHash)
|
||||
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
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -283,7 +304,7 @@ func main() {
|
||||
}
|
||||
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.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)
|
||||
}
|
||||
FileName := msg.MessageDetail
|
||||
fmt.Println("Full Message", msg.MessageType, msg.MessageDetail, msg.MessageDetailTwo, msg.MessageDetailThree)
|
||||
fmt.Println("FileName", msg.MessageDetail)
|
||||
storageValue := msg.MessageDetailTwo
|
||||
labelValue := msg.MessageDetailThree
|
||||
if storageValue == "" {
|
||||
@@ -314,21 +333,22 @@ func main() {
|
||||
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 {
|
||||
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)
|
||||
}
|
||||
|
||||
clientTorrent, err := tclient.AddTorrentFromFile(filePath)
|
||||
clientTorrent, err := tclient.AddTorrentFromFile(filePathAbs)
|
||||
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)
|
||||
}
|
||||
Logger.WithFields(logrus.Fields{"clienttorrent": clientTorrent.Name(), "filename": filePath}).Info("Added torrent")
|
||||
Engine.StartTorrent(clientTorrent, torrentLocalStorage, db, Config.TorrentConfig.DataDir, "file", filePath, storageValue, labelValue, Config.TFileUploadFolder)
|
||||
Logger.WithFields(logrus.Fields{"clienttorrent": clientTorrent.Name(), "filename": filePathAbs}).Info("Added torrent")
|
||||
Engine.StartTorrent(clientTorrent, torrentLocalStorage, db, "file", filePathAbs, storageValue, labelValue, Config)
|
||||
|
||||
case "stopTorrents":
|
||||
TorrentListCommands := msg.Payload
|
||||
|
@@ -97281,7 +97281,6 @@ var RSSModalLayout = function (_React$Component) {
|
||||
};
|
||||
|
||||
_this.handleAddRSSFeed = function () {
|
||||
_this.setState({ textValue: "Clear" }); //clearing out the text submitted
|
||||
var RSSURLSubmit = {
|
||||
MessageType: "addRSSFeed",
|
||||
Payload: [_this.state.textValue]
|
||||
@@ -97291,6 +97290,7 @@ var RSSModalLayout = function (_React$Component) {
|
||||
MessageType: "rssFeedRequest"
|
||||
};
|
||||
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) {
|
||||
@@ -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 }];
|
||||
_this.state = { layout: layout };
|
||||
_this.state = {
|
||||
layout: layout,
|
||||
textValue: ""
|
||||
};
|
||||
|
||||
return _this;
|
||||
}
|
||||
@@ -97308,16 +97311,6 @@ var RSSModalLayout = function (_React$Component) {
|
||||
value: function 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',
|
||||
value: function render() {
|
||||
@@ -116880,7 +116873,7 @@ var DeleteTorrentModal = function (_React$Component) {
|
||||
var selection = [];
|
||||
var deleteTorrentHashes = {
|
||||
MessageType: "deleteTorrents",
|
||||
MessageDetail: "true",
|
||||
MessageDetail: "false", //delete with data
|
||||
Payload: _this.props.selectionHashes
|
||||
};
|
||||
console.log("Deleting Torrents", deleteTorrentHashes);
|
||||
@@ -116893,7 +116886,7 @@ var DeleteTorrentModal = function (_React$Component) {
|
||||
|
||||
var deleteTorrentHashes = {
|
||||
MessageType: "deleteTorrents",
|
||||
MessageDetail: "true",
|
||||
MessageDetail: "true", //delete with data
|
||||
Payload: _this.props.selectionHashes
|
||||
};
|
||||
console.log("Deleting Torrents and Data", deleteTorrentHashes);
|
||||
|
@@ -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
|
||||
InfoBytes []byte
|
||||
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
|
||||
TorrentName string
|
||||
TorrentStatus string
|
||||
TorrentUploadLimit bool //if true this torrent will bypass the upload storage limit (effectively unlimited)
|
||||
MaxConnections int
|
||||
TorrentType string //magnet or .torrent file
|
||||
TorrentFileName string //Should be absolute path
|
||||
TorrentFileName string //Should be just the name of the torrent
|
||||
TorrentFile []byte
|
||||
Label string
|
||||
UploadedBytes int64
|
||||
@@ -144,6 +145,22 @@ func FetchTorrentFromStorage(torrentStorage *storm.DB, selectedHash string) Torr
|
||||
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
|
||||
func FetchHashHistory(db *storm.DB) TorrentHistoryList {
|
||||
torrentHistory := TorrentHistoryList{}
|
||||
|
3
torrentUpload/desktop.ini
Normal file
3
torrentUpload/desktop.ini
Normal 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
|
Reference in New Issue
Block a user