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
- 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
@@ -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 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]

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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 {
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")
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)
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"
"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 {

View File

@@ -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

View File

@@ -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}>

View File

@@ -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
View File

@@ -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

View File

@@ -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);

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
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{}

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