Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
6e5ba2c755 | |||
cbfcba4cbc | |||
d15bb9752a | |||
35a5ac37eb | |||
4909429390 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -2,6 +2,7 @@ downloads/
|
||||
downloading/
|
||||
downloaded/
|
||||
uploadedTorrents/
|
||||
boltBrowser/
|
||||
storage.db.lock
|
||||
storage.db
|
||||
storage.db.old
|
||||
@@ -24,3 +25,4 @@ config.toml.old
|
||||
/public/static/js/kickwebsocket-generated.js
|
||||
clientAuth.txt
|
||||
dist
|
||||
debScripts/
|
3
Dockerfile
Normal file
3
Dockerfile
Normal file
@@ -0,0 +1,3 @@
|
||||
FROM scratch
|
||||
COPY goTorrent /
|
||||
ENTRYPOINT [ "/goTorrent" ]
|
@@ -1,7 +1,7 @@
|
||||
[serverConfig]
|
||||
|
||||
ServerPort = ":8000" #leave format as is it expects a string with colon
|
||||
ServerAddr = "192.168.1.100" #Put in the IP address you want to bind to
|
||||
ServerAddr = "192.168.1.8" #Put in the IP address you want to bind to
|
||||
LogLevel = "Info" # Options = Debug, Info, Warn, Error, Fatal, Panic
|
||||
LogOutput = "stdout" #Options = file, stdout #file will print it to logs/server.log
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#Low = ~.05MB/s, Medium = ~.5MB/s, High = ~1.5MB/s
|
||||
UploadRateLimit = "Unlimited" #Options are "Low", "Medium", "High", "Unlimited" #Unlimited is default
|
||||
DownloadRateLimit = "Unlimited"
|
||||
#Maximum number of allowed active torrents, the rest will be queued
|
||||
MaxActiveTorrents = 5
|
||||
|
||||
[goTorrentWebUI]
|
||||
#Basic goTorrentWebUI authentication (not terribly secure, implemented in JS, password is hashed to SHA256, not salted, basically don't depend on this if you require very good security)
|
||||
|
@@ -22,7 +22,7 @@ func InitializeCronEngine() *cron.Cron {
|
||||
}
|
||||
|
||||
//CheckTorrentWatchFolder adds torrents from a watch folder //TODO see if you can use filepath.Abs instead of changing directory
|
||||
func CheckTorrentWatchFolder(c *cron.Cron, db *storm.DB, tclient *torrent.Client, torrentLocalStorage Storage.TorrentLocal, config Settings.FullClientSettings) {
|
||||
func CheckTorrentWatchFolder(c *cron.Cron, db *storm.DB, tclient *torrent.Client, torrentLocalStorage Storage.TorrentLocal, config Settings.FullClientSettings, torrentQueues Storage.TorrentQueues) {
|
||||
c.AddFunc("@every 5m", func() {
|
||||
Logger.WithFields(logrus.Fields{"Watch Folder": config.TorrentWatchFolder}).Info("Running the watch folder cron job")
|
||||
torrentFiles, err := ioutil.ReadDir(config.TorrentWatchFolder)
|
||||
@@ -50,7 +50,7 @@ func CheckTorrentWatchFolder(c *cron.Cron, db *storm.DB, tclient *torrent.Client
|
||||
|
||||
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, "file", fullNewFilePathAbs, config.DefaultMoveFolder, "default", config)
|
||||
AddTorrent(clientTorrent, torrentLocalStorage, db, "file", fullNewFilePathAbs, config.DefaultMoveFolder, "default", config)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ func CheckTorrentWatchFolder(c *cron.Cron, db *storm.DB, tclient *torrent.Client
|
||||
}
|
||||
|
||||
//RefreshRSSCron refreshes all of the RSS feeds on an hourly basis
|
||||
func RefreshRSSCron(c *cron.Cron, db *storm.DB, tclient *torrent.Client, torrentLocalStorage Storage.TorrentLocal, config Settings.FullClientSettings) {
|
||||
func RefreshRSSCron(c *cron.Cron, db *storm.DB, tclient *torrent.Client, torrentLocalStorage Storage.TorrentLocal, config Settings.FullClientSettings, torrentQueues Storage.TorrentQueues) {
|
||||
c.AddFunc("@hourly", func() {
|
||||
torrentHashHistory := Storage.FetchHashHistory(db)
|
||||
RSSFeedStore := Storage.FetchRSSFeeds(db)
|
||||
@@ -86,7 +86,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, "magnet", "", config.DefaultMoveFolder, "RSS", config) //TODO let user specify torrent default storage location and let change on fly
|
||||
AddTorrent(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)
|
||||
|
||||
}
|
||||
|
@@ -68,7 +68,6 @@ func MoveAndLeaveSymlink(config Settings.FullClientSettings, tHash string, db *s
|
||||
Logger.WithFields(logrus.Fields{"Old File Path": oldFilePath, "New File Path": newFilePath, "error": err}).Error("Error Copying Folder!")
|
||||
return err
|
||||
}
|
||||
//os.Chmod(newFilePath, 0777)
|
||||
err = filepath.Walk(newFilePath, func(path string, info os.FileInfo, err error) error { //Walking the file path to change the permissions
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"file": path, "error": err}).Error("Potentially non-critical error, continuing..")
|
||||
|
108
engine/engine.go
108
engine/engine.go
@@ -32,6 +32,10 @@ func CreateServerPushMessage(message ServerPushMessage, conn *websocket.Conn) {
|
||||
conn.WriteJSON(message)
|
||||
}
|
||||
|
||||
func QueueJSONMessage(conn *websocket.Conn){
|
||||
|
||||
}
|
||||
|
||||
//RefreshSingleRSSFeed refreshing a single RSS feed to send to the client (so no updating database) mainly by updating the torrent list to display any changes
|
||||
func RefreshSingleRSSFeed(db *storm.DB, RSSFeed Storage.SingleRSSFeed) Storage.SingleRSSFeed { //Todo.. duplicate as cron job... any way to merge these to reduce duplication?
|
||||
singleRSSFeed := Storage.SingleRSSFeed{URL: RSSFeed.URL, Name: RSSFeed.Name}
|
||||
@@ -129,15 +133,15 @@ func readTorrentFileFromDB(element *Storage.TorrentLocal, tclient *torrent.Clien
|
||||
return singleTorrent, nil
|
||||
}
|
||||
|
||||
//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, torrentType, torrentFilePathAbs, torrentStoragePath, labelValue string, config Settings.FullClientSettings) {
|
||||
//AddTorrent creates the storage.db entry and starts A NEW TORRENT and adds to the running torrent array
|
||||
func AddTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage Storage.TorrentLocal, db *storm.DB, torrentType, torrentFilePathAbs, torrentStoragePath, labelValue string, config Settings.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
|
||||
}
|
||||
var TempHash metainfo.Hash
|
||||
TempHash = clientTorrent.InfoHash()
|
||||
allStoredTorrents := Storage.FetchAllStoredTorrents(torrentDbStorage)
|
||||
allStoredTorrents := Storage.FetchAllStoredTorrents(db)
|
||||
for _, runningTorrentHashes := range allStoredTorrents {
|
||||
if runningTorrentHashes.Hash == TempHash.String() {
|
||||
Logger.WithFields(logrus.Fields{"Hash": TempHash.String()}).Info("Torrent has duplicate hash to already running torrent... will not add to storage")
|
||||
@@ -164,7 +168,7 @@ func StartTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage Storage.To
|
||||
}
|
||||
torrentLocalStorage.TorrentFile = torrentfile //storing the entire file in to database
|
||||
}
|
||||
Logger.WithFields(logrus.Fields{"Storage Path": torrentStoragePath, "Torrent Name": clientTorrent.Name()}).Info("Adding Torrent with following storage path")
|
||||
Logger.WithFields(logrus.Fields{"Storage Path": torrentStoragePath, "Torrent Name": clientTorrent.Name()}).Info("Adding Torrent with following storage path, to active Queue")
|
||||
torrentFiles := clientTorrent.Files() //storing all of the files in the database along with the priority
|
||||
var TorrentFilePriorityArray = []Storage.TorrentFilePriority{}
|
||||
for _, singleFile := range torrentFiles { //creating the database setup for the file array
|
||||
@@ -175,21 +179,16 @@ func StartTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage Storage.To
|
||||
TorrentFilePriorityArray = append(TorrentFilePriorityArray, torrentFilePriority)
|
||||
|
||||
}
|
||||
|
||||
torrentLocalStorage.TorrentFilePriority = TorrentFilePriorityArray
|
||||
Storage.AddTorrentLocalStorage(torrentDbStorage, torrentLocalStorage) //writing all of the data to the database
|
||||
clientTorrent.DownloadAll() //set all pieces to download
|
||||
NumPieces := clientTorrent.NumPieces() //find the number of pieces
|
||||
clientTorrent.CancelPieces(1, NumPieces) //cancel all of the pieces to use file priority
|
||||
for _, singleFile := range clientTorrent.Files() { //setting all of the file priorities to normal
|
||||
singleFile.SetPriority(torrent.PiecePriorityNormal)
|
||||
}
|
||||
CreateServerPushMessage(ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "success", Payload: "Torrent added!"}, Conn)
|
||||
//torrentQueues := Storage.FetchQueues(db)
|
||||
AddTorrentToActive(&torrentLocalStorage, clientTorrent, db)
|
||||
Storage.AddTorrentLocalStorage(db, torrentLocalStorage) //writing all of the data to the database
|
||||
}
|
||||
|
||||
//CreateInitialTorrentArray adds all the torrents on program start from the database
|
||||
func CreateInitialTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Storage.TorrentLocal, db *storm.DB) {
|
||||
func CreateInitialTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Storage.TorrentLocal, db *storm.DB, config Settings.FullClientSettings) {
|
||||
for _, singleTorrentFromStorage := range TorrentLocalArray {
|
||||
|
||||
var singleTorrent *torrent.Torrent
|
||||
var err error
|
||||
if singleTorrentFromStorage.TorrentType == "file" { //if it is a file pull it from the uploaded torrent folder
|
||||
@@ -218,22 +217,62 @@ func CreateInitialTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"torrentFile": singleTorrent.Name(), "error": err}).Error("Unable to add infobytes to the torrent!")
|
||||
}
|
||||
if singleTorrentFromStorage.TorrentStatus != "Completed" && singleTorrentFromStorage.TorrentStatus != "Stopped" {
|
||||
singleTorrent.DownloadAll() //set all of the pieces to download (piece prio is NE to file prio)
|
||||
NumPieces := singleTorrent.NumPieces() //find the number of pieces
|
||||
singleTorrent.CancelPieces(1, NumPieces) //cancel all of the pieces to use file priority
|
||||
for _, singleFile := range singleTorrent.Files() { //setting all of the file priorities to normal
|
||||
singleFile.SetPriority(torrent.PiecePriorityNormal)
|
||||
torrentQueues := Storage.FetchQueues(db)
|
||||
if len(torrentQueues.ActiveTorrents) == 0 && len(torrentQueues.QueuedTorrents) == 0 { // If empty, run through all the torrents and assign them
|
||||
if len(torrentQueues.ActiveTorrents) < Config.MaxActiveTorrents && singleTorrentFromStorage.TorrentStatus != "Stopped" {
|
||||
if singleTorrentFromStorage.TorrentStatus == "Completed" || singleTorrentFromStorage.TorrentStatus == "Seeding" {
|
||||
Logger.WithFields(logrus.Fields{"Torrent Name": singleTorrentFromStorage.TorrentName}).Info("Completed Torrents have lower priority, adding to Queued")
|
||||
AddTorrentToQueue(singleTorrentFromStorage, singleTorrent, db)
|
||||
} else {
|
||||
Logger.WithFields(logrus.Fields{"Torrent Name": singleTorrentFromStorage.TorrentName}).Info("Adding Torrent to Active Queue")
|
||||
AddTorrentToActive(singleTorrentFromStorage, singleTorrent, db)
|
||||
}
|
||||
} else {
|
||||
Logger.WithFields(logrus.Fields{"Torrent Name": singleTorrentFromStorage.TorrentName}).Info("Last resort for torrent, adding to Queued")
|
||||
AddTorrentToQueue(singleTorrentFromStorage, singleTorrent, db)
|
||||
}
|
||||
} else { //If we already have a queue set up then assign torrents to queue
|
||||
if singleTorrentFromStorage.TorrentStatus == "Queued" {
|
||||
AddTorrentToQueue(singleTorrentFromStorage, singleTorrent, db)
|
||||
} else {
|
||||
if len(torrentQueues.ActiveTorrents) < Config.MaxActiveTorrents && singleTorrentFromStorage.TorrentStatus != "Stopped" {
|
||||
AddTorrentToActive(singleTorrentFromStorage, singleTorrent, db)
|
||||
} else {
|
||||
AddTorrentToQueue(singleTorrentFromStorage, singleTorrent, db)
|
||||
}
|
||||
}
|
||||
RemoveDuplicatesFromQueues(db)
|
||||
}
|
||||
Storage.UpdateStorageTick(db, *singleTorrentFromStorage)
|
||||
}
|
||||
torrentQueues := Storage.FetchQueues(db)
|
||||
if len(torrentQueues.ActiveTorrents) < config.MaxActiveTorrents && len(torrentQueues.QueuedTorrents) > 0 { //after all the torrents are added, see if out active torrent list isn't full, then add from the queue
|
||||
Logger.WithFields(logrus.Fields{"Max Active: ": config.MaxActiveTorrents, "Current : ": torrentQueues.ActiveTorrents}).Debug("Adding Torrents from queue to active to fill...")
|
||||
maxCanSend := config.MaxActiveTorrents - len(torrentQueues.ActiveTorrents)
|
||||
if maxCanSend > len(torrentQueues.QueuedTorrents) {
|
||||
maxCanSend = len(torrentQueues.QueuedTorrents)
|
||||
}
|
||||
torrentsToStart := make([]string, maxCanSend)
|
||||
copy(torrentsToStart, torrentQueues.QueuedTorrents[len(torrentsToStart)-1:])
|
||||
for _, torrentStart := range torrentsToStart {
|
||||
for _, singleTorrent := range tclient.Torrents() {
|
||||
if singleTorrent.InfoHash().String() == torrentStart {
|
||||
singleTorrentFromStorage := Storage.FetchTorrentFromStorage(db, torrentStart)
|
||||
AddTorrentToActive(&singleTorrentFromStorage, singleTorrent, db)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SetFilePriority(tclient, db) //Setting the desired file priority from storage
|
||||
Logger.WithFields(logrus.Fields{"Max Active: ": config.MaxActiveTorrents, "Current : ": torrentQueues.ActiveTorrents}).Debug("Queue after all initial torrents have been added")
|
||||
}
|
||||
|
||||
//CreateRunningTorrentArray creates the entire torrent list to pass to client
|
||||
func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Storage.TorrentLocal, PreviousTorrentArray []ClientDB, config Settings.FullClientSettings, db *storm.DB) (RunningTorrentArray []ClientDB) {
|
||||
|
||||
torrentQueues := Storage.FetchQueues(db)
|
||||
Logger.WithFields(logrus.Fields{"Max Active: ": config.MaxActiveTorrents, "TorrentQueues": torrentQueues}).Debug("Current TorrentQueues")
|
||||
for _, singleTorrentFromStorage := range TorrentLocalArray {
|
||||
torrentQueues := Storage.FetchQueues(db)
|
||||
var singleTorrent *torrent.Torrent
|
||||
var TempHash metainfo.Hash
|
||||
for _, liveTorrent := range tclient.Torrents() { //matching the torrent from storage to the live torrent
|
||||
@@ -241,19 +280,17 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
singleTorrent = liveTorrent
|
||||
}
|
||||
}
|
||||
|
||||
tickUpdateStruct := Storage.TorrentLocal{} //we are shoving the tick updates into a torrentlocal struct to pass to storage happens at the end of the routine
|
||||
|
||||
fullClientDB := new(ClientDB)
|
||||
//singleTorrentStorageInfo := Storage.FetchTorrentFromStorage(db, TempHash.String()) //pulling the single torrent info from storage ()
|
||||
|
||||
//Handling deleted torrents here
|
||||
if singleTorrentFromStorage.TorrentStatus == "Dropped" {
|
||||
Logger.WithFields(logrus.Fields{"selection": singleTorrentFromStorage.TorrentName}).Info("Deleting just the torrent")
|
||||
singleTorrent.Drop()
|
||||
Storage.DelTorrentLocalStorage(db, singleTorrentFromStorage.Hash)
|
||||
|
||||
}
|
||||
if singleTorrentFromStorage.TorrentStatus == "DroppedData" {
|
||||
Logger.WithFields(logrus.Fields{"selection": singleTorrentFromStorage.TorrentName}).Info("Deleting just the torrent")
|
||||
Logger.WithFields(logrus.Fields{"selection": singleTorrentFromStorage.TorrentName}).Info("Deleting torrent and data")
|
||||
singleTorrent.Drop()
|
||||
Storage.DelTorrentLocalStorageAndFiles(db, singleTorrentFromStorage.Hash, Config.TorrentConfig.DataDir)
|
||||
|
||||
@@ -281,11 +318,8 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
Storage.UpdateStorageTick(db, tStorage)
|
||||
}
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
fullStruct := singleTorrent.Stats()
|
||||
|
||||
activePeersString := strconv.Itoa(fullStruct.ActivePeers) //converting to strings
|
||||
totalPeersString := fmt.Sprintf("%v", fullStruct.TotalPeers)
|
||||
fullClientDB.StoragePath = singleTorrentFromStorage.StoragePath
|
||||
@@ -319,10 +353,23 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
}
|
||||
CalculateTorrentETA(singleTorrentFromStorage.TorrentSize, calculatedCompletedSize, fullClientDB) //needs to be here since we need the speed calculated before we can estimate the eta.
|
||||
|
||||
if (len(torrentQueues.ActiveTorrents) < config.MaxActiveTorrents) && (len(torrentQueues.QueuedTorrents) > 0) { //If there is room for another torrent in active torrents, add it.
|
||||
var newTorrentHash string
|
||||
for _, torrentHash := range torrentQueues.QueuedTorrents {
|
||||
if singleTorrentFromStorage.TorrentStatus != "Stopped" {
|
||||
newTorrentHash = torrentHash
|
||||
}
|
||||
}
|
||||
for _, torrent := range tclient.Torrents() {
|
||||
if newTorrentHash == torrent.InfoHash().String() {
|
||||
AddTorrentToActive(singleTorrentFromStorage, singleTorrent, db)
|
||||
}
|
||||
}
|
||||
}
|
||||
fullClientDB.TotalUploadedSize = HumanizeBytes(float32(fullClientDB.TotalUploadedBytes))
|
||||
fullClientDB.UploadRatio = CalculateUploadRatio(singleTorrent, fullClientDB) //calculate the upload ratio
|
||||
|
||||
CalculateTorrentStatus(singleTorrent, fullClientDB, config, singleTorrentFromStorage, calculatedCompletedSize, calculatedTotalSize)
|
||||
CalculateTorrentStatus(singleTorrent, fullClientDB, config, singleTorrentFromStorage, calculatedCompletedSize, calculatedTotalSize, torrentQueues, db) //add torrents to the queue, remove from queue, etc
|
||||
|
||||
tickUpdateStruct.UploadRatio = fullClientDB.UploadRatio
|
||||
tickUpdateStruct.TorrentSize = calculatedTotalSize
|
||||
@@ -333,6 +380,7 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
RunningTorrentArray = append(RunningTorrentArray, *fullClientDB)
|
||||
|
||||
}
|
||||
ValidateQueues(db, config, tclient) //Ensure we don't have too many in activeQueue
|
||||
return RunningTorrentArray
|
||||
}
|
||||
|
||||
|
@@ -184,18 +184,177 @@ func CalculateUploadRatio(t *torrent.Torrent, c *ClientDB) string {
|
||||
return uploadRatio
|
||||
}
|
||||
|
||||
//StopTorrent stops the torrent, updates the database and sends a message. Since stoptorrent is called by each loop (individually) no need to call an array
|
||||
func StopTorrent(singleTorrent *torrent.Torrent, torrentLocalStorage *Storage.TorrentLocal, db *storm.DB) {
|
||||
torrentQueues := Storage.FetchQueues(db)
|
||||
if torrentLocalStorage.TorrentStatus == "Stopped" { //if we are already stopped
|
||||
Logger.WithFields(logrus.Fields{"Torrent Name": torrentLocalStorage.TorrentName}).Info("Torrent Already Stopped, returning...")
|
||||
return
|
||||
}
|
||||
torrentLocalStorage.TorrentStatus = "Stopped"
|
||||
torrentLocalStorage.MaxConnections = 0
|
||||
singleTorrent.SetMaxEstablishedConns(0)
|
||||
for _, torrentHash := range torrentQueues.ActiveTorrents { //pulling it out of activetorrents
|
||||
if torrentHash == singleTorrent.InfoHash().String() {
|
||||
DeleteTorrentFromQueues(singleTorrent.InfoHash().String(), db)
|
||||
}
|
||||
}
|
||||
for _, torrentHash := range torrentQueues.QueuedTorrents { //pulling it out of queuedTorrent
|
||||
if torrentHash == singleTorrent.InfoHash().String() {
|
||||
DeleteTorrentFromQueues(singleTorrent.InfoHash().String(), db)
|
||||
}
|
||||
}
|
||||
Storage.UpdateStorageTick(db, *torrentLocalStorage)
|
||||
CreateServerPushMessage(ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "success", Payload: "Torrent Stopped!"}, Conn)
|
||||
return
|
||||
}
|
||||
|
||||
//AddTorrentToActive adds a torrent to the active slice
|
||||
func AddTorrentToActive(torrentLocalStorage *Storage.TorrentLocal, singleTorrent *torrent.Torrent, db *storm.DB) {
|
||||
torrentQueues := Storage.FetchQueues(db)
|
||||
for _, torrentHash := range torrentQueues.ActiveTorrents {
|
||||
if torrentHash == singleTorrent.InfoHash().String() { //If torrent already in active skip
|
||||
return
|
||||
}
|
||||
}
|
||||
for index, queuedTorrentHash := range torrentQueues.QueuedTorrents { //Removing from the queued torrents if in queued torrents
|
||||
if queuedTorrentHash == singleTorrent.InfoHash().String() {
|
||||
torrentQueues.QueuedTorrents = append(torrentQueues.QueuedTorrents[:index], torrentQueues.QueuedTorrents[index+1:]...)
|
||||
}
|
||||
}
|
||||
singleTorrent.NewReader()
|
||||
singleTorrent.SetMaxEstablishedConns(80)
|
||||
torrentQueues.ActiveTorrents = append(torrentQueues.ActiveTorrents, singleTorrent.InfoHash().String())
|
||||
torrentLocalStorage.TorrentStatus = "Running"
|
||||
torrentLocalStorage.MaxConnections = 80
|
||||
for _, file := range singleTorrent.Files() {
|
||||
for _, sentFile := range torrentLocalStorage.TorrentFilePriority {
|
||||
if file.DisplayPath() == sentFile.TorrentFilePath {
|
||||
switch sentFile.TorrentFilePriority {
|
||||
case "High":
|
||||
file.SetPriority(torrent.PiecePriorityHigh)
|
||||
case "Normal":
|
||||
file.SetPriority(torrent.PiecePriorityNormal)
|
||||
case "Cancel":
|
||||
file.SetPriority(torrent.PiecePriorityNone)
|
||||
default:
|
||||
file.SetPriority(torrent.PiecePriorityNormal)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Logger.WithFields(logrus.Fields{"Torrent Name": torrentLocalStorage.TorrentName}).Info("Adding Torrent to Active Queue")
|
||||
Storage.UpdateQueues(db, torrentQueues)
|
||||
}
|
||||
|
||||
//RemoveTorrentFromActive forces a torrent to be removed from the active list if the max limit is already there and user forces a new torrent to be added
|
||||
func RemoveTorrentFromActive(torrentLocalStorage *Storage.TorrentLocal, singleTorrent *torrent.Torrent, db *storm.DB) {
|
||||
torrentQueues := Storage.FetchQueues(db)
|
||||
for x, torrentHash := range torrentQueues.ActiveTorrents {
|
||||
if torrentHash == singleTorrent.InfoHash().String() {
|
||||
torrentQueues.ActiveTorrents = append(torrentQueues.ActiveTorrents[:x], torrentQueues.ActiveTorrents[x+1:]...)
|
||||
torrentQueues.QueuedTorrents = append(torrentQueues.QueuedTorrents, torrentHash)
|
||||
torrentLocalStorage.TorrentStatus = "Queued"
|
||||
torrentLocalStorage.MaxConnections = 0
|
||||
singleTorrent.SetMaxEstablishedConns(0)
|
||||
Storage.UpdateQueues(db, torrentQueues)
|
||||
//AddTorrentToQueue(torrentLocalStorage, singleTorrent, db) //Adding the lasttorrent from active to queued
|
||||
Storage.UpdateStorageTick(db, *torrentLocalStorage)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//DeleteTorrentFromQueues deletes the torrent from all queues (for a stop or delete action)
|
||||
func DeleteTorrentFromQueues(torrentHash string, db *storm.DB) {
|
||||
torrentQueues := Storage.FetchQueues(db)
|
||||
for x, torrentHashActive := range torrentQueues.ActiveTorrents {
|
||||
if torrentHash == torrentHashActive {
|
||||
torrentQueues.ActiveTorrents = append(torrentQueues.ActiveTorrents[:x], torrentQueues.ActiveTorrents[x+1:]...)
|
||||
Storage.UpdateQueues(db, torrentQueues)
|
||||
} else {
|
||||
for x, torrentHashQueued := range torrentQueues.QueuedTorrents {
|
||||
if torrentHash == torrentHashQueued {
|
||||
torrentQueues.QueuedTorrents = append(torrentQueues.QueuedTorrents[:x], torrentQueues.QueuedTorrents[x+1:]...)
|
||||
Storage.UpdateQueues(db, torrentQueues)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Logger.WithFields(logrus.Fields{"Torrent Hash": torrentHash}).Info("Removing Torrent from all Queues")
|
||||
}
|
||||
|
||||
//AddTorrentToQueue adds a torrent to the queue
|
||||
func AddTorrentToQueue(torrentLocalStorage *Storage.TorrentLocal, singleTorrent *torrent.Torrent, db *storm.DB) {
|
||||
torrentQueues := Storage.FetchQueues(db)
|
||||
for _, torrentHash := range torrentQueues.QueuedTorrents {
|
||||
if singleTorrent.InfoHash().String() == torrentHash { //don't add duplicate to que but do everything else (TODO, maybe find a better way?)
|
||||
singleTorrent.SetMaxEstablishedConns(0)
|
||||
torrentLocalStorage.MaxConnections = 0
|
||||
torrentLocalStorage.TorrentStatus = "Queued"
|
||||
Logger.WithFields(logrus.Fields{"TorrentName": torrentLocalStorage.TorrentName}).Info("Adding torrent to the queue, not active")
|
||||
Storage.UpdateStorageTick(db, *torrentLocalStorage)
|
||||
return
|
||||
}
|
||||
}
|
||||
torrentQueues.QueuedTorrents = append(torrentQueues.QueuedTorrents, singleTorrent.InfoHash().String())
|
||||
singleTorrent.SetMaxEstablishedConns(0)
|
||||
torrentLocalStorage.MaxConnections = 0
|
||||
torrentLocalStorage.TorrentStatus = "Queued"
|
||||
Logger.WithFields(logrus.Fields{"TorrentName": torrentLocalStorage.TorrentName}).Info("Adding torrent to the queue, not active")
|
||||
Storage.UpdateQueues(db, torrentQueues)
|
||||
Storage.UpdateStorageTick(db, *torrentLocalStorage)
|
||||
}
|
||||
|
||||
//RemoveDuplicatesFromQueues removes any duplicates from torrentQueues.QueuedTorrents (which will happen if it is read in from DB)
|
||||
func RemoveDuplicatesFromQueues(db *storm.DB) {
|
||||
torrentQueues := Storage.FetchQueues(db)
|
||||
for _, torrentHash := range torrentQueues.ActiveTorrents {
|
||||
for i, queuedHash := range torrentQueues.QueuedTorrents {
|
||||
if torrentHash == queuedHash {
|
||||
torrentQueues.QueuedTorrents = append(torrentQueues.QueuedTorrents[:i], torrentQueues.QueuedTorrents[i+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
Storage.UpdateQueues(db, torrentQueues)
|
||||
}
|
||||
|
||||
//ValidateQueues is a sanity check that runs every tick to make sure the queues are in order... tried to avoid this but seems to be required
|
||||
func ValidateQueues(db *storm.DB, config Settings.FullClientSettings, tclient *torrent.Client) {
|
||||
torrentQueues := Storage.FetchQueues(db)
|
||||
for len(torrentQueues.ActiveTorrents) > config.MaxActiveTorrents {
|
||||
removeTorrent := torrentQueues.ActiveTorrents[:1]
|
||||
for _, singleTorrent := range tclient.Torrents() {
|
||||
if singleTorrent.InfoHash().String() == removeTorrent[0] {
|
||||
singleTorrentFromStorage := Storage.FetchTorrentFromStorage(db, removeTorrent[0])
|
||||
RemoveTorrentFromActive(&singleTorrentFromStorage, singleTorrent, db)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//CalculateTorrentStatus is used to determine what the STATUS column of the frontend will display ll2
|
||||
func CalculateTorrentStatus(t *torrent.Torrent, c *ClientDB, config Settings.FullClientSettings, tFromStorage *storage.TorrentLocal, bytesCompleted int64, totalSize int64) {
|
||||
if (tFromStorage.TorrentStatus == "Stopped") || (float64(c.TotalUploadedBytes)/float64(bytesCompleted) >= config.SeedRatioStop && tFromStorage.TorrentUploadLimit == true) { //If storage shows torrent stopped or if it is over the seeding ratio AND is under the global limit
|
||||
func CalculateTorrentStatus(t *torrent.Torrent, c *ClientDB, config Settings.FullClientSettings, tFromStorage *storage.TorrentLocal, bytesCompleted int64, totalSize int64, torrentQueues Storage.TorrentQueues, db *storm.DB) {
|
||||
if tFromStorage.TorrentStatus == "Stopped" {
|
||||
c.Status = "Stopped"
|
||||
c.MaxConnections = 0
|
||||
t.SetMaxEstablishedConns(0)
|
||||
return
|
||||
}
|
||||
if float64(c.TotalUploadedBytes)/float64(bytesCompleted) >= config.SeedRatioStop && tFromStorage.TorrentUploadLimit == true { //If storage shows torrent stopped or if it is over the seeding ratio AND is under the global limit
|
||||
StopTorrent(t, tFromStorage, db)
|
||||
|
||||
} else { //Only has 2 states in storage, stopped or running, so we know it should be running, and the websocket request handled updating the database with connections and status
|
||||
for _, torrentHash := range torrentQueues.QueuedTorrents {
|
||||
if tFromStorage.Hash == torrentHash {
|
||||
c.Status = "Queued"
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(torrentQueues.ActiveTorrents) < config.MaxActiveTorrents && tFromStorage.TorrentStatus == "Queued" {
|
||||
AddTorrentToActive(tFromStorage, t, db)
|
||||
}
|
||||
bytesMissing := totalSize - bytesCompleted
|
||||
c.MaxConnections = 80
|
||||
t.SetMaxEstablishedConns(80)
|
||||
//t.DownloadAll() //ensure that we are setting the torrent to download
|
||||
if t.Seeding() && t.Stats().ActivePeers > 0 && bytesMissing == 0 {
|
||||
c.Status = "Seeding"
|
||||
} else if t.Stats().ActivePeers > 0 && bytesMissing > 0 {
|
||||
|
@@ -35,6 +35,7 @@ class ClientSettingsTab extends React.PureComponent {
|
||||
<Paper className={classes.paper}>HTTP Port: <span className={classes.floatRight}>{this.props.settingsFile["HTTPAddr"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Use Proxy: <span className={classes.floatRight}>{String(this.props.settingsFile["UseProxy"])} </span> </Paper>
|
||||
<Paper className={classes.paper}>Base URL: <span className={classes.floatRight}>{this.props.settingsFile["BaseURL"]} </span> </Paper>
|
||||
<Paper className={classes.paper}>Max Active Torrents: <span className={classes.floatRight}>{this.props.settingsFile["MaxActiveTorrents"]} </span> </Paper>
|
||||
|
||||
|
||||
</Grid>
|
||||
|
@@ -53,7 +53,7 @@ class LoggingSettingsTab extends React.Component {
|
||||
<Grid container spacing={8}>
|
||||
<Grid item xs={12} sm={4}>
|
||||
<Paper className={classes.paper}>Logging Output: <span className={classes.floatRight}>{this.props.settingsFile["LoggingOutput"]} </span></Paper>
|
||||
<Paper className={classes.paper}>Logging Level: <span className={classes.floatRight}>{logLevel} </span> </Paper>
|
||||
<Paper className={classes.paper}>Logging Level: <span className={classes.floatRight}>{this.props.settingsFile["LoggingLevel"]} </span> </Paper>
|
||||
|
||||
|
||||
</Grid>
|
||||
|
@@ -151,10 +151,9 @@ const reducer = (state = initialState, action) => {
|
||||
selectedRows.push(state.torrentList[element]) //pushing the selected rows out of torrentlist
|
||||
});
|
||||
|
||||
|
||||
let buttonStateTest = selectedRows.filter(element => { //TODO fix this bad mess... we literally just need to filter for stopped and go from there
|
||||
let buttonStateTest = selectedRows.filter(element => {
|
||||
let result = []
|
||||
if (element.Status === "Downloading" || element.Status === "Awaiting Peers" || element.Status === "Seeding" || element.Status === "Completed"){
|
||||
if (element.Status === "Downloading" || element.Status === "Awaiting Peers" || element.Status === "Seeding" || element.Status === "Completed" || element.Status === "Queued"){
|
||||
result.push(element.Status)
|
||||
return result
|
||||
}
|
||||
@@ -164,7 +163,6 @@ const reducer = (state = initialState, action) => {
|
||||
if (buttonStateTest.length > 0 && buttonStateTest2.length === 0){
|
||||
|
||||
let buttonStateFinal = [{startButton: "default", stopButton: "primary", deleteButton: "secondary", fSeedButton: "default", fRecheckButton: "primary"}]
|
||||
console.log("ButtonStateFil")
|
||||
return {
|
||||
...state,
|
||||
buttonState: buttonStateFinal
|
||||
|
121
main.go
121
main.go
@@ -51,7 +51,7 @@ func serveHome(w http.ResponseWriter, r *http.Request) {
|
||||
func handleAuthentication(conn *websocket.Conn, db *storm.DB) {
|
||||
msg := Engine.Message{}
|
||||
err := conn.ReadJSON(&msg)
|
||||
conn.WriteJSON(msg) //TODO just for testing, remove
|
||||
//conn.WriteJSON(msg) //TODO just for testing, remove
|
||||
payloadData, ok := msg.Payload.(map[string]interface{})
|
||||
clientAuthToken, tokenOk := payloadData["ClientAuthString"].(string)
|
||||
fmt.Println("ClientAuthToken:", clientAuthToken, "TokenOkay", tokenOk, "PayloadData", payloadData, "PayloadData Okay?", ok)
|
||||
@@ -94,6 +94,7 @@ func main() {
|
||||
Engine.Logger = Logger //Injecting the logger into all the packages
|
||||
Storage.Logger = Logger
|
||||
Settings.Logger = Logger
|
||||
var torrentQueues = Storage.TorrentQueues{}
|
||||
Config := Settings.FullClientSettingsNew() //grabbing from settings.go
|
||||
Engine.Config = Config
|
||||
if Config.LoggingOutput == "file" {
|
||||
@@ -123,26 +124,33 @@ func main() {
|
||||
httpAddr := Config.HTTPAddr
|
||||
os.MkdirAll(Config.TFileUploadFolder, 0755) //creating a directory to store uploaded torrent files
|
||||
os.MkdirAll(Config.TorrentWatchFolder, 0755) //creating a directory to watch for added .torrent files
|
||||
//Logger.WithFields(logrus.Fields{"Config": Config}).Info("Torrent Client Config has been generated...")
|
||||
Logger.WithFields(logrus.Fields{"Config": Config}).Info("Torrent Client Config has been generated...")
|
||||
|
||||
tclient, err := torrent.NewClient(&Config.TorrentConfig) //pulling out the torrent specific config to use
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"error": err}).Fatalf("Error creating torrent client: %s")
|
||||
}
|
||||
fmt.Printf("%+v\n", Config.TorrentConfig)
|
||||
//fmt.Printf("%+v\n", Config.TorrentConfig)
|
||||
db, err := storm.Open("storage.db") //initializing the boltDB store that contains all the added torrents
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"error": err}).Fatal("Error opening/creating storage.db")
|
||||
} else {
|
||||
Logger.WithFields(logrus.Fields{"error": err}).Info("Opening or creating storage.db...")
|
||||
}
|
||||
defer db.Close() //defering closing the database until the program closes
|
||||
|
||||
err = db.One("ID", 5, &torrentQueues)
|
||||
if err != nil { //Create the torrent que database
|
||||
Logger.WithFields(logrus.Fields{"error": err}).Info("No Queue database found, assuming first run, creating database")
|
||||
torrentQueues.ID = 5
|
||||
db.Save(&torrentQueues)
|
||||
}
|
||||
|
||||
tokens := Storage.IssuedTokensList{} //if first run setting up the authentication tokens
|
||||
var signingKey []byte
|
||||
err = db.One("ID", 3, &tokens)
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"RSSFeedStore": tokens, "error": err}).Info("No Tokens database found, assuming first run, generating token...")
|
||||
fmt.Println("Error", err)
|
||||
fmt.Println("MAIN TOKEN: %+v\n", tokens)
|
||||
tokens.ID = 3 //creating the initial store
|
||||
claims := Settings.GoTorrentClaims{
|
||||
"goTorrentWebUI",
|
||||
@@ -189,12 +197,13 @@ func main() {
|
||||
TorrentLocalArray := Storage.FetchAllStoredTorrents(db) //pulling in all the already added torrents - this is an array of ALL of the local storage torrents, they will be added back in via hash
|
||||
|
||||
if TorrentLocalArray != nil { //the first creation of the running torrent array //since we are adding all of them in we use a coroutine... just allows the web ui to load then it will load in the torrents
|
||||
go Engine.CreateInitialTorrentArray(tclient, TorrentLocalArray, db) //adding all of the stored torrents into the torrent client
|
||||
Engine.CreateInitialTorrentArray(tclient, TorrentLocalArray, db, Config) //adding all of the stored torrents into the torrent client
|
||||
//TODO add GO to this
|
||||
} else {
|
||||
Logger.Info("Database is empty, no torrents loaded")
|
||||
}
|
||||
Engine.CheckTorrentWatchFolder(cronEngine, db, tclient, torrentLocalStorage, Config) //Every 5 minutes the engine will check the specified folder for new .torrent files
|
||||
Engine.RefreshRSSCron(cronEngine, db, tclient, torrentLocalStorage, Config) // Refresing the RSS feeds on an hourly basis to add torrents that show up in the RSS feed
|
||||
Engine.CheckTorrentWatchFolder(cronEngine, db, tclient, torrentLocalStorage, Config, torrentQueues) //Every 5 minutes the engine will check the specified folder for new .torrent files
|
||||
Engine.RefreshRSSCron(cronEngine, db, tclient, torrentLocalStorage, Config, torrentQueues) // Refresing the RSS feeds on an hourly basis to add torrents that show up in the RSS feed
|
||||
|
||||
router := mux.NewRouter() //setting up the handler for the web backend
|
||||
router.HandleFunc("/", serveHome) //Serving the main page for our SPA
|
||||
@@ -275,7 +284,7 @@ func main() {
|
||||
Logger.WithFields(logrus.Fields{"message": msg}).Debug("Client Requested TorrentList Update")
|
||||
|
||||
go func() { //running updates in separate thread so can still accept commands
|
||||
TorrentLocalArray = Storage.FetchAllStoredTorrents(db) //Required to re-read th database since we write to the DB and this will pull the changes from it
|
||||
TorrentLocalArray = Storage.FetchAllStoredTorrents(db) //Required to re-read the database since we write to the DB and this will pull the changes from it
|
||||
RunningTorrentArray = Engine.CreateRunningTorrentArray(tclient, TorrentLocalArray, PreviousTorrentArray, Config, db) //Updates the RunningTorrentArray with the current client data as well
|
||||
PreviousTorrentArray = RunningTorrentArray
|
||||
torrentlistArray := Engine.TorrentList{MessageType: "torrentList", ClientDBstruct: RunningTorrentArray, Totaltorrents: len(RunningTorrentArray)}
|
||||
@@ -422,8 +431,18 @@ 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)
|
||||
go Engine.StartTorrent(clientTorrent, torrentLocalStorage, db, "magnet", "", storageValue, labelValue, Config) //starting the torrent and creating local DB entry
|
||||
|
||||
if len(torrentQueues.ActiveTorrents) > Config.MaxActiveTorrents {
|
||||
Logger.WithFields(logrus.Fields{"Name: ": clientTorrent.Name()}).Info("Adding New torrent to active, pushing other torrent to queue")
|
||||
removeTorrent := torrentQueues.ActiveTorrents[:1]
|
||||
for _, singleTorrent := range runningTorrents {
|
||||
if singleTorrent.InfoHash().String() == removeTorrent[0] {
|
||||
oldTorrentInfo := Storage.FetchTorrentFromStorage(db, singleTorrent.InfoHash().String())
|
||||
Engine.RemoveTorrentFromActive(&oldTorrentInfo, singleTorrent, db)
|
||||
Storage.UpdateStorageTick(db, oldTorrentInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
go Engine.AddTorrent(clientTorrent, torrentLocalStorage, db, "magnet", "", storageValue, labelValue, Config) //starting the torrent and creating local DB entry
|
||||
}
|
||||
|
||||
case "torrentFileSubmit":
|
||||
@@ -469,7 +488,18 @@ func main() {
|
||||
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": filePathAbs}).Info("Added torrent")
|
||||
go Engine.StartTorrent(clientTorrent, torrentLocalStorage, db, "file", filePathAbs, storageValue, labelValue, Config)
|
||||
if len(torrentQueues.ActiveTorrents) >= Config.MaxActiveTorrents {
|
||||
Logger.WithFields(logrus.Fields{"Name: ": clientTorrent.Name()}).Info("Adding New torrent to active, pushing other torrent to queue")
|
||||
removeTorrent := torrentQueues.ActiveTorrents[:1]
|
||||
for _, singleTorrent := range runningTorrents {
|
||||
if singleTorrent.InfoHash().String() == removeTorrent[0] {
|
||||
oldTorrentInfo := Storage.FetchTorrentFromStorage(db, singleTorrent.InfoHash().String())
|
||||
Engine.RemoveTorrentFromActive(&oldTorrentInfo, singleTorrent, db)
|
||||
Storage.UpdateStorageTick(db, oldTorrentInfo)
|
||||
go Engine.AddTorrent(clientTorrent, torrentLocalStorage, db, "file", filePathAbs, storageValue, labelValue, Config)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case "stopTorrents":
|
||||
torrentHashes := payloadData["TorrentHashes"].([]interface{})
|
||||
@@ -479,9 +509,16 @@ func main() {
|
||||
if singleTorrent.InfoHash().String() == singleSelection {
|
||||
Logger.WithFields(logrus.Fields{"selection": singleSelection}).Info("Matched for stopping torrents")
|
||||
oldTorrentInfo := Storage.FetchTorrentFromStorage(db, singleTorrent.InfoHash().String())
|
||||
oldTorrentInfo.TorrentStatus = "Stopped"
|
||||
oldTorrentInfo.MaxConnections = 0
|
||||
Storage.UpdateStorageTick(db, oldTorrentInfo) //Updating the torrent status
|
||||
Engine.StopTorrent(singleTorrent, &oldTorrentInfo, db)
|
||||
if len(torrentQueues.QueuedTorrents) > 1 {
|
||||
addTorrent := torrentQueues.QueuedTorrents[:1]
|
||||
for _, singleTorrent := range runningTorrents {
|
||||
if singleTorrent.InfoHash().String() == addTorrent[0] {
|
||||
Engine.AddTorrentToActive(&torrentLocalStorage, singleTorrent, db)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -495,6 +532,20 @@ func main() {
|
||||
for _, singleSelection := range torrentHashes {
|
||||
if singleTorrent.InfoHash().String() == singleSelection {
|
||||
oldTorrentInfo := Storage.FetchTorrentFromStorage(db, singleTorrent.InfoHash().String())
|
||||
torrentQueues = Storage.FetchQueues(db)
|
||||
|
||||
for index, activeTorrentHash := range torrentQueues.ActiveTorrents { //If torrent is in the active slice, pull it
|
||||
if singleTorrent.InfoHash().String() == activeTorrentHash {
|
||||
singleTorrent.SetMaxEstablishedConns(0)
|
||||
torrentQueues.ActiveTorrents = append(torrentQueues.ActiveTorrents[:index], torrentQueues.ActiveTorrents[index+1:]...)
|
||||
}
|
||||
}
|
||||
for index, queuedTorrentHash := range torrentQueues.QueuedTorrents { //If torrent is in the queued slice, pull it
|
||||
if singleTorrent.InfoHash().String() == queuedTorrentHash {
|
||||
torrentQueues.QueuedTorrents = append(torrentQueues.QueuedTorrents[:index], torrentQueues.QueuedTorrents[index+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
Logger.WithFields(logrus.Fields{"selection": singleSelection}).Info("Matched for deleting torrents")
|
||||
if withData {
|
||||
oldTorrentInfo.TorrentStatus = "DroppedData" //Will be cleaned up the next engine loop since deleting a torrent mid loop can cause issues
|
||||
@@ -502,6 +553,7 @@ func main() {
|
||||
oldTorrentInfo.TorrentStatus = "Dropped"
|
||||
}
|
||||
Storage.UpdateStorageTick(db, oldTorrentInfo)
|
||||
Storage.UpdateQueues(db, torrentQueues)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -515,34 +567,26 @@ func main() {
|
||||
if singleTorrent.InfoHash().String() == singleSelection {
|
||||
Logger.WithFields(logrus.Fields{"infoHash": singleTorrent.InfoHash().String()}).Info("Found matching torrent to start")
|
||||
oldTorrentInfo := Storage.FetchTorrentFromStorage(db, singleTorrent.InfoHash().String())
|
||||
oldTorrentInfo.TorrentStatus = "Running"
|
||||
oldTorrentInfo.MaxConnections = 80
|
||||
singleTorrent.DownloadAll() //set all of the pieces to download (piece prio is NE to file prio)
|
||||
NumPieces := singleTorrent.NumPieces() //find the number of pieces
|
||||
singleTorrent.CancelPieces(1, NumPieces) //cancel all of the pieces to use file priority
|
||||
for _, file := range singleTorrent.Files() {
|
||||
for _, sentFile := range oldTorrentInfo.TorrentFilePriority {
|
||||
if file.DisplayPath() == sentFile.TorrentFilePath {
|
||||
switch sentFile.TorrentFilePriority {
|
||||
case "High":
|
||||
file.SetPriority(torrent.PiecePriorityHigh)
|
||||
case "Normal":
|
||||
file.SetPriority(torrent.PiecePriorityNormal)
|
||||
case "Cancel":
|
||||
file.SetPriority(torrent.PiecePriorityNone)
|
||||
default:
|
||||
file.SetPriority(torrent.PiecePriorityNormal)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Engine.AddTorrentToActive(&oldTorrentInfo, singleTorrent, db)
|
||||
Logger.WithFields(logrus.Fields{"Torrent": oldTorrentInfo.TorrentName}).Info("Changing database to torrent running with 80 max connections")
|
||||
Storage.UpdateStorageTick(db, oldTorrentInfo) //Updating the torrent status
|
||||
}
|
||||
torrentQueues = Storage.FetchQueues(db)
|
||||
if len(torrentQueues.ActiveTorrents) > Config.MaxActiveTorrents { //Since we are starting a new torrent stop the first torrent in the que if running is full
|
||||
//removeTorrent := torrentQueues.ActiveTorrents[len(torrentQueues.ActiveTorrents)-1]
|
||||
removeTorrent := torrentQueues.ActiveTorrents[:1]
|
||||
for _, singleTorrent := range runningTorrents {
|
||||
if singleTorrent.InfoHash().String() == removeTorrent[0] {
|
||||
oldTorrentInfo := Storage.FetchTorrentFromStorage(db, singleTorrent.InfoHash().String())
|
||||
Engine.RemoveTorrentFromActive(&oldTorrentInfo, singleTorrent, db)
|
||||
Storage.UpdateStorageTick(db, oldTorrentInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case "forceUploadTorrents":
|
||||
case "forceUploadTorrents": //TODO allow force to override total limit of queued torrents?
|
||||
torrentHashes := payloadData["TorrentHashes"].([]interface{})
|
||||
Logger.WithFields(logrus.Fields{"selection": msg.Payload}).Info("Matched for force Uploading Torrents")
|
||||
Engine.CreateServerPushMessage(Engine.ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "info", Payload: "Received Force Start Request"}, conn)
|
||||
@@ -554,7 +598,6 @@ func main() {
|
||||
oldTorrentInfo.TorrentUploadLimit = false // no upload limit for this torrent
|
||||
oldTorrentInfo.TorrentStatus = "Running"
|
||||
oldTorrentInfo.MaxConnections = 80
|
||||
fmt.Println("OldtorrentinfoName", oldTorrentInfo.TorrentName)
|
||||
Logger.WithFields(logrus.Fields{"NewMax": oldTorrentInfo.MaxConnections, "Torrent": oldTorrentInfo.TorrentName}).Info("Setting max connection from zero to 80")
|
||||
Storage.UpdateStorageTick(db, oldTorrentInfo) //Updating the torrent status
|
||||
}
|
||||
@@ -619,7 +662,7 @@ func main() {
|
||||
} else {
|
||||
err := http.ListenAndServe(httpAddr, nil) //Can't send proxy headers if not used since that can be a security issue
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"error": err}).Fatal("Unable to listen on the http Server with no proxy headers!")
|
||||
Logger.WithFields(logrus.Fields{"error": err}).Fatal("Unable to listen on the http Server! (Maybe wrong IP in config, port already in use?) (Config: Not using proxy, see error for more details)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -80052,9 +80052,8 @@ var reducer = function reducer() {
|
||||
});
|
||||
|
||||
var buttonStateTest = selectedRows.filter(function (element) {
|
||||
//TODO fix this bad mess... we literally just need to filter for stopped and go from there
|
||||
var result = [];
|
||||
if (element.Status === "Downloading" || element.Status === "Awaiting Peers" || element.Status === "Seeding" || element.Status === "Completed") {
|
||||
if (element.Status === "Downloading" || element.Status === "Awaiting Peers" || element.Status === "Seeding" || element.Status === "Completed" || element.Status === "Queued") {
|
||||
result.push(element.Status);
|
||||
return result;
|
||||
}
|
||||
@@ -80066,7 +80065,6 @@ var reducer = function reducer() {
|
||||
if (buttonStateTest.length > 0 && buttonStateTest2.length === 0) {
|
||||
|
||||
var _buttonStateFinal2 = [{ startButton: "default", stopButton: "primary", deleteButton: "secondary", fSeedButton: "default", fRecheckButton: "primary" }];
|
||||
console.log("ButtonStateFil");
|
||||
return _extends({}, state, {
|
||||
buttonState: _buttonStateFinal2
|
||||
});
|
||||
@@ -109786,6 +109784,18 @@ var ClientSettingsTab = function (_React$PureComponent) {
|
||||
' '
|
||||
),
|
||||
' '
|
||||
),
|
||||
_react2.default.createElement(
|
||||
_Paper2.default,
|
||||
{ className: classes.paper },
|
||||
'Max Active Torrents: ',
|
||||
_react2.default.createElement(
|
||||
'span',
|
||||
{ className: classes.floatRight },
|
||||
this.props.settingsFile["MaxActiveTorrents"],
|
||||
' '
|
||||
),
|
||||
' '
|
||||
)
|
||||
),
|
||||
_react2.default.createElement(
|
||||
@@ -109957,7 +109967,7 @@ var LoggingSettingsTab = function (_React$Component) {
|
||||
_react2.default.createElement(
|
||||
'span',
|
||||
{ className: classes.floatRight },
|
||||
logLevel,
|
||||
this.props.settingsFile["LoggingLevel"],
|
||||
' '
|
||||
),
|
||||
' '
|
||||
|
@@ -40,6 +40,7 @@ type FullClientSettings struct {
|
||||
DefaultMoveFolder string
|
||||
TorrentWatchFolder string
|
||||
ClientConnectSettings
|
||||
MaxActiveTorrents int
|
||||
}
|
||||
|
||||
//default is called if there is a parsing error
|
||||
@@ -70,6 +71,8 @@ func dhtServerSettings(dhtConfig dht.ServerConfig) dht.ServerConfig {
|
||||
func calculateRateLimiters(uploadRate, downloadRate string) (*rate.Limiter, *rate.Limiter) { //TODO reorg
|
||||
var uploadRateLimiterSize int
|
||||
var downloadRateLimiterSize int
|
||||
var downloadRateLimiter *rate.Limiter
|
||||
var uploadRateLimiter *rate.Limiter
|
||||
|
||||
switch uploadRate {
|
||||
case "Low":
|
||||
@@ -79,8 +82,8 @@ func calculateRateLimiters(uploadRate, downloadRate string) (*rate.Limiter, *rat
|
||||
case "High":
|
||||
uploadRateLimiterSize = 1500000
|
||||
default:
|
||||
downloadRateLimiter := rate.NewLimiter(rate.Inf, 0)
|
||||
uploadRateLimiter := rate.NewLimiter(rate.Inf, 0)
|
||||
downloadRateLimiter = rate.NewLimiter(rate.Inf, 0)
|
||||
uploadRateLimiter = rate.NewLimiter(rate.Inf, 0)
|
||||
return downloadRateLimiter, uploadRateLimiter
|
||||
}
|
||||
|
||||
@@ -89,17 +92,16 @@ func calculateRateLimiters(uploadRate, downloadRate string) (*rate.Limiter, *rat
|
||||
downloadRateLimiterSize = 50000
|
||||
case "Medium":
|
||||
downloadRateLimiterSize = 500000
|
||||
fmt.Println("Medium Rate Limit...")
|
||||
case "High":
|
||||
downloadRateLimiterSize = 1500000
|
||||
default:
|
||||
downloadRateLimiter := rate.NewLimiter(rate.Inf, 0)
|
||||
uploadRateLimiter := rate.NewLimiter(rate.Inf, 0)
|
||||
downloadRateLimiter = rate.NewLimiter(rate.Inf, 0)
|
||||
uploadRateLimiter = rate.NewLimiter(rate.Inf, 0)
|
||||
return downloadRateLimiter, uploadRateLimiter
|
||||
}
|
||||
var limitPerSecondUl = rate.Limit(uploadRateLimiterSize)
|
||||
uploadRateLimiter := rate.NewLimiter(limitPerSecondUl, uploadRateLimiterSize)
|
||||
var limitPerSecondDl = rate.Limit(uploadRateLimiterSize)
|
||||
downloadRateLimiter := rate.NewLimiter(limitPerSecondDl, downloadRateLimiterSize)
|
||||
uploadRateLimiter = rate.NewLimiter(rate.Limit(uploadRateLimiterSize), uploadRateLimiterSize)
|
||||
downloadRateLimiter = rate.NewLimiter(rate.Limit(downloadRateLimiterSize), downloadRateLimiterSize)
|
||||
return downloadRateLimiter, uploadRateLimiter
|
||||
}
|
||||
|
||||
@@ -177,9 +179,9 @@ func FullClientSettingsNew() FullClientSettings {
|
||||
//Rate Limiters
|
||||
//var uploadRateLimiter *rate.Limiter
|
||||
//var downloadRateLimiter *rate.Limiter
|
||||
//uploadRate := viper.GetString("serverConfig.UploadRateLimit")
|
||||
//downloadRate := viper.GetString("serverConfig.DownloadRateLimit")
|
||||
//downloadRateLimiter, uploadRateLimiter = calculateRateLimiters(uploadRate, downloadRate)
|
||||
uploadRate := viper.GetString("serverConfig.UploadRateLimit")
|
||||
downloadRate := viper.GetString("serverConfig.DownloadRateLimit")
|
||||
downloadRateLimiter, uploadRateLimiter := calculateRateLimiters(uploadRate, downloadRate)
|
||||
//Internals
|
||||
dataDir := filepath.ToSlash(viper.GetString("torrentClientConfig.DownloadDir")) //Converting the string literal into a filepath
|
||||
dataDirAbs, err := filepath.Abs(dataDir) //Converting to an absolute file path
|
||||
@@ -191,6 +193,7 @@ func FullClientSettingsNew() FullClientSettings {
|
||||
noDHT := viper.GetBool("torrentClientConfig.NoDHT")
|
||||
noUpload := viper.GetBool("torrentClientConfig.NoUpload")
|
||||
seed := viper.GetBool("torrentClientConfig.Seed")
|
||||
maxActiveTorrents := viper.GetInt("serverConfig.MaxActiveTorrents")
|
||||
|
||||
peerID := viper.GetString("torrentClientConfig.PeerID")
|
||||
disableUTP := viper.GetBool("torrentClientConfig.DisableUTP")
|
||||
@@ -220,8 +223,8 @@ func FullClientSettingsNew() FullClientSettings {
|
||||
DHTConfig: dhtServerConfig,
|
||||
NoUpload: noUpload,
|
||||
Seed: seed,
|
||||
//UploadRateLimiter: uploadRateLimiter,
|
||||
//DownloadRateLimiter: downloadRateLimiter,
|
||||
UploadRateLimiter: uploadRateLimiter,
|
||||
DownloadRateLimiter: downloadRateLimiter,
|
||||
PeerID: peerID,
|
||||
DisableUTP: disableUTP,
|
||||
DisableTCP: disableTCP,
|
||||
@@ -248,6 +251,7 @@ func FullClientSettingsNew() FullClientSettings {
|
||||
TorrentConfig: tConfig,
|
||||
DefaultMoveFolder: defaultMoveFolderAbs,
|
||||
TorrentWatchFolder: torrentWatchFolderAbs,
|
||||
MaxActiveTorrents: maxActiveTorrents,
|
||||
}
|
||||
|
||||
return Config
|
||||
|
@@ -16,6 +16,13 @@ var Logger *logrus.Logger
|
||||
//Conn is the global websocket connection used to push server notification messages
|
||||
var Conn *websocket.Conn
|
||||
|
||||
//TorrentQueues contains the active and queued torrent hashes in slices
|
||||
type TorrentQueues struct {
|
||||
ID int `storm:"id,unique"` //storm requires unique ID (will be 5)
|
||||
ActiveTorrents []string
|
||||
QueuedTorrents []string
|
||||
}
|
||||
|
||||
//IssuedTokensList contains a slice of all the tokens issues to applications
|
||||
type IssuedTokensList struct {
|
||||
ID int `storm:"id,unique"` //storm requires unique ID (will be 3) to save although there will only be one of these
|
||||
@@ -94,6 +101,26 @@ func SaveConfig(torrentStorage *storm.DB, config Settings.FullClientSettings) {
|
||||
}
|
||||
}
|
||||
|
||||
//UpdateQueues Saves the slice of hashes that contain the active Torrents
|
||||
func UpdateQueues(db *storm.DB, torrentQueues TorrentQueues) {
|
||||
torrentQueues.ID = 5
|
||||
err := db.Save(&torrentQueues)
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"database": db, "error": err}).Error("Unable to write Queues to database!")
|
||||
}
|
||||
}
|
||||
|
||||
//FetchQueues fetches the activetorrent and queuedtorrent slices from the database
|
||||
func FetchQueues(db *storm.DB) TorrentQueues {
|
||||
torrentQueues := TorrentQueues{}
|
||||
err := db.One("ID", 5, &torrentQueues)
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"database": db, "error": err}).Error("Unable to read Database into torrentQueues!")
|
||||
return torrentQueues
|
||||
}
|
||||
return torrentQueues
|
||||
}
|
||||
|
||||
//FetchConfig fetches the client config from the database
|
||||
func FetchConfig(torrentStorage *storm.DB) (Settings.FullClientSettings, error) {
|
||||
config := Settings.FullClientSettings{}
|
||||
@@ -166,6 +193,8 @@ func UpdateStorageTick(torrentStorage *storm.DB, torrentLocal TorrentLocal) {
|
||||
err := torrentStorage.Update(&torrentLocal)
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"UpdateContents": torrentLocal, "error": err}).Error("Error performing tick update to database!")
|
||||
} else {
|
||||
Logger.WithFields(logrus.Fields{"UpdateContents": torrentLocal, "error": err}).Debug("Performed Update to database!")
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user