2019-10-27 22:32:30 +01:00
const { Command } = require ( 'discord-akairo' ) ;
2020-08-25 17:21:26 +02:00
const { proxy } = require ( '../../config.json' ) ;
2019-10-27 22:32:30 +01:00
const YTPGenerator = require ( 'ytpplus-node' ) ;
const os = require ( 'os' ) ;
const fs = require ( 'fs' ) ;
2020-07-16 09:22:17 +02:00
const attachment = require ( '../../utils/attachment' ) ;
2020-06-17 18:42:52 +02:00
const downloader = require ( '../../utils/download' ) ;
2020-05-13 08:47:11 +02:00
const md5File = require ( 'md5-file' ) ;
const ytpHash = require ( '../../models' ) . ytpHash ;
2021-01-15 17:43:38 +01:00
const { ytpChannel } = require ( '../../config.json' ) ;
2021-01-16 09:00:59 +01:00
const ytpblacklist = require ( '../../models' ) . ytpblacklist ;
2020-05-13 08:47:11 +02:00
2020-05-03 19:23:54 +02:00
const MAX _CLIPS = 20 ;
2019-10-27 22:32:30 +01:00
class ytpCommand extends Command {
constructor ( ) {
super ( 'ytp' , {
aliases : [ 'ytp' , 'ytpplus' , 'ytp+' ] ,
category : 'fun' ,
2019-11-09 14:17:29 +01:00
clientPermissions : [ 'ATTACH_FILES' , 'SEND_MESSAGES' ] ,
2019-10-27 22:32:30 +01:00
args : [
{
id : 'add' ,
match : 'flag' ,
flag : [ '--add' ]
} ,
2019-10-27 23:18:09 +01:00
{
id : 'pool' ,
match : 'flag' ,
flag : [ '--pool' ]
} ,
2019-10-27 23:50:33 +01:00
{
id : 'force' ,
match : 'flag' ,
flag : [ '--force' ]
} ,
2019-12-10 22:33:52 +01:00
{
id : 'randomSound' ,
match : 'flag' ,
flag : [ '--randomSound' ]
} ,
{
id : 'randomSoundMute' ,
match : 'flag' ,
flag : [ '--randomSoundMute' ]
} ,
{
id : 'reverse' ,
match : 'flag' ,
flag : [ '--reverse' ]
} ,
{
id : 'chorus' ,
match : 'flag' ,
flag : [ '--chorus' ]
} ,
{
id : 'vibrato' ,
match : 'flag' ,
flag : [ '--vibrato' ]
} ,
{
id : 'highPitch' ,
match : 'flag' ,
flag : [ '--highPitch' ]
} ,
{
id : 'lowPitch' ,
match : 'flag' ,
flag : [ '--lowPitch' ]
} ,
{
id : 'speedUp' ,
match : 'flag' ,
flag : [ '--speedUp' ]
} ,
{
id : 'slowDown' ,
match : 'flag' ,
flag : [ '--slowDown' ]
} ,
{
id : 'dance' ,
match : 'flag' ,
flag : [ '--dance' ]
} ,
{
id : 'squidward' ,
match : 'flag' ,
flag : [ '--squidward' ]
} ,
2020-05-11 00:47:15 +02:00
{
id : 'how' ,
match : 'flag' ,
flag : [ '--how' ]
} ,
2019-12-10 22:38:51 +01:00
{
id : 'debug' ,
match : 'flag' ,
flag : [ '--debug' ]
} ,
2019-10-27 22:32:30 +01:00
{
id : 'link' ,
2020-07-16 09:22:17 +02:00
type : 'url' ,
prompt : {
start : 'Please send the URL of which video you want to download. Say `cancel` to stop the command' ,
retry : 'Please send a valid URL of the video you want to download. Say `cancel` to stop the command' ,
optional : true ,
} ,
unordered : true
2020-05-24 19:17:40 +02:00
} ,
{
id : 'max' ,
2020-07-16 09:22:17 +02:00
type : 'string' ,
unordered : true
2020-08-25 17:21:26 +02:00
} ,
{
id : 'proxy' ,
match : 'option' ,
flag : [ '--proxy' ] ,
} ,
{
id : 'listproxy' ,
match : 'flag' ,
flag : [ '--listproxy' , '--proxylist' ]
2019-10-27 22:32:30 +01:00
}
] ,
description : {
2020-09-06 22:53:17 +02:00
content : 'Generate random ytp\n--add with a link or attachment to add a video to the pool, only .mp4 work\n--pool to see how many vid there is currently in the pool\n--force to make the command work outside of nsfw channel BE AWARE THAT IT WON\'T CHANGE THE FINAL RESULT SO NSFW CAN STILL HAPPEN\n`--proxy #` to select a proxy, `--listproxy` to see a list of proxy' ,
2020-05-24 19:17:40 +02:00
usage : '(OPTIONAL) | [Minimum length of clip] [Max length of clip]' ,
2020-08-25 17:21:26 +02:00
examples : [ '5 10' , '--add https://www.youtube.com/watch?v=6n3pFFPSlW4' , '--add https://www.youtube.com/watch?v=6n3pFFPSlW4 --proxy 1' , '--listproxy' ]
2019-10-27 22:32:30 +01:00
}
} ) ;
}
async exec ( message , args ) {
2019-10-27 23:18:09 +01:00
if ( args . pool ) {
2019-11-09 14:17:29 +01:00
let mp4 = [ ] ;
fs . readdirSync ( './asset/ytp/userVid/' ) . forEach ( file => {
if ( file . endsWith ( 'mp4' ) ) {
mp4 . push ( file ) ;
}
} ) ;
2019-12-10 20:06:58 +01:00
return message . channel . send ( ` There is currently ${ mp4 . length } videos, you can add yours by doing \` \` ${ this . client . commandHandler . prefix [ 0 ] } ytp --add (link or attachment) \` \` ` ) ;
2019-10-27 23:18:09 +01:00
}
2020-08-25 17:21:26 +02:00
if ( args . listproxy ) {
let proxys = [ ] ;
let i = 0 ;
proxy . forEach ( proxy => {
i ++ ;
proxys . push ( ` [ ${ i } ] ${ proxy . hideip ? '[IP HIDDEN]' : proxy . ip . substring ( 0 , proxy . ip . length - 5 ) } - ${ proxy . country } ` ) ;
} ) ;
const Embed = this . client . util . embed ( )
. setColor ( message . member ? message . member . displayHexColor : 'NAVY' )
. setTitle ( 'List of available proxy' )
. setDescription ( proxys . join ( '\n' ) )
. setFooter ( 'You can help me get more proxy by either donating to me or providing a proxy for me' ) ;
return message . channel . send ( Embed ) ;
}
2019-10-27 22:32:30 +01:00
if ( args . add ) {
2021-01-16 09:00:59 +01:00
const blacklist = await ytpblacklist . findOne ( { where : { userID : message . author . id } } ) ;
if ( blacklist ) {
return message . channel . send ( ` You have been blacklisted for the following reasons: \` ${ blacklist . get ( 'reason' ) } \` be less naughty next time. ` ) ;
}
2020-09-14 15:37:28 +02:00
if ( args . proxy && ! args . proxyAuto ) { // args.proxyAuto is only provided when the command is run after a error 429
2020-08-25 17:21:26 +02:00
args . proxy = args . proxy - 1 ;
if ( ! proxy [ args . proxy ] ) args . proxy = 0 ;
}
2019-10-27 22:32:30 +01:00
let loadingmsg = await message . channel . send ( 'Downloading <a:loadingmin:527579785212329984>' ) ;
2020-07-16 09:22:17 +02:00
let url ;
if ( args . link )
url = args . link . href ;
else
url = await attachment ( message ) ;
2020-05-13 14:12:33 +02:00
2019-10-27 22:32:30 +01:00
if ( url ) {
2020-08-26 19:21:59 +02:00
let options = [ '--format=mp4' ] ;
if ( args . proxy ) {
options . push ( '--proxy' ) ;
options . push ( proxy [ args . proxy ] . ip ) ;
}
return downloader ( url , options , ` ./asset/ytp/userVid/ ${ message . id } .mp4 ` )
2020-07-11 01:33:12 +02:00
. on ( 'error' , ( err ) => {
2020-09-14 15:37:28 +02:00
if ( err . includes ( 'HTTP Error 429: Too Many Requests' ) ) {
if ( args . proxy != null ) {
args . proxy = args . proxy + 1 ;
} else {
args . proxy = 0 ;
args . proxyAuto = true ;
}
if ( ! proxy [ args . proxy ] ) return message . channel . send ( '`HTTP Error 429: Too Many Requests.`\nThe website you tried to download from probably has the bot blocked along with its proxy' ) ;
loadingmsg . delete ( ) ;
2020-09-14 15:39:27 +02:00
return this . client . commandHandler . runCommand ( message , this . client . commandHandler . findCommand ( 'ytp' ) , args ) ;
2020-09-14 15:37:28 +02:00
}
if ( err . includes ( 'Error: status code 403' ) ) return message . channel . send ( '`HTTP Error 403: Forbidden.`\nThe video you tried to download is not publicly available therefor the bot can\'t download it.' ) ;
2020-06-17 18:42:52 +02:00
return message . channel . send ( err , { code : true } ) ;
2020-09-14 15:37:28 +02:00
2020-06-17 18:42:52 +02:00
} )
2020-07-11 01:33:12 +02:00
. on ( 'end' , async output => {
2020-06-17 18:42:52 +02:00
const hash = md5File . sync ( output ) ;
2020-05-13 08:47:11 +02:00
const ytphash = await ytpHash . findOne ( { where : { hash : hash } } ) ;
if ( ytphash ) {
2020-06-17 18:42:52 +02:00
fs . unlinkSync ( output ) ;
2020-05-13 14:12:33 +02:00
loadingmsg . delete ( ) ;
2020-05-13 08:47:11 +02:00
return message . reply ( 'This video is a duplicate... Not adding.' ) ;
} else {
2020-08-03 11:07:14 +02:00
let file = fs . statSync ( output ) ;
let fileSize = file . size / 1000000.0 ;
if ( fileSize > 50 ) {
fs . unlinkSync ( output ) ;
loadingmsg . delete ( ) ;
return message . reply ( 'Video too big.. Not adding.' ) ;
}
2021-01-15 17:43:38 +01:00
const body = { hash : hash , messageID : message . id } ;
2020-05-13 08:47:11 +02:00
await ytpHash . create ( body ) ;
}
2020-03-29 03:04:21 +02:00
2019-11-09 14:17:29 +01:00
let mp4 = [ ] ;
fs . readdirSync ( './asset/ytp/userVid/' ) . forEach ( file => {
if ( file . endsWith ( 'mp4' ) ) {
mp4 . push ( file ) ;
}
} ) ;
2021-01-15 17:43:38 +01:00
// (Hopefully) limit video to 2k
if ( mp4 . length > 2000 ) {
let file = mp4 . sort ( ( a , b ) => {
let time1 = fs . statSync ( ` ./asset/ytp/userVid/ ${ b } ` ) . ctime ;
let time2 = fs . statSync ( ` ./asset/ytp/userVid/ ${ a } ` ) . ctime ;
if ( time1 < time2 ) return 1 ;
if ( time1 > time2 ) return - 1 ;
return 0 ;
} ) . slice ( 0 , 1 ) ;
console . log ( file ) ;
fs . unlinkSync ( ` ./asset/ytp/userVid/ ${ file [ 0 ] } ` ) ;
}
2019-10-27 22:51:38 +01:00
loadingmsg . delete ( ) ;
2021-01-15 17:43:38 +01:00
message . reply ( ` Video successfully added to the pool! There is now ${ mp4 . length } videos ` ) ;
const Embed = this . client . util . embed ( )
. setAuthor ( message . author . username , message . author . displayAvatarURL ( ) )
. addField ( 'Channel ID' , message . channel . id , true )
. addField ( 'Messsage ID' , message . id , true )
. addField ( 'Author' , ` ${ message . author . username } ( ${ message . author . id } ) ` , true )
. setTimestamp ( ) ;
if ( message . guild ) {
Embed . addField ( 'Guild' , ` ${ message . guild . name } ( ${ message . guild . id } ) ` , true ) ;
Embed . addField ( 'Message link' , ` https://discord.com/channels/ ${ message . guild . id } / ${ message . channel . id } / ${ message . id } ` ) ;
} else {
Embed . addField ( 'Message link' , ` https://discord.com/channels/@me/ ${ message . channel . id } / ${ message . id } ` ) ;
}
let channel = this . client . channels . resolve ( ytpChannel ) ;
return channel . send ( url , { embed : Embed } ) ;
2020-06-17 18:42:52 +02:00
} ) ;
2019-10-27 22:32:30 +01:00
} else {
2019-10-27 22:51:38 +01:00
loadingmsg . delete ( ) ;
2019-10-27 22:32:30 +01:00
return message . channel . send ( 'You need a valid video link!' ) ;
}
2020-05-13 14:12:33 +02:00
}
2019-10-27 22:32:30 +01:00
2019-11-09 14:17:29 +01:00
2019-12-22 15:52:11 +01:00
if ( ! message . channel . nsfw && ! args . force ) return message . channel . send ( ` Please execute this command in an NSFW channel ( Content might not be NSFW but since the video are user submitted better safe than sorry ) OR do \` \` ${ this . client . commandHandler . prefix [ 0 ] } ytp --force \` \` to make the command work outside of nsfw channel BE AWARE THAT IT WON'T CHANGE THE FINAL RESULT SO NSFW CAN STILL HAPPEN ` ) ;
2019-10-27 22:32:30 +01:00
2019-11-09 14:17:29 +01:00
// Read userVid folder and select random vid and only take .mp4
let mp4 = [ ] ;
2019-10-27 22:32:30 +01:00
let asset = [ ] ;
2019-11-09 14:17:29 +01:00
// Count number of total vid
2020-07-19 11:56:33 +02:00
fs . readdirSync ( './asset/ytp/userVid/' ) . forEach ( file => {
2019-11-09 14:17:29 +01:00
if ( file . endsWith ( 'mp4' ) ) {
mp4 . push ( file ) ;
}
} ) ;
2020-07-19 11:56:33 +02:00
2019-11-09 14:17:29 +01:00
// Select random vid depending on the amount of MAX_CLIPS
for ( let i = 0 ; i < MAX _CLIPS ; i ++ ) {
2020-07-19 11:56:33 +02:00
let random = Math . floor ( Math . random ( ) * mp4 . length ) ;
let vid = ` ./asset/ytp/userVid/ ${ mp4 [ random ] } ` ;
if ( mp4 [ random ] . endsWith ( 'mp4' ) ) {
2019-11-09 14:17:29 +01:00
if ( ! asset . includes ( vid ) ) {
asset . push ( vid ) ;
2019-10-27 22:32:30 +01:00
}
2019-11-09 14:17:29 +01:00
}
}
2019-10-28 02:47:08 +01:00
2020-06-15 17:56:51 +02:00
let loadingmsg = await message . channel . send ( ` Processing, this can take a ***long*** time, i'll ping you when i finished <a:loadingmin:527579785212329984> \n Some info: There are currently ${ mp4 . length } videos, you can add yours by doing \` \` ${ this . client . commandHandler . prefix [ 0 ] } ytp --add (link or attachment). Thanks for contributing! \` \` ` ) ;
2019-11-09 14:17:29 +01:00
2020-05-13 14:12:33 +02:00
let options = {
2019-12-10 22:38:51 +01:00
debug : args . debug ,
2020-05-24 19:17:40 +02:00
MIN _STREAM _DURATION : args . link ? Math . floor ( args . link ) : null ,
2020-05-24 19:26:07 +02:00
MAX _STREAM _DURATION : args . link && args . max ? args . max : Math . floor ( ( Math . random ( ) * 3 ) + 1 ) , // Random duration of video clip
2019-11-09 14:17:29 +01:00
sources : './asset/ytp/sources/' ,
sounds : './asset/ytp/sounds/' ,
music : './asset/ytp/music/' ,
resources : './asset/ytp/resources/' ,
temp : os . tmpdir ( ) ,
sourceList : asset ,
2020-04-29 19:38:26 +02:00
intro : args . force ? './asset/ytp/intro.mp4' : null ,
2020-05-11 00:47:15 +02:00
outro : './asset/ytp/outro.mp4' ,
2019-11-09 14:17:29 +01:00
OUTPUT _FILE : ` ${ os . tmpdir ( ) } / ${ message . id } _YTP.mp4 ` ,
MAX _CLIPS : MAX _CLIPS ,
transitions : true ,
2020-04-18 18:23:53 +02:00
showFileNames : true ,
2020-05-13 14:12:33 +02:00
effects : {
2019-12-10 22:33:52 +01:00
effect _RandomSound : ! args . randomSound ,
effect _RandomSoundMute : ! args . randomSoundMute ,
effect _Reverse : ! args . reverse ,
effect _Chorus : ! args . chorus ,
effect _Vibrato : ! args . vibrato ,
effect _HighPitch : ! args . highPitch ,
effect _LowPitch : ! args . lowPitch ,
effect _SpeedUp : ! args . speedUp ,
effect _SlowDown : ! args . slowDown ,
effect _Dance : ! args . dance ,
2020-05-11 00:47:15 +02:00
effect _Squidward : ! args . squidward ,
effect _How : ! args . how
2019-11-09 14:17:29 +01:00
}
} ;
2020-05-13 14:12:33 +02:00
2019-11-09 14:17:29 +01:00
new YTPGenerator ( ) . configurateAndGo ( options )
. then ( ( ) => {
2020-05-13 08:47:11 +02:00
md5File ( ` ${ os . tmpdir ( ) } / ${ message . id } _YTP.mp4 ` ) . then ( async hash => {
2021-01-15 17:43:38 +01:00
const body = { hash : hash , messageID : message . id } ;
2020-05-13 08:47:11 +02:00
await ytpHash . create ( body ) ;
} ) ;
2019-11-09 14:17:29 +01:00
loadingmsg . delete ( ) ;
2020-06-15 17:56:51 +02:00
return message . reply ( 'Here is your YTP! Remember, it might contain nsfw, so be careful!' , { files : [ ` ${ os . tmpdir ( ) } / ${ message . id } _YTP.mp4 ` ] } )
2020-04-18 18:23:53 +02:00
. catch ( err => {
console . error ( err ) ;
2019-11-09 14:17:29 +01:00
return message . channel . send ( 'Whoops, look like the vid might be too big for discord, my bad, please try again' ) ;
} ) ;
} )
. catch ( err => {
console . error ( err ) ;
loadingmsg . delete ( ) ;
2020-09-18 16:40:06 +02:00
if ( ! args . retry )
args . retry = 0 ;
else
args . retry += 1 ;
if ( args . retry === 3 ) {
return message . reply ( { files : [ Math . random ( ) < 0.5 ? './asset/ytp/error1.mp4' : './asset/ytp/error2.mp4' ] } )
. catch ( err => { // In case it can't send the video for some reason
console . error ( err ) ;
return message . channel . send ( 'Oh no, an error has occurred! please try again. If this happens alot, you should report this to the developers.' ) ;
} ) ;
}
return this . client . commandHandler . runCommand ( message , this . client . commandHandler . findCommand ( 'ytp' ) , args ) ;
2019-11-09 14:17:29 +01:00
} ) ;
2019-10-27 22:32:30 +01:00
}
}
2020-04-28 22:57:38 +02:00
module . exports = ytpCommand ;