// ==UserScript==
// @name Airpl4ne Discord Spammer
// @name:vi Airpl4ne Discord Spammer
// @namespace https://twisk.fun
// @version 1.0.1
// @description Automate sending messages to Discord DMs or server channels with customizable delay and count.
// @description:vi Tự động gửi tin nhắn đến Discord DMs hoặc kênh với có thể chỉnh delay và số lượng.
// @author airpl4ne
// @match https://discord.com/*
// @grant GM_addStyle
// @icon https://images-eds-ssl.xboxlive.com/image?url=4rt9.lXDC4H_93laV1_eHHFT949fUipzkiFOBH3fAiZZUCdYojwUyX2aTonS1aIwMrx6NUIsHfUHSLzjGJFxxsG72wAo9EWJR4yQWyJJaDaK1XdUso6cUMpI9hAdPUU_FNs11cY1X284vsHrnWtRw7oqRpN1m9YAg21d_aNKnIo-&format=source
// @license MIT
// ==/UserScript==
// never use it for illegal purposes.
// We do not take any responsibility.
// if you need help , join our discord : https://discord.gg/m3EV55SpYw
// please rate good if this tool is helpful to u! big thanks!<3
(function() {
'use strict';
// css
GM_addStyle(`
#message-sender-panel {
position: fixed;
top: 50px;
right: 20px;
background: #2f3136;
color: #dcddde;
padding: 15px;
border-radius: 8px;
z-index: 10000;
box-shadow: 0 2px 10px rgba(0,0,0,0.3);
font-family: 'Whitney', sans-serif;
width: 320px;
user-select: none;
transition: all 0.3s ease;
}
#message-sender-panel:hover {
box-shadow: 0 4px 15px rgba(0,0,0,0.4);
}
#panel-header {
display: flex;
justify-content: space-between;
align-items: center;
cursor: move;
margin-bottom: 10px;
}
#panel-header h3 {
margin: 0;
font-size: 16px;
font-weight: 600;
}
#close-btn {
background: none;
border: none;
color: #b9bbbe;
cursor: pointer;
font-size: 18px;
}
#close-btn:hover {
color: #dcddde;
}
#message-sender-panel label {
display: block;
margin: 5px 0 2px;
font-size: 12px;
color: #b9bbbe;
}
#message-sender-panel input, #message-sender-panel select, #message-sender-panel textarea {
background: #40444b;
border: none;
border-radius: 3px;
color: #dcddde;
padding: 8px;
width: 100%;
box-sizing: border-box;
font-size: 14px;
margin-bottom: 10px;
}
#message-sender-panel textarea {
resize: vertical;
min-height: 50px;
}
#message-sender-panel button {
background: #5865f2;
color: white;
border: none;
border-radius: 3px;
padding: 8px;
cursor: pointer;
font-size: 14px;
width: 100%;
margin: 5px 0;
transition: background 0.2s;
}
#message-sender-panel button:hover {
background: #4752c4;
}
#message-sender-panel button:disabled {
background: #72767d;
cursor: not-allowed;
}
#stop-btn {
background: #ed4245;
}
#stop-btn:hover {
background: #da373c;
}
#status {
margin-top: 10px;
font-size: 12px;
color: #43b581;
}
.error {
color: #f04747 !important;
}
.hidden {
display: none;
}
`);
// create css
function createPanel() {
const panel = document.createElement('div');
panel.id = 'message-sender-panel';
panel.innerHTML = `
<div id="panel-header">
<h3>Airpl4ne Spammer</h3>
<button id="close-btn">×</button>
</div>
<label for="target-type">Target Type:</label>
<select id="target-type">
<option value="dm">DM (User ID)</option>
<option value="channel">Server Channel (Channel ID)</option>
</select>
<div id="dm-input">
<label for="user-id">User ID:</label>
<input type="text" id="user-id" placeholder="Enter User ID (e.g., 123456789012345678)">
</div>
<div id="channel-input" class="hidden">
<label for="channel-id">Channel ID:</label>
<input type="text" id="channel-id" placeholder="Enter Channel ID (e.g., 987654321098765432)">
</div>
<label for="message-content">Message:</label>
<textarea id="message-content" placeholder="Enter message (supports multi-line)"></textarea>
<div style="display: flex; justify-content: space-between;">
<div style="width: 48%;">
<label for="delay">Delay (ms):</label>
<input type="number" id="delay" value="1000" min="500">
</div>
<div style="width: 48%;">
<label for="count">Count:</label>
<input type="number" id="count" value="1" min="1">
</div>
</div>
<button id="start-btn">Start Sending</button>
<button id="stop-btn" class="hidden">Stop Sending</button>
<div id="status"></div>
`;
document.body.appendChild(panel);
// event
document.getElementById('start-btn').addEventListener('click', startSending);
document.getElementById('stop-btn').addEventListener('click', stopSending);
document.getElementById('close-btn').addEventListener('click', () => panel.remove());
document.getElementById('target-type').addEventListener('change', toggleInputs);
// drag
makeDraggable(panel);
toggleInputs(); // Initial setup
}
// inputs
function toggleInputs() {
const type = document.getElementById('target-type').value;
document.getElementById('dm-input').classList.toggle('hidden', type !== 'dm');
document.getElementById('channel-input').classList.toggle('hidden', type !== 'channel');
}
// element drag
function makeDraggable(element) {
const header = document.getElementById('panel-header');
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
header.onmousedown = dragMouseDown;
function dragMouseDown(e) {
e.preventDefault();
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e.preventDefault();
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
element.style.top = (element.offsetTop - pos2) + "px";
element.style.left = (element.offsetLeft - pos1) + "px";
}
function closeDragElement() {
document.onmouseup = null;
document.onmousemove = null;
}
}
// discord auth
function getAuthToken() {
let token = localStorage.getItem('token');
if (!token) {
updateStatus('Error: No authorization token found. Please log in to Discord.', true);
return null;
}
return token.replace(/"/g, '');
}
// status
function updateStatus(message, isError = false) {
const statusDiv = document.getElementById('status');
statusDiv.textContent = message;
statusDiv.className = isError ? 'error' : '';
}
// vali id
function validateId(id) {
return /^\d{17,19}$/.test(id);
}
// api
async function sendMessage(channelId, message, authToken) {
const url = `https://discord.com/api/v10/channels/${channelId}/messages`;
const payload = {
content: message,
tts: false,
nonce: Date.now().toString() + Math.floor(Math.random() * 1000).toString()
};
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': authToken,
'Content-Type': 'application/json',
'User-Agent': navigator.userAgent
},
body: JSON.stringify(payload)
});
if (response.ok) {
return true;
} else {
const error = await response.json();
updateStatus(`Error: ${error.message || 'Failed to send message'}`, true);
return false;
}
} catch (error) {
updateStatus(`Error: ${error.message}`, true);
return false;
}
}
// sendinh
let isSending = false;
let sentCount = 0;
async function startSending() {
if (isSending) return;
const type = document.getElementById('target-type').value;
let targetId = type === 'dm' ? document.getElementById('user-id').value.trim() : document.getElementById('channel-id').value.trim();
const message = document.getElementById('message-content').value.trim();
const delay = parseInt(document.getElementById('delay').value);
const count = parseInt(document.getElementById('count').value);
const authToken = getAuthToken();
if (!authToken) return;
if (!message) {
updateStatus('Error: Please enter a message.', true);
return;
}
if (!targetId) {
updateStatus(`Error: Please enter a ${type === 'dm' ? 'User ID' : 'Channel ID'}.`, true);
return;
}
if (!validateId(targetId)) {
updateStatus('Error: Invalid ID format (must be 17-19 digits).', true);
return;
}
if (delay < 500) {
updateStatus('Warning: Delay set to minimum 500ms to avoid rate limits.', true);
document.getElementById('delay').value = 500;
}
let channelId = targetId;
if (type === 'dm') {
channelId = await getDMChannelId(targetId, authToken);
if (!channelId) return;
}
isSending = true;
sentCount = 0;
document.getElementById('start-btn').disabled = true;
document.getElementById('stop-btn').classList.remove('hidden');
updateStatus(`Sending messages... (0/${count})`);
for (let i = 0; i < count && isSending; i++) {
const success = await sendMessage(channelId, message, authToken);
if (!success) break;
sentCount++;
updateStatus(`Sending messages... (${sentCount}/${count})`);
if (i < count - 1) {
await new Promise(resolve => setTimeout(resolve, delay));
}
}
isSending = false;
document.getElementById('start-btn').disabled = false;
document.getElementById('stop-btn').classList.add('hidden');
updateStatus(`Finished sending ${sentCount} message(s).`);
}
// stop
function stopSending() {
isSending = false;
updateStatus(`Stopped after sending ${sentCount} message(s).`);
document.getElementById('start-btn').disabled = false;
document.getElementById('stop-btn').classList.add('hidden');
}
//get id
async function getDMChannelId(userId, authToken) {
const url = 'https://discord.com/api/v10/users/@me/channels';
const payload = { recipient_id: userId };
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': authToken,
'Content-Type': 'application/json',
'User-Agent': navigator.userAgent
},
body: JSON.stringify(payload)
});
if (response.ok) {
const data = await response.json();
return data.id;
} else {
const error = await response.json();
updateStatus(`Error creating DM channel: ${error.message || error.code}`, true);
return null;
}
} catch (error) {
updateStatus(`Error: ${error.message}`, true);
return null;
}
}
// bye bye!
if (window.location.href.includes('discord.com')) {
createPanel();
}
})();