Convert indentation to tabs and remove trailing newlines
This commit is contained in:
parent
0405cd07c4
commit
b17eefc617
8 changed files with 297 additions and 298 deletions
|
@ -7,4 +7,4 @@ WORKDIR /home/node/bot
|
|||
|
||||
RUN npm i
|
||||
|
||||
CMD [ "node", "index.js" ]
|
||||
CMD [ "node", "index.js" ]
|
|
@ -1,4 +1,4 @@
|
|||
module.exports = {
|
||||
prefix: `trol`,
|
||||
token: require(`./token`)
|
||||
}
|
||||
prefix: `trol`,
|
||||
token: require(`./token`)
|
||||
}
|
|
@ -5,4 +5,4 @@ services:
|
|||
build: .
|
||||
volumes:
|
||||
- ./token.js:/home/node/bot/token.js
|
||||
- ./config.js:/home/node/bot/config.js
|
||||
- ./config.js:/home/node/bot/config.js
|
130
index.js
130
index.js
|
@ -14,80 +14,80 @@ const client = new Client({ intents: [Intents.FLAGS.GUILD_MESSAGES, Intents.FLAG
|
|||
client.login(config.token);
|
||||
|
||||
if (!fs.existsSync(tempDir))
|
||||
fs.mkdirSync(tempDir);
|
||||
fs.mkdirSync(tempDir);
|
||||
else
|
||||
fs.readdir(tempDir, (err, files) =>
|
||||
{
|
||||
for (const file of files)
|
||||
{
|
||||
const filepath = path.join(tempDir, file);
|
||||
fs.rm(filepath, { recursive: true }, err => { if (err) { throw err; } })
|
||||
}
|
||||
});
|
||||
fs.readdir(tempDir, (err, files) =>
|
||||
{
|
||||
for (const file of files)
|
||||
{
|
||||
const filepath = path.join(tempDir, file);
|
||||
fs.rm(filepath, { recursive: true }, err => { if (err) { throw err; } })
|
||||
}
|
||||
});
|
||||
|
||||
client.once("ready", () =>
|
||||
{
|
||||
console.log("loaded trol bot");
|
||||
console.log("loaded trol bot");
|
||||
});
|
||||
|
||||
client.on("messageCreate", (msg) =>
|
||||
{
|
||||
if (msg.author.bot) return;
|
||||
if (msg.author.bot) return;
|
||||
|
||||
const args = msg.content.split(/ +/);
|
||||
const command = args.shift().toLowerCase();
|
||||
const args = msg.content.split(/ +/);
|
||||
const command = args.shift().toLowerCase();
|
||||
|
||||
if (command == config.prefix)
|
||||
{
|
||||
if (args[0] == "help")
|
||||
{
|
||||
const embed = new MessageEmbed()
|
||||
.setColor("#ffffff")
|
||||
.setTitle(config.prefix + " helpy :^)")
|
||||
.addFields(
|
||||
{ name: "trol", value: "uses attachment (if any)" },
|
||||
{ name: "trol <link>", value: "uses image link" },
|
||||
{ name: "trol me", value: "uses sender's pfp" },
|
||||
{ name: "trol <@mention>", value: "uses mentioned user's pfp" }
|
||||
);
|
||||
msg.channel.send({ embeds: [embed] });
|
||||
}
|
||||
else
|
||||
{
|
||||
var link = args[0];
|
||||
var file = null;
|
||||
if (msg.attachments.size == 1) file = msg.attachments.first().attachment;
|
||||
if (link != null && file == null)
|
||||
{
|
||||
if (link == "me") file = msg.author.avatarURL({ format: "png" });
|
||||
if (msg.mentions.users.size > 0) file = msg.mentions.users.values().next().value.avatarURL({ format: "png" });
|
||||
if (file == null) file = link;
|
||||
}
|
||||
if (command == config.prefix)
|
||||
{
|
||||
if (args[0] == "help")
|
||||
{
|
||||
const embed = new MessageEmbed()
|
||||
.setColor("#ffffff")
|
||||
.setTitle(config.prefix + " helpy :^)")
|
||||
.addFields(
|
||||
{ name: "trol", value: "uses attachment (if any)" },
|
||||
{ name: "trol <link>", value: "uses image link" },
|
||||
{ name: "trol me", value: "uses sender's pfp" },
|
||||
{ name: "trol <@mention>", value: "uses mentioned user's pfp" }
|
||||
);
|
||||
msg.channel.send({ embeds: [embed] });
|
||||
}
|
||||
else
|
||||
{
|
||||
var link = args[0];
|
||||
var file = null;
|
||||
if (msg.attachments.size == 1) file = msg.attachments.first().attachment;
|
||||
if (link != null && file == null)
|
||||
{
|
||||
if (link == "me") file = msg.author.avatarURL({ format: "png" });
|
||||
if (msg.mentions.users.size > 0) file = msg.mentions.users.values().next().value.avatarURL({ format: "png" });
|
||||
if (file == null) file = link;
|
||||
}
|
||||
|
||||
if (file != null)
|
||||
{
|
||||
const downloadDir = path.join(tempDir, "download");
|
||||
if (!fs.existsSync(downloadDir))
|
||||
fs.mkdirSync(downloadDir);
|
||||
if (file != null)
|
||||
{
|
||||
const downloadDir = path.join(tempDir, "download");
|
||||
if (!fs.existsSync(downloadDir))
|
||||
fs.mkdirSync(downloadDir);
|
||||
|
||||
var tempFilePath = path.join(downloadDir, `dl_${Math.floor(Math.random() * 10000).toString().padStart(4, "0")}`);
|
||||
request.head(file, (err, res, body) =>
|
||||
{
|
||||
if (err)
|
||||
{
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
request(file).pipe(fs.createWriteStream(tempFilePath)).on('close', () =>
|
||||
{
|
||||
generateVideo(tempFilePath, 5).then(result =>
|
||||
msg.channel.send({ files: [result] }).then(value =>
|
||||
fs.promises.rm(result)
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
var tempFilePath = path.join(downloadDir, `dl_${Math.floor(Math.random() * 10000).toString().padStart(4, "0")}`);
|
||||
request.head(file, (err, res, body) =>
|
||||
{
|
||||
if (err)
|
||||
{
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
request(file).pipe(fs.createWriteStream(tempFilePath)).on('close', () =>
|
||||
{
|
||||
generateVideo(tempFilePath, 5).then(result =>
|
||||
msg.channel.send({ files: [result] }).then(value =>
|
||||
fs.promises.rm(result)
|
||||
)
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
|
@ -10,16 +10,16 @@ let loadedSounds = [];
|
|||
let offset = 0;
|
||||
for (let p in soundPaths)
|
||||
{
|
||||
const soundPath = path.join(soundDir, soundPaths[p]);
|
||||
if (fs.statSync(soundPath).isDirectory())
|
||||
{
|
||||
offset++;
|
||||
continue;
|
||||
}
|
||||
const soundPath = path.join(soundDir, soundPaths[p]);
|
||||
if (fs.statSync(soundPath).isDirectory())
|
||||
{
|
||||
offset++;
|
||||
continue;
|
||||
}
|
||||
|
||||
let buffer = fs.readFileSync(soundPath);
|
||||
let decoded = wav.decode(buffer);
|
||||
loadedSounds[p - offset] = decoded;
|
||||
let buffer = fs.readFileSync(soundPath);
|
||||
let decoded = wav.decode(buffer);
|
||||
loadedSounds[p - offset] = decoded;
|
||||
}
|
||||
|
||||
// somehow this works
|
||||
|
@ -28,97 +28,97 @@ for (let p in soundPaths)
|
|||
// so i just made sure the sound files were exported with 48000 bytes per second
|
||||
async function mergeBuffers (buffers, playtime = -1)
|
||||
{
|
||||
// for the final length, either use the specified playtime, or the length of the first sound
|
||||
let length = playtime > 0 ? playtime * 48000 : buffers[0].length;
|
||||
let finalBuffer = [];
|
||||
for (let f_nr = 0; f_nr < length; f_nr++)
|
||||
{
|
||||
// literally add all the sound bytes together
|
||||
// yeah, this works??
|
||||
let value = 0;
|
||||
for (let buffer of buffers)
|
||||
if (buffer[f_nr]) value += buffer[f_nr];
|
||||
finalBuffer.push(value);
|
||||
}
|
||||
return Float32Array.from(finalBuffer);
|
||||
// for the final length, either use the specified playtime, or the length of the first sound
|
||||
let length = playtime > 0 ? playtime * 48000 : buffers[0].length;
|
||||
let finalBuffer = [];
|
||||
for (let f_nr = 0; f_nr < length; f_nr++)
|
||||
{
|
||||
// literally add all the sound bytes together
|
||||
// yeah, this works??
|
||||
let value = 0;
|
||||
for (let buffer of buffers)
|
||||
if (buffer[f_nr]) value += buffer[f_nr];
|
||||
finalBuffer.push(value);
|
||||
}
|
||||
return Float32Array.from(finalBuffer);
|
||||
}
|
||||
|
||||
class MemeAudio
|
||||
{
|
||||
constructor()
|
||||
{
|
||||
this.tracks = [];
|
||||
}
|
||||
constructor()
|
||||
{
|
||||
this.tracks = [];
|
||||
}
|
||||
|
||||
playSound (soundId, position = 0, track = -1)
|
||||
{
|
||||
// track not specified, go up one from previous
|
||||
if (track < 0)
|
||||
track = this.tracks.length;
|
||||
playSound (soundId, position = 0, track = -1)
|
||||
{
|
||||
// track not specified, go up one from previous
|
||||
if (track < 0)
|
||||
track = this.tracks.length;
|
||||
|
||||
// track doesn't exist, initialize a new one
|
||||
let stereoTrackBuffer = this.tracks[track];
|
||||
if (!this.tracks[track])
|
||||
stereoTrackBuffer = [[], []];
|
||||
// track doesn't exist, initialize a new one
|
||||
let stereoTrackBuffer = this.tracks[track];
|
||||
if (!this.tracks[track])
|
||||
stereoTrackBuffer = [[], []];
|
||||
|
||||
// get the data of the sound to play
|
||||
let sound = loadedSounds[soundId];
|
||||
for (let ch in stereoTrackBuffer) // should just be left/right audio channels
|
||||
{
|
||||
let loadedChannel = sound.channelData[ch];
|
||||
let byteArray = [];
|
||||
// get the data of the sound to play
|
||||
let sound = loadedSounds[soundId];
|
||||
for (let ch in stereoTrackBuffer) // should just be left/right audio channels
|
||||
{
|
||||
let loadedChannel = sound.channelData[ch];
|
||||
let byteArray = [];
|
||||
|
||||
// add empty space until the sound should play
|
||||
for (let i = 0; i < position * 48000; i++)
|
||||
byteArray[i] = 0;
|
||||
// add empty space until the sound should play
|
||||
for (let i = 0; i < position * 48000; i++)
|
||||
byteArray[i] = 0;
|
||||
|
||||
// copy audio data from sound's channel
|
||||
for (let byte of loadedChannel)
|
||||
byteArray.push(byte);
|
||||
// copy audio data from sound's channel
|
||||
for (let byte of loadedChannel)
|
||||
byteArray.push(byte);
|
||||
|
||||
// convert to Float32array
|
||||
stereoTrackBuffer[ch] = Float32Array.from(byteArray);
|
||||
}
|
||||
// convert to Float32array
|
||||
stereoTrackBuffer[ch] = Float32Array.from(byteArray);
|
||||
}
|
||||
|
||||
// add to timeline
|
||||
this.tracks[track] = stereoTrackBuffer;
|
||||
// add to timeline
|
||||
this.tracks[track] = stereoTrackBuffer;
|
||||
|
||||
return this;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
async encode (duration)
|
||||
{
|
||||
let ac = { sampleRate: 48000, float: true, bitDepth: 32 }; // encoding config
|
||||
async encode (duration)
|
||||
{
|
||||
let ac = { sampleRate: 48000, float: true, bitDepth: 32 }; // encoding config
|
||||
|
||||
// make an array of all left channel audio and all right channel audio
|
||||
let combinedTrack = [[], []];
|
||||
for (let track in this.tracks)
|
||||
{
|
||||
combinedTrack[0].push(this.tracks[track][0]);
|
||||
combinedTrack[1].push(this.tracks[track][1]);
|
||||
}
|
||||
// make an array of all left channel audio and all right channel audio
|
||||
let combinedTrack = [[], []];
|
||||
for (let track in this.tracks)
|
||||
{
|
||||
combinedTrack[0].push(this.tracks[track][0]);
|
||||
combinedTrack[1].push(this.tracks[track][1]);
|
||||
}
|
||||
|
||||
// make a single stereo track
|
||||
let mergedTrack = await Promise.all([mergeBuffers(combinedTrack[0], duration), mergeBuffers(combinedTrack[1], duration)]);
|
||||
// make a single stereo track
|
||||
let mergedTrack = await Promise.all([mergeBuffers(combinedTrack[0], duration), mergeBuffers(combinedTrack[1], duration)]);
|
||||
|
||||
let encoded = wav.encode(mergedTrack, ac);
|
||||
return encoded;
|
||||
}
|
||||
let encoded = wav.encode(mergedTrack, ac);
|
||||
return encoded;
|
||||
}
|
||||
}
|
||||
|
||||
async function generateAudio (seconds)
|
||||
{
|
||||
let audio = new MemeAudio();
|
||||
let pos = 0;
|
||||
while (pos < seconds)
|
||||
{
|
||||
audio.playSound(Math.floor(Math.random() * loadedSounds.length), pos);
|
||||
pos += (Math.random() * 1) - 0.25;
|
||||
}
|
||||
let encoded = await audio.encode(seconds);
|
||||
resultPath = path.join(tempDir, `snd_${Math.floor(Math.random() * 10000).toString().padStart(4, "0")}.wav`);
|
||||
await fs.promises.writeFile(resultPath, encoded);
|
||||
return resultPath;
|
||||
let audio = new MemeAudio();
|
||||
let pos = 0;
|
||||
while (pos < seconds)
|
||||
{
|
||||
audio.playSound(Math.floor(Math.random() * loadedSounds.length), pos);
|
||||
pos += (Math.random() * 1) - 0.25;
|
||||
}
|
||||
let encoded = await audio.encode(seconds);
|
||||
resultPath = path.join(tempDir, `snd_${Math.floor(Math.random() * 10000).toString().padStart(4, "0")}.wav`);
|
||||
await fs.promises.writeFile(resultPath, encoded);
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
module.exports = { generateAudio };
|
|
@ -11,180 +11,179 @@ let images = [];
|
|||
let imgPromises = [];
|
||||
fs.promises.readdir(imagesDir).then(filenames =>
|
||||
{
|
||||
for (var filename of filenames)
|
||||
imgPromises.push(loadImage(path.join(imagesDir, filename)).then(data => images.push(data)));
|
||||
for (var filename of filenames)
|
||||
imgPromises.push(loadImage(path.join(imagesDir, filename)).then(data => images.push(data)));
|
||||
|
||||
Promise.all(imgPromises).then(() => initialized = true);
|
||||
Promise.all(imgPromises).then(() => initialized = true);
|
||||
});
|
||||
|
||||
async function generateFrames (sourceImagePath, duration)
|
||||
{
|
||||
if (!initialized)
|
||||
return null;
|
||||
if (!initialized)
|
||||
return null;
|
||||
|
||||
let outputPath = path.join(tempDir, "frames_" + Math.floor(Math.random() * 10000).toString().padStart(4, "0"));
|
||||
let sourceImage;
|
||||
let outputPath = path.join(tempDir, "frames_" + Math.floor(Math.random() * 10000).toString().padStart(4, "0"));
|
||||
let sourceImage;
|
||||
|
||||
await Promise.all([
|
||||
fs.promises.mkdir(outputPath),
|
||||
loadImage(sourceImagePath).then(data => sourceImage = data)
|
||||
]);
|
||||
await Promise.all([
|
||||
fs.promises.mkdir(outputPath),
|
||||
loadImage(sourceImagePath).then(data => sourceImage = data)
|
||||
]);
|
||||
|
||||
// settings
|
||||
const fps = 20;
|
||||
const res = 256;
|
||||
// settings
|
||||
const fps = 20;
|
||||
const res = 256;
|
||||
|
||||
const totalFrames = fps * duration;
|
||||
const totalFrames = fps * duration;
|
||||
|
||||
// init timeline
|
||||
let objects = [];
|
||||
// init timeline
|
||||
let objects = [];
|
||||
|
||||
// define classes
|
||||
class Object
|
||||
{
|
||||
constructor(arg = {})
|
||||
{
|
||||
this.imageId = arg.imageId || -1;
|
||||
this.spawnFrame = arg.spawnFrame || 0;
|
||||
this.lifetime = fps * duration;
|
||||
this.pos = arg.pos || [0.5, 0.5];
|
||||
this.scale = arg.scale || [1, 1];
|
||||
this.pivot = arg.pivot || [0.5, 0.5];
|
||||
this.rot = arg.rot || 0;
|
||||
this.blink = false;
|
||||
this.sineDur = 0;
|
||||
// define classes
|
||||
class Object
|
||||
{
|
||||
constructor(arg = {})
|
||||
{
|
||||
this.imageId = arg.imageId || -1;
|
||||
this.spawnFrame = arg.spawnFrame || 0;
|
||||
this.lifetime = fps * duration;
|
||||
this.pos = arg.pos || [0.5, 0.5];
|
||||
this.scale = arg.scale || [1, 1];
|
||||
this.pivot = arg.pivot || [0.5, 0.5];
|
||||
this.rot = arg.rot || 0;
|
||||
this.blink = false;
|
||||
this.sineDur = 0;
|
||||
|
||||
this.actions = arg.actions || [];
|
||||
this.actions = arg.actions || [];
|
||||
|
||||
objects.push(this);
|
||||
}
|
||||
}
|
||||
objects.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
class Action
|
||||
{
|
||||
constructor(arg = {})
|
||||
{
|
||||
this.type = arg.type;
|
||||
this.delta = arg.delta;
|
||||
this.start = arg.start || 0;
|
||||
}
|
||||
}
|
||||
class Action
|
||||
{
|
||||
constructor(arg = {})
|
||||
{
|
||||
this.type = arg.type;
|
||||
this.delta = arg.delta;
|
||||
this.start = arg.start || 0;
|
||||
}
|
||||
}
|
||||
|
||||
// generate timeline
|
||||
const base = new Object();
|
||||
if (randomChance(80)) base.actions.push(new Action({ type: "scale", delta: [randomRange(0, 0.1), randomRange(0, 0.05)] }));
|
||||
// generate timeline
|
||||
const base = new Object();
|
||||
if (randomChance(80)) base.actions.push(new Action({ type: "scale", delta: [randomRange(0, 0.1), randomRange(0, 0.05)] }));
|
||||
|
||||
for (i = 0; i < randomRange(2, 12); i++)
|
||||
{
|
||||
const obj = new Object();
|
||||
obj.pos = [Math.random(), Math.random()];
|
||||
const uniformScale = randomRange(0.1, 0.7);
|
||||
obj.scale = [uniformScale + Math.random() * 0.01, uniformScale + Math.random() * 0.01];
|
||||
obj.imageId = Math.floor(Math.random() * images.length);
|
||||
obj.spawnFrame = Math.floor(Math.random() * totalFrames);
|
||||
obj.lifetime = randomRange(fps * 0.25, fps * 3);
|
||||
obj.pivot = [Math.random(), Math.random()];
|
||||
for (i = 0; i < randomRange(2, 12); i++)
|
||||
{
|
||||
const obj = new Object();
|
||||
obj.pos = [Math.random(), Math.random()];
|
||||
const uniformScale = randomRange(0.1, 0.7);
|
||||
obj.scale = [uniformScale + Math.random() * 0.01, uniformScale + Math.random() * 0.01];
|
||||
obj.imageId = Math.floor(Math.random() * images.length);
|
||||
obj.spawnFrame = Math.floor(Math.random() * totalFrames);
|
||||
obj.lifetime = randomRange(fps * 0.25, fps * 3);
|
||||
obj.pivot = [Math.random(), Math.random()];
|
||||
|
||||
if (randomChance(25))
|
||||
obj.actions.push(new Action({ type: "rotate", delta: randomRange(-8, 8) }))
|
||||
if (randomChance(25))
|
||||
obj.actions.push(new Action({ type: "scale", delta: [randomRange(0, 0.05), 0] }))
|
||||
if (randomChance(25))
|
||||
obj.actions.push(new Action({ type: "rotate", delta: randomRange(-8, 8) }))
|
||||
if (randomChance(25))
|
||||
obj.actions.push(new Action({ type: "scale", delta: [randomRange(0, 0.05), 0] }))
|
||||
|
||||
if (randomChance(25))
|
||||
obj.blink = true;
|
||||
else if (randomChance(25))
|
||||
obj.actions.push(new Action({ type: "move", delta: [randomRange(-0.05, 0.05), randomRange(-0.05, 0.05)] }))
|
||||
if (randomChance(25))
|
||||
obj.blink = true;
|
||||
else if (randomChance(25))
|
||||
obj.actions.push(new Action({ type: "move", delta: [randomRange(-0.05, 0.05), randomRange(-0.05, 0.05)] }))
|
||||
|
||||
if (randomChance(75))
|
||||
obj.sineDur = randomRange(1, 5);
|
||||
}
|
||||
if (randomChance(75))
|
||||
obj.sineDur = randomRange(1, 5);
|
||||
}
|
||||
|
||||
// sort by spawnframe
|
||||
objects.sort((a, b) => (a.spawnFrame > b.spawnFrame) ? 1 : -1);
|
||||
// sort by spawnframe
|
||||
objects.sort((a, b) => (a.spawnFrame > b.spawnFrame) ? 1 : -1);
|
||||
|
||||
// render frames
|
||||
let framePromises = [];
|
||||
for (var _f = 0; _f < totalFrames; _f++)
|
||||
{
|
||||
const f = _f;
|
||||
framePromises.push(async () =>
|
||||
{
|
||||
const canvas = createCanvas(res, res);
|
||||
const ctx = canvas.getContext("2d");
|
||||
// render frames
|
||||
let framePromises = [];
|
||||
for (var _f = 0; _f < totalFrames; _f++)
|
||||
{
|
||||
const f = _f;
|
||||
framePromises.push(async () =>
|
||||
{
|
||||
const canvas = createCanvas(res, res);
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
// draw objects
|
||||
for (var object of objects)
|
||||
{
|
||||
var life = f - object.spawnFrame; // frames passed since init
|
||||
if (life < 0) continue;
|
||||
if (life > object.lifetime) continue;
|
||||
if (object.blink && life % 2 == 1) continue;
|
||||
// draw objects
|
||||
for (var object of objects)
|
||||
{
|
||||
var life = f - object.spawnFrame; // frames passed since init
|
||||
if (life < 0) continue;
|
||||
if (life > object.lifetime) continue;
|
||||
if (object.blink && life % 2 == 1) continue;
|
||||
|
||||
var pos = object.pos;
|
||||
var rot = object.rot;
|
||||
var scale = object.scale;
|
||||
var image = object.imageId == -1 ? sourceImage : images[object.imageId];
|
||||
var pos = object.pos;
|
||||
var rot = object.rot;
|
||||
var scale = object.scale;
|
||||
var image = object.imageId == -1 ? sourceImage : images[object.imageId];
|
||||
|
||||
// process actions
|
||||
for (var action of object.actions)
|
||||
{
|
||||
if (f < object.spawnFrame + action.start + 1 || ((action.dur > 0) && (f > object.spawnFrame + action.start + action.dur))) continue; // ignore
|
||||
const progress = object.sineDur > 0 ? 10 * Math.sin(life * object.sineDur) : life;
|
||||
switch (action.type)
|
||||
{
|
||||
case "move":
|
||||
pos = [object.pos[0] + action.delta[0] * progress, object.pos[1] + action.delta[1] * progress];
|
||||
break;
|
||||
// process actions
|
||||
for (var action of object.actions)
|
||||
{
|
||||
if (f < object.spawnFrame + action.start + 1 || ((action.dur > 0) && (f > object.spawnFrame + action.start + action.dur))) continue; // ignore
|
||||
const progress = object.sineDur > 0 ? 10 * Math.sin(life * object.sineDur) : life;
|
||||
switch (action.type)
|
||||
{
|
||||
case "move":
|
||||
pos = [object.pos[0] + action.delta[0] * progress, object.pos[1] + action.delta[1] * progress];
|
||||
break;
|
||||
|
||||
case "scale":
|
||||
scale = [object.scale[0] + action.delta[0] * progress, object.scale[1] + action.delta[1] * progress];
|
||||
break;
|
||||
case "scale":
|
||||
scale = [object.scale[0] + action.delta[0] * progress, object.scale[1] + action.delta[1] * progress];
|
||||
break;
|
||||
|
||||
case "rotate":
|
||||
rot = object.rot + action.delta * life;
|
||||
break;
|
||||
}
|
||||
}
|
||||
case "rotate":
|
||||
rot = object.rot + action.delta * life;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var size = [scale[0] * res, scale[1] * res]; // size in pixels
|
||||
var cpos = [pos[0] * res, pos[1] * res]; // center pos
|
||||
var blpos = [cpos[0] - size[0] * object.pivot[0], cpos[1] - size[1] * object.pivot[1]] // bottom left pos
|
||||
var size = [scale[0] * res, scale[1] * res]; // size in pixels
|
||||
var cpos = [pos[0] * res, pos[1] * res]; // center pos
|
||||
var blpos = [cpos[0] - size[0] * object.pivot[0], cpos[1] - size[1] * object.pivot[1]] // bottom left pos
|
||||
|
||||
// save base canvas transform
|
||||
ctx.save();
|
||||
// save base canvas transform
|
||||
ctx.save();
|
||||
|
||||
// rotate canvas to match object rotation
|
||||
ctx.translate(cpos[0], cpos[1]);
|
||||
ctx.rotate(rot * Math.PI / 180);
|
||||
ctx.translate(-cpos[0], -cpos[1]);
|
||||
// rotate canvas to match object rotation
|
||||
ctx.translate(cpos[0], cpos[1]);
|
||||
ctx.rotate(rot * Math.PI / 180);
|
||||
ctx.translate(-cpos[0], -cpos[1]);
|
||||
|
||||
// draw
|
||||
ctx.drawImage(image, blpos[0], blpos[1], size[0], size[1])
|
||||
// draw
|
||||
ctx.drawImage(image, blpos[0], blpos[1], size[0], size[1])
|
||||
|
||||
// restore transform
|
||||
ctx.restore();
|
||||
// restore transform
|
||||
ctx.restore();
|
||||
|
||||
// save the frame
|
||||
const buffer = canvas.toBuffer("image/png");
|
||||
await fs.promises.writeFile(path.join(outputPath, `${f}.png"`), buffer);
|
||||
}
|
||||
});
|
||||
}
|
||||
// save the frame
|
||||
const buffer = canvas.toBuffer("image/png");
|
||||
await fs.promises.writeFile(path.join(outputPath, `${f}.png"`), buffer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await Promise.all(framePromises.map(fn => fn()));
|
||||
await Promise.all(framePromises.map(fn => fn()));
|
||||
|
||||
return outputPath;
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
function randomRange (x, y)
|
||||
{
|
||||
return Math.random() * (y - x) + x;
|
||||
return Math.random() * (y - x) + x;
|
||||
}
|
||||
|
||||
function randomChance (percent)
|
||||
{
|
||||
return (Math.random() * 100) <= percent;
|
||||
return (Math.random() * 100) <= percent;
|
||||
}
|
||||
|
||||
module.exports = { generateFrames };
|
||||
|
||||
module.exports = { generateFrames };
|
28
shitpost.js
28
shitpost.js
|
@ -5,25 +5,25 @@ const fs = require("fs");
|
|||
|
||||
async function generateVideo (sourceImg, duration)
|
||||
{
|
||||
let [framesPath, audioPath] = await Promise.all([
|
||||
generateFrames(sourceImg, duration),
|
||||
generateAudio(duration)
|
||||
]);
|
||||
let [framesPath, audioPath] = await Promise.all([
|
||||
generateFrames(sourceImg, duration),
|
||||
generateAudio(duration)
|
||||
]);
|
||||
|
||||
const outputPath = `./temp/output_${Math.floor(Math.random() * 10000).toString().padStart(4, "0")}.mp4`;
|
||||
const outputPath = `./temp/output_${Math.floor(Math.random() * 10000).toString().padStart(4, "0")}.mp4`;
|
||||
|
||||
const child = spawn(`ffmpeg -i ${audioPath} -r 20 -i ${framesPath}/%d.png -c:v libx264 -vf fps=20 -pix_fmt yuv420p ${outputPath}`, { shell: true })
|
||||
child.on("exit", (code) => { finished = true; });
|
||||
const child = spawn(`ffmpeg -i ${audioPath} -r 20 -i ${framesPath}/%d.png -c:v libx264 -vf fps=20 -pix_fmt yuv420p ${outputPath}`, { shell: true })
|
||||
child.on("exit", (code) => { finished = true; });
|
||||
|
||||
let finished = false;
|
||||
while (!finished) await new Promise(resolve => setTimeout(resolve, 10));
|
||||
let finished = false;
|
||||
while (!finished) await new Promise(resolve => setTimeout(resolve, 10));
|
||||
|
||||
// delete temp files
|
||||
fs.promises.rm(framesPath, { recursive: true });
|
||||
fs.promises.rm(audioPath);
|
||||
fs.promises.rm(sourceImg);
|
||||
// delete temp files
|
||||
fs.promises.rm(framesPath, { recursive: true });
|
||||
fs.promises.rm(audioPath);
|
||||
fs.promises.rm(sourceImg);
|
||||
|
||||
return outputPath;
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
module.exports = { generateVideo };
|
2
token.js
2
token.js
|
@ -1 +1 @@
|
|||
module.exports = `your.bot.token`;
|
||||
module.exports = `your.bot.token`;
|
Reference in a new issue