support rich replies, support basic m.mentions
This commit is contained in:
parent
5326b7d6be
commit
328ae74b61
7 changed files with 689 additions and 16 deletions
|
@ -27,7 +27,7 @@ async function sendMessage(message, guild) {
|
|||
await registerUser.syncUser(message.author, message.member, message.guild_id, roomID)
|
||||
}
|
||||
|
||||
const events = await messageToEvent.messageToEvent(message, guild)
|
||||
const events = await messageToEvent.messageToEvent(message, guild, api)
|
||||
const eventIDs = []
|
||||
let eventPart = 0 // 0 is primary, 1 is supporting
|
||||
for (const event of events) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
const assert = require("assert").strict
|
||||
const markdown = require("discord-markdown")
|
||||
const DiscordTypes = require("discord-api-types/v10")
|
||||
|
||||
const passthrough = require("../../passthrough")
|
||||
const { sync, db, discord } = passthrough
|
||||
|
@ -39,10 +40,56 @@ function getDiscordParseCallbacks(message, useHTML) {
|
|||
/**
|
||||
* @param {import("discord-api-types/v10").APIMessage} message
|
||||
* @param {import("discord-api-types/v10").APIGuild} guild
|
||||
* @param {import("../../matrix/api")} api simple-as-nails dependency injection for the matrix API
|
||||
*/
|
||||
async function messageToEvent(message, guild) {
|
||||
async function messageToEvent(message, guild, api) {
|
||||
const events = []
|
||||
|
||||
/**
|
||||
@type {{room?: boolean, user_ids?: string[]}}
|
||||
We should consider the following scenarios for mentions:
|
||||
1. TODO A discord user rich-replies to a matrix user with a text post
|
||||
+ The matrix user needs to be m.mentioned in the text event
|
||||
+ The matrix user needs to have their name/mxid/link in the text event (notification fallback)
|
||||
- So prepend their `@name:` to the start of the plaintext body
|
||||
2. TODO A discord user rich-replies to a matrix user with an image event only
|
||||
+ The matrix user needs to be m.mentioned in the image event
|
||||
+ The matrix user needs to have their name/mxid in the image event's body field, alongside the filename (notification fallback)
|
||||
- So append their name to the filename body, I guess!!!
|
||||
3. TODO A discord user `@`s a matrix user in the text body of their text box
|
||||
+ The matrix user needs to be m.mentioned in the text event
|
||||
+ No change needed to the text event content: it already has their name
|
||||
- So make sure we don't do anything in this case.
|
||||
*/
|
||||
const mentions = {}
|
||||
let repliedToEventId = null
|
||||
let repliedToEventRoomId = null
|
||||
let repliedToEventSenderMxid = null
|
||||
let repliedToEventOriginallyFromMatrix = false
|
||||
|
||||
function addMention(mxid) {
|
||||
if (!mentions.user_ids) mentions.user_ids = []
|
||||
mentions.user_ids.push(mxid)
|
||||
}
|
||||
|
||||
// Mentions scenarios 1 and 2, part A. i.e. translate relevant message.mentions to m.mentions
|
||||
// (Still need to do scenarios 1 and 2 part B, and scenario 3.)
|
||||
if (message.type === DiscordTypes.MessageType.Reply && message.message_reference?.message_id) {
|
||||
const row = db.prepare("SELECT event_id, room_id, source FROM event_message INNER JOIN channel_room USING (channel_id) WHERE message_id = ? AND part = 0").get(message.message_reference.message_id)
|
||||
if (row) {
|
||||
repliedToEventId = row.event_id
|
||||
repliedToEventRoomId = row.room_id
|
||||
repliedToEventOriginallyFromMatrix = row.source === 0 // source 0 = matrix
|
||||
}
|
||||
}
|
||||
if (repliedToEventOriginallyFromMatrix) {
|
||||
// Need to figure out who sent that event...
|
||||
const event = await api.getEvent(repliedToEventRoomId, repliedToEventId)
|
||||
repliedToEventSenderMxid = event.sender
|
||||
// Need to add the sender to m.mentions
|
||||
addMention(repliedToEventSenderMxid)
|
||||
}
|
||||
|
||||
// Text content appears first
|
||||
if (message.content) {
|
||||
let content = message.content
|
||||
|
@ -55,33 +102,63 @@ async function messageToEvent(message, guild) {
|
|||
}
|
||||
})
|
||||
|
||||
const html = markdown.toHTML(content, {
|
||||
let html = markdown.toHTML(content, {
|
||||
discordCallback: getDiscordParseCallbacks(message, true)
|
||||
}, null, null)
|
||||
|
||||
const body = markdown.toHTML(content, {
|
||||
let body = markdown.toHTML(content, {
|
||||
discordCallback: getDiscordParseCallbacks(message, false),
|
||||
discordOnly: true,
|
||||
escapeHTML: false,
|
||||
}, null, null)
|
||||
|
||||
// Fallback body/formatted_body for replies
|
||||
if (repliedToEventId) {
|
||||
let repliedToDisplayName
|
||||
let repliedToUserHtml
|
||||
if (repliedToEventOriginallyFromMatrix && repliedToEventSenderMxid) {
|
||||
const match = repliedToEventSenderMxid.match(/^@([^:]*)/)
|
||||
assert(match)
|
||||
repliedToDisplayName = match[1] || "a Matrix user" // grab the localpart as the display name, whatever
|
||||
repliedToUserHtml = `<a href="https://matrix.to/#/${repliedToEventSenderMxid}">${repliedToDisplayName}</a>`
|
||||
} else {
|
||||
repliedToDisplayName = message.referenced_message?.author.global_name || message.referenced_message?.author.username || "a Discord user"
|
||||
repliedToUserHtml = repliedToDisplayName
|
||||
}
|
||||
const repliedToContent = message.referenced_message?.content || "[Replied-to message content wasn't provided by Discord]"
|
||||
const repliedToHtml = markdown.toHTML(repliedToContent, {
|
||||
discordCallback: getDiscordParseCallbacks(message, true)
|
||||
}, null, null)
|
||||
const repliedToBody = markdown.toHTML(repliedToContent, {
|
||||
discordCallback: getDiscordParseCallbacks(message, false),
|
||||
discordOnly: true,
|
||||
escapeHTML: false,
|
||||
}, null, null)
|
||||
html = `<mx-reply><blockquote><a href="https://matrix.to/#/${repliedToEventRoomId}/${repliedToEventId}">In reply to</a> ${repliedToUserHtml}`
|
||||
+ `<br>${repliedToHtml}</blockquote></mx-reply>`
|
||||
+ html
|
||||
body = (`${repliedToDisplayName}: ` // scenario 1 part B for mentions
|
||||
+ repliedToBody).split("\n").map(line => "> " + line).join("\n")
|
||||
+ "\n\n" + body
|
||||
}
|
||||
|
||||
const newTextMessageEvent = {
|
||||
$type: "m.room.message",
|
||||
"m.mentions": mentions,
|
||||
msgtype: "m.text",
|
||||
body: body
|
||||
}
|
||||
|
||||
const isPlaintext = body === html
|
||||
|
||||
if (isPlaintext) {
|
||||
events.push({
|
||||
$type: "m.room.message",
|
||||
msgtype: "m.text",
|
||||
body: body
|
||||
})
|
||||
} else {
|
||||
events.push({
|
||||
$type: "m.room.message",
|
||||
msgtype: "m.text",
|
||||
body: body,
|
||||
if (!isPlaintext) {
|
||||
Object.assign(newTextMessageEvent, {
|
||||
format: "org.matrix.custom.html",
|
||||
formatted_body: html
|
||||
})
|
||||
}
|
||||
|
||||
events.push(newTextMessageEvent)
|
||||
}
|
||||
|
||||
// Then attachments
|
||||
|
@ -90,6 +167,7 @@ async function messageToEvent(message, guild) {
|
|||
if (attachment.content_type?.startsWith("image/") && attachment.width && attachment.height) {
|
||||
return {
|
||||
$type: "m.room.message",
|
||||
"m.mentions": mentions,
|
||||
msgtype: "m.image",
|
||||
url: await file.uploadDiscordFileToMxc(attachment.url),
|
||||
external_url: attachment.url,
|
||||
|
@ -105,6 +183,7 @@ async function messageToEvent(message, guild) {
|
|||
} else {
|
||||
return {
|
||||
$type: "m.room.message",
|
||||
"m.mentions": mentions,
|
||||
msgtype: "m.text",
|
||||
body: "Unsupported attachment:\n" + JSON.stringify(attachment, null, 2)
|
||||
}
|
||||
|
@ -122,6 +201,7 @@ async function messageToEvent(message, guild) {
|
|||
if (sticker && sticker.description) body += ` - ${sticker.description}`
|
||||
return {
|
||||
$type: "m.sticker",
|
||||
"m.mentions": mentions,
|
||||
body,
|
||||
info: {
|
||||
mimetype: format.mime
|
||||
|
@ -131,6 +211,7 @@ async function messageToEvent(message, guild) {
|
|||
} else {
|
||||
return {
|
||||
$type: "m.room.message",
|
||||
"m.mentions": mentions,
|
||||
msgtype: "m.text",
|
||||
body: "Unsupported sticker format. Name: " + stickerItem.name
|
||||
}
|
||||
|
@ -139,6 +220,17 @@ async function messageToEvent(message, guild) {
|
|||
events.push(...stickerEvents)
|
||||
}
|
||||
|
||||
// Rich replies
|
||||
if (repliedToEventId) {
|
||||
Object.assign(events[0], {
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
event_id: repliedToEventId
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return events
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,39 @@
|
|||
const {test} = require("supertape")
|
||||
const {messageToEvent} = require("./message-to-event")
|
||||
const data = require("../../test/data")
|
||||
const Ty = require("../../types")
|
||||
|
||||
/**
|
||||
* @param {string} roomID
|
||||
* @param {string} eventID
|
||||
* @returns {(roomID: string, eventID: string) => Promise<Ty.Event.Outer<Ty.Event.M_Room_Message>>}
|
||||
*/
|
||||
function mockGetEvent(t, roomID_in, eventID_in, outer) {
|
||||
return async function(roomID, eventID) {
|
||||
t.equal(roomID, roomID_in)
|
||||
t.equal(eventID, eventID_in)
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
event_id: eventID_in,
|
||||
room_id: roomID_in,
|
||||
origin_server_ts: 1680000000000,
|
||||
unsigned: {
|
||||
age: 2245,
|
||||
transaction_id: "$local.whatever"
|
||||
},
|
||||
...outer
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
test("message2event: simple plaintext", async t => {
|
||||
const events = await messageToEvent(data.message.simple_plaintext, data.guild.general)
|
||||
t.deepEqual(events, [{
|
||||
$type: "m.room.message",
|
||||
"m.mentions": {},
|
||||
msgtype: "m.text",
|
||||
body: "ayy lmao"
|
||||
}])
|
||||
|
@ -15,6 +43,7 @@ test("message2event: simple user mention", async t => {
|
|||
const events = await messageToEvent(data.message.simple_user_mention, data.guild.general)
|
||||
t.deepEqual(events, [{
|
||||
$type: "m.room.message",
|
||||
"m.mentions": {},
|
||||
msgtype: "m.text",
|
||||
body: "@crunch god: Tell me about Phil, renowned martial arts master and creator of the Chin Trick",
|
||||
format: "org.matrix.custom.html",
|
||||
|
@ -26,6 +55,7 @@ test("message2event: simple room mention", async t => {
|
|||
const events = await messageToEvent(data.message.simple_room_mention, data.guild.general)
|
||||
t.deepEqual(events, [{
|
||||
$type: "m.room.message",
|
||||
"m.mentions": {},
|
||||
msgtype: "m.text",
|
||||
body: "#main",
|
||||
format: "org.matrix.custom.html",
|
||||
|
@ -37,6 +67,7 @@ test("message2event: simple message link", async t => {
|
|||
const events = await messageToEvent(data.message.simple_message_link, data.guild.general)
|
||||
t.deepEqual(events, [{
|
||||
$type: "m.room.message",
|
||||
"m.mentions": {},
|
||||
msgtype: "m.text",
|
||||
body: "https://matrix.to/#/!kLRqKKUQXcibIMtOpl:cadence.moe/$X16nfVks1wsrhq4E9SSLiqrf2N8KD0erD0scZG7U5xg",
|
||||
format: "org.matrix.custom.html",
|
||||
|
@ -48,6 +79,7 @@ test("message2event: attachment with no content", async t => {
|
|||
const events = await messageToEvent(data.message.attachment_no_content, data.guild.general)
|
||||
t.deepEqual(events, [{
|
||||
$type: "m.room.message",
|
||||
"m.mentions": {},
|
||||
msgtype: "m.image",
|
||||
url: "mxc://cadence.moe/qXoZktDqNtEGuOCZEADAMvhM",
|
||||
body: "image.png",
|
||||
|
@ -65,10 +97,12 @@ test("message2event: stickers", async t => {
|
|||
const events = await messageToEvent(data.message.sticker, data.guild.general)
|
||||
t.deepEqual(events, [{
|
||||
$type: "m.room.message",
|
||||
"m.mentions": {},
|
||||
msgtype: "m.text",
|
||||
body: "can have attachments too"
|
||||
}, {
|
||||
$type: "m.room.message",
|
||||
"m.mentions": {},
|
||||
msgtype: "m.image",
|
||||
url: "mxc://cadence.moe/ZDCNYnkPszxGKgObUIFmvjus",
|
||||
body: "image.png",
|
||||
|
@ -81,6 +115,7 @@ test("message2event: stickers", async t => {
|
|||
},
|
||||
}, {
|
||||
$type: "m.sticker",
|
||||
"m.mentions": {},
|
||||
body: "pomu puff - damn that tiny lil bitch really chuffing. puffing that fat ass dart",
|
||||
info: {
|
||||
mimetype: "image/png"
|
||||
|
@ -90,3 +125,94 @@ test("message2event: stickers", async t => {
|
|||
url: "mxc://cadence.moe/UuUaLwXhkxFRwwWCXipDlBHn"
|
||||
}])
|
||||
})
|
||||
|
||||
test("message2event: skull webp attachment with content", async t => {
|
||||
const events = await messageToEvent(data.message.skull_webp_attachment_with_content, data.guild.general)
|
||||
t.deepEqual(events, [{
|
||||
$type: "m.room.message",
|
||||
"m.mentions": {},
|
||||
msgtype: "m.text",
|
||||
body: "Image"
|
||||
}, {
|
||||
$type: "m.room.message",
|
||||
"m.mentions": {},
|
||||
msgtype: "m.image",
|
||||
body: "skull.webp",
|
||||
info: {
|
||||
w: 1200,
|
||||
h: 628,
|
||||
mimetype: "image/webp",
|
||||
size: 74290
|
||||
},
|
||||
external_url: "https://cdn.discordapp.com/attachments/112760669178241024/1128084747910918195/skull.webp",
|
||||
url: "mxc://cadence.moe/sDxWmDErBhYBxtDcJQgBETes"
|
||||
}])
|
||||
})
|
||||
|
||||
test("message2event: reply to skull webp attachment with content", async t => {
|
||||
const events = await messageToEvent(data.message.reply_to_skull_webp_attachment_with_content, data.guild.general)
|
||||
t.deepEqual(events, [{
|
||||
$type: "m.room.message",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
event_id: "$oLyUTyZ_7e_SUzGNWZKz880ll9amLZvXGbArJCKai2Q"
|
||||
}
|
||||
},
|
||||
"m.mentions": {},
|
||||
msgtype: "m.text",
|
||||
body: "> Extremity: Image\n\nReply",
|
||||
format: "org.matrix.custom.html",
|
||||
formatted_body:
|
||||
'<mx-reply><blockquote><a href="https://matrix.to/#/!kLRqKKUQXcibIMtOpl:cadence.moe/$oLyUTyZ_7e_SUzGNWZKz880ll9amLZvXGbArJCKai2Q">In reply to</a> Extremity'
|
||||
+ '<br>Image</blockquote></mx-reply>'
|
||||
+ 'Reply'
|
||||
}, {
|
||||
$type: "m.room.message",
|
||||
"m.mentions": {},
|
||||
msgtype: "m.image",
|
||||
body: "RDT_20230704_0936184915846675925224905.jpg",
|
||||
info: {
|
||||
w: 2048,
|
||||
h: 1536,
|
||||
mimetype: "image/jpeg",
|
||||
size: 85906
|
||||
},
|
||||
external_url: "https://cdn.discordapp.com/attachments/112760669178241024/1128084851023675515/RDT_20230704_0936184915846675925224905.jpg",
|
||||
url: "mxc://cadence.moe/WlAbFSiNRIHPDEwKdyPeGywa"
|
||||
}])
|
||||
})
|
||||
|
||||
test("message2event: simple reply to matrix user", async t => {
|
||||
const events = await messageToEvent(data.message.simple_reply_to_matrix_user, data.guild.general, {
|
||||
getEvent: mockGetEvent(t, "!kLRqKKUQXcibIMtOpl:cadence.moe", "$Ij3qo7NxMA4VPexlAiIx2CB9JbsiGhJeyt-2OvkAUe4", {
|
||||
type: "m.room.message",
|
||||
content: {
|
||||
msgtype: "m.text",
|
||||
body: "so can you reply to my webhook uwu"
|
||||
},
|
||||
sender: "@cadence:cadence.moe"
|
||||
})
|
||||
})
|
||||
t.deepEqual(events, [{
|
||||
$type: "m.room.message",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
event_id: "$Ij3qo7NxMA4VPexlAiIx2CB9JbsiGhJeyt-2OvkAUe4"
|
||||
}
|
||||
},
|
||||
"m.mentions": {
|
||||
user_ids: [
|
||||
"@cadence:cadence.moe"
|
||||
]
|
||||
},
|
||||
msgtype: "m.text",
|
||||
body: "> cadence: so can you reply to my webhook uwu\n\nReply",
|
||||
format: "org.matrix.custom.html",
|
||||
formatted_body:
|
||||
'<mx-reply><blockquote><a href="https://matrix.to/#/!kLRqKKUQXcibIMtOpl:cadence.moe/$Ij3qo7NxMA4VPexlAiIx2CB9JbsiGhJeyt-2OvkAUe4">In reply to</a> <a href="https://matrix.to/#/@cadence:cadence.moe">cadence</a>'
|
||||
+ '<br>so can you reply to my webhook uwu</blockquote></mx-reply>'
|
||||
+ 'Reply'
|
||||
}])
|
||||
})
|
||||
|
||||
// TODO: read "edits of replies" in the spec
|
||||
|
|
|
@ -65,6 +65,17 @@ async function leaveRoom(roomID, mxid) {
|
|||
await mreq.mreq("POST", path(`/client/v3/rooms/${roomID}/leave`, mxid), {})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomID
|
||||
* @param {string} eventID
|
||||
* @template T
|
||||
*/
|
||||
async function getEvent(roomID, eventID) {
|
||||
/** @type {Ty.Event.Outer<T>} */
|
||||
const root = await mreq.mreq("GET", `/client/v3/rooms/${roomID}/event/${eventID}`)
|
||||
return root
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomID
|
||||
* @returns {Promise<Ty.Event.BaseStateEvent[]>}
|
||||
|
@ -73,6 +84,15 @@ function getAllState(roomID) {
|
|||
return mreq.mreq("GET", `/client/v3/rooms/${roomID}/state`)
|
||||
}
|
||||
|
||||
/**
|
||||
* "Any of the AS's users must be in the room. This API is primarily for Application Services and should be faster to respond than /members as it can be implemented more efficiently on the server."
|
||||
* @param {string} roomID
|
||||
* @returns {Promise<{joined: {[mxid: string]: Ty.R.RoomMember}}>}
|
||||
*/
|
||||
function getJoinedMembers(roomID) {
|
||||
return mreq.mreq("GET", `/client/v3/rooms/${roomID}/joined_members`)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomID
|
||||
* @param {string} type
|
||||
|
@ -114,7 +134,9 @@ module.exports.createRoom = createRoom
|
|||
module.exports.joinRoom = joinRoom
|
||||
module.exports.inviteToRoom = inviteToRoom
|
||||
module.exports.leaveRoom = leaveRoom
|
||||
module.exports.getEvent = getEvent
|
||||
module.exports.getAllState = getAllState
|
||||
module.exports.getJoinedMembers = getJoinedMembers
|
||||
module.exports.sendState = sendState
|
||||
module.exports.sendEvent = sendEvent
|
||||
module.exports.profileSetDisplayname = profileSetDisplayname
|
||||
|
|
|
@ -35,6 +35,6 @@
|
|||
"tap-dot": "github:cloudrac3r/tap-dot#223a4e67a6f7daf015506a12a7af74605f06c7f4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "cross-env FORCE_COLOR=true supertape --format tap test/test.js | tap-dot"
|
||||
"test": "cross-env FORCE_COLOR=true supertape --no-check-assertions-count --format tap test/test.js | tap-dot"
|
||||
}
|
||||
}
|
||||
|
|
428
test/data.js
428
test/data.js
|
@ -423,6 +423,434 @@ module.exports = {
|
|||
flags: 0,
|
||||
components: []
|
||||
},
|
||||
skull_webp_attachment_with_content: {
|
||||
type: 0,
|
||||
tts: false,
|
||||
timestamp: "2023-07-10T22:06:02.805000+00:00",
|
||||
referenced_message: null,
|
||||
pinned: false,
|
||||
nonce: "1128084721398448128",
|
||||
mentions: [],
|
||||
mention_roles: [],
|
||||
mention_everyone: false,
|
||||
member: {
|
||||
roles: [
|
||||
"112767366235959296",
|
||||
"118924814567211009",
|
||||
"199995902742626304",
|
||||
"204427286542417920",
|
||||
"222168467627835392",
|
||||
"271173313575780353",
|
||||
"392141548932038658",
|
||||
"1040735082610167858",
|
||||
"372954403902193689",
|
||||
"1124134606514442300",
|
||||
"585531096071012409"
|
||||
],
|
||||
premium_since: "2022-04-20T21:11:14.016000+00:00",
|
||||
pending: false,
|
||||
nick: "Tap to add a nickname",
|
||||
mute: false,
|
||||
joined_at: "2022-04-20T20:16:02.828000+00:00",
|
||||
flags: 0,
|
||||
deaf: false,
|
||||
communication_disabled_until: null,
|
||||
avatar: "a_4ea72c7b058ad848c9d9d35479fac26e"
|
||||
},
|
||||
id: "1128084748338741392",
|
||||
flags: 0,
|
||||
embeds: [],
|
||||
edited_timestamp: null,
|
||||
content: "Image",
|
||||
components: [],
|
||||
channel_id: "112760669178241024",
|
||||
author: {
|
||||
username: "extremity",
|
||||
public_flags: 768,
|
||||
id: "114147806469554185",
|
||||
global_name: "Extremity",
|
||||
discriminator: "0",
|
||||
avatar_decoration: null,
|
||||
avatar: "6628aaf6b27219c36e2d3b5cfd6d0ee6"
|
||||
},
|
||||
attachments: [
|
||||
{
|
||||
width: 1200,
|
||||
url: "https://cdn.discordapp.com/attachments/112760669178241024/1128084747910918195/skull.webp",
|
||||
size: 74290,
|
||||
proxy_url: "https://media.discordapp.net/attachments/112760669178241024/1128084747910918195/skull.webp",
|
||||
id: "1128084747910918195",
|
||||
height: 628,
|
||||
filename: "skull.webp",
|
||||
content_type: "image/webp"
|
||||
}
|
||||
],
|
||||
guild_id: "112760669178241024"
|
||||
},
|
||||
reply_to_skull_webp_attachment_with_content: {
|
||||
type: 19,
|
||||
tts: false,
|
||||
timestamp: "2023-07-10T22:06:27.348000+00:00",
|
||||
referenced_message: {
|
||||
type: 0,
|
||||
tts: false,
|
||||
timestamp: "2023-07-10T22:06:02.805000+00:00",
|
||||
pinned: false,
|
||||
mentions: [],
|
||||
mention_roles: [],
|
||||
mention_everyone: false,
|
||||
id: "1128084748338741392",
|
||||
flags: 0,
|
||||
embeds: [],
|
||||
edited_timestamp: null,
|
||||
content: "Image",
|
||||
components: [],
|
||||
channel_id: "112760669178241024",
|
||||
author: {
|
||||
username: "extremity",
|
||||
public_flags: 768,
|
||||
id: "114147806469554185",
|
||||
global_name: "Extremity",
|
||||
discriminator: "0",
|
||||
avatar_decoration: null,
|
||||
avatar: "6628aaf6b27219c36e2d3b5cfd6d0ee6"
|
||||
},
|
||||
attachments: [
|
||||
{
|
||||
width: 1200,
|
||||
url: "https://cdn.discordapp.com/attachments/112760669178241024/1128084747910918195/skull.webp",
|
||||
size: 74290,
|
||||
proxy_url: "https://media.discordapp.net/attachments/112760669178241024/1128084747910918195/skull.webp",
|
||||
id: "1128084747910918195",
|
||||
height: 628,
|
||||
filename: "skull.webp",
|
||||
content_type: "image/webp"
|
||||
}
|
||||
]
|
||||
},
|
||||
pinned: false,
|
||||
nonce: "1128084845403045888",
|
||||
message_reference: {
|
||||
message_id: "1128084748338741392",
|
||||
guild_id: "112760669178241024",
|
||||
channel_id: "112760669178241024"
|
||||
},
|
||||
mentions: [
|
||||
{
|
||||
username: "extremity",
|
||||
public_flags: 768,
|
||||
member: {
|
||||
roles: [
|
||||
"112767366235959296",
|
||||
"118924814567211009",
|
||||
"199995902742626304",
|
||||
"204427286542417920",
|
||||
"222168467627835392",
|
||||
"271173313575780353",
|
||||
"392141548932038658",
|
||||
"1040735082610167858",
|
||||
"372954403902193689",
|
||||
"1124134606514442300",
|
||||
"585531096071012409"
|
||||
],
|
||||
premium_since: "2022-04-20T21:11:14.016000+00:00",
|
||||
pending: false,
|
||||
nick: "Tap to add a nickname",
|
||||
mute: false,
|
||||
joined_at: "2022-04-20T20:16:02.828000+00:00",
|
||||
flags: 0,
|
||||
deaf: false,
|
||||
communication_disabled_until: null,
|
||||
avatar: "a_4ea72c7b058ad848c9d9d35479fac26e"
|
||||
},
|
||||
id: "114147806469554185",
|
||||
global_name: "Extremity",
|
||||
discriminator: "0",
|
||||
avatar_decoration: null,
|
||||
avatar: "6628aaf6b27219c36e2d3b5cfd6d0ee6"
|
||||
}
|
||||
],
|
||||
mention_roles: [],
|
||||
mention_everyone: false,
|
||||
member: {
|
||||
roles: [
|
||||
"112767366235959296",
|
||||
"118924814567211009",
|
||||
"199995902742626304",
|
||||
"204427286542417920",
|
||||
"222168467627835392",
|
||||
"271173313575780353",
|
||||
"392141548932038658",
|
||||
"1040735082610167858",
|
||||
"372954403902193689",
|
||||
"1124134606514442300",
|
||||
"585531096071012409"
|
||||
],
|
||||
premium_since: "2022-04-20T21:11:14.016000+00:00",
|
||||
pending: false,
|
||||
nick: "Tap to add a nickname",
|
||||
mute: false,
|
||||
joined_at: "2022-04-20T20:16:02.828000+00:00",
|
||||
flags: 0,
|
||||
deaf: false,
|
||||
communication_disabled_until: null,
|
||||
avatar: "a_4ea72c7b058ad848c9d9d35479fac26e"
|
||||
},
|
||||
id: "1128084851279536279",
|
||||
flags: 0,
|
||||
embeds: [],
|
||||
edited_timestamp: null,
|
||||
content: "Reply",
|
||||
components: [],
|
||||
channel_id: "112760669178241024",
|
||||
author: {
|
||||
username: "extremity",
|
||||
public_flags: 768,
|
||||
id: "114147806469554185",
|
||||
global_name: "Extremity",
|
||||
discriminator: "0",
|
||||
avatar_decoration: null,
|
||||
avatar: "6628aaf6b27219c36e2d3b5cfd6d0ee6"
|
||||
},
|
||||
attachments: [
|
||||
{
|
||||
width: 2048,
|
||||
url: "https://cdn.discordapp.com/attachments/112760669178241024/1128084851023675515/RDT_20230704_0936184915846675925224905.jpg",
|
||||
size: 85906,
|
||||
proxy_url: "https://media.discordapp.net/attachments/112760669178241024/1128084851023675515/RDT_20230704_0936184915846675925224905.jpg",
|
||||
id: "1128084851023675515",
|
||||
height: 1536,
|
||||
filename: "RDT_20230704_0936184915846675925224905.jpg",
|
||||
content_type: "image/jpeg"
|
||||
}
|
||||
],
|
||||
guild_id: "112760669178241024"
|
||||
},
|
||||
simple_reply_to_matrix_user: {
|
||||
type: 19,
|
||||
tts: false,
|
||||
timestamp: "2023-07-11T00:19:04.358000+00:00",
|
||||
referenced_message: {
|
||||
webhook_id: "703458020193206272",
|
||||
type: 0,
|
||||
tts: false,
|
||||
timestamp: "2023-07-11T00:18:52.856000+00:00",
|
||||
pinned: false,
|
||||
mentions: [],
|
||||
mention_roles: [],
|
||||
mention_everyone: false,
|
||||
id: "1128118177155526666",
|
||||
flags: 0,
|
||||
embeds: [],
|
||||
edited_timestamp: null,
|
||||
content: "so can you reply to my webhook uwu",
|
||||
components: [],
|
||||
channel_id: "112760669178241024",
|
||||
author: {
|
||||
username: "cadence",
|
||||
id: "703458020193206272",
|
||||
discriminator: "0000",
|
||||
bot: true,
|
||||
avatar: "ea5413d310c85eb9edaa9db865e80155"
|
||||
},
|
||||
attachments: [],
|
||||
application_id: "684280192553844747"
|
||||
},
|
||||
pinned: false,
|
||||
nonce: "1128118222315323392",
|
||||
message_reference: {
|
||||
message_id: "1128118177155526666",
|
||||
guild_id: "112760669178241024",
|
||||
channel_id: "112760669178241024"
|
||||
},
|
||||
mentions: [],
|
||||
mention_roles: [],
|
||||
mention_everyone: false,
|
||||
member: {
|
||||
roles: [
|
||||
"112767366235959296", "118924814567211009",
|
||||
"204427286542417920", "199995902742626304",
|
||||
"222168467627835392", "238028326281805825",
|
||||
"259806643414499328", "265239342648131584",
|
||||
"271173313575780353", "287733611912757249",
|
||||
"225744901915148298", "305775031223320577",
|
||||
"318243902521868288", "348651574924541953",
|
||||
"349185088157777920", "378402925128712193",
|
||||
"392141548932038658", "393912152173576203",
|
||||
"482860581670486028", "495384759074160642",
|
||||
"638988388740890635", "373336013109461013",
|
||||
"530220455085473813", "454567553738473472",
|
||||
"790724320824655873", "1123518980456452097",
|
||||
"1040735082610167858", "695946570482450442",
|
||||
"1123460940935991296", "849737964090556488"
|
||||
],
|
||||
premium_since: null,
|
||||
pending: false,
|
||||
nick: null,
|
||||
mute: false,
|
||||
joined_at: "2015-11-11T09:55:40.321000+00:00",
|
||||
flags: 0,
|
||||
deaf: false,
|
||||
communication_disabled_until: null,
|
||||
avatar: null
|
||||
},
|
||||
id: "1128118225398407228",
|
||||
flags: 0,
|
||||
embeds: [],
|
||||
edited_timestamp: null,
|
||||
content: "Reply",
|
||||
components: [],
|
||||
channel_id: "112760669178241024",
|
||||
author: {
|
||||
username: "kumaccino",
|
||||
public_flags: 128,
|
||||
id: "113340068197859328",
|
||||
global_name: "kumaccino",
|
||||
discriminator: "0",
|
||||
avatar_decoration: null,
|
||||
avatar: "b48302623a12bc7c59a71328f72ccb39"
|
||||
},
|
||||
attachments: [],
|
||||
guild_id: "112760669178241024"
|
||||
},
|
||||
edit_of_reply_to_skull_webp_attachment_with_content: {
|
||||
type: 19,
|
||||
tts: false,
|
||||
timestamp: "2023-07-10T22:06:27.348000+00:00",
|
||||
referenced_message: {
|
||||
type: 0,
|
||||
tts: false,
|
||||
timestamp: "2023-07-10T22:06:02.805000+00:00",
|
||||
pinned: false,
|
||||
mentions: [],
|
||||
mention_roles: [],
|
||||
mention_everyone: false,
|
||||
id: "1128084748338741392",
|
||||
flags: 0,
|
||||
embeds: [],
|
||||
edited_timestamp: null,
|
||||
content: "Image",
|
||||
components: [],
|
||||
channel_id: "112760669178241024",
|
||||
author: {
|
||||
username: "extremity",
|
||||
public_flags: 768,
|
||||
id: "114147806469554185",
|
||||
global_name: "Extremity",
|
||||
discriminator: "0",
|
||||
avatar_decoration: null,
|
||||
avatar: "6628aaf6b27219c36e2d3b5cfd6d0ee6"
|
||||
},
|
||||
attachments: [
|
||||
{
|
||||
width: 1200,
|
||||
url: "https://cdn.discordapp.com/attachments/112760669178241024/1128084747910918195/skull.webp",
|
||||
size: 74290,
|
||||
proxy_url: "https://media.discordapp.net/attachments/112760669178241024/1128084747910918195/skull.webp",
|
||||
id: "1128084747910918195",
|
||||
height: 628,
|
||||
filename: "skull.webp",
|
||||
content_type: "image/webp"
|
||||
}
|
||||
]
|
||||
},
|
||||
pinned: false,
|
||||
message_reference: {
|
||||
message_id: "1128084748338741392",
|
||||
guild_id: "112760669178241024",
|
||||
channel_id: "112760669178241024"
|
||||
},
|
||||
mentions: [
|
||||
{
|
||||
username: "extremity",
|
||||
public_flags: 768,
|
||||
member: {
|
||||
roles: [
|
||||
"112767366235959296",
|
||||
"118924814567211009",
|
||||
"199995902742626304",
|
||||
"204427286542417920",
|
||||
"222168467627835392",
|
||||
"271173313575780353",
|
||||
"392141548932038658",
|
||||
"1040735082610167858",
|
||||
"372954403902193689",
|
||||
"1124134606514442300",
|
||||
"585531096071012409"
|
||||
],
|
||||
premium_since: "2022-04-20T21:11:14.016000+00:00",
|
||||
pending: false,
|
||||
nick: "Tap to add a nickname",
|
||||
mute: false,
|
||||
joined_at: "2022-04-20T20:16:02.828000+00:00",
|
||||
flags: 0,
|
||||
deaf: false,
|
||||
communication_disabled_until: null,
|
||||
avatar: "a_4ea72c7b058ad848c9d9d35479fac26e"
|
||||
},
|
||||
id: "114147806469554185",
|
||||
global_name: "Extremity",
|
||||
discriminator: "0",
|
||||
avatar_decoration: null,
|
||||
avatar: "6628aaf6b27219c36e2d3b5cfd6d0ee6"
|
||||
}
|
||||
],
|
||||
mention_roles: [],
|
||||
mention_everyone: false,
|
||||
member: {
|
||||
roles: [
|
||||
"112767366235959296",
|
||||
"118924814567211009",
|
||||
"199995902742626304",
|
||||
"204427286542417920",
|
||||
"222168467627835392",
|
||||
"271173313575780353",
|
||||
"392141548932038658",
|
||||
"1040735082610167858",
|
||||
"372954403902193689",
|
||||
"1124134606514442300",
|
||||
"585531096071012409"
|
||||
],
|
||||
premium_since: "2022-04-20T21:11:14.016000+00:00",
|
||||
pending: false,
|
||||
nick: "Tap to add a nickname",
|
||||
mute: false,
|
||||
joined_at: "2022-04-20T20:16:02.828000+00:00",
|
||||
flags: 0,
|
||||
deaf: false,
|
||||
communication_disabled_until: null,
|
||||
avatar: "a_4ea72c7b058ad848c9d9d35479fac26e"
|
||||
},
|
||||
id: "1128084851279536279",
|
||||
flags: 0,
|
||||
embeds: [],
|
||||
edited_timestamp: "2023-07-10T22:08:57.442417+00:00",
|
||||
content: "Edit",
|
||||
components: [],
|
||||
channel_id: "112760669178241024",
|
||||
author: {
|
||||
username: "extremity",
|
||||
public_flags: 768,
|
||||
id: "114147806469554185",
|
||||
global_name: "Extremity",
|
||||
discriminator: "0",
|
||||
avatar_decoration: null,
|
||||
avatar: "6628aaf6b27219c36e2d3b5cfd6d0ee6"
|
||||
},
|
||||
attachments: [
|
||||
{
|
||||
width: 2048,
|
||||
url: "https://cdn.discordapp.com/attachments/112760669178241024/1128084851023675515/RDT_20230704_0936184915846675925224905.jpg",
|
||||
size: 85906,
|
||||
proxy_url: "https://media.discordapp.net/attachments/112760669178241024/1128084851023675515/RDT_20230704_0936184915846675925224905.jpg",
|
||||
id: "1128084851023675515",
|
||||
height: 1536,
|
||||
filename: "RDT_20230704_0936184915846675925224905.jpg",
|
||||
content_type: "image/jpeg"
|
||||
}
|
||||
],
|
||||
guild_id: "112760669178241024"
|
||||
},
|
||||
sticker: {
|
||||
id: "1106366167788044450",
|
||||
type: 0,
|
||||
|
|
5
types.d.ts
vendored
5
types.d.ts
vendored
|
@ -81,6 +81,11 @@ namespace R {
|
|||
room_id: string
|
||||
}
|
||||
|
||||
export type RoomMember = {
|
||||
avatar_url: string
|
||||
display_name: string
|
||||
}
|
||||
|
||||
export type FileUploaded = {
|
||||
content_uri: string
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue