From fd4ba2c3928518a48bfa517357e36cf85052d14f Mon Sep 17 00:00:00 2001 From: Alexey Kasyanchuk Date: Mon, 18 Jun 2018 00:06:28 +0300 Subject: [PATCH] fix eslint --- src/app/activity-page.js | 26 +- src/app/app.js | 90 +- src/app/bad-words.js | 502 +++---- src/app/changelog-page.js | 34 +- src/app/component.js | 14 +- src/app/config-page.js | 556 ++++---- src/app/content.js | 6 +- src/app/dmca-page.js | 38 +- src/app/download-page.js | 64 +- src/app/feed-page.js | 160 +-- src/app/feed.js | 56 +- src/app/filters-page.js | 318 ++--- src/app/footer.js | 22 +- src/app/format-bytes.js | 12 +- src/app/header.js | 344 ++--- src/app/index.js | 4 +- src/app/input-files-filter.js | 118 +- src/app/input-size.js | 122 +- src/app/pages-pie.js | 154 +- src/app/recent-torrents.js | 274 ++-- src/app/registerServiceWorker.js | 162 +-- src/app/router.js | 2 +- src/app/search-advanced-controls.js | 96 +- src/app/search-results.js | 252 ++-- src/app/search.js | 586 ++++---- src/app/singleton.js | 6 +- src/app/top-page.js | 308 ++-- src/app/torrent-page.js | 694 ++++----- src/app/torrent-statistic.js | 240 ++-- src/app/torrent.js | 522 +++---- src/app/touch.js | 144 +- src/background/api.js | 222 +-- src/background/background.js | 316 ++--- src/background/bt/client.js | 138 +- src/background/bt/cpu-usage.js | 24 +- src/background/bt/peer-queue.js | 72 +- src/background/bt/spider.js | 516 +++---- src/background/bt/udp-tracker-request.js | 158 +-- src/background/bt/wire.js | 310 ++-- src/background/checkInternet.js | 14 +- src/background/config.js | 12 +- src/background/dbPatcher.js | 286 ++-- src/background/electronAppPath.js | 96 +- src/background/feed.js | 154 +- src/background/forBigTable.js | 42 +- src/background/helpers/window.js | 122 +- src/background/menu/about_menu_template.js | 170 +-- src/background/menu/config_menu_template.js | 82 +- src/background/menu/dev_menu_template.js | 48 +- src/background/menu/edit_menu_template.js | 20 +- src/background/menu/manage_menu_template.js | 48 +- src/background/mysql.js | 190 +-- src/background/p2p.js | 8 +- src/background/server.js | 18 +- src/background/shuffle.js | 16 +- src/background/sphinx.js | 186 +-- src/background/spider.js | 1400 +++++++++---------- src/background/ssh.js | 2 +- src/background/store.js | 286 ++-- src/background/webpack.config.production.js | 162 +-- src/background/webpack.js | 12 +- 61 files changed, 5528 insertions(+), 5528 deletions(-) diff --git a/src/app/activity-page.js b/src/app/activity-page.js index d16730e..2b22dff 100644 --- a/src/app/activity-page.js +++ b/src/app/activity-page.js @@ -4,17 +4,17 @@ import Page from './page'; import RecentTorrents from './recent-torrents' export default class ActivityPage extends Page { - constructor(props) { - super(props) - this.setTitle('Rats On The Boat - Content Search Engine'); - } - render() { - return ( -
-
- -
-
- ); - } + constructor(props) { + super(props) + this.setTitle('Rats On The Boat - Content Search Engine'); + } + render() { + return ( +
+
+ +
+
+ ); + } } diff --git a/src/app/app.js b/src/app/app.js index 0c3b2e3..bc49347 100644 --- a/src/app/app.js +++ b/src/app/app.js @@ -20,52 +20,52 @@ if(typeof WEB !== 'undefined') } else { - const { ipcRenderer, remote } = require('electron'); - window.currentWindow = remote.getCurrentWindow() + const { ipcRenderer, remote } = require('electron'); + window.currentWindow = remote.getCurrentWindow() - window.torrentSocket = {} - window.torrentSocket.callbacks = {} - window.torrentSocket.listeners = {} - window.torrentSocket.on = (name, func) => { - const newListener = (event, ...data) => { - func(...data) - } - window.torrentSocket.listeners[func] = newListener - ipcRenderer.on(name, newListener); - } - window.torrentSocket.off = (name, func) => { - if(!func) - ipcRenderer.removeAllListeners(name); - else - { - const realListener = window.torrentSocket.listeners[func] - if(realListener) - { - ipcRenderer.removeListener(name, realListener); - delete window.torrentSocket.listeners[func] + window.torrentSocket = {} + window.torrentSocket.callbacks = {} + window.torrentSocket.listeners = {} + window.torrentSocket.on = (name, func) => { + const newListener = (event, ...data) => { + func(...data) } - } - } - window.torrentSocket.emit = (name, ...data) => { - if(typeof data[data.length - 1] === 'function') - { - const id = Math.random().toString(36).substring(5) - window.torrentSocket.callbacks[id] = data[data.length - 1]; - data[data.length - 1] = {callback: id} - } - ipcRenderer.send(name, data) - } - ipcRenderer.on('callback', (event, id, data) => { - const callback = window.torrentSocket.callbacks[id] - if(callback) - callback(data) - delete window.torrentSocket.callbacks[id] - }); + window.torrentSocket.listeners[func] = newListener + ipcRenderer.on(name, newListener); + } + window.torrentSocket.off = (name, func) => { + if(!func) + ipcRenderer.removeAllListeners(name); + else + { + const realListener = window.torrentSocket.listeners[func] + if(realListener) + { + ipcRenderer.removeListener(name, realListener); + delete window.torrentSocket.listeners[func] + } + } + } + window.torrentSocket.emit = (name, ...data) => { + if(typeof data[data.length - 1] === 'function') + { + const id = Math.random().toString(36).substring(5) + window.torrentSocket.callbacks[id] = data[data.length - 1]; + data[data.length - 1] = {callback: id} + } + ipcRenderer.send(name, data) + } + ipcRenderer.on('callback', (event, id, data) => { + const callback = window.torrentSocket.callbacks[id] + if(callback) + callback(data) + delete window.torrentSocket.callbacks[id] + }); - ipcRenderer.on('url', (event, url) => { - console.log('url', url) - router(url) - }); + ipcRenderer.on('url', (event, url) => { + console.log('url', url) + router(url) + }); } @@ -164,8 +164,8 @@ class App extends Component {
{ checkNotModal - && -
+ && +
}
diff --git a/src/app/bad-words.js b/src/app/bad-words.js index 322069f..641fd34 100644 --- a/src/app/bad-words.js +++ b/src/app/bad-words.js @@ -1,259 +1,259 @@ const XXX_BLOCK_WORDS = ['incestcash', 'asacp', 'xondemand', 'yankscash', 'klixxx', 'cybersitter', 'safesurf', -'surfwatch', 'netcash', 'watersport', 'fuck', 'threesome', 'tits', -'masturbating', 'incest', 'bestiality', 'analintercourse', 'analsex', 'animesex', -'anitablonde', 'autosex', 'blackass', 'blackasses', 'boner', 'boobcruise', -'boobies', 'bordello', 'braless', 'brothel', 'callgirl', 'callgirls', -'clit', 'clitoris', 'clits', 'cums', 'cybererotic', 'cybererotica', -'cybersex', 'cybersexx', 'ejaculation', 'erotica', 'eroticfilm', 'eroticfilms', -'eroticism', 'eroticphoto', 'eroticphotography', 'eroticphotos', 'erotics', 'eroticsex', -'eroticsexstories', 'eroticstories', 'eroticstory', 'erotik', 'erotika', 'antasysex', -'gaysex', 'gruppensex', 'horny', 'jackoff', 'lesbo', 'lesbos', -'makinglove', 'motherfucker', 'horsesex', 'dogsex', 'snakesex', 'sextracker', -'tranny', 'bdsm', 'porn', 'beastality', 'bizarre', 'blowjob', -'bondage', 'bondages', 'celebs', 'cum', 'cunt', 'transsexual', -'transsexuals', 'cumbath', 'cumshot', 'dildo', 'dildos', 'transvestites', -'transvestite', 'dominatrix', 'spank', 'dungeon', 'sexbilder', 'dungeons', -'pussie', 'ebony', 'fisting', 'gayshop', 'facesitting', 'sexshop', -'pussy', 'bukkake', 'escort', 'blowjobs', 'facial', 'facialized', -'facials', 'fetish', 'footfetish', 'fuckingpussy', 'fucking', 'hardcore', -'hentai', 'hustlerlatex', 'latex', 'lolita', 'lolitas', 'mlm', -'oralsex', 'peepshow', 'peepshows', 'phonesex', 'pornstars', 'preteen', -'preteens', 'pussies', 'shemale', 'shemales', 'sluts', 'whores', -'whore', 'spanking', 'strapon', 'twinks', 'upskirts', 'voyeur', -'whip', 'whipping', 'xxx', 'sexkey', 'femdom', 'gangbang', -'gloryhole', 'adultbuffet', 'adultcartoons', 'adultchat', 'adultchatnetwork', 'adultdvd', -'adultentertainment', 'adultentertainmenthouse', 'adulterotica', 'adultfilms', 'adultfree', 'adultfreepics', -'adultfreepix', 'adultfun', 'adulthardcore', 'adultimages', 'adultjpeg', 'adultlink', -'adultlinks', 'adultmovie', 'adultmovies', 'adultmpeg', 'adultmpegs', 'adultpass', -'adultpersonals', 'adultphotos', 'adultpic', 'adultpics', 'adultpicture', 'adultpictures', -'adultpix', 'adultporn', 'adultpornography', 'adultsearch', 'adultsex', 'adultsights', -'adultsites', 'adultsonly', 'adultstars', 'adultstories', 'adultvideo', 'adultvideos', -'adultweb', 'adultxxx', 'alt.sex', 'altsex', 'alt.sex.exhibitionism', 'alt.sex.pictures', -'altsexst', 'alt.sex.stories', 'alt.sex.voyeurism', 'amateurerotica', 'amateurfotos', 'amateurhardcore', -'amateurindex', 'amateurnaked', 'amateurnudes', 'amateurporn', 'amateurpussy', 'amateursex', -'amateursxxx', 'amatuerhardcore', 'amatuersex', 'ampland', 'analaction', 'analcum', -'analfuck', 'analfucking', 'analgallery', 'analingus', 'analpics', 'analpicture', -'analsex', 'analsexpics', 'analsexpictures', 'analxxx', 'animalbeastiality', 'animehentai', -'animeporno', 'animexxx', 'asiacarrera', 'assfuck', 'assfucking', 'asshole', -'assholes', 'asslick', 'asspics', 'assworship', 'autofellatio', 'babepix', -'badgirls', 'bakedchicks', 'baldcunt', 'baldpussies', 'baldpussy', 'barecelebs', -'barenaked', 'barepussy', 'beastiality', 'beaverboy', 'beavershots', 'bigballs', -'bigblackboobs', 'bigblackcocks', 'bigblackdicks', 'bigblacktits', 'bigboob', 'bigboobs', -'bigbreast', 'bigbreastlovers', 'bigbreasts', 'bigbutt', 'bigbutts', 'bigclit', -'bigclitoris', 'bigclits', 'bigcock', 'bigcocks', 'bigcunt', 'bigcunts', -'bigdick', 'bigdicks', 'biggestboobs', 'biggestdick', 'biggesttit', 'biggesttits', -'bighairyballs', 'bighardons', 'bighooters', 'bignipples', 'bigpussies', 'bigpussy', -'bigtit', 'bigtits', 'bigtitties', 'bigtitts', 'bizarresex', 'bizarrexxx', -'bizzaresex', 'blackbondage', 'blackboobs', 'blackbooty', 'blackbutt', 'blackcock', -'blackcocks', 'blackcum', 'blackcunt', 'blackcunts', 'blackdick', 'blackdicks', -'blackerotica', 'blackhardcore', 'blacknudes', 'blackonblondes', 'blackporn', 'blackporno', -'blackpornography', 'blackpussy', 'blacksex', 'blacksluts', 'blacksonblondes', 'blacktit', -'blacktits', 'blacktwat', 'blackxxx', 'blondepussy', 'blondsgay', 'bondagefree', -'bondagegallery', 'bondagelinks', 'bondagepics', 'bondagepictures', 'bondagesex', 'bondagestories', -'bondagestory', 'bukake', 'bustybabes', 'bustyblondes', 'bustyceleb', 'butt-fuck', -'buttfuck', 'buttfucker', 'buttfuckers', 'buttfucking', 'buttholes', 'buttman', -'buttpics', 'buttplug', 'buttthumbnails', 'cartoonporn', 'cartoonsex', 'cartoonsxxx', -'cartoonxxx', 'celebritiesnaked', 'celebritiesnude', 'celebritiesxxx', 'celebritybush', 'celebritybutts', -'celebritynude', 'celebritynudes', 'celebrityporn', 'celebritypussy', 'celebritysex', 'celebrityxxx', -'celebsxxx', 'celebxxx', 'centerfolds', 'chaseylain', 'chatsex', 'cheerleadersxxx', -'cheerleaderxxx', 'chickswithdicks', 'christycanyon', 'cicciolina', 'clitpics', 'clitpictures', -'closeuppussy', 'comixxx', 'crotchless', 'cruisingforsex', 'cumbaths', 'cumcoveredcunts', -'cumcunt', 'cumdrinker', 'cumdrinkers', 'cumdrinking', 'cumdrops', 'cumeater', -'cumeaters', 'cumeating', 'cumface', 'cumfaces', 'cumfacial', 'cumfacials', -'cumgallery', 'cumgargle', 'cumguzzlers', 'cumincunt', 'cumjunkies', 'cumlovers', -'cummpeg', 'cumpic', 'cumpics', 'cumpicture', 'cumpictures', 'cumpussy', -'cumsluts', 'cumsucker', 'cumsuckers', 'cumsucking', 'cumswallow', 'cumswallowers', -'cumswallowing', 'cumtasting', 'cumthumbnails', 'cunilingus', 'cunnilingus', 'cuntcum', -'cuntfuck', 'cuntfucking', 'cuntjuice', 'cuntlapper', 'cuntlick', 'cuntlickers', -'cuntlicking', 'cuntpics', 'cuntpictures', 'cunts', 'cuntstories', 'cuntsuckers', -'cuntz', 'cyberlust', 'cybernude', 'cyberporn', 'cyberpornlinks', 'cyberpornsexlinks', -'cyberslut', 'd’amateur', 'danniashe', 'dicksex', 'dicksuckers', 'dicksucking', -'digixxx', 'directporn', 'dirtypictures', 'dirtysex', 'doggiestyle', 'doggystyle', -'domatrix', 'dominatrixes', 'downblouse', 'drinkingcum', 'drippingcunt', 'drippingcunts', -'drippingpussy', 'easypic.com', 'eatcum', 'eatingcum', 'eatingpussy', 'eatpussy', -'ebony+ayres', 'ebonyporn', 'ebonypussy', 'ebonysex', 'ebonyxxx', 'enormoustits', -'erosvillage', 'eroticanime', 'eroticart', 'eroticas', 'eroticastories', 'eroticfiction', -'eroticlesbianstories', 'eroticmovie', 'eroticmovies', 'erotico', 'eroticos', 'eroticpics', -'eroticpicture', 'eroticpictures', 'eroticsites', 'eroticsounds', 'erotictales', 'erotictext', -'eroticvideo', 'eroticvideos', 'eroticwomen', 'eroticwriting', 'erotikchat', 'erotique', -'erotismo', 'escortservice', 'escortservices', 'eurosex', 'explicitsex', 'facecum', -'facesit', 'facesitters', 'fastporn', 'fatass', 'fatsex', 'feetfetish', -'feetsex', 'felatio', 'fellatio', 'fellations', 'fetishwear', 'fettegirls', -'fingerbang', 'fingerfuck', 'flesh4free', 'footjobs', 'footlicking', 'footworship', -'fornication', 'freeanal', 'freeanalsex', 'freeass', 'freebigboobs', 'freebigtit', -'freebigtits', 'freeblackcunt', 'freeblackpussy', 'freeblowjob', 'freeblowjobs', 'freebondage', -'freeboobs', 'freecum', 'freecumshot', 'freecumshots', 'freecunt', 'freecunts', -'freedick', 'freeerotic', 'freeerotica', 'freeeroticstories', 'freefuck', 'freefucking', -'freefuckpics', 'freegay', 'freegaypics', 'freehardcore', 'freehardcorepics', 'freehardcorepictures', -'freehardcoreporn', 'freehardcoresex', 'freehardcoresexpics', 'freehentai', 'freehooters', 'freelargehooters', -'freelesbian', 'freelesbianporn', 'freelesbiansex', 'freenakedpic', 'freenakedpics', 'freenakedpictures', -'freenakedwomen', 'freenude', 'freenudecelebs', 'freenudephotos', 'freenudepics', 'freenudes', -'freeporn', 'freepornmovies', 'freeporno', 'freepornography', 'freepornopics', 'freepornopictures', -'freepornos', 'freepornpic', 'freepornpics', 'freepornpictures', 'freeporns', 'freepornsite', -'freepornsites', 'freepussy', 'freepussypic', 'freepussypics', 'freepussypictures', 'freesex', -'freesexchat', 'freesexmovies', 'freesexnet', 'freesexphotos', 'freesexpic', 'freesexpics', -'freesexpicture', 'freesexpictures', 'freesexsites', 'freesexstories', 'freesexvideos', 'freesexycam', -'freeshemale', 'freesmut', 'freetit', 'freetits', 'freevoyeur', 'freexxx', -'freexxxmovie', 'freexxxmovies', 'freexxxmpeg', 'freexxxphotos', 'freexxxpic', 'freexxxpics', -'freexxxpicture', 'freexxxpictures', 'freexxxstories', 'freexxxvideo', 'freexxxx', 'fuking', -'gangbangs', 'gratishardcoregalerie', 'hardcorecelebs', 'hardcorefisting', 'hardcorefree', 'hardcorefucking', -'hardcorehooters', 'hardcorejunkie', 'hardcorejunky', 'hardcoremovie', 'hardcoremovies', 'hardcorepic', -'hardcorepics', 'hardcorepictures', 'hardcorepix', 'hardcoreporn', 'hardcoreporno', 'hardcorepornography', -'hardcorepornos', 'hardcorepussy', 'hardcoresamples', 'hardcoresex', 'hardcoresexpictures', 'hardcorestories', -'hardcorethumbnails', 'hardcorevideo', 'hardcorevideos', 'hardcorexxx', 'harddicks', 'hardnipples', -'hardons', 'hardporn', 'indiasex', 'interacialhardcore', 'interacialsex', 'interacialxxx', -'intercoursepositions', 'internetsex', 'interracialfucking', 'interracialhardcore', 'interracialporn', 'interracialpornography', -'interracialsex', 'interracialsexstories', 'interracialxxx', 'intimatesex', 'ittybittytitty', 'japaneseporn', -'japanesesex', 'japansex', 'japanxxx', 'jennacam.com', 'jennajameson', 'jennicam', -'jerkoff', 'jism', 'jiz', 'jizz', 'juicycunts', 'juicypussy', -'justhardcore', 'karasamateurs', 'karasxxx', 'kascha', 'kaylakleevage', 'kobetai', -'koreasex', 'lapdance', 'largeclits', 'largecunts', 'largedicks', 'largehooters', -'largepussy', 'largetit', 'largetits', 'latinapussy', 'latinasex', 'latinosex', -'latinoxxx', 'latinxxx', 'legsex', 'lesbianerotica', 'lesbianhardcore', 'lesbianorgies', -'lesbianorgy', 'lesbianpics', 'lesbianpink', 'lesbianporn', 'lesbian-porno', 'lesbianporno', -'lesbianpornography', 'lesbianpornos', 'lesbianpussy', 'lesbiansex', 'lesbiansexpics', 'lesbiansexstories', -'lesbianxxx', 'lickadick', 'lickingpussy', 'lindalovelace', 'lingeriexxx', 'literotica', -'littleboobs', 'littlepussy', 'littletits', 'livefucking', 'liveporn', 'livesex', -'livesexcam', 'livesexcams', 'longdicks', 'lovedoll', 'lovedolls', 'magazinessex', -'makinglove', 'malaysex', 'malenudes', 'malesex', 'mangaporno', 'mangax', -'mangaxxx', 'manpics', 'mansex', 'marilynchambers', 'massivecocks', 'masterbating', -'masturbation', 'masturbationvideos', 'maturefucking', 'maturesex', 'maturexxx', 'megaboobs', -'megaporno', 'megapussy', 'megatits', 'mensdicks', 'mensex', 'm.i.l.f.', -'milf', 'milfhunterpic', 'milfmpegsample', 'modelsex', 'mondoporn', 'monstercocks', -'monsterdicks', 'motherfucker', 'moviepost.com', 'mpegsex', 'mpegxxx', 'muffdiving', -'myslutwife', 'nacktfotos', 'nakedbabes', 'nakedblackwomen', 'nakedcelebrity', 'nakedcelebs', -'nakedcheerleader', 'nakedchicks', 'nakedgirls', 'nakedguys', 'nakedladies', 'nakedlady', -'nakedman', 'nakedmen', 'nakedness', 'nakedphotographs', 'nakedphotography', 'nakedphotos', -'nakedpic', 'nakedpics', 'nakedpicture', 'nakedpictures', 'nakedpussy', 'nakedstars', -'nakedwife', 'nakedwoman', 'nakedwomen', 'nastychat', 'nastypussy', 'nastysex', -'nastythumbs', 'naturaltits', 'naughty.com', 'naughtylinks', 'naughtylinx', 'naughtylynx', -'naughtynurses', 'netsex', 'niceass', 'nicetits', 'nikkinova', 'nikkityler', -'nipples', 'nookie', 'nookies', 'nudeactress', 'nudeactresses', 'nudeamateur', -'nudeamateurs', 'nudeasianwomen', 'nudebabes', 'nudebigboobs', 'nudeblack', 'nudeblackwomen', -'nudeblondes', 'nudeceleb', 'nudeceleberties', 'nudecelebraties', 'nudecelebrites', 'nudecelebrities', -'nudecelebrity', 'nudecelebs', 'nudecollegegirls', 'nudefemale', 'nudefemales', 'nudefree', -'nudegay', 'nudeimages', 'nudeladies', 'nudelesbians', 'nudemale', 'nudemales', -'nudeman', 'nudemen', 'nudepic', 'nudepics', 'nudepicture', 'nudepictures', -'nudepornography', 'nudepussy', 'nuderaider', 'nuderedheads', 'nudes', 'nudesex', -'nudestar', 'nudestars', 'nudevideoconferencing', 'nudewoman', 'nudewomen', 'nudism', -'nudist', 'nudists', 'nudity', 'nylonfetish', 'nylonsex', 'nympho', -'nymphos', 'olderbabes', 'oldersex', 'oldersluts', 'oldpussy', 'oldsex', -'oldsluts', 'openlegs', 'openpussy', 'oral4free', 'oral-sex', 'oralsexpictures', -'orgie', 'orgies', 'orgypics', 'orgys', 'pantyhosefetish', 'pantyhosesex', -'peepcam', 'persiankitty', 'persiankitty.com', 'perverted', 'picsxxx', 'picturesex', -'picturesofsex', 'picturessex', 'pimpserver', 'pimpserver.com', 'pinkpussy', 'pissing', -'pixxx', 'poontang', 'pornagraphy', 'porncast', 'porncity', 'porndirectory', -'porne', 'pornfree', 'pornmovies', 'pornno', 'pornnude', 'porno', -'pornoadult', 'pornocartoons', 'pornochat', 'pornodeluxe', 'pornoe', 'pornofilms', -'pornofree', 'pornogame', 'pornografi', 'pornografia', 'pornografie', 'pornografy', -'pornograph', 'pornographi', 'pornographia', 'pornographic', 'pornographicpictures', 'pornographics', -'pornographicvideo', 'pornographicvideos', 'pornographie', 'pornography', 'pornographyfree', 'pornographyphotos', -'pornographypictures', 'pornography-sex', 'pornographysex', 'pornoland', 'pornolinks', 'pornolynx', -'pornomagazines', 'pornomovies', 'pornompeg', 'pornophotos', 'pornopic', 'pornopics', -'pornopicture', 'pornopictures', 'pornos', 'pornosex', 'pornosite', 'pornosites', -'pornostar', 'pornostories', 'pornovideo', 'pornovideos', 'pornoxxx', 'pornphotos', -'pornpics', 'pornpictures', 'pornpix', 'pornpost', 'pornqueens', 'pornrated', -'porns', 'pornsex', 'pornstar', 'pornstories', 'porntrack', 'pornvideo', -'pornvideos', 'pornypics', 'porstars', 'privatesex', 'privatex', 'privatexx', -'privatexxx', 'prono', 'pronography', 'publicnudity', 'puffynipples', 'purple+passion', -'pussyboard', 'pussycam', 'pussycams', 'pussycloseup', 'pussycloseups', 'pussycum', -'pussycunt', 'pussyeater', 'pussyeaters', 'pussyeating', 'pussyfuck', 'pussyfucking', -'pussyhair', 'pussyheaven', 'pussyjuice', 'pussylickers', 'pussylicking', 'pussylink', -'pussylips', 'pussyphotos', 'pussyporno', 'pussys', 'pussysex', 'pussyshots', -'pussythumbnails', 'pussytits', 'pusy', 'racqueldarrian', 'rape', 'rawlinks', -'rawpussy', 'rawsex', 'realhardcore', 'realsex', 'redneckporn', 'redpussy', -'rubberfetish', 'russianxxx', 'scat', 'schiffernude', 'seka', 'seniorsex', -'sex4free', 'sex66', 'sexacts', 'sexadult', 'sexaids', 'sexamateur', -'sexanal', 'sexandpictures', 'sexaphone', 'sexaudio', 'sexavi', 'sexbondage', -'sexboner', 'sexbuttfucker', 'sexcam', 'sexcams', 'sexchat', 'sexchatrooms', -'sexcites', 'sexclub', 'sexclubs', 'sex.com', 'sexdating', 'sexe', -'sexfantasies', 'sexfantasy', 'sexfilm', 'sexgallery', 'sexgame', 'sexgames', -'sexgirl', 'sexgirls', 'sexgroup', 'sexguide', 'sexhardcore', 'sexhphoto', -'sexhungry', 'sexhungryjoe', 'sexhungryjoes', 'sexi', 'seximages', 'sexis', -'sexjapan', 'sex.jpg', 'sexlinda', 'sexlinks', 'sexlinx', 'sexlive', -'sexmagazine', 'sexmagazines', 'sexmature', 'sexmelayu', 'sexmodels', 'sexmovie', -'sexmovies', 'sexmpeg', 'sexnude', 'sexnudity', 'sexo', 'sexoanal', -'sexole', 'sexontheinternet', 'sexoral', 'sexpasswords', 'sexphoto', 'sexphotos', -'sexpic', 'sexpicnet', 'sexpics', 'sexpicture', 'sexpictures', 'sexpicturesfree', -'sexpix', 'sexplaza', 'sexporn', 'sexporno', 'sexpositions', 'sexpussy', -'sexroulette', 'sexs', 'sexsamples', 'sexsearch', 'sexsex', 'sexsexsex', -'sexshare', 'sexshops', 'sexshow', 'sexshows', 'sexsite', 'sexsites', -'sexslave', 'sexsound', 'sexsounds', 'sexsource', 'sexspaces', 'sexspaces.com', -'sexstories', 'sexstory', 'sexstorys', 'sextalk', 'sexteen', 'sexthumbnails', -'sex-toons', 'sextoons', 'sextour', 'sextoy', 'sextoys', 'sextpus', -'sextracker.com', 'sextropolis', 'sexualbondage', 'sexualfantasies', 'sexualfantasy', 'sexualintercourse', -'sexualpictures', 'sexualpleasure', 'sexualpositions', 'sexuncensored', 'sexvideo', 'sexvision', -'sexvote', 'sexwomen', 'sexworld', 'sexx', 'sexxx', 'sexxxx', -'sexxxxx', 'sexyamateurs', 'sexybabes', 'sexyblack', 'sexyboobs', 'sexybookmark', -'sexybookmarka', 'sexybookmarks', 'sexybutts', 'sexycunts', 'sexygirl', 'sexygirls', -'sexyladies', 'sexylady', 'sexylegs', 'sexylingerie', 'sexymen', 'sexyphotos', -'sexypics', 'sexypictures', 'sexypost', 'sexypussies', 'sexypussy', 'sexysites', -'sexystories', 'sexywoman', 'sexywomen', 'shavedcunt', 'shavedcunts', 'shavedpussies', -'shavedpussy', 'shavedpussypics', 'shavedsluts', 'shavedwomen', 'shavenpussies', 'shavenpussy', -'shavepussy', 'sheboy', 'she-male', 'shemale+video', 'shemaleyum', 'showcam', -'showcams', 'showercam', 'showercams', 'slavesex', 'smallboobs', 'smallbreasts', -'smalldicks', 'smallpussy', 'smalltits', 'smut', 'smut69', 'smutland', -'smutserver', 'smutshack', 'softcore', 'softporn', 'softpornography', 'spankingpage', -'spreadpussy', 'spycamadult', 'stockingsex', 'storieserotic', 'storiessex', 'straightsex', -'stretchedcunt', 'stripclub', 'stripclubs', 'stripshow', 'striptease', 'strokeit', -'strokeme', 'suckdick', 'sucksex', 'superchicken', 'supersex', 'supertits', -'swallowcum', 'swinger', 'swingerclub', 'swingers', 'swollenclits', 'syberporn', -'sylviasaint', 'teenanal', 'teenanalsex', 'teenhardcore', 'teenie', 'teenies', -'teennude', 'teenpics', 'teenporn', 'teenporno', 'teenpussy', 'teensex', -'teenslut', 'teensluts', 'teensuck', 'teenxxx', 'tgp', 'thaipussy', -'thaisex', 'thehun', 'threesomes', 'thumblords', 'thumbnailssex', 'thumbzilla', -'tiffanytowers', 'tightcunt', 'tightpussies', 'tightpussy', 'tinypussy', 'tinytits', -'tinytitties', 'tisandass', 'tit', 'titbondage', 'titfuck', 'titfucking', -'tities', 'titman', 'titsandass', 'titsass', 'titties', 'titts', -'titty', 'tittyfuck', 'tittyfucking', 'tittys', 'tokyotopless', 'tommysbookmark', -'toplesswomen', 'trannies', 'transexual', 'transsexuels', 'twat', 'twats', -'twink', 'ultradonkey', 'ultrahardcore', 'uncutcocks', 'vaginalintercourse', 'vaginapictures', -'videoporno', 'videosex', 'videoxxx', 'vintageporn', 'virtualsex', 'vividtv', -'wank', 'wankers', 'wanking', 'wendywhoppers', 'wetcunt', 'wetcunts', -'wetdick', 'wetpanties', 'wetpussies', 'wetpussy', 'wetsex', 'wetvagina', -'whitepussy', 'whitesex', 'whitetits', 'whitexxx', 'wifesharing', 'wifeswapping', -'wildpussy', 'wildsex', 'womensex', 'worldsex', 'worldsexguide', 'x-rated', -'xrated', 'x-ratedmovie', 'x-ratedmovies', 'x-ratedvideo', 'x-ratedvideos', 'xxx4free', -'xxxadult', 'xxxadultmovies', 'xxxadultvideo', 'xxxadultvideos', 'xxxbabes', 'xxxcam', -'xxxcelebrities', 'xxxfree', 'xxxfreepics', 'xxxgalleries', 'xxxhardcore', 'xxxjapan', -'xxxlinks', 'xxxmodels', 'xxxmovie', 'xxxmovies', 'xxxmpeg', 'xxxpassword', -'xxxphoto', 'xxxphotos', 'xxxpic', 'xxx-pics', 'xxxpics', 'xxxpicture', -'xxxpictures', 'xxxpicturesfree', 'xxxpicx', 'xxxpirtures', 'xxxporn', 'xxxporno', -'xxxpussy', 'xxx-rated', 'xxxrated', 'xxxsex', 'xxxsites', 'xxxsluts', -'xxxstories', 'xxxteen', 'xxxthumbnails', 'xxxthumbs', 'xxxtoons', 'xxxtoys', -'xxxvideo', 'xxxvideos', 'xxxwomen', 'xxxx', 'xxxxx', 'xxxxxx', -'filthyfarm', 'adultcheck', 'erotic', 'mistresses', 'naughty', -'adult', 'amateur', 'amateurs', 'anal', 'analau', 'poker', -'anally', 'asian', 'swinging', 'ass', 'orgy', 'sexvideos', -'babe', 'babes', 'bare', 'glamour', 'casino', 'bed', -'vibrator', 'bikini', 'bisexual', 'blonde', 'breasted', 'breasts', -'busty', 'butts', 'candy', 'caning', 'caps', 'catholic', -'chained', 'chested', 'chubby', 'close-ups', 'coupling', -'cucumber', 'doll', 'dolls', 'dolly', 'dominating', 'drinking', -'drunk', 'fat', 'feet', 'fingering', 'fishnet', 'flasher', -'footjob', 'foreplay', 'foreplaying', 'girlfriend', 'girlfriends', 'gymnast', -'hairy', 'holly', 'horse', 'housewife', 'houswife', 'insertion', -'insertions', 'interracial', 'jerka', 'juicy', 'kissing', 'kitty', -'lactating', 'ladyboy', 'lance', 'latina', 'latins', 'leather', -'legs', 'lesbian', 'lesbians', 'licking', 'lingerie', 'lubricants', -'mature', 'midget', 'minor', 'mistress', 'nude', -'older', 'olez', 'oral', 'panties', 'pantyhose', 'pedro', -'peeing', 'penetration', 'pigtailed', 'pleasure', 'plump', -'plumper', 'poser', 'posers', 'poses', 'posing', 'prosecuted', -'punishment', 'reproducing', 'sex', 'shaved', 'shock', 'slave', -'sleeping', 'speculums', 'spread', 'spreading', 'squirting', 'stripper', -'stripping', 'swapping', 'thong', 'topless', 'toying', -'trix', 'undressing', 'uniform', 'whipcream', 'brazzers', 'порно', -'порн', 'лесб', 'гей', 'геи', 'прон' + 'surfwatch', 'netcash', 'watersport', 'fuck', 'threesome', 'tits', + 'masturbating', 'incest', 'bestiality', 'analintercourse', 'analsex', 'animesex', + 'anitablonde', 'autosex', 'blackass', 'blackasses', 'boner', 'boobcruise', + 'boobies', 'bordello', 'braless', 'brothel', 'callgirl', 'callgirls', + 'clit', 'clitoris', 'clits', 'cums', 'cybererotic', 'cybererotica', + 'cybersex', 'cybersexx', 'ejaculation', 'erotica', 'eroticfilm', 'eroticfilms', + 'eroticism', 'eroticphoto', 'eroticphotography', 'eroticphotos', 'erotics', 'eroticsex', + 'eroticsexstories', 'eroticstories', 'eroticstory', 'erotik', 'erotika', 'antasysex', + 'gaysex', 'gruppensex', 'horny', 'jackoff', 'lesbo', 'lesbos', + 'makinglove', 'motherfucker', 'horsesex', 'dogsex', 'snakesex', 'sextracker', + 'tranny', 'bdsm', 'porn', 'beastality', 'bizarre', 'blowjob', + 'bondage', 'bondages', 'celebs', 'cum', 'cunt', 'transsexual', + 'transsexuals', 'cumbath', 'cumshot', 'dildo', 'dildos', 'transvestites', + 'transvestite', 'dominatrix', 'spank', 'dungeon', 'sexbilder', 'dungeons', + 'pussie', 'ebony', 'fisting', 'gayshop', 'facesitting', 'sexshop', + 'pussy', 'bukkake', 'escort', 'blowjobs', 'facial', 'facialized', + 'facials', 'fetish', 'footfetish', 'fuckingpussy', 'fucking', 'hardcore', + 'hentai', 'hustlerlatex', 'latex', 'lolita', 'lolitas', 'mlm', + 'oralsex', 'peepshow', 'peepshows', 'phonesex', 'pornstars', 'preteen', + 'preteens', 'pussies', 'shemale', 'shemales', 'sluts', 'whores', + 'whore', 'spanking', 'strapon', 'twinks', 'upskirts', 'voyeur', + 'whip', 'whipping', 'xxx', 'sexkey', 'femdom', 'gangbang', + 'gloryhole', 'adultbuffet', 'adultcartoons', 'adultchat', 'adultchatnetwork', 'adultdvd', + 'adultentertainment', 'adultentertainmenthouse', 'adulterotica', 'adultfilms', 'adultfree', 'adultfreepics', + 'adultfreepix', 'adultfun', 'adulthardcore', 'adultimages', 'adultjpeg', 'adultlink', + 'adultlinks', 'adultmovie', 'adultmovies', 'adultmpeg', 'adultmpegs', 'adultpass', + 'adultpersonals', 'adultphotos', 'adultpic', 'adultpics', 'adultpicture', 'adultpictures', + 'adultpix', 'adultporn', 'adultpornography', 'adultsearch', 'adultsex', 'adultsights', + 'adultsites', 'adultsonly', 'adultstars', 'adultstories', 'adultvideo', 'adultvideos', + 'adultweb', 'adultxxx', 'alt.sex', 'altsex', 'alt.sex.exhibitionism', 'alt.sex.pictures', + 'altsexst', 'alt.sex.stories', 'alt.sex.voyeurism', 'amateurerotica', 'amateurfotos', 'amateurhardcore', + 'amateurindex', 'amateurnaked', 'amateurnudes', 'amateurporn', 'amateurpussy', 'amateursex', + 'amateursxxx', 'amatuerhardcore', 'amatuersex', 'ampland', 'analaction', 'analcum', + 'analfuck', 'analfucking', 'analgallery', 'analingus', 'analpics', 'analpicture', + 'analsex', 'analsexpics', 'analsexpictures', 'analxxx', 'animalbeastiality', 'animehentai', + 'animeporno', 'animexxx', 'asiacarrera', 'assfuck', 'assfucking', 'asshole', + 'assholes', 'asslick', 'asspics', 'assworship', 'autofellatio', 'babepix', + 'badgirls', 'bakedchicks', 'baldcunt', 'baldpussies', 'baldpussy', 'barecelebs', + 'barenaked', 'barepussy', 'beastiality', 'beaverboy', 'beavershots', 'bigballs', + 'bigblackboobs', 'bigblackcocks', 'bigblackdicks', 'bigblacktits', 'bigboob', 'bigboobs', + 'bigbreast', 'bigbreastlovers', 'bigbreasts', 'bigbutt', 'bigbutts', 'bigclit', + 'bigclitoris', 'bigclits', 'bigcock', 'bigcocks', 'bigcunt', 'bigcunts', + 'bigdick', 'bigdicks', 'biggestboobs', 'biggestdick', 'biggesttit', 'biggesttits', + 'bighairyballs', 'bighardons', 'bighooters', 'bignipples', 'bigpussies', 'bigpussy', + 'bigtit', 'bigtits', 'bigtitties', 'bigtitts', 'bizarresex', 'bizarrexxx', + 'bizzaresex', 'blackbondage', 'blackboobs', 'blackbooty', 'blackbutt', 'blackcock', + 'blackcocks', 'blackcum', 'blackcunt', 'blackcunts', 'blackdick', 'blackdicks', + 'blackerotica', 'blackhardcore', 'blacknudes', 'blackonblondes', 'blackporn', 'blackporno', + 'blackpornography', 'blackpussy', 'blacksex', 'blacksluts', 'blacksonblondes', 'blacktit', + 'blacktits', 'blacktwat', 'blackxxx', 'blondepussy', 'blondsgay', 'bondagefree', + 'bondagegallery', 'bondagelinks', 'bondagepics', 'bondagepictures', 'bondagesex', 'bondagestories', + 'bondagestory', 'bukake', 'bustybabes', 'bustyblondes', 'bustyceleb', 'butt-fuck', + 'buttfuck', 'buttfucker', 'buttfuckers', 'buttfucking', 'buttholes', 'buttman', + 'buttpics', 'buttplug', 'buttthumbnails', 'cartoonporn', 'cartoonsex', 'cartoonsxxx', + 'cartoonxxx', 'celebritiesnaked', 'celebritiesnude', 'celebritiesxxx', 'celebritybush', 'celebritybutts', + 'celebritynude', 'celebritynudes', 'celebrityporn', 'celebritypussy', 'celebritysex', 'celebrityxxx', + 'celebsxxx', 'celebxxx', 'centerfolds', 'chaseylain', 'chatsex', 'cheerleadersxxx', + 'cheerleaderxxx', 'chickswithdicks', 'christycanyon', 'cicciolina', 'clitpics', 'clitpictures', + 'closeuppussy', 'comixxx', 'crotchless', 'cruisingforsex', 'cumbaths', 'cumcoveredcunts', + 'cumcunt', 'cumdrinker', 'cumdrinkers', 'cumdrinking', 'cumdrops', 'cumeater', + 'cumeaters', 'cumeating', 'cumface', 'cumfaces', 'cumfacial', 'cumfacials', + 'cumgallery', 'cumgargle', 'cumguzzlers', 'cumincunt', 'cumjunkies', 'cumlovers', + 'cummpeg', 'cumpic', 'cumpics', 'cumpicture', 'cumpictures', 'cumpussy', + 'cumsluts', 'cumsucker', 'cumsuckers', 'cumsucking', 'cumswallow', 'cumswallowers', + 'cumswallowing', 'cumtasting', 'cumthumbnails', 'cunilingus', 'cunnilingus', 'cuntcum', + 'cuntfuck', 'cuntfucking', 'cuntjuice', 'cuntlapper', 'cuntlick', 'cuntlickers', + 'cuntlicking', 'cuntpics', 'cuntpictures', 'cunts', 'cuntstories', 'cuntsuckers', + 'cuntz', 'cyberlust', 'cybernude', 'cyberporn', 'cyberpornlinks', 'cyberpornsexlinks', + 'cyberslut', 'd’amateur', 'danniashe', 'dicksex', 'dicksuckers', 'dicksucking', + 'digixxx', 'directporn', 'dirtypictures', 'dirtysex', 'doggiestyle', 'doggystyle', + 'domatrix', 'dominatrixes', 'downblouse', 'drinkingcum', 'drippingcunt', 'drippingcunts', + 'drippingpussy', 'easypic.com', 'eatcum', 'eatingcum', 'eatingpussy', 'eatpussy', + 'ebony+ayres', 'ebonyporn', 'ebonypussy', 'ebonysex', 'ebonyxxx', 'enormoustits', + 'erosvillage', 'eroticanime', 'eroticart', 'eroticas', 'eroticastories', 'eroticfiction', + 'eroticlesbianstories', 'eroticmovie', 'eroticmovies', 'erotico', 'eroticos', 'eroticpics', + 'eroticpicture', 'eroticpictures', 'eroticsites', 'eroticsounds', 'erotictales', 'erotictext', + 'eroticvideo', 'eroticvideos', 'eroticwomen', 'eroticwriting', 'erotikchat', 'erotique', + 'erotismo', 'escortservice', 'escortservices', 'eurosex', 'explicitsex', 'facecum', + 'facesit', 'facesitters', 'fastporn', 'fatass', 'fatsex', 'feetfetish', + 'feetsex', 'felatio', 'fellatio', 'fellations', 'fetishwear', 'fettegirls', + 'fingerbang', 'fingerfuck', 'flesh4free', 'footjobs', 'footlicking', 'footworship', + 'fornication', 'freeanal', 'freeanalsex', 'freeass', 'freebigboobs', 'freebigtit', + 'freebigtits', 'freeblackcunt', 'freeblackpussy', 'freeblowjob', 'freeblowjobs', 'freebondage', + 'freeboobs', 'freecum', 'freecumshot', 'freecumshots', 'freecunt', 'freecunts', + 'freedick', 'freeerotic', 'freeerotica', 'freeeroticstories', 'freefuck', 'freefucking', + 'freefuckpics', 'freegay', 'freegaypics', 'freehardcore', 'freehardcorepics', 'freehardcorepictures', + 'freehardcoreporn', 'freehardcoresex', 'freehardcoresexpics', 'freehentai', 'freehooters', 'freelargehooters', + 'freelesbian', 'freelesbianporn', 'freelesbiansex', 'freenakedpic', 'freenakedpics', 'freenakedpictures', + 'freenakedwomen', 'freenude', 'freenudecelebs', 'freenudephotos', 'freenudepics', 'freenudes', + 'freeporn', 'freepornmovies', 'freeporno', 'freepornography', 'freepornopics', 'freepornopictures', + 'freepornos', 'freepornpic', 'freepornpics', 'freepornpictures', 'freeporns', 'freepornsite', + 'freepornsites', 'freepussy', 'freepussypic', 'freepussypics', 'freepussypictures', 'freesex', + 'freesexchat', 'freesexmovies', 'freesexnet', 'freesexphotos', 'freesexpic', 'freesexpics', + 'freesexpicture', 'freesexpictures', 'freesexsites', 'freesexstories', 'freesexvideos', 'freesexycam', + 'freeshemale', 'freesmut', 'freetit', 'freetits', 'freevoyeur', 'freexxx', + 'freexxxmovie', 'freexxxmovies', 'freexxxmpeg', 'freexxxphotos', 'freexxxpic', 'freexxxpics', + 'freexxxpicture', 'freexxxpictures', 'freexxxstories', 'freexxxvideo', 'freexxxx', 'fuking', + 'gangbangs', 'gratishardcoregalerie', 'hardcorecelebs', 'hardcorefisting', 'hardcorefree', 'hardcorefucking', + 'hardcorehooters', 'hardcorejunkie', 'hardcorejunky', 'hardcoremovie', 'hardcoremovies', 'hardcorepic', + 'hardcorepics', 'hardcorepictures', 'hardcorepix', 'hardcoreporn', 'hardcoreporno', 'hardcorepornography', + 'hardcorepornos', 'hardcorepussy', 'hardcoresamples', 'hardcoresex', 'hardcoresexpictures', 'hardcorestories', + 'hardcorethumbnails', 'hardcorevideo', 'hardcorevideos', 'hardcorexxx', 'harddicks', 'hardnipples', + 'hardons', 'hardporn', 'indiasex', 'interacialhardcore', 'interacialsex', 'interacialxxx', + 'intercoursepositions', 'internetsex', 'interracialfucking', 'interracialhardcore', 'interracialporn', 'interracialpornography', + 'interracialsex', 'interracialsexstories', 'interracialxxx', 'intimatesex', 'ittybittytitty', 'japaneseporn', + 'japanesesex', 'japansex', 'japanxxx', 'jennacam.com', 'jennajameson', 'jennicam', + 'jerkoff', 'jism', 'jiz', 'jizz', 'juicycunts', 'juicypussy', + 'justhardcore', 'karasamateurs', 'karasxxx', 'kascha', 'kaylakleevage', 'kobetai', + 'koreasex', 'lapdance', 'largeclits', 'largecunts', 'largedicks', 'largehooters', + 'largepussy', 'largetit', 'largetits', 'latinapussy', 'latinasex', 'latinosex', + 'latinoxxx', 'latinxxx', 'legsex', 'lesbianerotica', 'lesbianhardcore', 'lesbianorgies', + 'lesbianorgy', 'lesbianpics', 'lesbianpink', 'lesbianporn', 'lesbian-porno', 'lesbianporno', + 'lesbianpornography', 'lesbianpornos', 'lesbianpussy', 'lesbiansex', 'lesbiansexpics', 'lesbiansexstories', + 'lesbianxxx', 'lickadick', 'lickingpussy', 'lindalovelace', 'lingeriexxx', 'literotica', + 'littleboobs', 'littlepussy', 'littletits', 'livefucking', 'liveporn', 'livesex', + 'livesexcam', 'livesexcams', 'longdicks', 'lovedoll', 'lovedolls', 'magazinessex', + 'makinglove', 'malaysex', 'malenudes', 'malesex', 'mangaporno', 'mangax', + 'mangaxxx', 'manpics', 'mansex', 'marilynchambers', 'massivecocks', 'masterbating', + 'masturbation', 'masturbationvideos', 'maturefucking', 'maturesex', 'maturexxx', 'megaboobs', + 'megaporno', 'megapussy', 'megatits', 'mensdicks', 'mensex', 'm.i.l.f.', + 'milf', 'milfhunterpic', 'milfmpegsample', 'modelsex', 'mondoporn', 'monstercocks', + 'monsterdicks', 'motherfucker', 'moviepost.com', 'mpegsex', 'mpegxxx', 'muffdiving', + 'myslutwife', 'nacktfotos', 'nakedbabes', 'nakedblackwomen', 'nakedcelebrity', 'nakedcelebs', + 'nakedcheerleader', 'nakedchicks', 'nakedgirls', 'nakedguys', 'nakedladies', 'nakedlady', + 'nakedman', 'nakedmen', 'nakedness', 'nakedphotographs', 'nakedphotography', 'nakedphotos', + 'nakedpic', 'nakedpics', 'nakedpicture', 'nakedpictures', 'nakedpussy', 'nakedstars', + 'nakedwife', 'nakedwoman', 'nakedwomen', 'nastychat', 'nastypussy', 'nastysex', + 'nastythumbs', 'naturaltits', 'naughty.com', 'naughtylinks', 'naughtylinx', 'naughtylynx', + 'naughtynurses', 'netsex', 'niceass', 'nicetits', 'nikkinova', 'nikkityler', + 'nipples', 'nookie', 'nookies', 'nudeactress', 'nudeactresses', 'nudeamateur', + 'nudeamateurs', 'nudeasianwomen', 'nudebabes', 'nudebigboobs', 'nudeblack', 'nudeblackwomen', + 'nudeblondes', 'nudeceleb', 'nudeceleberties', 'nudecelebraties', 'nudecelebrites', 'nudecelebrities', + 'nudecelebrity', 'nudecelebs', 'nudecollegegirls', 'nudefemale', 'nudefemales', 'nudefree', + 'nudegay', 'nudeimages', 'nudeladies', 'nudelesbians', 'nudemale', 'nudemales', + 'nudeman', 'nudemen', 'nudepic', 'nudepics', 'nudepicture', 'nudepictures', + 'nudepornography', 'nudepussy', 'nuderaider', 'nuderedheads', 'nudes', 'nudesex', + 'nudestar', 'nudestars', 'nudevideoconferencing', 'nudewoman', 'nudewomen', 'nudism', + 'nudist', 'nudists', 'nudity', 'nylonfetish', 'nylonsex', 'nympho', + 'nymphos', 'olderbabes', 'oldersex', 'oldersluts', 'oldpussy', 'oldsex', + 'oldsluts', 'openlegs', 'openpussy', 'oral4free', 'oral-sex', 'oralsexpictures', + 'orgie', 'orgies', 'orgypics', 'orgys', 'pantyhosefetish', 'pantyhosesex', + 'peepcam', 'persiankitty', 'persiankitty.com', 'perverted', 'picsxxx', 'picturesex', + 'picturesofsex', 'picturessex', 'pimpserver', 'pimpserver.com', 'pinkpussy', 'pissing', + 'pixxx', 'poontang', 'pornagraphy', 'porncast', 'porncity', 'porndirectory', + 'porne', 'pornfree', 'pornmovies', 'pornno', 'pornnude', 'porno', + 'pornoadult', 'pornocartoons', 'pornochat', 'pornodeluxe', 'pornoe', 'pornofilms', + 'pornofree', 'pornogame', 'pornografi', 'pornografia', 'pornografie', 'pornografy', + 'pornograph', 'pornographi', 'pornographia', 'pornographic', 'pornographicpictures', 'pornographics', + 'pornographicvideo', 'pornographicvideos', 'pornographie', 'pornography', 'pornographyfree', 'pornographyphotos', + 'pornographypictures', 'pornography-sex', 'pornographysex', 'pornoland', 'pornolinks', 'pornolynx', + 'pornomagazines', 'pornomovies', 'pornompeg', 'pornophotos', 'pornopic', 'pornopics', + 'pornopicture', 'pornopictures', 'pornos', 'pornosex', 'pornosite', 'pornosites', + 'pornostar', 'pornostories', 'pornovideo', 'pornovideos', 'pornoxxx', 'pornphotos', + 'pornpics', 'pornpictures', 'pornpix', 'pornpost', 'pornqueens', 'pornrated', + 'porns', 'pornsex', 'pornstar', 'pornstories', 'porntrack', 'pornvideo', + 'pornvideos', 'pornypics', 'porstars', 'privatesex', 'privatex', 'privatexx', + 'privatexxx', 'prono', 'pronography', 'publicnudity', 'puffynipples', 'purple+passion', + 'pussyboard', 'pussycam', 'pussycams', 'pussycloseup', 'pussycloseups', 'pussycum', + 'pussycunt', 'pussyeater', 'pussyeaters', 'pussyeating', 'pussyfuck', 'pussyfucking', + 'pussyhair', 'pussyheaven', 'pussyjuice', 'pussylickers', 'pussylicking', 'pussylink', + 'pussylips', 'pussyphotos', 'pussyporno', 'pussys', 'pussysex', 'pussyshots', + 'pussythumbnails', 'pussytits', 'pusy', 'racqueldarrian', 'rape', 'rawlinks', + 'rawpussy', 'rawsex', 'realhardcore', 'realsex', 'redneckporn', 'redpussy', + 'rubberfetish', 'russianxxx', 'scat', 'schiffernude', 'seka', 'seniorsex', + 'sex4free', 'sex66', 'sexacts', 'sexadult', 'sexaids', 'sexamateur', + 'sexanal', 'sexandpictures', 'sexaphone', 'sexaudio', 'sexavi', 'sexbondage', + 'sexboner', 'sexbuttfucker', 'sexcam', 'sexcams', 'sexchat', 'sexchatrooms', + 'sexcites', 'sexclub', 'sexclubs', 'sex.com', 'sexdating', 'sexe', + 'sexfantasies', 'sexfantasy', 'sexfilm', 'sexgallery', 'sexgame', 'sexgames', + 'sexgirl', 'sexgirls', 'sexgroup', 'sexguide', 'sexhardcore', 'sexhphoto', + 'sexhungry', 'sexhungryjoe', 'sexhungryjoes', 'sexi', 'seximages', 'sexis', + 'sexjapan', 'sex.jpg', 'sexlinda', 'sexlinks', 'sexlinx', 'sexlive', + 'sexmagazine', 'sexmagazines', 'sexmature', 'sexmelayu', 'sexmodels', 'sexmovie', + 'sexmovies', 'sexmpeg', 'sexnude', 'sexnudity', 'sexo', 'sexoanal', + 'sexole', 'sexontheinternet', 'sexoral', 'sexpasswords', 'sexphoto', 'sexphotos', + 'sexpic', 'sexpicnet', 'sexpics', 'sexpicture', 'sexpictures', 'sexpicturesfree', + 'sexpix', 'sexplaza', 'sexporn', 'sexporno', 'sexpositions', 'sexpussy', + 'sexroulette', 'sexs', 'sexsamples', 'sexsearch', 'sexsex', 'sexsexsex', + 'sexshare', 'sexshops', 'sexshow', 'sexshows', 'sexsite', 'sexsites', + 'sexslave', 'sexsound', 'sexsounds', 'sexsource', 'sexspaces', 'sexspaces.com', + 'sexstories', 'sexstory', 'sexstorys', 'sextalk', 'sexteen', 'sexthumbnails', + 'sex-toons', 'sextoons', 'sextour', 'sextoy', 'sextoys', 'sextpus', + 'sextracker.com', 'sextropolis', 'sexualbondage', 'sexualfantasies', 'sexualfantasy', 'sexualintercourse', + 'sexualpictures', 'sexualpleasure', 'sexualpositions', 'sexuncensored', 'sexvideo', 'sexvision', + 'sexvote', 'sexwomen', 'sexworld', 'sexx', 'sexxx', 'sexxxx', + 'sexxxxx', 'sexyamateurs', 'sexybabes', 'sexyblack', 'sexyboobs', 'sexybookmark', + 'sexybookmarka', 'sexybookmarks', 'sexybutts', 'sexycunts', 'sexygirl', 'sexygirls', + 'sexyladies', 'sexylady', 'sexylegs', 'sexylingerie', 'sexymen', 'sexyphotos', + 'sexypics', 'sexypictures', 'sexypost', 'sexypussies', 'sexypussy', 'sexysites', + 'sexystories', 'sexywoman', 'sexywomen', 'shavedcunt', 'shavedcunts', 'shavedpussies', + 'shavedpussy', 'shavedpussypics', 'shavedsluts', 'shavedwomen', 'shavenpussies', 'shavenpussy', + 'shavepussy', 'sheboy', 'she-male', 'shemale+video', 'shemaleyum', 'showcam', + 'showcams', 'showercam', 'showercams', 'slavesex', 'smallboobs', 'smallbreasts', + 'smalldicks', 'smallpussy', 'smalltits', 'smut', 'smut69', 'smutland', + 'smutserver', 'smutshack', 'softcore', 'softporn', 'softpornography', 'spankingpage', + 'spreadpussy', 'spycamadult', 'stockingsex', 'storieserotic', 'storiessex', 'straightsex', + 'stretchedcunt', 'stripclub', 'stripclubs', 'stripshow', 'striptease', 'strokeit', + 'strokeme', 'suckdick', 'sucksex', 'superchicken', 'supersex', 'supertits', + 'swallowcum', 'swinger', 'swingerclub', 'swingers', 'swollenclits', 'syberporn', + 'sylviasaint', 'teenanal', 'teenanalsex', 'teenhardcore', 'teenie', 'teenies', + 'teennude', 'teenpics', 'teenporn', 'teenporno', 'teenpussy', 'teensex', + 'teenslut', 'teensluts', 'teensuck', 'teenxxx', 'tgp', 'thaipussy', + 'thaisex', 'thehun', 'threesomes', 'thumblords', 'thumbnailssex', 'thumbzilla', + 'tiffanytowers', 'tightcunt', 'tightpussies', 'tightpussy', 'tinypussy', 'tinytits', + 'tinytitties', 'tisandass', 'tit', 'titbondage', 'titfuck', 'titfucking', + 'tities', 'titman', 'titsandass', 'titsass', 'titties', 'titts', + 'titty', 'tittyfuck', 'tittyfucking', 'tittys', 'tokyotopless', 'tommysbookmark', + 'toplesswomen', 'trannies', 'transexual', 'transsexuels', 'twat', 'twats', + 'twink', 'ultradonkey', 'ultrahardcore', 'uncutcocks', 'vaginalintercourse', 'vaginapictures', + 'videoporno', 'videosex', 'videoxxx', 'vintageporn', 'virtualsex', 'vividtv', + 'wank', 'wankers', 'wanking', 'wendywhoppers', 'wetcunt', 'wetcunts', + 'wetdick', 'wetpanties', 'wetpussies', 'wetpussy', 'wetsex', 'wetvagina', + 'whitepussy', 'whitesex', 'whitetits', 'whitexxx', 'wifesharing', 'wifeswapping', + 'wildpussy', 'wildsex', 'womensex', 'worldsex', 'worldsexguide', 'x-rated', + 'xrated', 'x-ratedmovie', 'x-ratedmovies', 'x-ratedvideo', 'x-ratedvideos', 'xxx4free', + 'xxxadult', 'xxxadultmovies', 'xxxadultvideo', 'xxxadultvideos', 'xxxbabes', 'xxxcam', + 'xxxcelebrities', 'xxxfree', 'xxxfreepics', 'xxxgalleries', 'xxxhardcore', 'xxxjapan', + 'xxxlinks', 'xxxmodels', 'xxxmovie', 'xxxmovies', 'xxxmpeg', 'xxxpassword', + 'xxxphoto', 'xxxphotos', 'xxxpic', 'xxx-pics', 'xxxpics', 'xxxpicture', + 'xxxpictures', 'xxxpicturesfree', 'xxxpicx', 'xxxpirtures', 'xxxporn', 'xxxporno', + 'xxxpussy', 'xxx-rated', 'xxxrated', 'xxxsex', 'xxxsites', 'xxxsluts', + 'xxxstories', 'xxxteen', 'xxxthumbnails', 'xxxthumbs', 'xxxtoons', 'xxxtoys', + 'xxxvideo', 'xxxvideos', 'xxxwomen', 'xxxx', 'xxxxx', 'xxxxxx', + 'filthyfarm', 'adultcheck', 'erotic', 'mistresses', 'naughty', + 'adult', 'amateur', 'amateurs', 'anal', 'analau', 'poker', + 'anally', 'asian', 'swinging', 'ass', 'orgy', 'sexvideos', + 'babe', 'babes', 'bare', 'glamour', 'casino', 'bed', + 'vibrator', 'bikini', 'bisexual', 'blonde', 'breasted', 'breasts', + 'busty', 'butts', 'candy', 'caning', 'caps', 'catholic', + 'chained', 'chested', 'chubby', 'close-ups', 'coupling', + 'cucumber', 'doll', 'dolls', 'dolly', 'dominating', 'drinking', + 'drunk', 'fat', 'feet', 'fingering', 'fishnet', 'flasher', + 'footjob', 'foreplay', 'foreplaying', 'girlfriend', 'girlfriends', 'gymnast', + 'hairy', 'holly', 'horse', 'housewife', 'houswife', 'insertion', + 'insertions', 'interracial', 'jerka', 'juicy', 'kissing', 'kitty', + 'lactating', 'ladyboy', 'lance', 'latina', 'latins', 'leather', + 'legs', 'lesbian', 'lesbians', 'licking', 'lingerie', 'lubricants', + 'mature', 'midget', 'minor', 'mistress', 'nude', + 'older', 'olez', 'oral', 'panties', 'pantyhose', 'pedro', + 'peeing', 'penetration', 'pigtailed', 'pleasure', 'plump', + 'plumper', 'poser', 'posers', 'poses', 'posing', 'prosecuted', + 'punishment', 'reproducing', 'sex', 'shaved', 'shock', 'slave', + 'sleeping', 'speculums', 'spread', 'spreading', 'squirting', 'stripper', + 'stripping', 'swapping', 'thong', 'topless', 'toying', + 'trix', 'undressing', 'uniform', 'whipcream', 'brazzers', 'порно', + 'порн', 'лесб', 'гей', 'геи', 'прон' ]; const XXX_VERY_BAD_WORDS = [ - 'catgoddess', 'gracel', 'fatman', 'falko', 'pthc', - 'ptsc', 'yukikax', 'ls-models', '3yo', '4yo', '5yo', '6yo', '7yo', '8yo', '9yo', - '10yo', '11yo', '12yo', '13yo', '14yo', '15yo', '16yo' + 'catgoddess', 'gracel', 'fatman', 'falko', 'pthc', + 'ptsc', 'yukikax', 'ls-models', '3yo', '4yo', '5yo', '6yo', '7yo', '8yo', '9yo', + '10yo', '11yo', '12yo', '13yo', '14yo', '15yo', '16yo' ] module.exports = { - XXX_BLOCK_WORDS, - XXX_VERY_BAD_WORDS + XXX_BLOCK_WORDS, + XXX_VERY_BAD_WORDS }; diff --git a/src/app/changelog-page.js b/src/app/changelog-page.js index a576448..6e59a09 100644 --- a/src/app/changelog-page.js +++ b/src/app/changelog-page.js @@ -4,23 +4,23 @@ import ReactMarkdown from 'react-markdown' import fs from 'fs' export default class ChangeLog extends Page { - constructor(props) { - super(props) - this.setTitle('Changelog'); + constructor(props) { + super(props) + this.setTitle('Changelog'); - let changelogPath = 'CHANGELOG.md' - if(!fs.existsSync(changelogPath)) - changelogPath = 'resources/CHANGELOG.md' + let changelogPath = 'CHANGELOG.md' + if(!fs.existsSync(changelogPath)) + changelogPath = 'resources/CHANGELOG.md' - this.changelog = fs.readFileSync(changelogPath) - if(!this.changelog) - throw new Error('no changelog file') - } - render() { - return ( -
- -
- ); - } + this.changelog = fs.readFileSync(changelogPath) + if(!this.changelog) + throw new Error('no changelog file') + } + render() { + return ( +
+ +
+ ); + } } diff --git a/src/app/component.js b/src/app/component.js index 625e56c..d2060cf 100644 --- a/src/app/component.js +++ b/src/app/component.js @@ -6,13 +6,13 @@ export default class BTComponent extends Component { // Свайп действия if( this.props.onSwipeLeft || - this.props.onSwipeRight || - this.props.onSwipeTop || - this.props.onSwipeBottom || - this.onSwipeLeft || - this.onSwipeRight || - this.onSwipeTop || - this.onSwipeBottom + this.props.onSwipeRight || + this.props.onSwipeTop || + this.props.onSwipeBottom || + this.onSwipeLeft || + this.onSwipeRight || + this.onSwipeTop || + this.onSwipeBottom ) { this.swipeFunctions = listenSwipe(this, { diff --git a/src/app/config-page.js b/src/app/config-page.js index e6f4ad8..e7c0bf8 100644 --- a/src/app/config-page.js +++ b/src/app/config-page.js @@ -9,302 +9,302 @@ import Slider from 'material-ui/Slider' import fs from 'fs' let dialog if(typeof WEB === 'undefined') - dialog = require('electron').remote.dialog + dialog = require('electron').remote.dialog export default class ConfigPage extends Page { - constructor(props) { - super(props) - this.setTitle('Rats settings'); - this.options = {} - } - componentDidMount() { - this.loadSettings() - } - loadSettings() { - window.torrentSocket.emit('config', window.customLoader((options) => { - this.options = options; - console.log(this.options) - this.forceUpdate(); - })); - } - saveSettings() { - window.torrentSocket.emit('setConfig', this.options) - this.settingsSavedMessage = true - this.forceUpdate() - setTimeout(() => { - this.settingsSavedMessage = false - this.forceUpdate() - }, 1000) - } - render() { - return ( -
-
- { - window.router('/') - }} /> -
-
- { - this.options.indexer = checked - if(!this.options.indexer) - this.options.p2p = false - this.forceUpdate() - }} - /> -
-
-
{__('Scanning port')}
- 0 ? undefined : __('This field is required')} - value={this.options.spiderPort} - onChange={(e, value) => { - if(!value) - value = 0 - if(value > 65535) - value = 65535 + constructor(props) { + super(props) + this.setTitle('Rats settings'); + this.options = {} + } + componentDidMount() { + this.loadSettings() + } + loadSettings() { + window.torrentSocket.emit('config', window.customLoader((options) => { + this.options = options; + console.log(this.options) + this.forceUpdate(); + })); + } + saveSettings() { + window.torrentSocket.emit('setConfig', this.options) + this.settingsSavedMessage = true + this.forceUpdate() + setTimeout(() => { + this.settingsSavedMessage = false + this.forceUpdate() + }, 1000) + } + render() { + return ( +
+
+ { + window.router('/') + }} /> +
+
+ { + this.options.indexer = checked + if(!this.options.indexer) + this.options.p2p = false + this.forceUpdate() + }} + /> +
+
+
{__('Scanning port')}
+ 0 ? undefined : __('This field is required')} + value={this.options.spiderPort} + onChange={(e, value) => { + if(!value) + value = 0 + if(value > 65535) + value = 65535 - this.options.spiderPort = parseInt(value) - this.forceUpdate() - }} - /> -
-
* {__('For current work TCP and UDP ports must be fully open and forward in case of router usage')}
-
+ this.options.spiderPort = parseInt(value) + this.forceUpdate() + }} + /> +
+
* {__('For current work TCP and UDP ports must be fully open and forward in case of router usage')}
+
-
-
-
{__('Trackers responce port')}
- 0 ? undefined : __('This field is required')} - value={this.options.udpTrackersPort} - onChange={(e, value) => { - if(!value) - value = 0 - if(value > 65535) - value = 65535 +
+
+
{__('Trackers responce port')}
+ 0 ? undefined : __('This field is required')} + value={this.options.udpTrackersPort} + onChange={(e, value) => { + if(!value) + value = 0 + if(value > 65535) + value = 65535 - this.options.udpTrackersPort = parseInt(value) - this.forceUpdate() - }} - /> -
-
* {__('For current work UDP port must be fully open and forward in case of router usage')}
-
+ this.options.udpTrackersPort = parseInt(value) + this.forceUpdate() + }} + /> +
+
* {__('For current work UDP port must be fully open and forward in case of router usage')}
+
- { - this.options.upnp = checked - this.forceUpdate() - }} - /> + { + this.options.upnp = checked + this.forceUpdate() + }} + /> -
-
{__('Collection directory')}
- 0 ? undefined : __('This field is required')} - value={this.options.dbPath} - onChange={(e, value) => { - if(!fs.existsSync(value)) - return +
+
{__('Collection directory')}
+ 0 ? undefined : __('This field is required')} + value={this.options.dbPath} + onChange={(e, value) => { + if(!fs.existsSync(value)) + return - this.options.dbPath = value - this.forceUpdate() - }} - /> - { - if(!dialog) - return - const dir = dialog.showOpenDialog({properties: ['openDirectory']})[0] - if(dir) - { - this.options.dbPath = dir - this.forceUpdate() - } - }} /> -
+ this.options.dbPath = value + this.forceUpdate() + }} + /> + { + if(!dialog) + return + const dir = dialog.showOpenDialog({properties: ['openDirectory']})[0] + if(dir) + { + this.options.dbPath = dir + this.forceUpdate() + } + }} /> +
-
-
{__('Download torrents directory')}
- { - if(!fs.existsSync(value)) - return +
+
{__('Download torrents directory')}
+ { + if(!fs.existsSync(value)) + return - this.options.client.downloadPath = value - this.forceUpdate() - }} - /> - { - if(!dialog) - return - const dir = dialog.showOpenDialog({properties: ['openDirectory']})[0] - if(dir) - { - this.options.client.downloadPath = dir - this.forceUpdate() - } - }} /> -
+ this.options.client.downloadPath = value + this.forceUpdate() + }} + /> + { + if(!dialog) + return + const dir = dialog.showOpenDialog({properties: ['openDirectory']})[0] + if(dir) + { + this.options.client.downloadPath = dir + this.forceUpdate() + } + }} /> +
- { - this.options.trayOnMinimize = checked - this.forceUpdate() - }} - /> + { + this.options.trayOnMinimize = checked + this.forceUpdate() + }} + /> - { - this.options.trayOnClose = checked - this.forceUpdate() - }} - /> + { + this.options.trayOnClose = checked + this.forceUpdate() + }} + /> -
{__('P2P Rats network settings')}:
- { - this.options.p2p = this.options.indexer && checked - this.forceUpdate() - }} - /> -
- { - this.options.p2pBootstrap = checked - this.forceUpdate() - }} - /> -
* {__('Use extrnral bootstrap nodes to get p2p peers when network setted wrong or need external source')}
-
-
-
-
{__('Max peers limit')} ({__('current')}: {this.options.p2pConnections})
- { - this.options.p2pConnections = value - this.forceUpdate() - }} - /> -
-
-
- { - this.options.p2pReplication = checked - this.forceUpdate() - }} - /> -
* {__('Enable torrents replication from another rats clients. Dont recomended if torrent scanner works correct')}.
-
+
{__('P2P Rats network settings')}:
+ { + this.options.p2p = this.options.indexer && checked + this.forceUpdate() + }} + /> +
+ { + this.options.p2pBootstrap = checked + this.forceUpdate() + }} + /> +
* {__('Use extrnral bootstrap nodes to get p2p peers when network setted wrong or need external source')}
+
+
+
+
{__('Max peers limit')} ({__('current')}: {this.options.p2pConnections})
+ { + this.options.p2pConnections = value + this.forceUpdate() + }} + /> +
+
+
+ { + this.options.p2pReplication = checked + this.forceUpdate() + }} + /> +
* {__('Enable torrents replication from another rats clients. Dont recomended if torrent scanner works correct')}.
+
-
{__('Torrent network scanner settings')}:
-
-
-
{__('Scanner walk speed')} ({__('current')}: {this.options.spider && this.options.spider.walkInterval}) [{__('affected after program reload')}]
- { - this.options.spider.walkInterval = value - this.forceUpdate() - }} - /> -
-
* {__('Low value')} - {__('fast initial scanning and high cpu usage')}. {__('High Value')} - {__('low cpu usage but very slow scanning')}. - {__('Good value between')} 3-60. {__('Defaul value')}: 5
-
-
-
-
{__('Nodes usage')} ({__('current')}: {this.options.spider && this.options.spider.nodesUsage})
- { - this.options.spider.nodesUsage = value - this.forceUpdate() - }} - /> -
-
* {__('Low Value')} - {__('very low usage of nodes, low network traffic, slow torrent scanning')}. {__('High value')} - {__('high traffic, fast scanning, high routers usage')}. - {__('Recomended value between')} 10-1000. {__('Defaul value')}: 100. 0 - {__('Ignore this option')} ({__('no limit')}). -
-
-
-
-
{__('Reduce network packages')} ({__('current')}: {this.options.spider && this.options.spider.packagesLimit})
- { - this.options.spider.packagesLimit = value - this.forceUpdate() - }} - /> -
-
* {__('Low Value')} - {__('ignore more usless network packages, lower traffic and routers usage')}. {__('High Value')} - {__('high traffic and router usage in prospect')}. - {__('Recomended value between')} 300-2000. {__('Defaul value')}: 500. 0 - {__('Ignore this option')} ({__('no limit')}). -
-
+
{__('Torrent network scanner settings')}:
+
+
+
{__('Scanner walk speed')} ({__('current')}: {this.options.spider && this.options.spider.walkInterval}) [{__('affected after program reload')}]
+ { + this.options.spider.walkInterval = value + this.forceUpdate() + }} + /> +
+
* {__('Low value')} - {__('fast initial scanning and high cpu usage')}. {__('High Value')} - {__('low cpu usage but very slow scanning')}. + {__('Good value between')} 3-60. {__('Defaul value')}: 5
+
+
+
+
{__('Nodes usage')} ({__('current')}: {this.options.spider && this.options.spider.nodesUsage})
+ { + this.options.spider.nodesUsage = value + this.forceUpdate() + }} + /> +
+
* {__('Low Value')} - {__('very low usage of nodes, low network traffic, slow torrent scanning')}. {__('High value')} - {__('high traffic, fast scanning, high routers usage')}. + {__('Recomended value between')} 10-1000. {__('Defaul value')}: 100. 0 - {__('Ignore this option')} ({__('no limit')}). +
+
+
+
+
{__('Reduce network packages')} ({__('current')}: {this.options.spider && this.options.spider.packagesLimit})
+ { + this.options.spider.packagesLimit = value + this.forceUpdate() + }} + /> +
+
* {__('Low Value')} - {__('ignore more usless network packages, lower traffic and routers usage')}. {__('High Value')} - {__('high traffic and router usage in prospect')}. + {__('Recomended value between')} 300-2000. {__('Defaul value')}: 500. 0 - {__('Ignore this option')} ({__('no limit')}). +
+
- { - this.settingsSavedMessage + { + this.settingsSavedMessage &&
{__('Settings saved')}
- } + } -
- { - this.saveSettings() - }} /> -
+
+ { + this.saveSettings() + }} /> +
-
-
- ); - } +
+
+ ); + } } diff --git a/src/app/content.js b/src/app/content.js index 59083f0..2321641 100644 --- a/src/app/content.js +++ b/src/app/content.js @@ -236,7 +236,7 @@ const ContentCategoryProp = 'contentCategory'; const { XXX_BLOCK_WORDS, - XXX_VERY_BAD_WORDS + XXX_VERY_BAD_WORDS } = require('./bad-words'); // блокируем порнографию @@ -270,7 +270,7 @@ const detectSubCategory = (torrent, files, typesPriority, contentType) => { fileCheck = fileCheck.join('.'); blockBadName(torrent, fileCheck); - + return torrent[ContentTypeProp] == 'bad'; }) } @@ -304,7 +304,7 @@ const torrentTypeDetect = (torrent, files) => { } } let priority = Object.keys(typesPriority).sort(function(a, b){ - return typesPriority[b] - typesPriority[a] + return typesPriority[b] - typesPriority[a] }); if(priority.length > 0) torrent[ContentTypeProp] = priority[0]; diff --git a/src/app/dmca-page.js b/src/app/dmca-page.js index 57b0f75..c627a61 100644 --- a/src/app/dmca-page.js +++ b/src/app/dmca-page.js @@ -7,27 +7,27 @@ import NavigationClose from 'material-ui/svg-icons/navigation/close'; export default class DMCAPage extends Page { - render() { - return ( -
- { window.router('/') }}>} - /> + render() { + return ( +
+ { window.router('/') }}>} + /> -
-
RatsOnTheBoat.org is in compliance with 17 U.S.C. § 512, the Digital Millennium Copyright Act ("DMCA") and the Directive 2001/29/EC of the European Parliament.
- -
Content status
+
+
RatsOnTheBoat.org is in compliance with 17 U.S.C. § 512, the Digital Millennium Copyright Act ("DMCA") and the Directive 2001/29/EC of the European Parliament.
+ +
Content status
- Our main goal is collect and make analysis of information from the torrent network. We don't save/distribute any real content/data and also don't save any torrents files - we are respect DMCA law. - Information collected automaticly and the real source are torrent clients based on torrent protocol. + Our main goal is collect and make analysis of information from the torrent network. We don't save/distribute any real content/data and also don't save any torrents files - we are respect DMCA law. + Information collected automaticly and the real source are torrent clients based on torrent protocol. -
Block mechanisms (for rightholders)
+
Block mechanisms (for rightholders)
- Right holders can block/remove content that they responsible for. Contact administration or left application about content removal. -
-
- ); - } + Right holders can block/remove content that they responsible for. Contact administration or left application about content removal. +
+
+ ); + } } diff --git a/src/app/download-page.js b/src/app/download-page.js index 96c3940..2b5554b 100644 --- a/src/app/download-page.js +++ b/src/app/download-page.js @@ -10,48 +10,48 @@ export default class TopPage extends Page { downloads = [] constructor(props) { - super(props) - this.setTitle('Current Downloads'); + super(props) + this.setTitle('Current Downloads'); } getDownloads() { - window.torrentSocket.emit('downloads', window.customLoader((downloads) => { - this.downloads = downloads - this.forceUpdate() - })) + window.torrentSocket.emit('downloads', window.customLoader((downloads) => { + this.downloads = downloads + this.forceUpdate() + })) } componentDidMount() { - super.componentDidMount(); - this.getDownloads() - this.downloading = () => this.getDownloads() - window.torrentSocket.on('downloading', this.downloading); - this.downloadDone = () => this.getDownloads() - window.torrentSocket.on('downloadDone', this.downloadDone); + super.componentDidMount(); + this.getDownloads() + this.downloading = () => this.getDownloads() + window.torrentSocket.on('downloading', this.downloading); + this.downloadDone = () => this.getDownloads() + window.torrentSocket.on('downloadDone', this.downloadDone); } componentWillUnmount() { - if(this.downloading) - window.torrentSocket.off('downloading', this.downloading); - if(this.downloadDone) - window.torrentSocket.off('downloadDone', this.downloadDone); + if(this.downloading) + window.torrentSocket.off('downloading', this.downloading); + if(this.downloadDone) + window.torrentSocket.off('downloadDone', this.downloadDone); } render() { - return ( -
-
- { - window.router('/') - }} /> - - { - this.downloads.map((download, index) => { - return - }) - } - -
-
- ); + return ( +
+
+ { + window.router('/') + }} /> + + { + this.downloads.map((download, index) => { + return + }) + } + +
+
+ ); } } diff --git a/src/app/feed-page.js b/src/app/feed-page.js index 41cad0d..8a11b42 100644 --- a/src/app/feed-page.js +++ b/src/app/feed-page.js @@ -8,89 +8,89 @@ import MenuItem from 'material-ui/MenuItem'; import Feed from './feed'; export default class FeedPage extends Page { - constructor(props) { - super(props) - this.setTitle('Rats On The Boat - Content Search Engine'); - } - componentDidMount() - { - Search.instance().onSearchUpdate = () => this.forceUpdate() - } - componentWillUnmount() - { - Search.instance().onSearchUpdate = () => {} - } - render() { - const orderText = (text, field) => { - if(field !== Search.instance().state.orderBy) - return text; + constructor(props) { + super(props) + this.setTitle('Rats On The Boat - Content Search Engine'); + } + componentDidMount() + { + Search.instance().onSearchUpdate = () => this.forceUpdate() + } + componentWillUnmount() + { + Search.instance().onSearchUpdate = () => {} + } + render() { + const orderText = (text, field) => { + if(field !== Search.instance().state.orderBy) + return text; - if(Search.instance().state.orderDesc) - return text + ' ⇩' - else - return text + ' ⇧' - } + if(Search.instance().state.orderDesc) + return text + ' ⇩' + else + return text + ' ⇧' + } - return ( -
-
- { - event.preventDefault(); // fix overclick on torrent - if(value === 'none') { - Search.instance().setState({orderBy: null}, () => { - Search.instance().search(true) - }) - return; - } + return ( +
+
+ { + event.preventDefault(); // fix overclick on torrent + if(value === 'none') { + Search.instance().setState({orderBy: null}, () => { + Search.instance().search(true) + }) + return; + } - if(value === Search.instance().state.orderBy) - { - Search.instance().setState({orderDesc: !Search.instance().state.orderDesc}, () => { - Search.instance().search(true) - }) - return; - } + if(value === Search.instance().state.orderBy) + { + Search.instance().setState({orderDesc: !Search.instance().state.orderDesc}, () => { + Search.instance().search(true) + }) + return; + } - Search.instance().setState({ - orderBy: value, - orderDesc: (value === 'seeders' || value === 'completed' || value === 'added') ? true : Search.instance().state.orderDesc - }, () => { - Search.instance().search(true) - }) - }} - > - - - - - - - - - } + Search.instance().setState({ + orderBy: value, + orderDesc: (value === 'seeders' || value === 'completed' || value === 'added') ? true : Search.instance().state.orderDesc + }, () => { + Search.instance().search(true) + }) + }} + > + + + + + + + + + } - moreTorrentsEnabled={Search.instance().moreSearchTorrents && !Search.instance().state.searchingIndicator} - moreFilesEnabled={Search.instance().moreSearchFiles && !Search.instance().state.searchingIndicator} - onMoreTorrents={() => Search.instance().moreTorrents()} - onMoreFiles={() => Search.instance().moreFiles()} - moreTorrentsIndicator={Search.instance().state.moreTorrentsIndicator} - moreFilesIndicator={Search.instance().state.moreFilesIndicator} - /> -
-
- -
-
- ); - } + moreTorrentsEnabled={Search.instance().moreSearchTorrents && !Search.instance().state.searchingIndicator} + moreFilesEnabled={Search.instance().moreSearchFiles && !Search.instance().state.searchingIndicator} + onMoreTorrents={() => Search.instance().moreTorrents()} + onMoreFiles={() => Search.instance().moreFiles()} + moreTorrentsIndicator={Search.instance().state.moreTorrentsIndicator} + moreFilesIndicator={Search.instance().state.moreFilesIndicator} + /> +
+
+ +
+
+ ); + } } diff --git a/src/app/feed.js b/src/app/feed.js index 6b55937..92d94e0 100644 --- a/src/app/feed.js +++ b/src/app/feed.js @@ -5,32 +5,32 @@ import Divider from 'material-ui/Divider'; import Subheader from 'material-ui/Subheader'; export default class RecentTorrents extends Component { - constructor() { - super() - this.torrents = []; - } - componentDidMount() { - window.torrentSocket.emit('feed', window.customLoader((data) => { - if(data) { - this.torrents = data; - console.log(data) - this.forceUpdate(); - } - })) - } - render() { - return ( - - - {__('Feed')} - - - { - this.torrents.map((torrent, index) =>{ - return ; - }) - } - - ); - } + constructor() { + super() + this.torrents = []; + } + componentDidMount() { + window.torrentSocket.emit('feed', window.customLoader((data) => { + if(data) { + this.torrents = data; + console.log(data) + this.forceUpdate(); + } + })) + } + render() { + return ( + + + {__('Feed')} + + + { + this.torrents.map((torrent, index) =>{ + return ; + }) + } + + ); + } } diff --git a/src/app/filters-page.js b/src/app/filters-page.js index 3fb82ef..43c999d 100644 --- a/src/app/filters-page.js +++ b/src/app/filters-page.js @@ -11,182 +11,182 @@ import MenuItem from 'material-ui/MenuItem'; import fs from 'fs' export default class ConfigPage extends Page { - constructor(props) { - super(props) - this.setTitle('Rats filters'); - this.options = {} - } - componentDidMount() { - this.loadSettings() - } - loadSettings() { - window.torrentSocket.emit('config', window.customLoader((options) => { - this.options = options; - console.log(this.options) - this.forceUpdate(); - })); - } - saveSettings() { - window.torrentSocket.emit('setConfig', this.options) - this.settingsSavedMessage = true - this.forceUpdate() - setTimeout(() => { - this.settingsSavedMessage = false - this.forceUpdate() - }, 1000) - } - render() { - return ( -
-
- { - window.router('/') - }} /> -
+ constructor(props) { + super(props) + this.setTitle('Rats filters'); + this.options = {} + } + componentDidMount() { + this.loadSettings() + } + loadSettings() { + window.torrentSocket.emit('config', window.customLoader((options) => { + this.options = options; + console.log(this.options) + this.forceUpdate(); + })); + } + saveSettings() { + window.torrentSocket.emit('setConfig', this.options) + this.settingsSavedMessage = true + this.forceUpdate() + setTimeout(() => { + this.settingsSavedMessage = false + this.forceUpdate() + }, 1000) + } + render() { + return ( +
+
+ { + window.router('/') + }} /> +
-
+
-
-
-
{__('Max files per torrent')} ({__('current')}: {this.options.filters && this.options.filters.maxFiles})
- { - this.options.filters.maxFiles = value - this.forceUpdate() - }} - /> - { - if(!this.options.filters) - return +
+
+
{__('Max files per torrent')} ({__('current')}: {this.options.filters && this.options.filters.maxFiles})
+ { + this.options.filters.maxFiles = value + this.forceUpdate() + }} + /> + { + if(!this.options.filters) + return - this.options.filters.maxFiles = parseInt(value) - this.forceUpdate() - }} - /> -
-
* 0 - {__('Disabled')}. -
-
+ this.options.filters.maxFiles = parseInt(value) + this.forceUpdate() + }} + /> +
+
* 0 - {__('Disabled')}. +
+
-
-
-
{__('Torrent name regular extension filtering')}
- { - if(!this.options.filters) - return +
+
+
{__('Torrent name regular extension filtering')}
+ { + if(!this.options.filters) + return - this.options.filters.namingRegExp = value - this.forceUpdate() - }} - /> - { - if(!this.options.filters) - return + this.options.filters.namingRegExp = value + this.forceUpdate() + }} + /> + { + if(!this.options.filters) + return - this.options.filters.namingRegExp = value - this.forceUpdate() - }} - > - \u0400-\u04FF]+$`} primaryText={__('Russian + English only (With symbols)')} /> - ]+$'} primaryText={__('English only (With symbols)')} /> - - -
- { - if(!this.options.filters) - return + this.options.filters.namingRegExp = value + this.forceUpdate() + }} + > + \u0400-\u04FF]+$`} primaryText={__('Russian + English only (With symbols)')} /> + ]+$'} primaryText={__('English only (With symbols)')} /> + + +
+ { + if(!this.options.filters) + return - this.options.filters.namingRegExpNegative = checked - this.forceUpdate() - }} - /> -
+ this.options.filters.namingRegExpNegative = checked + this.forceUpdate() + }} + /> +
* - {__('clean string means disabled')} -
-
+
+
- { - if(!this.options.filters) - return + { + if(!this.options.filters) + return - this.options.filters.adultFilter = checked - this.forceUpdate() - }} - /> + this.options.filters.adultFilter = checked + this.forceUpdate() + }} + /> - { - this.toRemoveProbably && this.toRemoveProbably > 0 - ? -
{__('Torrents to clean')}: {this.toRemoveProbably}
- : - null - } - { - this.toRemove && this.toRemove > 0 - ? -
{__('Torrents cleaned')}: {this.toRemove}
- : - null - } + { + this.toRemoveProbably && this.toRemoveProbably > 0 + ? +
{__('Torrents to clean')}: {this.toRemoveProbably}
+ : + null + } + { + this.toRemove && this.toRemove > 0 + ? +
{__('Torrents cleaned')}: {this.toRemove}
+ : + null + } - { - this.settingsSavedMessage + { + this.settingsSavedMessage &&
{__('Settings saved')}
- } + } -
- { - window.torrentSocket.emit('removeTorrents', true, window.customLoader((toRemove) => { - this.toRemoveProbably = toRemove - this.forceUpdate() - })); - }} /> - { - window.torrentSocket.emit('removeTorrents', false, window.customLoader((toRemove) => { - this.toRemove = toRemove - this.forceUpdate() - })); - }} /> -
+
+ { + window.torrentSocket.emit('removeTorrents', true, window.customLoader((toRemove) => { + this.toRemoveProbably = toRemove + this.forceUpdate() + })); + }} /> + { + window.torrentSocket.emit('removeTorrents', false, window.customLoader((toRemove) => { + this.toRemove = toRemove + this.forceUpdate() + })); + }} /> +
-
- { - this.saveSettings() - }} /> -
+
+ { + this.saveSettings() + }} /> +
-
+
-
- ); - } +
+ ); + } } diff --git a/src/app/footer.js b/src/app/footer.js index 19616c5..b0f11f5 100644 --- a/src/app/footer.js +++ b/src/app/footer.js @@ -3,18 +3,18 @@ import React from 'react'; export default (props) => { return (
- + + c5.308,6.188,7.074,12.091,4.423,11.212c-2.66-0.896-13.267-7.08-45.104-2.066c-4.126,1.17-21.221-12.682-44.513-12.977 + c-23.283-0.295-40.381,6.346-64.85,72.296c-2.356,5.828-18.866,19.386-27.71,25.865C3.536,162.529,0.007,169.787,0,182.763 + c-0.018,18.158,25.934,27.187,81.648,26.889c55.715-0.292,85.195-9.388,85.195-9.388c-62.789,6.773-158.907,10.52-158.907-18.687 + c0-20.641,28.321-28.47,36.281-28.184c7.958,0.3,13.562,12.673,33.307,5.603c3.247-0.295,1.48,4.423-1.18,7.369 + c-2.651,2.942-0.586,6.487,9.73,6.487c10.315,0,41.183,0.295,47.707,0c6.531-0.299,11.839-11.792-9.384-12.68 + c-18.548,0.311,12.023-5.773,15.915-21.813c0.709-3.927,8.84-4.139,15.918-4.119c20.777,0.029,34.485,38.193,38.912,38.338 + c4.416,0.15,17.979,1.621,17.683-4.273c-0.292-5.897-11.491-3.241-13.854-6.487c-2.359-3.234-10.023-15.504-7.366-21.104 + c2.65-5.59,12.674-21.229,24.463-22.988c11.789-1.777,42.451,7.361,47.459,0c5.012-7.372-6.783-11.512-15.918-28.611 + C243.779,80.572,238.768,71.728,220.195,71.427z"/> -
+
) } \ No newline at end of file diff --git a/src/app/format-bytes.js b/src/app/format-bytes.js index d902356..e5905a3 100644 --- a/src/app/format-bytes.js +++ b/src/app/format-bytes.js @@ -1,8 +1,8 @@ export default function formatBytes(bytes,decimals) { - if(bytes == 0) return '0 Byte'; - var k = 1000; // or 1024 for binary - var dm = decimals + 1 || 3; - var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; - var i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; + if(bytes == 0) return '0 Byte'; + var k = 1000; // or 1024 for binary + var dm = decimals + 1 || 3; + var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + var i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; } \ No newline at end of file diff --git a/src/app/header.js b/src/app/header.js index 72e0d51..d68b3ea 100644 --- a/src/app/header.js +++ b/src/app/header.js @@ -5,64 +5,64 @@ import RaisedButton from 'material-ui/RaisedButton'; import Search from './search' class Header extends React.Component { - constructor(props) - { - super(props) - this.header = React.createRef(); - } - componentDidMount() - { + constructor(props) + { + super(props) + this.header = React.createRef(); + } + componentDidMount() + { window.onscroll = () => { if (window.pageYOffset >= 15) { - const scrollHeight = Math.max( - document.body.scrollHeight, document.documentElement.scrollHeight, - document.body.offsetHeight, document.documentElement.offsetHeight, - document.body.clientHeight, document.documentElement.clientHeight - ); + const scrollHeight = Math.max( + document.body.scrollHeight, document.documentElement.scrollHeight, + document.body.offsetHeight, document.documentElement.offsetHeight, + document.body.clientHeight, document.documentElement.clientHeight + ); - if(scrollHeight - 240 < document.documentElement.clientHeight) - { - return - } + if(scrollHeight - 240 < document.documentElement.clientHeight) + { + return + } if(!this.stickyHeader) { - this.stickyHeader = true - this.header.current.classList.add("sticky"); + this.stickyHeader = true + this.header.current.classList.add("sticky"); } } else { if(this.stickyHeader) { - this.stickyHeader = false - this.header.current.classList.remove("sticky"); + this.stickyHeader = false + this.header.current.classList.remove("sticky"); } } }; - } - componentWillUnmount() - { - window.onscroll = null - } + } + componentWillUnmount() + { + window.onscroll = null + } - render() - { - return ( -
- - -
- { - window.router('/config') - }} - fill='white' style={{height: 45, margin: 4}} viewBox="0 0 932.179 932.179"> - - + + - - - - - { - window.router('/filters') - }} - fill='white' style={{height: 45, margin: 4}} viewBox="0 0 512 512"> - - - + + + - - - - - - - - - - - - - - - - - - - - - - - -
+ + + +
- {__('Welcome to')} ROTB! {__('This is file search engine based on the torrents from the internet')}. - {__('Here you can easily find torrent or file that you intrested for')}. {__('We are not responsible for any content')}: - {__('this is only information about content that collected automatically')}! - } />} - > -
- { - window.router('/') - }} - backgroundColor='#69238c' - labelColor='white' - style={{height: 60, borderRadius: 6, margin: 5, zIndex: 1}} - buttonStyle={{borderRadius: 5}} - icon={ - - - - - - - - + {__('Welcome to')} ROTB! {__('This is file search engine based on the torrents from the internet')}. + {__('Here you can easily find torrent or file that you intrested for')}. {__('We are not responsible for any content')}: + {__('this is only information about content that collected automatically')}! +
} />} + > +
+ { + window.router('/') + }} + backgroundColor='#69238c' + labelColor='white' + style={{height: 60, borderRadius: 6, margin: 5, zIndex: 1}} + buttonStyle={{borderRadius: 5}} + icon={ + + + + + + + + - } - /> - { - window.router('/downloads') - }} - backgroundColor='#2080E4' - labelColor='white' - style={{height: 60, borderRadius: 6, margin: 5, zIndex: 1}} - buttonStyle={{borderRadius: 5}} - icon={ - + - - } - /> - { - window.router('/top') - }} - backgroundColor='#B1CE57' - labelColor='white' - style={{height: 60, width: 120, borderRadius: 5, margin: 5, zIndex: 1}} - buttonStyle={{borderRadius: 5}} - icon={ - - + + - - - - } - /> - { - window.router('/activity') - }} - backgroundColor='#2a5cba' - labelColor='white' - style={{height: 60, width: 150, borderRadius: 5, margin: 5, zIndex: 1}} - buttonStyle={{borderRadius: 5}} - icon={ - - + + - - - - - } - /> -
- + + + } + /> +
+ +
-
- - -
-
- ) + + +
+
+ ) - } + } } export {Header} diff --git a/src/app/index.js b/src/app/index.js index 7eb2c6f..cf4f715 100644 --- a/src/app/index.js +++ b/src/app/index.js @@ -12,6 +12,6 @@ import './css/izi/animations.css'; import './index.css'; ReactDOM.render( - , - document.getElementById('mount-point') + , + document.getElementById('mount-point') ); diff --git a/src/app/input-files-filter.js b/src/app/input-files-filter.js index 4f65df1..08fcb71 100644 --- a/src/app/input-files-filter.js +++ b/src/app/input-files-filter.js @@ -8,65 +8,65 @@ import MenuItem from 'material-ui/MenuItem'; import Checkbox from 'material-ui/Checkbox'; export default class InputFilesFilter extends Component { - constructor(props) - { - super(props) - this.state = { - files: this.props.value || { min: 0, max: 50 }, - enabled: false || this.props.enabled, - filesMax: this.props.filesMax || 100 // 1mb - } - } - setState(val) - { - if(val.filesMax && this.state.files.max > val.filesMax) - val.files = {min: this.state.files.min, max: val.filesMax}; + constructor(props) + { + super(props) + this.state = { + files: this.props.value || { min: 0, max: 50 }, + enabled: false || this.props.enabled, + filesMax: this.props.filesMax || 100 // 1mb + } + } + setState(val) + { + if(val.filesMax && this.state.files.max > val.filesMax) + val.files = {min: this.state.files.min, max: val.filesMax}; - if(val.filesMax && this.state.files.min > val.filesMax) - val.files = {min: 0, max: val.files ? val.files.max || this.state.files.max : this.state.files.max }; + if(val.filesMax && this.state.files.min > val.filesMax) + val.files = {min: 0, max: val.files ? val.files.max || this.state.files.max : this.state.files.max }; - super.setState(val, () => { - if(this.props.onChange) - this.props.onChange({ - enabled: this.state.enabled, - filesMax: this.state.filesMax, - files: !this.state.enabled ? {min: 0, max: 0} : this.state.files - }) - }) - } - render() { - return ( -
- this.setState({enabled: !this.state.enabled})} - /> -
- this.setState({ files })} - /> - this.setState({filesMax: value})} - className='filter-control-border' - > - - - - - - - -
-
- ); - } + super.setState(val, () => { + if(this.props.onChange) + this.props.onChange({ + enabled: this.state.enabled, + filesMax: this.state.filesMax, + files: !this.state.enabled ? {min: 0, max: 0} : this.state.files + }) + }) + } + render() { + return ( +
+ this.setState({enabled: !this.state.enabled})} + /> +
+ this.setState({ files })} + /> + this.setState({filesMax: value})} + className='filter-control-border' + > + + + + + + + +
+
+ ); + } } diff --git a/src/app/input-size.js b/src/app/input-size.js index 6c478e3..8965111 100644 --- a/src/app/input-size.js +++ b/src/app/input-size.js @@ -8,67 +8,67 @@ import MenuItem from 'material-ui/MenuItem'; import Checkbox from 'material-ui/Checkbox'; export default class InputSize extends Component { - constructor(props) - { - super(props) - this.state = { - size: this.props.value || { min: 0, max: 500 * 1024 }, - enabled: false || this.props.enabled, - maxSize: this.props.maxSize || 1024 * 1024 // 1mb - } - } - setState(val) - { - if(val.maxSize && this.state.size.max > val.maxSize) - val.size = {min: this.state.size.min, max: val.maxSize}; + constructor(props) + { + super(props) + this.state = { + size: this.props.value || { min: 0, max: 500 * 1024 }, + enabled: false || this.props.enabled, + maxSize: this.props.maxSize || 1024 * 1024 // 1mb + } + } + setState(val) + { + if(val.maxSize && this.state.size.max > val.maxSize) + val.size = {min: this.state.size.min, max: val.maxSize}; - if(val.maxSize && this.state.size.min > val.maxSize) - val.size = {min: 0, max: val.size ? val.size.max || this.state.size.max : this.state.size.max }; + if(val.maxSize && this.state.size.min > val.maxSize) + val.size = {min: 0, max: val.size ? val.size.max || this.state.size.max : this.state.size.max }; - super.setState(val, () => { - if(this.props.onChange) - this.props.onChange({ - enabled: this.state.enabled, - maxSize: this.state.maxSize, - size: !this.state.enabled ? {min: 0, max: 0} : this.state.size - }) - }) - } - render() { - return ( -
- this.setState({enabled: !this.state.enabled})} - /> -
- formatBytes(size)} - style={this.props.style} - className={this.props.className} - onChange={size => this.setState({ size })} - /> - this.setState({maxSize: value})} - className='filter-control-border' - > - - - - - - - - -
-
- ); - } + super.setState(val, () => { + if(this.props.onChange) + this.props.onChange({ + enabled: this.state.enabled, + maxSize: this.state.maxSize, + size: !this.state.enabled ? {min: 0, max: 0} : this.state.size + }) + }) + } + render() { + return ( +
+ this.setState({enabled: !this.state.enabled})} + /> +
+ formatBytes(size)} + style={this.props.style} + className={this.props.className} + onChange={size => this.setState({ size })} + /> + this.setState({maxSize: value})} + className='filter-control-border' + > + + + + + + + + +
+
+ ); + } } diff --git a/src/app/pages-pie.js b/src/app/pages-pie.js index c3ed4f2..13ea30a 100644 --- a/src/app/pages-pie.js +++ b/src/app/pages-pie.js @@ -2,84 +2,84 @@ import React, { Component } from 'react'; import singleton from './singleton' class PagesPie extends Component { - pie = []; + pie = []; - open(pages, params) { - if (params && params.replace) { - if (params.replace === 'all') { - this.pie = []; - } else - if (params.replace === 'last') { - this.pie.pop(); - } - this.forceUpdate(); - delete params.replace; - } - setTimeout(() => { - if (Array.isArray(pages)) { - for (let i in pages) { - this.pie.push({ - Page: pages[i], - params: params - }); - } - } else { - this.pie.push({ - Page: pages, - params: params - }); - } - this.forceUpdate(); - }, 0); - } - close(count) { - if (count && typeof count === 'number') { - for (let i = 0; i < count; i++) { - this.pie.pop(); - } - } else { - this.pie.pop(); - } - this.forceUpdate(); - } - findOpened(windowType) { - for (let i in this.refs) { - if(this.refs[i] instanceof windowType) - return this.refs[i]; - } - } - // ОТРИСОВКА - render() { - if (this.pie.length > 0) { - return ( -
- { - this.pie.map(({Page, params}, index) => { - let focus = false; - if (index === this.pie.length-1) { - focus = true; - } - return ( - { index> 0 ? this.close() : null}} - index={index} - key={index} - ref={index} - {...params} - > - - ) - }) - } -
- ) - } else { - return null - } - } + open(pages, params) { + if (params && params.replace) { + if (params.replace === 'all') { + this.pie = []; + } else + if (params.replace === 'last') { + this.pie.pop(); + } + this.forceUpdate(); + delete params.replace; + } + setTimeout(() => { + if (Array.isArray(pages)) { + for (let i in pages) { + this.pie.push({ + Page: pages[i], + params: params + }); + } + } else { + this.pie.push({ + Page: pages, + params: params + }); + } + this.forceUpdate(); + }, 0); + } + close(count) { + if (count && typeof count === 'number') { + for (let i = 0; i < count; i++) { + this.pie.pop(); + } + } else { + this.pie.pop(); + } + this.forceUpdate(); + } + findOpened(windowType) { + for (let i in this.refs) { + if(this.refs[i] instanceof windowType) + return this.refs[i]; + } + } + // ОТРИСОВКА + render() { + if (this.pie.length > 0) { + return ( +
+ { + this.pie.map(({Page, params}, index) => { + let focus = false; + if (index === this.pie.length-1) { + focus = true; + } + return ( + { index> 0 ? this.close() : null}} + index={index} + key={index} + ref={index} + {...params} + > + + ) + }) + } +
+ ) + } else { + return null + } + } } export default singleton(PagesPie) \ No newline at end of file diff --git a/src/app/recent-torrents.js b/src/app/recent-torrents.js index 7c003a2..7999bd7 100644 --- a/src/app/recent-torrents.js +++ b/src/app/recent-torrents.js @@ -8,152 +8,152 @@ import FlatButton from 'material-ui/FlatButton'; import RefreshIndicator from 'material-ui/RefreshIndicator'; export default class RecentTorrents extends Component { - constructor() { - super() - this.torrents = []; - this.torrentsAssoc = {}; - this.displayQueue = []; - this.displayQueueAssoc = {}; - this.maxQueueSize = 1000; - this.maxDisplaySize = 10; - this.state = { - pause: false, - searchingIndicator: false - } - } - componentDidMount() { - window.torrentSocket.emit('recentTorrents', window.customLoader((data) => { - if(data) { - this.torrents = data; - //this.forceUpdate(); // вызывается через searchingIndicator - } + constructor() { + super() + this.torrents = []; + this.torrentsAssoc = {}; + this.displayQueue = []; + this.displayQueueAssoc = {}; + this.maxQueueSize = 1000; + this.maxDisplaySize = 10; + this.state = { + pause: false, + searchingIndicator: false + } + } + componentDidMount() { + window.torrentSocket.emit('recentTorrents', window.customLoader((data) => { + if(data) { + this.torrents = data; + //this.forceUpdate(); // вызывается через searchingIndicator + } - this.displayNewTorrent = () => { - if(!this.displayNewTorrent) { - return; - } + this.displayNewTorrent = () => { + if(!this.displayNewTorrent) { + return; + } - if(this.displayQueue.length == 0) { - setTimeout(this.displayNewTorrent, 1000); - return; - } + if(this.displayQueue.length == 0) { + setTimeout(this.displayNewTorrent, 1000); + return; + } - const speed = 850; + const speed = 850; - if(this.state.pause) { - setTimeout(this.displayNewTorrent, speed); - return; - } + if(this.state.pause) { + setTimeout(this.displayNewTorrent, speed); + return; + } - let torrent = this.displayQueue.shift(); - this.torrents.unshift(torrent); - this.torrentsAssoc[torrent.hash] = torrent; - if(this.torrents.length > this.maxDisplaySize) { - let toDelete = this.torrents.pop() - delete this.torrentsAssoc[toDelete.hash]; - delete this.displayQueueAssoc[toDelete.hash]; - } - this.displayTorrentCounterValue = this.displayQueue.length; + let torrent = this.displayQueue.shift(); + this.torrents.unshift(torrent); + this.torrentsAssoc[torrent.hash] = torrent; + if(this.torrents.length > this.maxDisplaySize) { + let toDelete = this.torrents.pop() + delete this.torrentsAssoc[toDelete.hash]; + delete this.displayQueueAssoc[toDelete.hash]; + } + this.displayTorrentCounterValue = this.displayQueue.length; - this.forceUpdate(); - setTimeout(this.displayNewTorrent, speed); - } - this.displayNewTorrent(); + this.forceUpdate(); + setTimeout(this.displayNewTorrent, speed); + } + this.displayNewTorrent(); - this.displayTorrentCounterValue = 0; - this.displayTorrentCounter = setInterval(() => { - if(this.displayTorrentCounterValue != this.displayQueue.length) { - this.displayTorrentCounterValue = this.displayQueue.length; - this.forceUpdate(); - } - }, 40); - }, () => { - this.setState({ - searchingIndicator: true - }); - }, () => { - this.setState({ - searchingIndicator: false - }); - })); - this.newTorrentFunc = (torrent) => { - if(this.displayQueue.length < this.maxQueueSize) { - this.displayQueue.push(torrent); - this.displayQueueAssoc[torrent.hash] = torrent; - } - }; - window.torrentSocket.on('newTorrent', this.newTorrentFunc); + this.displayTorrentCounterValue = 0; + this.displayTorrentCounter = setInterval(() => { + if(this.displayTorrentCounterValue != this.displayQueue.length) { + this.displayTorrentCounterValue = this.displayQueue.length; + this.forceUpdate(); + } + }, 40); + }, () => { + this.setState({ + searchingIndicator: true + }); + }, () => { + this.setState({ + searchingIndicator: false + }); + })); + this.newTorrentFunc = (torrent) => { + if(this.displayQueue.length < this.maxQueueSize) { + this.displayQueue.push(torrent); + this.displayQueueAssoc[torrent.hash] = torrent; + } + }; + window.torrentSocket.on('newTorrent', this.newTorrentFunc); - this.tracketUpdate = (statistic) => { - if(statistic.hash in this.displayQueueAssoc) - { - Object.assign(this.displayQueueAssoc[statistic.hash], statistic); - if(statistic.hash in this.torrentsAssoc) { - this.forceUpdate(); - } - } - } - window.torrentSocket.on('trackerTorrentUpdate', this.tracketUpdate); - } - pauseAndContinue() { - this.setState({ - pause: !this.state.pause - }); - } - componentWillUnmount() { - if(this.newTorrentFunc) - window.torrentSocket.off('newTorrent', this.newTorrentFunc); - if(this.tracketUpdate) - window.torrentSocket.off('trackerTorrentUpdate', this.tracketUpdate); - if(this.displayNewTorrent) - delete this.displayNewTorrent; - if(this.displayTorrentCounter) - clearInterval(this.displayTorrentCounter); - } - render() { - const style = { - refresh: { - display: 'inline-block', - position: 'relative', - }, - }; + this.tracketUpdate = (statistic) => { + if(statistic.hash in this.displayQueueAssoc) + { + Object.assign(this.displayQueueAssoc[statistic.hash], statistic); + if(statistic.hash in this.torrentsAssoc) { + this.forceUpdate(); + } + } + } + window.torrentSocket.on('trackerTorrentUpdate', this.tracketUpdate); + } + pauseAndContinue() { + this.setState({ + pause: !this.state.pause + }); + } + componentWillUnmount() { + if(this.newTorrentFunc) + window.torrentSocket.off('newTorrent', this.newTorrentFunc); + if(this.tracketUpdate) + window.torrentSocket.off('trackerTorrentUpdate', this.tracketUpdate); + if(this.displayNewTorrent) + delete this.displayNewTorrent; + if(this.displayTorrentCounter) + clearInterval(this.displayTorrentCounter); + } + render() { + const style = { + refresh: { + display: 'inline-block', + position: 'relative', + }, + }; - if(this.state.searchingIndicator) { - return ( -
- -
- ); - } + if(this.state.searchingIndicator) { + return ( +
+ +
+ ); + } - if(!this.torrents || this.torrents.length == 0) - return null; + if(!this.torrents || this.torrents.length == 0) + return null; - return ( - - - { - window.router('/top'); - }} /> - { - this.pauseAndContinue() - }} /> - {__('Most recent torrents')}{this.displayQueue.length > 0 ? ` (${__('and')} ${this.displayQueue.length} ${__('more')})` : null} - - - { - this.torrents.map((torrent, index) =>{ - return ; - }) - } - - ); - } + return ( + + + { + window.router('/top'); + }} /> + { + this.pauseAndContinue() + }} /> + {__('Most recent torrents')}{this.displayQueue.length > 0 ? ` (${__('and')} ${this.displayQueue.length} ${__('more')})` : null} + + + { + this.torrents.map((torrent, index) =>{ + return ; + }) + } + + ); + } } diff --git a/src/app/registerServiceWorker.js b/src/app/registerServiceWorker.js index a866079..01f2e66 100644 --- a/src/app/registerServiceWorker.js +++ b/src/app/registerServiceWorker.js @@ -9,105 +9,105 @@ // This link also includes instructions on opting out of this behavior. const isLocalhost = Boolean( - window.location.hostname === 'localhost' || + window.location.hostname === 'localhost' || // [::1] is the IPv6 localhost address. window.location.hostname === '[::1]' || // 127.0.0.1/8 is considered localhost for IPv4. window.location.hostname.match( - /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ ) ); export default function register() { - if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { - // The URL constructor is available in all browsers that support SW. - const publicUrl = new URL(process.env.PUBLIC_URL, window.location); - if (publicUrl.origin !== window.location.origin) { - // Our service worker won't work if PUBLIC_URL is on a different origin - // from what our page is served on. This might happen if a CDN is used to - // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374 - return; - } + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { + // The URL constructor is available in all browsers that support SW. + const publicUrl = new URL(process.env.PUBLIC_URL, window.location); + if (publicUrl.origin !== window.location.origin) { + // Our service worker won't work if PUBLIC_URL is on a different origin + // from what our page is served on. This might happen if a CDN is used to + // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374 + return; + } - window.addEventListener('load', () => { - const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; + window.addEventListener('load', () => { + const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; - if (!isLocalhost) { - // Is not local host. Just register service worker - registerValidSW(swUrl); - } else { - // This is running on localhost. Lets check if a service worker still exists or not. - checkValidServiceWorker(swUrl); - } - }); - } + if (!isLocalhost) { + // Is not local host. Just register service worker + registerValidSW(swUrl); + } else { + // This is running on localhost. Lets check if a service worker still exists or not. + checkValidServiceWorker(swUrl); + } + }); + } } function registerValidSW(swUrl) { - navigator.serviceWorker - .register(swUrl) - .then(registration => { - registration.onupdatefound = () => { - const installingWorker = registration.installing; - installingWorker.onstatechange = () => { - if (installingWorker.state === 'installed') { - if (navigator.serviceWorker.controller) { - // At this point, the old content will have been purged and - // the fresh content will have been added to the cache. - // It's the perfect time to display a "New content is - // available; please refresh." message in your web app. - console.log('New content is available; please refresh.'); - } else { - // At this point, everything has been precached. - // It's the perfect time to display a - // "Content is cached for offline use." message. - console.log('Content is cached for offline use.'); - } - } - }; - }; - }) - .catch(error => { - console.error('Error during service worker registration:', error); - }); + navigator.serviceWorker + .register(swUrl) + .then(registration => { + registration.onupdatefound = () => { + const installingWorker = registration.installing; + installingWorker.onstatechange = () => { + if (installingWorker.state === 'installed') { + if (navigator.serviceWorker.controller) { + // At this point, the old content will have been purged and + // the fresh content will have been added to the cache. + // It's the perfect time to display a "New content is + // available; please refresh." message in your web app. + console.log('New content is available; please refresh.'); + } else { + // At this point, everything has been precached. + // It's the perfect time to display a + // "Content is cached for offline use." message. + console.log('Content is cached for offline use.'); + } + } + }; + }; + }) + .catch(error => { + console.error('Error during service worker registration:', error); + }); } function checkValidServiceWorker(swUrl) { - // Check if the service worker can be found. If it can't reload the page. - fetch(swUrl) - .then(response => { - // Ensure service worker exists, and that we really are getting a JS file. - if ( - response.status === 404 || + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl) + .then(response => { + // Ensure service worker exists, and that we really are getting a JS file. + if ( + response.status === 404 || response.headers.get('content-type').indexOf('javascript') === -1 - ) { - // No service worker found. Probably a different app. Reload the page. - navigator.serviceWorker.ready.then(registration => { - registration.unregister().then(() => { - window.location.reload(); - }); - }); - } else { - // Service worker found. Proceed as normal. - registerValidSW(swUrl); - } - }) - .catch(() => { - console.log( - 'No internet connection found. App is running in offline mode.' - ); - }); + ) { + // No service worker found. Probably a different app. Reload the page. + navigator.serviceWorker.ready.then(registration => { + registration.unregister().then(() => { + window.location.reload(); + }); + }); + } else { + // Service worker found. Proceed as normal. + registerValidSW(swUrl); + } + }) + .catch(() => { + console.log( + 'No internet connection found. App is running in offline mode.' + ); + }); } export function unregister() { - if ('serviceWorker' in navigator) { - return navigator.serviceWorker.ready.then(registration => { - console.log("Unregister service worker"); - return registration.unregister(); - }); - } else { - return new Promise(function(resolve, reject) { - resolve(); - }) - } + if ('serviceWorker' in navigator) { + return navigator.serviceWorker.ready.then(registration => { + console.log("Unregister service worker"); + return registration.unregister(); + }); + } else { + return new Promise(function(resolve, reject) { + resolve(); + }) + } } diff --git a/src/app/router.js b/src/app/router.js index d780495..023e0c1 100644 --- a/src/app/router.js +++ b/src/app/router.js @@ -31,7 +31,7 @@ const router = (page, callback) => { params[pg.args[i]] = p[i] } console.log(params) - + pg.callback({ params }) diff --git a/src/app/search-advanced-controls.js b/src/app/search-advanced-controls.js index 74dbb54..0146ac7 100644 --- a/src/app/search-advanced-controls.js +++ b/src/app/search-advanced-controls.js @@ -5,52 +5,52 @@ import InputSize from './input-size'; import FilesFilterInput from './input-files-filter'; export default class AdvancedSearchControl extends Component { - constructor(props) - { - super(props) - this.state = { - type: undefined, - size: {min: 0, max: 0}, - maxSize: 1024 * 1024 * 1024, - sizeEnabled: false, - filesEnabled: false, - files: {min: 0, max: 0}, - filesMax: 100, - } - if(this.props.state) - this.state = Object.assign(this.state, this.props.state) - } - setState(val) - { - super.setState(val, (v) => { - if(this.props.onChange) - this.props.onChange(this.state) - }) - } - render() { - return ( -
- this.setState({type: value})} - > - - - - - - - - - -
- this.setState({size, maxSize, sizeEnabled: enabled})} /> -
-
- this.setState({files, filesMax, filesEnabled: enabled})} /> -
-
- ); - } + constructor(props) + { + super(props) + this.state = { + type: undefined, + size: {min: 0, max: 0}, + maxSize: 1024 * 1024 * 1024, + sizeEnabled: false, + filesEnabled: false, + files: {min: 0, max: 0}, + filesMax: 100, + } + if(this.props.state) + this.state = Object.assign(this.state, this.props.state) + } + setState(val) + { + super.setState(val, (v) => { + if(this.props.onChange) + this.props.onChange(this.state) + }) + } + render() { + return ( +
+ this.setState({type: value})} + > + + + + + + + + + +
+ this.setState({size, maxSize, sizeEnabled: enabled})} /> +
+
+ this.setState({files, filesMax, filesEnabled: enabled})} /> +
+
+ ); + } } diff --git a/src/app/search-results.js b/src/app/search-results.js index 5499880..3490fe8 100644 --- a/src/app/search-results.js +++ b/src/app/search-results.js @@ -7,130 +7,130 @@ import Divider from 'material-ui/Divider'; import LinearProgress from 'material-ui/LinearProgress'; export default class SearchResults extends Component { - render() { - return ( - - { - (this.props.torrentsSearchResults && this.props.torrentsSearchResults.length > 0) - || (this.props.filesSearchResults && this.props.filesSearchResults.length > 0) - ? -
- {__('Search results for')} {this.props.searchText} -
{this.props.resultSelector}
-
- : - null - } - { - this.props.torrentsSearchResults && this.props.torrentsSearchResults.length > 0 - ? - this.props.torrentsSearchResults.map((torrent, index) =>{ - return( - - ); - }) - : - null - } - { - this.props.moreTorrentsEnabled && !this.props.moreTorrentsIndicator - ? -
- {__('More Torrents')}} onClick={() => { - if(this.props.onMoreTorrents) - this.props.onMoreTorrents(); - }} /> - -
- : - null - } - { - this.props.moreTorrentsIndicator - ? -
- -
- : - null - } - { - this.props.filesSearchResults && this.props.filesSearchResults.length > 0 - ? - this.props.filesSearchResults.map((torrent, index) =>{ - return( - - ); - }) - : - null - } - { - this.props.moreFilesEnabled && !this.props.moreFilesIndicator - ? -
- { - if(this.props.onMoreFiles) - this.props.onMoreFiles(); - }} /> - -
- : - null - } - { - this.props.moreFilesIndicator - ? -
- -
- : - null - } - { - this.props.torrentsSearchResults && this.props.torrentsSearchResults.length == 0 - && this.props.filesSearchResults && this.props.filesSearchResults.length == 0 - && !this.props.currentSearching - ? -
- - - - - - -
{__('no torrents for')} {this.props.searchText} {__('were found')}
-
- : - null - } -
- ); - } + render() { + return ( + + { + (this.props.torrentsSearchResults && this.props.torrentsSearchResults.length > 0) + || (this.props.filesSearchResults && this.props.filesSearchResults.length > 0) + ? +
+ {__('Search results for')} {this.props.searchText} +
{this.props.resultSelector}
+
+ : + null + } + { + this.props.torrentsSearchResults && this.props.torrentsSearchResults.length > 0 + ? + this.props.torrentsSearchResults.map((torrent, index) =>{ + return( + + ); + }) + : + null + } + { + this.props.moreTorrentsEnabled && !this.props.moreTorrentsIndicator + ? +
+ {__('More Torrents')}} onClick={() => { + if(this.props.onMoreTorrents) + this.props.onMoreTorrents(); + }} /> + +
+ : + null + } + { + this.props.moreTorrentsIndicator + ? +
+ +
+ : + null + } + { + this.props.filesSearchResults && this.props.filesSearchResults.length > 0 + ? + this.props.filesSearchResults.map((torrent, index) =>{ + return( + + ); + }) + : + null + } + { + this.props.moreFilesEnabled && !this.props.moreFilesIndicator + ? +
+ { + if(this.props.onMoreFiles) + this.props.onMoreFiles(); + }} /> + +
+ : + null + } + { + this.props.moreFilesIndicator + ? +
+ +
+ : + null + } + { + this.props.torrentsSearchResults && this.props.torrentsSearchResults.length == 0 + && this.props.filesSearchResults && this.props.filesSearchResults.length == 0 + && !this.props.currentSearching + ? +
+ + + + + + +
{__('no torrents for')} {this.props.searchText} {__('were found')}
+
+ : + null + } +
+ ); + } } diff --git a/src/app/search.js b/src/app/search.js index 0bbd5e8..c672a6e 100644 --- a/src/app/search.js +++ b/src/app/search.js @@ -17,332 +17,332 @@ import _ from 'lodash' import singleton from './singleton'; class Search extends Component { - constructor(props) - { - super(props) - this.onSearchUpdate = () => {} + constructor(props) + { + super(props) + this.onSearchUpdate = () => {} - this.state = { - searchingIndicator: false, - safeSearchText: __('safe search enabled'), - safeSearchColor: 'rgb(0, 188, 212)', - moreTorrentsIndicator: false, - moreFilesIndicator: false, - orderBy: null, - orderDesc: false, - advancedSearch: false, - } - this.searchLimit = 10 - this.advanced = {} - this.searchError = undefined; - } + this.state = { + searchingIndicator: false, + safeSearchText: __('safe search enabled'), + safeSearchColor: 'rgb(0, 188, 212)', + moreTorrentsIndicator: false, + moreFilesIndicator: false, + orderBy: null, + orderDesc: false, + advancedSearch: false, + } + this.searchLimit = 10 + this.advanced = {} + this.searchError = undefined; + } - search(oldSearch) { - window.router('/') - this.setState({ - searchingIndicator: true - }); - this.onSearchUpdate('indicator') + search(oldSearch) { + window.router('/') + this.setState({ + searchingIndicator: true + }); + this.onSearchUpdate('indicator') - this.searchTorrents = []; - this.moreSearchTorrents = true; - this.searchFiles = []; - this.moreSearchFiles = true; - this.currentSearch = this.searchValue; - let queries = 2; - let searchTorrentsParams = { - limit: this.searchLimit, - safeSearch: !this.notSafeSearch, - orderBy: this.state.orderBy, - orderDesc: this.state.orderDesc, - }; - if(this.state.advancedSearch && this.advanced) - searchTorrentsParams = Object.assign(searchTorrentsParams, this.advanced); + this.searchTorrents = []; + this.moreSearchTorrents = true; + this.searchFiles = []; + this.moreSearchFiles = true; + this.currentSearch = this.searchValue; + let queries = 2; + let searchTorrentsParams = { + limit: this.searchLimit, + safeSearch: !this.notSafeSearch, + orderBy: this.state.orderBy, + orderDesc: this.state.orderDesc, + }; + if(this.state.advancedSearch && this.advanced) + searchTorrentsParams = Object.assign(searchTorrentsParams, this.advanced); - window.torrentSocket.emit('searchTorrent', oldSearch ? this.currentSearch : this.searchValue, searchTorrentsParams, window.customLoader((torrents) => { - if(torrents) { - this.searchTorrents = torrents; - if(torrents.length != this.searchLimit) - this.moreSearchTorrents = false; - } - else - { - this.moreSearchTorrents = false; - } - if(--queries == 0) { - this.setState({ - searchingIndicator: false - }); - } - this.onSearchUpdate('torrents') - })); - let searchFilesParams = { - limit: this.searchLimit, - safeSearch: !this.notSafeSearch, - orderBy: this.state.orderBy, - orderDesc: this.state.orderDesc, - }; - if(this.state.advancedSearch && this.advanced) - searchFilesParams = Object.assign(searchFilesParams, this.advanced); + window.torrentSocket.emit('searchTorrent', oldSearch ? this.currentSearch : this.searchValue, searchTorrentsParams, window.customLoader((torrents) => { + if(torrents) { + this.searchTorrents = torrents; + if(torrents.length != this.searchLimit) + this.moreSearchTorrents = false; + } + else + { + this.moreSearchTorrents = false; + } + if(--queries == 0) { + this.setState({ + searchingIndicator: false + }); + } + this.onSearchUpdate('torrents') + })); + let searchFilesParams = { + limit: this.searchLimit, + safeSearch: !this.notSafeSearch, + orderBy: this.state.orderBy, + orderDesc: this.state.orderDesc, + }; + if(this.state.advancedSearch && this.advanced) + searchFilesParams = Object.assign(searchFilesParams, this.advanced); - window.torrentSocket.emit('searchFiles', oldSearch ? this.currentSearch : this.searchValue, searchFilesParams, window.customLoader((torrents) => { - if(torrents) { - this.searchFiles = torrents; - let files = 0; - torrents.forEach((torrent) => { - if(torrent.path && torrent.path.length > 0) - files += torrent.path.length - }); - if(files != this.searchLimit) - this.moreSearchFiles = false; - } - else - { - this.moreSearchFiles = false; - } - if(--queries == 0) { - this.setState({ - searchingIndicator: false - }); - } - this.onSearchUpdate('files') - })); - } - moreTorrents() { - this.setState({moreTorrentsIndicator: true}); - this.onSearchUpdate('indicator') + window.torrentSocket.emit('searchFiles', oldSearch ? this.currentSearch : this.searchValue, searchFilesParams, window.customLoader((torrents) => { + if(torrents) { + this.searchFiles = torrents; + let files = 0; + torrents.forEach((torrent) => { + if(torrent.path && torrent.path.length > 0) + files += torrent.path.length + }); + if(files != this.searchLimit) + this.moreSearchFiles = false; + } + else + { + this.moreSearchFiles = false; + } + if(--queries == 0) { + this.setState({ + searchingIndicator: false + }); + } + this.onSearchUpdate('files') + })); + } + moreTorrents() { + this.setState({moreTorrentsIndicator: true}); + this.onSearchUpdate('indicator') - window.torrentSocket.emit('searchTorrent', this.currentSearch, { - index: this.searchTorrents.length, - limit: this.searchLimit, - safeSearch: !this.notSafeSearch, - orderBy: this.state.orderBy, - orderDesc: this.state.orderDesc, - }, window.customLoader((torrents) => { - if(torrents) { - this.searchTorrents = this.searchTorrents.concat(torrents); - if(torrents.length != this.searchLimit) - this.moreSearchTorrents = false; + window.torrentSocket.emit('searchTorrent', this.currentSearch, { + index: this.searchTorrents.length, + limit: this.searchLimit, + safeSearch: !this.notSafeSearch, + orderBy: this.state.orderBy, + orderDesc: this.state.orderDesc, + }, window.customLoader((torrents) => { + if(torrents) { + this.searchTorrents = this.searchTorrents.concat(torrents); + if(torrents.length != this.searchLimit) + this.moreSearchTorrents = false; - this.setState({moreTorrentsIndicator: false}); - this.onSearchUpdate('more torrents') - } - })); - } - calcTorrentsFiles(torrents) - { - let files = 0; - torrents.forEach((torrent) => { - if(torrent.path && torrent.path.length > 0) - files += torrent.path.length - }); - return files - } - moreFiles() { - let index = 0; - this.searchFiles.forEach((torrent) => { - if(torrent.path && torrent.path.length > 0) - index += torrent.path.length; - }); + this.setState({moreTorrentsIndicator: false}); + this.onSearchUpdate('more torrents') + } + })); + } + calcTorrentsFiles(torrents) + { + let files = 0; + torrents.forEach((torrent) => { + if(torrent.path && torrent.path.length > 0) + files += torrent.path.length + }); + return files + } + moreFiles() { + let index = 0; + this.searchFiles.forEach((torrent) => { + if(torrent.path && torrent.path.length > 0) + index += torrent.path.length; + }); - this.setState({moreFilesIndicator: true}); - this.onSearchUpdate('indicator') + this.setState({moreFilesIndicator: true}); + this.onSearchUpdate('indicator') - window.torrentSocket.emit('searchFiles', this.currentSearch, { - index: index, - limit: this.searchLimit, - safeSearch: !this.notSafeSearch, - orderBy: this.state.orderBy, - orderDesc: this.state.orderDesc, - }, window.customLoader((torrents) => { - if(torrents) { - this.searchFiles = this.searchFiles.concat(torrents); + window.torrentSocket.emit('searchFiles', this.currentSearch, { + index: index, + limit: this.searchLimit, + safeSearch: !this.notSafeSearch, + orderBy: this.state.orderBy, + orderDesc: this.state.orderDesc, + }, window.customLoader((torrents) => { + if(torrents) { + this.searchFiles = this.searchFiles.concat(torrents); - if(this.calcTorrentsFiles(torrents) != this.searchLimit) - this.moreSearchFiles = false; + if(this.calcTorrentsFiles(torrents) != this.searchLimit) + this.moreSearchFiles = false; - this.mergeFiles() + this.mergeFiles() - this.setState({moreFilesIndicator: false}); - this.onSearchUpdate('more files') - } - })); - } - mergeFiles() - { - for(let i = 0; i < this.searchFiles.length; i++) - { - for(let j = i + 1; j < this.searchFiles.length; j++) - { - if(this.searchFiles[i].hash != this.searchFiles[j].hash) - continue + this.setState({moreFilesIndicator: false}); + this.onSearchUpdate('more files') + } + })); + } + mergeFiles() + { + for(let i = 0; i < this.searchFiles.length; i++) + { + for(let j = i + 1; j < this.searchFiles.length; j++) + { + if(this.searchFiles[i].hash != this.searchFiles[j].hash) + continue - if(!this.searchFiles[i].remove) - { - this.searchFiles[i].path = this.searchFiles[i].path.concat(this.searchFiles[j].path) - } + if(!this.searchFiles[i].remove) + { + this.searchFiles[i].path = this.searchFiles[i].path.concat(this.searchFiles[j].path) + } - this.searchFiles[j].remove = true - } - } + this.searchFiles[j].remove = true + } + } - this.searchFiles = this.searchFiles.filter(torrent => !torrent.remove) - } + this.searchFiles = this.searchFiles.filter(torrent => !torrent.remove) + } - componentDidMount() { - this.newStatisticFunc = (statistic) => { - if(statistic) { - this.stats = statistic; - this.forceUpdate(); - } - }; - window.torrentSocket.emit('statistic', window.customLoader(this.newStatisticFunc)); - window.torrentSocket.on('newStatistic', this.newStatisticFunc); + componentDidMount() { + this.newStatisticFunc = (statistic) => { + if(statistic) { + this.stats = statistic; + this.forceUpdate(); + } + }; + window.torrentSocket.emit('statistic', window.customLoader(this.newStatisticFunc)); + window.torrentSocket.on('newStatistic', this.newStatisticFunc); - this.remoteSearchTorrent = (torrents) => { - if(!torrents) - return + this.remoteSearchTorrent = (torrents) => { + if(!torrents) + return - if(torrents.length === this.searchLimit) - this.moreSearchTorrents = true; + if(torrents.length === this.searchLimit) + this.moreSearchTorrents = true; - this.searchTorrents = _.unionBy(this.searchTorrents, torrents, 'hash') - this.onSearchUpdate('remote torrents') - } - window.torrentSocket.on('remoteSearchTorrent', this.remoteSearchTorrent); + this.searchTorrents = _.unionBy(this.searchTorrents, torrents, 'hash') + this.onSearchUpdate('remote torrents') + } + window.torrentSocket.on('remoteSearchTorrent', this.remoteSearchTorrent); - this.remoteSearchFiles = (torrents) => { - if(!torrents) - return + this.remoteSearchFiles = (torrents) => { + if(!torrents) + return - if(torrents.length > 0 && this.calcTorrentsFiles(torrents) === this.searchLimit) - this.moreSearchFiles = true; + if(torrents.length > 0 && this.calcTorrentsFiles(torrents) === this.searchLimit) + this.moreSearchFiles = true; - this.searchFiles = _.unionBy(this.searchFiles, torrents, 'hash') - this.mergeFiles() - this.onSearchUpdate('remote files') - } - window.torrentSocket.on('remoteSearchFiles', this.remoteSearchFiles); - } - componentWillUnmount() - { - if(this.newStatisticFunc) - window.torrentSocket.off('newStatistic', this.newStatisticFunc); + this.searchFiles = _.unionBy(this.searchFiles, torrents, 'hash') + this.mergeFiles() + this.onSearchUpdate('remote files') + } + window.torrentSocket.on('remoteSearchFiles', this.remoteSearchFiles); + } + componentWillUnmount() + { + if(this.newStatisticFunc) + window.torrentSocket.off('newStatistic', this.newStatisticFunc); - if(this.remoteSearchTorrent) - window.torrentSocket.off('remoteSearchTorrent', this.remoteSearchTorrent); + if(this.remoteSearchTorrent) + window.torrentSocket.off('remoteSearchTorrent', this.remoteSearchTorrent); - if(this.remoteSearchFiles) - window.torrentSocket.off('remoteSearchFiles', this.remoteSearchFiles); - } - setSafeSearch(ch) { - this.notSafeSearch = ch; - if(ch) - { - return {safeSearchText: __('safe search disabled'), safeSearchColor: '#EC407A'} - } - else - { - return {safeSearchText: __('safe search enabled'), safeSearchColor: 'rgb(0, 188, 212)'} - } - } - render() { - const style = { - refresh: { - display: 'inline-block', - position: 'relative', - }, - }; + if(this.remoteSearchFiles) + window.torrentSocket.off('remoteSearchFiles', this.remoteSearchFiles); + } + setSafeSearch(ch) { + this.notSafeSearch = ch; + if(ch) + { + return {safeSearchText: __('safe search disabled'), safeSearchColor: '#EC407A'} + } + else + { + return {safeSearchText: __('safe search enabled'), safeSearchColor: 'rgb(0, 188, 212)'} + } + } + render() { + const style = { + refresh: { + display: 'inline-block', + position: 'relative', + }, + }; - return ( -
-
- { - if (e.key === 'Enter') { - this.search(); - } - }} - onChange={e => { - this.searchValue = e.target.value - if(this.searchValue.length < 3 && this.searchValue.length > 0) - this.searchError = __('too short string for search'); - else - this.searchError = undefined; - this.forceUpdate() - }} - /> + return ( +
+
+ { + if (e.key === 'Enter') { + this.search(); + } + }} + onChange={e => { + this.searchValue = e.target.value + if(this.searchValue.length < 3 && this.searchValue.length > 0) + this.searchError = __('too short string for search'); + else + this.searchError = undefined; + this.forceUpdate() + }} + /> -
- } - uncheckedIcon={} - iconStyle={{fill: this.state.safeSearchColor}} - onCheck={(ev, ch) => { - this.setState(this.setSafeSearch(ch)); - }} - style={{paddingBottom: '0.8em'}} - /> -
-
- } - uncheckedIcon={} - iconStyle={{fill: 'black'}} - onCheck={(ev, ch) => { - this.setState({advancedSearch: ch}); - }} - style={{paddingBottom: '0.8em'}} - /> -
+
+ } + uncheckedIcon={} + iconStyle={{fill: this.state.safeSearchColor}} + onCheck={(ev, ch) => { + this.setState(this.setSafeSearch(ch)); + }} + style={{paddingBottom: '0.8em'}} + /> +
+
+ } + uncheckedIcon={} + iconStyle={{fill: 'black'}} + onCheck={(ev, ch) => { + this.setState({advancedSearch: ch}); + }} + style={{paddingBottom: '0.8em'}} + /> +
- { - this.search() - }} /> -
- { - this.state.advancedSearch + { + this.search() + }} /> +
+ { + this.state.advancedSearch && { - this.advanced = state; + this.advanced = state; }} state={this.advanced} /> - } - { - this.stats + } + { + this.stats && - } - { - this.state.searchingIndicator - ? -
- -
- : - null - } -
- ); - } + } + { + this.state.searchingIndicator + ? +
+ +
+ : + null + } +
+ ); + } } export default singleton(Search) \ No newline at end of file diff --git a/src/app/singleton.js b/src/app/singleton.js index a0ca4bf..dd6c4cc 100644 --- a/src/app/singleton.js +++ b/src/app/singleton.js @@ -1,6 +1,6 @@ export default (Superclass) => { let instance; - + return class Singleton extends Superclass { constructor(props) { super(props) @@ -14,12 +14,12 @@ export default (Superclass) => { if (instance) { return instance; } else { - return new Singleton(); + return new Singleton(); } } static do(key, ...params) { if ( typeof this.instance()[key] === 'function') { - return this.instance()[key](...params); + return this.instance()[key](...params); } else { return this.instance()[key]; } diff --git a/src/app/top-page.js b/src/app/top-page.js index 2f356fc..eb39af4 100644 --- a/src/app/top-page.js +++ b/src/app/top-page.js @@ -12,171 +12,171 @@ import {Tabs, Tab} from 'material-ui/Tabs'; import _ from 'lodash' export default class TopPage extends Page { - constructor(props) { - super(props) - this.setTitle('Rats On The Boat - Torrents top'); - this.topTorrents = {}; - this.types = ['main', 'video', 'audio', 'books', 'pictures', 'application', 'archive'] - this.descriptions = { - main: __('All'), - video: __('Video'), - audio: __('Audio/Music'), - books: __('Books'), - pictures: __('Pictures/Images'), - application: __('Apps/Games'), - archive: __('Archives') - } - this.times = { - overall: __('Overall'), - hours: __('Last hour'), - week: __('Last week'), - month: __('Last month') - } - this.state = {type: 'main', time: 'overall'} - } - loadMoreTorrents(type, time) - { - time = time ? time : this.state.time - window.torrentSocket.emit('topTorrents', - type == 'main' ? null : type, - {index: (this.topTorrents[type] && this.topTorrents[type][time] && this.topTorrents[type][time].length) || 0, time}, - window.customLoader((data) => { - if(!this.topTorrents[type]) - this.topTorrents[type] = {} - if(!this.topTorrents[type][time]) - this.topTorrents[type][time] = [] + constructor(props) { + super(props) + this.setTitle('Rats On The Boat - Torrents top'); + this.topTorrents = {}; + this.types = ['main', 'video', 'audio', 'books', 'pictures', 'application', 'archive'] + this.descriptions = { + main: __('All'), + video: __('Video'), + audio: __('Audio/Music'), + books: __('Books'), + pictures: __('Pictures/Images'), + application: __('Apps/Games'), + archive: __('Archives') + } + this.times = { + overall: __('Overall'), + hours: __('Last hour'), + week: __('Last week'), + month: __('Last month') + } + this.state = {type: 'main', time: 'overall'} + } + loadMoreTorrents(type, time) + { + time = time ? time : this.state.time + window.torrentSocket.emit('topTorrents', + type == 'main' ? null : type, + {index: (this.topTorrents[type] && this.topTorrents[type][time] && this.topTorrents[type][time].length) || 0, time}, + window.customLoader((data) => { + if(!this.topTorrents[type]) + this.topTorrents[type] = {} + if(!this.topTorrents[type][time]) + this.topTorrents[type][time] = [] - if(data && data.length > 0) - { - this.topTorrents[type][time] = this.topTorrents[type][time].concat(data); - this._update() - } - }) - ) - } - _update() - { - if(this.timeForce) - return - this.timeForce = setTimeout(() => { - delete this.timeForce - this.forceUpdate() - }, 550) - } - componentDidMount() - { - super.componentDidMount(); - for(const type of this.types) - { - this.loadMoreTorrents(type) - } - this.remoteTopTorrents = ({torrents, type, time}) => { - if(!torrents) - return + if(data && data.length > 0) + { + this.topTorrents[type][time] = this.topTorrents[type][time].concat(data); + this._update() + } + }) + ) + } + _update() + { + if(this.timeForce) + return + this.timeForce = setTimeout(() => { + delete this.timeForce + this.forceUpdate() + }, 550) + } + componentDidMount() + { + super.componentDidMount(); + for(const type of this.types) + { + this.loadMoreTorrents(type) + } + this.remoteTopTorrents = ({torrents, type, time}) => { + if(!torrents) + return - time = time ? time : 'overall' - type = type ? type : 'main' - this.topTorrents[type][time] = _.orderBy(_.unionBy(this.topTorrents[type][time], torrents, 'hash'), ['seeders'], ['desc']) - this._update(); - } - window.torrentSocket.on('remoteTopTorrents', this.remoteTopTorrents); - } - componentWillUnmount() - { - if(this.remoteTopTorrents) - window.torrentSocket.off('remoteTopTorrents', this.remoteTopTorrents); - } - render() { - return ( -
-
- { - Object.keys(this.topTorrents).length == 0 + time = time ? time : 'overall' + type = type ? type : 'main' + this.topTorrents[type][time] = _.orderBy(_.unionBy(this.topTorrents[type][time], torrents, 'hash'), ['seeders'], ['desc']) + this._update(); + } + window.torrentSocket.on('remoteTopTorrents', this.remoteTopTorrents); + } + componentWillUnmount() + { + if(this.remoteTopTorrents) + window.torrentSocket.off('remoteTopTorrents', this.remoteTopTorrents); + } + render() { + return ( +
+
+ { + Object.keys(this.topTorrents).length == 0 &&
- +
- } - { - this.setState({type}); - // lost other content - if(!this.topTorrents[type][this.state.time]) - { - this.loadMoreTorrents(type, this.state.time) - } - }} - tabItemContainerStyle={{flexWrap: 'wrap', alignItems: 'stretch'}} - inkBarStyle={{display: 'none'}} - > - { - this.types.map((type, index) => { - if(!this.topTorrents[type]) - return null; + } + { + this.setState({type}); + // lost other content + if(!this.topTorrents[type][this.state.time]) + { + this.loadMoreTorrents(type, this.state.time) + } + }} + tabItemContainerStyle={{flexWrap: 'wrap', alignItems: 'stretch'}} + inkBarStyle={{display: 'none'}} + > + { + this.types.map((type, index) => { + if(!this.topTorrents[type]) + return null; - return ( - - { - this.setState({time}) - // lost other content - if(!this.topTorrents[type][time]) - { - this.loadMoreTorrents(type, time) - } - }} - tabItemContainerStyle={{flexWrap: 'wrap', alignItems: 'stretch'}} - inkBarStyle={{display: 'none'}} - > - { - Object.keys(this.times).map((time, index) => { - const torrents = this.topTorrents[type][time]; + return ( + + { + this.setState({time}) + // lost other content + if(!this.topTorrents[type][time]) + { + this.loadMoreTorrents(type, time) + } + }} + tabItemContainerStyle={{flexWrap: 'wrap', alignItems: 'stretch'}} + inkBarStyle={{display: 'none'}} + > + { + Object.keys(this.times).map((time, index) => { + const torrents = this.topTorrents[type][time]; - if(!torrents) - return ( - -
- -
-
- ) + if(!torrents) + return ( + +
+ +
+
+ ) - return ( - - - { - torrents.map((torrent, index) => { - return - }) - } - { - torrents.length > 0 + return ( + + + { + torrents.map((torrent, index) => { + return + }) + } + { + torrents.length > 0 &&
- {__('More Torrents')}} onClick={() => { - this.loadMoreTorrents(type) - }} /> - + {__('More Torrents')}} onClick={() => { + this.loadMoreTorrents(type) + }} /> +
- } -
-
) - }) - } + } +
+
) + }) + } -
-
- ) +
+
+ ) - }) - } -
-
-
- ); - } + }) + } + +
+
+ ); + } } diff --git a/src/app/torrent-page.js b/src/app/torrent-page.js index bfaf995..e0fe538 100644 --- a/src/app/torrent-page.js +++ b/src/app/torrent-page.js @@ -53,34 +53,34 @@ const treeToTorrentFiles = (tree) => { arr.push( 1 ? : contentIcon(fileTypeDetect({path: file}))} - />); + secondaryText={formatBytes(tree[file].__sizeBT)} + nestedItems={treeToTorrentFiles(tree[file])} + primaryTogglesNestedList={true} + innerDivStyle={{wordBreak: 'break-word'}} + leftIcon={tree[file] && Object.keys(tree[file]).length > 1 ? : contentIcon(fileTypeDetect({path: file}))} + />); } return arr; } const TorrentFiles = (props) => { - let filesList = props.torrent.filesList; + let filesList = props.torrent.filesList; let tree = buildFilesTree(filesList); return ( - { - filesList.length > 0 - ? -
- {__('Content of the torrent')}: - {treeToTorrentFiles(tree)} -
- : -
- {__('Processing files')}... - -
- } + { + filesList.length > 0 + ? +
+ {__('Content of the torrent')}: + {treeToTorrentFiles(tree)} +
+ : +
+ {__('Processing files')}... + +
+ }
); }; @@ -89,84 +89,84 @@ const TorrentInformation = (props) => { let torrent = props.torrent; return ( - {__('Information about torrent')} - } backgroundColor={blue500} />} - rightIcon={} - primaryText={__('Torrent Name')} - secondaryText={{torrent.name}} - /> - } backgroundColor={yellow600} />} - rightIcon={} - primaryText={__('Torrent Size')} - secondaryText={formatBytes(torrent.size)} - /> - } backgroundColor={yellow600} />} - rightIcon={} - primaryText={__('Torrent contains files')} - secondaryText={torrent.files} - onClick={() => { - if(!props.parent) - return + {__('Information about torrent')} + } backgroundColor={blue500} />} + rightIcon={} + primaryText={__('Torrent Name')} + secondaryText={{torrent.name}} + /> + } backgroundColor={yellow600} />} + rightIcon={} + primaryText={__('Torrent Size')} + secondaryText={formatBytes(torrent.size)} + /> + } backgroundColor={yellow600} />} + rightIcon={} + primaryText={__('Torrent contains files')} + secondaryText={torrent.files} + onClick={() => { + if(!props.parent) + return - props.parent.setState({ - value: 'files' - }) - }} - /> - } backgroundColor={yellow600} />} - rightIcon={} - primaryText={__('Indexed/Added torrent date')} - secondaryText={moment(torrent.added * 1000).format('MMMM Do YYYY, hh:mm')} - /> - } backgroundColor={yellow600} />} - rightIcon={} - primaryText={__('Content type')} - secondaryText={torrent.contentType || 'unknown'} - /> - } backgroundColor={yellow600} />} - rightIcon={} - primaryText={__('Category')} - secondaryText={torrent.contentCategory || 'unknown'} - /> - + props.parent.setState({ + value: 'files' + }) + }} + /> + } backgroundColor={yellow600} />} + rightIcon={} + primaryText={__('Indexed/Added torrent date')} + secondaryText={moment(torrent.added * 1000).format('MMMM Do YYYY, hh:mm')} + /> + } backgroundColor={yellow600} />} + rightIcon={} + primaryText={__('Content type')} + secondaryText={torrent.contentType || 'unknown'} + /> + } backgroundColor={yellow600} />} + rightIcon={} + primaryText={__('Category')} + secondaryText={torrent.contentCategory || 'unknown'} + /> + ); } export default class TorrentPage extends Page { - constructor(props) { - super(props); - this.state = { - value: 'info', - searchingIndicator: false, - voting: false, - voted: false, - askDownloading: false, - downloading: false, - downloadProgress: {} - }; - this.setTitle('Information about torrent'); - } + constructor(props) { + super(props); + this.state = { + value: 'info', + searchingIndicator: false, + voting: false, + voted: false, + askDownloading: false, + downloading: false, + downloadProgress: {} + }; + this.setTitle('Information about torrent'); + } - changeTab(tab) { - if(this.state.value != tab) { - this.setState({ - value: tab - }); - console.log('change'); - } - } - onSwipeRight() { - this.changeTab('files'); - } - onSwipeLeft() { - this.changeTab('info'); - } + changeTab(tab) { + if(this.state.value != tab) { + this.setState({ + value: tab + }); + console.log('change'); + } + } + onSwipeRight() { + this.changeTab('files'); + } + onSwipeLeft() { + this.changeTab('info'); + } handleChange = (value) => { if(value == 'main') { @@ -174,18 +174,18 @@ export default class TorrentPage extends Page { return; } - this.setState({ - value: value, - }); + this.setState({ + value: value, + }); }; getTorrentInfo() { window.torrentSocket.emit('torrent', this.props.hash, {files: true, peer: this.props.peer}, window.customLoader((data) => { if(data) { this.torrent = data this.setTitle(this.torrent.name + ' - Rats On The Boat'); - if(this.torrent.contentCategory == 'xxx') { - this.setMetaTag('robots', 'noindex'); - } + if(this.torrent.contentCategory == 'xxx') { + this.setMetaTag('robots', 'noindex'); + } //this.forceUpdate(); // вызывается через searchingIndicator // Получаем более новую статистику пира @@ -194,195 +194,195 @@ export default class TorrentPage extends Page { } } }, () => { - this.setState({ - searchingIndicator: true - }); - }, () => { - this.setState({ - searchingIndicator: false - }); - })); + this.setState({ + searchingIndicator: true + }); + }, () => { + this.setState({ + searchingIndicator: false + }); + })); } componentDidMount() { super.componentDidMount(); this.filesUpdated = (hash) => { if(this.props.hash != hash) - return; + return; this.getTorrentInfo(); } window.torrentSocket.on('filesReady', this.filesUpdated); this.trackerUpdate = (info) => { - if(this.props.hash != info.hash) - return; + if(this.props.hash != info.hash) + return; - if(!this.torrent) - return; + if(!this.torrent) + return; - Object.assign(this.torrent, info); - this.forceUpdate(); - } - window.torrentSocket.on('trackerTorrentUpdate', this.trackerUpdate); + Object.assign(this.torrent, info); + this.forceUpdate(); + } + window.torrentSocket.on('trackerTorrentUpdate', this.trackerUpdate); - this.onVotes = async ({hash, good, bad, selfVote}) => { - if(this.props.hash != hash) - return; + this.onVotes = async ({hash, good, bad, selfVote}) => { + if(this.props.hash != hash) + return; - if(!this.torrent) - return + if(!this.torrent) + return - this.torrent.good = good; - this.torrent.bad = bad; - this.state.voted = selfVote; - this.forceUpdate(); - } - window.torrentSocket.on('votes', this.onVotes); + this.torrent.good = good; + this.torrent.bad = bad; + this.state.voted = selfVote; + this.forceUpdate(); + } + window.torrentSocket.on('votes', this.onVotes); - this.downloading = (hash) => { - if(this.props.hash != hash) - return; + this.downloading = (hash) => { + if(this.props.hash != hash) + return; - this.setState({downloading: true}) - } - window.torrentSocket.on('downloading', this.downloading); + this.setState({downloading: true}) + } + window.torrentSocket.on('downloading', this.downloading); - this.downloadDone = (hash, canceled) => { - if(this.props.hash != hash) - return; + this.downloadDone = (hash, canceled) => { + if(this.props.hash != hash) + return; - this.setState({ - downloading: false, - askDownloading: !canceled - }) - } - window.torrentSocket.on('downloadDone', this.downloadDone); + this.setState({ + downloading: false, + askDownloading: !canceled + }) + } + window.torrentSocket.on('downloadDone', this.downloadDone); - this.downloadProgress = (hash, progress) => { - if(this.props.hash != hash) - return; + this.downloadProgress = (hash, progress) => { + if(this.props.hash != hash) + return; - this.setState({downloadProgress: progress}) - } - window.torrentSocket.on('downloadProgress', this.downloadProgress); + this.setState({downloadProgress: progress}) + } + window.torrentSocket.on('downloadProgress', this.downloadProgress); - this.getTorrentInfo(); + this.getTorrentInfo(); } componentWillUnmount() { if(this.filesUpdated) - window.torrentSocket.off('filesReady', this.filesUpdated); + window.torrentSocket.off('filesReady', this.filesUpdated); if(this.trackerUpdate) - window.torrentSocket.off('trackerTorrentUpdate', this.trackerUpdate); - if(this.onVotes) - window.torrentSocket.off('votes', this.onVotes); - if(this.torrent && this.torrent.contentCategory == 'xxx') { - this.removeMetaTag('robots'); - } - if(this.downloading) - window.torrentSocket.off('downloading', this.downloading); - if(this.downloadDone) - window.torrentSocket.off('downloadDone', this.downloadDone); - if(this.downloadProgress) - window.torrentSocket.off('downloadProgress', this.downloadProgress); + window.torrentSocket.off('trackerTorrentUpdate', this.trackerUpdate); + if(this.onVotes) + window.torrentSocket.off('votes', this.onVotes); + if(this.torrent && this.torrent.contentCategory == 'xxx') { + this.removeMetaTag('robots'); + } + if(this.downloading) + window.torrentSocket.off('downloading', this.downloading); + if(this.downloadDone) + window.torrentSocket.off('downloadDone', this.downloadDone); + if(this.downloadProgress) + window.torrentSocket.off('downloadProgress', this.downloadProgress); } vote(good) { - if(!this.torrent) - return; + if(!this.torrent) + return; - this.setState({ - voting: true - }); - window.torrentSocket.emit('vote', this.torrent.hash, !!good, window.customLoader((success) => { - this.setState({ - voted: true, - voting: false - }); - })); + this.setState({ + voting: true + }); + window.torrentSocket.emit('vote', this.torrent.hash, !!good, window.customLoader((success) => { + this.setState({ + voted: true, + voting: false + }); + })); } render() { const style = { - refresh: { - display: 'inline-block', - position: 'relative', - }, - }; + refresh: { + display: 'inline-block', + position: 'relative', + }, + }; - if(this.state.searchingIndicator) { - return ( -
- -
- ); - } + if(this.state.searchingIndicator) { + return ( +
+ +
+ ); + } - let torrentRating; - if(this.torrent) { - torrentRating = Math.round(rating(this.torrent.good, this.torrent.bad) * 100); - } + let torrentRating; + if(this.torrent) { + torrentRating = Math.round(rating(this.torrent.good, this.torrent.bad) * 100); + } - return ( -
- { - this.torrent - ? - - - -
-
-
- -
-
- - { - e.preventDefault(); - window.open(`magnet:?xt=urn:btih:${this.torrent.hash}`, '_self') - }} - icon={} - /> - { - !this.state.askDownloading && !this.state.downloading + return ( +
+ { + this.torrent + ? + + + +
+
+
+ +
+
+ + { + e.preventDefault(); + window.open(`magnet:?xt=urn:btih:${this.torrent.hash}`, '_self') + }} + icon={} + /> + { + !this.state.askDownloading && !this.state.downloading && { - e.preventDefault(); - this.setState({askDownloading: true}) - window.torrentSocket.emit('download', this.torrent) - }} - icon={ - - - { + e.preventDefault(); + this.setState({askDownloading: true}) + window.torrentSocket.emit('download', this.torrent) + }} + icon={ + + + - - - - } + + + } /> - } - { - this.state.downloading + } + { + this.state.downloading &&
-
{__('downloading')} {this.state.downloadProgress && (this.state.downloadProgress.progress * 100).toFixed(1)}%
- - { - window.torrentSocket.emit('downloadCancel', this.torrent.hash) - }} - label={__('Cancel download')} - secondary={true} - icon={} - /> +
{__('downloading')} {this.state.downloadProgress && (this.state.downloadProgress.progress * 100).toFixed(1)}%
+ + { + window.torrentSocket.emit('downloadCancel', this.torrent.hash) + }} + label={__('Cancel download')} + secondary={true} + icon={} + />
- } -
BTIH:
{this.torrent.hash}
- { - this.torrent.seeders || this.torrent.leechers || this.torrent.completed - ? -
-
{__('seeders')}: {this.torrent.seeders}
-
{__('leechers')}: {this.torrent.leechers}
-
{__('completed')}: {this.torrent.completed}
-
- : - null - } - { - !this.state.voted && !this.state.voting - ? -
- - - + + - - - - } - onClick={() => this.vote(true)} - /> - - - + + + } + onClick={() => this.vote(true)} + /> + + + - - - } - onClick={() => this.vote(false)} - /> -
- : - this.state.voting - ? -
voting...
- : -
Thank you for voting!
- } - { - this.torrent.good > 0 || this.torrent.bad > 0 - ? -
- = 50 ? '#00E676' : '#FF3D00'} - style={{ - height: '5px', - }} - /> -
= 50 ? '#00E676' : '#FF3D00'}}>{__('Torrent rating')}: {torrentRating}%
-
- : - null - } -
-
-
-
- - - -
- : - null - } -
- ); + + + } + onClick={() => this.vote(false)} + /> +
+ : + this.state.voting + ? +
voting...
+ : +
Thank you for voting!
+ } + { + this.torrent.good > 0 || this.torrent.bad > 0 + ? +
+ = 50 ? '#00E676' : '#FF3D00'} + style={{ + height: '5px', + }} + /> +
= 50 ? '#00E676' : '#FF3D00'}}>{__('Torrent rating')}: {torrentRating}%
+
+ : + null + } +
+
+
+ + + + + + : + null + } + + ); } } diff --git a/src/app/torrent-statistic.js b/src/app/torrent-statistic.js index 0346d4c..f810666 100644 --- a/src/app/torrent-statistic.js +++ b/src/app/torrent-statistic.js @@ -2,37 +2,37 @@ import React, { Component } from 'react'; import formatBytes from './format-bytes' export default class TorrentsStatistic extends Component { - constructor(props) - { - super(props) + constructor(props) + { + super(props) - this.stats = props.stats || {} - } - componentDidMount() - { - this.newTorrentFunc = (torrent) => { - this.stats.size += torrent.size; - this.stats.torrents++; - this.stats.files += torrent.files; - this.forceUpdate() - } + this.stats = props.stats || {} + } + componentDidMount() + { + this.newTorrentFunc = (torrent) => { + this.stats.size += torrent.size; + this.stats.torrents++; + this.stats.files += torrent.files; + this.forceUpdate() + } - window.torrentSocket.on('newTorrent', this.newTorrentFunc); - } - componentWillUnmount() - { - if(this.newTorrentFunc) - window.torrentSocket.off('newTorrent', this.newTorrentFunc); - } - render() - { - return ( -
-
-
-
- - + - -
{ formatBytes(this.stats.size, 1) } {__('data')}
-
+ +
{ formatBytes(this.stats.size, 1) } {__('data')}
+
-
- - - + + - - - - - + + + + - - - - -
{this.stats.torrents} {__('torrents')}
-
+ + + +
{this.stats.torrents} {__('torrents')}
+
-
- - - - - - - - - - -
{this.stats.files} {__('files')}
-
-
+
+ + + + + + + + + + +
{this.stats.files} {__('files')}
+
+ -
-
0 ? '#19c632' : 'white', fontSize: '1.15em', fill: window.peers > 0 ? '#19c632' : 'white'}}> - - - + + - - - - - - - -
{window.peers} {__('peers')}
-
+ + + +
{window.peers} {__('peers')}
+
-
0 ? '#19c687' : 'white', fontSize: '1.15em', fill: window.peersTorrents > 0 ? '#19c687' : 'white', marginLeft: '20px'}}> - - - + + - - -
{window.peersTorrents} {__('remote torrents')}
-
+ + +
{window.peersTorrents} {__('remote torrents')}
+ -
- { - window.p2pStatus == 0 +
+ { + window.p2pStatus == 0 &&
- - - + + - - - - - -
{__('not available')}
+ + +
{__('not available')}
- } - { - window.p2pStatus == 1 + } + { + window.p2pStatus == 1 &&
- - - + + - - -
{__('redirect')}
+ + +
{__('redirect')}
- } - { - window.p2pStatus == 2 + } + { + window.p2pStatus == 2 &&
- - - + + - - -
{__('direct')}
+ + +
{__('direct')}
- } -
-
+ } + + - - - ) - } + + + ) + } } \ No newline at end of file diff --git a/src/app/torrent.js b/src/app/torrent.js index 9e55e5c..b229cea 100644 --- a/src/app/torrent.js +++ b/src/app/torrent.js @@ -11,12 +11,12 @@ import LinearProgress from 'material-ui/LinearProgress'; let rating = require('./rating'); const contentIcon = (type, category, fill = 'grey') => { - if(category == 'xxx') - { - return ( - - - + + - - - ) - } + + + ) + } - switch(type) - { - case 'video': - return ( - - + - - - + + - - ) - case 'audio': - return ( - - + - - + - ) - case 'pictures': - return ( - - + - - ) - case 'application': - return ( - - + - - ) - case 'books': - return ( - - - + + - - - - - - ) - case 'archive': - return ( - - - + + - { h-32.443c-2.399,0-4.345-1.944-4.345-4.345V279.28c0-2.4,1.946-4.346,4.345-4.346h32.443c2.399,0,4.345,1.945,4.345,4.346V289.708z M335.919,117.333H54.081V87.062c0-6.239,5.602-9.968,11.019-9.968h108.788c20.687,0,32.219-9.173,41.484-16.542 c8.552-6.803,14.732-11.717,29.204-11.717h75.278c8.858,0,16.066,7.206,16.066,16.064V117.333z"/> - - - ) - case 'disc': - return ( - - - - + + + - - - ) - default: - return ( - - - + + - - + - - - ) - } + + + ) + } }; export {contentIcon} export default class Torrent extends Component { state = { - downloading: false, - askDownloading: false, - downloadProgress: {} + downloading: false, + askDownloading: false, + downloadProgress: {} } constructor(props) { - super(props) - if(props.download) - { - const { progress, downloaded, speed } = props.download - this.state.downloadProgress = { - progress, downloaded, speed - } - } + super(props) + if(props.download) + { + const { progress, downloaded, speed } = props.download + this.state.downloadProgress = { + progress, downloaded, speed + } + } } componentDidMount() { - this.downloading = (hash) => { - if(this.props.torrent.hash != hash) - return; + this.downloading = (hash) => { + if(this.props.torrent.hash != hash) + return; - this.setState({downloading: true}) - } - window.torrentSocket.on('downloading', this.downloading); + this.setState({downloading: true}) + } + window.torrentSocket.on('downloading', this.downloading); - this.downloadDone = (hash, canceled) => { - if(this.props.torrent.hash != hash) - return; + this.downloadDone = (hash, canceled) => { + if(this.props.torrent.hash != hash) + return; - this.setState({ - downloading: false, - askDownloading: !canceled - }) - } - window.torrentSocket.on('downloadDone', this.downloadDone); + this.setState({ + downloading: false, + askDownloading: !canceled + }) + } + window.torrentSocket.on('downloadDone', this.downloadDone); - this.downloadProgress = (hash, progress) => { - if(this.props.torrent.hash != hash) - return; + this.downloadProgress = (hash, progress) => { + if(this.props.torrent.hash != hash) + return; - this.setState({ - downloading: true, - askDownloading: true, - downloadProgress: progress - }) - } - window.torrentSocket.on('downloadProgress', this.downloadProgress); + this.setState({ + downloading: true, + askDownloading: true, + downloadProgress: progress + }) + } + window.torrentSocket.on('downloadProgress', this.downloadProgress); } componentWillUnmount() { - if(this.downloading) - window.torrentSocket.off('downloading', this.downloading); - if(this.downloadDone) - window.torrentSocket.off('downloadDone', this.downloadDone); - if(this.downloadProgress) - window.torrentSocket.off('downloadProgress', this.downloadProgress); + if(this.downloading) + window.torrentSocket.off('downloading', this.downloading); + if(this.downloadDone) + window.torrentSocket.off('downloadDone', this.downloadDone); + if(this.downloadProgress) + window.torrentSocket.off('downloadProgress', this.downloadProgress); } render() { - const torrent = this.props.torrent; - let torrentRating = -1 - if(torrent.good > 0 || torrent.bad > 0) - torrentRating = Math.round(rating(torrent.good, torrent.bad) * 100); + const torrent = this.props.torrent; + let torrentRating = -1 + if(torrent.good > 0 || torrent.bad > 0) + torrentRating = Math.round(rating(torrent.good, torrent.bad) * 100); - return ( -
- { - const link = '/torrent/' + torrent.hash; - if(e.button === 1) - return false; + return ( +
+ { + const link = '/torrent/' + torrent.hash; + if(e.button === 1) + return false; - /* + /* if(e.ctrlKey && e.button === 0) { let win = window.open(link, '_blank'); //win.focus(); @@ -239,105 +239,105 @@ export default class Torrent extends Component { } */ - PagesPie.instance().open(TorrentPage, {replace: 'all', hash: torrent.hash, peer: torrent.peer}) - }} - primaryText={ - { - if(node) - node.onclick = () => { return false } - }}> - - {torrent.name} - - - } - secondaryText={ - { - if(node) - node.onclick = () => { return false } - }}> -
-
-
- { - formatBytes(torrent.size, 1) + ' (' + torrent.files + ' files)' - } -
- { - this.state.downloading + PagesPie.instance().open(TorrentPage, {replace: 'all', hash: torrent.hash, peer: torrent.peer}) + }} + primaryText={ +
{ + if(node) + node.onclick = () => { return false } + }}> + + {torrent.name} + + + } + secondaryText={ + { + if(node) + node.onclick = () => { return false } + }}> +
+
+
+ { + formatBytes(torrent.size, 1) + ' (' + torrent.files + ' files)' + } +
+ { + this.state.downloading && - } -
- { - torrent.path && torrent.path.length > 0 - ? - torrent.path.map((path, index) => { - return
{path}
- }) - : - null - } - { - torrent.seeders || torrent.leechers || torrent.completed - ? -
- 0 ? '#00C853' : 'grey')}}>{torrent.seeders} {__('seeders')} - 0 ? '#AA00FF' : 'grey'), marginLeft: '12px'}}>{torrent.leechers} {__('leechers')} - 0 ? '#FF6D00' : 'grey'), marginLeft: '12px'}}>{torrent.completed} {__('completed')} -
- : - null - } - { - (torrent.good > 0 || torrent.bad > 0) + style={{width: '44%', marginLeft: 20}} + mode="determinate" + value={this.state.downloadProgress && (this.state.downloadProgress.progress ? this.state.downloadProgress.progress : 0) * 100} + /> + } +
+ { + torrent.path && torrent.path.length > 0 + ? + torrent.path.map((path, index) => { + return
{path}
+ }) + : + null + } + { + torrent.seeders || torrent.leechers || torrent.completed + ? +
+ 0 ? '#00C853' : 'grey')}}>{torrent.seeders} {__('seeders')} + 0 ? '#AA00FF' : 'grey'), marginLeft: '12px'}}>{torrent.leechers} {__('leechers')} + 0 ? '#FF6D00' : 'grey'), marginLeft: '12px'}}>{torrent.completed} {__('completed')} +
+ : + null + } + { + (torrent.good > 0 || torrent.bad > 0) &&
- = 50 ? '#00E676' : '#FF3D00'} - style={{ - height: '5px', - }} - /> -
= 50 ? '#00E676' : '#FF3D00', width: '190px'}}>{__('Torrent rating')}: {torrentRating}%
-
- } -
- - } - leftIcon={contentIcon(torrent.contentType, torrent.contentCategory, torrent.contentCategory != 'xxx' ? (torrent.peer ? '#6f5ee0' : 'grey') : (torrent.peer ? '#9083e2' : '#d3d3d3'))} - rightIcon={ - + } +
+ + } + leftIcon={contentIcon(torrent.contentType, torrent.contentCategory, torrent.contentCategory != 'xxx' ? (torrent.peer ? '#6f5ee0' : 'grey') : (torrent.peer ? '#9083e2' : '#d3d3d3'))} + rightIcon={ +
+ { + !this.state.askDownloading && !this.state.downloading + ? + + { + e.preventDefault(); + e.stopPropagation(); + this.setState({askDownloading: true}) + window.torrentSocket.emit('download', torrent) + }} viewBox="0 0 56 56"> + + - - + - - - : - this.state.askDownloading && !this.state.downloading - ? - - : - this.state.askDownloading && this.state.downloading + + + : + this.state.askDownloading && !this.state.downloading + ? + + : + this.state.askDownloading && this.state.downloading && - { - e.preventDefault(); - e.stopPropagation(); + { + e.preventDefault(); + e.stopPropagation(); - window.torrentSocket.emit('downloadCancel', torrent.hash) - }} viewBox="0 0 18 18"> - - } - - { - e.preventDefault(); - e.stopPropagation(); - var win = window.open(`magnet:?xt=urn:btih:${torrent.hash}`, '_self'); - }} viewBox="0 0 24 24"> - + + } + + { + e.preventDefault(); + e.stopPropagation(); + var win = window.open(`magnet:?xt=urn:btih:${torrent.hash}`, '_self'); + }} viewBox="0 0 24 24"> + - -
- } - /> - -
- ) + +
+ } + /> + + + ) } } \ No newline at end of file diff --git a/src/app/touch.js b/src/app/touch.js index c64ed4c..19c0810 100644 --- a/src/app/touch.js +++ b/src/app/touch.js @@ -2,94 +2,94 @@ import ReactDOM from 'react-dom'; let listenSwipe = (component, handlers) => { - let element = ReactDOM.findDOMNode(component), - startX, - startY, - distanceX, - distanceY, - threshold = 110, - allowedTime = 280, - thresholdAlternativeAxis = 145, - elapsedTime, - startTime; + let element = ReactDOM.findDOMNode(component), + startX, + startY, + distanceX, + distanceY, + threshold = 110, + allowedTime = 280, + thresholdAlternativeAxis = 145, + elapsedTime, + startTime; - let touchFunctions = { - touchstart : (e) => { - let touchObject = e.changedTouches[0] + let touchFunctions = { + touchstart : (e) => { + let touchObject = e.changedTouches[0] - distanceX = 0; - distanceY = 0; + distanceX = 0; + distanceY = 0; - startX = touchObject.pageX - startY = touchObject.pageY + startX = touchObject.pageX + startY = touchObject.pageY - startTime = new Date().getTime() + startTime = new Date().getTime() - if(handlers && handlers.preventDefault) - e.preventDefault(); + if(handlers && handlers.preventDefault) + e.preventDefault(); - if(handlers && handlers.initSwipe) - handlers.initSwipe.call(component); - }, - touchmove : (e) => { - if(handlers && handlers.preventDefault) - e.preventDefault(); - }, - touchend : (e) => { - let touchObject = e.changedTouches[0]; + if(handlers && handlers.initSwipe) + handlers.initSwipe.call(component); + }, + touchmove : (e) => { + if(handlers && handlers.preventDefault) + e.preventDefault(); + }, + touchend : (e) => { + let touchObject = e.changedTouches[0]; - distanceX = touchObject.pageX - startX; - distanceY = touchObject.pageY - startY; + distanceX = touchObject.pageX - startX; + distanceY = touchObject.pageY - startY; - elapsedTime = new Date().getTime() - startTime; // get time elapsed + elapsedTime = new Date().getTime() - startTime; // get time elapsed - let params = { - startX, - startY, - endX: touchObject.pageX, - endY: touchObject.pageY, - distanceX, - distanceY - }; + let params = { + startX, + startY, + endX: touchObject.pageX, + endY: touchObject.pageY, + distanceX, + distanceY + }; - if (elapsedTime <= allowedTime) - { - if(distanceX >= threshold && Math.abs(distanceY) <= thresholdAlternativeAxis) - { - if(handlers && handlers.left) - handlers.left.call(component, params); - } else - if(-distanceX >= threshold && Math.abs(distanceY) <= thresholdAlternativeAxis) { - if(handlers && handlers.right) - handlers.right.call(component, params); - } else - if(distanceY >= threshold && Math.abs(distanceX) <= thresholdAlternativeAxis) { - if(handlers && handlers.top) - handlers.top.call(component, params); - } else - if(-distanceY >= threshold && Math.abs(distanceX) <= thresholdAlternativeAxis) { - if(handlers && handlers.bottom) - handlers.bottom.call(component, params); - } - } + if (elapsedTime <= allowedTime) + { + if(distanceX >= threshold && Math.abs(distanceY) <= thresholdAlternativeAxis) + { + if(handlers && handlers.left) + handlers.left.call(component, params); + } else + if(-distanceX >= threshold && Math.abs(distanceY) <= thresholdAlternativeAxis) { + if(handlers && handlers.right) + handlers.right.call(component, params); + } else + if(distanceY >= threshold && Math.abs(distanceX) <= thresholdAlternativeAxis) { + if(handlers && handlers.top) + handlers.top.call(component, params); + } else + if(-distanceY >= threshold && Math.abs(distanceX) <= thresholdAlternativeAxis) { + if(handlers && handlers.bottom) + handlers.bottom.call(component, params); + } + } - if(handlers && handlers.preventDefault) - e.preventDefault(); - } - }; + if(handlers && handlers.preventDefault) + e.preventDefault(); + } + }; - element.addEventListener('touchstart', touchFunctions.touchstart, false); - element.addEventListener('touchmove', touchFunctions.touchmove, false); - element.addEventListener('touchend', touchFunctions.touchend, false); + element.addEventListener('touchstart', touchFunctions.touchstart, false); + element.addEventListener('touchmove', touchFunctions.touchmove, false); + element.addEventListener('touchend', touchFunctions.touchend, false); - return touchFunctions; + return touchFunctions; } let removeSwipeListener = (component, touchFunctions) => { - let element = ReactDOM.findDOMNode(component); - element.removeEventListener('touchstart', touchFunctions.touchstart); - element.removeEventListener('touchmove', touchFunctions.touchmove); - element.removeEventListener('touchend', touchFunctions.touchend); + let element = ReactDOM.findDOMNode(component); + element.removeEventListener('touchstart', touchFunctions.touchstart); + element.removeEventListener('touchmove', touchFunctions.touchmove); + element.removeEventListener('touchend', touchFunctions.touchend); } export { listenSwipe, removeSwipeListener } \ No newline at end of file diff --git a/src/background/api.js b/src/background/api.js index df0ac3c..934ac04 100644 --- a/src/background/api.js +++ b/src/background/api.js @@ -35,17 +35,17 @@ module.exports = async ({ return; sphinx.query('SELECT * FROM `torrents` ORDER BY added DESC LIMIT 0,10', function (error, rows, fields) { - if(!rows) { - callback(undefined) - return; - } + if(!rows) { + callback(undefined) + return; + } - let torrents = []; - rows.forEach((row) => { - torrents.push(baseRowData(row)); - }); + let torrents = []; + rows.forEach((row) => { + torrents.push(baseRowData(row)); + }); - callback(torrents) + callback(torrents) }); }); @@ -55,25 +55,25 @@ module.exports = async ({ return; sphinx.query('SELECT count(*) AS torrents, sum(size) AS sz FROM `torrents`', function (error, rows, fields) { - if(!rows) { - console.error(error) - callback(undefined) - return; - } - - let result = {torrents: rows[0].torrents || 0, size: rows[0].sz || 0} - - sphinx.query('SELECT count(*) AS files FROM `files`', function (error, rows, fields) { - if(!rows) { - console.error(error) - callback(undefined) - return; + if(!rows) { + console.error(error) + callback(undefined) + return; } - result.files = rows[0].files || 0 + let result = {torrents: rows[0].torrents || 0, size: rows[0].sz || 0} - callback(result) - }) + sphinx.query('SELECT count(*) AS files FROM `files`', function (error, rows, fields) { + if(!rows) { + console.error(error) + callback(undefined) + return; + } + + result.files = rows[0].files || 0 + + callback(result) + }) }); }); @@ -112,43 +112,43 @@ module.exports = async ({ } sphinx.query('SELECT * FROM `torrents` WHERE `hash` = ?', hash, async function (error, rows, fields) { - if(!rows || rows.length == 0) { - callback(undefined) - return; - } - let torrent = rows[0]; - - if(options.files) - { - torrent.filesList = await sphinx.query('SELECT * FROM `files` WHERE `hash` = ? LIMIT 50000', hash); - callback(baseRowData(torrent)) - } - else - { - callback(baseRowData(torrent)) - } - - if(torrentClientHashMap[hash]) - { - const torrent = torrentClient.get(torrentClientHashMap[hash]) - if(torrent) - { - send('downloading', torrent.infoHash) + if(!rows || rows.length == 0) { + callback(undefined) + return; } - } + let torrent = rows[0]; - // get votes - const {good, bad, selfVote} = await getVotes(hash) - send('votes', { - hash, good, bad, selfVote - }); - if(torrent.good != good || torrent.bad != bad) - { - console.log('finded new rating on', torrent.name, 'update votes to it') - torrent.good = good - torrent.bad = bad - updateTorrentToDB(torrent) - } + if(options.files) + { + torrent.filesList = await sphinx.query('SELECT * FROM `files` WHERE `hash` = ? LIMIT 50000', hash); + callback(baseRowData(torrent)) + } + else + { + callback(baseRowData(torrent)) + } + + if(torrentClientHashMap[hash]) + { + const torrent = torrentClient.get(torrentClientHashMap[hash]) + if(torrent) + { + send('downloading', torrent.infoHash) + } + } + + // get votes + const {good, bad, selfVote} = await getVotes(hash) + send('votes', { + hash, good, bad, selfVote + }); + if(torrent.good != good || torrent.bad != bad) + { + console.log('finded new rating on', torrent.name, 'update votes to it') + torrent.good = good + torrent.bad = bad + updateTorrentToDB(torrent) + } }); } @@ -167,27 +167,27 @@ module.exports = async ({ 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 = [] @@ -277,13 +277,13 @@ module.exports = async ({ sphinx.query('SELECT * FROM `torrents` WHERE MATCH(?) ' + where + ' ' + order + ' LIMIT ?,?', args, function (error, rows, fields) { if(!rows) { console.log(error) - callback(undefined) - return; + callback(undefined) + return; } rows.forEach((row) => { searchList.push(baseRowData(row)); - }); - callback(searchList); + }); + callback(searchList); }); } @@ -328,37 +328,37 @@ module.exports = async ({ let where = ''; /* - if(orderBy && orderBy.length > 0) - { - const orderDesc = navigation.orderDesc ? 'DESC' : 'ASC'; - args.splice(1, 0, orderBy); - order = 'ORDER BY ?? ' + orderDesc; - } - */ + if(orderBy && orderBy.length > 0) + { + const orderDesc = navigation.orderDesc ? 'DESC' : 'ASC'; + args.splice(1, 0, orderBy); + order = 'ORDER BY ?? ' + orderDesc; + } + */ /* - if(safeSearch) - { - where += " and contentCategory != 'xxx' "; - } - if(navigation.type && navigation.type.length > 0) - { - where += ' and contentType = ' + sphinx.escape(navigation.type) + ' '; - } - if(navigation.size) - { - if(navigation.size.max > 0) - where += ' and torrentSize < ' + sphinx.escape(navigation.size.max) + ' '; - if(navigation.size.min > 0) - where += ' and torrentSize > ' + sphinx.escape(navigation.size.min) + ' '; - } - if(navigation.files) - { - if(navigation.files.max > 0) - where += ' and files < ' + sphinx.escape(navigation.files.max) + ' '; - if(navigation.files.min > 0) - where += ' and files > ' + sphinx.escape(navigation.files.min) + ' '; - } - */ + if(safeSearch) + { + where += " and contentCategory != 'xxx' "; + } + if(navigation.type && navigation.type.length > 0) + { + where += ' and contentType = ' + sphinx.escape(navigation.type) + ' '; + } + if(navigation.size) + { + if(navigation.size.max > 0) + where += ' and torrentSize < ' + sphinx.escape(navigation.size.max) + ' '; + if(navigation.size.min > 0) + where += ' and torrentSize > ' + sphinx.escape(navigation.size.min) + ' '; + } + if(navigation.files) + { + if(navigation.files.max > 0) + where += ' and files < ' + sphinx.escape(navigation.files.max) + ' '; + if(navigation.files.min > 0) + where += ' and files > ' + sphinx.escape(navigation.files.min) + ' '; + } + */ let search = {}; //args.splice(orderBy && orderBy.length > 0 ? 1 : 0, 1); @@ -366,8 +366,8 @@ module.exports = async ({ sphinx.query('SELECT * FROM `files` WHERE MATCH(?) ' + where + ' ' + order + ' LIMIT ?,?', args, function (error, files, fields) { if(!files) { console.log(error) - callback(undefined) - return; + callback(undefined) + return; } if(files.length === 0) { @@ -392,7 +392,7 @@ module.exports = async ({ for(const torrent of torrents) { search[torrent.hash] = Object.assign(baseRowData(torrent), search[torrent.hash]) - + // temporary ignore adult content in search (workaroud) if(safeSearch && search[torrent.hash].contentCategory == 'xxx') delete search[torrent.hash] @@ -466,7 +466,7 @@ module.exports = async ({ where += ' and `added` > ' + (Math.floor(Date.now() / 1000) - (60 * 60 * 24 * 30)) } } - + const query = `SELECT * FROM torrents WHERE seeders > 0 and contentCategory != 'xxx' ${where} ORDER BY seeders DESC LIMIT ${index},${limit}`; if(topCache[query]) { @@ -478,10 +478,10 @@ module.exports = async ({ callback(undefined) return; } - + rows = rows.map((row) => baseRowData(row)); topCache[query] = rows; - callback(rows); + callback(rows); }); } @@ -571,7 +571,7 @@ module.exports = async ({ { spider.announceHashes = [] } - + if(typeof callback === 'function') callback(true) }); @@ -739,9 +739,9 @@ module.exports = async ({ if(!temp || !temp.torrent) return - + const { torrent } = temp - + if(torrent.hash !== record.torrentHash) return @@ -760,7 +760,7 @@ module.exports = async ({ // update feed if(record.vote !== 'good') return - + feed.add(torrent) send('feedUpdate', { feed: feed.feed @@ -787,10 +787,10 @@ module.exports = async ({ p2p.emit('feed', null, (remoteFeed) => { if(!remoteFeed) return - + if(remoteFeed.length <= feed.size()) return - + console.log('replace our feed with remote feed') feed.feed = remoteFeed send('feedUpdate', { @@ -799,5 +799,5 @@ module.exports = async ({ }); }, 1000) }) - + } \ No newline at end of file diff --git a/src/background/background.js b/src/background/background.js index 484e60f..c9faeea 100644 --- a/src/background/background.js +++ b/src/background/background.js @@ -28,17 +28,17 @@ require('electron-context-menu')({}) // Thanks to this you can use production and development versions of the app // on same machine like those are two separate apps. if (env.name !== "production") { - const userDataPath = app.getPath("userData"); - app.setPath("userData", `${userDataPath} (${env.name})`); + const userDataPath = app.getPath("userData"); + app.setPath("userData", `${userDataPath} (${env.name})`); } // portative version let portative = false if(env.name === "production") { - if(fs.existsSync(path.dirname(process.execPath) + `/data`)) - { - portative = true; - app.setPath("userData", path.dirname(process.execPath) + `/data`); - } + if(fs.existsSync(path.dirname(process.execPath) + `/data`)) + { + portative = true; + app.setPath("userData", path.dirname(process.execPath) + `/data`); + } } const resourcesPath = env.name === "production" ? process.resourcesPath : 'resources' @@ -54,33 +54,33 @@ let sphinx = undefined let spider = undefined const setApplicationMenu = () => { - const settingsMenuTemplate = settingsMenuTemplateFunc(appConfig, (lang) => { - // update menu translation - changeLanguage(lang, () => setApplicationMenu()) - }) - const menus = [editMenuTemplateFunc(), manageMenuTemplateFunc(), settingsMenuTemplate, aboutMenuTemplateFunc()]; + const settingsMenuTemplate = settingsMenuTemplateFunc(appConfig, (lang) => { + // update menu translation + changeLanguage(lang, () => setApplicationMenu()) + }) + const menus = [editMenuTemplateFunc(), manageMenuTemplateFunc(), settingsMenuTemplate, aboutMenuTemplateFunc()]; - if (env.name !== "production") { - menus.push(devMenuTemplate); - } - // append version as disabled menu item - menus.push({ - label: app.getVersion() - }) - Menu.setApplicationMenu(Menu.buildFromTemplate(menus)); + if (env.name !== "production") { + menus.push(devMenuTemplate); + } + // append version as disabled menu item + menus.push({ + label: app.getVersion() + }) + Menu.setApplicationMenu(Menu.buildFromTemplate(menus)); }; const util = require('util'); if (!fs.existsSync(app.getPath("userData"))){ - fs.mkdirSync(app.getPath("userData")); + fs.mkdirSync(app.getPath("userData")); } const logFile = fs.createWriteStream(app.getPath("userData") + '/rats.log', {flags : 'w'}); const logStdout = process.stdout; console.log = (...d) => { - const date = (new Date).toLocaleTimeString() - logFile.write(`[${date}] ` + util.format(...d) + '\n'); - logStdout.write(util.format(...d) + '\n'); + const date = (new Date).toLocaleTimeString() + logFile.write(`[${date}] ` + util.format(...d) + '\n'); + logStdout.write(util.format(...d) + '\n'); }; // print os info @@ -94,21 +94,21 @@ console.log('Total memory:', (os.totalmem() / (1024 * 1024)).toFixed(2), 'MB') console.log('Free memory:', (os.freemem() / (1024 * 1024)).toFixed(2), 'MB') if(portative) -console.log('portative compability') + console.log('portative compability') const shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) { - // Someone tried to run a second instance, we should focus our window. - console.log('openned second application, just focus this one') - if (mainWindow) { - if (mainWindow.isMinimized()) - mainWindow.restore(); - mainWindow.focus(); - } + // Someone tried to run a second instance, we should focus our window. + console.log('openned second application, just focus this one') + if (mainWindow) { + if (mainWindow.isMinimized()) + mainWindow.restore(); + mainWindow.focus(); + } }); if (shouldQuit) { - console.log('closed because of second application') - app.exit(0); + console.log('closed because of second application') + app.exit(0); } // log autoupdate @@ -116,162 +116,162 @@ const log = require('electron-log') log.transports.file.level = false; log.transports.console.level = false; log.transports.console = function(msg) { - const text = util.format.apply(util, msg.data); - console.log(text); + const text = util.format.apply(util, msg.data); + console.log(text); }; autoUpdater.logger = log; autoUpdater.on('update-downloaded', () => { - console.log('update-downloaded lats quitAndInstall'); - if (env.name === "production") { - dialog.showMessageBox({ - type: 'info', - title: 'Found Updates', - message: 'Found updates, do you want update now?', - buttons: ['Sure', 'No'] - }, (buttonIndex) => { - if (buttonIndex === 0) { - const isSilent = true; - const isForceRunAfter = true; - autoUpdater.quitAndInstall(isSilent, isForceRunAfter); - } - }) - } + console.log('update-downloaded lats quitAndInstall'); + if (env.name === "production") { + dialog.showMessageBox({ + type: 'info', + title: 'Found Updates', + message: 'Found updates, do you want update now?', + buttons: ['Sure', 'No'] + }, (buttonIndex) => { + if (buttonIndex === 0) { + const isSilent = true; + const isForceRunAfter = true; + autoUpdater.quitAndInstall(isSilent, isForceRunAfter); + } + }) + } }) let tray = undefined app.on("ready", () => { - sphinx = startSphinx(() => { + sphinx = startSphinx(() => { - mainWindow = createWindow("main", { - width: 1000, - height: 600 - }); + mainWindow = createWindow("main", { + width: 1000, + height: 600 + }); - dbPatcher(() => { - changeLanguage(appConfig.language, () => setApplicationMenu()) + dbPatcher(() => { + changeLanguage(appConfig.language, () => setApplicationMenu()) - mainWindow.loadURL( - url.format({ - pathname: path.join(__dirname, "app.html"), - protocol: "file:", - slashes: true - }) - ); + mainWindow.loadURL( + url.format({ + pathname: path.join(__dirname, "app.html"), + protocol: "file:", + slashes: true + }) + ); - if (env.name === "development") { - mainWindow.openDevTools(); - } + if (env.name === "development") { + mainWindow.openDevTools(); + } - if(process.platform === 'darwin') - tray = new Tray(`${resourcesPath}/icons/19x19.png`) - else - tray = new Tray(`${resourcesPath}/icons/512x512.png`) + if(process.platform === 'darwin') + tray = new Tray(`${resourcesPath}/icons/19x19.png`) + else + tray = new Tray(`${resourcesPath}/icons/512x512.png`) - tray.on('click', () => { - mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show() - }) - mainWindow.on('show', () => { - tray.setHighlightMode('always') - }) - mainWindow.on('hide', () => { - tray.setHighlightMode('never') - }) + tray.on('click', () => { + mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show() + }) + mainWindow.on('show', () => { + tray.setHighlightMode('always') + }) + mainWindow.on('hide', () => { + tray.setHighlightMode('never') + }) - mainWindow.on('close', (event) => { - if (!app.isQuiting && appConfig.trayOnClose && process.platform !== 'linux') { - event.preventDefault() - mainWindow.hide() - return - } - }) - mainWindow.on('closed', () => { - mainWindow = undefined - }) + mainWindow.on('close', (event) => { + if (!app.isQuiting && appConfig.trayOnClose && process.platform !== 'linux') { + event.preventDefault() + mainWindow.hide() + return + } + }) + mainWindow.on('closed', () => { + mainWindow = undefined + }) - mainWindow.on('minimize', (event) => { - if(appConfig.trayOnMinimize) - { - event.preventDefault(); - mainWindow.hide(); - } - }); + mainWindow.on('minimize', (event) => { + if(appConfig.trayOnMinimize) + { + event.preventDefault(); + mainWindow.hide(); + } + }); - var contextMenu = Menu.buildFromTemplate([ - { label: 'Show', click: function(){ - mainWindow.show(); - } }, - { label: 'Quit', click: function(){ - app.isQuiting = true; - if (sphinx) - stop() - else - app.quit() - } } - ]); + var contextMenu = Menu.buildFromTemplate([ + { label: 'Show', click: function(){ + mainWindow.show(); + } }, + { label: 'Quit', click: function(){ + app.isQuiting = true; + if (sphinx) + stop() + else + app.quit() + } } + ]); - tray.setContextMenu(contextMenu) - tray.setToolTip('Rats on The Boat search') + tray.setContextMenu(contextMenu) + tray.setToolTip('Rats on The Boat search') - mainWindow.webContents.on('will-navigate', e => { e.preventDefault() }) - mainWindow.webContents.on('new-window', (event, url, frameName) => { - if(frameName == '_self') - { - event.preventDefault() - mainWindow.loadURL(url) - } - }) + mainWindow.webContents.on('will-navigate', e => { e.preventDefault() }) + mainWindow.webContents.on('new-window', (event, url, frameName) => { + if(frameName == '_self') + { + event.preventDefault() + mainWindow.loadURL(url) + } + }) - if (env.name === "production" && !portative) { autoUpdater.checkForUpdates() } + if (env.name === "production" && !portative) { autoUpdater.checkForUpdates() } - spider = new spiderCall((...data) => { - if(mainWindow) - mainWindow.webContents.send(...data) - }, (message, callback) => { - ipcMain.on(message, (event, arg) => { - if(Array.isArray(arg) && typeof arg[arg.length - 1] === 'object' && arg[arg.length - 1].callback) - { - const id = arg[arg.length - 1].callback - arg[arg.length - 1] = (responce) => { - mainWindow.webContents.send('callback', id, responce) - } - } - callback.apply(null, arg) - }) - }, app.getPath("userData"), app.getVersion(), env.name) - }, mainWindow, sphinx) - }, app.getPath("userData"), () => app.quit()) + spider = new spiderCall((...data) => { + if(mainWindow) + mainWindow.webContents.send(...data) + }, (message, callback) => { + ipcMain.on(message, (event, arg) => { + if(Array.isArray(arg) && typeof arg[arg.length - 1] === 'object' && arg[arg.length - 1].callback) + { + const id = arg[arg.length - 1].callback + arg[arg.length - 1] = (responce) => { + mainWindow.webContents.send('callback', id, responce) + } + } + callback.apply(null, arg) + }) + }, app.getPath("userData"), app.getVersion(), env.name) + }, mainWindow, sphinx) + }, app.getPath("userData"), () => app.quit()) }); let stopProtect = false const stop = () => { - if(stopProtect) - return - stopProtect = true + if(stopProtect) + return + stopProtect = true - if(tray) - tray.destroy() + if(tray) + tray.destroy() - if(spider) - { - spider.stop(() => sphinx.stop()) - } - else - { - sphinx.stop() - } + if(spider) + { + spider.stop(() => sphinx.stop()) + } + else + { + sphinx.stop() + } } app.on("window-all-closed", () => { - if (sphinx) - stop() - else - app.quit() + if (sphinx) + stop() + else + app.quit() }); app.on('before-quit', () => { - app.isQuiting = true - if (sphinx) - stop() + app.isQuiting = true + if (sphinx) + stop() }) \ No newline at end of file diff --git a/src/background/bt/client.js b/src/background/bt/client.js index 7964349..5aa65a1 100644 --- a/src/background/bt/client.js +++ b/src/background/bt/client.js @@ -11,88 +11,88 @@ const config = require('../config') class Client extends Emiter { - constructor(options) { - super(); - this.timeout = config.downloader.timeout; - this.maxConnections = config.downloader.maxConnections; - debug('timeout', this.timeout) - debug('maxConnections', this.maxConnections) - this.activeConnections = 0; - this.peers = new PeerQueue(this.maxConnections); - this.on('download', this._download); + constructor(options) { + super(); + this.timeout = config.downloader.timeout; + this.maxConnections = config.downloader.maxConnections; + debug('timeout', this.timeout) + debug('maxConnections', this.maxConnections) + this.activeConnections = 0; + this.peers = new PeerQueue(this.maxConnections); + this.on('download', this._download); - // if (typeof options.ignore === 'function') { - // this.ignore = options.ignore; - //} - //else { - this.ignore = function (infohash, rinfo, ignore) { - ignore(false); - }; - // } - } + // if (typeof options.ignore === 'function') { + // this.ignore = options.ignore; + //} + //else { + this.ignore = function (infohash, rinfo, ignore) { + ignore(false); + }; + // } + } - _next(infohash, successful) { - var req = this.peers.shift(infohash, successful); - if (req) { - this.ignore(req.infohash.toString('hex'), req.rinfo, (drop) => { - if (!drop) { - this.emit('download', req.rinfo, req.infohash); - } - }); - } - } + _next(infohash, successful) { + var req = this.peers.shift(infohash, successful); + if (req) { + this.ignore(req.infohash.toString('hex'), req.rinfo, (drop) => { + if (!drop) { + this.emit('download', req.rinfo, req.infohash); + } + }); + } + } - _download(rinfo, infohash) - { - debug('start download', infohash.toString('hex'), 'connections', this.activeConnections); - this.activeConnections++; + _download(rinfo, infohash) + { + debug('start download', infohash.toString('hex'), 'connections', this.activeConnections); + this.activeConnections++; - var successful = false; - var socket = new net.Socket(); + var successful = false; + var socket = new net.Socket(); - socket.setTimeout(this.timeout || 5000); - socket.connect(rinfo.port, rinfo.address, () => { - var wire = new Wire(infohash); - socket.pipe(wire).pipe(socket); + socket.setTimeout(this.timeout || 5000); + socket.connect(rinfo.port, rinfo.address, () => { + var wire = new Wire(infohash); + socket.pipe(wire).pipe(socket); - wire.on('metadata', (metadata, infoHash) => { - successful = true; - debug('successfuly downloader', infoHash, rinfo); - this.emit('complete', metadata, infoHash, rinfo); - socket.destroy(); - }); + wire.on('metadata', (metadata, infoHash) => { + successful = true; + debug('successfuly downloader', infoHash, rinfo); + this.emit('complete', metadata, infoHash, rinfo); + socket.destroy(); + }); - wire.on('fail', () => { - socket.destroy(); - }); + wire.on('fail', () => { + socket.destroy(); + }); - wire.sendHandshake(); - }); + wire.sendHandshake(); + }); - socket.on('error', (err) => { - socket.destroy(); - }); + socket.on('error', (err) => { + socket.destroy(); + }); - socket.on('timeout', (err) => { - socket.destroy(); - }); + socket.on('timeout', (err) => { + socket.destroy(); + }); - socket.once('close', () => { - this.activeConnections--; - this._next(infohash, successful); - }); - } + socket.once('close', () => { + this.activeConnections--; + this._next(infohash, successful); + }); + } - add(rinfo, infohash) { - this.peers.push({infohash: infohash, rinfo: rinfo}); - if (this.activeConnections < this.maxConnections && this.peers.length() > 0) { - this._next(); - } - } + add(rinfo, infohash) { + this.peers.push({infohash: infohash, rinfo: rinfo}); + if (this.activeConnections < this.maxConnections && this.peers.length() > 0) { + this._next(); + } + } - isIdle() { - return this.peers.length() === 0; - } + isIdle() { + return this.peers.length() === 0; + } } module.exports = Client; \ No newline at end of file diff --git a/src/background/bt/cpu-usage.js b/src/background/bt/cpu-usage.js index eede29d..4fbee1e 100644 --- a/src/background/bt/cpu-usage.js +++ b/src/background/bt/cpu-usage.js @@ -8,28 +8,28 @@ let sw = false const cpuTimer = setInterval(() => { if(!sw) { keepTime = process.hrtime(); - keepUsage = process.cpuUsage(); - sw = true; + keepUsage = process.cpuUsage(); + sw = true; } else { startTime = keepTime; startUsage = keepUsage; sw = false; - } + } }, 500) cpuTimer.unref() module.exports = () => { - function secNSec2ms (secNSec) { - return secNSec[0] * 1000 + secNSec[1] / 1000000 - } + function secNSec2ms (secNSec) { + return secNSec[0] * 1000 + secNSec[1] / 1000000 + } - var elapTime = process.hrtime(startTime) - var elapUsage = process.cpuUsage(startUsage) + var elapTime = process.hrtime(startTime) + var elapUsage = process.cpuUsage(startUsage) - var elapTimeMS = secNSec2ms(elapTime) - var elapUserMS = elapUsage.user - var elapSystMS = elapUsage.system + var elapTimeMS = secNSec2ms(elapTime) + var elapUserMS = elapUsage.user + var elapSystMS = elapUsage.system - return Math.round(100 * ((elapUserMS + elapSystMS) / 1000) / elapTimeMS) + return Math.round(100 * ((elapUserMS + elapSystMS) / 1000) / elapTimeMS) } \ No newline at end of file diff --git a/src/background/bt/peer-queue.js b/src/background/bt/peer-queue.js index 6d289c1..4113888 100644 --- a/src/background/bt/peer-queue.js +++ b/src/background/bt/peer-queue.js @@ -1,55 +1,55 @@ 'use strict'; var PeerQueue = function (maxSize, perLimit) { - this.maxSize = maxSize || 200; - this.perLimit = perLimit || 10; - this.peers = {}; - this.reqs = []; + this.maxSize = maxSize || 200; + this.perLimit = perLimit || 10; + this.peers = {}; + this.reqs = []; }; PeerQueue.prototype._shift = function () { - if (this.length() > 0) { - var req = this.reqs.shift(); - this.peers[req.infohash.toString('hex')] = []; - return req; - } + if (this.length() > 0) { + var req = this.reqs.shift(); + this.peers[req.infohash.toString('hex')] = []; + return req; + } }; PeerQueue.prototype.push = function (peer) { - var infohashHex = peer.infohash.toString('hex'); - var peers = this.peers[infohashHex]; + var infohashHex = peer.infohash.toString('hex'); + var peers = this.peers[infohashHex]; - if (peers && peers.length < this.perLimit) { - peers.push(peer); - } - else if (this.length() < this.maxSize) { - this.reqs.push(peer); - } + if (peers && peers.length < this.perLimit) { + peers.push(peer); + } + else if (this.length() < this.maxSize) { + this.reqs.push(peer); + } }; PeerQueue.prototype.shift = function (infohash, successful) { - if (infohash) { - var infohashHex = infohash.toString('hex'); - if (successful === true) { - delete this.peers[infohashHex]; - } - else { - var peers = this.peers[infohashHex]; - if (peers) { - if (peers.length > 0) { - return peers.shift(); - } - else { - delete this.peers[infohashHex]; - } - } - } - } - return this._shift(); + if (infohash) { + var infohashHex = infohash.toString('hex'); + if (successful === true) { + delete this.peers[infohashHex]; + } + else { + var peers = this.peers[infohashHex]; + if (peers) { + if (peers.length > 0) { + return peers.shift(); + } + else { + delete this.peers[infohashHex]; + } + } + } + } + return this._shift(); }; PeerQueue.prototype.length = function () { - return this.reqs.length; + return this.reqs.length; }; module.exports = PeerQueue; \ No newline at end of file diff --git a/src/background/bt/spider.js b/src/background/bt/spider.js index 8558dfc..40ff4c4 100644 --- a/src/background/bt/spider.js +++ b/src/background/bt/spider.js @@ -9,312 +9,312 @@ const config = require('../config') const fs = require('fs') const bootstraps = [{ - address: 'router.bittorrent.com', - port: 6881 + address: 'router.bittorrent.com', + port: 6881 }, { - address: 'router.utorrent.com', - port: 6881 + address: 'router.utorrent.com', + port: 6881 }, { - address: 'dht.transmissionbt.com', - port: 6881 + address: 'dht.transmissionbt.com', + port: 6881 }, { - address: 'dht.aelitis.com', - port: 6881 + address: 'dht.aelitis.com', + port: 6881 }] function isValidPort(port) { - return port > 0 && port < (1 << 16) + return port > 0 && port < (1 << 16) } function generateTid() { - return parseInt(Math.random() * 99).toString() + return parseInt(Math.random() * 99).toString() } class Spider extends Emiter { - constructor(client) { - super() - const options = arguments.length? arguments[0]: {} - this.table = new Table(options.tableCaption || 1000) - this.bootstraps = options.bootstraps || bootstraps - this.token = new Token() - this.client = client - this.ignore = false; // ignore all requests - this.initialized = false; + constructor(client) { + super() + const options = arguments.length? arguments[0]: {} + this.table = new Table(options.tableCaption || 1000) + this.bootstraps = options.bootstraps || bootstraps + this.token = new Token() + this.client = client + this.ignore = false; // ignore all requests + this.initialized = false; - this.walkInterval = config.spider.walkInterval; - this.foundSpeed = 0; - this.foundCounter = 0; - setInterval(() => { - this.foundSpeed = this.foundCounter; - this.foundCounter = 0; - }, 1000) + this.walkInterval = config.spider.walkInterval; + this.foundSpeed = 0; + this.foundCounter = 0; + setInterval(() => { + this.foundSpeed = this.foundCounter; + this.foundCounter = 0; + }, 1000) - this.announceHashes = [] - } + this.announceHashes = [] + } - send(message, address) { - const data = bencode.encode(message) - this.udp.send(data, 0, data.length, address.port, address.address) - } + send(message, address) { + const data = bencode.encode(message) + this.udp.send(data, 0, data.length, address.port, address.address) + } - findNode(id, address) { - const message = { - t: generateTid(), - y: 'q', - q: 'find_node', - a: { - id: id, - target: Node.generateID() - } - } - this.send(message, address) - } + findNode(id, address) { + const message = { + t: generateTid(), + y: 'q', + q: 'find_node', + a: { + id: id, + target: Node.generateID() + } + } + this.send(message, address) + } - getPeersRequest(infoHash, address) { - const message = { - t: generateTid(), - y: 'q', - q: 'get_peers', - a: { - id: this.table.id, - info_hash: infoHash - } - } - this.send(message, address) - } + getPeersRequest(infoHash, address) { + const message = { + t: generateTid(), + y: 'q', + q: 'get_peers', + a: { + id: this.table.id, + info_hash: infoHash + } + } + this.send(message, address) + } - announcePeer(infoHash, token, address, port) - { - const message = { - t: generateTid(), - y: 'q', - q: 'announce_peer', - a: { - id: this.table.id, - token: token, - info_hash: infoHash, - port: port, - implied_port: port ? 0 : 1 - } - } - this.send(message, address) - } + announcePeer(infoHash, token, address, port) + { + const message = { + t: generateTid(), + y: 'q', + q: 'announce_peer', + a: { + id: this.table.id, + token: token, + info_hash: infoHash, + port: port, + implied_port: port ? 0 : 1 + } + } + this.send(message, address) + } - join() { - this.bootstraps.forEach((bootstrap) => { - this.findNode(this.table.id, bootstrap) - }) - } + join() { + this.bootstraps.forEach((bootstrap) => { + this.findNode(this.table.id, bootstrap) + }) + } - walk() { - if(this.closing) - return + walk() { + if(this.closing) + return - if(!this.client || this.client.isIdle()) { - if(!this.ignore) - { - const node = this.table.shift() - if (node && (config.spider.nodesUsage === 0 || parseInt(Math.random() * this.table.nodes.length / config.spider.nodesUsage) === 0)) { - this.findNode(Node.neighbor(node.id, this.table.id), {address: node.address, port: node.port}) - } - } - } - setTimeout(()=>this.walk(), this.walkInterval) - } + if(!this.client || this.client.isIdle()) { + if(!this.ignore) + { + const node = this.table.shift() + if (node && (config.spider.nodesUsage === 0 || parseInt(Math.random() * this.table.nodes.length / config.spider.nodesUsage) === 0)) { + this.findNode(Node.neighbor(node.id, this.table.id), {address: node.address, port: node.port}) + } + } + } + setTimeout(()=>this.walk(), this.walkInterval) + } - onFoundNodes(data, token, address) { - const nodes = Node.decodeNodes(data) - nodes.forEach((node) => { - if (node.id != this.table.id && isValidPort(node.port)) { - this.table.add(node) - } - }) - this.emit('nodes', nodes) + onFoundNodes(data, token, address) { + const nodes = Node.decodeNodes(data) + nodes.forEach((node) => { + if (node.id != this.table.id && isValidPort(node.port)) { + this.table.add(node) + } + }) + this.emit('nodes', nodes) - // announce torrents - if(token) - { - for(const hash of this.announceHashes) - { - this.announcePeer(hash, token, address) - } - } - } + // announce torrents + if(token) + { + for(const hash of this.announceHashes) + { + this.announcePeer(hash, token, address) + } + } + } - onFoundPeers(peers, token, address) { - if(token) - { - for(const hash of this.announceHashes) - { - this.announcePeer(hash, token, address) - } - } + onFoundPeers(peers, token, address) { + if(token) + { + for(const hash of this.announceHashes) + { + this.announcePeer(hash, token, address) + } + } - if(!peers || peers.length == 0) - return; + if(!peers || peers.length == 0) + return; - const ips = Node.decodeCompactIP(peers) - this.emit('peer', ips) - } + const ips = Node.decodeCompactIP(peers) + this.emit('peer', ips) + } - onFindNodeRequest(message, address) { - if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit) - { - return - } + onFindNodeRequest(message, address) { + if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit) + { + return + } - const {t: tid, a: {id: nid, target: infohash}} = message + const {t: tid, a: {id: nid, target: infohash}} = message - if (tid === undefined || target.length != 20 || nid.length != 20) { - return - } + if (tid === undefined || target.length != 20 || nid.length != 20) { + return + } - this.send({ - t: tid, - y: 'r', - r: { - id: Node.neighbor(nid, this.table.id), - nodes: Node.encodeNodes(this.table.first()) - } - }, address) + this.send({ + t: tid, + y: 'r', + r: { + id: Node.neighbor(nid, this.table.id), + nodes: Node.encodeNodes(this.table.first()) + } + }, address) - // also check hashes of alive ones - for(const hash of this.announceHashes) - { - this.getPeersRequest(hash, address) - } - } + // also check hashes of alive ones + for(const hash of this.announceHashes) + { + this.getPeersRequest(hash, address) + } + } - onGetPeersRequest(message, address) { - if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit) - { - return - } + onGetPeersRequest(message, address) { + if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit) + { + return + } - const {t: tid, a: {id: nid, info_hash: infohash}} = message + const {t: tid, a: {id: nid, info_hash: infohash}} = message - if (tid === undefined || infohash.length != 20 || nid.length != 20) { - return - } + if (tid === undefined || infohash.length != 20 || nid.length != 20) { + return + } - this.send({ - t: tid, - y: 'r', - r: { - id: Node.neighbor(nid, this.table.id), - nodes: Node.encodeNodes(this.table.first()), - token: this.token.token - } - }, address) + this.send({ + t: tid, + y: 'r', + r: { + id: Node.neighbor(nid, this.table.id), + nodes: Node.encodeNodes(this.table.first()), + token: this.token.token + } + }, address) - this.emit('unensureHash', infohash.toString('hex').toUpperCase()) + this.emit('unensureHash', infohash.toString('hex').toUpperCase()) - // also check hashes of alive ones - for(const hash of this.announceHashes) - { - this.getPeersRequest(hash, address) - } - } + // also check hashes of alive ones + for(const hash of this.announceHashes) + { + this.getPeersRequest(hash, address) + } + } - onAnnouncePeerRequest(message, address) { - let {t: tid, a: {info_hash: infohash, token: token, id: id, implied_port: implied, port: port}} = message - if (!tid) return + onAnnouncePeerRequest(message, address) { + let {t: tid, a: {info_hash: infohash, token: token, id: id, implied_port: implied, port: port}} = message + if (!tid) return - if (!this.token.isValid(token)) return + if (!this.token.isValid(token)) return - port = (implied != undefined && implied != 0) ? address.port : (port || 0) - if (!isValidPort(port)) return + port = (implied != undefined && implied != 0) ? address.port : (port || 0) + if (!isValidPort(port)) return - this.send({ t: tid, y: 'r', r: { id: Node.neighbor(id, this.table.id) } }, address) + this.send({ t: tid, y: 'r', r: { id: Node.neighbor(id, this.table.id) } }, address) - let addressPair = { - address: address.address, - port: port - }; - this.emit('ensureHash', infohash.toString('hex').toUpperCase(), addressPair) - if(this.client && !this.ignore) { - this.client.add(addressPair, infohash); - } - } + let addressPair = { + address: address.address, + port: port + }; + this.emit('ensureHash', infohash.toString('hex').toUpperCase(), addressPair) + if(this.client && !this.ignore) { + this.client.add(addressPair, infohash); + } + } - onPingRequest(message, address) { - if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit) - { - return - } + onPingRequest(message, address) { + if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit) + { + return + } - this.send({ t: message.t, y: 'r', r: { id: Node.neighbor(message.a.id, this.table.id) } }, address) - } + this.send({ t: message.t, y: 'r', r: { id: Node.neighbor(message.a.id, this.table.id) } }, address) + } - parse(data, address) { - try { - const message = bencode.decode(data) - if (message.y.toString() == 'r') { - if(message.r.nodes) { - this.foundCounter++; - this.onFoundNodes(message.r.nodes, message.r.token, address) - } else if(message.r.values) { - this.onFoundPeers(message.r.values, message.r.token, address) - } - } else if (message.y.toString() == 'q') { - this.foundCounter++; - switch(message.q.toString()) { - case 'get_peers': - this.onGetPeersRequest(message, address) - break - case 'announce_peer': - this.onAnnouncePeerRequest(message, address) - break - case 'find_node': - this.onFindNodeRequest(message, address) - break - case 'ping': - this.onPingRequest(message, address) - break - } - } - } catch (err) {} - } + parse(data, address) { + try { + const message = bencode.decode(data) + if (message.y.toString() == 'r') { + if(message.r.nodes) { + this.foundCounter++; + this.onFoundNodes(message.r.nodes, message.r.token, address) + } else if(message.r.values) { + this.onFoundPeers(message.r.values, message.r.token, address) + } + } else if (message.y.toString() == 'q') { + this.foundCounter++; + switch(message.q.toString()) { + case 'get_peers': + this.onGetPeersRequest(message, address) + break + case 'announce_peer': + this.onAnnouncePeerRequest(message, address) + break + case 'find_node': + this.onFindNodeRequest(message, address) + break + case 'ping': + this.onPingRequest(message, address) + break + } + } + } catch (err) {} + } - listen(port) { - if(this.initialized) - return - this.initialized = true + listen(port) { + if(this.initialized) + return + this.initialized = true - this.closing = false - this.udp = dgram.createSocket('udp4') - this.udp.bind(port) - this.udp.on('listening', () => { - console.log(`Listen DHT protocol on ${this.udp.address().address}:${this.udp.address().port}`) - }) - this.udp.on('message', (data, addr) => { - this.parse(data, addr) - }) - this.udp.on('error', (err) => {}) - this.joinInterval = setInterval(() => { - if(!this.client || this.client.isIdle()) { - this.join() - } - }, 3000) - this.join() - this.walk() - } + this.closing = false + this.udp = dgram.createSocket('udp4') + this.udp.bind(port) + this.udp.on('listening', () => { + console.log(`Listen DHT protocol on ${this.udp.address().address}:${this.udp.address().port}`) + }) + this.udp.on('message', (data, addr) => { + this.parse(data, addr) + }) + this.udp.on('error', (err) => {}) + this.joinInterval = setInterval(() => { + if(!this.client || this.client.isIdle()) { + this.join() + } + }, 3000) + this.join() + this.walk() + } - close(callback) - { - if(!this.initialized) { - if(callback) - callback() - return - } - clearInterval(this.joinInterval) - this.closing = true - this.udp.close(() => { - this.initialized = false - if(callback) - callback() - }) - } + close(callback) + { + if(!this.initialized) { + if(callback) + callback() + return + } + clearInterval(this.joinInterval) + this.closing = true + this.udp.close(() => { + this.initialized = false + if(callback) + callback() + }) + } } module.exports = Spider \ No newline at end of file diff --git a/src/background/bt/udp-tracker-request.js b/src/background/bt/udp-tracker-request.js index 6056761..1c247b8 100644 --- a/src/background/bt/udp-tracker-request.js +++ b/src/background/bt/udp-tracker-request.js @@ -13,119 +13,119 @@ const connectionIdLow = 0x27101980 const requests = {}; let message = function (buf, host, port) { - server.send(buf, 0, buf.length, port, host, function(err, bytes) { - if (err) { - console.log(err.message); - } - }); + server.send(buf, 0, buf.length, port, host, function(err, bytes) { + if (err) { + console.log(err.message); + } + }); }; let connectTracker = function(connection) { - debug('start screape connection'); - let buffer = new Buffer(16); + debug('start screape connection'); + let buffer = new Buffer(16); - const transactionId = Math.floor((Math.random()*100000)+1); + const transactionId = Math.floor((Math.random()*100000)+1); - buffer.fill(0); + buffer.fill(0); - buffer.writeUInt32BE(connectionIdHigh, 0); - buffer.writeUInt32BE(connectionIdLow, 4); - buffer.writeUInt32BE(ACTION_CONNECT, 8); - buffer.writeUInt32BE(transactionId, 12); + buffer.writeUInt32BE(connectionIdHigh, 0); + buffer.writeUInt32BE(connectionIdLow, 4); + buffer.writeUInt32BE(ACTION_CONNECT, 8); + buffer.writeUInt32BE(transactionId, 12); - // очистка старых соединений - for(const transaction in requests) { - if((new Date).getTime() - requests[transaction].date.getTime() > config.udpTrackersTimeout) { - delete requests[transaction]; - } - } + // очистка старых соединений + for(const transaction in requests) { + if((new Date).getTime() - requests[transaction].date.getTime() > config.udpTrackersTimeout) { + delete requests[transaction]; + } + } - requests[transactionId] = connection; - message(buffer, connection.host, connection.port); + requests[transactionId] = connection; + message(buffer, connection.host, connection.port); }; let scrapeTorrent = function (connectionIdHigh, connectionIdLow, transactionId) { - let connection = requests[transactionId]; - if(!connection) - return; + let connection = requests[transactionId]; + if(!connection) + return; - if(!connection.hash || connection.hash.length != 40) - return + if(!connection.hash || connection.hash.length != 40) + return - debug('start scrape'); - let buffer = new Buffer(56) + debug('start scrape'); + let buffer = new Buffer(56) - buffer.fill(0); + buffer.fill(0); - buffer.writeUInt32BE(connectionIdHigh, 0); - buffer.writeUInt32BE(connectionIdLow, 4); - buffer.writeUInt32BE(ACTION_SCRAPE, 8); - buffer.writeUInt32BE(transactionId, 12); + buffer.writeUInt32BE(connectionIdHigh, 0); + buffer.writeUInt32BE(connectionIdLow, 4); + buffer.writeUInt32BE(ACTION_SCRAPE, 8); + buffer.writeUInt32BE(transactionId, 12); - try - { - buffer.write(connection.hash, 16, buffer.length, 'hex'); - // do scrape - message(buffer, connection.host, connection.port); - } catch(error) - { - console.log('ERROR on scrape', error) - } + try + { + buffer.write(connection.hash, 16, buffer.length, 'hex'); + // do scrape + message(buffer, connection.host, connection.port); + } catch(error) + { + console.log('ERROR on scrape', error) + } }; server.on("message", function (msg, rinfo) { - let buffer = new Buffer(msg) + let buffer = new Buffer(msg) - const action = buffer.readUInt32BE(0, 4); - const transactionId = buffer.readUInt32BE(4, 4); + const action = buffer.readUInt32BE(0, 4); + const transactionId = buffer.readUInt32BE(4, 4); - if(!(transactionId in requests)) - return; + if(!(transactionId in requests)) + return; - debug("returned action: " + action); - debug("returned transactionId: " + transactionId); + debug("returned action: " + action); + debug("returned transactionId: " + transactionId); - if (action === ACTION_CONNECT) { - debug("connect response"); + if (action === ACTION_CONNECT) { + debug("connect response"); - let connectionIdHigh = buffer.readUInt32BE(8, 4); - let connectionIdLow = buffer.readUInt32BE(12, 4); + let connectionIdHigh = buffer.readUInt32BE(8, 4); + let connectionIdLow = buffer.readUInt32BE(12, 4); - scrapeTorrent(connectionIdHigh, connectionIdLow, transactionId); + scrapeTorrent(connectionIdHigh, connectionIdLow, transactionId); - } else if (action === ACTION_SCRAPE) { - debug("scrape response"); + } else if (action === ACTION_SCRAPE) { + debug("scrape response"); - let seeders = buffer.readUInt32BE(8, 4); - let completed = buffer.readUInt32BE(12, 4); - let leechers = buffer.readUInt32BE(16, 4); + let seeders = buffer.readUInt32BE(8, 4); + let completed = buffer.readUInt32BE(12, 4); + let leechers = buffer.readUInt32BE(16, 4); - let connection = requests[transactionId]; - connection.callback({ - host: connection.host, - port: connection.port, - hash: connection.hash, - seeders, - completed, - leechers - }) - delete requests[transactionId]; - } else if (action === ACTION_ERROR) { - delete requests[transactionId]; - console.log("error in scrape response"); - } + let connection = requests[transactionId]; + connection.callback({ + host: connection.host, + port: connection.port, + hash: connection.hash, + seeders, + completed, + leechers + }) + delete requests[transactionId]; + } else if (action === ACTION_ERROR) { + delete requests[transactionId]; + console.log("error in scrape response"); + } }); let getPeersStatistic = (host, port, hash, callback) => { - let connection = { - host, port, hash, callback, date: new Date() - } - connectTracker(connection); + let connection = { + host, port, hash, callback, date: new Date() + } + connectTracker(connection); } server.on("listening", function () { - var address = server.address(); - console.log("listening udp tracker respose on " + address.address + ":" + address.port); + var address = server.address(); + console.log("listening udp tracker respose on " + address.address + ":" + address.port); }); server.bind(config.udpTrackersPort); diff --git a/src/background/bt/wire.js b/src/background/bt/wire.js index d2232ce..71c639b 100644 --- a/src/background/bt/wire.js +++ b/src/background/bt/wire.js @@ -18,230 +18,230 @@ var EXT_HANDSHAKE_ID = 0; var BT_MSG_ID = 20; var Wire = function(infohash) { - stream.Duplex.call(this); + stream.Duplex.call(this); - this._bitfield = new BitField(0, { grow: BITFIELD_GROW }); - this._infohash = infohash; + this._bitfield = new BitField(0, { grow: BITFIELD_GROW }); + this._infohash = infohash; - this._buffer = []; - this._bufferSize = 0; + this._buffer = []; + this._bufferSize = 0; - this._next = null; - this._nextSize = 0; + this._next = null; + this._nextSize = 0; - this._metadata = null; - this._metadataSize = null; - this._numPieces = 0; - this._ut_metadata = null; + this._metadata = null; + this._metadataSize = null; + this._numPieces = 0; + this._ut_metadata = null; - this._onHandshake(); + this._onHandshake(); } util.inherits(Wire, stream.Duplex); Wire.prototype._onMessageLength = function (buffer) { - if (buffer.length >= 4) { - var length = buffer.readUInt32BE(0); - if (length > 0) { - this._register(length, this._onMessage) - } - } + if (buffer.length >= 4) { + var length = buffer.readUInt32BE(0); + if (length > 0) { + this._register(length, this._onMessage) + } + } }; Wire.prototype._onMessage = function (buffer) { - this._register(4, this._onMessageLength) - if (buffer[0] == BT_MSG_ID) { - this._onExtended(buffer.readUInt8(1), buffer.slice(2)); - } + this._register(4, this._onMessageLength) + if (buffer[0] == BT_MSG_ID) { + this._onExtended(buffer.readUInt8(1), buffer.slice(2)); + } }; Wire.prototype._onExtended = function(ext, buf) { - if (ext === 0) { - try { - this._onExtHandshake(bencode.decode(buf)); - } - catch (err) { - this._fail(); - } - } - else { - this._onPiece(buf); - } + if (ext === 0) { + try { + this._onExtHandshake(bencode.decode(buf)); + } + catch (err) { + this._fail(); + } + } + else { + this._onPiece(buf); + } }; Wire.prototype._register = function (size, next) { - this._nextSize = size; - this._next = next; + this._nextSize = size; + this._next = next; }; Wire.prototype.end = function() { - stream.Duplex.prototype.end.apply(this, arguments); + stream.Duplex.prototype.end.apply(this, arguments); }; Wire.prototype._onHandshake = function() { - this._register(1, function(buffer) { - if (buffer.length == 0) { - this.end(); - return this._fail(); - } - var pstrlen = buffer.readUInt8(0); - this._register(pstrlen + 48, function(handshake) { - var protocol = handshake.slice(0, pstrlen); - if (protocol.toString() !== BT_PROTOCOL.toString()) { - this.end(); - this._fail(); - return; - } - handshake = handshake.slice(pstrlen); - if ( !!(handshake[5] & 0x10) ) { - this._register(4, this._onMessageLength); - this._sendExtHandshake(); - } - else { - this._fail(); - } - }.bind(this)); - }.bind(this)); + this._register(1, function(buffer) { + if (buffer.length == 0) { + this.end(); + return this._fail(); + } + var pstrlen = buffer.readUInt8(0); + this._register(pstrlen + 48, function(handshake) { + var protocol = handshake.slice(0, pstrlen); + if (protocol.toString() !== BT_PROTOCOL.toString()) { + this.end(); + this._fail(); + return; + } + handshake = handshake.slice(pstrlen); + if ( !!(handshake[5] & 0x10) ) { + this._register(4, this._onMessageLength); + this._sendExtHandshake(); + } + else { + this._fail(); + } + }.bind(this)); + }.bind(this)); }; Wire.prototype._onExtHandshake = function(extHandshake) { - if (!extHandshake.metadata_size || !extHandshake.m.ut_metadata + if (!extHandshake.metadata_size || !extHandshake.m.ut_metadata || extHandshake.metadata_size > MAX_METADATA_SIZE) { - this._fail(); - return; - } + this._fail(); + return; + } - this._metadataSize = extHandshake.metadata_size; - this._numPieces = Math.ceil(this._metadataSize / PIECE_LENGTH); - this._ut_metadata = extHandshake.m.ut_metadata; + this._metadataSize = extHandshake.metadata_size; + this._numPieces = Math.ceil(this._metadataSize / PIECE_LENGTH); + this._ut_metadata = extHandshake.m.ut_metadata; - this._requestPieces(); + this._requestPieces(); } Wire.prototype._requestPieces = function() { - this._metadata = new Buffer(this._metadataSize); - for (var piece = 0; piece < this._numPieces; piece++) { - this._requestPiece(piece); - } + this._metadata = new Buffer(this._metadataSize); + for (var piece = 0; piece < this._numPieces; piece++) { + this._requestPiece(piece); + } }; Wire.prototype._requestPiece = function(piece) { - var msg = Buffer.concat([ - new Buffer([BT_MSG_ID]), - new Buffer([this._ut_metadata]), - bencode.encode({msg_type: 0, piece: piece}) - ]); - this._sendMessage(msg); + var msg = Buffer.concat([ + new Buffer([BT_MSG_ID]), + new Buffer([this._ut_metadata]), + bencode.encode({msg_type: 0, piece: piece}) + ]); + this._sendMessage(msg); }; Wire.prototype._sendPacket = function(packet) { - this.push(packet); + this.push(packet); }; Wire.prototype._sendMessage = function(msg) { - var buf = new Buffer(4); - buf.writeUInt32BE(msg.length, 0); - this._sendPacket(Buffer.concat([buf, msg])); + var buf = new Buffer(4); + buf.writeUInt32BE(msg.length, 0); + this._sendPacket(Buffer.concat([buf, msg])); }; Wire.prototype.sendHandshake = function() { - var peerID = Node.generateID(); - var packet = Buffer.concat([ - new Buffer([BT_PROTOCOL.length]), - BT_PROTOCOL, BT_RESERVED, this._infohash, peerID - ]); - this._sendPacket(packet); + var peerID = Node.generateID(); + var packet = Buffer.concat([ + new Buffer([BT_PROTOCOL.length]), + BT_PROTOCOL, BT_RESERVED, this._infohash, peerID + ]); + this._sendPacket(packet); }; Wire.prototype._sendExtHandshake = function() { - var msg = Buffer.concat([ - new Buffer([BT_MSG_ID]), - new Buffer([EXT_HANDSHAKE_ID]), - bencode.encode({m: {ut_metadata: 1}}) - ]); - this._sendMessage(msg); + var msg = Buffer.concat([ + new Buffer([BT_MSG_ID]), + new Buffer([EXT_HANDSHAKE_ID]), + bencode.encode({m: {ut_metadata: 1}}) + ]); + this._sendMessage(msg); }; Wire.prototype._onPiece = function(piece) { - var dict, trailer; - try { - var str = piece.toString(); - var trailerIndex = str.indexOf('ee') + 2; - dict = bencode.decode(str.substring(0, trailerIndex)); - trailer = piece.slice(trailerIndex); - } - catch (err) { - this._fail(); - return; - } - if (dict.msg_type != 1) { - this._fail(); - return; - } - if (trailer.length > PIECE_LENGTH) { - this._fail(); - return; - } - trailer.copy(this._metadata, dict.piece * PIECE_LENGTH); - this._bitfield.set(dict.piece); - this._checkDone(); + var dict, trailer; + try { + var str = piece.toString(); + var trailerIndex = str.indexOf('ee') + 2; + dict = bencode.decode(str.substring(0, trailerIndex)); + trailer = piece.slice(trailerIndex); + } + catch (err) { + this._fail(); + return; + } + if (dict.msg_type != 1) { + this._fail(); + return; + } + if (trailer.length > PIECE_LENGTH) { + this._fail(); + return; + } + trailer.copy(this._metadata, dict.piece * PIECE_LENGTH); + this._bitfield.set(dict.piece); + this._checkDone(); }; Wire.prototype._checkDone = function () { - var done = true; - for (var piece = 0; piece < this._numPieces; piece++) { - if (!this._bitfield.get(piece)) { - done = false; - break; - } - } - if (!done) { - return - } - this._onDone(this._metadata); + var done = true; + for (var piece = 0; piece < this._numPieces; piece++) { + if (!this._bitfield.get(piece)) { + done = false; + break; + } + } + if (!done) { + return + } + this._onDone(this._metadata); }; Wire.prototype._onDone = function(metadata) { - try { - var info = bencode.decode(metadata).info; - if (info) { - metadata = bencode.encode(info); - } - } - catch (err) { - this._fail(); - return; - } - var infohash = crypto.createHash('sha1').update(metadata).digest('hex'); - if (this._infohash.toString('hex') != infohash ) { - this._fail(); - return false; - } - this.emit('metadata', {info: bencode.decode(metadata, 'utf8')}, this._infohash); + try { + var info = bencode.decode(metadata).info; + if (info) { + metadata = bencode.encode(info); + } + } + catch (err) { + this._fail(); + return; + } + var infohash = crypto.createHash('sha1').update(metadata).digest('hex'); + if (this._infohash.toString('hex') != infohash ) { + this._fail(); + return false; + } + this.emit('metadata', {info: bencode.decode(metadata, 'utf8')}, this._infohash); }; Wire.prototype._fail = function() { - this.emit('fail'); + this.emit('fail'); }; Wire.prototype._write = function (buf, encoding, next) { - this._bufferSize += buf.length; - this._buffer.push(buf); + this._bufferSize += buf.length; + this._buffer.push(buf); - while (this._bufferSize >= this._nextSize) { - var buffer = Buffer.concat(this._buffer); - this._bufferSize -= this._nextSize; - this._buffer = this._bufferSize - ? [buffer.slice(this._nextSize)] - : []; - this._next(buffer.slice(0, this._nextSize)); - } + while (this._bufferSize >= this._nextSize) { + var buffer = Buffer.concat(this._buffer); + this._bufferSize -= this._nextSize; + this._buffer = this._bufferSize + ? [buffer.slice(this._nextSize)] + : []; + this._next(buffer.slice(0, this._nextSize)); + } - next(null); + next(null); } Wire.prototype._read = function() { - // do nothing + // do nothing }; module.exports = Wire; diff --git a/src/background/checkInternet.js b/src/background/checkInternet.js index c8f3079..abe4f89 100644 --- a/src/background/checkInternet.js +++ b/src/background/checkInternet.js @@ -1,10 +1,10 @@ // https://stackoverflow.com/questions/15270902/check-for-internet-connectivity-in-nodejs module.exports = function checkInternet(cb) { - require('dns').lookup('google.com',function(err) { - if (err && err.code == "ENOTFOUND") { - cb(false); - } else { - cb(true); - } - }) + require('dns').lookup('google.com',function(err) { + if (err && err.code == "ENOTFOUND") { + cb(false); + } else { + cb(true); + } + }) } \ No newline at end of file diff --git a/src/background/config.js b/src/background/config.js index c48b6ff..d676305 100644 --- a/src/background/config.js +++ b/src/background/config.js @@ -11,7 +11,7 @@ let config = { udpTrackersTimeout: 3 * 60 * 1000, peerId: undefined, language: 'en', - + p2p: true, p2pConnections: 10, p2pBootstrap: true, @@ -25,9 +25,9 @@ let config = { sitemapMaxSize: 25000, sphinx: { - host : '127.0.0.1', - port : 9306, - connectionLimit: 30 + host : '127.0.0.1', + port : 9306, + connectionLimit: 30 }, spider: { @@ -79,8 +79,8 @@ const configProxy = new Proxy(config, { target[prop] = value - - if(!fs.existsSync(configPath)) + + if(!fs.existsSync(configPath)) fs.writeFileSync(configPath, '{}') const data = fs.readFileSync(configPath) diff --git a/src/background/dbPatcher.js b/src/background/dbPatcher.js index a5554a7..5009c56 100644 --- a/src/background/dbPatcher.js +++ b/src/background/dbPatcher.js @@ -13,31 +13,31 @@ const currentVersion = 4 module.exports = async (callback, mainWindow, sphinxApp) => { - const sphinx = await single().waitConnection() + const sphinx = await single().waitConnection() - const setVersion = async (version) => { - await sphinx.query(`delete from version where id = 1`) - await sphinx.query(`insert into version(id, version) values(1, ${version})`) - if(sphinxApp) - fs.writeFileSync(`${sphinxApp.directoryPath}/version.vrs`, version) - } + const setVersion = async (version) => { + await sphinx.query(`delete from version where id = 1`) + await sphinx.query(`insert into version(id, version) values(1, ${version})`) + if(sphinxApp) + fs.writeFileSync(`${sphinxApp.directoryPath}/version.vrs`, version) + } - let patchWindow; - const openPatchWindow = () => { - if(patchWindow) - return + let patchWindow; + const openPatchWindow = () => { + if(patchWindow) + return - if(!BrowserWindow) - return + if(!BrowserWindow) + return - if(mainWindow) - mainWindow.hide() + if(mainWindow) + mainWindow.hide() - patchWindow = new BrowserWindow({width: 800, height: 400, closable: false}) + patchWindow = new BrowserWindow({width: 800, height: 400, closable: false}) - patchWindow.setMenu(null) + patchWindow.setMenu(null) - patchWindow.loadURL("data:text/html;charset=utf-8," + encodeURI(` + patchWindow.loadURL("data:text/html;charset=utf-8," + encodeURI(` Database patching...