feat: Add/Ban peers support (#598) @Larsluph

This commit is contained in:
Rémi Marseault 2023-01-09 09:11:13 +01:00 committed by GitHub
parent 004c8f57d2
commit 59b47dbc8d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 106 additions and 47 deletions

View file

@ -1,33 +1,61 @@
<template> <template>
<v-card flat> <v-card flat>
<v-data-table v-if="peers" dense :headers="headers" :items="peers" :items-per-page="-1" :hide-default-footer="true" mobile-breakpoint="0"> <v-card-text class="pa-0">
<template #item="row"> <v-data-table v-if="peers" v-model="selectedPeers" dense show-select :headers="headers" :items="peers" :items-per-page="-1" item-key="key" mobile-breakpoint="0">
<tr> <template #body="{ items }">
<td class="ip"> <tbody>
<template v-if="row.item.country_code"> <tr v-for="item in items" :key="item.key">
<img v-if="isWindows" class="country-flag" :title="row.item.country" :alt="codeToFlag(row.item.country_code).char" :src="codeToFlag(row.item.country_code).url" /> <td>
<template v-else> <v-checkbox v-model="selectedPeers" :value="item.key" hide-details class="pa-0 ma-0" color="accent" />
{{ codeToFlag(row.item.country_code).char }} </td>
<td class="ip">
<template v-if="item.country_code">
<img v-if="isWindows" class="country-flag" :title="item.country" :alt="codeToFlag(item.country_code).char" :src="codeToFlag(item.country_code).url" />
<template v-else>
{{ codeToFlag(item.country_code).char }}
</template>
</template> </template>
</template> {{ item.ip }}
{{ row.item.ip }} <span class="grey--text">:{{ item.port }}</span>
<span class="grey--text">:{{ row.item.port }}</span> </td>
</td> <td>{{ item.connection }}</td>
<td>{{ row.item.connection }}</td> <td :title="item.flags_desc">
<td :title="row.item.flags_desc"> {{ item.flags }}
{{ row.item.flags }} </td>
</td> <td>{{ item.client }}</td>
<td>{{ row.item.client }}</td> <td>{{ item.progress | progress }}</td>
<td>{{ row.item.progress | progress }}</td> <td>{{ item.dl_speed | networkSpeed }}</td>
<td>{{ row.item.dl_speed | networkSpeed }}</td> <td>{{ item.downloaded | networkSize }}</td>
<td>{{ row.item.downloaded | networkSize }}</td> <td>{{ item.up_speed | networkSpeed }}</td>
<td>{{ row.item.up_speed | networkSpeed }}</td> <td>{{ item.uploaded | networkSize }}</td>
<td>{{ row.item.uploaded | networkSize }}</td> <td>{{ item.relevance | progress }}</td>
<td>{{ row.item.relevance | progress }}</td> <td>{{ item.files }}</td>
<td>{{ row.item.files }}</td> </tr>
</tr> </tbody>
</template> </template>
</v-data-table> </v-data-table>
</v-card-text>
<v-card-actions class="justify-center">
<v-btn class="error white--text elevation-0 px-4 mx-2" @click="banPeers">Ban</v-btn>
<v-dialog v-model="peersDialog" content-class="rounded-form" persistent max-width="290">
<template #activator="{ on, attrs }">
<v-btn class="accent white--text elevation-0 px-4 mx-2" v-bind="attrs" v-on="on">Add</v-btn>
</template>
<v-card>
<v-card-title class="justify-center">
<h3>Add Peers</h3>
</v-card-title>
<v-card-text>
<v-textarea v-model="newPeers" label="Peers" rows="1" required autofocus auto-grow clearable hint="One link per line" />
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn color="red darken-1" text @click="closeAddPeers">Cancel</v-btn>
<v-btn color="green darken-1" text @click="addPeers">Add</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-card-actions>
</v-card> </v-card>
</template> </template>
@ -42,8 +70,11 @@ export default {
mixins: [FullScreenModal], mixins: [FullScreenModal],
props: { hash: String, isActive: Boolean }, props: { hash: String, isActive: Boolean },
data: () => ({ data: () => ({
peersDialog: false,
refreshTimer: '', refreshTimer: '',
peersObj: null peersObj: null,
newPeers: '',
selectedPeers: []
}), }),
computed: { computed: {
rid: { rid: {
@ -64,10 +95,7 @@ export default {
{ text: this.$i18n.t('modals.detail.pagePeers.flags'), value: 'flags' }, { text: this.$i18n.t('modals.detail.pagePeers.flags'), value: 'flags' },
{ text: this.$i18n.t('modals.detail.pagePeers.client'), value: 'client' }, { text: this.$i18n.t('modals.detail.pagePeers.client'), value: 'client' },
{ text: this.$i18n.t('modals.detail.pagePeers.progress'), value: 'progress' }, { text: this.$i18n.t('modals.detail.pagePeers.progress'), value: 'progress' },
{ { text: this.$i18n.t('modals.detail.pagePeers.downloadSpeed'), value: 'dl_speed' },
text: this.$i18n.t('modals.detail.pagePeers.downloadSpeed'),
value: 'dl_speed'
},
{ text: this.$i18n.t('modals.detail.pagePeers.downloaded'), value: 'downloaded' }, { text: this.$i18n.t('modals.detail.pagePeers.downloaded'), value: 'downloaded' },
{ text: this.$i18n.t('modals.detail.pagePeers.upSpeed'), value: 'up_speed' }, { text: this.$i18n.t('modals.detail.pagePeers.upSpeed'), value: 'up_speed' },
{ text: this.$i18n.t('modals.detail.pagePeers.uploaded'), value: 'uploaded' }, { text: this.$i18n.t('modals.detail.pagePeers.uploaded'), value: 'uploaded' },
@ -83,9 +111,7 @@ export default {
this.refreshTimer = setInterval( this.refreshTimer = setInterval(
function () { function () {
this.getTorrentPeers() this.getTorrentPeers()
}.bind(this), }.bind(this), 2000)
2000
)
} else { } else {
clearTimeout(this.refreshTimer) clearTimeout(this.refreshTimer)
} }
@ -106,6 +132,28 @@ export default {
this.rid = data.rid this.rid = data.rid
this.peersObj = data.peers this.peersObj = data.peers
},
async addPeers() {
if (this.newPeers.length === 0) {
this.peersDialog = false
return
}
qbit.addTorrentPeers([this.hash], this.newPeers.split('\n'))
this.newPeers = ''
await this.getTorrentPeers()
this.peersDialog = false
},
closeAddPeers() {
this.newPeers = ''
this.peersDialog = false
},
async banPeers() {
if (this.selectedPeers.length === 0) return
qbit.banPeers(this.selectedPeers)
this.selectedPeers = []
await this.getTorrentPeers()
} }
} }
} }

View file

@ -6,7 +6,7 @@
<tbody> <tbody>
<tr v-for="item in items" :key="item.url"> <tr v-for="item in items" :key="item.url">
<td> <td>
<v-checkbox v-if="typeof item.tier === 'number'" v-model="selectedTrackers" :value="item" hide-details class="pa-0 ma-0" color="accent" /> <v-checkbox v-if="item.isSelectable" v-model="selectedTrackers" :value="item" hide-details class="pa-0 ma-0" color="accent" />
</td> </td>
<td>{{ item.tier }}</td> <td>{{ item.tier }}</td>
<td>{{ item.url }}</td> <td>{{ item.url }}</td>
@ -22,10 +22,10 @@
</v-data-table> </v-data-table>
</v-card-text> </v-card-text>
<v-card-actions class="justify-center"> <v-card-actions class="justify-center">
<v-btn class="error white--text elevation-0 px-4 mx-2" @click="DeleteTrackers"> Delete </v-btn> <v-btn class="error white--text elevation-0 px-4 mx-2" @click="DeleteTrackers">Delete</v-btn>
<v-dialog v-model="trackerDialog" content-class="rounded-form" persistent max-width="290"> <v-dialog v-model="trackerDialog" content-class="rounded-form" persistent max-width="290">
<template #activator="{ on, attrs }"> <template #activator="{ on, attrs }">
<v-btn class="accent white--text elevation-0 px-4 mx-2" v-bind="attrs" v-on="on"> Add </v-btn> <v-btn class="accent white--text elevation-0 px-4 mx-2" v-bind="attrs" v-on="on">Add</v-btn>
</template> </template>
<v-card> <v-card>
<v-card-title class="justify-center"> <v-card-title class="justify-center">
@ -76,7 +76,7 @@ export default {
trackers() { trackers() {
return this.tempTrackers.map(x => ({ return this.tempTrackers.map(x => ({
...x, ...x,
isSelectable: typeof x.tier === 'number' isSelectable: x.tier >= 0
})) }))
}, },
headers() { headers() {
@ -86,14 +86,8 @@ export default {
{ text: this.$i18n.t('modals.detail.pageTrackers.status'), value: 'status' }, { text: this.$i18n.t('modals.detail.pageTrackers.status'), value: 'status' },
{ text: this.$i18n.t('modals.detail.pageTrackers.peers'), value: 'num_peers' }, { text: this.$i18n.t('modals.detail.pageTrackers.peers'), value: 'num_peers' },
{ text: this.$i18n.t('modals.detail.pageTrackers.seeds'), value: 'num_seeds' }, { text: this.$i18n.t('modals.detail.pageTrackers.seeds'), value: 'num_seeds' },
{ { text: this.$i18n.t('modals.detail.pageTrackers.leeches'), value: 'num_leeches' },
text: this.$i18n.t('modals.detail.pageTrackers.leeches'), { text: this.$i18n.t('modals.detail.pageTrackers.downloaded'), value: 'num_downloaded' },
value: 'num_leeches'
},
{
text: this.$i18n.t('modals.detail.pageTrackers.downloaded'),
value: 'num_downloaded'
},
{ text: this.$i18n.t('modals.detail.pageTrackers.message'), value: 'msg' } { text: this.$i18n.t('modals.detail.pageTrackers.message'), value: 'msg' }
] ]
} }

View file

@ -346,6 +346,23 @@ export class QBitApi {
return this.execute('post', '/torrents/removeTrackers', params) return this.execute('post', '/torrents/removeTrackers', params)
} }
addTorrentPeers(hashes: Array<string>, peers: Array<string>) {
const params = {
hashes: hashes.join('|'),
peers: peers.join('|')
}
return this.execute('post', '/torrents/addPeers', params)
}
banPeers(peers: Array<string>) {
const params = {
peers: peers.join('|')
}
return this.execute('post', '/transfer/banPeers', params)
}
torrentAction(action, hashes, extra) { torrentAction(action, hashes, extra) {
const params = { const params = {
hashes: hashes.length ? hashes.join('|') : 'all', hashes: hashes.length ? hashes.join('|') : 'all',