Skip to content

Commit

Permalink
feat: new message properties and methods (#75)
Browse files Browse the repository at this point in the history
* feat: new message properties and methods

* i hate everything

* try no permission setting at all

* add token

* why wont you work wtf

* what about this
  • Loading branch information
thewilloftheshadow authored Sep 11, 2024
1 parent ad217dd commit 50e360e
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 22 deletions.
5 changes: 5 additions & 0 deletions .changeset/olive-horses-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@buape/carbon": minor
---

feat: new message properties and methods
22 changes: 3 additions & 19 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ jobs:
- name: Build
run: pnpm run ci

- name: Publish
run: pnpx pkg-pr-new publish './packages/*' --comment=update --pnpm

biome:
name: Check Formatting
timeout-minutes: 15
Expand All @@ -46,22 +49,3 @@ jobs:

- name: Run tests
run: pnpm run test

library_build:
name: Build and publish
runs-on: ubuntu-latest
needs: [build, biome, test]
permissions:
pull-requests: write
steps:
- name: Check out code
uses: actions/checkout@v4

- name: Setup
uses: ./.github/actions/setup

- name: Build
run: pnpm build --filter={./packages/*}

- name: Publish
run: pnpx pkg-pr-new publish './packages/*' --comment=update --pnpm
170 changes: 167 additions & 3 deletions packages/carbon/src/structures/Message.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import {
type APIAllowedMentions,
type APIAttachment,
type APIChannel,
type APIMessage,
type APIMessageInteractionMetadata,
type APIMessageReference,
type APIPoll,
type APIReaction,
type APISticker,
type APIThreadChannel,
type ChannelType,
type MessageFlags,
type MessageType,
type RESTPostAPIChannelThreadsJSONBody,
Routes
} from "discord-api-types/v10"
Expand All @@ -10,21 +20,96 @@ import type { Client } from "../classes/Client.js"
import { channelFactory } from "../factories/channelFactory.js"
import { GuildThreadChannel } from "./GuildThreadChannel.js"
import { User } from "./User.js"
import { Embed } from "../classes/Embed.js"
import type { Row } from "../classes/Row.js"
import { Role } from "./Role.js"

export class Message extends Base {
/**
* The ID of the message
*/
id: string
protected id: string
/**
* The ID of the channel the message is in
*/
channelId: string
protected channelId: string
/**
* Whether the message is a partial message (meaning it does not have all the data).
* If this is true, you should use {@link Message.fetch} to get the full data of the message.
*/
partial: boolean
protected partial: boolean
/**
* If this message is a response to an interaction, this is the ID of the interaction's application
*/
protected applicationId?: string
/**
* The attachments of the message
*/
protected attachments?: APIAttachment[]
/**
* The components of the message
*/
protected components?: APIMessage["components"]
/**
* The content of the message
*/
protected content?: string
/**
* If this message was edited, this is the timestamp of the edit
*/
protected editedTimestamp?: string | null
/**
* The flags of the message
*/
protected flags?: MessageFlags
/**
* The interaction metadata of the message
*/
protected interactionMetadata?: APIMessageInteractionMetadata
/**
* Whether the message mentions everyone
*/
protected mentionedEveryone?: boolean
/**
* The data about the referenced message. You can use {@link Message.referencedMessage} to get the referenced message itself.
*/
protected messageReference?: APIMessageReference
/**
* Whether the message is pinned
*/
protected pinned?: boolean
/**
* The poll contained in the message
*/
protected poll?: APIPoll
/**
* The approximate position of the message in the channel
*/
protected position?: number
/**
* The reactions on the message
*/
protected reactions?: APIReaction[]
/**
* The stickers in the message
*/
protected stickers?: APISticker[]
/**
* The timestamp of the original message
*/
protected timestamp?: string
/**
* Whether the message is a TTS message
*/
protected tts?: boolean
/**
* The type of the message
*/
protected type?: MessageType
/**
* If a webhook is used to send the message, this is the ID of the webhook
*/
protected webhookId?: string

private rawData: APIMessage | null = null

Expand All @@ -51,6 +136,24 @@ export class Message extends Base {
private setData(data: typeof this.rawData) {
this.rawData = data
if (!data) throw new Error("Cannot set data without having data... smh")
this.applicationId = data.application_id
this.attachments = data.attachments
this.components = data.components
this.content = data.content
this.editedTimestamp = data.edited_timestamp
this.flags = data.flags
this.interactionMetadata = data.interaction_metadata
this.mentionedEveryone = data.mention_everyone
this.messageReference = data.message_reference
this.pinned = data.pinned
this.poll = data.poll
this.position = data.position
this.reactions = data.reactions
this.stickers = data.stickers
this.timestamp = data.timestamp
this.tts = data.tts
this.type = data.type
this.webhookId = data.webhook_id
}

/**
Expand All @@ -76,6 +179,9 @@ export class Message extends Base {
)
}

/**
* Get the author of the message
*/
get author(): User | null {
if (this.rawData?.webhook_id) return null // TODO: Add webhook user
// Check if we have an additional property on the author object, in which case we have a full user object
Expand All @@ -87,6 +193,9 @@ export class Message extends Base {
return null
}

/**
* Get the channel the message was sent in
*/
async fetchChannel() {
const data = (await this.client.rest.get(
Routes.channel(this.channelId)
Expand Down Expand Up @@ -121,4 +230,59 @@ export class Message extends Base {
)) as APIThreadChannel
return new GuildThreadChannel(this.client, thread)
}

get thread(): GuildThreadChannel<
ChannelType.PublicThread | ChannelType.AnnouncementThread
> | null {
if (!this.rawData?.thread) return null
return channelFactory(
this.client,
this.rawData?.thread
) as GuildThreadChannel<
ChannelType.PublicThread | ChannelType.AnnouncementThread
>
}

get embeds(): Embed[] {
if (!this.rawData?.embeds) return []
return this.rawData.embeds.map((embed) => new Embed(embed))
}

async edit(data: {
content?: string
embeds?: Embed[]
allowedMentions?: APIAllowedMentions
components?: Row[]
}) {
await this.client.rest.patch(
Routes.channelMessage(this.channelId, this.id),
{
body: {
...data,
embeds: data.embeds?.map((embed) => embed.serialize()),
components: data.components?.map((row) => row.serialize()),
allowed_mentions: data.allowedMentions
}
}
)
}

get mentionedUsers(): User[] {
if (!this.rawData?.mentions) return []
return this.rawData.mentions.map(
(mention) => new User(this.client, mention)
)
}

get mentionedRoles(): Role[] {
if (!this.rawData?.mention_roles) return []
return this.rawData.mention_roles.map(
(mention) => new Role(this.client, mention)
)
}

get referencedMessage(): Message | null {
if (!this.rawData?.referenced_message) return null
return new Message(this.client, this.rawData?.referenced_message)
}
}

0 comments on commit 50e360e

Please sign in to comment.