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
 | 
					## Usage
 | 
				
			||||||
1. `pnpm i`
 | 
					1. `pnpm i`
 | 
				
			||||||
2. `node src/index.js <token>`
 | 
					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.
 | 
					### User Accounts
 | 
				
			||||||
~~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.~~
 | 
					User accounts are *partially* supported via `allowUserAccounts=true` in your `.comcordrc`.
 | 
				
			||||||
(I have no idea currently what the state of user support in Oceanic is)
 | 
					This is use at your own risk, despite spoofing the official client. I am not responsible for any banned accounts.
 | 
				
			||||||
I also don't want to give skids an easy point of reference of how to spoof the client. :^)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### 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.
 | 
					You **MUST** grant your bot all Privileged Gateway Intents.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Design Decisions
 | 
					## Design Decisions
 | 
				
			||||||
* Node.js was chosen currently due to familiarity.
 | 
					* 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.
 | 
					* "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
 | 
					## TODO
 | 
				
			||||||
| 
						 | 
					@ -39,6 +46,9 @@ You **MUST** grant your bot all Privileged Gateway Intents.
 | 
				
			||||||
  - [x] Clear (c)
 | 
					  - [x] Clear (c)
 | 
				
			||||||
  - [ ] Surf channels forwards (>)
 | 
					  - [ ] Surf channels forwards (>)
 | 
				
			||||||
  - [ ] Surf channels backwards (<)
 | 
					  - [ ] Surf channels backwards (<)
 | 
				
			||||||
 | 
					  - [x] AFK toggle (A)
 | 
				
			||||||
 | 
					  - [x] Send DM (s)
 | 
				
			||||||
 | 
					  - [x] Answer DM (a)
 | 
				
			||||||
- [x] Message Receiving
 | 
					- [x] Message Receiving
 | 
				
			||||||
  - [x] Markdown styling
 | 
					  - [x] Markdown styling
 | 
				
			||||||
    - [ ] Common markdown (bold, italic, etc)
 | 
					    - [ ] 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
 | 
					  - [x] Puts incoming messages into queue whilst in send mode
 | 
				
			||||||
  - [ ] Mentions
 | 
					  - [ ] Mentions
 | 
				
			||||||
  - [ ] Replies
 | 
					  - [ ] Replies
 | 
				
			||||||
- [ ] Configuration
 | 
					- [x] Configuration
 | 
				
			||||||
  - [ ] Default guild/channel
 | 
					  - [x] Default guild/channel
 | 
				
			||||||
 | 
					    - No way to set in client (yet?), `defaultChannel=` and `defaultGuild=` in your `.comcordrc`.
 | 
				
			||||||
- [ ] Threads
 | 
					- [ ] 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
 | 
					- [x] Not have everything in one file
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ const {updatePresence} = require("../lib/presence");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
addCommand("A", "toggles AFK mode", function () {
 | 
					addCommand("A", "toggles AFK mode", function () {
 | 
				
			||||||
  if (comcord.state.afk == true) {
 | 
					  if (comcord.state.afk == true) {
 | 
				
			||||||
 | 
					    comcord.state.afk = false;
 | 
				
			||||||
    comcord.client.shards.forEach((shard) => (shard.presence.afk = false));
 | 
					    comcord.client.shards.forEach((shard) => (shard.presence.afk = false));
 | 
				
			||||||
    comcord.client.editStatus("online");
 | 
					    comcord.client.editStatus("online");
 | 
				
			||||||
    console.log("<you have returned>");
 | 
					    console.log("<you have returned>");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,21 +40,22 @@ function listUsers() {
 | 
				
			||||||
  );
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const online = [...guild.members.values()].filter((m) => m.presence);
 | 
					  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;
 | 
					  let longest = 0;
 | 
				
			||||||
  for (const member of online) {
 | 
					  for (const member of online) {
 | 
				
			||||||
    const name = member.user.tag;
 | 
					    const name = member.tag;
 | 
				
			||||||
    if (name.length + 3 > longest) longest = name.length + 3;
 | 
					    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;
 | 
					  let index = 0;
 | 
				
			||||||
  for (const member of online) {
 | 
					  for (const member of online) {
 | 
				
			||||||
    const name = member.user.tag;
 | 
					    const name = member.tag;
 | 
				
			||||||
    const status = getStatus(member.presence.status);
 | 
					    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++;
 | 
					    index++;
 | 
				
			||||||
    process.stdout.write(
 | 
					    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 () {
 | 
					addCommand("G", "goto guild", function () {
 | 
				
			||||||
  startPrompt(":guild> ", switchGuild);
 | 
					  startPrompt(":guild> ", switchGuild);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = {switchGuild};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										219
									
								
								src/index.js
									
										
									
									
									
								
							
							
						
						
									
										219
									
								
								src/index.js
									
										
									
									
									
								
							| 
						 | 
					@ -1,15 +1,36 @@
 | 
				
			||||||
const {Client} = require("oceanic.js");
 | 
					const {Client, Constants} = require("oceanic.js");
 | 
				
			||||||
const chalk = require("chalk");
 | 
					 | 
				
			||||||
const DiscordRPC = require("discord-rpc");
 | 
					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 CLIENT_ID = "1026163285877325874";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const token = process.argv[2];
 | 
					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";
 | 
					process.title = "comcord";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
global.comcord = {
 | 
					global.comcord = {
 | 
				
			||||||
 | 
					  config,
 | 
				
			||||||
  state: {
 | 
					  state: {
 | 
				
			||||||
 | 
					    rpcConnected: false,
 | 
				
			||||||
    startTime: Date.now(),
 | 
					    startTime: Date.now(),
 | 
				
			||||||
    currentGuild: null,
 | 
					    currentGuild: null,
 | 
				
			||||||
    currentChannel: null,
 | 
					    currentChannel: null,
 | 
				
			||||||
| 
						 | 
					@ -22,21 +43,28 @@ global.comcord = {
 | 
				
			||||||
  commands: {},
 | 
					  commands: {},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
const client = new Client({
 | 
					const client = new Client({
 | 
				
			||||||
  auth: "Bot " + token,
 | 
					  auth:
 | 
				
			||||||
 | 
					    (config.allowUserAccounts == "true" ? "" : "Bot ") +
 | 
				
			||||||
 | 
					    (token ?? config.token),
 | 
				
			||||||
  defaultImageFormat: "png",
 | 
					  defaultImageFormat: "png",
 | 
				
			||||||
  defaultImageSize: 1024,
 | 
					  defaultImageSize: 1024,
 | 
				
			||||||
  gateway: {
 | 
					  gateway: {
 | 
				
			||||||
    intents: ["ALL"],
 | 
					    intents: ["ALL"],
 | 
				
			||||||
    activities: [
 | 
					    maxShards: 1,
 | 
				
			||||||
      {
 | 
					    concurrency: 1,
 | 
				
			||||||
        name: "comcord",
 | 
					    presence: {
 | 
				
			||||||
        type: "GAME",
 | 
					      status: "online",
 | 
				
			||||||
        application_id: CLIENT_ID,
 | 
					      activities: [
 | 
				
			||||||
        timestamps: {
 | 
					        {
 | 
				
			||||||
          start: comcord.state.startTime,
 | 
					          name: "comcord",
 | 
				
			||||||
 | 
					          type: 0,
 | 
				
			||||||
 | 
					          application_id: CLIENT_ID,
 | 
				
			||||||
 | 
					          timestamps: {
 | 
				
			||||||
 | 
					            start: comcord.state.startTime,
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      },
 | 
					      ],
 | 
				
			||||||
    ],
 | 
					    },
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
comcord.client = client;
 | 
					comcord.client = client;
 | 
				
			||||||
| 
						 | 
					@ -53,10 +81,11 @@ require("./commands/help");
 | 
				
			||||||
const {sendMode} = require("./commands/send");
 | 
					const {sendMode} = require("./commands/send");
 | 
				
			||||||
require("./commands/emote");
 | 
					require("./commands/emote");
 | 
				
			||||||
const {listGuilds} = require("./commands/listGuilds");
 | 
					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/switchChannel"); //loads listUsers
 | 
				
			||||||
require("./commands/history"); // includes extended history
 | 
					require("./commands/history"); // includes extended history
 | 
				
			||||||
require("./commands/afk");
 | 
					require("./commands/afk");
 | 
				
			||||||
 | 
					require("./commands/privateMessages");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
process.stdin.setRawMode(true);
 | 
					process.stdin.setRawMode(true);
 | 
				
			||||||
process.stdin.resume();
 | 
					process.stdin.resume();
 | 
				
			||||||
| 
						 | 
					@ -70,20 +99,44 @@ client.once("ready", function () {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  listGuilds();
 | 
					  listGuilds();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  rpc
 | 
					  if (config.defaultGuild) {
 | 
				
			||||||
    .login({
 | 
					    const guild = client.guilds.get(config.defaultGuild);
 | 
				
			||||||
      clientId: CLIENT_ID,
 | 
					    if (guild != null) {
 | 
				
			||||||
    })
 | 
					      if (config.defaultChannel) {
 | 
				
			||||||
    .catch(function () {});
 | 
					        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 () {});
 | 
					client.on("error", function () {});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
rpc.on("connected", function () {
 | 
					rpc.on("connected", function () {
 | 
				
			||||||
 | 
					  comcord.state.rpcConnected = true;
 | 
				
			||||||
  updatePresence();
 | 
					  updatePresence();
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
let retryingRPC = false;
 | 
					let retryingRPC = false;
 | 
				
			||||||
rpc.once("ready", function () {
 | 
					rpc.once("ready", function () {
 | 
				
			||||||
  rpc.transport.on("close", function () {
 | 
					  rpc.transport.on("close", function () {
 | 
				
			||||||
 | 
					    comcord.state.rpcConnected = false;
 | 
				
			||||||
    if (!retryingRPC) {
 | 
					    if (!retryingRPC) {
 | 
				
			||||||
      retryingRPC = true;
 | 
					      retryingRPC = true;
 | 
				
			||||||
      setTimeout(function () {
 | 
					      setTimeout(function () {
 | 
				
			||||||
| 
						 | 
					@ -102,21 +155,55 @@ rpc.once("ready", function () {
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
rpc.on("error", 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.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) {
 | 
					    if (comcord.state.inPrompt) {
 | 
				
			||||||
      comcord.state.messageQueue.push(msg);
 | 
					      comcord.state.messageQueue.push(msg);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      processMessage(msg);
 | 
					      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.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 (msg.content == old.content) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (comcord.state.inPrompt) {
 | 
					    if (comcord.state.inPrompt) {
 | 
				
			||||||
| 
						 | 
					@ -125,6 +212,10 @@ client.on("messageUpdate", function (msg, old) {
 | 
				
			||||||
      processMessage(msg);
 | 
					      processMessage(msg);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (msg.channel?.recipient != null) {
 | 
				
			||||||
 | 
					    comcord.state.lastDM = msg.author;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
process.stdin.on("data", async function (key) {
 | 
					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("COMcord (c)left 2022");
 | 
				
			||||||
console.log("Type 'h' for Commands");
 | 
					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({
 | 
					function formatMessage({
 | 
				
			||||||
  name,
 | 
					  name,
 | 
				
			||||||
 | 
					  tag,
 | 
				
			||||||
  content,
 | 
					  content,
 | 
				
			||||||
  bot,
 | 
					  bot,
 | 
				
			||||||
  attachments,
 | 
					  attachments,
 | 
				
			||||||
| 
						 | 
					@ -163,6 +164,7 @@ function formatMessage({
 | 
				
			||||||
  noColor = false,
 | 
					  noColor = false,
 | 
				
			||||||
  dump = false,
 | 
					  dump = false,
 | 
				
			||||||
  history = false,
 | 
					  history = false,
 | 
				
			||||||
 | 
					  dm = false,
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
  if (name.length + 2 > comcord.state.nameLength)
 | 
					  if (name.length + 2 > comcord.state.nameLength)
 | 
				
			||||||
    comcord.state.nameLength = name.length + 2;
 | 
					    comcord.state.nameLength = name.length + 2;
 | 
				
			||||||
| 
						 | 
					@ -248,7 +250,15 @@ function formatMessage({
 | 
				
			||||||
      .replace(REGEX_COMMAND, replaceCommands)
 | 
					      .replace(REGEX_COMMAND, replaceCommands)
 | 
				
			||||||
      .replace(REGEX_TIMESTAMP, replaceTimestamps);
 | 
					      .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.length > 1 &&
 | 
				
			||||||
        content.startsWith("*") &&
 | 
					        content.startsWith("*") &&
 | 
				
			||||||
        content.endsWith("*")) ||
 | 
					        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) {
 | 
					  if (msg.time) {
 | 
				
			||||||
    console.log(msg.content);
 | 
					    console.log(msg.content);
 | 
				
			||||||
  } else if (msg.content.indexOf("\n") > -1) {
 | 
					  } else if (msg.content.indexOf("\n") > -1) {
 | 
				
			||||||
    if (msg.content.match(REGEX_CODEBLOCK)) {
 | 
					    if (msg.content.match(REGEX_CODEBLOCK)) {
 | 
				
			||||||
      formatMessage({
 | 
					      formatMessage({
 | 
				
			||||||
        name: msg.author.username,
 | 
					        name: msg.author.username,
 | 
				
			||||||
 | 
					        tag: msg.author.tag,
 | 
				
			||||||
        bot: msg.author.bot,
 | 
					        bot: msg.author.bot,
 | 
				
			||||||
        content: msg.content.replace(
 | 
					        content: msg.content.replace(
 | 
				
			||||||
          REGEX_CODEBLOCK_GLOBAL,
 | 
					          REGEX_CODEBLOCK_GLOBAL,
 | 
				
			||||||
| 
						 | 
					@ -334,6 +349,7 @@ function processMessage(msg, options) {
 | 
				
			||||||
        const line = lines[index];
 | 
					        const line = lines[index];
 | 
				
			||||||
        formatMessage({
 | 
					        formatMessage({
 | 
				
			||||||
          name: msg.author.username,
 | 
					          name: msg.author.username,
 | 
				
			||||||
 | 
					          tag: msg.author.tag,
 | 
				
			||||||
          bot: msg.author.bot,
 | 
					          bot: msg.author.bot,
 | 
				
			||||||
          content:
 | 
					          content:
 | 
				
			||||||
            line +
 | 
					            line +
 | 
				
			||||||
| 
						 | 
					@ -350,6 +366,7 @@ function processMessage(msg, options) {
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    formatMessage({
 | 
					    formatMessage({
 | 
				
			||||||
      name: msg.author.username,
 | 
					      name: msg.author.username,
 | 
				
			||||||
 | 
					      tag: msg.author.tag,
 | 
				
			||||||
      bot: msg.author.bot,
 | 
					      bot: msg.author.bot,
 | 
				
			||||||
      content: msg.content + (msg.editedTimestamp != null ? " (edited)" : ""),
 | 
					      content: msg.content + (msg.editedTimestamp != null ? " (edited)" : ""),
 | 
				
			||||||
      attachments: msg.attachments,
 | 
					      attachments: msg.attachments,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,5 @@
 | 
				
			||||||
 | 
					const CLIENT_ID = "1026163285877325874";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function updatePresence() {
 | 
					function updatePresence() {
 | 
				
			||||||
  let guild, channel;
 | 
					  let guild, channel;
 | 
				
			||||||
  if (comcord.state.currentGuild != null) {
 | 
					  if (comcord.state.currentGuild != null) {
 | 
				
			||||||
| 
						 | 
					@ -7,19 +9,54 @@ function updatePresence() {
 | 
				
			||||||
    channel = guild.channels.get(comcord.state.currentChannel);
 | 
					    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 = {
 | 
					    const activity = {
 | 
				
			||||||
      startTimestamp: comcord.state.startTime,
 | 
					      application_id: CLIENT_ID,
 | 
				
			||||||
      smallImageKey: `https://cdn.discordapp.com/avatars/${comcord.client.user.id}/${comcord.client.user.avatar}.png?size=1024`,
 | 
					      name: "comcord",
 | 
				
			||||||
      smallImageText: `${comcord.client.user.username}#${comcord.client.user.discriminator}`,
 | 
					      timestamps: {
 | 
				
			||||||
      buttons: [
 | 
					        start: comcord.state.startTime,
 | 
				
			||||||
        {label: "comcord Repo", url: "https://github.com/Cynosphere/comcord"},
 | 
					      },
 | 
				
			||||||
      ],
 | 
					      assets: {},
 | 
				
			||||||
 | 
					      buttons: ["comcord Repo"],
 | 
				
			||||||
 | 
					      metadata: {
 | 
				
			||||||
 | 
					        button_urls: ["https://github.com/Cynosphere/comcord"],
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      type: 0,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (guild != null) {
 | 
					    if (guild != null) {
 | 
				
			||||||
      activity.largeImageKey = `https://cdn.discordapp.com/icons/${guild.id}/${guild.icon}.png?size=1024`;
 | 
					      activity.assets.large_image = `mp:icons/${guild.id}/${guild.icon}.png?size=1024`;
 | 
				
			||||||
      activity.largeImageText = guild.name;
 | 
					      activity.assets.large_text = guild.name;
 | 
				
			||||||
      if (channel != null) {
 | 
					      if (channel != null) {
 | 
				
			||||||
        activity.details = `#${channel.name} - ${guild.name}`;
 | 
					        activity.details = `#${channel.name} - ${guild.name}`;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -27,9 +64,13 @@ function updatePresence() {
 | 
				
			||||||
    if (comcord.state.afk == true) {
 | 
					    if (comcord.state.afk == true) {
 | 
				
			||||||
      activity.state = "AFK";
 | 
					      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…
	
	Add table
		Add a link
		
	
		Reference in a new issue