upgrade to discord.js v14
This commit is contained in:
parent
35a64b4f25
commit
7c0b91e1be
12 changed files with 446 additions and 533 deletions
22
package.json
22
package.json
|
@ -10,22 +10,22 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cliqz/adblocker": "^1.23.8",
|
"@cliqz/adblocker": "^1.23.8",
|
||||||
"discord-command-parser": "^1.5.3",
|
"discord-command-parser": "^1.5.3",
|
||||||
"discord.js": "^13.8.0",
|
"discord.js": "^14.0.3",
|
||||||
"just-random": "^3.0.1",
|
"just-random": "^3.0.1",
|
||||||
"kleur": "^4.1.4",
|
"kleur": "^4.1.5",
|
||||||
"node-fetch": "^3.2.5",
|
"node-fetch": "^3.2.9",
|
||||||
"remove-markdown": "^0.5.0",
|
"remove-markdown": "^0.5.0",
|
||||||
"tsx": "^3.4.2",
|
"tsx": "^3.8.0",
|
||||||
"url-regex": "^5.0.0"
|
"url-regex": "^5.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^17.0.41",
|
"@types/node": "^18.6.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.27.1",
|
"@typescript-eslint/eslint-plugin": "^5.31.0",
|
||||||
"@typescript-eslint/parser": "^5.27.1",
|
"@typescript-eslint/parser": "^5.31.0",
|
||||||
"dotenv": "^16.0.1",
|
"dotenv": "^16.0.1",
|
||||||
"esbuild": "^0.14.43",
|
"esbuild": "^0.14.50",
|
||||||
"eslint": "^8.17.0",
|
"eslint": "^8.20.0",
|
||||||
"prettier": "^2.6.2",
|
"prettier": "^2.7.1",
|
||||||
"typescript": "^4.6.4"
|
"typescript": "^4.7.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
import { MessageEmbed } from 'discord.js';
|
import { EmbedBuilder } from 'discord.js';
|
||||||
import { commands } from '.';
|
import { commands } from '.';
|
||||||
import { Command } from '..';
|
import type { Command } from '..';
|
||||||
|
import { COLORS } from '../constants';
|
||||||
|
|
||||||
export const cmd: Command = {
|
export const cmd: Command = {
|
||||||
name: 'help',
|
name: 'help',
|
||||||
desc: 'Shows this menu.',
|
desc: 'Shows this menu.',
|
||||||
exec: async (e) => {
|
exec: async (e) => {
|
||||||
const embed = new MessageEmbed()
|
const embed = new EmbedBuilder()
|
||||||
.setTitle('Help Menu')
|
.setTitle('Help Menu')
|
||||||
.setColor('DARK_GREEN');
|
.setColor(COLORS.green);
|
||||||
|
|
||||||
const comman = commands;
|
const comman = commands;
|
||||||
comman.sort((x, y) => {
|
comman.sort((x, y) => {
|
||||||
|
@ -27,7 +28,7 @@ export const cmd: Command = {
|
||||||
if (cmd.examples && cmd.examples[0]) {
|
if (cmd.examples && cmd.examples[0]) {
|
||||||
resp.push(`**Examples**: \n${cmd.examples.join('\n> ')}`);
|
resp.push(`**Examples**: \n${cmd.examples.join('\n> ')}`);
|
||||||
}
|
}
|
||||||
embed.addField('!' + cmd.name, resp.join('\n'));
|
embed.addFields({ name: '!' + cmd.name, value: resp.join('\n') });
|
||||||
}
|
}
|
||||||
|
|
||||||
await e.reply({ embeds: [embed] });
|
await e.reply({ embeds: [embed] });
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import type { Command } from '../index';
|
import type { Command } from '..';
|
||||||
|
import { COLORS } from '../constants';
|
||||||
|
|
||||||
export const cmd: Command = {
|
export const cmd: Command = {
|
||||||
name: 'members',
|
name: 'members',
|
||||||
|
@ -20,7 +21,7 @@ export const cmd: Command = {
|
||||||
m.presence?.status === 'dnd'
|
m.presence?.status === 'dnd'
|
||||||
).length
|
).length
|
||||||
} online members`,
|
} online members`,
|
||||||
color: 'GOLD',
|
color: COLORS.blue,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { Command } from '../index';
|
import type { Command } from '..';
|
||||||
|
|
||||||
export const cmd: Command = {
|
export const cmd: Command = {
|
||||||
name: 'ping',
|
name: 'ping',
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { COLORS } from '../constants';
|
||||||
import type { Command } from '../index';
|
import type { Command } from '../index';
|
||||||
|
|
||||||
export const cmd: Command = {
|
export const cmd: Command = {
|
||||||
|
@ -12,7 +13,7 @@ export const cmd: Command = {
|
||||||
embeds: [
|
embeds: [
|
||||||
{
|
{
|
||||||
title: `⭐ ${count} total stars!`,
|
title: `⭐ ${count} total stars!`,
|
||||||
color: 'GOLD',
|
color: COLORS.yellow,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { MessageEmbed } from 'discord.js';
|
import { EmbedBuilder } from 'discord.js';
|
||||||
import { getTags, type Command } from '..';
|
import { getTags, type Command } from '..';
|
||||||
|
import { COLORS } from '../constants';
|
||||||
|
|
||||||
export const cmd: Command = {
|
export const cmd: Command = {
|
||||||
name: 'tags',
|
name: 'tags',
|
||||||
desc: 'Lists the tags available',
|
desc: 'Lists the tags available',
|
||||||
exec: async (e) => {
|
exec: async (e) => {
|
||||||
const em = new MessageEmbed().setTitle('tags').setColor('DARK_GREEN');
|
const em = new EmbedBuilder().setTitle('tags').setColor(COLORS.green);
|
||||||
|
|
||||||
const tags = await getTags();
|
const tags = await getTags();
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ export const cmd: Command = {
|
||||||
text += '\n[embedded message]';
|
text += '\n[embedded message]';
|
||||||
}
|
}
|
||||||
|
|
||||||
em.addField('?' + tag.name, text);
|
em.addFields({ name: '?' + tag.name, value: text });
|
||||||
}
|
}
|
||||||
|
|
||||||
await e.reply({ embeds: [em] });
|
await e.reply({ embeds: [em] });
|
||||||
|
|
|
@ -20,3 +20,10 @@ export const ETA_MESSAGES = [
|
||||||
'Next week',
|
'Next week',
|
||||||
'In PolyMC 2.0.0',
|
'In PolyMC 2.0.0',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const COLORS = {
|
||||||
|
red: 0xef4444,
|
||||||
|
green: 0x22c55e,
|
||||||
|
blue: 0x60a5fa,
|
||||||
|
yellow: 0xfde047,
|
||||||
|
} as const;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Message } from 'discord.js';
|
import type { Message } from 'discord.js';
|
||||||
import { isBad } from './badLinks';
|
import { isBad } from './badLinks';
|
||||||
import urlRegex from 'url-regex';
|
import urlRegex from 'url-regex';
|
||||||
|
import { COLORS } from './constants';
|
||||||
|
|
||||||
// true if message is ok, false if filtered
|
// true if message is ok, false if filtered
|
||||||
export async function filterMessage(e: Message): Promise<boolean> {
|
export async function filterMessage(e: Message): Promise<boolean> {
|
||||||
|
@ -19,7 +20,7 @@ export async function filterMessage(e: Message): Promise<boolean> {
|
||||||
title: 'Hold on!',
|
title: 'Hold on!',
|
||||||
description:
|
description:
|
||||||
'There seems to be a phishing / malware link in your message.',
|
'There seems to be a phishing / malware link in your message.',
|
||||||
color: 'RED',
|
color: COLORS.red,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
64
src/index.ts
64
src/index.ts
|
@ -1,10 +1,4 @@
|
||||||
import {
|
import { Client, Message, EmbedBuilder, type EmbedData } from 'discord.js';
|
||||||
Client,
|
|
||||||
Intents,
|
|
||||||
Message,
|
|
||||||
MessageEmbed,
|
|
||||||
type MessageEmbedOptions,
|
|
||||||
} from 'discord.js';
|
|
||||||
|
|
||||||
import * as BuildConfig from './constants';
|
import * as BuildConfig from './constants';
|
||||||
import { commands } from './commands';
|
import { commands } from './commands';
|
||||||
|
@ -20,7 +14,7 @@ import {
|
||||||
import random from 'just-random';
|
import random from 'just-random';
|
||||||
import { readFile } from 'fs/promises';
|
import { readFile } from 'fs/promises';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { green, bold, blue, underline, yellow } from 'kleur/colors';
|
import { green, bold, yellow } from 'kleur/colors';
|
||||||
import 'dotenv/config';
|
import 'dotenv/config';
|
||||||
|
|
||||||
export interface Command {
|
export interface Command {
|
||||||
|
@ -38,7 +32,7 @@ interface Tag {
|
||||||
name: string;
|
name: string;
|
||||||
aliases?: Array<string>;
|
aliases?: Array<string>;
|
||||||
text?: string;
|
text?: string;
|
||||||
embed?: MessageEmbedOptions;
|
embed?: EmbedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getTags = async (): Promise<Tag[]> => {
|
export const getTags = async (): Promise<Tag[]> => {
|
||||||
|
@ -49,13 +43,14 @@ export const getTags = async (): Promise<Tag[]> => {
|
||||||
|
|
||||||
const client = new Client({
|
const client = new Client({
|
||||||
intents: [
|
intents: [
|
||||||
Intents.FLAGS.GUILDS,
|
'Guilds',
|
||||||
Intents.FLAGS.GUILD_MESSAGES,
|
'GuildMessages',
|
||||||
Intents.FLAGS.DIRECT_MESSAGES,
|
'MessageContent',
|
||||||
Intents.FLAGS.GUILD_MEMBERS,
|
'DirectMessages',
|
||||||
Intents.FLAGS.GUILD_PRESENCES,
|
'GuildMembers',
|
||||||
Intents.FLAGS.GUILD_MESSAGE_REACTIONS,
|
'GuildPresences',
|
||||||
Intents.FLAGS.GUILD_BANS,
|
'GuildMessageReactions',
|
||||||
|
'GuildBans',
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -65,18 +60,6 @@ client.once('ready', async () => {
|
||||||
if (process.env.NODE_ENV !== 'development')
|
if (process.env.NODE_ENV !== 'development')
|
||||||
console.warn(yellow(bold('Running in production mode!')));
|
console.warn(yellow(bold('Running in production mode!')));
|
||||||
|
|
||||||
console.log(
|
|
||||||
'Invite link:',
|
|
||||||
blue(
|
|
||||||
underline(
|
|
||||||
client.generateInvite({
|
|
||||||
scopes: ['bot'],
|
|
||||||
permissions: ['ADMINISTRATOR'],
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
client.user?.presence.set({
|
client.user?.presence.set({
|
||||||
activities: [{ name: `Minecraft ${await getLatestMinecraftVersion()}` }],
|
activities: [{ name: `Minecraft ${await getLatestMinecraftVersion()}` }],
|
||||||
status: 'online',
|
status: 'online',
|
||||||
|
@ -84,7 +67,7 @@ client.once('ready', async () => {
|
||||||
|
|
||||||
client.on('messageCreate', async (e) => {
|
client.on('messageCreate', async (e) => {
|
||||||
if (!e.content) return;
|
if (!e.content) return;
|
||||||
if (!e.channel.isText()) return;
|
if (!e.channel.isTextBased()) return;
|
||||||
if (e.author === client.user) return;
|
if (e.author === client.user) return;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -138,9 +121,9 @@ async function parseMsgForCommands(e: Message) {
|
||||||
try {
|
try {
|
||||||
await cmd.exec(e, parsed);
|
await cmd.exec(e, parsed);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
const em = new MessageEmbed()
|
const em = new EmbedBuilder()
|
||||||
.setTitle('Error')
|
.setTitle('Error')
|
||||||
.setColor('RED')
|
.setColor('Red')
|
||||||
// @ts-expect-error no why
|
// @ts-expect-error no why
|
||||||
.setDescription(err['message'] as string);
|
.setDescription(err['message'] as string);
|
||||||
|
|
||||||
|
@ -161,12 +144,27 @@ async function parseMsgForTags(e: Message) {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (tag) {
|
if (tag) {
|
||||||
|
const requesterAvatarURL = e.author.avatar;
|
||||||
|
const tagRequester = {
|
||||||
|
text: `Requested by ${e.author.tag}`,
|
||||||
|
...(requesterAvatarURL ? { icon_url: requesterAvatarURL } : null),
|
||||||
|
};
|
||||||
|
|
||||||
if (tag.text) {
|
if (tag.text) {
|
||||||
e.reply(tag.text);
|
e.reply({
|
||||||
|
embeds: [
|
||||||
|
new EmbedBuilder({
|
||||||
|
title: tag.name,
|
||||||
|
description: tag.text,
|
||||||
|
footer: tagRequester,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
} else if (tag.embed) {
|
} else if (tag.embed) {
|
||||||
const em = new MessageEmbed(tag.embed);
|
const em = new EmbedBuilder(tag.embed).setFooter(tagRequester);
|
||||||
e.reply({ embeds: [em] });
|
e.reply({ embeds: [em] });
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
32
src/logs.ts
32
src/logs.ts
|
@ -1,11 +1,12 @@
|
||||||
import { getLatestPolyMCVersion } from './utils/remoteVersions';
|
import { getLatestPolyMCVersion } from './utils/remoteVersions';
|
||||||
import { MessageEmbed } from 'discord.js';
|
import { EmbedBuilder } from 'discord.js';
|
||||||
|
|
||||||
// log providers
|
// log providers
|
||||||
import { readMcLogs } from './logproviders/mclogs';
|
import { readMcLogs } from './logproviders/mclogs';
|
||||||
import { read0x0 } from './logproviders/0x0';
|
import { read0x0 } from './logproviders/0x0';
|
||||||
import { readPasteGG } from './logproviders/pastegg';
|
import { readPasteGG } from './logproviders/pastegg';
|
||||||
import { readHastebin } from './logproviders/haste';
|
import { readHastebin } from './logproviders/haste';
|
||||||
|
import { COLORS } from './constants';
|
||||||
|
|
||||||
type Analyzer = (text: string) => Promise<Array<string> | null>;
|
type Analyzer = (text: string) => Promise<Array<string> | null>;
|
||||||
type LogProvider = (text: string) => Promise<null | string>;
|
type LogProvider = (text: string) => Promise<null | string>;
|
||||||
|
@ -224,14 +225,14 @@ const providers: LogProvider[] = [
|
||||||
readHastebin,
|
readHastebin,
|
||||||
];
|
];
|
||||||
|
|
||||||
export async function parseLog(s: string): Promise<MessageEmbed | null> {
|
export async function parseLog(s: string): Promise<EmbedBuilder | null> {
|
||||||
if (s.includes('https://pastebin.com/')) {
|
if (s.includes('https://pastebin.com/')) {
|
||||||
const embed = new MessageEmbed()
|
const embed = new EmbedBuilder()
|
||||||
.setTitle('pastebin.com detected')
|
.setTitle('pastebin.com detected')
|
||||||
.setDescription(
|
.setDescription(
|
||||||
'Please use https://mclo.gs or another paste provider and send logs using the Log Upload feature in PolyMC. (See !log)'
|
'Please use https://mclo.gs or another paste provider and send logs using the Log Upload feature in PolyMC. (See !log)'
|
||||||
)
|
)
|
||||||
.setColor('DARK_RED');
|
.setColor(COLORS.red);
|
||||||
return embed;
|
return embed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,19 +248,28 @@ export async function parseLog(s: string): Promise<MessageEmbed | null> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!log) return null;
|
if (!log) return null;
|
||||||
const embed = new MessageEmbed()
|
const embed = new EmbedBuilder().setTitle('Log analysis');
|
||||||
.setTitle('Log analysis')
|
|
||||||
.setColor('DARK_GREEN');
|
|
||||||
|
|
||||||
|
let thereWasAnIssue = false;
|
||||||
for (const i in analyzers) {
|
for (const i in analyzers) {
|
||||||
const Analyzer = analyzers[i];
|
const Analyzer = analyzers[i];
|
||||||
const out = await Analyzer(log);
|
const out = await Analyzer(log);
|
||||||
if (out) embed.addField(out[0], out[1]);
|
if (out) {
|
||||||
|
embed.addFields({ name: out[0], value: out[1] });
|
||||||
|
thereWasAnIssue = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (embed.fields[0]) return embed;
|
if (thereWasAnIssue) {
|
||||||
else {
|
embed.setColor(COLORS.red);
|
||||||
embed.addField('Analyze failed', 'No issues found automatically');
|
return embed;
|
||||||
|
} else {
|
||||||
|
embed.setColor(COLORS.green);
|
||||||
|
embed.addFields({
|
||||||
|
name: 'Analyze failed',
|
||||||
|
value: 'No issues found automatically',
|
||||||
|
});
|
||||||
|
|
||||||
return embed;
|
return embed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
"name": "optifine",
|
"name": "optifine",
|
||||||
"aliases": ["of", "optimize", "opticrap", "notfine"],
|
"aliases": ["of", "optimize", "opticrap", "notfine"],
|
||||||
"embed": {
|
"embed": {
|
||||||
"color": "DARK_GREEN",
|
|
||||||
"title": "OptiFine",
|
"title": "OptiFine",
|
||||||
"description": "OptiFine is known to cause problems when paired with other mods.\nPlease see [Installing OptiFine Alternatives](https://polymc.org/wiki/getting-started/install-of-alternatives/).\nIf you really want to use OptiFine, see [Installing OptiFine](https://polymc.org/wiki/getting-started/installing-optifine/)"
|
"description": "OptiFine is known to cause problems when paired with other mods.\nPlease see [Installing OptiFine Alternatives](https://polymc.org/wiki/getting-started/install-of-alternatives/).\nIf you really want to use OptiFine, see [Installing OptiFine](https://polymc.org/wiki/getting-started/installing-optifine/)"
|
||||||
}
|
}
|
||||||
|
@ -43,7 +42,7 @@
|
||||||
"embed": {
|
"embed": {
|
||||||
"title": "Data directories",
|
"title": "Data directories",
|
||||||
"description": "Where PolyMC stores your data (e.g. instances)",
|
"description": "Where PolyMC stores your data (e.g. instances)",
|
||||||
"color": "AQUA",
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"name": "Portable (Windows / Linux)",
|
"name": "Portable (Windows / Linux)",
|
||||||
|
@ -86,8 +85,7 @@
|
||||||
"name": "whyjava8",
|
"name": "whyjava8",
|
||||||
"embed": {
|
"embed": {
|
||||||
"title": "Why does PolyMC ask me to change java version?",
|
"title": "Why does PolyMC ask me to change java version?",
|
||||||
"description": "Minecraft versions before 1.17 required Java 8 and have issues with newer java, while newer versions require Java 17, so you need to change java version. Some people think Java 8 is very outdated, but it's actually an LTS, it's still getting updates. If one of your mods is weird and requires newer java, you can bypass this going to instance settings-Java and ticking 'Skip java compatibility checks', but be aware of potential issues, such as [random CMEs](https://bugs.mojang.com/browse/MC-149777).",
|
"description": "Minecraft versions before 1.17 required Java 8 and have issues with newer java, while newer versions require Java 17, so you need to change java version. Some people think Java 8 is very outdated, but it's actually an LTS, it's still getting updates. If one of your mods is weird and requires newer java, you can bypass this going to instance settings-Java and ticking 'Skip java compatibility checks', but be aware of potential issues, such as [random CMEs](https://bugs.mojang.com/browse/MC-149777)."
|
||||||
"color": "ORANGE"
|
|
||||||
},
|
},
|
||||||
"aliases": ["isjava8ancient", "whyispolyforcingme"]
|
"aliases": ["isjava8ancient", "whyispolyforcingme"]
|
||||||
},
|
},
|
||||||
|
@ -95,8 +93,7 @@
|
||||||
"name": "update",
|
"name": "update",
|
||||||
"embed": {
|
"embed": {
|
||||||
"title": "Does PolyMC auto-update?",
|
"title": "Does PolyMC auto-update?",
|
||||||
"description": "PolyMC auto-updates for macOS using the Sparkle Framework.\n\nWindows auto-updating is WIP for now, you will need to download the installer and run it again. (You will not lose your instances.)\n\nFor Linux, just use your package manager!",
|
"description": "PolyMC auto-updates for macOS using the Sparkle Framework.\n\nWindows auto-updating is WIP for now, you will need to download the installer and run it again. (You will not lose your instances.)\n\nFor Linux, just use your package manager!"
|
||||||
"color": "BLUE"
|
|
||||||
},
|
},
|
||||||
"aliases": ["updating", "autoupdate"]
|
"aliases": ["updating", "autoupdate"]
|
||||||
},
|
},
|
||||||
|
@ -104,8 +101,7 @@
|
||||||
"name": "modupdater",
|
"name": "modupdater",
|
||||||
"embed": {
|
"embed": {
|
||||||
"title": "Mod updater",
|
"title": "Mod updater",
|
||||||
"description": "Mod updating has been introduced in PolyMC 1.4.0! Upgrade if you haven't and you'll be able to use it.",
|
"description": "Mod updating has been introduced in PolyMC 1.4.0! Upgrade if you haven't and you'll be able to use it."
|
||||||
"color": "GREEN"
|
|
||||||
},
|
},
|
||||||
"aliases": ["mod-update", "modupdate"]
|
"aliases": ["mod-update", "modupdate"]
|
||||||
},
|
},
|
||||||
|
@ -113,8 +109,7 @@
|
||||||
"name": "curseforge",
|
"name": "curseforge",
|
||||||
"embed": {
|
"embed": {
|
||||||
"title": "What's wrong with CurseForge?",
|
"title": "What's wrong with CurseForge?",
|
||||||
"description": "CurseForge added a new option to block third party clients like PolyMC from accessing mod files, and they started to enforce this option lately. We can't allow you to download those mods directly from PolyMC, but PolyMC 1.3.1 and higher have a workaround to let modpacks work: letting you to download those opted out mods manually. We highly encourage asking authors that opted out to stop doing so.",
|
"description": "CurseForge added a new option to block third party clients like PolyMC from accessing mod files, and they started to enforce this option lately. We can't allow you to download those mods directly from PolyMC, but PolyMC 1.3.1 and higher have a workaround to let modpacks work: letting you to download those opted out mods manually. We highly encourage asking authors that opted out to stop doing so."
|
||||||
"color": "ORANGE"
|
|
||||||
},
|
},
|
||||||
"aliases": ["cf", "curse", "cursed", "cursedfrog"]
|
"aliases": ["cf", "curse", "cursed", "cursedfrog"]
|
||||||
},
|
},
|
||||||
|
@ -122,8 +117,7 @@
|
||||||
"name": "piracy",
|
"name": "piracy",
|
||||||
"embed": {
|
"embed": {
|
||||||
"title": "We don't tolerate piracy!",
|
"title": "We don't tolerate piracy!",
|
||||||
"description": "PolyMC has always been legal, legitimate & appropriate. We don't and never will have features such as offline login without an official account.",
|
"description": "PolyMC has always been legal, legitimate & appropriate. We don't and never will have features such as offline login without an official account."
|
||||||
"color": "DARK_RED"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue