fixed deployment (finally)

This commit is contained in:
daan 2019-08-10 17:56:54 +02:00
parent 3f35340c0d
commit 9374f5bab8
18 changed files with 3855 additions and 3793 deletions

View file

@ -1,6 +1,7 @@
nodemodules
src
LICENSE.md
package-lock.json
package.json
README.md
README.md
babel.config.js
.gitignore
.env

7
.env.example Normal file
View file

@ -0,0 +1,7 @@
VUE_APP_DOMAIN=http://localhost:3001
VUE_APP_WEB_USER=test
VUE_APP_WEB_PASS=test
QBIT_USER=test
QBIT_PASS=test
QBIT_HOST=localhost:8080
PORT=3001

28
.eslintrc.js Normal file
View file

@ -0,0 +1,28 @@
module.exports = {
env: {
browser: true,
commonjs: true,
es6: true,
},
extends: ['plugin:vue/essential', 'airbnb-base'],
globals: {
Atomics: 'readonly',
SharedArrayBuffer: 'readonly',
},
parserOptions: {
ecmaVersion: 2018,
},
plugins: ['vue'],
rules: {
semi: ['warn', 'never'],
'no-console' : 0,
camelcase: 0,
'no-restricted-syntax': 0,
'no-shadow': 0,
'class-methods-use-this': 0,
'prefer-promise-reject-errors': 0,
'no-underscore-dangle': 0,
'no-param-reassign' : 0,
'no-unused-vars': 0
},
}

5
.gitignore vendored
View file

@ -6,6 +6,7 @@ server/dist
# local env files
.env.local
.env.*.local
.env
# Log files
npm-debug.log*
@ -20,7 +21,3 @@ yarn-error.log*
*.njsproj
*.sln
*.sw*
#config files
server/config/config.json
src/config/config.json

View file

@ -1,15 +1,14 @@
FROM node:10-slim
WORKDIR /app
# Create app directory
WORKDIR /usr/src/app
COPY package.json /app
COPY package*.json ./
RUN npm install
COPY server /app
COPY . .
COPY dist /app
EXPOSE 3001
EXPOSE 3009
CMD ["npm", "start"]
CMD ["node", "server/server.js"]

View file

@ -1,58 +1,112 @@
# VueTorrent
A modern looking WEBUI for qBittorrent made with Vuejs & express!
(support for more clients coming in the future)
> Vue, Node, Express, qBitorrent
## Screenshots
<p align="center">
<a href="https://i.imgur.com/vPBcrK4.png"><img src="https://i.imgur.com/vPBcrK4.png" title="Desktop" alt="Desktop Screenshot" ></a>
A modern looking WEBUI for qBittorrent made with Vuejs & express!
(support for more clients coming in the future)
> Vue, Node, Express, qBitorrent
## Screenshots
<p align="center">
<a href="https://i.imgur.com/vPBcrK4.png"><img src="https://i.imgur.com/vPBcrK4.png" title="Desktop" alt="Desktop Screenshot" ></a>
</p>
<p align="center">
<a href="https://i.imgur.com/SUOEyy9.png"><img src="https://i.imgur.com/SUOEyy9.png" title="Mobile" alt="Mobile Screenshot" width="320" height="500"></a>
<p align="center">
<a href="https://i.imgur.com/SUOEyy9.png"><img src="https://i.imgur.com/SUOEyy9.png" title="Mobile" alt="Mobile Screenshot" width="320" height="540"></a>
</p>
## Installation
- Probably a Docker image but I haven't properly figured out this part yet...
Easiest way is with docker-compose:
```
vuetorrent:
image: wdaan/vuetorrent
container_name: vuetorrent
restart: always
ports:
- "4000:4000"
environment:
- VUE_APP_DOMAIN=http://172.18.0.4:4000
- VUE_APP_WEB_USER=vuetr
- VUE_APP_WEB_PASS=vuetr
- QBIT_USER=qbit
- QBIT_PASS=qbit
- QBIT_HOST=http://10.0.0.8:8080
- PORT=4000
```
## Development
FRONTEND : Git clone & npm run serve!
FRONTEND : Git clone & npm run serve!
SERVER : npm run build & npm run start!
SERVER : (npm run build, copy dist to /server (optional)) & nodemon server.js!
## Features
- viewing sessions stats ( down / upload speed, session uploaded / downloaded )
- adding / removing / pausing / resuming torrents
- sorting by every property shown!
- mobile friendly! (maybe not for thousands of torrents...)
## Contributing
I'll gladly accept help/pull requests & advice! (this is my first project of this nature, pls be kind 😛 ).
## FAQ
- **Why build this??**
- Why not? Most WebUI's look very dated and now it's no longer necessary to search for a remote control app!
- **Why build this??**
- Why not? Most WebUI's look very dated and now it's no longer necessary to search for a remote control app!
## Support
Reach out to me at one of the following places!
- <a href="https://m.me/WijnsDaan" target="_blank">`Facebook Messenger`</a>
- <a href="https://m.me/WijnsDaan" target="_blank">`Facebook Messenger`</a>
- Open up an issue 😛
## Credits
Dashboard design heavily inspired by: 'https://github.com/iamshaunjp/vuetify-playlist'
Also check out The Net Ninja's Youtube Channel.
---
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)

6746
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -6,39 +6,45 @@
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"start" : "nodemon server/server.js"
"start": "nodemon server/server.js"
},
"dependencies": {
"apexcharts": "^3.6.5",
"axios": "^0.18.0",
"date-fns": "^1.29.0",
"express": "^4.16.4",
"filepond": "^4.3.9",
"filepond-plugin-file-validate-size": "^2.1.3",
"apexcharts": "^3.8.4",
"axios": "^0.18.1",
"cors": "^2.8.5",
"date-fns": "^1.30.1",
"dotenv": "^8.0.0",
"express": "^4.17.1",
"filepond": "^4.4.12",
"filepond-plugin-file-validate-size": "^2.2.0",
"filepond-plugin-file-validate-type": "^1.2.4",
"filepond-plugin-image-preview": "^4.0.8",
"multer": "^1.4.1",
"filepond-plugin-image-preview": "^4.2.1",
"multer": "^1.4.2",
"qbittorrent-api": "^1.0.0",
"register-service-worker": "^1.6.2",
"vue": "^2.5.17",
"vue-apexcharts": "^1.3.2",
"vue-filepond": "^5.1.0",
"vue-router": "^3.0.1",
"vuetify": "^1.3.0",
"vuex": "^3.1.0"
"vue": "^2.6.10",
"vue-apexcharts": "^1.4.0",
"vue-filepond": "^5.1.3",
"vue-router": "^3.1.2",
"vuetify": "^1.5.16",
"vuex": "^3.1.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.5.5",
"@vue/cli-plugin-eslint": "^3.0.5",
"@vue/cli-plugin-pwa": "^3.6.0",
"@vue/cli-service": "^3.5.3",
"@vue/cli-plugin-babel": "^3.10.0",
"@vue/cli-plugin-eslint": "^3.10.0",
"@vue/cli-plugin-pwa": "^3.10.0",
"@vue/cli-service": "^3.10.0",
"eslint": "^6.1.0",
"eslint-config-airbnb-base": "^14.0.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-vue": "^5.2.3",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.1",
"vue-cli-plugin-vuetify": "^0.4.5",
"vue-template-compiler": "^2.5.17",
"vuetify-loader": "^1.0.5",
"webpack": "^4.30.0",
"webpack-cli": "^3.3.0"
"vue-cli-plugin-vuetify": "^0.4.6",
"vue-template-compiler": "^2.6.10",
"vuetify-loader": "^1.3.0",
"webpack": "^4.39.1",
"webpack-cli": "^3.3.6"
},
"eslintConfig": {
"root": true,

View file

@ -1,8 +0,0 @@
{
"qbit_user": "admin",
"qbit_pass": "adminadmin",
"qbit_host": "https://qbittorrent.mydomain.com",
"web_user": "username",
"web_pass": " password",
"web_host": "https://vuetorrent.mydomain.com"
}

View file

@ -1,53 +1,52 @@
module.exports = class Torrent {
constructor(data) {
this.name = data.name;
this.size = this.formatBytes(data.size);
this.birth = new Date(data.added_on * 1000).toLocaleString();
this.dlspeed = this.formatBytes(data.dlspeed, 1);
this.dloaded = this.formatBytes(data.downloaded);
this.upspeed = this.formatBytes(data.upspeed, 1);
this.uploaded = this.formatBytes(data.uploaded);
this.eta =
new Date(data.eta).getHours() +
'h ' +
new Date(data.eta).getMinutes() +
'min';
this.num_leechs = data.num_leechs;
this.num_seeds = data.num_seeds;
this.path = data.path === undefined ? '/downloads' : data.path;
this.state = this.formatState(data.state);
//hash is used to identify
this.hash = data.hash;
//available seeds
this.available_seeds = data.num_complete;
this.available_peers = data.num_incomplete;
this.name = data.name
this.size = this.formatBytes(data.size)
this.birth = new Date(data.added_on * 1000).toLocaleString()
this.dlspeed = this.formatBytes(data.dlspeed, 1)
this.dloaded = this.formatBytes(data.downloaded)
this.upspeed = this.formatBytes(data.upspeed, 1)
this.uploaded = this.formatBytes(data.uploaded)
this.eta = `${new Date(data.eta).getHours()
}h ${
new Date(data.eta).getMinutes()
}min`
this.num_leechs = data.num_leechs
this.num_seeds = data.num_seeds
this.path = data.path === undefined ? '/downloads' : data.path
this.state = this.formatState(data.state)
// hash is used to identify
this.hash = data.hash
// available seeds
this.available_seeds = data.num_complete
this.available_peers = data.num_incomplete
}
formatState(state) {
switch (state) {
case 'pausedDL':
return 'paused';
return 'paused'
case 'downloading':
return 'busy';
return 'busy'
case 'stalledDL':
return 'fail';
return 'fail'
case 'pausedUP':
return 'done';
return 'done'
case 'missingFiles':
return 'fail';
case 'stalledUP':
return 'done';
return 'fail'
case 'stalledUP':
return 'done'
default:
return undefined;
return undefined
}
}
formatBytes(a, b) {
if (0 == a) return '0 Bytes';
var c = 1024,
d = b || 2,
e = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
f = Math.floor(Math.log(a) / Math.log(c));
return parseFloat((a / Math.pow(c, f)).toFixed(d)) + ' ' + e[f];
if (a == 0) return '0 Bytes'
const c = 1024
const d = b || 2
const e = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
const f = Math.floor(Math.log(a) / Math.log(c))
return `${parseFloat((a / Math.pow(c, f)).toFixed(d))} ${e[f]}`
}
};
}

View file

@ -1,95 +1,96 @@
const api = require('qbittorrent-api');
const Torrent = require('./models/torrent.class.js');
const Stat = require('./models/stat.class.js');
const api = require('qbittorrent-api')
const dotenv = require('dotenv')
const Torrent = require('./models/torrent.class.js')
const Stat = require('./models/stat.class.js')
const info = require('./config/config.json');
dotenv.config()
//server
const qbt = api.connect(info.qbit_host, info.qbit_user, info.qbit_pass);
// server
const qbt = api.connect(process.env.QBIT_HOST, process.env.QBIT_USER, process.env.QBIT_PASS)
class Qbit {
async get_all(prop) {
return new Promise((resolve, reject) => {
qbt.all({sort: prop.name, reverse: prop.reverse}, (err, res) => {
let torrents = [];
res.forEach(el => {
//console.log(el);
const t = new Torrent(el);
torrents.push(t);
});
//console.log(torrents[0]);
resolve(torrents);
reject(err);
});
});
qbt.all({ sort: prop.name, reverse: prop.reverse }, (err, res) => {
const torrents = []
res.forEach((el) => {
// console.log(el);
const t = new Torrent(el)
torrents.push(t)
})
// console.log(torrents[0]);
resolve(torrents)
reject(err)
})
})
}
async get_session_stats() {
return new Promise((resolve, reject) => {
qbt.transferInfo((err, res) => {
let stat = new Stat(res);
//console.log(stat);
resolve(stat);
reject('something went wrong:' + err);
});
});
const stat = new Stat(res)
// console.log(stat);
resolve(stat)
reject(`something went wrong:${err}`)
})
})
}
async pause_torrents(torrents) {
return new Promise((resolve, reject) => {
qbt.pause(torrents, (err, res) => {
resolve(res);
reject('something went wrong:' + err);
});
});
resolve(res)
reject(`something went wrong:${err}`)
})
})
}
async pause_all() {
return new Promise((resolve, reject) => {
qbt.pauseAll((err, res) => {
resolve(res);
reject('something went wrong:' + err);
});
});
resolve(res)
reject(`something went wrong:${err}`)
})
})
}
async resume_torrents(torrents) {
return new Promise((resolve, reject) => {
qbt.resume(torrents, (err, res) => {
resolve(res);
reject('something went wrong:' + err);
});
});
resolve(res)
reject(`something went wrong:${err}`)
})
})
}
async resume_all() {
return new Promise((resolve, reject) => {
qbt.resumeAll((err, res) => {
resolve(res);
reject('something went wrong:' + err);
});
});
resolve(res)
reject(`something went wrong:${err}`)
})
})
}
async remove_torrents(torrents) {
return new Promise((resolve, reject) => {
qbt.delete(torrents, (err, res) => {
resolve(res);
reject('something went wrong:' + err);
});
});
resolve(res)
reject(`something went wrong:${err}`)
})
})
}
async add(torrent) {
return new Promise((resolve, reject) => {
qbt.add(torrent.path, null, null, (err, res) => {
resolve(res);
reject(err);
});
});
resolve(res)
reject(err)
})
})
}
}
const qbit = new Qbit();
const qbit = new Qbit()
module.exports = qbit;
module.exports = qbit

View file

@ -1,135 +1,130 @@
const express = require('express');
const qbit = require('./qbit');
const multer = require('multer');
const fs = require('fs');
const path = require('path');
const info = require('./config/config.json');
const express = require('express')
const multer = require('multer')
const fs = require('fs')
const path = require('path')
const qbit = require('./qbit')
let newest_torrent = {
const PORT = process.env.PORT || 3000
const newest_torrent = {
name: '',
path: ''
};
path: '',
}
const upload = multer({
dest: './src/tmp/'
});
dest: './src/tmp/',
})
//init express
const app = express();
// init express
const app = express()
app.use(express.json());
app.use(express.static('dist'));
app.use(express.json())
app.use(express.static('dist'))
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
);
res.header('Access-Control-Allow-Methods', 'DELETE');
next();
});
//requests
//login
// requests
// login
app.post('/login', (req, res) => {
if (req.body.username !== info.web_user) {
return res.send('No such user');
} else if (
req.body.username === info.web_user &&
req.body.password !== info.web_pass
if (req.body.username !== process.env.VUE_APP_WEB_USER) {
return res.send('No such user')
} if (
req.body.username === process.env.VUE_APP_WEB_USER
&& req.body.password !== process.env.VUE_APP_WEB_PASS
) {
return res.send('Wrong password!');
} else if (
req.body.username === info.web_user &&
req.body.password === info.web_pass
return res.send('Wrong password!')
} if (
req.body.username === process.env.VUE_APP_WEB_USER
&& req.body.password === process.env.VUE_APP_WEB_PASS
) {
return res.send('SUCCES');
} else {
return res.send('Something went wrong');
return res.send('SUCCES')
}
});
return res.send('Something went wrong')
})
//get all torrents
//AAAND sort torrents
// get all torrents
// AAAND sort torrents
app.post('/all', async (req, res) => {
let torrents = await qbit.get_all(req.body);
res.set('Content-Type', 'application/json');
res.send(torrents);
});
const torrents = await qbit.get_all(req.body)
res.set('Content-Type', 'application/json')
res.send(torrents)
})
//get session stats
// get session stats
app.get('/session', async (req, res) => {
let stats = await qbit.get_session_stats();
res.set('Content-Type', 'application/json');
res.send(stats);
});
const stats = await qbit.get_session_stats()
res.set('Content-Type', 'application/json')
res.send(stats)
})
//pause selected torrents
// pause selected torrents
app.post('/pause', async (req, res) => {
// console.log(req.body);
let msg = await qbit.pause_torrents(req.body);
return res.send(msg);
});
const msg = await qbit.pause_torrents(req.body)
return res.send(msg)
})
//pause all torrents
// pause all torrents
app.post('/pause_all', async (req, res) => {
let msg = await qbit.pause_all();
return res.send(msg);
});
const msg = await qbit.pause_all()
return res.send(msg)
})
//resume selected torrents
// resume selected torrents
app.post('/resume', async (req, res) => {
//console.log(req.body);
let msg = await qbit.resume_torrents(req.body);
return res.send(msg);
});
// console.log(req.body);
const msg = await qbit.resume_torrents(req.body)
return res.send(msg)
})
//resume all torrents
// resume all torrents
app.post('/resume_all', async (req, res) => {
let msg = await qbit.resume_all();
return res.send(msg);
});
const msg = await qbit.resume_all()
return res.send(msg)
})
//remove selected torrents
// remove selected torrents
app.post('/remove', async (req, res) => {
//console.log(req.body);
let msg = await qbit.remove_torrents(req.body);
return res.send(msg);
});
// console.log(req.body);
const msg = await qbit.remove_torrents(req.body)
return res.send(msg)
})
//upload files to server
// upload files to server
app.post('/upload', upload.single('file'), (req, res) => {
newest_torrent.name = req.file.filename;
newest_torrent.path = req.file.path;
return res.send('succes');
});
newest_torrent.name = req.file.filename
newest_torrent.path = req.file.path
return res.send('succes')
})
//add a torrent
// add a torrent
app.post('/add', async (req, res) => {
let msg = await qbit.add(newest_torrent);
fs.unlinkSync(newest_torrent.path);
return res.send(msg);
});
const msg = await qbit.add(newest_torrent)
fs.unlinkSync(newest_torrent.path)
return res.send(msg)
})
//delete last uploaded file
// delete last uploaded file
app.delete('/upload', upload.single('file'), (req, res) => {
fs.unlinkSync(newest_torrent.path);
return res.send('deleted file');
});
fs.unlinkSync(newest_torrent.path)
return res.send('deleted file')
})
app.listen(3009, () => console.log(`Server listening on port 3009!`));
app.listen(PORT, () => console.log(`Server listening on port ${PORT}!`))
//clear the tmp directory on every boot
const directory = path.resolve(__dirname + '/tmp');
app.get('/test', (req, res) => {
res.set('Content-Type', 'application/json')
res.send('test')
})
// clear the tmp directory on every boot
const directory = path.resolve(`${__dirname}/tmp`)
fs.readdir(directory, (err, files) => {
if (err) throw err;
if (err) console.log(err)
for (const file of files) {
fs.unlink(path.join(directory, file), err => {
if (err) throw err;
});
fs.unlink(path.join(directory, file), (err) => {
if (err) console.log(err)
})
}
});
})

View file

@ -15,7 +15,7 @@
label-idle="Drop file here..."
accepted-file-types="application/x-bittorrent"
data-max-file-size="1MB"
server="http://localhost:3000/upload"
:server="uploaddomain"
v-model="Files"
/>
</div>
@ -81,7 +81,8 @@ export default {
],
loading: false,
dialog: false,
Files: []
Files: [],
uploaddomain: this.$store.getters["GET_UPLOAD_DOMAIN"]
};
},
methods: {

View file

@ -17,11 +17,3 @@
</v-container>
</v-dialog>
</template>
<script>
export default {
data() {
return {};
}
};
</script>

View file

@ -1,8 +0,0 @@
{
"qbit_user": "admin",
"qbit_pass": "adminadmin",
"qbit_host": "https://qbittorrent.mydomain.com",
"web_user": "username",
"web_pass": " password",
"web_host": "https://vuetorrent.mydomain.com"
}

View file

@ -1,19 +1,20 @@
import Vue from 'vue';
import './plugins/vuetify';
import App from './App.vue';
import router from './router';
import VueApexCharts from 'vue-apexcharts';
import store from './services/store';
import Vue from 'vue'
import './plugins/vuetify'
import VueApexCharts from 'vue-apexcharts'
import App from './App.vue'
import router from './router'
import store from './services/store'
import './registerServiceWorker'
Vue.use(VueApexCharts);
Vue.component('apexchart', VueApexCharts);
Vue.use(VueApexCharts)
Vue.config.productionTip = false;
Vue.component('apexchart', VueApexCharts)
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app');
render: (h) => h(App),
}).$mount('#app')

View file

@ -1,64 +1,63 @@
const axios = require('axios');
const info = require('../config/config.json');
const axios = require('axios')
class Qbit {
constructor() {
this._axios = axios.create({
baseURL: info.web_host,
timeout: 1000
});
// baseURL: process.env.VUE_APP_DOMAIN,
timeout: 1000,
})
}
async getAll(sort) {
let res = await this._axios.post('/all', sort);
return res.data;
const res = await this._axios.post('/all', sort)
return res.data
}
async get_sessions_stats() {
let res = await this._axios.get('/session');
return res.data;
const res = await this._axios.get('/session')
return res.data
}
async pause_torrents(torrents) {
let res = await this._axios.post('/pause', torrents);
return res.data;
const res = await this._axios.post('/pause', torrents)
return res.data
}
async pause_all() {
let res = await this._axios.post('/pause_all');
return res.data;
const res = await this._axios.post('/pause_all')
return res.data
}
async resume_torrents(torrents) {
let res = await this._axios.post('/resume', torrents);
return res.data;
const res = await this._axios.post('/resume', torrents)
return res.data
}
async resume_all() {
let res = await this._axios.post('/resume_all');
return res.data;
const res = await this._axios.post('/resume_all')
return res.data
}
async add_torrent(torrent) {
let res = await this._axios.post('/add', torrent);
return res;
const res = await this._axios.post('/add', torrent)
return res
}
async remove_torrents(torrents) {
let res = await this._axios.post('/remove', torrents)
return res.data;
const res = await this._axios.post('/remove', torrents)
return res.data
}
async login(credentials) {
let timeout = false;
let res = await this._axios.post('/login', credentials).catch(error => {
if (error.code === 'ECONNABORTED') timeout = true;
else throw error;
});
return timeout ? 'timeout' : res.data;
let timeout = false
const res = await this._axios.post('/login', credentials).catch((error) => {
if (error.code === 'ECONNABORTED') timeout = true
else throw error
})
return timeout ? 'timeout' : res.data
}
}
const qbit = new Qbit();
const qbit = new Qbit()
export default qbit;
export default qbit

View file

@ -1,9 +1,9 @@
import Vue from 'vue';
import Vuex from 'vuex';
import Vue from 'vue'
import Vuex from 'vuex'
import qbit from './qbit';
import qbit from './qbit'
Vue.use(Vuex);
Vue.use(Vuex)
export default new Vuex.Store({
state: {
@ -13,12 +13,12 @@ export default new Vuex.Store({
dlspeed: '6 Mbps',
upspeed: '1 Mbps',
downloaded: '6.95 Gb',
uploaded: '1014 Mb'
uploaded: '1014 Mb',
},
upload_data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
download_data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
torrents: [],
init_torrents : false,
init_torrents: false,
selected_torrents: [],
network_error: false,
snackbar_error: false,
@ -27,183 +27,183 @@ export default new Vuex.Store({
succes_msg: '',
authenticated: false,
loading: false,
sort_options: {sort: 'name', reverse: false}
sort_options: { sort: 'name', reverse: false },
serverdomain: process.env.VUE_APP_DOMAIN,
},
getters: {
CONTAINS_TORRENT: state => hash => {
return state.selected_torrents.includes(hash);
}
CONTAINS_TORRENT: (state) => (hash) => state.selected_torrents.includes(hash),
GET_DOMAIN: (state) => state.serverdomain,
GET_UPLOAD_DOMAIN: (state) => `${state.serverdomain}/upload`,
},
mutations: {
REFRESH_TORRENTS: async state => {
let torrents = await qbit.getAll(state.sort_options).catch(() => {
state.network_error = true;
state.error_msg = 'Lost connection with server, reload page';
state.snackbar_error = true;
});
state.torrents = torrents.map(a => ({ ...a }));
state.init_torrents = true;
REFRESH_TORRENTS: async (state) => {
const torrents = await qbit.getAll(state.sort_options).catch(() => {
state.network_error = true
state.error_msg = 'Lost connection with server, reload page'
state.snackbar_error = true
})
state.torrents = torrents.map((a) => ({ ...a }))
state.init_torrents = true
},
REFRESH_SESSION_STATS: async state => {
let _stats = await qbit.get_sessions_stats();
//push in array for graph
state.download_data.splice(0, 1);
REFRESH_SESSION_STATS: async (state) => {
const _stats = await qbit.get_sessions_stats()
// push in array for graph
state.download_data.splice(0, 1)
if (_stats.dlspeed.indexOf('KB' > -1)) {
state.download_data.push(
_stats.dlspeed.substring(0, _stats.dlspeed.indexOf(' ')) / 1000
);
_stats.dlspeed.substring(0, _stats.dlspeed.indexOf(' ')) / 1000,
)
} else {
state.download_data.push(
_stats.dlspeed(0, _stats.dlspeed.indexOf(' '))
);
_stats.dlspeed(0, _stats.dlspeed.indexOf(' ')),
)
}
state.upload_data.splice(0, 1);
state.upload_data.splice(0, 1)
if (_stats.upspeed.indexOf('KB' > -1)) {
state.upload_data.push(
_stats.upspeed.substring(0, _stats.upspeed.indexOf(' ')) / 1000
);
_stats.upspeed.substring(0, _stats.upspeed.indexOf(' ')) / 1000,
)
} else {
state.upload_data.push(
_stats.upspeed.substring(0, _stats.upspeed.indexOf(' '))
);
_stats.upspeed.substring(0, _stats.upspeed.indexOf(' ')),
)
}
state.stats = _stats;
state.stats = _stats
},
CLEAR_INTERVALS: state => {
if (state.intervals.length > 1)
state.intervals.forEach(el => clearInterval(el));
CLEAR_INTERVALS: (state) => {
if (state.intervals.length > 1) { state.intervals.forEach((el) => clearInterval(el)) }
},
ADD_SELECTED: (state, payload) => {
state.selected_torrents.push(payload);
state.selected_torrents.push(payload)
},
REMOVE_SELECTED: (state, payload) => {
state.selected_torrents.splice(
state.selected_torrents.indexOf(payload),
1
);
1,
)
},
RESET_SELECTED: state => {
state.selected_torrents = [];
RESET_SELECTED: (state) => {
state.selected_torrents = []
},
PAUSE_TORRENTS: async state => {
let res;
PAUSE_TORRENTS: async (state) => {
let res
if (state.selected_torrents.length === 0) {
res = await qbit.pause_all();
res = await qbit.pause_all()
} else {
res = await qbit.pause_torrents(state.selected_torrents);
res = await qbit.pause_torrents(state.selected_torrents)
}
},
RESUME_TORRENTS: async state => {
let res;
RESUME_TORRENTS: async (state) => {
let res
if (state.selected_torrents.length === 0) {
res = await qbit.resume_all();
res = await qbit.resume_all()
} else {
res = await qbit.resume_torrents(state.selected_torrents);
res = await qbit.resume_torrents(state.selected_torrents)
}
},
ADD_TORRENT: async (state, payload) => {
let res = await qbit.add_torrent(payload);
const res = await qbit.add_torrent(payload)
if (res.statusText === 'OK') {
state.snackbar = true;
state.succes_msg = 'Awesome! You added a new Torrent.';
state.snackbar = true
state.succes_msg = 'Awesome! You added a new Torrent.'
setTimeout(() => {
state.snackbar = false;
}, 4000);
state.snackbar = false
}, 4000)
} else {
state.snackbar_error = true;
state.error_msg = 'Something went wrong';
state.snackbar_error = true
state.error_msg = 'Something went wrong'
setTimeout(() => {
state.snackbar_error = false;
}, 4000);
state.snackbar_error = false
}, 4000)
}
},
REMOVE_TORRENTS: async state => {
REMOVE_TORRENTS: async (state) => {
if (state.selected_torrents.length !== 0) {
let res = await qbit.remove_torrents(state.selected_torrents);
const res = await qbit.remove_torrents(state.selected_torrents)
}
},
LOGIN: async (state, payload) => {
let res = await qbit.login(payload);
const res = await qbit.login(payload)
if (res == 'timeout') {
state.loading = false;
state.snackbar_error = true;
state.error_msg = 'Express server timed out!';
state.loading = false
state.snackbar_error = true
state.error_msg = 'Express server timed out!'
setTimeout(() => {
state.snackbar_error = false;
}, 4000);
state.snackbar_error = false
}, 4000)
} else {
switch (res) {
case 'No such user':
state.snackbar_error = true;
state.error_msg = 'No such user!';
state.snackbar_error = true
state.error_msg = 'No such user!'
setTimeout(() => {
state.snackbar_error = false;
}, 4000);
break;
state.snackbar_error = false
}, 4000)
break
case 'Wrong password!':
state.snackbar_error = true;
state.error_msg = 'Wrong password!';
state.snackbar_error = true
state.error_msg = 'Wrong password!'
setTimeout(() => {
state.snackbar_error = false;
}, 4000);
break;
state.snackbar_error = false
}, 4000)
break
case 'SUCCES':
state.snackbar = true;
state.succes_msg = 'Succesfully logged in!';
state.authenticated = true;
state.snackbar = true
state.succes_msg = 'Succesfully logged in!'
state.authenticated = true
setTimeout(() => {
state.snackbar = false;
}, 4000);
break;
state.snackbar = false
}, 4000)
break
default:
state.snackbar_error = true;
state.error_msg = 'Something went wrong';
state.snackbar_error = true
state.error_msg = 'Something went wrong'
setTimeout(() => {
state.snackbar_error = false;
}, 4000);
break;
state.snackbar_error = false
}, 4000)
break
}
state.loading = false;
state.loading = false
}
}
},
},
actions: {
REFRESH_TORRENTS: context => {
REFRESH_TORRENTS: (context) => {
context.state.intervals[1] = setInterval(async () => {
context.commit('REFRESH_TORRENTS');
context.commit('REFRESH_TORRENTS')
if (context.state.network_error) {
context.commit('CLEAR_INTERVALS');
context.commit('CLEAR_INTERVALS')
}
}, 2000);
}, 2000)
},
REFRESH_SESSION_STATS: context => {
REFRESH_SESSION_STATS: (context) => {
context.state.intervals[0] = setInterval(async () => {
context.commit('REFRESH_SESSION_STATS');
}, 1000);
context.commit('REFRESH_SESSION_STATS')
}, 1000)
},
ADD_SELECTED: (context, payload) => {
context.commit('ADD_SELECTED', payload);
context.commit('ADD_SELECTED', payload)
},
REMOVE_SELECTED: (context, payload) => {
context.commit('REMOVE_SELECTED', payload);
context.commit('REMOVE_SELECTED', payload)
},
RESET_SELECTED: context => {
context.commit('RESET_SELECTED');
RESET_SELECTED: (context) => {
context.commit('RESET_SELECTED')
},
PAUSE_TORRENTS: context => {
context.commit('PAUSE_TORRENTS');
PAUSE_TORRENTS: (context) => {
context.commit('PAUSE_TORRENTS')
},
RESUME_TORRENTS: context => {
context.commit('RESUME_TORRENTS');
RESUME_TORRENTS: (context) => {
context.commit('RESUME_TORRENTS')
},
ADD_TORRENT: (context, payload) => {
context.commit('ADD_TORRENT', payload);
context.commit('ADD_TORRENT', payload)
},
REMOVE_TORRENTS: context => {
context.commit('REMOVE_TORRENTS');
REMOVE_TORRENTS: (context) => {
context.commit('REMOVE_TORRENTS')
},
LOGIN: (context, payload) => {
context.commit('LOGIN', payload);
}
}
});
context.commit('LOGIN', payload)
},
},
})