This commit is contained in:
xhyrom 2021-12-21 11:10:06 +01:00
commit d7d487e0b2
8 changed files with 1465 additions and 0 deletions

18
.github/workflows/pages.yml vendored Normal file
View file

@ -0,0 +1,18 @@
name: Pages Deployment
on:
push:
branches: [main]
jobs:
website:
name: Website
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Deploy site
uses: JamesIves/github-pages-deploy-action@4.1.4
with:
branch: gh-pages
folder: src/web

135
.gitignore vendored Normal file
View file

@ -0,0 +1,135 @@
# Created by https://www.toptal.com/developers/gitignore/api/node
# Edit at https://www.toptal.com/developers/gitignore?templates=node
### Node ###
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
.env.production
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
### Node Patch ###
# Serverless Webpack directories
.webpack/
# Optional stylelint cache
.stylelintcache
# SvelteKit build / generate output
.svelte-kit
# End of https://www.toptal.com/developers/gitignore/api/node

8
format.json Normal file
View file

@ -0,0 +1,8 @@
{
"message": "lol",
"channel": "862700556438732851",
"roles": [
{"id": "777805077825060867","label":"Bots","emoji":"😦"},
{"id":"922762668841009152","label":"Ping","emoji":"🤩"}
]
}

1097
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

19
package.json Normal file
View file

@ -0,0 +1,19 @@
{
"name": "roles-bot-interactions",
"version": "1.0.0",
"description": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@types/express": "^4.17.13",
"@types/node": "^17.0.2",
"discord-interactions": "^2.4.1",
"dotenv": "^10.0.0",
"express": "^4.17.2",
"hyttpo": "^0.3.2"
}
}

6
src/bot/constants.ts Normal file
View file

@ -0,0 +1,6 @@
export interface RoleObject {
label?: string,
emoji?: string,
id?: string,
style?: number
}

117
src/bot/index.ts Normal file
View file

@ -0,0 +1,117 @@
require('dotenv').config();
import express from 'express';
import hyttpo, { PayloadMethod } from 'hyttpo';
import Utils from 'hyttpo/dist/js/util/utils';
import { RoleObject } from './constants';
import { verifyKeyMiddleware, InteractionType, InteractionResponseType, InteractionResponseFlags } from 'discord-interactions';
const app = express();
const baseUrl = 'https://discord.com/api/v9';
app.get('/', (req, res) => res.send('lol'))
const badFormatting = (res, rolesMax?: boolean) => {
res.send({
type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
data: {
flags: InteractionResponseFlags.EPHEMERAL,
content: `${rolesMax ? 'You can have maximum 25 buttons. (5x5)' : 'Bad formatting, generate [here](https://xhyrom.github.io/roles-bot)'}`
}
})
}
app.post('/interactions', verifyKeyMiddleware(process.env.CLIENT_PUBLIC_KEY), async(req, res) => {
const interaction = req.body;
if (interaction.type === InteractionType.APPLICATION_COMMAND && interaction.data.name === 'setup') {
const json = Utils.isJSON(interaction.data.options[0].value) ? JSON.parse(interaction.data.options[0].value) : null;
if (!json) return badFormatting(res);
const channelId = json.channel;
const message = json.message?.toString();
let roles = json.roles;
if (!channelId) return badFormatting(res);
if (!message) return badFormatting(res);
if (!roles || Object.values(json.roles).filter((role: RoleObject) => role.id && role.label).length === 0 || roles.length === 0 || roles.length > 25) return badFormatting(res, roles.length > 25);
roles = roles.map(r => {
return {
type: 2,
style: r.style || 2,
label: r.label,
emoji: {
id: null,
name: r.emoji
},
custom_id: r.id
}
})
const finalComponents = [];
for (let i = 0; i <= roles.length; i += 5) {
const row = {
type: 1,
components: []
}
const btnslice = roles.slice(i, i + 5);
for (let y = 0; y < btnslice.length; y++) row.components.push(btnslice[y]);
finalComponents.push(row);
}
await hyttpo.request({
method: 'POST',
url: `${baseUrl}/channels/${channelId}/messages`,
headers: {
'Authorization': `Bot ${process.env.CLIENT_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
content: message,
components: finalComponents
})
}).catch(e => e)
res.send({
type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
data: {
flags: InteractionResponseFlags.EPHEMERAL,
content: 'Done!'
}
})
} else if (interaction.type === InteractionType.MESSAGE_COMPONENT) {
const roleId = interaction.data.custom_id;
const url = `${baseUrl}/guilds/${interaction.guild_id}/members/${interaction.member.user.id}/roles/${roleId}`;
let method = "";
let content = "";
if (!interaction.member.roles.includes(roleId)) {
content = `Gave the <@&${roleId}> role!`;
method = 'PUT';
} else {
content = `Removed the <@&${roleId}> role!`;
method = 'DELETE';
}
await hyttpo.request({
method: method as PayloadMethod,
url,
headers: {
'Authorization': `Bot ${process.env.CLIENT_TOKEN}`
},
body: JSON.stringify({})
}).catch(e => e);
res.send({
type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
data: {
flags: InteractionResponseFlags.EPHEMERAL,
content: content,
allowed_mentions: { parse: [] }
}
})
}
});
app.listen(80)

65
src/web/index.html Normal file
View file

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html>
<body>
Message
<input name="message" id="message"/>
<br/><br/>
Channel Id
<input name="channel" id="channel"/>
<br/><br/>
<button id='addRole'>Add Role</button>
<p id='json'></p>
<script src="//cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js'></script>
<script>
let json = {
roles: []
}
$('input').change((e) => {
json[e.currentTarget.id] = e.currentTarget.value;
document.getElementById('json').innerText = JSON.stringify(json);
})
$('button[id=addRole]').click((e) => {
Swal.fire({
title: 'Add Role',
html:
'<input id="swal-input1" class="swal2-input" placeholder="Button Label*" required>' +
'<input id="swal-input2" class="swal2-input" placeholder="Role Id*" required>' +
'<input id="swal-input3" class="swal2-input" placeholder="Emoji">',
preConfirm: function () {
return new Promise(function (resolve) {
resolve([
$('#swal-input1').val(),
$('#swal-input2').val(),
$('#swal-input3').val()
])
})
},
}).then(function (result) {
if (result.value?.[0] && result.value?.[1]) {
json.roles.push({
id: result.value[1],
label: result.value[0],
emoji: result.value[2] || null
})
document.getElementById('json').innerText = JSON.stringify(json);
} else Swal.fire('Missing parameters')
}).catch(swal.noop)
})
$(window).on('load', () => {
$('input').toArray().forEach((i) => i.value = '');
document.getElementById('json').innerText = JSON.stringify(json);
})
</script>
</body>
</html>