import { login } from './qbittorrent/auth' ; import { addTags , addTorrent , deleteTorrents , getTorrentInfo , getTorrents , getTrackers , reannounce } from './qbittorrent/api' ; import { sleep } from './helpers/utilities' ; import { logger } from './helpers/logger' ; import { preRaceCheck } from './helpers/pre_race' ; import { SETTINGS } from '../settings' ; import { sendMessage } from './discord/api' ; import { addMessage } from './discord/messages' ; import { torrentFromApi } from './interfaces' ; import { resume } from './helpers/resume' ; module . exports = async ( args ) => { const infohash = args [ 0 ] . toLowerCase ( ) ; const torrentName = args [ 1 ] ; const tracker = args [ 2 ] ; const path = args [ 3 ] ; let category = null ; for ( let index = 4 ; index < args . length ; index ++ ) { if ( args [ index ] === '--category' ) { if ( index + 1 < args . length ) { category = args [ index + 1 ] ; } else { logger . error ( '--category set but the category is missing.' ) ; break ; } } } let t1 = Date . now ( ) ; try { await login ( ) ; } catch ( error ) { logger . error ( `Failed to login. Exiting...` ) ; process . exit ( 1 ) ; } let t2 = Date . now ( ) ; logger . info ( `Login completed in ${ ( ( t2 - t1 ) / 1000 ) . toFixed ( 2 ) } seconds.` ) ; logger . info ( 'Performing Pre Race check...' ) ; const okay = await preRaceCheck ( ) ; if ( okay === false ) { logger . info ( `Conditions not met. Skipping ${ torrentName }` ) ; process . exit ( 0 ) ; } logger . info ( `Adding torrent ${ torrentName }` ) ; try { await addTorrent ( path , category ) ; } catch ( error ) { process . exit ( 1 ) ; } await sleep ( 5000 ) ; let tags = [ ] ; try { let trackers = await getTrackers ( infohash ) ; trackers . splice ( 0 , 3 ) ; tags = trackers . map ( ( { url } ) => new URL ( url ) . hostname ) ; logger . info ( `Adding ${ tags . length } tags.` ) ; await addTags ( [ { hash : infohash } ] , tags ) ; } catch ( error ) { logger . error ( `Failed to add tags. Error code ${ error }` ) ; } let torrent ; try { torrent = await getTorrentInfo ( infohash ) ; } catch ( error ) { process . exit ( 1 ) ; } logger . info ( "Starting reannounce check..." ) ; let attempts = 0 ; let announceOK = false ; while ( attempts < SETTINGS . REANNOUNCE_LIMIT ) { logger . info ( `Attempt #${ attempts + 1 }: Querying tracker status...` ) ; try { let trackers = await getTrackers ( infohash ) ; trackers . splice ( 0 , 3 ) ; let working = trackers . some ( tracker => tracker . status === 2 ) ; if ( ! working ) { logger . info ( 'Need to reannounce. Sending request and sleeping...' ) ; await reannounce ( infohash ) ; await sleep ( SETTINGS . REANNOUNCE_INTERVAL ) ; attempts ++ ; } else { announceOK = true ; logger . info ( 'Tracker is OK. Exiting...' ) ; break ; } } catch ( error ) { logger . error ( 'Caught an error. Exiting...' ) ; process . exit ( 1 ) ; } } if ( announceOK === false ) { logger . info ( `Did not get an OK from tracker even after ${ SETTINGS . REANNOUNCE_LIMIT } attempts. Deleting...` ) ; await deleteTorrents ( [ { hash : infohash } ] ) ; logger . info ( 'Going to resume any paused torrents...' ) ; const torrents = await getTorrents ( ) ; resume ( torrents ) ; } else { const { enabled } = SETTINGS . DISCORD_NOTIFICATIONS || { enabled : false } ; if ( enabled === true ) { try { await sendMessage ( addMessage ( torrent . name , tags , torrent . size , attempts ) ) ; } catch ( error ) { process . exit ( 1 ) ; } } } } ;