Skip to content

Commit

Permalink
plugins can register interest in a message
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdickinson committed Jul 12, 2024
1 parent e454893 commit 7f1609e
Show file tree
Hide file tree
Showing 6 changed files with 394 additions and 126 deletions.
39 changes: 26 additions & 13 deletions LOUDBOT/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,38 @@ import {
Result,
IncomingReaction,
OutgoingRequest,
watchMessage,
} from "./pdk";
import { sendMessage, react, request } from "./pdk";

/**
* @param input An incoming event
*/
export function handleImpl(input: IncomingEvent) {
if (input.message) {
react({ messageId: input.message.id, channel: input.channel, with: '🎤' } as any)
const result = sendMessage({
message: 'WOW TURN IT DOWN OKAY'
})
export function handleImpl(input: any) {
switch (input.kind) {
case 'content':
react({ messageId: input.message!.id, channel: input.channel, with: '🎤' } as any)
const result = sendMessage({
message: 'WOW TURN IT DOWN OKAY',
reply: input.message!.id
} as any)

if (result.id) {
react({ messageId: result.id, channel: input.channel, with: '🎤' } as any)
} else {
console.log(JSON.stringify(result))
}
} else {
console.log('received message ' + JSON.stringify(input))
if (!result.id) {
return
}

watchMessage(result.id)
break;
case 'watch:reference':
console.log('I got that reference.')
break;
case 'watch:reaction:added':
console.log(JSON.stringify(input))
break;
case 'watch:reaction:removed':
console.log(JSON.stringify(input))
break;
default:
break
}
}
19 changes: 15 additions & 4 deletions plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,13 @@ imports:
schemas:
- name: IncomingEvent
description: An incoming event
required: ['channel']
required: ['kind', 'channel']
contentType: application/json
properties:
- name: kind
type: string
description: The reason for the event

- name: message
$ref: '#/schemas/IncomingMessage'
- name: reaction
Expand Down Expand Up @@ -120,7 +124,7 @@ schemas:

- name: IncomingMessage
description: An incoming message
required: ['id', 'message', 'author']
required: ['id', 'content', 'author']
contentType: application/json
properties:
- name: id
Expand All @@ -132,6 +136,9 @@ schemas:
- name: author
type: object
description: The author of the message
- name: reference
type: string
description: The id of the message to which this message replies

- name: OutgoingMessage
description: An outgoing message
Expand All @@ -144,14 +151,18 @@ schemas:
- name: channel
type: string
description: The channel the message was received in
- name: reply
type: string
description: A message ID to reply to

- name: Result
description: a result
description: A result.
contentType: application/json
properties:
- name: id
type: string
description: An id for the result
- name: errorCode
type: number
description: An error code.
description: |
An error code. Zero indicates success. Negative numbers indicate failure.
111 changes: 109 additions & 2 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import safe from 'safe-regex';

import { DISCORD_BOT_TOKEN, DISCORD_BOT_CLIENT_ID, DISCORD_GUILD_FILTER } from './config';
import { findUserByUsername, getXtpData, registerUser } from './domain/users';
import { executeHandlers, fetchByContentInterest, registerMessageContentInterest } from './domain/interests';
import { executeHandlers, fetchByContentInterest, fetchByMessageIdInterest, registerMessageContentInterest } from './domain/interests';
import { getLogger } from './logger';

type Logger = ReturnType<typeof getLogger>
Expand Down Expand Up @@ -52,14 +52,121 @@ export async function startDiscordClient(logger: Logger) {
await executeHandlers(client, handlers, {
channel: message.channel.name,
guild: guild.id,
kind: 'content',
message: {
id: message.id,
content: message.content,
author: message.author
author: message.author.username,
reference: message.reference?.messageId
}
}, {}, message.channel.name)

if (message.reference === null || !message.reference.messageId) {
return
}

const id = message.reference.messageId
const messageIdInterests = await fetchByMessageIdInterest({ guild: guild.id, channel: message.channel.name, id })
await executeHandlers(client, messageIdInterests, {
channel: message.channel.name,
guild: guild.id,
kind: 'watch:reference',
message: {
id: message.id,
content: message.content,
author: message.author.username,
reference: id,
}
}, {}, message.channel.name)

});

client.on('messageReactionAdd', async (reaction, user) => {
if (reaction.message.channel.type !== ChannelType.GuildText) {
console.log(`skipping message; channel type was not GuildText`)
return
}

if (user.id === client.user!.id) {
return;
}

const guild = reaction.message.guild || { name: "", id: "" };

if (reaction.message.channel.type !== ChannelType.GuildText) {
logger.info(`skipping message; channel type was not GuildText`)
return
}

if (DISCORD_GUILD_FILTER.size && !DISCORD_GUILD_FILTER.has(guild.name)) {
logger.info(`skipping message; not in guild filter (got="${guild.name}"; valid="${[...DISCORD_GUILD_FILTER].join('", "')}")`)
return
}

const handlers = await fetchByMessageIdInterest({
guild: guild.id,
channel: reaction.message.channel.name,
id: reaction.message.id
})
await executeHandlers(client, handlers, {
channel: reaction.message.channel.name,
guild: guild.id,
kind: 'watch:reaction:added',
reaction: {
message: {
id: reaction.message.id,
content: reaction.message.content,
author: reaction.message.author?.username,
},
from: user.username,
with: reaction.emoji,
}
}, {}, reaction.message.channel.name)
})

client.on('messageReactionRemove', async (reaction, user) => {
if (reaction.message.channel.type !== ChannelType.GuildText) {
console.log(`skipping message; channel type was not GuildText`)
return
}

if (user.id === client.user!.id) {
return;
}

const guild = reaction.message.guild || { name: "", id: "" };

if (reaction.message.channel.type !== ChannelType.GuildText) {
logger.info(`skipping message; channel type was not GuildText`)
return
}

if (DISCORD_GUILD_FILTER.size && !DISCORD_GUILD_FILTER.has(guild.name)) {
logger.info(`skipping message; not in guild filter (got="${guild.name}"; valid="${[...DISCORD_GUILD_FILTER].join('", "')}")`)
return
}

const handlers = await fetchByMessageIdInterest({
guild: guild.id,
channel: reaction.message.channel.name,
id: reaction.message.id
})
await executeHandlers(client, handlers, {
channel: reaction.message.channel.name,
guild: guild.id,
kind: 'watch:reaction:removed',
reaction: {
message: {
id: reaction.message.id,
content: reaction.message.content,
author: reaction.message.author?.username,
},
from: user.username,
with: reaction.emoji,
}
}, {}, reaction.message.channel.name)
})

client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) {
return;
Expand Down
36 changes: 24 additions & 12 deletions src/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import createClient from '@dylibso/xtp';
import EventEmitter from 'node:events'
import pg from 'pg'

import { HostContext } from './domain/host-context';
import { getLogger } from './logger';
import { PGURL } from './config';
import { HostContext } from './domain/interests';
console.log(process.env.XTP_ENDPOINT)

const logger = getLogger()

let db: any
export async function getDatabaseConnection() {
Expand Down Expand Up @@ -43,15 +44,15 @@ export async function getXtp(): ReturnType<typeof createClient> {
logger: getLogger(),
functions: {
'extism:host/user': {
async react(context: CurrentPlugin, outgoingReaction: bigint) {
async react(context: CurrentPlugin, outgoingReactionBuf: bigint) {
try {
const arg = context.read(outgoingReaction)!.json()
const outgoingReaction = context.read(outgoingReactionBuf)!.json()
const hostContext = context.hostContext<HostContext>();
const result = await hostContext.react(arg)
const result = await hostContext.react(outgoingReaction)

return context.store(JSON.stringify(result))
} catch (error: any) {
console.error(error.stack)
logger.error(error)
return context.store(JSON.stringify({ errorCode: -1, error }))
}
},
Expand All @@ -60,20 +61,31 @@ export async function getXtp(): ReturnType<typeof createClient> {
return 0n
},

async sendMessage(context: CurrentPlugin, outgoingMessage: bigint) {
async sendMessage(context: CurrentPlugin, outgoingMessageBuf: bigint) {
try {
const arg = context.read(outgoingMessage)!.json()
const outgoingMessage = context.read(outgoingMessageBuf)!.json()
const hostContext = context.hostContext<HostContext>();
const result = await hostContext.sendMessage(arg)
const result = await hostContext.sendMessage(outgoingMessage)

return context.store(JSON.stringify(result))
} catch (error) {
} catch (error: any) {
logger.error(error)
return context.store(JSON.stringify({ errorCode: -1, error }))
}
},

watchMessage(context: CurrentPlugin, outgoingRequest: bigint) {
return 0n
async watchMessage(context: CurrentPlugin, messageIdBuf: bigint) {
try {
const messageId = context.read(messageIdBuf)!.text()

const hostContext = context.hostContext<HostContext>();
const result = await hostContext.watchMessage(messageId)

return context.store(JSON.stringify(result))
} catch (error: any) {
logger.error(error)
return context.store(JSON.stringify({ errorCode: -1, error }))
}
}
}
}
Expand Down
Loading

0 comments on commit 7f1609e

Please sign in to comment.