config support, user account support, private message support
This commit is contained in:
parent
7a27a7f1b9
commit
9199002e12
10 changed files with 484 additions and 50 deletions
27
README.md
27
README.md
|
@ -8,17 +8,24 @@ A CLI-based client for Discord inspired by [SDF](https://sdf.org)'s [commode](ht
|
|||
## Usage
|
||||
1. `pnpm i`
|
||||
2. `node src/index.js <token>`
|
||||
Your token will be then stored in `.comcordrc` after the first launch.
|
||||
|
||||
Currently only bot accounts are supported, and that is unlikely to change anytime soon.
|
||||
~~Eris has a lot of user-only endpoints implemented, but it would require hacking apart Eris to do the things nessicary to spoof being the actual client.~~
|
||||
(I have no idea currently what the state of user support in Oceanic is)
|
||||
I also don't want to give skids an easy point of reference of how to spoof the client. :^)
|
||||
### User Accounts
|
||||
User accounts are *partially* supported via `allowUserAccounts=true` in your `.comcordrc`.
|
||||
This is use at your own risk, despite spoofing the official client. I am not responsible for any banned accounts.
|
||||
|
||||
#### Guild members not populating
|
||||
This is due to Oceanic not implementing Lazy Guilds as they are user account specific. **DO NOT bother Oceanic to implement it!** They are purely a bot-focused library.
|
||||
|
||||
If you are willing to implement Lazy Guilds based off of [unofficial documentation](https://luna.gitlab.io/discord-unofficial-docs/lazy_guilds.html)
|
||||
and my already existing horrible hacks to make user accounts work in the first place, feel free to send a PR (on GitLab, GitHub repo is a read only mirror).
|
||||
|
||||
### Bot Accounts (prefered)
|
||||
You **MUST** grant your bot all Privileged Gateway Intents.
|
||||
|
||||
## Design Decisions
|
||||
* Node.js was chosen currently due to familiarity.
|
||||
* ~~Eris~~ Oceanic was chosen due to familiarity and the nature of everything not being abstracted out to 200 different classes unlike discord.js.
|
||||
* Oceanic was chosen due to familiarity and the nature of everything not being abstracted out to 200 different classes unlike discord.js.
|
||||
* "Jank" by design. While I don't expect anyone to actually use comcord on serial terminals or teletypes other than for meme factor, the option is still there.
|
||||
|
||||
## TODO
|
||||
|
@ -39,6 +46,9 @@ You **MUST** grant your bot all Privileged Gateway Intents.
|
|||
- [x] Clear (c)
|
||||
- [ ] Surf channels forwards (>)
|
||||
- [ ] Surf channels backwards (<)
|
||||
- [x] AFK toggle (A)
|
||||
- [x] Send DM (s)
|
||||
- [x] Answer DM (a)
|
||||
- [x] Message Receiving
|
||||
- [x] Markdown styling
|
||||
- [ ] Common markdown (bold, italic, etc)
|
||||
|
@ -54,8 +64,9 @@ You **MUST** grant your bot all Privileged Gateway Intents.
|
|||
- [x] Puts incoming messages into queue whilst in send mode
|
||||
- [ ] Mentions
|
||||
- [ ] Replies
|
||||
- [ ] Configuration
|
||||
- [ ] Default guild/channel
|
||||
- [x] Configuration
|
||||
- [x] Default guild/channel
|
||||
- No way to set in client (yet?), `defaultChannel=` and `defaultGuild=` in your `.comcordrc`.
|
||||
- [ ] Threads
|
||||
- [ ] Not have the token just be in argv
|
||||
- [x] Not have the token just be in argv
|
||||
- [x] Not have everything in one file
|
||||
|
|
|
@ -3,6 +3,7 @@ const {updatePresence} = require("../lib/presence");
|
|||
|
||||
addCommand("A", "toggles AFK mode", function () {
|
||||
if (comcord.state.afk == true) {
|
||||
comcord.state.afk = false;
|
||||
comcord.client.shards.forEach((shard) => (shard.presence.afk = false));
|
||||
comcord.client.editStatus("online");
|
||||
console.log("<you have returned>");
|
||||
|
|
|
@ -40,21 +40,22 @@ function listUsers() {
|
|||
);
|
||||
|
||||
const online = [...guild.members.values()].filter((m) => m.presence);
|
||||
online.sort((a, b) => a.name - b.name);
|
||||
online.sort((a, b) => a.tag.localeCompare(b.tag));
|
||||
|
||||
let longest = 0;
|
||||
for (const member of online) {
|
||||
const name = member.user.tag;
|
||||
const name = member.tag;
|
||||
if (name.length + 3 > longest) longest = name.length + 3;
|
||||
}
|
||||
|
||||
const columns = Math.ceil(process.stdout.columns / longest);
|
||||
const columns = Math.floor(process.stdout.columns / longest);
|
||||
|
||||
let index = 0;
|
||||
for (const member of online) {
|
||||
const name = member.user.tag;
|
||||
const name = member.tag;
|
||||
const status = getStatus(member.presence.status);
|
||||
const nameAndStatus = chalk.reset(name) + status;
|
||||
const nameAndStatus =
|
||||
(member.user.bot ? chalk.yellow(name) : chalk.reset(name)) + status;
|
||||
|
||||
index++;
|
||||
process.stdout.write(
|
||||
|
|
51
src/commands/privateMessages.js
Normal file
51
src/commands/privateMessages.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
const chalk = require("chalk");
|
||||
|
||||
const {addCommand} = require("../lib/command");
|
||||
const {startPrompt} = require("../lib/prompt");
|
||||
const {listUsers} = require("./listUsers");
|
||||
|
||||
function startDM(user) {
|
||||
startPrompt(":msg> ", async function (input) {
|
||||
if (input == "") {
|
||||
console.log(`\n<message not sent to ${user.tag}>`);
|
||||
} else {
|
||||
try {
|
||||
const channel = await user.createDM();
|
||||
await channel.createMessage({content: input});
|
||||
console.log(chalk.bold.green(`\n<message sent to ${user.tag}>`));
|
||||
} catch (err) {
|
||||
console.log("\n<failed to send message: " + err.message + ">");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addCommand("s", "send private", function () {
|
||||
console.log("Provide a RECIPIENT");
|
||||
startPrompt(":to> ", function (who) {
|
||||
let target;
|
||||
for (const user of comcord.client.users.values()) {
|
||||
if (user.tag == who) {
|
||||
target = user;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (target) {
|
||||
console.log("");
|
||||
startDM(target);
|
||||
} else {
|
||||
listUsers();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
addCommand("a", "answer a send", function () {
|
||||
if (comcord.state.lastDM) {
|
||||
console.log(chalk.bold.green(`<answering ${comcord.state.lastDM.tag}>`));
|
||||
startDM(comcord.state.lastDM);
|
||||
} else {
|
||||
// FIXME: figure out the actual message in com
|
||||
console.log("<no one to answer>");
|
||||
}
|
||||
});
|
|
@ -56,3 +56,5 @@ function switchGuild(input) {
|
|||
addCommand("G", "goto guild", function () {
|
||||
startPrompt(":guild> ", switchGuild);
|
||||
});
|
||||
|
||||
module.exports = {switchGuild};
|
||||
|
|
219
src/index.js
219
src/index.js
|
@ -1,15 +1,36 @@
|
|||
const {Client} = require("oceanic.js");
|
||||
const chalk = require("chalk");
|
||||
const {Client, Constants} = require("oceanic.js");
|
||||
const DiscordRPC = require("discord-rpc");
|
||||
const chalk = require("chalk");
|
||||
const fs = require("fs");
|
||||
|
||||
const rcfile = require("./lib/rcfile");
|
||||
const config = {};
|
||||
|
||||
if (fs.existsSync(rcfile.path)) {
|
||||
console.log("% Reading " + rcfile.path + " ...");
|
||||
rcfile.readFile(config);
|
||||
}
|
||||
|
||||
const CLIENT_ID = "1026163285877325874";
|
||||
|
||||
const token = process.argv[2];
|
||||
if (!config.token && token) {
|
||||
console.log("% Writing token to .comcordrc");
|
||||
config.token = token;
|
||||
rcfile.writeFile(config);
|
||||
}
|
||||
|
||||
if (!config.token && !token) {
|
||||
console.log("No token provided.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
process.title = "comcord";
|
||||
|
||||
global.comcord = {
|
||||
config,
|
||||
state: {
|
||||
rpcConnected: false,
|
||||
startTime: Date.now(),
|
||||
currentGuild: null,
|
||||
currentChannel: null,
|
||||
|
@ -22,21 +43,28 @@ global.comcord = {
|
|||
commands: {},
|
||||
};
|
||||
const client = new Client({
|
||||
auth: "Bot " + token,
|
||||
auth:
|
||||
(config.allowUserAccounts == "true" ? "" : "Bot ") +
|
||||
(token ?? config.token),
|
||||
defaultImageFormat: "png",
|
||||
defaultImageSize: 1024,
|
||||
gateway: {
|
||||
intents: ["ALL"],
|
||||
activities: [
|
||||
{
|
||||
name: "comcord",
|
||||
type: "GAME",
|
||||
application_id: CLIENT_ID,
|
||||
timestamps: {
|
||||
start: comcord.state.startTime,
|
||||
maxShards: 1,
|
||||
concurrency: 1,
|
||||
presence: {
|
||||
status: "online",
|
||||
activities: [
|
||||
{
|
||||
name: "comcord",
|
||||
type: 0,
|
||||
application_id: CLIENT_ID,
|
||||
timestamps: {
|
||||
start: comcord.state.startTime,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
comcord.client = client;
|
||||
|
@ -53,10 +81,11 @@ require("./commands/help");
|
|||
const {sendMode} = require("./commands/send");
|
||||
require("./commands/emote");
|
||||
const {listGuilds} = require("./commands/listGuilds");
|
||||
require("./commands/switchGuild"); // loads listChannels and listUsers
|
||||
const {switchGuild} = require("./commands/switchGuild"); // loads listChannels and listUsers
|
||||
require("./commands/switchChannel"); //loads listUsers
|
||||
require("./commands/history"); // includes extended history
|
||||
require("./commands/afk");
|
||||
require("./commands/privateMessages");
|
||||
|
||||
process.stdin.setRawMode(true);
|
||||
process.stdin.resume();
|
||||
|
@ -70,20 +99,44 @@ client.once("ready", function () {
|
|||
|
||||
listGuilds();
|
||||
|
||||
rpc
|
||||
.login({
|
||||
clientId: CLIENT_ID,
|
||||
})
|
||||
.catch(function () {});
|
||||
if (config.defaultGuild) {
|
||||
const guild = client.guilds.get(config.defaultGuild);
|
||||
if (guild != null) {
|
||||
if (config.defaultChannel) {
|
||||
comcord.state.currentChannel = config.defaultChannel;
|
||||
comcord.state.lastChannel.set(
|
||||
config.defaultGuild,
|
||||
config.defaultChannel
|
||||
);
|
||||
}
|
||||
switchGuild(guild.name);
|
||||
} else {
|
||||
console.log("% This account is not in the defined default guild.");
|
||||
}
|
||||
} else {
|
||||
if (config.defaultChannel) {
|
||||
console.log("% Default channel defined without defining default guild.");
|
||||
}
|
||||
}
|
||||
|
||||
if (client.user.bot) {
|
||||
rpc
|
||||
.login({
|
||||
clientId: CLIENT_ID,
|
||||
})
|
||||
.catch(function () {});
|
||||
}
|
||||
});
|
||||
client.on("error", function () {});
|
||||
|
||||
rpc.on("connected", function () {
|
||||
comcord.state.rpcConnected = true;
|
||||
updatePresence();
|
||||
});
|
||||
let retryingRPC = false;
|
||||
rpc.once("ready", function () {
|
||||
rpc.transport.on("close", function () {
|
||||
comcord.state.rpcConnected = false;
|
||||
if (!retryingRPC) {
|
||||
retryingRPC = true;
|
||||
setTimeout(function () {
|
||||
|
@ -102,21 +155,55 @@ rpc.once("ready", function () {
|
|||
});
|
||||
rpc.on("error", function () {});
|
||||
|
||||
client.on("messageCreate", function (msg) {
|
||||
client.on("messageCreate", async function (msg) {
|
||||
if (msg.author.id === client.user.id) return;
|
||||
|
||||
if (msg.channel.id == comcord.state.currentChannel) {
|
||||
if (msg.channelID && !msg.channel) {
|
||||
try {
|
||||
const dmChannel = await msg.author.createDM();
|
||||
if (dmChannel.id === msg.channelID) {
|
||||
msg.channel = dmChannel;
|
||||
}
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(msg.channel ? msg.channel.id : msg.channelID) ==
|
||||
comcord.state.currentChannel ||
|
||||
msg.channel?.recipient != null
|
||||
) {
|
||||
if (comcord.state.inPrompt) {
|
||||
comcord.state.messageQueue.push(msg);
|
||||
} else {
|
||||
processMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.channel?.recipient != null) {
|
||||
comcord.state.lastDM = msg.author;
|
||||
}
|
||||
});
|
||||
client.on("messageUpdate", function (msg, old) {
|
||||
client.on("messageUpdate", async function (msg, old) {
|
||||
if (msg.author.id === client.user.id) return;
|
||||
|
||||
if (msg.channel.id == comcord.state.currentChannel) {
|
||||
if (msg.channelID && !msg.channel) {
|
||||
try {
|
||||
const dmChannel = await msg.author.createDM();
|
||||
if (dmChannel.id === msg.channelID) {
|
||||
msg.channel = dmChannel;
|
||||
}
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(msg.channel ? msg.channel.id : msg.channelID) ==
|
||||
comcord.state.currentChannel ||
|
||||
msg.channel?.recipient != null
|
||||
) {
|
||||
if (msg.content == old.content) return;
|
||||
|
||||
if (comcord.state.inPrompt) {
|
||||
|
@ -125,6 +212,10 @@ client.on("messageUpdate", function (msg, old) {
|
|||
processMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.channel?.recipient != null) {
|
||||
comcord.state.lastDM = msg.author;
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on("data", async function (key) {
|
||||
|
@ -158,7 +249,89 @@ process.stdin.on("data", async function (key) {
|
|||
}
|
||||
});
|
||||
|
||||
client.connect();
|
||||
if (
|
||||
config.allowUserAccounts == "true" &&
|
||||
!(token ?? config.token).startsWith("Bot ")
|
||||
) {
|
||||
if (fetch == null) {
|
||||
console.log("Node v18+ needed for user account support.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
(async function () {
|
||||
comcord.clientSpoof = require("./lib/clientSpoof");
|
||||
const superProperties = await comcord.clientSpoof.getSuperProperties();
|
||||
|
||||
console.log("% Allowing non-bot tokens to connect");
|
||||
const connectLines = client.connect.toString().split("\n");
|
||||
connectLines.splice(0, 4);
|
||||
connectLines.splice(-1, 1);
|
||||
|
||||
const newConnect = new client.connect.constructor(connectLines.join("\n"));
|
||||
client.connect = newConnect.bind(client);
|
||||
|
||||
// gross hack
|
||||
global.Constants_1 = Constants;
|
||||
try {
|
||||
global.Erlpack = require("erlpack");
|
||||
} catch {
|
||||
global.Erlpack = false;
|
||||
}
|
||||
|
||||
console.log("% Injecting headers into request handler");
|
||||
client.rest.handler.options.userAgent = `Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) discord/${superProperties.client_version} Chrome/91.0.4472.164 Electron/13.6.6 Safari/537.36`;
|
||||
client.rest.handler._request = client.rest.handler.request.bind(
|
||||
client.rest.handler
|
||||
);
|
||||
client.rest.handler.request = async function (options) {
|
||||
options.headers = options.headers ?? {};
|
||||
options.headers["X-Super-Properties"] =
|
||||
await comcord.clientSpoof.getSuperPropertiesBase64();
|
||||
|
||||
return await this._request.apply(this, [options]);
|
||||
}.bind(client.rest.handler);
|
||||
|
||||
console.log("% Setting gateway connection properties");
|
||||
client.shards.options.connectionProperties = superProperties;
|
||||
|
||||
console.log("% Injecting application into READY payload");
|
||||
client.shards._spawn = client.shards.spawn.bind(client.shards);
|
||||
client.shards.spawn = function (id) {
|
||||
const res = this._spawn.apply(this, [id]);
|
||||
const shard = this.get(id);
|
||||
if (shard) {
|
||||
shard._onDispatch = shard.onDispatch.bind(shard);
|
||||
shard.onDispatch = async function (packet) {
|
||||
if (packet.t == "READY") {
|
||||
packet.d.application = {id: CLIENT_ID, flags: 565248};
|
||||
}
|
||||
|
||||
const ret = await this._onDispatch.apply(this, [packet]);
|
||||
|
||||
if (packet.t == "READY") {
|
||||
for (const guild of packet.d.guilds) {
|
||||
await this._onDispatch.apply(this, [
|
||||
{
|
||||
t: "GUILD_CREATE",
|
||||
d: guild,
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}.bind(shard);
|
||||
}
|
||||
|
||||
return res;
|
||||
}.bind(client.shards);
|
||||
|
||||
console.log("% Connecting to gateway now");
|
||||
await client.connect();
|
||||
})();
|
||||
} else {
|
||||
client.connect();
|
||||
}
|
||||
|
||||
console.log("COMcord (c)left 2022");
|
||||
console.log("Type 'h' for Commands");
|
||||
|
|
107
src/lib/clientSpoof.js
Normal file
107
src/lib/clientSpoof.js
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* This single file is **EXCLUDED** from the project license.
|
||||
*
|
||||
* (c) 2022 Cynthia Foxwell, all rights reserved.
|
||||
* Permission is hereby granted to redistribute this file ONLY with copies of comcord.
|
||||
* You may not reverse engineer, modify, copy, or redistribute this file for any other uses outside of comcord.
|
||||
*/
|
||||
|
||||
const os = require("os");
|
||||
|
||||
async function fetchMainPage() {
|
||||
const res = await fetch("https://discord.com/channels/@me");
|
||||
return await res.text();
|
||||
}
|
||||
|
||||
async function fetchAsset(assetPath) {
|
||||
return await fetch("https://discord.com/" + assetPath).then((res) =>
|
||||
res.text()
|
||||
);
|
||||
}
|
||||
|
||||
const MATCH_SCRIPT = '<script src="(.+?)" integrity=".+?">';
|
||||
const REGEX_SCRIPT = new RegExp(MATCH_SCRIPT);
|
||||
const REGEX_SCRIPT_GLOBAL = new RegExp(MATCH_SCRIPT, "g");
|
||||
|
||||
async function extractScripts() {
|
||||
const mainPage = await fetchMainPage();
|
||||
|
||||
return mainPage
|
||||
.match(REGEX_SCRIPT_GLOBAL)
|
||||
.map((script) => script.match(REGEX_SCRIPT)[1]);
|
||||
}
|
||||
|
||||
const REGEX_BUILD_NUMBER = /Build Number: (\d+), Version Hash:/;
|
||||
const REGEX_BUILD_NUMBER_SWC = /Build Number: "\).concat\("(\d+)"/;
|
||||
|
||||
async function getBuildNumber() {
|
||||
if (comcord.state.cachedBuildNumber) {
|
||||
return comcord.state.cachedBuildNumber;
|
||||
}
|
||||
|
||||
const scripts = await extractScripts();
|
||||
const chunkWithBuildInfoAsset = scripts[3];
|
||||
const chunkWithBuildInfo = await fetchAsset(chunkWithBuildInfoAsset);
|
||||
|
||||
const buildNumber =
|
||||
chunkWithBuildInfo.match(REGEX_BUILD_NUMBER_SWC)?.[1] ??
|
||||
chunkWithBuildInfo.match(REGEX_BUILD_NUMBER)?.[1];
|
||||
comcord.state.cachedBuildNumber = buildNumber;
|
||||
|
||||
return buildNumber;
|
||||
}
|
||||
|
||||
async function getClientVersion() {
|
||||
if (comcord.state.cachedClientVersion) {
|
||||
return comcord.state.cachedClientVersion;
|
||||
}
|
||||
|
||||
const data = await fetch(
|
||||
"https://updates.discord.com/distributions/app/manifests/latest?channel=stable&platform=win&arch=x86"
|
||||
).then((res) => res.json());
|
||||
const clientVersion = data.full.host_version.join(".");
|
||||
comcord.state.cachedClientVersion = clientVersion;
|
||||
|
||||
return clientVersion;
|
||||
}
|
||||
|
||||
async function getSuperProperties() {
|
||||
const buildNumber = await getBuildNumber();
|
||||
const clientVersion = await getClientVersion();
|
||||
|
||||
let _os;
|
||||
switch (process.platform) {
|
||||
case "win32":
|
||||
_os = "Windows";
|
||||
break;
|
||||
case "darwin":
|
||||
_os = "Mac OS X";
|
||||
break;
|
||||
case "linux":
|
||||
_os = "Linux";
|
||||
break;
|
||||
default:
|
||||
_os = process.platform;
|
||||
}
|
||||
|
||||
const props = {
|
||||
os: _os,
|
||||
browser: "Discord Client",
|
||||
releaseChannel: "stable",
|
||||
client_version: clientVersion,
|
||||
os_version: os.release(),
|
||||
os_arch: os.arch(),
|
||||
system_locale: "en-US",
|
||||
client_build_number: buildNumber,
|
||||
client_event_source: null,
|
||||
};
|
||||
return props;
|
||||
}
|
||||
|
||||
async function getSuperPropertiesBase64() {
|
||||
return Buffer.from(JSON.stringify(await getSuperProperties())).toString(
|
||||
"base64"
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {getSuperProperties, getSuperPropertiesBase64};
|
|
@ -155,6 +155,7 @@ function replaceTimestamps(_, time, format = "f") {
|
|||
|
||||
function formatMessage({
|
||||
name,
|
||||
tag,
|
||||
content,
|
||||
bot,
|
||||
attachments,
|
||||
|
@ -163,6 +164,7 @@ function formatMessage({
|
|||
noColor = false,
|
||||
dump = false,
|
||||
history = false,
|
||||
dm = false,
|
||||
}) {
|
||||
if (name.length + 2 > comcord.state.nameLength)
|
||||
comcord.state.nameLength = name.length + 2;
|
||||
|
@ -248,7 +250,15 @@ function formatMessage({
|
|||
.replace(REGEX_COMMAND, replaceCommands)
|
||||
.replace(REGEX_TIMESTAMP, replaceTimestamps);
|
||||
|
||||
if (
|
||||
if (dm) {
|
||||
if (noColor) {
|
||||
console.log(`*${tag}* ${content}\x07`);
|
||||
} else {
|
||||
console.log(
|
||||
chalk.bold.red(`*${tag}*`) + chalk.reset(" " + content + "\x07")
|
||||
);
|
||||
}
|
||||
} else if (
|
||||
(content.length > 1 &&
|
||||
content.startsWith("*") &&
|
||||
content.endsWith("*")) ||
|
||||
|
@ -310,13 +320,18 @@ function formatMessage({
|
|||
}
|
||||
}
|
||||
|
||||
function processMessage(msg, options) {
|
||||
function processMessage(msg, options = {}) {
|
||||
if (msg.channel?.recipient) {
|
||||
options.dm = true;
|
||||
}
|
||||
|
||||
if (msg.time) {
|
||||
console.log(msg.content);
|
||||
} else if (msg.content.indexOf("\n") > -1) {
|
||||
if (msg.content.match(REGEX_CODEBLOCK)) {
|
||||
formatMessage({
|
||||
name: msg.author.username,
|
||||
tag: msg.author.tag,
|
||||
bot: msg.author.bot,
|
||||
content: msg.content.replace(
|
||||
REGEX_CODEBLOCK_GLOBAL,
|
||||
|
@ -334,6 +349,7 @@ function processMessage(msg, options) {
|
|||
const line = lines[index];
|
||||
formatMessage({
|
||||
name: msg.author.username,
|
||||
tag: msg.author.tag,
|
||||
bot: msg.author.bot,
|
||||
content:
|
||||
line +
|
||||
|
@ -350,6 +366,7 @@ function processMessage(msg, options) {
|
|||
} else {
|
||||
formatMessage({
|
||||
name: msg.author.username,
|
||||
tag: msg.author.tag,
|
||||
bot: msg.author.bot,
|
||||
content: msg.content + (msg.editedTimestamp != null ? " (edited)" : ""),
|
||||
attachments: msg.attachments,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
const CLIENT_ID = "1026163285877325874";
|
||||
|
||||
function updatePresence() {
|
||||
let guild, channel;
|
||||
if (comcord.state.currentGuild != null) {
|
||||
|
@ -7,19 +9,54 @@ function updatePresence() {
|
|||
channel = guild.channels.get(comcord.state.currentChannel);
|
||||
}
|
||||
|
||||
try {
|
||||
if (comcord.client.user.bot) {
|
||||
if (comcord.state.rpcConnected) {
|
||||
try {
|
||||
const activity = {
|
||||
startTimestamp: comcord.state.startTime,
|
||||
smallImageKey: `https://cdn.discordapp.com/avatars/${comcord.client.user.id}/${comcord.client.user.avatar}.png?size=1024`,
|
||||
smallImageText: comcord.client.user.tag,
|
||||
buttons: [
|
||||
{
|
||||
label: "comcord Repo",
|
||||
url: "https://github.com/Cynosphere/comcord",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
if (guild != null) {
|
||||
activity.largeImageKey = `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.png?size=1024`;
|
||||
activity.largeImageText = guild.name;
|
||||
if (channel != null) {
|
||||
activity.details = `#${channel.name} - ${guild.name}`;
|
||||
}
|
||||
}
|
||||
if (comcord.state.afk == true) {
|
||||
activity.state = "AFK";
|
||||
}
|
||||
comcord.rpc.setActivity(activity);
|
||||
} catch (err) {
|
||||
//
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const activity = {
|
||||
startTimestamp: comcord.state.startTime,
|
||||
smallImageKey: `https://cdn.discordapp.com/avatars/${comcord.client.user.id}/${comcord.client.user.avatar}.png?size=1024`,
|
||||
smallImageText: `${comcord.client.user.username}#${comcord.client.user.discriminator}`,
|
||||
buttons: [
|
||||
{label: "comcord Repo", url: "https://github.com/Cynosphere/comcord"},
|
||||
],
|
||||
application_id: CLIENT_ID,
|
||||
name: "comcord",
|
||||
timestamps: {
|
||||
start: comcord.state.startTime,
|
||||
},
|
||||
assets: {},
|
||||
buttons: ["comcord Repo"],
|
||||
metadata: {
|
||||
button_urls: ["https://github.com/Cynosphere/comcord"],
|
||||
},
|
||||
type: 0,
|
||||
};
|
||||
|
||||
if (guild != null) {
|
||||
activity.largeImageKey = `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.png?size=1024`;
|
||||
activity.largeImageText = guild.name;
|
||||
activity.assets.large_image = `mp:icons/${guild.id}/${guild.icon}.png?size=1024`;
|
||||
activity.assets.large_text = guild.name;
|
||||
if (channel != null) {
|
||||
activity.details = `#${channel.name} - ${guild.name}`;
|
||||
}
|
||||
|
@ -27,9 +64,13 @@ function updatePresence() {
|
|||
if (comcord.state.afk == true) {
|
||||
activity.state = "AFK";
|
||||
}
|
||||
comcord.rpc.setActivity(activity);
|
||||
} catch (err) {
|
||||
//
|
||||
|
||||
comcord.client.shards.forEach((shard) => {
|
||||
if (shard.ready) {
|
||||
shard.presence.activities = [activity];
|
||||
shard.sendPresenceUpdate();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
30
src/lib/rcfile.js
Normal file
30
src/lib/rcfile.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const os = require("os");
|
||||
|
||||
const RCPATH = path.resolve(os.homedir(), ".comcordrc");
|
||||
|
||||
function readFile(config) {
|
||||
const rc = fs.readFileSync(RCPATH, "utf8");
|
||||
const lines = rc.split("\n");
|
||||
for (const line of lines) {
|
||||
const [key, value] = line.split("=");
|
||||
config[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
function writeFile(config) {
|
||||
if (fs.existsSync(RCPATH)) {
|
||||
readFile(config);
|
||||
}
|
||||
const newrc = [];
|
||||
|
||||
for (const key in config) {
|
||||
const value = config[key];
|
||||
newrc.push(`${key}=${value}`);
|
||||
}
|
||||
|
||||
fs.writeFileSync(RCPATH, newrc.join("\n"));
|
||||
}
|
||||
|
||||
module.exports = {readFile, writeFile, path: RCPATH};
|
Loading…
Reference in a new issue