* Discord chat bot to announce projects (#590) Add support for discord chat bot to announce when images are set, with instructions on configuring for dev. This uses the REST API instead of a websocket connection, which is needed for serverless deployment. Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch> * Remove discord.js dependency. Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch>
This commit was merged in pull request #600.
This commit is contained in:
@@ -32,7 +32,7 @@ Install dependencies
|
|||||||
yarn install
|
yarn install
|
||||||
```
|
```
|
||||||
|
|
||||||
Setting up the db, you'll need to have a postgres installed locally, you can [follow this guide](https://redwoodjs.com/docs/local-postgres-setup).
|
Setting up the db, you'll need to have a postgres installed locally, you can [follow this guide](https://redwoodjs.com/docs/local-postgres-setup).
|
||||||
|
|
||||||
Run the following (Note: these commands require the `DATABASE_URL` env variable to be set. if you see no result when you run `echo $DATABASE_URL`, you can set it with a command like `export DATABASE_URL=postgres://postgres:somepassword@localhost`)
|
Run the following (Note: these commands require the `DATABASE_URL` env variable to be set. if you see no result when you run `echo $DATABASE_URL`, you can set it with a command like `export DATABASE_URL=postgres://postgres:somepassword@localhost`)
|
||||||
``` terminal
|
``` terminal
|
||||||
@@ -59,6 +59,27 @@ localUser2@kurthutten.com: `abc123`
|
|||||||
|
|
||||||
localAdmin@kurthutten.com: `abc123`
|
localAdmin@kurthutten.com: `abc123`
|
||||||
|
|
||||||
|
### Discord bot setup
|
||||||
|
|
||||||
|
To set up the discord bot to notify when users publish new content, we're using the [REST](https://discord.com/developers/docs/resources/channel#message-object) API directly, used more as a notification service rather than a bot since we are not listening to messages in the chat.
|
||||||
|
|
||||||
|
1. If you're setting up the bot in a dev environment, create a new discord server (the "plus" button on the left when logged into the Discord webpage). Make note of the name of the project.
|
||||||
|
2. With [developer mode turned on](https://www.howtogeek.com/714348/how-to-enable-or-disable-developer-mode-on-discord/), right click the channel you wish the bot to announce on and select "Copy ID". Add this to `.env.defaults` as `DISCORD_CHANNEL_ID`.
|
||||||
|
3. [create a new application](https://discord.com/developers/applications), or navigate to an existing one.
|
||||||
|
4. Create a bot within that application. Copy the bot token and add it to `.env.defaults` as `DISCORD_TOKEN`.
|
||||||
|
5. Go to the "URL Generator" under "OAuth2" and create a URL with scope "bot" and text permission "Send Messages".
|
||||||
|
6. Copy the generated URL and open it in a new tab. Follow the instructions on the page to add the bot to your discord server.
|
||||||
|
|
||||||
|
When you next start CADHub, you should see in the logs `Discord: logged in as <bot name>` and you should see a startup message from the bot in the channel.
|
||||||
|
|
||||||
|
To send messages as the bot when things happen in the service, use the `sendChat` helper function:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { sendDiscordMessage } from 'src/lib/discord'
|
||||||
|
|
||||||
|
sendDiscordMessage("hello world!")
|
||||||
|
```
|
||||||
|
|
||||||
## Designs
|
## Designs
|
||||||
|
|
||||||
In progress, though can be [seen on Figma](https://www.figma.com/file/VUh53RdncjZ7NuFYj0RGB9/CadHub?node-id=0%3A1)
|
In progress, though can be [seen on Figma](https://www.figma.com/file/VUh53RdncjZ7NuFYj0RGB9/CadHub?node-id=0%3A1)
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ CLOUDINARY_API_KEY=476712943135152
|
|||||||
# trace | info | debug | warn | error | silent
|
# trace | info | debug | warn | error | silent
|
||||||
# LOG_LEVEL=debug
|
# LOG_LEVEL=debug
|
||||||
|
|
||||||
|
|
||||||
# EMAIL_PASSWORD=abc123
|
# EMAIL_PASSWORD=abc123
|
||||||
|
# DISCORD_TOKEN=abc123
|
||||||
|
# DISCORD_CHANNEL_ID=12345
|
||||||
|
|
||||||
# CAD_LAMBDA_BASE_URL="http://localhost:8080"
|
# CAD_LAMBDA_BASE_URL="http://localhost:8080"
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"@redwoodjs/api": "^0.38.1",
|
"@redwoodjs/api": "^0.38.1",
|
||||||
"@redwoodjs/graphql-server": "^0.38.1",
|
"@redwoodjs/graphql-server": "^0.38.1",
|
||||||
"@sentry/node": "^6.5.1",
|
"@sentry/node": "^6.5.1",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.25.0",
|
||||||
"cloudinary": "^1.23.0",
|
"cloudinary": "^1.23.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
@@ -21,4 +21,4 @@
|
|||||||
"concurrently": "^6.0.0",
|
"concurrently": "^6.0.0",
|
||||||
"nodemon": "^2.0.7"
|
"nodemon": "^2.0.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
33
app/api/src/lib/discord.ts
Normal file
33
app/api/src/lib/discord.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
let inst = null;
|
||||||
|
if (!process.env.DISCORD_TOKEN || !process.env.DISCORD_CHANNEL_ID) {
|
||||||
|
console.warn("Discord bot not configured - please set process.env.DISCORD_TOKEN and process.env.DISCORD_CHANNEL_ID to send discord chats");
|
||||||
|
} else {
|
||||||
|
inst = axios.create({
|
||||||
|
baseURL: 'https://discord.com/api'
|
||||||
|
});
|
||||||
|
inst.defaults.headers.common['Authorization'] = `Bot ${process.env.DISCORD_TOKEN}`
|
||||||
|
console.log(`Discord: using API token ${process.env.DISCORD_TOKEN}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function sendDiscordMessage(text: string, url?: string) {
|
||||||
|
if (!inst) {
|
||||||
|
console.error(`Discord: not configured to send message ("${text}")`);
|
||||||
|
} else {
|
||||||
|
const API_URL = `/channels/${process.env.DISCORD_CHANNEL_ID}/messages`;
|
||||||
|
if (url) {
|
||||||
|
return inst.post(API_URL, { embeds: [{
|
||||||
|
title: text,
|
||||||
|
image: {
|
||||||
|
url,
|
||||||
|
},
|
||||||
|
}] });
|
||||||
|
} else {
|
||||||
|
return inst.post(API_URL, {
|
||||||
|
content: text,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -12,6 +12,8 @@ import {
|
|||||||
} from 'src/services/helpers'
|
} from 'src/services/helpers'
|
||||||
import { requireAuth } from 'src/lib/auth'
|
import { requireAuth } from 'src/lib/auth'
|
||||||
import { requireOwnership, requireProjectOwnership } from 'src/lib/owner'
|
import { requireOwnership, requireProjectOwnership } from 'src/lib/owner'
|
||||||
|
import { sendDiscordMessage } from 'src/lib/discord'
|
||||||
|
|
||||||
|
|
||||||
export const projects = ({ userName }) => {
|
export const projects = ({ userName }) => {
|
||||||
if (!userName) {
|
if (!userName) {
|
||||||
@@ -243,7 +245,19 @@ export const updateProjectImages = async ({
|
|||||||
const [updatedProject] = await Promise.all([
|
const [updatedProject] = await Promise.all([
|
||||||
projectPromise,
|
projectPromise,
|
||||||
imageDestroyPromise,
|
imageDestroyPromise,
|
||||||
])
|
]).then(async (result) => {
|
||||||
|
const { userName } = await db.user.findUnique({
|
||||||
|
where: { id: project.userId },
|
||||||
|
})
|
||||||
|
sendDiscordMessage([
|
||||||
|
`${userName} just added an image to their ${project.cadPackage} project:`,
|
||||||
|
` => ${project.title}`,
|
||||||
|
``,
|
||||||
|
`Check it out, leave a comment, make them feel welcome!`,
|
||||||
|
`https://cadhub.xyz/u/${userName}/${project.title}`
|
||||||
|
].join('\n'), `https://res.cloudinary.com/irevdev/image/upload/c_scale,w_700/v1/${mainImage}`)
|
||||||
|
return result
|
||||||
|
})
|
||||||
return updatedProject
|
return updatedProject
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
'SENTRY_AUTH_TOKEN',
|
'SENTRY_AUTH_TOKEN',
|
||||||
'SENTRY_ORG',
|
'SENTRY_ORG',
|
||||||
'SENTRY_PROJECT',
|
'SENTRY_PROJECT',
|
||||||
'EMAIL_PASSWORD'
|
'EMAIL_PASSWORD',
|
||||||
]
|
]
|
||||||
# experimentalFastRefresh = true # this seems to break cascadeStudio
|
# experimentalFastRefresh = true # this seems to break cascadeStudio
|
||||||
[api]
|
[api]
|
||||||
|
|||||||
@@ -5300,6 +5300,13 @@ axios@^0.21.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects "^1.14.0"
|
follow-redirects "^1.14.0"
|
||||||
|
|
||||||
|
axios@^0.25.0:
|
||||||
|
version "0.25.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a"
|
||||||
|
integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==
|
||||||
|
dependencies:
|
||||||
|
follow-redirects "^1.14.7"
|
||||||
|
|
||||||
axobject-query@^2.2.0:
|
axobject-query@^2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
|
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
|
||||||
@@ -9205,6 +9212,11 @@ follow-redirects@^1.0.0, follow-redirects@^1.14.0:
|
|||||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
|
||||||
integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==
|
integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==
|
||||||
|
|
||||||
|
follow-redirects@^1.14.7:
|
||||||
|
version "1.14.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685"
|
||||||
|
integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==
|
||||||
|
|
||||||
for-in@^1.0.2:
|
for-in@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
|
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
|
||||||
|
|||||||
Reference in New Issue
Block a user