feat(p2p): p2p torrents replication
This commit is contained in:
@ -11,7 +11,7 @@ import Slider from 'material-ui/Slider'
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
const {dialog} = require('electron').remote
|
const {dialog} = require('electron').remote
|
||||||
|
|
||||||
export default class AdminPage extends Page {
|
export default class ConfigPage extends Page {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.setTitle('Rats settings');
|
this.setTitle('Rats settings');
|
||||||
@ -196,6 +196,18 @@ export default class AdminPage extends Page {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className='column w100p'>
|
||||||
|
<Toggle
|
||||||
|
style={{marginTop: '10px'}}
|
||||||
|
label="P2P torrents replication"
|
||||||
|
toggled={this.options.p2pReplication}
|
||||||
|
onToggle={(e, checked) => {
|
||||||
|
this.options.p2pReplication = checked
|
||||||
|
this.forceUpdate()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className='fs0-75' style={{color: 'grey'}}>* Enable torrents replication from another rats clients. Dont recomended if torrent scanner works correct.</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div style={{marginTop: 10}}>Torrent network scanner settings:</div>
|
<div style={{marginTop: 10}}>Torrent network scanner settings:</div>
|
@ -4,7 +4,7 @@ import PagesPie from './pages-pie.js';
|
|||||||
import IndexPage from './index-page.js'
|
import IndexPage from './index-page.js'
|
||||||
import TorrentPage from './torrent-page.js'
|
import TorrentPage from './torrent-page.js'
|
||||||
import DMCAPage from './dmca-page.js'
|
import DMCAPage from './dmca-page.js'
|
||||||
import AdminPage from './admin-page.js'
|
import ConfigPage from './config-page.js'
|
||||||
import TopPage from './top-page.js'
|
import TopPage from './top-page.js'
|
||||||
import DownloadPage from './download-page.js'
|
import DownloadPage from './download-page.js'
|
||||||
import ChangelogPage from './changelog-page.js'
|
import ChangelogPage from './changelog-page.js'
|
||||||
@ -72,7 +72,7 @@ router('/DMCA', () => {
|
|||||||
|
|
||||||
router('/config', () => {
|
router('/config', () => {
|
||||||
//singleton
|
//singleton
|
||||||
PagesPie.instance().open(AdminPage, {replace: 'all'});
|
PagesPie.instance().open(ConfigPage, {replace: 'all'});
|
||||||
});
|
});
|
||||||
|
|
||||||
router('/top', () => {
|
router('/top', () => {
|
||||||
|
@ -13,6 +13,7 @@ let config = {
|
|||||||
p2p: true,
|
p2p: true,
|
||||||
p2pConnections: 10,
|
p2pConnections: 10,
|
||||||
p2pBootstrap: true,
|
p2pBootstrap: true,
|
||||||
|
p2pReplication: false,
|
||||||
|
|
||||||
upnp: true,
|
upnp: true,
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ class p2p {
|
|||||||
|
|
||||||
// new peer with peer exchange
|
// new peer with peer exchange
|
||||||
this.on('peer', (peer) => {
|
this.on('peer', (peer) => {
|
||||||
|
console.log('got peer exchange', peer)
|
||||||
this.add(peer)
|
this.add(peer)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -411,6 +411,66 @@ if(config.p2pBootstrap)
|
|||||||
onTorrent(hash, options, (data) => callback(data))
|
onTorrent(hash, options, (data) => callback(data))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if(config.p2pReplication)
|
||||||
|
{
|
||||||
|
console.log('p2p replication enabled')
|
||||||
|
|
||||||
|
p2p.on('randomTorrents', (nil, callback) => {
|
||||||
|
if(typeof callback != 'function')
|
||||||
|
return;
|
||||||
|
|
||||||
|
sphinx.query('SELECT * FROM `torrents` ORDER BY rand() limit 5', (error, torrents) => {
|
||||||
|
if(!torrents || torrents.length == 0) {
|
||||||
|
callback(undefined)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let hashes = {}
|
||||||
|
for(const torrent of torrents)
|
||||||
|
{
|
||||||
|
delete torrent.id
|
||||||
|
hashes[torrent.hash] = torrent
|
||||||
|
}
|
||||||
|
|
||||||
|
const inSql = Object.keys(hashes).map(hash => sphinx.escape(hash)).join(',');
|
||||||
|
sphinx.query(`SELECT * FROM files WHERE hash IN(${inSql}) limit 50000`, (error, files) => {
|
||||||
|
if(!files)
|
||||||
|
{
|
||||||
|
files = []
|
||||||
|
}
|
||||||
|
|
||||||
|
files.forEach((file) => {
|
||||||
|
if(!hashes[file.hash].filesList)
|
||||||
|
hashes[file.hash].filesList = []
|
||||||
|
hashes[file.hash].filesList.push(file)
|
||||||
|
})
|
||||||
|
callback(Object.values(hashes))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const getReplicationTorrents = (nextTimeout = 5000) => {
|
||||||
|
console.log('call replication')
|
||||||
|
let gotTorrents = 0
|
||||||
|
|
||||||
|
p2p.emit('randomTorrents', null, (torrents) => {
|
||||||
|
if(!torrents || torrents.length == 0)
|
||||||
|
return
|
||||||
|
|
||||||
|
gotTorrents += torrents.length
|
||||||
|
|
||||||
|
torrents.forEach((torrent) => {
|
||||||
|
console.log('replicate remote torrent', torrent)
|
||||||
|
insertTorrentToDB(torrent)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
setTimeout(() => getReplicationTorrents(gotTorrents > 8 ? gotTorrents * 600 : 10000), nextTimeout)
|
||||||
|
}
|
||||||
|
// start
|
||||||
|
getReplicationTorrents()
|
||||||
|
}
|
||||||
|
|
||||||
const searchTorrentCall = function(text, navigation, callback)
|
const searchTorrentCall = function(text, navigation, callback)
|
||||||
{
|
{
|
||||||
if(typeof callback != 'function')
|
if(typeof callback != 'function')
|
||||||
@ -985,8 +1045,79 @@ const cleanupTorrents = (cleanTorrents = 1) => {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const insertTorrentToDB = (torrent) => {
|
||||||
|
if(!torrent)
|
||||||
|
return
|
||||||
|
|
||||||
|
const { filesList } = torrent
|
||||||
|
delete torrent.filesList;
|
||||||
|
|
||||||
|
mysqlSingle.query("SELECT id FROM torrents WHERE hash = ?", torrent.hash, (err, single) => {
|
||||||
|
if(!single)
|
||||||
|
{
|
||||||
|
console.log(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if(single.length > 0)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mysqlSingle.insertValues('torrents', torrent, function(err, result) {
|
||||||
|
if(result) {
|
||||||
|
send('newTorrent', {
|
||||||
|
hash: torrent.hash,
|
||||||
|
name: torrent.name,
|
||||||
|
size: torrent.size,
|
||||||
|
files: torrent.files,
|
||||||
|
piecelength: torrent.piecelength,
|
||||||
|
contentType: torrent.contentType,
|
||||||
|
contentCategory: torrent.contentCategory,
|
||||||
|
});
|
||||||
|
updateTorrentTrackers(torrent.hash);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.log(torrent);
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
let filesToAdd = filesList.length;
|
||||||
|
mysqlSingle.query('SELECT count(*) as files_count FROM files WHERE hash = ?', [torrent.hash], function(err, rows) {
|
||||||
|
if(!rows)
|
||||||
|
return
|
||||||
|
|
||||||
|
const db_files = rows[0]['files_count'];
|
||||||
|
if(db_files !== torrent.files)
|
||||||
|
{
|
||||||
|
mysqlSingle.query('DELETE FROM files WHERE hash = ?', torrent.hash, function (err, result) {
|
||||||
|
if(err)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filesList.forEach((file) => {
|
||||||
|
mysqlSingle.insertValues('files', file, function(err, result) {
|
||||||
|
if(!result) {
|
||||||
|
console.log(file);
|
||||||
|
console.error(err);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if(--filesToAdd === 0) {
|
||||||
|
send('filesReady', torrent.hash);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const updateTorrent = (metadata, infohash, rinfo) => {
|
const updateTorrent = (metadata, infohash, rinfo) => {
|
||||||
console.log('writing torrent', metadata.info.name, 'to database');
|
console.log('finded torrent', metadata.info.name, ' and add to database');
|
||||||
|
|
||||||
const hash = infohash.toString('hex');
|
const hash = infohash.toString('hex');
|
||||||
let size = metadata.info.length ? metadata.info.length : 0;
|
let size = metadata.info.length ? metadata.info.length : 0;
|
||||||
@ -1019,37 +1150,7 @@ const updateTorrent = (metadata, infohash, rinfo) => {
|
|||||||
filesAdd(metadata.info.name, size)
|
filesAdd(metadata.info.name, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
let filesToAdd = filesArray.length;
|
const torrentQ = {
|
||||||
mysqlSingle.query('SELECT count(*) as files_count FROM files WHERE hash = ?', [hash], function(err, rows) {
|
|
||||||
if(!rows)
|
|
||||||
return
|
|
||||||
|
|
||||||
const db_files = rows[0]['files_count'];
|
|
||||||
if(db_files !== filesCount)
|
|
||||||
{
|
|
||||||
mysqlSingle.query('DELETE FROM files WHERE hash = ?', hash, function (err, result) {
|
|
||||||
if(err)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
filesArray.forEach((file) => {
|
|
||||||
mysqlSingle.insertValues('files', file, function(err, result) {
|
|
||||||
if(!result) {
|
|
||||||
console.log(file);
|
|
||||||
console.error(err);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if(--filesToAdd === 0) {
|
|
||||||
send('filesReady', hash);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
var torrentQ = {
|
|
||||||
id: torrentsId++,
|
id: torrentsId++,
|
||||||
hash: hash,
|
hash: hash,
|
||||||
name: metadata.info.name,
|
name: metadata.info.name,
|
||||||
@ -1063,39 +1164,8 @@ const updateTorrent = (metadata, infohash, rinfo) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
torrentTypeDetect(torrentQ, filesArray);
|
torrentTypeDetect(torrentQ, filesArray);
|
||||||
|
torrentQ.filesList = filesArray;
|
||||||
mysqlSingle.query("SELECT id FROM torrents WHERE hash = ?", hash, (err, single) => {
|
insertTorrentToDB(torrentQ)
|
||||||
if(!single)
|
|
||||||
{
|
|
||||||
console.log(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if(single.length > 0)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mysqlSingle.insertValues('torrents', torrentQ, function(err, result) {
|
|
||||||
if(result) {
|
|
||||||
send('newTorrent', {
|
|
||||||
hash: hash,
|
|
||||||
name: metadata.info.name,
|
|
||||||
size: size,
|
|
||||||
files: filesCount,
|
|
||||||
piecelength: metadata.info['piece length'],
|
|
||||||
contentType: torrentQ.contentType,
|
|
||||||
contentCategory: torrentQ.contentCategory,
|
|
||||||
});
|
|
||||||
updateTorrentTrackers(hash);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
console.log(torrentQ);
|
|
||||||
console.error(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client.on('complete', function (metadata, infohash, rinfo) {
|
client.on('complete', function (metadata, infohash, rinfo) {
|
||||||
|
Reference in New Issue
Block a user