Merge branch 'master' of https://github.com/janderedev/automod
This commit is contained in:
commit
a29732b00e
8 changed files with 232 additions and 60 deletions
166
.github/workflows/docker.yml
vendored
Normal file
166
.github/workflows/docker.yml
vendored
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
name: Docker
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "master"
|
||||||
|
tags:
|
||||||
|
- "*"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish_api:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
-
|
||||||
|
name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
# list of Docker images to use as base name for tags
|
||||||
|
images: ghcr.io/janderedev/automod-api
|
||||||
|
# generate Docker tags based on branch and short commit SHA
|
||||||
|
tags: |
|
||||||
|
type=ref,event=branch
|
||||||
|
type=sha
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build and push - API
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: ./api
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
|
publish_web:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
-
|
||||||
|
name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
# list of Docker images to use as base name for tags
|
||||||
|
images: ghcr.io/janderedev/automod-web
|
||||||
|
# generate Docker tags based on branch and short commit SHA
|
||||||
|
tags: |
|
||||||
|
type=ref,event=branch
|
||||||
|
type=sha
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build and push - Web
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: ./web
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
|
publish_bridge:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
-
|
||||||
|
name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
# list of Docker images to use as base name for tags
|
||||||
|
images: ghcr.io/janderedev/automod-bridge
|
||||||
|
# generate Docker tags based on branch and short commit SHA
|
||||||
|
tags: |
|
||||||
|
type=ref,event=branch
|
||||||
|
type=sha
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build and push - Bridge
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: ./bridge
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
|
publish_bot:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
-
|
||||||
|
name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
# list of Docker images to use as base name for tags
|
||||||
|
images: ghcr.io/janderedev/automod-bot
|
||||||
|
# generate Docker tags based on branch and short commit SHA
|
||||||
|
tags: |
|
||||||
|
type=ref,event=branch
|
||||||
|
type=sha
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build and push - Bot
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: ./bot
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
|
@ -13,7 +13,7 @@
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@janderedev/revolt.js": "^6.0.0-patch.3",
|
"@janderedev/revolt.js": "^6.0.0-2-patch.1",
|
||||||
"@types/monk": "^6.0.0",
|
"@types/monk": "^6.0.0",
|
||||||
"axios": "^0.22.0",
|
"axios": "^0.22.0",
|
||||||
"dayjs": "^1.10.7",
|
"dayjs": "^1.10.7",
|
||||||
|
|
|
@ -26,7 +26,8 @@ export default {
|
||||||
if (amount > MAX_PURGE_AMOUNT) return message.reply(`Message count exceeds the limit of ${MAX_PURGE_AMOUNT}.`);
|
if (amount > MAX_PURGE_AMOUNT) return message.reply(`Message count exceeds the limit of ${MAX_PURGE_AMOUNT}.`);
|
||||||
|
|
||||||
messages = await message.channel!.fetchMessages({
|
messages = await message.channel!.fetchMessages({
|
||||||
limit: amount
|
limit: amount,
|
||||||
|
before: message._id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// delete messages between [id] and [id]
|
// delete messages between [id] and [id]
|
||||||
|
@ -78,15 +79,21 @@ export default {
|
||||||
messages = messages.filter(m => users.find(u => u?._id == m.author_id));
|
messages = messages.filter(m => users.find(u => u?._id == m.author_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
let m = await (message.channel?.sendMessage(`Deleting ${messages.length} messages...`)?.catch(console.error));
|
await message.channel?.deleteMessages(messages.map(m => m._id));
|
||||||
let res = await Promise.allSettled(messages.map(m => m.delete()));
|
|
||||||
|
|
||||||
let failures = res.filter(r => r.status == 'rejected').length;
|
const replyMsg = await message.channel?.sendMessage({ content: `Deleted ${messages.length} messages.` })
|
||||||
|
|
||||||
await m?.edit({ content: `Deleted ${messages.length} messages.`
|
|
||||||
+ `${failures > 0 ? `\n${failures} message${failures == 1 ? '' : 's'} failed to delete.` : ''}` })
|
|
||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
|
|
||||||
|
setTimeout(async () => {
|
||||||
|
try {
|
||||||
|
await message.channel?.deleteMessages([
|
||||||
|
replyMsg!._id,
|
||||||
|
message._id,
|
||||||
|
]);
|
||||||
|
} catch(e) { console.error(e) }
|
||||||
|
}, 6000);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
console.error(e);
|
||||||
message.channel?.sendMessage(`An error has occurred: ${e}`);
|
message.channel?.sendMessage(`An error has occurred: ${e}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,9 +42,6 @@ client.on('packet', async (packet) => {
|
||||||
discord: {
|
discord: {
|
||||||
description: `Author: @${m?.author?.username || m?.author_id || "Unknown"} | Channel: ${channel?.name || channel?._id}`
|
description: `Author: @${m?.author?.username || m?.author_id || "Unknown"} | Channel: ${channel?.name || channel?._id}`
|
||||||
},
|
},
|
||||||
revoltRvembed: {
|
|
||||||
description: `Author: @${m?.author?.username || m?.author_id || "Unknown"} | Channel: ${channel?.name || channel?._id}`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,9 +85,6 @@ client.on('packet', async (packet) => {
|
||||||
discord: {
|
discord: {
|
||||||
description: `Author: @${message.author?.username || message.author_id} | Channel: ${message.channel?.name || message.channel_id}`
|
description: `Author: @${message.author?.username || message.author_id} | Channel: ${message.channel?.name || message.channel_id}`
|
||||||
},
|
},
|
||||||
revoltRvembed: {
|
|
||||||
description: `Author: @${message.author?.username || message.author_id} | Channel: ${message.channel?.name || message.channel_id}`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +106,33 @@ client.on('packet', async (packet) => {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (packet.type == 'BulkMessageDelete') {
|
||||||
|
const channel = client.channels.get(packet.channel);
|
||||||
|
if (!channel) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
let config = await dbs.SERVERS.findOne({ id: channel.server?._id });
|
||||||
|
if (config?.logs?.messageUpdate) {
|
||||||
|
let embed: LogMessage = {
|
||||||
|
title: `Bulk delete in in ${channel.server?.name}`,
|
||||||
|
description: `${packet.ids.length} messages deleted in ` +
|
||||||
|
`[#${channel.name}](/server/${channel.server_id}/channel/${channel._id})`,
|
||||||
|
fields: [],
|
||||||
|
color: '#ff392b',
|
||||||
|
overrides: {
|
||||||
|
discord: {
|
||||||
|
description: `${packet.ids.length} messages deleted in #${channel.name}`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await sendLogMessage(config.logs.messageUpdate, embed);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
async function logModAction(type: 'warn'|'kick'|'ban'|'votekick', server: Server, mod: Member, target: string, reason: string|null, infractionID: string, extraText?: string): Promise<void> {
|
async function logModAction(type: 'warn'|'kick'|'ban'|'votekick', server: Server, mod: Member, target: string, reason: string|null, infractionID: string, extraText?: string): Promise<void> {
|
||||||
|
@ -132,15 +153,7 @@ async function logModAction(type: 'warn'|'kick'|'ban'|'votekick', server: Server
|
||||||
+ `**Warn ID**: \`${infractionID}\`\n`
|
+ `**Warn ID**: \`${infractionID}\`\n`
|
||||||
+ (extraText ?? ''),
|
+ (extraText ?? ''),
|
||||||
color: embedColor,
|
color: embedColor,
|
||||||
overrides: {
|
overrides: {},
|
||||||
revoltRvembed: {
|
|
||||||
description: `@${mod.user?.username} ${aType} `
|
|
||||||
+ `${await fetchUsername(target)}${type == 'warn' ? '.' : ` from ${server.name}.`}\n`
|
|
||||||
+ `Reason: ${reason ? reason : 'No reason provided.'}\n`
|
|
||||||
+ `Warn ID: ${infractionID}\n`
|
|
||||||
+ (extraText ?? ''),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
|
|
@ -218,36 +218,23 @@ async function sendLogMessage(config: LogConfig, content: LogMessage) {
|
||||||
const channel = client.channels.get(config.revolt.channel) || await client.channels.fetch(config.revolt.channel);
|
const channel = client.channels.get(config.revolt.channel) || await client.channels.fetch(config.revolt.channel);
|
||||||
|
|
||||||
let message = '';
|
let message = '';
|
||||||
|
let embed: SendableEmbed|undefined = undefined;
|
||||||
switch(config.revolt.type) {
|
switch(config.revolt.type) {
|
||||||
case 'RVEMBED':
|
case 'EMBED':
|
||||||
case 'DYNAMIC':
|
c = { ...c, ...content.overrides?.revoltEmbed };
|
||||||
c = { ...c, ...content.overrides?.revoltRvembed };
|
embed = {
|
||||||
let url = `https://rvembed.janderedev.xyz/embed`;
|
title: c.title,
|
||||||
let args = [];
|
description: c.description,
|
||||||
|
colour: c.color,
|
||||||
|
}
|
||||||
|
|
||||||
let description = (c.description ?? '');
|
|
||||||
if (c.fields?.length) {
|
if (c.fields?.length) {
|
||||||
for (const field of c.fields) {
|
for (const field of c.fields) {
|
||||||
description += `\n${field.title}\n` +
|
embed.description += `\n#### ${field.title}\n${field.content}`;
|
||||||
`${field.content}`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
description = description.trim();
|
|
||||||
|
|
||||||
if (c.title) args.push(`title=${encodeURIComponent(c.title)}`);
|
|
||||||
if (description) args.push(`description=${encodeURIComponent(description)}`);
|
|
||||||
if (c.color) args.push(`color=${encodeURIComponent(c.color)}`);
|
|
||||||
if (c.image) {
|
|
||||||
args.push(`image=${encodeURIComponent(c.image.url)}`);
|
|
||||||
args.push(`image_large=true`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(config.revolt.type == 'DYNAMIC' && (description.length > 1000 || description.split('\n').length > 6))) {
|
|
||||||
for (const i in args) url += `${i == '0' ? '?' : '&'}${args[i]}`;
|
|
||||||
message = `[\u200b](${url})`;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: // QUOTEBLOCK, PLAIN or unspecified
|
default: // QUOTEBLOCK, PLAIN or unspecified
|
||||||
|
|
||||||
// please disregard this mess
|
// please disregard this mess
|
||||||
|
@ -271,6 +258,7 @@ async function sendLogMessage(config: LogConfig, content: LogMessage) {
|
||||||
|
|
||||||
channel.sendMessage({
|
channel.sendMessage({
|
||||||
content: message,
|
content: message,
|
||||||
|
embeds: embed ? [ embed ] : undefined,
|
||||||
attachments: content.attachments ?
|
attachments: content.attachments ?
|
||||||
await Promise.all(content.attachments?.map(a => uploadFile(a.content, a.name))) :
|
await Promise.all(content.attachments?.map(a => uploadFile(a.content, a.name))) :
|
||||||
undefined
|
undefined
|
||||||
|
|
|
@ -2,11 +2,9 @@ export default class LogConfig {
|
||||||
revolt?: {
|
revolt?: {
|
||||||
channel?: string,
|
channel?: string,
|
||||||
|
|
||||||
// RVEMBED uses https://rvembed.janderedev.xyz to send a discord style embed, which doesn't
|
// EMBED uses Revolt's embeds.
|
||||||
// work properly with longer messages.
|
|
||||||
// PLAIN is like QUOTEBLOCK but without the quotes.
|
// PLAIN is like QUOTEBLOCK but without the quotes.
|
||||||
// DYNAMIC uses RVEMBED if the message is short enough, otherwise defaults to QUOTEBLOCK.
|
type?: 'EMBED'|'QUOTEBLOCK'|'PLAIN';
|
||||||
type?: 'QUOTEBLOCK'|'PLAIN'|'RVEMBED'|'DYNAMIC';
|
|
||||||
}
|
}
|
||||||
discord?: {
|
discord?: {
|
||||||
webhookUrl?: string,
|
webhookUrl?: string,
|
||||||
|
|
|
@ -11,7 +11,7 @@ export default class LogMessage {
|
||||||
attachments?: { name: string, content: Buffer }[];
|
attachments?: { name: string, content: Buffer }[];
|
||||||
overrides?: {
|
overrides?: {
|
||||||
// These take priority over `revolt`
|
// These take priority over `revolt`
|
||||||
revoltRvembed?: Override,
|
revoltEmbed?: Override,
|
||||||
revoltQuoteblock?: Override,
|
revoltQuoteblock?: Override,
|
||||||
|
|
||||||
revolt?: Override,
|
revolt?: Override,
|
||||||
|
|
|
@ -47,10 +47,10 @@
|
||||||
axios "^0.26.1"
|
axios "^0.26.1"
|
||||||
openapi-typescript "^5.2.0"
|
openapi-typescript "^5.2.0"
|
||||||
|
|
||||||
"@janderedev/revolt.js@^6.0.0-patch.3":
|
"@janderedev/revolt.js@^6.0.0-2-patch.1":
|
||||||
version "6.0.0-patch.3"
|
version "6.0.0-2-patch.1"
|
||||||
resolved "https://registry.yarnpkg.com/@janderedev/revolt.js/-/revolt.js-6.0.0-patch.3.tgz#7d9ad66e5a0d54fb2f5f0f8887cbd1382c69d301"
|
resolved "https://registry.yarnpkg.com/@janderedev/revolt.js/-/revolt.js-6.0.0-2-patch.1.tgz#c0e1b5004c2d212ceb4167c628de58ccb278b469"
|
||||||
integrity sha512-aZ1vubm8+l10lTy5HwO3vAc7E2/bm3+hfFhNqU7l+9QKecIAm6f45p7RNC19afSYChIZiyhtGPtWTuVJ9pa0RA==
|
integrity sha512-DxC9BlGgtx6D0Vb/Cvl5IPJJ7IEPtaD+FDuM1WHEvUUDBTcRZsaSXD/6EmzuejdXRVO9FEYKq1UMhLsX7TIDGg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@insertish/exponential-backoff" "3.1.0-patch.2"
|
"@insertish/exponential-backoff" "3.1.0-patch.2"
|
||||||
"@insertish/isomorphic-ws" "^4.0.1"
|
"@insertish/isomorphic-ws" "^4.0.1"
|
||||||
|
@ -61,7 +61,7 @@
|
||||||
lodash.isequal "^4.5.0"
|
lodash.isequal "^4.5.0"
|
||||||
long "^5.2.0"
|
long "^5.2.0"
|
||||||
mobx "^6.3.2"
|
mobx "^6.3.2"
|
||||||
revolt-api "0.5.3"
|
revolt-api "0.5.3-5-patch.3"
|
||||||
ulid "^2.3.0"
|
ulid "^2.3.0"
|
||||||
ws "^8.2.2"
|
ws "^8.2.2"
|
||||||
|
|
||||||
|
@ -600,10 +600,10 @@ require-at@^1.0.6:
|
||||||
resolved "https://registry.yarnpkg.com/require-at/-/require-at-1.0.6.tgz#9eb7e3c5e00727f5a4744070a7f560d4de4f6e6a"
|
resolved "https://registry.yarnpkg.com/require-at/-/require-at-1.0.6.tgz#9eb7e3c5e00727f5a4744070a7f560d4de4f6e6a"
|
||||||
integrity sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==
|
integrity sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==
|
||||||
|
|
||||||
revolt-api@0.5.3:
|
revolt-api@0.5.3-5-patch.3:
|
||||||
version "0.5.3"
|
version "0.5.3-5-patch.3"
|
||||||
resolved "https://registry.yarnpkg.com/revolt-api/-/revolt-api-0.5.3.tgz#e0ec2dcf812ea4338247b2eb77d67fc731d71b8a"
|
resolved "https://registry.yarnpkg.com/revolt-api/-/revolt-api-0.5.3-5-patch.3.tgz#73a0614a02a210adac2b946fc0fc35f4304fb348"
|
||||||
integrity sha512-hYdyStQiDZFvD+0dlf6SgQSiOk+JiEmQo0qIQHaqYRtrFN6FQBbGVNaiv7b5LzHHMPq7vks6ZVVA7hSNpcwlkA==
|
integrity sha512-xESgQ9kp8T5iupeixt/yJIiGDiM11pm1b2E6srM/+jrV7Jyrj/vPgDPv3hEeJFhNmUK6EP5tKxkmTBhcqNE/Vw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@insertish/oapi" "0.1.15"
|
"@insertish/oapi" "0.1.15"
|
||||||
axios "^0.26.1"
|
axios "^0.26.1"
|
||||||
|
|
Loading…
Reference in a new issue