Move discord bot out of packages directory
This commit is contained in:
2
pkg/discord/.env.test
Normal file
2
pkg/discord/.env.test
Normal file
@ -0,0 +1,2 @@
|
||||
API_ENV=local
|
||||
DISCORD_BOT_KEY=BlaBlaBla
|
||||
56
pkg/discord/.eslintrc
Normal file
56
pkg/discord/.eslintrc
Normal file
@ -0,0 +1,56 @@
|
||||
{
|
||||
"extends": "eslint:recommended",
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2021,
|
||||
"project": "tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
"arrow-spacing": ["warn", { "before": true, "after": true }],
|
||||
"brace-style": ["error", "stroustrup", { "allowSingleLine": true }],
|
||||
"comma-dangle": ["warn", {
|
||||
"arrays": "always-multiline",
|
||||
"objects": "always-multiline",
|
||||
"imports": "always-multiline",
|
||||
"exports": "always-multiline",
|
||||
"functions": "never"
|
||||
}],
|
||||
"comma-spacing": "error",
|
||||
"comma-style": "error",
|
||||
"curly": ["error", "multi-line", "consistent"],
|
||||
"dot-location": ["error", "property"],
|
||||
"handle-callback-err": "off",
|
||||
"indent": ["warn", 2],
|
||||
"keyword-spacing": "error",
|
||||
"max-nested-callbacks": ["error", { "max": 4 }],
|
||||
"max-statements-per-line": ["error", { "max": 2 }],
|
||||
"no-console": "off",
|
||||
"no-empty-function": "error",
|
||||
"no-floating-decimal": "error",
|
||||
"no-inline-comments": "error",
|
||||
"no-lonely-if": "error",
|
||||
"no-multi-spaces": "error",
|
||||
"no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }],
|
||||
"no-shadow": ["error", { "allow": ["err", "resolve", "reject"] }],
|
||||
"no-trailing-spaces": ["error"],
|
||||
"no-var": "error",
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
"prefer-const": "error",
|
||||
"quotes": ["error", "single"],
|
||||
"semi": ["warn", "never"],
|
||||
"space-before-blocks": "error",
|
||||
"space-before-function-paren": ["error", {
|
||||
"anonymous": "never",
|
||||
"named": "never",
|
||||
"asyncArrow": "always"
|
||||
}],
|
||||
"space-in-parens": "error",
|
||||
"space-infix-ops": "error",
|
||||
"space-unary-ops": "error",
|
||||
"spaced-comment": "error",
|
||||
"yoda": "error"
|
||||
}
|
||||
}
|
||||
33
pkg/discord/Dockerfile
Normal file
33
pkg/discord/Dockerfile
Normal file
@ -0,0 +1,33 @@
|
||||
FROM node:18.16 as builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update && apt-get install -y g++ make python3
|
||||
|
||||
COPY package.json .
|
||||
COPY yarn.lock .
|
||||
COPY tsconfig.json .
|
||||
COPY .prettierrc .
|
||||
COPY .eslintrc .
|
||||
|
||||
COPY /packages/discord/src ./packages/discord/src
|
||||
COPY /packages/discord/package.json ./packages/discord/package.json
|
||||
COPY /packages/discord/tsconfig.json ./packages/discord/tsconfig.json
|
||||
|
||||
RUN yarn install --pure-lockfile
|
||||
RUN yarn workspace @omnivore/discord build
|
||||
|
||||
FROM node:18.16 as runner
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV production
|
||||
|
||||
COPY --from=builder /app/packages/discord/dist /app/packages/discord/dist
|
||||
COPY --from=builder /app/packages/discord/package.json /app/packages/discord/package.json
|
||||
COPY --from=builder /app/packages/discord/node_modules /app/packages/discord/node_modules
|
||||
|
||||
COPY --from=builder /app/node_modules /app/node_modules
|
||||
COPY --from=builder /app/package.json /app/package.json
|
||||
|
||||
CMD ["yarn", "workspace", "@omnivore/discord", "start"]
|
||||
22
pkg/discord/package.json
Normal file
22
pkg/discord/package.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "@omnivore/discord",
|
||||
"version": "1.0.0",
|
||||
"description": "A Discord Bot to extract features to add to Community Picks",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "ts-node-dev --files src/index.ts",
|
||||
"start": "node dist/index.js",
|
||||
"lint": "eslint src --ext ts,js,tsx,jsx",
|
||||
"lint:fix": "eslint src --fix --ext ts,js,tsx,jsx",
|
||||
"test:typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@google-cloud/pubsub": "^4.0.0",
|
||||
"discord.js": "^14.14.1",
|
||||
"dotenv": "^16.4.5",
|
||||
"typescript": "^5.4.2",
|
||||
"typescript-eslint": "^7.1.1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
||||
94
pkg/discord/src/index.ts
Normal file
94
pkg/discord/src/index.ts
Normal file
@ -0,0 +1,94 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
|
||||
import {
|
||||
Client,
|
||||
Partials,
|
||||
GatewayIntentBits,
|
||||
Events,
|
||||
MessageReaction,
|
||||
User,
|
||||
Embed,
|
||||
PartialMessageReaction,
|
||||
PartialUser,
|
||||
} from 'discord.js'
|
||||
import { PubSub } from '@google-cloud/pubsub'
|
||||
import { OmnivoreArticle } from './types/OmnivoreArticle'
|
||||
import { slugify } from 'voca'
|
||||
import * as dotenv from 'dotenv'
|
||||
|
||||
dotenv.config()
|
||||
|
||||
const client = new Client({
|
||||
partials: [Partials.Message, Partials.Reaction],
|
||||
intents: [
|
||||
GatewayIntentBits.GuildMessageReactions,
|
||||
GatewayIntentBits.GuildMessages,
|
||||
GatewayIntentBits.MessageContent,
|
||||
GatewayIntentBits.Guilds,
|
||||
],
|
||||
})
|
||||
|
||||
const pubSubClient = new PubSub()
|
||||
|
||||
// Will have missed people here
|
||||
const VALID_USERS = new Set([
|
||||
'danielprindii',
|
||||
'riiku',
|
||||
'hongbowu',
|
||||
'mollydot',
|
||||
'jackson.harper',
|
||||
'podginator',
|
||||
])
|
||||
const TOPIC_NAME = 'discordCommunityArticles'
|
||||
|
||||
client.once(Events.ClientReady, () => {
|
||||
console.log('Ready!')
|
||||
})
|
||||
|
||||
const createMessageFromEmbed = (embed: Embed): OmnivoreArticle | undefined => {
|
||||
if (!embed.url || !embed.title || !embed.description) {
|
||||
return undefined
|
||||
}
|
||||
return {
|
||||
slug: slugify(embed.url),
|
||||
title: embed.title,
|
||||
description: embed.description,
|
||||
image: embed.thumbnail?.url,
|
||||
url: embed.url,
|
||||
authors: embed.author?.name ?? new URL(embed.url).host,
|
||||
publishedAt: new Date(),
|
||||
site: embed.url,
|
||||
type: 'community',
|
||||
}
|
||||
}
|
||||
|
||||
client.on(
|
||||
Events.MessageReactionAdd,
|
||||
async (
|
||||
props: MessageReaction | PartialMessageReaction,
|
||||
user: User | PartialUser
|
||||
): Promise<void> => {
|
||||
const emoji = props.emoji.name
|
||||
const message = props.message.partial
|
||||
? await props.message.fetch(true)
|
||||
: props.message
|
||||
const embed = message.embeds[0]
|
||||
const userName = user.username
|
||||
|
||||
if (emoji === '🦥' && userName && VALID_USERS.has(userName) && embed) {
|
||||
const jsonMessage = createMessageFromEmbed(embed)
|
||||
if (message) {
|
||||
await pubSubClient
|
||||
.topic(TOPIC_NAME)
|
||||
.publishMessage({ json: jsonMessage })
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
client.login(process.env.DISCORD_BOT_KEY).catch((error) => {
|
||||
console.log('error logging in:', error)
|
||||
})
|
||||
11
pkg/discord/src/types/OmnivoreArticle.ts
Normal file
11
pkg/discord/src/types/OmnivoreArticle.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export type OmnivoreArticle = {
|
||||
slug: string
|
||||
title: string
|
||||
description: string
|
||||
image?: string
|
||||
authors: string
|
||||
site: string
|
||||
url: string
|
||||
publishedAt: Date
|
||||
type: 'community'
|
||||
}
|
||||
14
pkg/discord/tsconfig.json
Normal file
14
pkg/discord/tsconfig.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "./../../tsconfig.json",
|
||||
"compileOnSave": false,
|
||||
"include": ["src/**/*"],
|
||||
"ts-node": {
|
||||
"files": true
|
||||
},
|
||||
"exclude": ["**/node_modules"],
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"outDir": "dist",
|
||||
}
|
||||
}
|
||||
|
||||
51
pkg/discord/tslint.json
Normal file
51
pkg/discord/tslint.json
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
"extends": "tslint:recommended",
|
||||
"rulesDirectory": ["codelyzer"],
|
||||
"rules": {
|
||||
"array-type": false,
|
||||
"arrow-parens": false,
|
||||
"deprecation": {
|
||||
"severity": "warn"
|
||||
},
|
||||
"import-blacklist": [true, "rxjs/Rx"],
|
||||
"interface-name": false,
|
||||
"max-classes-per-file": false,
|
||||
"max-line-length": [true, 140],
|
||||
"member-access": false,
|
||||
"member-ordering": [
|
||||
true,
|
||||
{
|
||||
"order": [
|
||||
"static-field",
|
||||
"instance-field",
|
||||
"static-method",
|
||||
"instance-method"
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-consecutive-blank-lines": false,
|
||||
"no-console": [true, "debug", "info", "time", "timeEnd", "trace"],
|
||||
"no-empty": false,
|
||||
"no-inferrable-types": [true, "ignore-params"],
|
||||
"no-non-null-assertion": true,
|
||||
"no-redundant-jsdoc": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-use-before-declare": true,
|
||||
"no-var-requires": false,
|
||||
"object-literal-key-quotes": [true, "as-needed"],
|
||||
"object-literal-sort-keys": false,
|
||||
"ordered-imports": false,
|
||||
"quotemark": [true, "single"],
|
||||
"trailing-comma": false,
|
||||
"no-output-on-prefix": true,
|
||||
"no-inputs-metadata-property": true,
|
||||
"no-outputs-metadata-property": true,
|
||||
"no-host-metadata-property": true,
|
||||
"no-input-rename": true,
|
||||
"no-output-rename": true,
|
||||
"use-life-cycle-interface": true,
|
||||
"use-pipe-transform-interface": true,
|
||||
"component-class-suffix": true,
|
||||
"directive-class-suffix": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user