Hello!
I recently create a module that post Discord’s Webhook with strict typing,
However, After making it halfway, i notice that there’s many repeated element in type,
Are there something like extending type
like in Typescript?
Typescript extending type
interface Shape {
color: string;
}
// What i meant by extending type
interface Square extends Shape {
sideLength: number;
}
My Code
local HttpService = game:GetService("HttpService")
local DiscordWebhook = {}
-- TYPE --
export type EmbedType = "rich" | "image" | "video" | "gifv" | "article" | "link"
export type EmbedThumbnail = {
url: string,
proxy_url: string?,
height: number?,
width: number?
}
export type EmbedVideo = {
url: string?,
proxy_url: string?,
height: number?,
width: number?
}
export type EmbedImage = {
url: string,
proxy_url: string?,
height: number?,
width: number?
}
export type EmbedProvider = {
name: string?,
url: string?
}
export type EmbedAuthor = {
name: string,
url: string?,
icon_url: string?,
proxy_icon_url: string?
}
export type EmbedFooter = {
text: string,
icon_url: string?,
proxy_icon_url: string?
}
export type EmbedField = {
name: string,
value: string,
inline: boolean?
}
export type Embed = {
title: string?,
type: EmbedType?,
description: string?,
url: string?,
timestamp: string?,
color: number?,
footer: EmbedFooter?,
image: EmbedImage?,
thumbnail: EmbedThumbnail?,
video: EmbedVideo?,
provider: EmbedProvider?,
author: EmbedAuthor?,
fields: {[number]: EmbedField}?
}
export type AllowedMentions = {
parse: {[string]: "users" | "roles" | "everyone"},
roles: {[number]: string},
users: {[number]: string},
replied_user: boolean?
}
export type WebhookRequest = {
content: string,
username: string?,
avatar_url: string?,
tts: boolean?,
embeds: {[number]: Embed}?,
allowed_mentions: {[number]: AllowedMentions}?,
components: any?, --TODO
payload_json: string?,
attachments: {[number]: any}?,
flags: number?,
thread_name: string?,
[string]: any
}
export type User = {
id: string,
username: string,
discriminator: string,
avatar: string?,
bot: boolean?,
system: boolean?,
mfa_enabled: boolean?,
banner: string?,
accent_color: number?,
locale: string?,
verified: boolean?,
email: string?,
flags: number?,
premium_type: number?,
public_flags: number?
}
export type MessageReference = {
message_id: string?,
channel_id: string?,
guild_id: string?,
fail_if_not_exists: boolean?
}
export type StickerItem = {
id: string,
name: string,
format_type: number
}
export type Sticker = {
id: string,
pack_id: string?,
name: string,
description: string?,
tags: string,
asset: string?,
type: number,
format_type: number,
available: boolean?,
guild_id: string,
user: User?,
sort_value: number?
}
export type Attachment = {
id: string,
filename: string,
description: string?,
content_type: string?,
size: number,
url: string,
proxy_url: string,
height: number?,
width: number?,
ephemeral: boolean?,
}
export type GuildMember = {
user: User?,
nick: string?,
avatar: string?,
roles: {[number]: string},
joined_at: string?,
premium_since: string?,
deaf: boolean?,
mute: boolean?,
pending: boolean?,
permissions: string?,
communication_disabled_until: string?
}
export type MessageMentionUser = {
id: string,
username: string,
discriminator: string,
avatar: string?,
bot: boolean?,
system: boolean?,
mfa_enabled: boolean?,
banner: string?,
accent_color: number?,
locale: string?,
verified: boolean?,
email: string?,
flags: number?,
premium_type: number?,
public_flags: number?,
member: GuildMember
}
export type MessageActivity = {
type: number,
party_id: string?
}
export type Emoji = {
id: string?,
name: string,
roles: {[number]: string},
user: User?,
require_colons: boolean?,
managed: boolean?,
animated: boolean?,
available: boolean?
}
export type Reaction = {
count: number,
me: boolean,
emoji: Emoji
}
export type ChannelMention = {
id: string,
guild_id: string,
type: number,
name: string
}
export type MessageInteraction = {
id: string,
type: number,
name: string,
user: User,
member: GuildMember?
}
export type ThreadMember = {
id: string?,
user_id: string?,
join_timestamp: string,
flags: number
}
export type ThreadMetadata = {
archived: boolean,
auto_archive_duration: number,
archive_timestamp: string,
locked: boolean,
invitable: boolean?,
create_timestamp: string?
}
export type Overwrite = {
id: string,
type: number,
allow: string,
deny: string
}
export type Channel = {
id: string,
type: number,
guild_id: number?,
position: number?,
permission_overwrites: {[number]: Overwrite}?,
name: string?,
topic: string?,
nsfw: boolean?,
last_message_id: string?,
bitrate: number?,
user_limit: number?,
rate_limit_per_user: number?,
recipients: {[number]: User}?,
icon: string?,
owner_id: string?,
application_id: string?,
parent_id: string?,
last_pin_timestamp: string?,
rtc_region: string?,
video_quality_mode: number?,
message_count: number?,
member_count: number?,
thread_metadata: ThreadMetadata?,
member: ThreadMember?,
default_auto_archive_duration: number?,
permissions: string?,
flags: number?
}
export type InstallParams = {
scopes: {[number]: string},
permissions: string
}
export type TeamMember = {
membership_state: number,
permissions: {[number]: string},
team_id: string,
user: User
}
export type Team = {
icon: string?,
id: string,
members: {[number]: TeamMember},
name: string,
owner_user_id: string
}
export type Application = {
id: string,
name: string,
icon: string?,
description: string,
rpc_origins: {[number]: string},
bot_public: boolean,
bot_require_code_grant: boolean,
terms_of_service_url: string?,
privacy_policy_url: string?,
owner: User?,
summary: string, -- deprecated
verify_key: string,
team: Team?,
guild_id: string?,
primary_sku_id: string?,
slug: string?,
cover_image: string?,
flags: number?,
tags: {[number]: string}?,
install_params: InstallParams?,
custom_install_url: string?
}
export type Message = {
id: string,
channel_id: string,
guild_id: string?,
author: User,
member: GuildMember?,
content: string,
timestamp: number,
edited_timestamp: number?,
tts: boolean,
mention_everyone: boolean,
mentions: {[number]: MessageMentionUser},
mention_roles: {[number]: string},
mention_channels: {[number]: ChannelMention},
attachments: {[number]: Attachment},
embeds: {[number]: Embed},
reactions: {[string]: Reaction},
pinned: boolean,
webhook_id: string?,
type: number,
activity: MessageActivity?,
application: Application?,
message_reference: MessageReference?,
flags: number?,
referenced_message: Message?,
interaction: MessageInteraction?,
thread: Channel?,
components: {[number]: any}?, --TODO
sticker_items: {[number]: StickerItem}?,
stickers: {[number]: Sticker}?
}
---------------------------------
function DiscordWebhook.new(id: string?, token: string?, version: number?)
local self = setmetatable({
id = id,
token = token,
version = version or 10
}, DiscordWebhook)
return self
end
function DiscordWebhook:Post(data: WebhookRequest, url: string?): Message?
url = url or "https://discord.com/api/v" .. self.version .. "/webhooks/" .. self.id .. "/" .. self.token
local success, response = pcall(function()
return HttpService:PostAsync(url, HttpService:JSONEncode(data))
end)
return success and (HttpService:JSONDecode(response) :: Message) or nil
end
return DiscordWebhook
Thank you!