Getting ready to release 0.3.0, changing to new documentation system
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -18,6 +18,7 @@ boltbrowser.win64.exe
|
|||||||
logs/server.log
|
logs/server.log
|
||||||
.goreleaser.yml
|
.goreleaser.yml
|
||||||
config.toml.backup
|
config.toml.backup
|
||||||
|
config.1.toml
|
||||||
/public/static/js/kickwebsocket.js.backup
|
/public/static/js/kickwebsocket.js.backup
|
||||||
/public/static/js/kickwebsocket-generated.js
|
/public/static/js/kickwebsocket-generated.js
|
||||||
clientAuth.txt
|
clientAuth.txt
|
||||||
|
118
README.md
118
README.md
@@ -45,6 +45,8 @@ Image of the frontend UI
|
|||||||
|
|
||||||
- [X] Mostly generated client config from toml.config on first run
|
- [X] Mostly generated client config from toml.config on first run
|
||||||
|
|
||||||
|
- [X] Ability to view TOML settings from WebUI (and perhaps change a few as well)
|
||||||
|
|
||||||
- [ ] Unit testing completed for a large portion of the package
|
- [ ] Unit testing completed for a large portion of the package
|
||||||
|
|
||||||
- [ ] Stability/bug fixing/Optimization rewrite of some of the core structures of the WebUI and base server
|
- [ ] Stability/bug fixing/Optimization rewrite of some of the core structures of the WebUI and base server
|
||||||
@@ -53,7 +55,7 @@ Image of the frontend UI
|
|||||||
|
|
||||||
- [ ] Ability to set priority for individual files (just added to anacrolix/torrent so coming soon, already added to my UI)
|
- [ ] Ability to set priority for individual files (just added to anacrolix/torrent so coming soon, already added to my UI)
|
||||||
|
|
||||||
- [ ] Ability to view TOML settings from WebUI (and perhaps change a few as well)
|
|
||||||
|
|
||||||
|
|
||||||
- Late 2018
|
- Late 2018
|
||||||
@@ -62,119 +64,9 @@ Image of the frontend UI
|
|||||||
|
|
||||||
- [ ] React-native Android app (I don't own any Mac products so there will be no iPhone version)
|
- [ ] React-native Android app (I don't own any Mac products so there will be no iPhone version)
|
||||||
|
|
||||||
# Installation:
|
# Documentation
|
||||||
|
|
||||||
## Linux (tested on Debian)
|
All the documentation is available [here](https://deranjer.github.io/)
|
||||||
|
|
||||||
You can watch a YouTube video of me setting it up:
|
|
||||||
|
|
||||||
<a href="http://www.youtube.com/watch?feature=player_embedded&v=G0gO_cm_Oks
|
|
||||||
" target="_blank"><img src="http://img.youtube.com/vi/G0gO_cm_Oks/0.jpg"
|
|
||||||
alt="goTorrent Alpha Setup Video" width="240" height="180" border="10" /></a>
|
|
||||||
|
|
||||||
### Configuring the backend
|
|
||||||
|
|
||||||
Download the latest release from the releases tab, it will be in a tar.gz format.
|
|
||||||
|
|
||||||
Create a directory where goTorrent will run from
|
|
||||||
|
|
||||||
sudo mkdir /opt/goTorrent
|
|
||||||
|
|
||||||
Put the tar.gz release into the folder, and extract it.
|
|
||||||
|
|
||||||
tar -zxvf goTorrent_release_64-git.tar.gz
|
|
||||||
|
|
||||||
|
|
||||||
You can then remove the tar.gz if you wish. You should have something similar to the following files:
|
|
||||||
|
|
||||||
drwxr-xr-x 5 root root 9 Jan 21 14:56 .
|
|
||||||
drwxr-xr-x 5 root root 5 Jan 21 14:54 ..
|
|
||||||
-rw-rw-rw- 1 root root 1086 Dec 1 01:42 LICENSE
|
|
||||||
-rw-rw-rw- 1 root root 69 Dec 1 01:01 README.md
|
|
||||||
-rw-rw-rw- 1 root root 4466 Jan 21 03:48 config.toml
|
|
||||||
drwxr-xr-x 3 root root 3 Jan 21 14:55 dist-specific-files
|
|
||||||
-rw-rw-rw- 1 root root 12503552 Jan 21 03:53 goTorrent
|
|
||||||
drwxr-xr-x 3 root root 3 Jan 21 14:55 public
|
|
||||||
drwxr-xr-x 2 root root 3 Jan 21 14:55 templates
|
|
||||||
|
|
||||||
The `config.toml` file contains all of the settings for the server part of the application. Most of the important settings are at the top of the file, so open it with your prefered text editor.
|
|
||||||
|
|
||||||
[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 = "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
|
|
||||||
#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]
|
|
||||||
|
|
||||||
PushBulletToken = "" #add your pushbullet api token here to notify of torrent completion to pushbullet
|
|
||||||
|
|
||||||
Usually you don't need to change anything in this file, goTorrent will use your default IP address and bind to it. You can change the port if you wish.
|
|
||||||
|
|
||||||
Next, we need to make sure that the executable runs, so run the following:
|
|
||||||
|
|
||||||
chmod +x goTorrent
|
|
||||||
|
|
||||||
This will make the program executable.
|
|
||||||
|
|
||||||
###Connecting the Frontend to the Backend
|
|
||||||
|
|
||||||
We need to connect our react frontend to our Golang backend, for this we only need to edit one JS file.
|
|
||||||
|
|
||||||
nano public/static/js/kickwebsocket.js
|
|
||||||
|
|
||||||
var ws = new WebSocket("ws://192.168.1.141:8000/websocket"); //creating websocket
|
|
||||||
|
|
||||||
Just change the IP address after ws:// to your server IP address, and change the port if you changed the port in the `config.toml` file.
|
|
||||||
|
|
||||||
Then save that file and return to `/opt/goTorrent`.
|
|
||||||
|
|
||||||
Now we can test the server. For testing I recommend going into the `config.toml` file and changing the `LogOutput` to `stdout`, and the `LogLevel` to `Info`.
|
|
||||||
|
|
||||||
Then start the server:
|
|
||||||
|
|
||||||
./goTorrent
|
|
||||||
|
|
||||||
If you have `LogLevel` set to `Info`, you should see the confirmation that the client config has been generated.
|
|
||||||
|
|
||||||
You can then open your browser and connect to IP:Port (http) and you should see the main page. You will see an error for retrieving RSS feeds in stdout, but this is expected for first load.
|
|
||||||
|
|
||||||
You can press `F12` if using Chrome to open the console and click around the UI to see the logging available for the frontend.
|
|
||||||
|
|
||||||
### Running goTorrent as a Service
|
|
||||||
|
|
||||||
If you are on a linux system that uses systemd, in the `dist-specific-files\Linux-systemd\` folder there is a `goTorrent.service` file that can be used to setup systemd for goTorrent. A quick overview of what is needed.
|
|
||||||
|
|
||||||
1. Edit the systemd file to specify your specific implementation
|
|
||||||
2. Copy the file to your systemd folder, i.e. `/etc/systemd/system`
|
|
||||||
3. Enable the service `systemctl enable goTorrent.service`
|
|
||||||
4. If using a new user, create that user and assign permissions:
|
|
||||||
|
|
||||||
a. `useradd goTorrent`
|
|
||||||
|
|
||||||
b. `sudo chown -R goTorrent:goTorrent /opt/goTorrent`
|
|
||||||
|
|
||||||
c. If you want to test server: `su goTorrent` then run the executable
|
|
||||||
|
|
||||||
5. Set your `config.toml` file to the values you want.
|
|
||||||
6. Start your server: `systemctl start goTorrent`
|
|
||||||
7. Check for errors: `systemctl status goTorrent`. You can also check `logs\server.log`.
|
|
||||||
|
|
||||||
### Windows
|
|
||||||
|
|
||||||
Please see the linux instructions as they are similar, for running it as a service I havn't tried out any of the programs that claim to do that, but perhaps try [NSSM](http://nssm.cc/download)
|
|
||||||
|
|
||||||
|
|
||||||
# Special Thanks
|
# Special Thanks
|
||||||
|
@@ -5,6 +5,8 @@ import (
|
|||||||
|
|
||||||
"github.com/anacrolix/torrent"
|
"github.com/anacrolix/torrent"
|
||||||
"github.com/anacrolix/torrent/metainfo"
|
"github.com/anacrolix/torrent/metainfo"
|
||||||
|
Settings "github.com/deranjer/goTorrent/settings"
|
||||||
|
Storage "github.com/deranjer/goTorrent/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
//All the message types are first, first the server handling messages from the client
|
//All the message types are first, first the server handling messages from the client
|
||||||
@@ -37,6 +39,15 @@ type RSSFeedsNames struct {
|
|||||||
RSSFeedURL string
|
RSSFeedURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//SingleRSSFeedMessage contains the torrents/name/etc of a single torrent feed
|
||||||
|
type SingleRSSFeedMessage struct { //TODO had issues with getting this to work with Storage or Engine
|
||||||
|
MessageType string
|
||||||
|
URL string //the URL of the individual RSS feed
|
||||||
|
Name string
|
||||||
|
TotalTorrents int
|
||||||
|
Torrents []Storage.SingleRSSTorrent //name of the torrents
|
||||||
|
}
|
||||||
|
|
||||||
//TorrentList struct contains the torrent list that is sent to the client
|
//TorrentList struct contains the torrent list that is sent to the client
|
||||||
type TorrentList struct { //helps create the JSON structure that react expects to receive
|
type TorrentList struct { //helps create the JSON structure that react expects to receive
|
||||||
MessageType string `json:"MessageType"`
|
MessageType string `json:"MessageType"`
|
||||||
@@ -68,6 +79,11 @@ type TorrentFile struct {
|
|||||||
FilePriority string //Currently "High", "Normal", or "Cancel"
|
FilePriority string //Currently "High", "Normal", or "Cancel"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SettingsFile struct {
|
||||||
|
MessageType string
|
||||||
|
Config Settings.FullClientSettings
|
||||||
|
}
|
||||||
|
|
||||||
//ClientDB struct contains the struct that is used to compose the torrentlist
|
//ClientDB struct contains the struct that is used to compose the torrentlist
|
||||||
type ClientDB struct { //TODO maybe separate out the internal bits into another client struct
|
type ClientDB struct { //TODO maybe separate out the internal bits into another client struct
|
||||||
TorrentHashString string //Passed to client for displaying hash and is used to uniquely identify all torrents
|
TorrentHashString string //Passed to client for displaying hash and is used to uniquely identify all torrents
|
||||||
|
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/anacrolix/torrent"
|
"github.com/anacrolix/torrent"
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
|
Settings "github.com/deranjer/goTorrent/settings"
|
||||||
Storage "github.com/deranjer/goTorrent/storage"
|
Storage "github.com/deranjer/goTorrent/storage"
|
||||||
"github.com/mmcdole/gofeed"
|
"github.com/mmcdole/gofeed"
|
||||||
"github.com/robfig/cron"
|
"github.com/robfig/cron"
|
||||||
@@ -21,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
|
//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 FullClientSettings) {
|
func CheckTorrentWatchFolder(c *cron.Cron, db *storm.DB, tclient *torrent.Client, torrentLocalStorage Storage.TorrentLocal, config Settings.FullClientSettings) {
|
||||||
c.AddFunc("@every 5m", func() {
|
c.AddFunc("@every 5m", func() {
|
||||||
Logger.WithFields(logrus.Fields{"Watch Folder": config.TorrentWatchFolder}).Info("Running the watch folder cron job")
|
Logger.WithFields(logrus.Fields{"Watch Folder": config.TorrentWatchFolder}).Info("Running the watch folder cron job")
|
||||||
torrentFiles, err := ioutil.ReadDir(config.TorrentWatchFolder)
|
torrentFiles, err := ioutil.ReadDir(config.TorrentWatchFolder)
|
||||||
@@ -57,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
|
//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 FullClientSettings) {
|
func RefreshRSSCron(c *cron.Cron, db *storm.DB, tclient *torrent.Client, torrentLocalStorage Storage.TorrentLocal, config Settings.FullClientSettings) {
|
||||||
c.AddFunc("@hourly", func() {
|
c.AddFunc("@hourly", func() {
|
||||||
torrentHashHistory := Storage.FetchHashHistory(db)
|
torrentHashHistory := Storage.FetchHashHistory(db)
|
||||||
RSSFeedStore := Storage.FetchRSSFeeds(db)
|
RSSFeedStore := Storage.FetchRSSFeeds(db)
|
||||||
|
@@ -6,6 +6,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
|
Settings "github.com/deranjer/goTorrent/settings"
|
||||||
Storage "github.com/deranjer/goTorrent/storage"
|
Storage "github.com/deranjer/goTorrent/storage"
|
||||||
pushbullet "github.com/mitsuse/pushbullet-go"
|
pushbullet "github.com/mitsuse/pushbullet-go"
|
||||||
"github.com/mitsuse/pushbullet-go/requests"
|
"github.com/mitsuse/pushbullet-go/requests"
|
||||||
@@ -14,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
//MoveAndLeaveSymlink takes the file from the default download dir and moves it to the user specified directory and then leaves a symlink behind.
|
//MoveAndLeaveSymlink takes the file from the default download dir and moves it to the user specified directory and then leaves a symlink behind.
|
||||||
func MoveAndLeaveSymlink(config FullClientSettings, tHash string, db *storm.DB, moveDone bool, oldPath string) { //moveDone and oldPath are for moving a completed torrent
|
func MoveAndLeaveSymlink(config Settings.FullClientSettings, tHash string, db *storm.DB, moveDone bool, oldPath string) { //moveDone and oldPath are for moving a completed torrent
|
||||||
tStorage := Storage.FetchTorrentFromStorage(db, tHash)
|
tStorage := Storage.FetchTorrentFromStorage(db, tHash)
|
||||||
Logger.WithFields(logrus.Fields{"Torrent Name": tStorage.TorrentName}).Info("Move and Create symlink started for torrent")
|
Logger.WithFields(logrus.Fields{"Torrent Name": tStorage.TorrentName}).Info("Move and Create symlink started for torrent")
|
||||||
var oldFilePath string
|
var oldFilePath string
|
||||||
@@ -77,7 +78,7 @@ func MoveAndLeaveSymlink(config FullClientSettings, tHash string, db *storm.DB,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func notifyUser(tStorage Storage.TorrentLocal, config FullClientSettings, db *storm.DB) {
|
func notifyUser(tStorage Storage.TorrentLocal, config Settings.FullClientSettings, db *storm.DB) {
|
||||||
Logger.WithFields(logrus.Fields{"New File Path": tStorage.StoragePath, "Torrent Name": tStorage.TorrentName}).Info("Attempting to notify user..")
|
Logger.WithFields(logrus.Fields{"New File Path": tStorage.StoragePath, "Torrent Name": tStorage.TorrentName}).Info("Attempting to notify user..")
|
||||||
tStorage.TorrentMoved = true
|
tStorage.TorrentMoved = true
|
||||||
//Storage.AddTorrentLocalStorage(db, tStorage) //Updating the fact that we moved the torrent
|
//Storage.AddTorrentLocalStorage(db, tStorage) //Updating the fact that we moved the torrent
|
||||||
|
@@ -4,12 +4,13 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
|
Settings "github.com/deranjer/goTorrent/settings"
|
||||||
Storage "github.com/deranjer/goTorrent/storage"
|
Storage "github.com/deranjer/goTorrent/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMoveAndLeaveSymlink(t *testing.T) {
|
func TestMoveAndLeaveSymlink(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
config FullClientSettings
|
config Settings.FullClientSettings
|
||||||
tStorage Storage.TorrentLocal
|
tStorage Storage.TorrentLocal
|
||||||
db *storm.DB
|
db *storm.DB
|
||||||
}
|
}
|
||||||
@@ -29,7 +30,7 @@ func TestMoveAndLeaveSymlink(t *testing.T) {
|
|||||||
func Test_notifyUser(t *testing.T) {
|
func Test_notifyUser(t *testing.T) {
|
||||||
type args struct {
|
type args struct {
|
||||||
tStorage Storage.TorrentLocal
|
tStorage Storage.TorrentLocal
|
||||||
config FullClientSettings
|
config Settings.FullClientSettings
|
||||||
db *storm.DB
|
db *storm.DB
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/anacrolix/torrent"
|
"github.com/anacrolix/torrent"
|
||||||
"github.com/anacrolix/torrent/metainfo"
|
"github.com/anacrolix/torrent/metainfo"
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
|
Settings "github.com/deranjer/goTorrent/settings"
|
||||||
Storage "github.com/deranjer/goTorrent/storage"
|
Storage "github.com/deranjer/goTorrent/storage"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/mmcdole/gofeed"
|
"github.com/mmcdole/gofeed"
|
||||||
@@ -127,7 +128,7 @@ func readTorrentFileFromDB(element *Storage.TorrentLocal, tclient *torrent.Clien
|
|||||||
}
|
}
|
||||||
|
|
||||||
//StartTorrent creates the storage.db entry and starts A NEW TORRENT and adds to the running torrent array
|
//StartTorrent creates the storage.db entry and starts A NEW TORRENT and adds to the running torrent array
|
||||||
func StartTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage Storage.TorrentLocal, torrentDbStorage *storm.DB, torrentType, torrentFilePathAbs, torrentStoragePath, labelValue string, config FullClientSettings) {
|
func StartTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage Storage.TorrentLocal, torrentDbStorage *storm.DB, torrentType, torrentFilePathAbs, torrentStoragePath, labelValue string, config Settings.FullClientSettings) {
|
||||||
timedOut := timeOutInfo(clientTorrent, 45) //seeing if adding the torrent times out (giving 45 seconds)
|
timedOut := timeOutInfo(clientTorrent, 45) //seeing if adding the torrent times out (giving 45 seconds)
|
||||||
if timedOut { //if we fail to add the torrent return
|
if timedOut { //if we fail to add the torrent return
|
||||||
return
|
return
|
||||||
@@ -179,7 +180,7 @@ func StartTorrent(clientTorrent *torrent.Torrent, torrentLocalStorage Storage.To
|
|||||||
}
|
}
|
||||||
|
|
||||||
//CreateRunningTorrentArray creates the entire torrent list to pass to client
|
//CreateRunningTorrentArray creates the entire torrent list to pass to client
|
||||||
func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Storage.TorrentLocal, PreviousTorrentArray []ClientDB, config FullClientSettings, db *storm.DB) (RunningTorrentArray []ClientDB) {
|
func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Storage.TorrentLocal, PreviousTorrentArray []ClientDB, config Settings.FullClientSettings, db *storm.DB) (RunningTorrentArray []ClientDB) {
|
||||||
|
|
||||||
for _, singleTorrentFromStorage := range TorrentLocalArray {
|
for _, singleTorrentFromStorage := range TorrentLocalArray {
|
||||||
var singleTorrent *torrent.Torrent
|
var singleTorrent *torrent.Torrent
|
||||||
@@ -274,7 +275,7 @@ func CreateRunningTorrentArray(tclient *torrent.Client, TorrentLocalArray []*Sto
|
|||||||
}
|
}
|
||||||
|
|
||||||
//CreateFileListArray creates a file list for a single torrent that is selected and sent to the server
|
//CreateFileListArray creates a file list for a single torrent that is selected and sent to the server
|
||||||
func CreateFileListArray(tclient *torrent.Client, selectedHash string, db *storm.DB, config FullClientSettings) TorrentFileList {
|
func CreateFileListArray(tclient *torrent.Client, selectedHash string, db *storm.DB, config Settings.FullClientSettings) TorrentFileList {
|
||||||
runningTorrents := tclient.Torrents() //don't need running torrent array since we aren't adding or deleting from storage
|
runningTorrents := tclient.Torrents() //don't need running torrent array since we aren't adding or deleting from storage
|
||||||
torrentFileListStorage := Storage.FetchTorrentFromStorage(db, selectedHash)
|
torrentFileListStorage := Storage.FetchTorrentFromStorage(db, selectedHash)
|
||||||
TorrentFileListSelected := TorrentFileList{}
|
TorrentFileListSelected := TorrentFileList{}
|
||||||
|
@@ -7,6 +7,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/anacrolix/torrent"
|
"github.com/anacrolix/torrent"
|
||||||
|
Settings "github.com/deranjer/goTorrent/settings"
|
||||||
"github.com/deranjer/goTorrent/storage"
|
"github.com/deranjer/goTorrent/storage"
|
||||||
Storage "github.com/deranjer/goTorrent/storage"
|
Storage "github.com/deranjer/goTorrent/storage"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@@ -139,7 +140,7 @@ func CalculateUploadRatio(t *torrent.Torrent, c *ClientDB) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//CalculateTorrentStatus is used to determine what the STATUS column of the frontend will display ll2
|
//CalculateTorrentStatus is used to determine what the STATUS column of the frontend will display ll2
|
||||||
func CalculateTorrentStatus(t *torrent.Torrent, c *ClientDB, config FullClientSettings, tFromStorage *storage.TorrentLocal, bytesCompleted int64, totalSize int64) {
|
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
|
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
|
||||||
c.Status = "Stopped"
|
c.Status = "Stopped"
|
||||||
c.MaxConnections = 0
|
c.MaxConnections = 0
|
||||||
|
45
main.go
45
main.go
@@ -9,6 +9,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
_ "net/http/pprof"
|
_ "net/http/pprof"
|
||||||
@@ -26,15 +27,6 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
//SingleRSSFeedMessage will most likely be deprecated as this is the only way I could get it working currently
|
|
||||||
type SingleRSSFeedMessage struct { //TODO had issues with getting this to work with Storage or Engine
|
|
||||||
MessageType string
|
|
||||||
URL string //the URL of the individual RSS feed
|
|
||||||
Name string
|
|
||||||
TotalTorrents int
|
|
||||||
Torrents []Storage.SingleRSSTorrent //name of the torrents
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
//Logger does logging for the entire project
|
//Logger does logging for the entire project
|
||||||
Logger = logrus.New()
|
Logger = logrus.New()
|
||||||
@@ -144,7 +136,6 @@ func main() {
|
|||||||
authString := Settings.GenerateToken(claims, signingkey)
|
authString := Settings.GenerateToken(claims, signingkey)
|
||||||
tokens.SigningKey = signingkey
|
tokens.SigningKey = signingkey
|
||||||
fmt.Println("ClientToken: ", authString)
|
fmt.Println("ClientToken: ", authString)
|
||||||
Settings.GenerateClientConfigFile(Config, authString) //if first run generate the client config file
|
|
||||||
tokens.FirstToken = authString
|
tokens.FirstToken = authString
|
||||||
tokens.TokenNames = append(tokens.TokenNames, Storage.SingleToken{"firstClient"})
|
tokens.TokenNames = append(tokens.TokenNames, Storage.SingleToken{"firstClient"})
|
||||||
err := ioutil.WriteFile("clientAuth.txt", []byte(authString), 0755)
|
err := ioutil.WriteFile("clientAuth.txt", []byte(authString), 0755)
|
||||||
@@ -156,9 +147,13 @@ func main() {
|
|||||||
|
|
||||||
oldConfig, err := Storage.FetchConfig(db)
|
oldConfig, err := Storage.FetchConfig(db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Logger.WithFields(logrus.Fields{"error": err}).Info("Assuming first run as no config found in database")
|
Logger.WithFields(logrus.Fields{"error": err}).Info("Assuming first run as no config found in database, client config being generated")
|
||||||
|
Settings.GenerateClientConfigFile(Config, tokens.FirstToken) //if first run generate the client config file
|
||||||
} else {
|
} else {
|
||||||
if oldConfig != Config {
|
if reflect.DeepEqual(oldConfig.ClientConnectSettings, Config.ClientConnectSettings) {
|
||||||
|
Logger.WithFields(logrus.Fields{"error": err}).Info("Configs are the same, not regenerating client config")
|
||||||
|
} else {
|
||||||
|
Logger.WithFields(logrus.Fields{"error": err}).Info("Config has changed, re-writting config")
|
||||||
Settings.GenerateClientConfigFile(Config, tokens.FirstToken)
|
Settings.GenerateClientConfigFile(Config, tokens.FirstToken)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,16 +176,14 @@ func main() {
|
|||||||
} else {
|
} else {
|
||||||
Logger.Info("Database is empty, no torrents loaded")
|
Logger.Info("Database is empty, no torrents loaded")
|
||||||
}
|
}
|
||||||
Engine.CheckTorrentWatchFolder(cronEngine, db, tclient, torrentLocalStorage, Config)
|
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.RefreshRSSCron(cronEngine, db, tclient, torrentLocalStorage, Config) // 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 := mux.NewRouter() //setting up the handler for the web backend
|
||||||
//reverseProxy := handlers.ProxyHeaders(router) //handlers.ProxyHeaders(router) //TODO pull this from the config file
|
|
||||||
router.HandleFunc("/", serveHome) //Serving the main page for our SPA
|
router.HandleFunc("/", serveHome) //Serving the main page for our SPA
|
||||||
//http.Handle("/static/", http.FileServer(http.Dir("public")))
|
|
||||||
router.PathPrefix("/static/").Handler(http.FileServer(http.Dir("public")))
|
router.PathPrefix("/static/").Handler(http.FileServer(http.Dir("public")))
|
||||||
http.Handle("/", router)
|
http.Handle("/", router)
|
||||||
router.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) { //exposing the data to the
|
router.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) { //TODO, remove this
|
||||||
TorrentLocalArray = Storage.FetchAllStoredTorrents(db)
|
TorrentLocalArray = Storage.FetchAllStoredTorrents(db)
|
||||||
RunningTorrentArray = Engine.CreateRunningTorrentArray(tclient, TorrentLocalArray, PreviousTorrentArray, Config, db) //Updates the RunningTorrentArray with the current client data as well
|
RunningTorrentArray = Engine.CreateRunningTorrentArray(tclient, TorrentLocalArray, PreviousTorrentArray, Config, db) //Updates the RunningTorrentArray with the current client data as well
|
||||||
var torrentlistArray = new(Engine.TorrentList)
|
var torrentlistArray = new(Engine.TorrentList)
|
||||||
@@ -213,7 +206,7 @@ func main() {
|
|||||||
if Authenticated != true {
|
if Authenticated != true {
|
||||||
handleAuthentication(conn, db)
|
handleAuthentication(conn, db)
|
||||||
} else { //If we are authenticated inject the connection into the other packages
|
} else { //If we are authenticated inject the connection into the other packages
|
||||||
Logger.WithFields(logrus.Fields{"Conn": conn}).Info("Authenticated, websocket connection available!")
|
Logger.Info("Authenticated, websocket connection available!")
|
||||||
}
|
}
|
||||||
Engine.Conn = conn
|
Engine.Conn = conn
|
||||||
Storage.Conn = conn
|
Storage.Conn = conn
|
||||||
@@ -260,12 +253,6 @@ func main() {
|
|||||||
FileListArray := Engine.CreateFileListArray(tclient, fileListArrayRequest, db, Config)
|
FileListArray := Engine.CreateFileListArray(tclient, fileListArrayRequest, db, Config)
|
||||||
conn.WriteJSON(FileListArray) //writing the JSON to the client
|
conn.WriteJSON(FileListArray) //writing the JSON to the client
|
||||||
|
|
||||||
//case "torrentDetailedInfo":
|
|
||||||
// Logger.WithFields(logrus.Fields{"message": msg}).Debug("Client Requested TorrentListDetail Update")
|
|
||||||
// fileListArrayRequest := payloadData["FileListArray"].(string)
|
|
||||||
// torrentDetailArray := Engine.CreateTorrentDetailJSON(tclient, msg.Payload[0], db)
|
|
||||||
// conn.WriteJSON(torrentDetailArray)
|
|
||||||
|
|
||||||
case "torrentPeerListRequest":
|
case "torrentPeerListRequest":
|
||||||
Logger.WithFields(logrus.Fields{"message": msg}).Debug("Client Requested PeerList Update")
|
Logger.WithFields(logrus.Fields{"message": msg}).Debug("Client Requested PeerList Update")
|
||||||
peerListArrayRequest := payloadData["PeerListHash"].(string)
|
peerListArrayRequest := payloadData["PeerListHash"].(string)
|
||||||
@@ -310,11 +297,7 @@ func main() {
|
|||||||
|
|
||||||
case "settingsFileRequest":
|
case "settingsFileRequest":
|
||||||
Logger.WithFields(logrus.Fields{"message": msg}).Debug("Client Requested Settings File")
|
Logger.WithFields(logrus.Fields{"message": msg}).Debug("Client Requested Settings File")
|
||||||
clientSettingsFile, err := json.Marshal(Config)
|
clientSettingsFile := Engine.SettingsFile{MessageType: "settingsFile", Config: Config}
|
||||||
if err != nil {
|
|
||||||
Logger.WithFields(logrus.Fields{"message": msg}).Error("Unable to Marshal Setting file into JSON!")
|
|
||||||
Engine.CreateServerPushMessage(Engine.ServerPushMessage{MessageType: "serverPushMessage", MessageLevel: "error", Payload: "Unable to marshal config into JSON!"}, conn)
|
|
||||||
}
|
|
||||||
conn.WriteJSON(clientSettingsFile)
|
conn.WriteJSON(clientSettingsFile)
|
||||||
|
|
||||||
case "rssFeedRequest":
|
case "rssFeedRequest":
|
||||||
@@ -370,7 +353,7 @@ func main() {
|
|||||||
RSSFeedURL := payloadData["RSSURL"].(string)
|
RSSFeedURL := payloadData["RSSURL"].(string)
|
||||||
Logger.WithFields(logrus.Fields{"RSSFeed": RSSFeedURL}).Info("Requesting torrentList for feed..")
|
Logger.WithFields(logrus.Fields{"RSSFeed": RSSFeedURL}).Info("Requesting torrentList for feed..")
|
||||||
UpdatedRSSFeed := Engine.RefreshSingleRSSFeed(db, Storage.FetchSpecificRSSFeed(db, RSSFeedURL))
|
UpdatedRSSFeed := Engine.RefreshSingleRSSFeed(db, Storage.FetchSpecificRSSFeed(db, RSSFeedURL))
|
||||||
TorrentRSSList := SingleRSSFeedMessage{MessageType: "rssTorrentList", URL: RSSFeedURL, Name: UpdatedRSSFeed.Name, TotalTorrents: len(UpdatedRSSFeed.Torrents), Torrents: UpdatedRSSFeed.Torrents}
|
TorrentRSSList := Engine.SingleRSSFeedMessage{MessageType: "rssTorrentList", URL: RSSFeedURL, Name: UpdatedRSSFeed.Name, TotalTorrents: len(UpdatedRSSFeed.Torrents), Torrents: UpdatedRSSFeed.Torrents}
|
||||||
Logger.WithFields(logrus.Fields{"TorrentRSSList": TorrentRSSList}).Debug("Returning Torrent list from RSSFeed to client")
|
Logger.WithFields(logrus.Fields{"TorrentRSSList": TorrentRSSList}).Debug("Returning Torrent list from RSSFeed to client")
|
||||||
conn.WriteJSON(TorrentRSSList)
|
conn.WriteJSON(TorrentRSSList)
|
||||||
|
|
||||||
|
File diff suppressed because one or more lines are too long
@@ -17,10 +17,7 @@ import (
|
|||||||
//Logger is the injected variable for global logger
|
//Logger is the injected variable for global logger
|
||||||
var Logger *logrus.Logger
|
var Logger *logrus.Logger
|
||||||
|
|
||||||
//FullClientSettings contains all of the settings for our entire application
|
type ClientConnectSettings struct {
|
||||||
type FullClientSettings struct {
|
|
||||||
LoggingLevel logrus.Level
|
|
||||||
LoggingOutput string
|
|
||||||
HTTPAddr string
|
HTTPAddr string
|
||||||
HTTPAddrIP string
|
HTTPAddrIP string
|
||||||
UseProxy bool
|
UseProxy bool
|
||||||
@@ -28,18 +25,27 @@ type FullClientSettings struct {
|
|||||||
BaseURL string
|
BaseURL string
|
||||||
ClientUsername string
|
ClientUsername string
|
||||||
ClientPassword string
|
ClientPassword string
|
||||||
Version int
|
PushBulletToken string `json:"-"`
|
||||||
TorrentConfig torrent.Config
|
}
|
||||||
TFileUploadFolder string
|
|
||||||
SeedRatioStop float64
|
//FullClientSettings contains all of the settings for our entire application
|
||||||
PushBulletToken string
|
type FullClientSettings struct {
|
||||||
DefaultMoveFolder string
|
ID int `storm:"id,unique"`
|
||||||
TorrentWatchFolder string
|
LoggingLevel logrus.Level
|
||||||
|
LoggingOutput string
|
||||||
|
Version int
|
||||||
|
TorrentConfig torrent.Config `json:"-"`
|
||||||
|
TFileUploadFolder string
|
||||||
|
SeedRatioStop float64
|
||||||
|
DefaultMoveFolder string
|
||||||
|
TorrentWatchFolder string
|
||||||
|
ClientConnectSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
//default is called if there is a parsing error
|
//default is called if there is a parsing error
|
||||||
func defaultConfig() FullClientSettings {
|
func defaultConfig() FullClientSettings {
|
||||||
var Config FullClientSettings
|
var Config FullClientSettings
|
||||||
|
Config.ID = 4 //Unique ID for StormDB
|
||||||
Config.Version = 1.0
|
Config.Version = 1.0
|
||||||
Config.LoggingLevel = 3 //Warn level
|
Config.LoggingLevel = 3 //Warn level
|
||||||
Config.TorrentConfig.DataDir = "downloads" //the absolute or relative path of the default download directory for torrents
|
Config.TorrentConfig.DataDir = "downloads" //the absolute or relative path of the default download directory for torrents
|
||||||
@@ -225,21 +231,23 @@ func FullClientSettingsNew() FullClientSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Config := FullClientSettings{
|
Config := FullClientSettings{
|
||||||
LoggingLevel: logLevel,
|
LoggingLevel: logLevel,
|
||||||
LoggingOutput: logOutput,
|
LoggingOutput: logOutput,
|
||||||
SeedRatioStop: seedRatioStop,
|
SeedRatioStop: seedRatioStop,
|
||||||
HTTPAddr: httpAddr,
|
ClientConnectSettings: ClientConnectSettings{
|
||||||
HTTPAddrIP: httpAddrIP,
|
HTTPAddr: httpAddr,
|
||||||
UseProxy: proxySet,
|
HTTPAddrIP: httpAddrIP,
|
||||||
WebsocketClientPort: websocketClientPort,
|
UseProxy: proxySet,
|
||||||
ClientUsername: webUIUser,
|
WebsocketClientPort: websocketClientPort,
|
||||||
ClientPassword: webUIPasswordHash,
|
ClientUsername: webUIUser,
|
||||||
TorrentConfig: tConfig,
|
ClientPassword: webUIPasswordHash,
|
||||||
BaseURL: baseURL,
|
BaseURL: baseURL,
|
||||||
TFileUploadFolder: "uploadedTorrents",
|
PushBulletToken: pushBulletToken,
|
||||||
PushBulletToken: pushBulletToken,
|
},
|
||||||
DefaultMoveFolder: defaultMoveFolderAbs,
|
TFileUploadFolder: "uploadedTorrents",
|
||||||
TorrentWatchFolder: torrentWatchFolderAbs,
|
TorrentConfig: tConfig,
|
||||||
|
DefaultMoveFolder: defaultMoveFolderAbs,
|
||||||
|
TorrentWatchFolder: torrentWatchFolderAbs,
|
||||||
}
|
}
|
||||||
|
|
||||||
return Config
|
return Config
|
||||||
|
@@ -5,6 +5,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/asdine/storm"
|
"github.com/asdine/storm"
|
||||||
|
Settings "github.com/deranjer/goTorrent/settings"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@@ -85,7 +86,8 @@ type TorrentLocal struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//SaveConfig saves the config to the database to compare for changes to settings.toml on restart
|
//SaveConfig saves the config to the database to compare for changes to settings.toml on restart
|
||||||
func SaveConfig(torrentStorage *storm.DB, config interface{}) {
|
func SaveConfig(torrentStorage *storm.DB, config Settings.FullClientSettings) {
|
||||||
|
config.ID = 4
|
||||||
err := torrentStorage.Save(&config)
|
err := torrentStorage.Save(&config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Logger.WithFields(logrus.Fields{"database": torrentStorage, "error": err}).Error("Error saving Config to database!")
|
Logger.WithFields(logrus.Fields{"database": torrentStorage, "error": err}).Error("Error saving Config to database!")
|
||||||
@@ -93,9 +95,9 @@ func SaveConfig(torrentStorage *storm.DB, config interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//FetchConfig fetches the client config from the database
|
//FetchConfig fetches the client config from the database
|
||||||
func FetchConfig(torrentStorage *storm.DB) (Engine.FullClientSettings, error) {
|
func FetchConfig(torrentStorage *storm.DB) (Settings.FullClientSettings, error) {
|
||||||
config := Engine.FullClientSettings{}
|
config := Settings.FullClientSettings{}
|
||||||
err := torrentStorage.All(&config)
|
err := torrentStorage.One("ID", 4, &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Logger.WithFields(logrus.Fields{"database": torrentStorage, "error": err}).Error("Unable to read Database into configFile!")
|
Logger.WithFields(logrus.Fields{"database": torrentStorage, "error": err}).Error("Unable to read Database into configFile!")
|
||||||
return config, err
|
return config, err
|
||||||
|
Reference in New Issue
Block a user