Upload code
This commit is contained in:
commit
340082f454
45 changed files with 4816 additions and 0 deletions
181
pages/channel.js
Normal file
181
pages/channel.js
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
var fs = require('fs');
|
||||
var minify = require('html-minifier').minify;
|
||||
var escape = require('escape-html');
|
||||
var md = require('markdown-it')({breaks: true, linkify: true});
|
||||
var he = require('he'); // Encodes HTML attributes
|
||||
|
||||
// Minify at runtime to save data on slow connections, but still allow editing the unminified file easily
|
||||
// Is that a bad idea?
|
||||
|
||||
// Templates for viewing the messages in a channel
|
||||
const channel_template = minify(fs.readFileSync('pages/templates/channel.html', 'utf-8'));
|
||||
|
||||
const message_template = minify(fs.readFileSync('pages/templates/message/message.html', 'utf-8'));
|
||||
const first_message_content_template = minify(fs.readFileSync('pages/templates/message/first_message_content.html', 'utf-8'));
|
||||
const merged_message_content_template = minify(fs.readFileSync('pages/templates/message/merged_message_content.html', 'utf-8'));
|
||||
const mention_template = minify(fs.readFileSync('pages/templates/message/mention.html', 'utf-8'));
|
||||
|
||||
const input_template = minify(fs.readFileSync('pages/templates/channel/input.html', 'utf-8'));
|
||||
const input_disabled_template = minify(fs.readFileSync('pages/templates/channel/input_disabled.html', 'utf-8'));
|
||||
|
||||
const no_message_history_template = minify(fs.readFileSync('pages/templates/channel/no_message_history.html', 'utf-8'));
|
||||
|
||||
function strReplace(string, needle, replacement) {
|
||||
return string.split(needle).join(replacement||"");
|
||||
};
|
||||
|
||||
// https://stackoverflow.com/questions/1967119/why-does-javascript-replace-only-first-instance-when-using-replace
|
||||
|
||||
exports.processChannel = async function processChannel(bot, req, res, args, discordID) {
|
||||
try {
|
||||
response = "";
|
||||
chnl = await bot.client.channels.fetch(args[2]);
|
||||
} catch (err) {
|
||||
chnl = undefined;
|
||||
}
|
||||
|
||||
if (chnl) {
|
||||
member = await chnl.guild.members.fetch(discordID);
|
||||
user = member.user;
|
||||
username = user.tag;
|
||||
if (member.displayName != user.username) {
|
||||
username = member.displayName + " (@" + user.tag + ")";
|
||||
}
|
||||
|
||||
if (!member.permissionsIn(chnl).has("VIEW_CHANNEL", true)) {
|
||||
res.write("You don't have permission to do that!");
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!member.permissionsIn(chnl).has("READ_MESSAGE_HISTORY", true)) {
|
||||
template = strReplace(channel_template, "{$SERVER_ID}", chnl.guild.id)
|
||||
template = strReplace(template, "{$CHANNEL_ID}", chnl.id)
|
||||
|
||||
if (member.permissionsIn(chnl).has("SEND_MESSAGES", true)) {
|
||||
final = strReplace(template, "{$INPUT}", input_template);
|
||||
} else {
|
||||
final = strReplace(template, "{$INPUT}", input_disabled_template);
|
||||
}
|
||||
final = strReplace(final, "{$MESSAGES}", no_message_history_template); // You do not have permission... message
|
||||
|
||||
res.write(final); //write a response to the client
|
||||
res.end(); //end the response
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("Processed valid channel request");
|
||||
messages = await bot.getHistoryCached(chnl);
|
||||
lastauthor = undefined;
|
||||
lastmember = undefined;
|
||||
lastdate = new Date('1995-12-17T03:24:00');
|
||||
currentmessage = "";
|
||||
islastmessage = false;
|
||||
|
||||
handlemessage = async function (item) { // Save the function to use later in the for loop and to process the last message
|
||||
if (lastauthor) { // Only consider the last message if this is not the first
|
||||
// If the last message is not going to be merged with this one, put it into the response
|
||||
if (islastmessage || lastauthor.id != item.author.id || lastauthor.username != item.author.username || item.createdAt - lastdate > 420000) {
|
||||
|
||||
|
||||
currentmessage = message_template.replace("{$MESSAGE_CONTENT}", currentmessage);
|
||||
if (lastmember) { // Webhooks are not members!
|
||||
currentmessage = currentmessage.replace("{$MESSAGE_AUTHOR}", escape(lastmember.displayName));
|
||||
} else {
|
||||
currentmessage = currentmessage.replace("{$MESSAGE_AUTHOR}", escape(lastauthor.username));
|
||||
}
|
||||
|
||||
var url = lastauthor.avatarURL();
|
||||
if (lastauthor.avatarURL && url && url.toString().startsWith("http")) { // Sometimes the URL is null or something else
|
||||
currentmessage = currentmessage.replace("{$PROFILE_URL}", url);
|
||||
}
|
||||
currentmessage = strReplace(currentmessage, "{$MESSAGE_DATE}", lastdate.toLocaleTimeString('en-US') + " " + lastdate.toDateString());
|
||||
currentmessage = strReplace(currentmessage, "{$TAG}", he.encode(JSON.stringify("@" + lastauthor.tag)));
|
||||
response += currentmessage;
|
||||
currentmessage = "";
|
||||
}
|
||||
}
|
||||
|
||||
if (!item) { // When processing the last message outside of the forEach item is undefined
|
||||
return;
|
||||
}
|
||||
|
||||
// messagetext = strReplace(escape(item.content), "\n", "<br>");
|
||||
messagetext = /* strReplace( */ md.renderInline(item.content) /* , "\n", "<br>") */;
|
||||
if (item.mentions) {
|
||||
item.mentions.members.forEach(function(user) {
|
||||
if (user) {
|
||||
messagetext = strReplace(messagetext, "<@" + user.id.toString() + ">", mention_template.replace("{$USERNAME}", escape("@" + user.displayName)));
|
||||
messagetext = strReplace(messagetext, "<@!" + user.id.toString() + ">", mention_template.replace("{$USERNAME}", escape("@" + user.displayName)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/6323417/regex-to-extract-all-matches-from-string-using-regexp-exec
|
||||
|
||||
var regex = /<#([0-9]{18})>/g; // Regular expression to detect channel IDs
|
||||
var m;
|
||||
|
||||
do {
|
||||
m = regex.exec(messagetext);
|
||||
if (m) {
|
||||
try {
|
||||
channel = await bot.client.channels.cache.get(m[1]);
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
if (channel) {
|
||||
messagetext = strReplace(messagetext, m[0], mention_template.replace("{$USERNAME}", escape("#" + channel.name)));
|
||||
}
|
||||
}
|
||||
} while (m);
|
||||
|
||||
messagetext = strReplace(messagetext, "@everyone", mention_template.replace("{$USERNAME}", "@everyone"));
|
||||
messagetext = strReplace(messagetext, "@here", mention_template.replace("{$USERNAME}", "@here"));
|
||||
|
||||
|
||||
|
||||
// If the last message is not going to be merged with this one, use the template for the first message, otherwise use the template for merged messages
|
||||
if (!lastauthor || lastauthor.id != item.author.id || lastauthor.username != item.author.username || item.createdAt - lastdate > 420000) {
|
||||
messagetext = first_message_content_template.replace("{$MESSAGE_TEXT}", messagetext);
|
||||
} else {
|
||||
messagetext = merged_message_content_template.replace("{$MESSAGE_TEXT}", messagetext);
|
||||
}
|
||||
|
||||
lastauthor = item.author;
|
||||
lastmember = item.member;
|
||||
lastdate = item.createdAt;
|
||||
currentmessage += messagetext;
|
||||
|
||||
}
|
||||
|
||||
for (const item of messages) {
|
||||
await handlemessage(item);
|
||||
}
|
||||
|
||||
// Handle the last message
|
||||
// Uses the function in the foreach from earlier
|
||||
|
||||
islastmessage = true;
|
||||
await handlemessage();
|
||||
|
||||
template = strReplace(channel_template, "{$SERVER_ID}", chnl.guild.id)
|
||||
template = strReplace(template, "{$CHANNEL_ID}", chnl.id)
|
||||
template = strReplace(template, "{$REFRESH_URL}", chnl.id + "?random=" + Math.random() + "#end")
|
||||
|
||||
if (member.permissionsIn(chnl).has("SEND_MESSAGES", true)) {
|
||||
final = strReplace(template, "{$INPUT}", input_template);
|
||||
} else {
|
||||
final = strReplace(template, "{$INPUT}", input_disabled_template);
|
||||
}
|
||||
final = strReplace(final, "{$MESSAGES}", response);
|
||||
|
||||
res.writeHead(200, { "Content-Type": "text/html" });
|
||||
res.write(final); //write a response to the client
|
||||
res.end(); //end the response
|
||||
} else {
|
||||
res.writeHead(404, { "Content-Type": "text/html" });
|
||||
res.write("Invalid channel!"); //write a response to the client
|
||||
res.end(); //end the response
|
||||
}
|
||||
}
|
||||
25
pages/forgot.js
Normal file
25
pages/forgot.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
var url = require('url');
|
||||
var fs = require('fs');
|
||||
var minify = require('html-minifier').minify;
|
||||
var escape = require('escape-html');
|
||||
|
||||
var auth = require('../authentication.js');
|
||||
|
||||
const forgot_template = minify(fs.readFileSync('pages/templates/forgot.html', 'utf-8'));
|
||||
const error_template = minify(fs.readFileSync('pages/templates/login/error.html', 'utf-8'));
|
||||
|
||||
function strReplace(string, needle, replacement) {
|
||||
return string.split(needle).join(replacement||"");
|
||||
};
|
||||
|
||||
exports.processForgot = async function(bot, req, res, args) {
|
||||
parsedurl = url.parse(req.url, true);
|
||||
response = forgot_template;
|
||||
if (parsedurl.query.errortext) {
|
||||
response = strReplace(response, "{$ERROR}", strReplace(error_template, "{$ERROR_MESSAGE}", strReplace(escape(parsedurl.query.errortext), "\n", "<br>")));
|
||||
} else {
|
||||
response = strReplace(response, "{$ERROR}", "");
|
||||
}
|
||||
res.write(response);
|
||||
res.end();
|
||||
}
|
||||
37
pages/guest.js
Normal file
37
pages/guest.js
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
var url = require('url');
|
||||
var fs = require('fs');
|
||||
var minify = require('html-minifier').minify;
|
||||
var escape = require('escape-html');
|
||||
|
||||
var auth = require('../authentication.js');
|
||||
|
||||
const guest_login_template = minify(fs.readFileSync('pages/templates/guest.html', 'utf-8'));
|
||||
const error_template = minify(fs.readFileSync('pages/templates/login/error.html', 'utf-8'));
|
||||
|
||||
function strReplace(string, needle, replacement) {
|
||||
return string.split(needle).join(replacement||"");
|
||||
};
|
||||
|
||||
exports.processGuestLogin = async function(bot, req, res, args) {
|
||||
discordID = await auth.checkAuth(req, res, true); // true means that the user isn't redirected to the login page
|
||||
if (discordID) {
|
||||
// res.writeHead(200, {'Content-Type': 'text/html'});
|
||||
res.writeHead(303, {"Location": "/server/", "Content-Type": "text/html"});
|
||||
res.write('Logged in! Click <a href="/server/">here</a> to continue.');
|
||||
} else {
|
||||
parsedurl = url.parse(req.url, true);
|
||||
response = guest_login_template;
|
||||
if (parsedurl.query.redirect) {
|
||||
response = strReplace(response, "{$REDIRECT_URL}", strReplace(parsedurl.query.redirect, '"', "%22"));
|
||||
} else {
|
||||
response = strReplace(response, "{$REDIRECT_URL}", "/server/");
|
||||
}
|
||||
if (parsedurl.query.errortext) {
|
||||
response = strReplace(response, "{$ERROR}", strReplace(error_template, "{$ERROR_MESSAGE}", strReplace(escape(parsedurl.query.errortext), "\n", "<br>")));
|
||||
} else {
|
||||
response = strReplace(response, "{$ERROR}", "");
|
||||
}
|
||||
res.write(response);
|
||||
}
|
||||
res.end();
|
||||
}
|
||||
27
pages/index.js
Normal file
27
pages/index.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
var fs = require('fs');
|
||||
var minify = require('html-minifier').minify;
|
||||
var escape = require('escape-html');
|
||||
|
||||
var auth = require('../authentication.js');
|
||||
|
||||
const index_template = minify(fs.readFileSync('pages/templates/index.html', 'utf-8'));
|
||||
|
||||
const logged_in_template = minify(fs.readFileSync('pages/templates/index/logged_in.html', 'utf-8'));
|
||||
const logged_out_template = minify(fs.readFileSync('pages/templates/index/logged_out.html', 'utf-8'));
|
||||
|
||||
function strReplace(string, needle, replacement) {
|
||||
return string.split(needle).join(replacement||"");
|
||||
};
|
||||
|
||||
exports.processIndex = async function(bot, req, res, args) {
|
||||
discordID = await auth.checkAuth(req, res, true); // true means that the user isn't redirected to the login page
|
||||
if (discordID) {
|
||||
response = strReplace(index_template, "{$MENU_OPTIONS}",
|
||||
strReplace(logged_in_template, "{$USER}", escape(await auth.getUsername(discordID)))
|
||||
);
|
||||
} else {
|
||||
response = strReplace(index_template, "{$MENU_OPTIONS}", logged_out_template);
|
||||
}
|
||||
res.write(response);
|
||||
res.end();
|
||||
}
|
||||
37
pages/login.js
Normal file
37
pages/login.js
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
var url = require('url');
|
||||
var fs = require('fs');
|
||||
var minify = require('html-minifier').minify;
|
||||
var escape = require('escape-html');
|
||||
|
||||
var auth = require('../authentication.js');
|
||||
|
||||
const login_template = minify(fs.readFileSync('pages/templates/login.html', 'utf-8'));
|
||||
const error_template = minify(fs.readFileSync('pages/templates/login/error.html', 'utf-8'));
|
||||
|
||||
function strReplace(string, needle, replacement) {
|
||||
return string.split(needle).join(replacement||"");
|
||||
};
|
||||
|
||||
exports.processLogin = async function(bot, req, res, args) {
|
||||
discordID = await auth.checkAuth(req, res, true); // true means that the user isn't redirected to the login page
|
||||
if (discordID) {
|
||||
// res.writeHead(200, {'Content-Type': 'text/html'});
|
||||
res.writeHead(303, {"Location": "/server/", "Content-Type": "text/html"});
|
||||
res.write('Logged in! Click <a href="/server/">here</a> to continue.');
|
||||
} else {
|
||||
parsedurl = url.parse(req.url, true);
|
||||
response = login_template;
|
||||
if (parsedurl.query.redirect) {
|
||||
response = strReplace(response, "{$REDIRECT_URL}", strReplace(parsedurl.query.redirect, '"', "%22"));
|
||||
} else {
|
||||
response = strReplace(response, "{$REDIRECT_URL}", "/server/");
|
||||
}
|
||||
if (parsedurl.query.errortext) {
|
||||
response = strReplace(response, "{$ERROR}", strReplace(error_template, "{$ERROR_MESSAGE}", strReplace(escape(parsedurl.query.errortext), "\n", "<br>")));
|
||||
} else {
|
||||
response = strReplace(response, "{$ERROR}", "");
|
||||
}
|
||||
res.write(response);
|
||||
}
|
||||
res.end();
|
||||
}
|
||||
31
pages/register.js
Normal file
31
pages/register.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
var url = require('url');
|
||||
var fs = require('fs');
|
||||
var minify = require('html-minifier').minify;
|
||||
var escape = require('escape-html');
|
||||
|
||||
var auth = require('../authentication.js');
|
||||
|
||||
const register_template = minify(fs.readFileSync('pages/templates/register.html', 'utf-8'));
|
||||
const error_template = minify(fs.readFileSync('pages/templates/login/error.html', 'utf-8'));
|
||||
|
||||
function strReplace(string, needle, replacement) {
|
||||
return string.split(needle).join(replacement||"");
|
||||
};
|
||||
|
||||
exports.processRegister = async function(bot, req, res, args) {
|
||||
discordID = await auth.checkAuth(req, res, true); // true means that the user isn't redirected to the login page
|
||||
if (discordID) {
|
||||
res.writeHead(302, {"Location": "/server/"});
|
||||
res.write('Logged in! Click <a href="/server/">here</a> to continue.');
|
||||
} else {
|
||||
parsedurl = url.parse(req.url, true);
|
||||
response = register_template;
|
||||
if (parsedurl.query.errortext) {
|
||||
response = strReplace(response, "{$ERROR}", strReplace(error_template, "{$ERROR_MESSAGE}", strReplace(escape(parsedurl.query.errortext), "\n", "<br>")));
|
||||
} else {
|
||||
response = strReplace(response, "{$ERROR}", "");
|
||||
}
|
||||
res.write(response);
|
||||
}
|
||||
res.end();
|
||||
}
|
||||
100
pages/send.js
Normal file
100
pages/send.js
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
const url = require('url');
|
||||
const auth = require('../authentication.js');
|
||||
const bot = require('../bot.js');
|
||||
const discord = require('discord.js');
|
||||
|
||||
const send_special = require('../secrets/send_special.js'); // A secret function that proxies the webhook for security. Does nothing in the public version.
|
||||
|
||||
function strReplace(string, needle, replacement) {
|
||||
return string.split(needle).join(replacement||"");
|
||||
};
|
||||
|
||||
// https://stackoverflow.com/questions/1967119/why-does-javascript-replace-only-first-instance-when-using-replace
|
||||
|
||||
async function clean(server, nodelete) {
|
||||
(await server.fetchWebhooks()).forEach(async function(item) {
|
||||
if ((item.owner.username.search("Discross") != -1) && (item.id != nodelete)) {
|
||||
try {
|
||||
await item.delete();
|
||||
} catch(err) {}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
exports.sendMessage = async function sendMessage(bot, req, res, args, discordID) {
|
||||
parsedurl = url.parse(req.url, true);
|
||||
if (parsedurl.query.message != "") {
|
||||
|
||||
channel = await bot.client.channels.fetch(parsedurl.query.channel);
|
||||
|
||||
member = await channel.guild.members.fetch(discordID);
|
||||
user = member.user;
|
||||
username = user.tag;
|
||||
if (member.displayName != user.username) {
|
||||
username = member.displayName + " (@" + user.tag + ")";
|
||||
}
|
||||
|
||||
// if (user.permissionsIn(channel).FLAGS)]
|
||||
if (!member.permissionsIn(channel).has("SEND_MESSAGES", true)) { // True always allows admins to send messages
|
||||
res.write("You don't have permission to do that!");
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (channel.guild.id == 421771267100901377) { // A secret function that proxies the webhook for security. Only for The Wii Hacking House because I have to hardcode the webhook URLs and that's the most likely target. I have a thing that automatically shuts the bot down if any server gets attacked anyway.
|
||||
await send_special.send(channel, parsedurl.query.message, {username: username, avatarURL: user.avatarURL(), disableEveryone: true});
|
||||
res.writeHead(302, {"Location": "/channels/" + parsedurl.query.channel + "#end"});
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// webhooks (serverID INT, webhookID INT, url STRING)
|
||||
webhookDB = await auth.dbQuerySingle("SELECT * FROM webhooks WHERE serverID=?", [channel.guild.id]);
|
||||
|
||||
if (!webhookDB) {
|
||||
webhook = await channel.createWebhook("Discross", "pages/static/resources/logo.png", "Discross uses webhooks to send messages");
|
||||
auth.dbQuerySingle("INSERT INTO webhooks VALUES (?,?,?)", [channel.guild.id, webhook.id, webhook.token]);
|
||||
clean(channel.guild, webhook.id); // Clean up all webhooks except the new one
|
||||
} else {
|
||||
// webhook = new Discord.WebhookClient(webhookDB.webhookID, webhookDB.token);
|
||||
try {
|
||||
webhook = await bot.client.fetchWebhook(webhookDB.webhookID);
|
||||
} catch (err) {
|
||||
webhook = await channel.createWebhook("Discross", "pages/static/resources/logo.png", "Discross uses webhooks to send messages");
|
||||
auth.dbQuerySingle("INSERT INTO webhooks VALUES (?,?,?)", [channel.guild.id, webhook.id, webhook.token]);
|
||||
clean(channel.guild, webhook.id); // Clean up all webhooks except the new one
|
||||
}
|
||||
clean(channel.guild, webhookDB.webhookID);
|
||||
}
|
||||
|
||||
processedmessage = parsedurl.query.message;
|
||||
|
||||
// https://stackoverflow.com/questions/6323417/regex-to-extract-all-matches-from-string-using-regexp-exec
|
||||
// regex modified from https://www.reddit.com/r/discordapp/comments/6k4fml/username_requirements/
|
||||
|
||||
var regex = /@([^#]{2,32}#\d{4})/g; // Regular expression to detect user mentions
|
||||
var m;
|
||||
|
||||
do {
|
||||
m = regex.exec(processedmessage);
|
||||
if (m) {
|
||||
mentioneduser = await channel.guild.members.cache.find(member => member.user.tag == m[1]);
|
||||
if (!mentioneduser) {
|
||||
mentioneduser = (await channel.guild.members.fetch()).find(member => member.user.tag == m[1]);
|
||||
}
|
||||
if (mentioneduser) {
|
||||
processedmessage = strReplace(processedmessage, m[0], "<@" + mentioneduser.id + ">");
|
||||
}
|
||||
}
|
||||
} while (m);
|
||||
|
||||
await webhook.edit({channel: channel});
|
||||
message = await webhook.send(processedmessage, {username: username, avatarURL: user.avatarURL(), disableEveryone: true});
|
||||
|
||||
bot.addToCache(message);
|
||||
|
||||
}
|
||||
|
||||
res.writeHead(302, {"Location": "/channels/" + parsedurl.query.channel + "#end"});
|
||||
res.end();
|
||||
}
|
||||
117
pages/server.js
Normal file
117
pages/server.js
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
var fs = require('fs');
|
||||
var minify = require('html-minifier').minify;
|
||||
var escape = require('escape-html');
|
||||
|
||||
// Minify at runtime to save data on slow connections, but still allow editing the unminified file easily
|
||||
// Is that a bad idea?
|
||||
|
||||
// Templates for viewing the channels in a server
|
||||
const server_template = minify(fs.readFileSync('pages/templates/server.html', 'utf-8'));
|
||||
|
||||
const text_channel_template = minify(fs.readFileSync('pages/templates/channellist/textchannel.html', 'utf-8'));
|
||||
const category_channel_template = minify(fs.readFileSync('pages/templates/channellist/categorychannel.html', 'utf-8'));
|
||||
|
||||
const server_icon_template = minify(fs.readFileSync('pages/templates/server/server_icon.html', 'utf-8'));
|
||||
|
||||
const invalid_server_template = minify(fs.readFileSync('pages/templates/server/invalid_server.html', 'utf-8'));
|
||||
|
||||
const cachedMembers = {}; // TODO: Find a better way
|
||||
|
||||
function strReplace(string, needle, replacement) {
|
||||
return string.split(needle).join(replacement||"");
|
||||
};
|
||||
|
||||
// https://stackoverflow.com/questions/1967119/why-does-javascript-replace-only-first-instance-when-using-replace
|
||||
|
||||
exports.processServer = async function (bot, req, res, args, discordID) {
|
||||
guestServers = ["439461201731387392"];
|
||||
guestChannels = ["608958017366654986"];
|
||||
var isGuest = false;
|
||||
if (typeof(discordID) == "object") {
|
||||
isGuest = true;
|
||||
}
|
||||
serverList = "";
|
||||
for (var server of bot.client.guilds.cache) {
|
||||
server = server[1];
|
||||
if (cachedMembers[discordID] && cachedMembers[discordID][server.id] !== undefined) {
|
||||
member = cachedMembers[discordID][server.id];
|
||||
} else if (!(isGuest && guestServers.includes(server.id))) {
|
||||
try {
|
||||
member = await server.members.fetch(discordID);
|
||||
} catch (err) {
|
||||
member = null;
|
||||
}
|
||||
if (!cachedMembers[discordID]) {
|
||||
cachedMembers[discordID] = {};
|
||||
}
|
||||
cachedMembers[discordID][server.id] = member;
|
||||
}
|
||||
if ((isGuest && guestServers.includes(server.id)) || (member && member.user)) {
|
||||
serverHTML = strReplace(server_icon_template, "{$SERVER_ICON_URL}", server.iconURL());
|
||||
serverHTML = strReplace(serverHTML, "{$SERVER_URL}", "./" + server.id);
|
||||
serverList += serverHTML;
|
||||
}
|
||||
}
|
||||
|
||||
response = server_template.replace("{$SERVER_LIST}", serverList);
|
||||
|
||||
server = bot.client.guilds.cache.get(args[2]);
|
||||
|
||||
try {
|
||||
if (!(isGuest && guestServers.includes(server.id))) {
|
||||
member = await server.members.fetch(discordID);
|
||||
user = member.user;
|
||||
username = user.tag;
|
||||
if (member.displayName != user.username) {
|
||||
username = member.displayName + " (@" + user.tag + ")";
|
||||
}
|
||||
}
|
||||
//} else {
|
||||
// username = "Guest";
|
||||
//}
|
||||
// username =
|
||||
if (!((isGuest && guestServers.includes(server.id)) || member.user)) {
|
||||
server = undefined;
|
||||
}
|
||||
} catch (err) { // If they aren't in the server
|
||||
// console.log(err); TODO: Only ignore TypeError: Cannot read property 'members' of undefined
|
||||
server = undefined; // Act like it doesn't exist
|
||||
}
|
||||
|
||||
if (server) {
|
||||
categories = server.channels.cache.filter(channel => channel.type == "category");
|
||||
categoriesSorted = categories.sort((a, b) => (a.calculatedPosition - b.calculatedPosition));
|
||||
|
||||
channelsSorted = server.channels.cache.filter(channel => channel.type != "category" && channel.type != "voice" && !channel.parent).array(); // Start with lone channels (no category)
|
||||
channelsSorted = channelsSorted.sort((a, b) => (a.calculatedPosition - b.calculatedPosition));
|
||||
|
||||
|
||||
categoriesSorted.forEach(function(category) {
|
||||
channelsSorted.push(category);
|
||||
channelsSorted = channelsSorted.concat(
|
||||
category.children.sort((a, b) => (a.calculatedPosition - b.calculatedPosition))
|
||||
.array()
|
||||
.filter(channel => channel.type != "voice")
|
||||
);
|
||||
});
|
||||
|
||||
channelList = "";
|
||||
channelsSorted.forEach(function(item) {
|
||||
if ((isGuest && guestChannels.includes(item.id)) || (member.permissionsIn && member.permissionsIn(item).has("VIEW_CHANNEL", true))) {
|
||||
if (item.type == "category") {
|
||||
channelList += category_channel_template.replace("{$CHANNEL_NAME}", escape(item.name));
|
||||
} else {
|
||||
channelList += text_channel_template.replace("{$CHANNEL_NAME}", escape(item.name)).replace("{$CHANNEL_LINK}", "../channels/" + item.id + "#end");
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channelList = invalid_server_template;
|
||||
}
|
||||
|
||||
response = response.replace("{$CHANNEL_LIST}", channelList);
|
||||
|
||||
res.writeHead(200, { "Content-Type": "text/html" });
|
||||
res.write(response);
|
||||
res.end();
|
||||
}
|
||||
214
pages/static/connection.js
Normal file
214
pages/static/connection.js
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
connectiontype = "none";
|
||||
latest_message_id = 0;
|
||||
messages = [];
|
||||
isxhr = false;
|
||||
authkey = "authpls";
|
||||
// nocache
|
||||
|
||||
// https://stackoverflow.com/a/15339941
|
||||
function Xhr(){ /* returns cross-browser XMLHttpRequest, or null if unable */
|
||||
try {
|
||||
return new XMLHttpRequest();
|
||||
}catch(e){}
|
||||
try {
|
||||
return new ActiveXObject("Msxml3.XMLHTTP");
|
||||
}catch(e){}
|
||||
try {
|
||||
return new ActiveXObject("Msxml2.XMLHTTP.6.0");
|
||||
}catch(e){}
|
||||
try {
|
||||
return new ActiveXObject("Msxml2.XMLHTTP.3.0");
|
||||
}catch(e){}
|
||||
try {
|
||||
return new ActiveXObject("Msxml2.XMLHTTP");
|
||||
}catch(e){}
|
||||
try {
|
||||
return new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}catch(e){}
|
||||
return null;
|
||||
}
|
||||
|
||||
function addMessage(text) {
|
||||
messages = messages.concat(text);
|
||||
// console.log(text);
|
||||
// console.log(messages);
|
||||
// var node = document.createElement("div"); // Create a <li> node
|
||||
// var textnode = document.createTextNode(text); // Create a text node
|
||||
// node.appendChild(textnode); // Append the text to <li>
|
||||
// document.getElementById("myList").appendChild(node); // Append <li> to <ul> with id="myList"
|
||||
// ws.close();
|
||||
|
||||
document.getElementById("myList").innerHTML = messages.join("<br>");
|
||||
}
|
||||
|
||||
function addLongpoll(id) {
|
||||
addScript("/longpoll.js?" + id, 'longpollScript');
|
||||
}
|
||||
|
||||
function addScript(src, elementID) {
|
||||
if (isxhr) {
|
||||
xhttp2.open("GET", src, true);
|
||||
xhttp2.send(null);
|
||||
} else {
|
||||
document.getElementById(elementID).innerHTML = "";
|
||||
var script = document.createElement('script');
|
||||
script.setAttribute('src', src);
|
||||
document.getElementById(elementID).appendChild(script);
|
||||
}
|
||||
}
|
||||
|
||||
function auth() {
|
||||
if (connectiontype == "websocket") {
|
||||
send("AUTH " + authkey);
|
||||
}
|
||||
}
|
||||
|
||||
function send(message) {
|
||||
if (connectiontype == "none") {
|
||||
} else if (connectiontype == "websocket") {
|
||||
ws.send(message);
|
||||
} else if (connectiontype == "longpoll") {
|
||||
time = (new Date()).getTime().toString();
|
||||
|
||||
|
||||
|
||||
// alert(encodeURIComponent("test"));
|
||||
|
||||
|
||||
|
||||
// alert(encodeURIComponent(message));
|
||||
|
||||
|
||||
|
||||
addScript('/api.js?uid=' +
|
||||
time +
|
||||
'&message=' +
|
||||
message
|
||||
+ '&authkey=' +
|
||||
authkey,
|
||||
'apiScript');
|
||||
}
|
||||
}
|
||||
|
||||
/* document.getElementById('messagebox').onkeypress = function(e){
|
||||
if (!e) e = window.event;
|
||||
var keyCode = e.keyCode || e.which;
|
||||
if (keyCode == '13' && document.getElementById('messagebox').value != ""){
|
||||
// alert("s");
|
||||
// Enter pressed
|
||||
send("SEND " + document.getElementById('messagebox').value);
|
||||
document.getElementById('messagebox').value = "";
|
||||
return false;
|
||||
}
|
||||
} */
|
||||
|
||||
function myFunction(e) {
|
||||
if (e.preventDefault) {
|
||||
e.preventDefault();
|
||||
}
|
||||
send("SEND " + document.getElementById("messagebox").value);
|
||||
document.getElementById("messagebox").value = "";
|
||||
return false;
|
||||
}
|
||||
|
||||
function longpoll_xhr(id) {
|
||||
xhttp.open("GET", "/longpoll-xhr?" + id + "&uid=" + (new Date()).getTime().toString(), true);
|
||||
xhttp.send(null);
|
||||
}
|
||||
|
||||
function setup_xhr() {
|
||||
xhttp = Xhr();
|
||||
xhttp.onreadystatechange = function() {
|
||||
// alert("test " + xhttp.responseText);
|
||||
if (xhttp.readyState == 4) {
|
||||
// alert(xhttp.status);
|
||||
// alert(xhttp.responseText);
|
||||
eval(xhttp.responseText);
|
||||
// addMessage(JSON.parse(this.responseText));
|
||||
setup_xhr();
|
||||
// longpoll_xhr(latest_message_id);
|
||||
}
|
||||
}
|
||||
xhttp.open("GET", "/longpoll-xhr?" + latest_message_id, true);
|
||||
xhttp.send(null);
|
||||
}
|
||||
|
||||
xhttp2 = Xhr();
|
||||
|
||||
// function WebSocketTest(usews) {
|
||||
|
||||
|
||||
|
||||
|
||||
if (window.WebSocket || window.MozWebSocket) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (!window.WebSocket) {
|
||||
|
||||
|
||||
|
||||
|
||||
window.WebSocket = window.MozWebSocket;
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
connectiontype = "websocket";
|
||||
// Let us open a web socket
|
||||
ws = new WebSocket("wss://" + location.host + "/");
|
||||
|
||||
ws.onopen = function() {
|
||||
auth();
|
||||
// Web Socket is connected, send data using send()
|
||||
// ws.send("Message to send");
|
||||
// alert("Message is sent...");
|
||||
};
|
||||
ws.onmessage = function (evt) {
|
||||
var received_msg = evt.data;
|
||||
addMessage(received_msg);
|
||||
};
|
||||
ws.onclose = function() {
|
||||
// websocket is closed.
|
||||
if (xhttp2) {
|
||||
connectiontype = "longpoll";
|
||||
// addLongpoll(latest_message_id);
|
||||
isxhr = true;
|
||||
setup_xhr();
|
||||
longpoll_xhr(latest_message_id);
|
||||
} else {
|
||||
connectiontype = "longpoll";
|
||||
isxhr = false
|
||||
addLongpoll(latest_message_id);
|
||||
// setup_xhr();
|
||||
// longpoll_xhr(latest_message_id);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
// The browser doesn't support WebSocket maybe
|
||||
if (xhttp2) {
|
||||
connectiontype = "longpoll";
|
||||
// addLongpoll(latest_message_id);
|
||||
isxhr = true;
|
||||
setup_xhr();
|
||||
longpoll_xhr(latest_message_id);
|
||||
} else {
|
||||
connectiontype = "longpoll";
|
||||
isxhr = false
|
||||
addLongpoll(latest_message_id);
|
||||
// setup_xhr();
|
||||
// longpoll_xhr(latest_message_id);
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
BIN
pages/static/resources/images/menu.png
Normal file
BIN
pages/static/resources/images/menu.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 150 B |
BIN
pages/static/resources/images/menuspacer.png
Normal file
BIN
pages/static/resources/images/menuspacer.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 164 B |
BIN
pages/static/resources/images/refresh.png
Normal file
BIN
pages/static/resources/images/refresh.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 665 B |
BIN
pages/static/resources/logo.png
Normal file
BIN
pages/static/resources/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
BIN
pages/static/resources/logo_old.png
Normal file
BIN
pages/static/resources/logo_old.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
36
pages/static/webapp.html
Normal file
36
pages/static/webapp.html
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Discross</title>
|
||||
<meta name="description" content="A work-in-progress unofficial Discord relay (that acts like a client) aiming to support all platforms that support HTML.">
|
||||
<meta name="keywords" content="Discord,client,wii,nintendo switch,switch">
|
||||
<meta name="author" content="circuit10#0158">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<!-- iOS web app support - https://gist.github.com/tfausak/2222823n !-->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-title" content="Discross">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="viewport" content="initial-scale=1,minimum-scale=1,maximum-scale=1">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<link rel="apple-touch-icon" href="resources/logo.png">
|
||||
<script>(function(a,b,c){if(c in b&&b[c]){var d,e=a.location,f=/^(a|html)$/i;a.addEventListener("click",function(a){d=a.target;while(!f.test(d.nodeName))d=d.parentNode;"href"in d&&(d.href.indexOf("http")||~d.href.indexOf(e.host))&&(a.preventDefault(),e.href=d.href)},!1)}})(document,window.navigator,"standalone")</script>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%
|
||||
}
|
||||
iframe {
|
||||
border: none;
|
||||
width: 100%;
|
||||
height: 100%
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#303338" style="margin: 0;">
|
||||
<iframe src="index.html">
|
||||
</body>
|
||||
</html>
|
||||
103
pages/templates/channel.html
Normal file
103
pages/templates/channel.html
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Discross - #general</title>
|
||||
<style>
|
||||
body {
|
||||
background: #303338;
|
||||
}
|
||||
|
||||
br.nodisp {
|
||||
display: none
|
||||
}
|
||||
|
||||
th {
|
||||
vertical-align: top;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
text-align: left;
|
||||
font-weight: 400!important
|
||||
}
|
||||
|
||||
th.join {
|
||||
vertical-align: middle
|
||||
}
|
||||
|
||||
hr {
|
||||
border-top: none;
|
||||
margin-bottom: 15px;
|
||||
border-bottom: solid 1px #393c40;
|
||||
border-left: solid 1px #393c40;
|
||||
border-right: solid 1px #393c40
|
||||
}
|
||||
|
||||
table {
|
||||
padding-bottom: 5px
|
||||
}
|
||||
|
||||
form table {
|
||||
height: 86px;
|
||||
background: #303338;
|
||||
width: 100%;
|
||||
padding: 15px 0 0 8px;
|
||||
border-top: solid 1px #393c40
|
||||
}
|
||||
|
||||
a {
|
||||
color: #647dcd;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#303338">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top" style="vertical-align: top;">
|
||||
<div class="links">
|
||||
<a href="../server/{$SERVER_ID}"><img src="/resources/images/menu.png" alt="Menu" style="position: fixed; top: 32px;left: 12px;"></a>
|
||||
<br><img src="/resources/images/menuspacer.png" alt=" " height="14px" width="32px"></div>
|
||||
<br>
|
||||
</td>
|
||||
<td>
|
||||
<div id="msgcontainer">
|
||||
{$MESSAGES}
|
||||
</div>
|
||||
<div id = "myList"></div> <!-- TODO: Remove -->
|
||||
<br>
|
||||
<a id="end" name="end"></a>
|
||||
<form action="../send">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="middle" width="23px" style="vertical-align: middle; width: 23px;">
|
||||
<a href="../server/{$SERVER_ID}"><img src="/resources/images/menu.png" alt="Menu" style="position: fixed; top: 32px;left: 12px;"></a>
|
||||
</td>
|
||||
<td>
|
||||
<input type="hidden" id="channel" name="channel" value="{$CHANNEL_ID}">
|
||||
<input type="hidden" id="lite" name="lite" value="False">
|
||||
<div style="box-sizing: border-box;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;padding: 16px;background: #393c40;width: 100%;border-radius: 10px;">
|
||||
{$INPUT}
|
||||
</div>
|
||||
</td>
|
||||
<td style="width: 55px;">
|
||||
<input type="submit" style="width: 70px;right: 17px;position: relative;border-radius: 10px;border: transparent;color: #dddddd;height: 50px;background: #393c40;" value="Send">
|
||||
</td>
|
||||
<td valign="middle" style="vertical-align: middle; width: 48px;">
|
||||
<a href="{$REFRESH_URL}"><img src="/resources/images/refresh.png" alt="Refresh"></a>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<script src="/connection.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
1
pages/templates/channel/input.html
Normal file
1
pages/templates/channel/input.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
<input type="text" name="message" id="message" value="" style="color: #dddddd;background: #393c40;border: none;width: 100%;outline: none;box-shadow: 0 0 0 50px #393c40 inset;-webkit-text-fill-color: #dddddd;" required="" placeholder="Message #general">
|
||||
1
pages/templates/channel/input_disabled.html
Normal file
1
pages/templates/channel/input_disabled.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
<input type="text" name="message" id="message" value="" style="color: #dddddd;background: #393c40;border: none;width: 100%;outline: none;box-shadow: 0 0 0 50px #393c40 inset;-webkit-text-fill-color: #dddddd;" required="true" disabled="true" placeholder='You do not have permission to send messages in this channel.'>
|
||||
7
pages/templates/channel/no_message_history.html
Normal file
7
pages/templates/channel/no_message_history.html
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<br>
|
||||
<font face="Arial, Helvetica, sans-serif" color="#dddddd">
|
||||
         
|
||||
You do not have permission to view the message history of this channel.
|
||||
</font>
|
||||
<br>
|
||||
<br>
|
||||
4
pages/templates/channellist/categorychannel.html
Normal file
4
pages/templates/channellist/categorychannel.html
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<font size="1" color="#999999" face="Arial, Helvetica, sans-serif">
|
||||
{$CHANNEL_NAME}
|
||||
</font>
|
||||
<br>
|
||||
6
pages/templates/channellist/textchannel.html
Normal file
6
pages/templates/channellist/textchannel.html
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<a href="{$CHANNEL_LINK}" style="text-decoration none;">
|
||||
<font color="#999999" size="4" face="Arial, Helvetica, sans-serif">
|
||||
# {$CHANNEL_NAME}
|
||||
</font>
|
||||
</a>
|
||||
<br>
|
||||
47
pages/templates/forgot.html
Normal file
47
pages/templates/forgot.html
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Discross - Forgot username or password</title>
|
||||
</head>
|
||||
<body style="margin: 0;" bgcolor="#303338">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="index.html"><img src="resources/logo.png" alt="Logo"></a></td>
|
||||
<td> </td>
|
||||
<td><font size="7" face="Arial, Helvetica, sans-serif" color="#dddddd">DISCROSS</font></td>
|
||||
<td width="100%" align="right"><font size="4" face="Arial, Helvetica, sans-serif" color="#dddddd"> <a style="color: #dddddd;" href="login.html"><font color="#dddddd">Login</font></a> </font><font size="4" face="Arial, Helvetica, sans-serif" color="#dddddd"> <a style="color: #dddddd;" href="register.html"><font color="#dddddd">Register</font></a> </font></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr style="margin: 0; position: relative; bottom: 4px;">
|
||||
<br>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
<form action="/forgot" method="post">
|
||||
<font size="6" face="Arial, Helvetica, sans-serif" color="#dddddd">Forgot username or password<br>
|
||||
WARNING:<br>
|
||||
This will delete your account so that you can create a new one.</font>
|
||||
<font face="Arial, Helvetica, sans-serif" color="#dddddd">
|
||||
<br><br>
|
||||
Verification code:
|
||||
<br><br>
|
||||
Type ^connect on a server with Discross to get this.
|
||||
<br><br>
|
||||
<div style="padding: 16px;background: #393c40;width: 300px;border-radius: 10px;"><input type="text" name="token" id="token" value="" style="color: #dddddd;background: #393c40;border: none;width: 100%;outline: none;box-shadow: 0 0 0 50px #393c40 inset;-webkit-text-fill-color: #dddddd;" placeholder="Verification code"></div>
|
||||
<br>{$ERROR}<br>
|
||||
<input type="submit" style="border-radius: 10px;color: #dddddd;height: 44px;width:150px;border: none;background: #393c40;" value="Delete account">
|
||||
</font>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
55
pages/templates/guest.html
Normal file
55
pages/templates/guest.html
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Discross - Guest Login</title>
|
||||
</head>
|
||||
<body style="margin: 0;" bgcolor="#303338">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="index.html"><img src="resources/logo.png" alt="Logo"></a></td>
|
||||
<td> </td>
|
||||
<td><font size="7" face="Arial, Helvetica, sans-serif" color="#dddddd">DISCROSS</font></td>
|
||||
<td width="100%" align="right"><font size="4" face="Arial, Helvetica, sans-serif" color="#dddddd"> <a style="color: #dddddd;" href="login.html"><font color="#dddddd">Login</font></a> </font><font size="4" face="Arial, Helvetica, sans-serif" color="#dddddd"> <a style="color: #dddddd;" href="register.html"><font color="#dddddd">Register</font></a> </font></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr style="margin: 0; position: relative; bottom: 4px;">
|
||||
<br>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
<form action="/guest" method="post">
|
||||
<font size="6" face="Arial, Helvetica, sans-serif" color="#dddddd">Guest Login</font><br><br>
|
||||
<font face="Arial, Helvetica, sans-serif" color="#dddddd">
|
||||
Choose a username:
|
||||
<br><br>
|
||||
<div style="padding: 16px;background: #393c40;width: 300px;border-radius: 10px;"><input type="text" name="username" id="username" value="" style="color: #dddddd;background: #393c40;border: none;width: 100%;outline: none;box-shadow: 0 0 0 50px #393c40 inset;-webkit-text-fill-color: #dddddd;" placeholder="Username"></div>
|
||||
<br>
|
||||
<a href="/forgot.html" style="text-decoration none;">
|
||||
<font color="#999999" size="4" face="Arial, Helvetica, sans-serif">
|
||||
Forgot username or password
|
||||
</font>
|
||||
</a>
|
||||
<br>
|
||||
<br>{$ERROR}<br>
|
||||
<input type="hidden" id="redirect" name="redirect" value="{$REDIRECT_URL}">
|
||||
<input type="submit" style="border-radius: 10px;color: #dddddd;height: 44px;width:150px;border: none;background: #393c40;" value="Login">
|
||||
<br>
|
||||
<br>
|
||||
<a style="text-decoration none;" href="/login.html">
|
||||
<font size="4" face="Arial, Helvetica, sans-serif" color="#999999">Normal login</font>
|
||||
</a>
|
||||
</font>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
1
pages/templates/icon.html
Normal file
1
pages/templates/icon.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
<a href="/server/{$SERVER_ID}"><img src="{$SERVER_ICON_URL}" alt="{$SERVER_NAME}" width="48px" height="48px"></a>
|
||||
86
pages/templates/index.html
Normal file
86
pages/templates/index.html
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Discross - Home</title>
|
||||
<meta name="description"
|
||||
content="A work-in-progress unofficial Discord relay (that acts like a client) aiming to support all platforms that support HTML.">
|
||||
<meta name="keywords" content="Discord,client,wii,nintendo switch,switch">
|
||||
<meta name="author" content="circuit10#0158">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#303338" style="margin: 0;">
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="./resources/logo.png" alt="Logo"></td>
|
||||
|
||||
<td>
|
||||
<font size="7" face="Arial, Helvetica, sans-serif" color="#dddddd">discross</font>
|
||||
</td>
|
||||
<td width="100%" align="right">
|
||||
<font size="4" face="Arial, Helvetica, sans-serif" color="#dddddd">  
|
||||
{$MENU_OPTIONS}
|
||||
</font>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr style="margin: 0; position: relative; bottom: 4px;">
|
||||
<br>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
<a style="color: #647dcd;" href='https://discordapp.com/invite/pXdeUqb'>
|
||||
<font color='#647dcd'>Join our Discord!</font>
|
||||
</a>
|
||||
<br>
|
||||
<a style="color: #647dcd;"
|
||||
href='https://discordapp.com/oauth2/authorize?client_id=596074053903581226&scope=bot&permissions=8'>
|
||||
<font color='#647dcd'>Add Discross to your server!</font>
|
||||
</a>
|
||||
<br>
|
||||
<a style="color: #647dcd;" href='https://github.com/Heath123/discross'>
|
||||
<font color='#647dcd'><del>Source code</del></font>
|
||||
</a>
|
||||
<font color='#dddddd'>Not uploaded yet</font>
|
||||
<br>
|
||||
<br>
|
||||
<font face="Arial, Helvetica, sans-serif" color="#dddddd">By logging in or registering you agree to the use of
|
||||
cookies</font>
|
||||
<br>
|
||||
<br>
|
||||
<font size="6" face="Arial, Helvetica, sans-serif" color="#dddddd">What is Discross?</font>
|
||||
<br>
|
||||
<br>
|
||||
<font face="Arial, Helvetica, sans-serif" color="#dddddd">A work-in-progress unofficial Discord relay (that
|
||||
acts like a client) aiming to support all platforms that support HTML. It uses webhooks and a bot so it
|
||||
doesn't need your user token, which would allow anyone to control your account. However, this means it only
|
||||
works on servers with the bot.
|
||||
<br><br>
|
||||
|
||||
<font size="6" face="Arial, Helvetica, sans-serif" color="#dddddd">What platforms are supported?</font>
|
||||
<br>
|
||||
<br>
|
||||
<font face="Arial, Helvetica, sans-serif" color="#dddddd">Virtually anything, although you may not get all
|
||||
features. Platforms that are confirmed to work, to some extent:</font>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<font face="Arial, Helvetica, sans-serif" color="#dddddd">
|
||||
<ul>
|
||||
<li>Nintendo Switch (requires a workaround to access the web browser)</li>
|
||||
<li>Nintendo Wii</li>
|
||||
<li>Windows 95/98</li>
|
||||
</ul>
|
||||
<font size="3" face="Arial, Helvetica, sans-serif" color="#aaaaaa">    Discross version
|
||||
1.2.0-node-dev</font>
|
||||
<br>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
3
pages/templates/index/logged_in.html
Normal file
3
pages/templates/index/logged_in.html
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<font color="#aaaaaa" size="2">Logged in as {$USER}</font>  
|
||||
<a style="color: #dddddd;" href="./server/"><font color="#dddddd">Server list</font></a>  
|
||||
<a style="color: #dddddd;" href="./logout"><font color="#dddddd">Logout</font></a>  
|
||||
2
pages/templates/index/logged_out.html
Normal file
2
pages/templates/index/logged_out.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<a style="color: #dddddd;" href="./login.html"><font color="#dddddd">Login</font></a>  
|
||||
<a style="color: #dddddd;" href="./register.html"><font color="#dddddd">Register</font></a>  
|
||||
59
pages/templates/login.html
Normal file
59
pages/templates/login.html
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Discross - Login</title>
|
||||
</head>
|
||||
<body style="margin: 0;" bgcolor="#303338">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="index.html"><img src="resources/logo.png" alt="Logo"></a></td>
|
||||
<td> </td>
|
||||
<td><font size="7" face="Arial, Helvetica, sans-serif" color="#dddddd">DISCROSS</font></td>
|
||||
<td width="100%" align="right"><font size="4" face="Arial, Helvetica, sans-serif" color="#dddddd"> <a style="color: #dddddd;" href="login.html"><font color="#dddddd">Login</font></a> </font><font size="4" face="Arial, Helvetica, sans-serif" color="#dddddd"> <a style="color: #dddddd;" href="register.html"><font color="#dddddd">Register</font></a> </font></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr style="margin: 0; position: relative; bottom: 4px;">
|
||||
<br>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
<form action="/login" method="post">
|
||||
<font size="6" face="Arial, Helvetica, sans-serif" color="#dddddd">Login</font><br><br>
|
||||
<font face="Arial, Helvetica, sans-serif" color="#dddddd">
|
||||
Username:
|
||||
<br><br>
|
||||
<div style="padding: 16px;background: #393c40;width: 300px;border-radius: 10px;"><input type="text" name="username" id="username" value="" style="color: #dddddd;background: #393c40;border: none;width: 100%;outline: none;box-shadow: 0 0 0 50px #393c40 inset;-webkit-text-fill-color: #dddddd;" placeholder="Username"></div>
|
||||
<br>
|
||||
Password:
|
||||
<br><br>
|
||||
<div style="padding: 16px;background: #393c40;width: 300px;border-radius: 10px;"><input type="password" name="password" id="password" value="" style="color: #dddddd;background: #393c40;border: none;width: 100%;outline: none;box-shadow: 0 0 0 50px #393c40 inset;-webkit-text-fill-color: #dddddd;" placeholder="Password"></div>
|
||||
<br>
|
||||
<a href="/forgot.html" style="text-decoration none;">
|
||||
<font color="#999999" size="4" face="Arial, Helvetica, sans-serif">
|
||||
Forgot username or password
|
||||
</font>
|
||||
</a>
|
||||
<br>
|
||||
<br>{$ERROR}<br>
|
||||
<input type="hidden" id="redirect" name="redirect" value="{$REDIRECT_URL}">
|
||||
<input type="submit" style="border-radius: 10px;color: #dddddd;height: 44px;width:150px;border: none;background: #393c40;" value="Login">
|
||||
<!-- <br>
|
||||
<br>
|
||||
<a style="text-decoration none;" href="/guest.html">
|
||||
<font size="4" face="Arial, Helvetica, sans-serif" color="#999999">Guest mode</font>
|
||||
</a> !-->
|
||||
</font>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
1
pages/templates/login/error.html
Normal file
1
pages/templates/login/error.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
<font color="#ff0000">{$ERROR_MESSAGE}</font><br>
|
||||
1
pages/templates/message/first_message_content.html
Normal file
1
pages/templates/message/first_message_content.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
<span id="647916312823070720" name="647916312823070720" class="firstmessage">{$MESSAGE_TEXT}</span>
|
||||
1
pages/templates/message/mention.html
Normal file
1
pages/templates/message/mention.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
<font color="#647dcd" style="background-color: rgba(100,125,205,0.1);">{$USERNAME}</font>
|
||||
1
pages/templates/message/merged_message_content.html
Normal file
1
pages/templates/message/merged_message_content.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
<span id="647916335015395338" name="647916335015395338" class="message"><br>{$MESSAGE_TEXT}</span></font>
|
||||
27
pages/templates/message/message.html
Normal file
27
pages/templates/message/message.html
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<div class="message">
|
||||
<hr noshade="">
|
||||
<br class="nodisp">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top"><img class="avatar" src="{$PROFILE_URL}" width="40px" height="40px" style="border-radius: 99px;"> </td>
|
||||
<td valign="top"><font color="#303338">- </font> </td>
|
||||
<td valign="top" align="left">
|
||||
<div class="content">
|
||||
|
||||
<div>
|
||||
<font onclick="document.getElementById('message').value += {$TAG}" class="name" color="#ffffff" face="Arial, Helvetica, sans-serif">{$MESSAGE_AUTHOR}</font>
|
||||
<font class="date" size="1" face="Arial, Helvetica, sans-serif" color="#888888">{$MESSAGE_DATE}</font><br>
|
||||
</div>
|
||||
|
||||
<div class="messagecontent">
|
||||
|
||||
<font size="2" face="Arial, Helvetica, sans-serif" color="#dddddd">
|
||||
{$MESSAGE_CONTENT}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
77
pages/templates/register.html
Normal file
77
pages/templates/register.html
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Discross - Register</title>
|
||||
</head>
|
||||
<body style="margin: 0;" bgcolor="#303338">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="index.html"><img src="resources/logo.png" alt="Logo"></a></td>
|
||||
<td> </td>
|
||||
<td><font size="7" face="Arial, Helvetica, sans-serif" color="#dddddd">DISCROSS</font></td>
|
||||
<td width="100%" align="right"><font size="4" face="Arial, Helvetica, sans-serif" color="#dddddd"> <a style="color: #dddddd;" href="login.html"><font color="#dddddd">Login</font></a> </font><font size="4" face="Arial, Helvetica, sans-serif" color="#dddddd"> <a style="color: #dddddd;" href="register.html"><font color="#dddddd">Register</font></a> </font></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr style="margin: 0; position: relative; bottom: 4px;">
|
||||
<br>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
<form action="/register" method="post">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<font size="6" face="Arial, Helvetica, sans-serif" color="#dddddd">Register</font><br><br>
|
||||
<font face="Arial, Helvetica, sans-serif" color="#dddddd">
|
||||
Username:
|
||||
<br><br>
|
||||
<div style="padding: 16px;background: #393c40;width: 300px;border-radius: 10px;"><input type="text" name="username" id="username" value="" style="color: #dddddd;background: #393c40;border: none;width: 100%;outline: none;box-shadow: 0 0 0 50px #393c40 inset;-webkit-text-fill-color: #dddddd;" placeholder="Username"></div>
|
||||
<br><br>
|
||||
<font face="Arial, Helvetica, sans-serif" color="#dddddd">
|
||||
Password:<br><br>(don't use your Discord password)
|
||||
<br><br>
|
||||
<div style="padding: 16px;background: #393c40;width: 300px;border-radius: 10px;"><input type="password" name="password" id="password" value="" style="color: #dddddd;background: #393c40;border: none;width: 100%;outline: none;box-shadow: 0 0 0 50px #393c40 inset;-webkit-text-fill-color: #dddddd;" placeholder="Password"></div>
|
||||
<br>
|
||||
<font face="Arial, Helvetica, sans-serif" color="#dddddd">
|
||||
Confirm password:
|
||||
<br><br>
|
||||
<div style="padding: 16px;background: #393c40;width: 300px;border-radius: 10px;"><input type="password" name="confirm" id="confirm" value="" style="color: #dddddd;background: #393c40;border: none;width: 100%;outline: none;box-shadow: 0 0 0 50px #393c40 inset;-webkit-text-fill-color: #dddddd;" placeholder="Confirm password"></div>
|
||||
<br>{$ERROR}<br>
|
||||
<input type="submit" style="border-radius: 10px;color: #dddddd;height: 44px;width:150px;border: none;background: #393c40;;" value="Register">
|
||||
</font>
|
||||
</font>
|
||||
</font>
|
||||
</td>
|
||||
<td valign="top">
|
||||
|
||||
</td>
|
||||
<td style="vetical-align: top;" valign="top">
|
||||
<br><br><br>
|
||||
<font face="Arial, Helvetica, sans-serif" color="#dddddd">
|
||||
Verification code:
|
||||
<br><br>
|
||||
Type ^connect on a server with Discross to get this.
|
||||
<br><br>
|
||||
<div style="padding: 16px;background: #393c40;width: 300px;border-radius: 10px;"><input type="text" name="token" id="token" value="" style="color: #dddddd;background: #393c40;border: none;width: 100%;outline: none;box-shadow: 0 0 0 50px #393c40 inset;-webkit-text-fill-color: #dddddd;" placeholder="Verification code"></div>
|
||||
</font>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
32
pages/templates/server.html
Normal file
32
pages/templates/server.html
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<title>Discross - Menu</title>
|
||||
<style>
|
||||
hr {
|
||||
border: solid 1px #494c50;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#303338">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top" style="vertical-align: top;">
|
||||
<a href="/server/"><img src="/resources/logo.png" alt="Home" style="border-radius: 999px;" width="48px" height="48px"></a><br>
|
||||
<hr noshade>
|
||||
{$SERVER_LIST}
|
||||
</td>
|
||||
<td><font color="#303338">- </font></td>
|
||||
<td valign="top" style="vertical-align: top;">
|
||||
{$CHANNEL_LIST}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
1
pages/templates/server/invalid_server.html
Normal file
1
pages/templates/server/invalid_server.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
<font face="Arial, Helvetica, sans-serif" color="#dddddd">Click on a server! <a href="/"><font face="Arial, Helvetica, sans-serif" color="#dddddd">Home</font></a></font>
|
||||
1
pages/templates/server/server_icon.html
Normal file
1
pages/templates/server/server_icon.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
<a href="{$SERVER_URL}"><img height="48px" width="48px" src="{$SERVER_ICON_URL}" alt="{$SERVER_NAME}" style="border-radius: 999px;"></a><br><br>
|
||||
Loading…
Add table
Add a link
Reference in a new issue