195 lines
7.9 KiB
JavaScript
195 lines
7.9 KiB
JavaScript
|
import { SlashCommandBuilder } from '@discordjs/builders';
|
|||
|
import { MessageEmbed } from 'discord.js';
|
|||
|
import Twit from 'twit';
|
|||
|
import fetch from 'node-fetch';
|
|||
|
import os from 'node:os';
|
|||
|
import fs from 'node:fs';
|
|||
|
|
|||
|
import db from '../../models/index.js';
|
|||
|
import wordToCensor from '../../json/censor.json' assert {type: 'json'};;
|
|||
|
import dotenv from 'dotenv';
|
|||
|
dotenv.config();
|
|||
|
const { twiConsumer, twiConsumerSecret, twiToken, twiTokenSecret, twiChannel, twiLogChannel } = process.env;
|
|||
|
|
|||
|
const Blacklists = db.Blacklists;
|
|||
|
|
|||
|
export default {
|
|||
|
data: new SlashCommandBuilder()
|
|||
|
.setName('tweet')
|
|||
|
.setDescription('Send tweet from Haha yes twitter account. Please do not use it for advertisement and keep it english')
|
|||
|
.addStringOption(option =>
|
|||
|
option.setName('content')
|
|||
|
.setDescription('The content of the tweet you want to send me.')
|
|||
|
.setRequired(false))
|
|||
|
.addAttachmentOption(option =>
|
|||
|
option.setName('image')
|
|||
|
.setDescription('Optional attachment (Image only.)')
|
|||
|
.setRequired(false)),
|
|||
|
async execute(interaction) {
|
|||
|
await interaction.deferReply({ ephemeral: false });
|
|||
|
const client = interaction.client;
|
|||
|
let tweet = interaction.options.getString('content');
|
|||
|
const attachment = interaction.options.getAttachment('image');
|
|||
|
const date = new Date();
|
|||
|
// If account is less than 6 months old don't accept the tweet ( alt prevention )
|
|||
|
if (interaction.user.createdAt > date.setMonth(date.getMonth() - 6)) {
|
|||
|
await interaction.editReply({ content: 'Your account is too new to be able to use this command!' });
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// If account is less than 1 year old don't accept attachment
|
|||
|
if (attachment && interaction.user.createdAt > date.setFullYear(date.getFullYear() - 1)) {
|
|||
|
await interaction.editReply({ content: 'Your account need to be 1 year or older to be able to send attachment!' });
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// remove zero width space
|
|||
|
if (tweet) {
|
|||
|
tweet = tweet.replace('', '');
|
|||
|
}
|
|||
|
|
|||
|
if (tweet) {
|
|||
|
// Detect banned word (Blacklist the user directly)
|
|||
|
if (wordToCensor.includes(tweet) || wordToCensor.includes(tweet.substr(0, tweet.length - 1)) || wordToCensor.includes(tweet.substr(1, tweet.length))) {
|
|||
|
const body = { type:'tweet', uid: interaction.user.id, reason: 'Automatic ban from banned word.' };
|
|||
|
Blacklists.create(body);
|
|||
|
|
|||
|
await interaction.editReply({ content: 'Sike, you just posted cringe! Enjoy the blacklist :)' });
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// Very simple link detection
|
|||
|
if (new RegExp('([a-zA-Z0-9]+://)?([a-zA-Z0-9_]+:[a-zA-Z0-9_]+@)?([a-zA-Z0-9.-]+\\.[A-Za-z]{2,4})(:[0-9]+)?(/.*)?').test(tweet) && !tweet.includes('twitter.com')) {
|
|||
|
await interaction.editReply({ content: 'You may not tweet links outside of twitter.com' });
|
|||
|
return;
|
|||
|
}
|
|||
|
// Do not allow discord invites
|
|||
|
if (tweet.includes('discord.gg') || tweet.includes('discord.com/invite/')) {
|
|||
|
await interaction.editReply({ content: 'No discord invite allowed.' });
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
const T = new Twit({
|
|||
|
consumer_key: twiConsumer,
|
|||
|
consumer_secret: twiConsumerSecret,
|
|||
|
access_token: twiToken,
|
|||
|
access_token_secret: twiTokenSecret,
|
|||
|
});
|
|||
|
|
|||
|
try {
|
|||
|
// Make sure there is an attachment and if its an image
|
|||
|
if (attachment) {
|
|||
|
if (attachment.name.toLowerCase().endsWith('.jpg') || attachment.name.toLowerCase().endsWith('.png') || attachment.name.toLowerCase().endsWith('.gif')) {
|
|||
|
fetch(attachment.url)
|
|||
|
.then(res => {
|
|||
|
const dest = fs.createWriteStream(`${os.tmpdir()}/${attachment.name}`);
|
|||
|
res.body.pipe(dest);
|
|||
|
dest.on('finish', () => {
|
|||
|
const file = fs.statSync(`${os.tmpdir()}/${attachment.name}`);
|
|||
|
const fileSize = file.size / 1000000.0;
|
|||
|
|
|||
|
if ((attachment.name.toLowerCase().endsWith('.jpg') || attachment.name.toLowerCase().endsWith('.png')) && fileSize > 5) {
|
|||
|
return interaction.editReply({ content: 'Images can\'t be larger than 5 MB!' });
|
|||
|
}
|
|||
|
else if (attachment.name.toLowerCase().endsWith('.gif') && fileSize > 15) {
|
|||
|
return interaction.editReply({ content: 'Gifs can\'t be larger than 15 MB!' });
|
|||
|
}
|
|||
|
|
|||
|
const b64Image = fs.readFileSync(`${os.tmpdir()}/${attachment.name}`, { encoding: 'base64' });
|
|||
|
T.post('media/upload', { media_data: b64Image }, function(err, data) {
|
|||
|
if (err) {
|
|||
|
console.log('OH NO AN ERROR!!!!!!!');
|
|||
|
console.error(err);
|
|||
|
return interaction.editReply({ content: 'OH NO!!! AN ERROR HAS occurred!!! please hold on while i find what\'s causing this issue! ' });
|
|||
|
}
|
|||
|
else {
|
|||
|
Tweet(data);
|
|||
|
}
|
|||
|
});
|
|||
|
});
|
|||
|
});
|
|||
|
}
|
|||
|
else {
|
|||
|
await interaction.editReply({ content: 'File type not supported, you can only send jpg/png/gif' });
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
Tweet();
|
|||
|
}
|
|||
|
}
|
|||
|
catch (err) {
|
|||
|
console.error(err);
|
|||
|
await interaction.editReply({ content: 'Oh no, an error has occurred :(' });
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
function Tweet(data) {
|
|||
|
let options = {
|
|||
|
status: tweet,
|
|||
|
};
|
|||
|
|
|||
|
if (data && tweet) {
|
|||
|
options = {
|
|||
|
status: tweet,
|
|||
|
media_ids: new Array(data.media_id_string),
|
|||
|
};
|
|||
|
}
|
|||
|
else if (data) {
|
|||
|
options = {
|
|||
|
media_ids: new Array(data.media_id_string),
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
T.post('statuses/update', options, function(err, response) {
|
|||
|
if (err) {
|
|||
|
// Rate limit exceeded
|
|||
|
if (err.code == 88) return interaction.editReply({ content: err.interaction });
|
|||
|
// Tweet needs to be a bit shorter.
|
|||
|
if (err.code == 186) return interaction.editReply({ content: `${err.interaction} Your interaction was ${tweet.length} characters, you need to remove ${tweet.length - 280} characters (This count may be inaccurate if your interaction contained link)` });
|
|||
|
// Status is a duplicate.
|
|||
|
if (err.code == 187) return interaction.editReply({ content: err.interaction });
|
|||
|
// To protect our users from spam and other malicious activity, this account is temporarily locked.
|
|||
|
if (err.code == 326) return interaction.editReply({ content: err.interaction });
|
|||
|
console.error('OH NO!!!!');
|
|||
|
console.error(err);
|
|||
|
return interaction.editReply({ content: 'OH NO!!! AN ERROR HAS occurred!!! please hold on while i find what\'s causing this issue!' });
|
|||
|
}
|
|||
|
|
|||
|
const tweetid = response.id_str;
|
|||
|
const FunnyWords = ['oppaGangnamStyle', '69', '420', 'cum', 'funnyMan', 'GUCCISmartToilet', 'TwitterForClowns', 'fart', 'mcDotnamejeffDotxyz', 'ok', 'hi', 'howAreYou', 'WhatsNinePlusTen', '21'];
|
|||
|
const TweetLink = `https://twitter.com/${FunnyWords[Math.floor((Math.random() * FunnyWords.length))]}/status/${tweetid}`;
|
|||
|
|
|||
|
// Im too lazy for now to make an entry in config.json
|
|||
|
let channel = interaction.client.channels.resolve(twiChannel);
|
|||
|
channel.send(TweetLink);
|
|||
|
|
|||
|
const Embed = new MessageEmbed()
|
|||
|
.setAuthor({ name: interaction.user.username, iconURL: interaction.user.displayAvatarURL() })
|
|||
|
.setDescription(tweet)
|
|||
|
.addField('Link', TweetLink, true)
|
|||
|
.addField('Tweet ID', tweetid, true)
|
|||
|
.addField('Channel ID', interaction.channel.id, true)
|
|||
|
.addField('Messsage ID', interaction.id, true)
|
|||
|
.addField('Author', `${interaction.user.username} (${interaction.user.id})`, true)
|
|||
|
.setTimestamp();
|
|||
|
|
|||
|
if (interaction.guild) {
|
|||
|
Embed.addField('Guild', `${interaction.guild.name} (${interaction.guild.id})`, true);
|
|||
|
Embed.addField('message link', `https://discord.com/channels/${interaction.guild.id}/${interaction.channel.id}/${interaction.id}`);
|
|||
|
}
|
|||
|
else {
|
|||
|
Embed.addField('message link', `https://discord.com/channels/@me/${interaction.channel.id}/${interaction.id}`);
|
|||
|
}
|
|||
|
|
|||
|
if (attachment) Embed.setImage(attachment.url);
|
|||
|
|
|||
|
channel = interaction.client.channels.resolve(twiLogChannel);
|
|||
|
channel.send({ embeds: [Embed] });
|
|||
|
return interaction.editReply({ content: `Go see ur epic tweet ${TweetLink}` });
|
|||
|
});
|
|||
|
}
|
|||
|
},
|
|||
|
};
|