Skip to content

Commit

Permalink
fix: dm messages not being emitted (#291)
Browse files Browse the repository at this point in the history
* fix: dm messages not being emitted
* upgrade ed25519
  • Loading branch information
DjDeveloperr authored Jan 18, 2022
1 parent 9ad2a12 commit 95d52cb
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 24 deletions.
2 changes: 2 additions & 0 deletions deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ export { fetchAuto } from 'https://deno.land/x/[email protected]/mod.ts'
export { walk } from 'https://deno.land/[email protected]/fs/walk.ts'
export { join } from 'https://deno.land/[email protected]/path/mod.ts'
export { Mixin } from 'https://esm.sh/[email protected]'
export { verify as edverify } from 'https://unpkg.com/@evan/[email protected]/target/ed25519/deno.js'
export { decode as decodeHex } from 'https://deno.land/[email protected]/encoding/hex.ts'
30 changes: 20 additions & 10 deletions src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,19 +192,24 @@ export class Client extends HarmonyEventEmitter<ClientEvents> {
this.shards = new ShardManager(this)
this.forceNewSession = options.forceNewSession
if (options.cache !== undefined) this.cache = options.cache
if (options.presence !== undefined)
if (options.presence !== undefined) {
this.presence =
options.presence instanceof ClientPresence
? options.presence
: new ClientPresence(options.presence)
if (options.messageCacheLifetime !== undefined)
}
if (options.messageCacheLifetime !== undefined) {
this.messageCacheLifetime = options.messageCacheLifetime
if (options.reactionCacheLifetime !== undefined)
}
if (options.reactionCacheLifetime !== undefined) {
this.reactionCacheLifetime = options.reactionCacheLifetime
if (options.fetchUncachedReactions === true)
}
if (options.fetchUncachedReactions === true) {
this.fetchUncachedReactions = true
if (options.messageCacheMax !== undefined)
}
if (options.messageCacheMax !== undefined) {
this.messageCacheMax = options.messageCacheMax
}
if (options.compress !== undefined) this.compress = options.compress

if (
Expand Down Expand Up @@ -251,8 +256,9 @@ export class Client extends HarmonyEventEmitter<ClientEvents> {
client: this
}

if (options.restOptions !== undefined)
if (options.restOptions !== undefined) {
Object.assign(restOptions, options.restOptions)
}
this.rest = new RESTManager(restOptions)

this.slash = this.interactions = new InteractionsClient({
Expand Down Expand Up @@ -282,8 +288,9 @@ export class Client extends HarmonyEventEmitter<ClientEvents> {
this.presence = presence
} else this.presence = new ClientPresence(presence)
this.shards.list.forEach((shard) => {
if (onlyInShards.length !== 0 && onlyInShards.includes(shard.shardID))
if (onlyInShards.length !== 0 && onlyInShards.includes(shard.shardID)) {
return
}
shard.sendPresence(this.presence.create())
})
}
Expand Down Expand Up @@ -354,8 +361,9 @@ export class Client extends HarmonyEventEmitter<ClientEvents> {

this.rest.token = token
if (this.shard !== undefined) {
if (typeof this.shardCount === 'number')
if (typeof this.shardCount === 'number') {
this.shards.cachedShardCount = this.shardCount
}
await this.shards.launch(this.shard)
} else await this.shards.connect()
await readyPromise
Expand Down Expand Up @@ -424,10 +432,11 @@ export class Client extends HarmonyEventEmitter<ClientEvents> {
username?: string
avatar?: string
}): Promise<Client> {
if (data.username === undefined && data.avatar === undefined)
if (data.username === undefined && data.avatar === undefined) {
throw new Error(
'Either username or avatar or both must be specified to edit'
)
}

if (data.avatar?.startsWith('http') === true) {
data.avatar = await fetchAuto(data.avatar)
Expand Down Expand Up @@ -493,8 +502,9 @@ export function event(name?: keyof ClientEvents) {
[name in keyof ClientEvents]: (...args: ClientEvents[name]) => any
}
)[prop as unknown as keyof ClientEvents]
if (typeof listener !== 'function')
if (typeof listener !== 'function') {
throw new Error('@event decorator requires a function')
}

if (c._decoratedEvents === undefined) c._decoratedEvents = {}
const key = name === undefined ? prop : name
Expand Down
13 changes: 11 additions & 2 deletions src/gateway/handlers/messageCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,22 @@ export const messageCreate: GatewayEventHandler = async (
gateway: Gateway,
d: MessagePayload
) => {
const channel = await gateway.client.channels.get<TextChannel>(d.channel_id)
let channel = await gateway.client.channels.get<TextChannel>(d.channel_id)
// Fetch the channel if not cached.
// Commented out right now as it causes some undefined behavior.
// if (channel === undefined)
// // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
// channel = (await gateway.client.channels.fetch(d.channel_id)) as TextChannel
if (channel === undefined) return
if (channel === undefined) {
if (d.guild_id === undefined) {
// Let's assume it's a DM channel.
await gateway.client.channels.set(d.channel_id, {
id: d.channel_id,
type: 1
})
channel = (await gateway.client.channels.get<TextChannel>(d.channel_id))!
} else return
}
await channel.messages.set(d.id, d)
const user = new User(gateway.client, d.author)
await gateway.client.users.set(d.author.id, d.author)
Expand Down
34 changes: 22 additions & 12 deletions src/interactions/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ import {
InteractionType
} from '../types/interactions.ts'
import {
ApplicationCommandType,
ApplicationCommandOptionType,
ApplicationCommandType,
InteractionApplicationCommandData
} from '../types/applicationCommand.ts'
import type { Client } from '../client/mod.ts'
import { RESTManager } from '../rest/mod.ts'
import { ApplicationCommandsModule } from './commandModule.ts'
import { verify as edverify } from 'https://deno.land/x/[email protected]/mod.ts'
import { edverify, decodeHex } from '../../deps.ts'
import { User } from '../structures/user.ts'
import { HarmonyEventEmitter } from '../utils/events.ts'
import { encodeText, decodeText } from '../utils/encoding.ts'
import { decodeText, encodeText } from '../utils/encoding.ts'
import { ApplicationCommandsManager } from './applicationCommand.ts'
import { Application } from '../structures/application.ts'
import { Member } from '../structures/member.ts'
Expand Down Expand Up @@ -101,8 +101,9 @@ export class InteractionsClient extends HarmonyEventEmitter<InteractionsClientEv
super()
let id = options.id
if (options.token !== undefined) id = atob(options.token?.split('.')[0])
if (id === undefined)
if (id === undefined) {
throw new Error('ID could not be found. Pass at least client or token')
}
this.id = id

if (options.client !== undefined) {
Expand Down Expand Up @@ -203,8 +204,9 @@ export class InteractionsClient extends HarmonyEventEmitter<InteractionsClientEv
typeof type === 'string' ? ApplicationCommandType[type] : type
}

if (handle.handler === undefined)
if (handle.handler === undefined) {
throw new Error('Invalid usage. Handler function not provided')
}

if (
(handle.type === undefined ||
Expand All @@ -215,8 +217,9 @@ export class InteractionsClient extends HarmonyEventEmitter<InteractionsClientEv
handle.group === undefined
) {
const parts = handle.name.split(/ +/).filter((e) => e !== '')
if (parts.length > 3 || parts.length < 1)
if (parts.length > 3 || parts.length < 1) {
throw new Error('Invalid command name')
}
const root = parts.shift() as string
const group = parts.length === 2 ? parts.shift() : undefined
const sub = parts.shift()
Expand Down Expand Up @@ -359,28 +362,34 @@ export class InteractionsClient extends HarmonyEventEmitter<InteractionsClientEv
}

/** Verify HTTP based Interaction */
async verifyKey(
verifyKey(
rawBody: string | Uint8Array,
signature: string | Uint8Array,
timestamp: string | Uint8Array
): Promise<boolean> {
if (this.publicKey === undefined)
): boolean {
if (this.publicKey === undefined) {
throw new Error('Public Key is not present')
}

const fullBody = new Uint8Array([
...(typeof timestamp === 'string' ? encodeText(timestamp) : timestamp),
...(typeof rawBody === 'string' ? encodeText(rawBody) : rawBody)
])

return edverify(signature, fullBody, this.publicKey).catch(() => false)
return edverify(
decodeHex(encodeText(this.publicKey)),
decodeHex(
signature instanceof Uint8Array ? signature : encodeText(signature)
),
fullBody
)
}

/**
* Verify [Deno Std HTTP Server Request](https://deno.land/std/http/server.ts) and return Interaction.
*
* **Data present in Interaction returned by this method is very different from actual typings
* as there is no real `Client` behind the scenes to cache things.**
*
*/
async verifyServerRequest(req: {
headers: Headers
Expand Down Expand Up @@ -596,8 +605,9 @@ export class InteractionsClient extends HarmonyEventEmitter<InteractionsClientEv
const timestamp = req.headers.get('x-signature-timestamp')
const contentLength = req.headers.get('content-length')

if (signature === null || timestamp === null || contentLength === null)
if (signature === null || timestamp === null || contentLength === null) {
return false
}

const body = new Uint8Array(parseInt(contentLength))
await req.body.read(body)
Expand Down

0 comments on commit 95d52cb

Please sign in to comment.