Fixes #15, started seperating Settings into their own package
This commit is contained in:
122
config.1.toml
Normal file
122
config.1.toml
Normal file
@@ -0,0 +1,122 @@
|
||||
[serverConfig]
|
||||
|
||||
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
|
||||
LogOutput = "stdout" #Options = file, stdout #file will print it to logs/server.log
|
||||
|
||||
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"
|
||||
|
||||
[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)
|
||||
WebUIAuth = true # bool, if false no authentication is required for the webUI
|
||||
WebUIUser = "admin"
|
||||
WebUIPassword = "Password1"
|
||||
|
||||
|
||||
[notifications]
|
||||
|
||||
PushBulletToken = "" #add your pushbullet api token here to notify of torrent completion to pushbullet
|
||||
|
||||
[reverseProxy]
|
||||
#This is for setting up goTorrent behind a reverse Proxy (with SSL, reverse proxy with no SSL will require editing the WSS connection to a WS connection manually)
|
||||
ProxyEnabled = false #bool, either false or true
|
||||
#URL is CASE SENSITIVE
|
||||
BaseURL = "yoursubdomain.domain.org/subroute/" # MUST be in the format (if you have a subdomain, and must have trailing slash) "yoursubdomain.domain.org/subroute/"
|
||||
|
||||
[EncryptionPolicy]
|
||||
|
||||
DisableEncryption = false
|
||||
ForceEncryption = false
|
||||
PreferNoEncryption = true
|
||||
|
||||
[torrentClientConfig]
|
||||
DownloadDir = 'downloading' #the full OR relative path where the torrent server stores in-progress torrents
|
||||
|
||||
Seed = true #boolean #seed after download
|
||||
|
||||
# Never send chunks to peers.
|
||||
NoUpload = false #boolean
|
||||
|
||||
#User-provided Client peer ID. If not present, one is generated automatically.
|
||||
PeerID = "" #string
|
||||
|
||||
#The address to listen for new uTP and TCP bittorrent protocol connections. DHT shares a UDP socket with uTP unless configured otherwise.
|
||||
ListenAddr = "" #Leave Blank for default, syntax "HOST:PORT"
|
||||
|
||||
#Don't announce to trackers. This only leaves DHT to discover peers.
|
||||
DisableTrackers = false #boolean
|
||||
|
||||
DisablePEX = false # boolean
|
||||
|
||||
# Don't create a DHT.
|
||||
NoDHT = false #boolean
|
||||
|
||||
#For the bittorrent protocol.
|
||||
DisableUTP = false #bool
|
||||
|
||||
#For the bittorrent protocol.
|
||||
DisableTCP = false #bool
|
||||
|
||||
#Called to instantiate storage for each added torrent. Builtin backends
|
||||
# are in the storage package. If not set, the "file" implementation is used.
|
||||
DefaultStorage = "storage.ClientImpl"
|
||||
|
||||
#encryption policy
|
||||
IPBlocklist = "" #of type iplist.Ranger
|
||||
|
||||
DisableIPv6 = false #boolean
|
||||
|
||||
Debug = false #boolean
|
||||
|
||||
#HTTP *http.Client
|
||||
|
||||
HTTPUserAgent = "" # HTTPUserAgent changes default UserAgent for HTTP requests
|
||||
|
||||
ExtendedHandshakeClientVersion = ""
|
||||
|
||||
Bep20 = ""
|
||||
|
||||
# Overrides the default DHT configuration, see dhtServerConfig #advanced.. so be careful
|
||||
DHTConfig = "" # default is "dht.ServerConfig"
|
||||
|
||||
[dhtServerConfig]
|
||||
# Set NodeId Manually. Caller must ensure that if NodeId does not conform to DHT Security Extensions, that NoSecurity is also set.
|
||||
NodeId = "" #[20]byte
|
||||
|
||||
Conn = "" # https:#godoc.org/net#PacketConn #not implemented
|
||||
|
||||
# Don't respond to queries from other nodes.
|
||||
Passive = false # boolean
|
||||
|
||||
# the default addresses are "router.utorrent.com:6881","router.bittorrent.com:6881","dht.transmissionbt.com:6881","dht.aelitis.com:6881",
|
||||
#https:#github.com/anacrolix/dht/blob/master/dht.go
|
||||
StartingNodes = "dht.GlobalBootstrapAddrs"
|
||||
|
||||
#Disable the DHT security extension: http:#www.libtorrent.org/dht_sec.html.
|
||||
NoSecurity = false
|
||||
|
||||
#Initial IP blocklist to use. Applied before serving and bootstrapping begins.
|
||||
IPBlocklist = "" #of type iplist.Ranger
|
||||
|
||||
#Used to secure the server's ID. Defaults to the Conn's LocalAddr(). Set to the IP that remote nodes will see,
|
||||
#as that IP is what they'll use to validate our ID.
|
||||
PublicIP = "" #net.IP
|
||||
|
||||
#Hook received queries. Return true if you don't want to propagate to the default handlers.
|
||||
OnQuery = "func(query *krpc.Msg, source net.Addr) (propagate bool)"
|
||||
|
||||
#Called when a peer successfully announces to us.
|
||||
OnAnnouncePeer = "func(infoHash metainfo.Hash, peer Peer)"
|
||||
|
||||
#How long to wait before re-sending queries that haven't received a response. Defaults to a random value between 4.5 and 5.5s.
|
||||
QueryResendDelay = "func() time.Duration"
|
11
config.toml
11
config.toml
@@ -8,7 +8,7 @@
|
||||
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
|
||||
DefaultMoveFolder = 'Z:\downloads' #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).
|
||||
@@ -18,19 +18,20 @@
|
||||
|
||||
[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)
|
||||
WebUIAuth = true # bool, if false no authentication is required for the webUI
|
||||
WebUIAuth = false # bool, if false no authentication is required for the webUI
|
||||
WebUIUser = "admin"
|
||||
WebUIPassword = "Password1"
|
||||
|
||||
|
||||
[notifications]
|
||||
|
||||
PushBulletToken = "" #add your pushbullet api token here to notify of torrent completion to pushbullet
|
||||
PushBulletToken = "o.8sUHemPkTCaty3u7KnyvEBN19EkeT63g" #add your pushbullet api token here to notify of torrent completion to pushbullet
|
||||
|
||||
[reverseProxy]
|
||||
#This is for setting up goTorrent behind a reverse Proxy (with SSL, reverse proxy with no SSL will require editing the WSS connection to a WS connection manually)
|
||||
ProxyEnabled = false #bool, either false or true
|
||||
BaseURL = "yoursubdomain.domain.org/subroute/" # MUST be in the format (if you have a subdomain, and must have trailing slash) "yoursubdomain.domain.org/subroute/"
|
||||
ProxyEnabled = true #bool, either false or true
|
||||
#URL is CASE SENSITIVE
|
||||
BaseURL = "derajnet.duckdns.org/gopher/" # MUST be in the format (if you have a subdomain, and must have trailing slash) "yoursubdomain.domain.org/subroute/"
|
||||
|
||||
[EncryptionPolicy]
|
||||
|
||||
|
@@ -173,7 +173,6 @@ func StartTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage Storage.To
|
||||
|
||||
}
|
||||
torrentLocalStorage.TorrentFilePriority = TorrentFilePriorityArray
|
||||
fmt.Println("TorrentUPloadLimit", torrentLocalStorage.TorrentUploadLimit)
|
||||
Storage.AddTorrentLocalStorage(torrentDbStorage, torrentLocalStorage) //writing all of the data to the database
|
||||
clientTorrent.DownloadAll() //starting the download
|
||||
CreateServerPushMessage(ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "success", Payload: "Torrent added!"}, Conn)
|
||||
@@ -267,7 +266,6 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
||||
tickUpdateStruct.UploadedBytes = fullClientDB.TotalUploadedBytes
|
||||
tickUpdateStruct.TorrentStatus = fullClientDB.Status
|
||||
tickUpdateStruct.Hash = fullClientDB.TorrentHashString //needed for index
|
||||
fmt.Println("Status", tickUpdateStruct.TorrentStatus)
|
||||
Storage.UpdateStorageTick(db, tickUpdateStruct)
|
||||
RunningTorrentArray = append(RunningTorrentArray, *fullClientDB)
|
||||
|
||||
|
@@ -69,8 +69,8 @@ func CalculateTorrentSpeed(t *torrent.Torrent, c *ClientDB, oc ClientDB) {
|
||||
dbU := float32(bytesUpload - oc.DataBytesWritten)
|
||||
rateUpload := dbU * (float32(time.Second) / dt)
|
||||
if rate >= 0 {
|
||||
rate = rate / 1024 / 1024 //creating integer to calculate ETA
|
||||
c.DownloadSpeed = fmt.Sprintf("%.2f", rate)
|
||||
rateMB := rate / 1024 / 1024 //creating MB to calculate ETA
|
||||
c.DownloadSpeed = fmt.Sprintf("%.2f", rateMB)
|
||||
c.DownloadSpeed = c.DownloadSpeed + " MB/s"
|
||||
c.downloadSpeedInt = int64(rate)
|
||||
}
|
||||
@@ -117,13 +117,12 @@ func CalculateCompletedSize(tFromStorage *Storage.TorrentLocal, activeTorrent *t
|
||||
//CalculateTorrentETA is used to estimate the remaining dl time of the torrent based on the speed that the MB are being downloaded
|
||||
func CalculateTorrentETA(tSize int64, tBytesCompleted int64, c *ClientDB) {
|
||||
missingBytes := tSize - tBytesCompleted
|
||||
missingMB := missingBytes / 1024 / 1024
|
||||
if missingMB == 0 {
|
||||
if missingBytes == 0 {
|
||||
c.ETA = "Done"
|
||||
} else if c.downloadSpeedInt == 0 {
|
||||
c.ETA = "N/A"
|
||||
} else {
|
||||
ETASeconds := missingMB / c.downloadSpeedInt
|
||||
ETASeconds := missingBytes / c.downloadSpeedInt
|
||||
str := secondsToMinutes(ETASeconds) //converting seconds to minutes + seconds
|
||||
c.ETA = str
|
||||
}
|
||||
|
37
main.go
37
main.go
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/anacrolix/torrent"
|
||||
"github.com/asdine/storm"
|
||||
Engine "github.com/deranjer/goTorrent/engine"
|
||||
Settings "github.com/deranjer/goTorrent/settings"
|
||||
Storage "github.com/deranjer/goTorrent/storage"
|
||||
jwt "github.com/dgrijalva/jwt-go"
|
||||
"github.com/gorilla/handlers"
|
||||
@@ -84,7 +85,8 @@ func handleAuthentication(conn *websocket.Conn, db *storm.DB) {
|
||||
func main() {
|
||||
Engine.Logger = Logger //Injecting the logger into all the packages
|
||||
Storage.Logger = Logger
|
||||
Config := Engine.FullClientSettingsNew() //grabbing from settings.go
|
||||
Settings.Logger = Logger
|
||||
Config := Settings.FullClientSettingsNew() //grabbing from settings.go
|
||||
if Config.LoggingOutput == "file" {
|
||||
_, err := os.Stat("logs")
|
||||
if os.IsNotExist(err) {
|
||||
@@ -131,19 +133,19 @@ func main() {
|
||||
fmt.Println("Error", err)
|
||||
fmt.Println("MAIN TOKEN: %+v\n", tokens)
|
||||
tokens.ID = 3 //creating the initial store
|
||||
claims := Engine.GoTorrentClaims{
|
||||
claims := Settings.GoTorrentClaims{
|
||||
"goTorrentWebUI",
|
||||
jwt.StandardClaims{
|
||||
Issuer: "goTorrentServer",
|
||||
},
|
||||
}
|
||||
signingkey := Engine.GenerateSigningKey() //Running this will invalidate any certs you already issued!!
|
||||
signingkey := Settings.GenerateSigningKey() //Running this will invalidate any certs you already issued!!
|
||||
fmt.Println("SigningKey", signingkey)
|
||||
authString := Engine.GenerateToken(claims, signingkey)
|
||||
authString := Settings.GenerateToken(claims, signingkey)
|
||||
tokens.SigningKey = signingkey
|
||||
fmt.Println("ClientToken: ", authString)
|
||||
Engine.GenerateClientConfigFile(Config, authString) //if first run generate the client config file
|
||||
|
||||
Settings.GenerateClientConfigFile(Config, authString) //if first run generate the client config file
|
||||
tokens.FirstToken = authString
|
||||
tokens.TokenNames = append(tokens.TokenNames, Storage.SingleToken{"firstClient"})
|
||||
err := ioutil.WriteFile("clientAuth.txt", []byte(authString), 0755)
|
||||
if err != nil {
|
||||
@@ -152,6 +154,16 @@ func main() {
|
||||
db.Save(&tokens) //Writing all of that to the database
|
||||
}
|
||||
|
||||
oldConfig, err := Storage.FetchConfig(db)
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"error": err}).Info("Assuming first run as no config found in database")
|
||||
} else {
|
||||
if oldConfig != Config {
|
||||
Settings.GenerateClientConfigFile(Config, tokens.FirstToken)
|
||||
}
|
||||
}
|
||||
Storage.SaveConfig(db, Config) //Save the config to the database
|
||||
|
||||
cronEngine := Engine.InitializeCronEngine() //Starting the cron engine for tasks
|
||||
Logger.Debug("Cron Engine Initialized...")
|
||||
|
||||
@@ -278,9 +290,9 @@ func main() {
|
||||
case "changeStorageValue":
|
||||
Logger.WithFields(logrus.Fields{"message": msg}).Debug("Client Requested Storage Location Update")
|
||||
newStorageLocation := payloadData["StorageValue"].(string)
|
||||
hashes := payloadData["ChangeStorageHashes"].([]string)
|
||||
hashes := payloadData["ChangeStorageHashes"].([]interface{})
|
||||
for _, singleHash := range hashes {
|
||||
singleTorrent := Storage.FetchTorrentFromStorage(db, singleHash)
|
||||
singleTorrent := Storage.FetchTorrentFromStorage(db, singleHash.(string))
|
||||
oldPath := singleTorrent.StoragePath
|
||||
newStorageLocationAbs, err := filepath.Abs(filepath.ToSlash(newStorageLocation))
|
||||
if err != nil {
|
||||
@@ -292,7 +304,7 @@ func main() {
|
||||
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("Change Storage Value called")
|
||||
Engine.MoveAndLeaveSymlink(Config, singleHash, db, true, oldPath)
|
||||
Engine.MoveAndLeaveSymlink(Config, singleHash.(string), db, true, oldPath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,9 +390,9 @@ func main() {
|
||||
storageValue, _ = filepath.Abs(filepath.ToSlash(Config.DefaultMoveFolder))
|
||||
}
|
||||
}
|
||||
magnetLinks := payloadData["MagnetLinks"].([]string)
|
||||
magnetLinks := payloadData["MagnetLinks"].([]interface{})
|
||||
for _, magnetLink := range magnetLinks {
|
||||
clientTorrent, err := tclient.AddMagnet(magnetLink) //reading the payload into the torrent client
|
||||
clientTorrent, err := tclient.AddMagnet(magnetLink.(string)) //reading the payload into the torrent client
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"err": err, "MagnetLink": magnetLink}).Error("Unable to add magnetlink to client!")
|
||||
Engine.CreateServerPushMessage(Engine.ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "error", Payload: "Unable to add magnetlink to client!"}, conn)
|
||||
@@ -446,6 +458,7 @@ func main() {
|
||||
oldTorrentInfo := Storage.FetchTorrentFromStorage(db, singleTorrent.InfoHash().String())
|
||||
oldTorrentInfo.TorrentStatus = "Stopped"
|
||||
oldTorrentInfo.MaxConnections = 0
|
||||
fmt.Println("Running Command...", "oldMax=singleTorrent.SetMaxEstablishedConns(0)")
|
||||
oldMax := singleTorrent.SetMaxEstablishedConns(0) //Forcing the max amount of connections allowed to zero effectively stopping it
|
||||
Logger.WithFields(logrus.Fields{"oldMaxConnections": oldMax, "torrent": singleTorrent}).Info("Forcing connections to zero for torrent")
|
||||
Storage.UpdateStorageTick(db, oldTorrentInfo) //Updating the torrent status
|
||||
@@ -517,7 +530,7 @@ func main() {
|
||||
case "setFilePriority": //TODO disable if the file is already at 100%?
|
||||
priorityRequested := payloadData["FilePriority"].(string)
|
||||
torrentHash := payloadData["TorrentHash"].(string)
|
||||
fileList := payloadData["FilePaths"].([]string)
|
||||
fileList := payloadData["FilePaths"].([]interface{})
|
||||
Logger.WithFields(logrus.Fields{"selection": torrentHash}).Info("Matched for setting file priority")
|
||||
Engine.CreateServerPushMessage(Engine.ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "info", Payload: "Received Set Priority Request"}, conn)
|
||||
Logger.WithFields(logrus.Fields{"filelist": fileList}).Debug("Full filelist for setting file priority")
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package engine
|
||||
package settings
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
@@ -1,4 +1,4 @@
|
||||
package engine
|
||||
package settings
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
@@ -1,4 +1,4 @@
|
||||
package engine
|
||||
package settings
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
@@ -14,6 +14,9 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
//Logger is the injected variable for global logger
|
||||
var Logger *logrus.Logger
|
||||
|
||||
//FullClientSettings contains all of the settings for our entire application
|
||||
type FullClientSettings struct {
|
||||
LoggingLevel logrus.Level
|
@@ -20,6 +20,7 @@ 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
|
||||
SigningKey []byte
|
||||
TokenNames []SingleToken
|
||||
FirstToken string `storm:omitempty`
|
||||
}
|
||||
|
||||
//SingleToken stores a single token and all of the associated information
|
||||
@@ -83,6 +84,25 @@ type TorrentLocal struct {
|
||||
TorrentFilePriority []TorrentFilePriority
|
||||
}
|
||||
|
||||
//SaveConfig saves the config to the database to compare for changes to settings.toml on restart
|
||||
func SaveConfig(torrentStorage *storm.DB, config interface{}) {
|
||||
err := torrentStorage.Save(&config)
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"database": torrentStorage, "error": err}).Error("Error saving Config to database!")
|
||||
}
|
||||
}
|
||||
|
||||
//FetchConfig fetches the client config from the database
|
||||
func FetchConfig(torrentStorage *storm.DB) (Engine.FullClientSettings, error) {
|
||||
config := Engine.FullClientSettings{}
|
||||
err := torrentStorage.All(&config)
|
||||
if err != nil {
|
||||
Logger.WithFields(logrus.Fields{"database": torrentStorage, "error": err}).Error("Unable to read Database into configFile!")
|
||||
return config, err
|
||||
}
|
||||
return config, err
|
||||
}
|
||||
|
||||
//FetchAllStoredTorrents is called to read in ALL local stored torrents in the boltdb database (called on server restart)
|
||||
func FetchAllStoredTorrents(torrentStorage *storm.DB) (torrentLocalArray []*TorrentLocal) {
|
||||
torrentLocalArray = []*TorrentLocal{} //creating the array of the torrentlocal struct
|
||||
|
Reference in New Issue
Block a user