Compare commits
No commits in common. "6803b156bc51cc8ffd3f089e1b437f252b285964" and "6a04f3f79814478348a399400253c53923e885ad" have entirely different histories.
6803b156bc
...
6a04f3f798
8 changed files with 10 additions and 281 deletions
|
@ -247,19 +247,8 @@ async function messageToEvent(message, guild, options = {}, di) {
|
||||||
: attachment.content_type?.startsWith("text/") ? "📝"
|
: attachment.content_type?.startsWith("text/") ? "📝"
|
||||||
: attachment.content_type?.startsWith("audio/") ? "🎶"
|
: attachment.content_type?.startsWith("audio/") ? "🎶"
|
||||||
: "📄"
|
: "📄"
|
||||||
// no native media spoilers in Element, so we'll post a link instead, forcing it to not preview using a blockquote
|
|
||||||
if (attachment.filename.startsWith("SPOILER_")) {
|
|
||||||
return {
|
|
||||||
$type: "m.room.message",
|
|
||||||
"m.mentions": mentions,
|
|
||||||
msgtype: "m.text",
|
|
||||||
body: `${emoji} Uploaded SPOILER file: ${attachment.url} (${pb(attachment.size)})`,
|
|
||||||
format: "org.matrix.custom.html",
|
|
||||||
formatted_body: `<blockquote>${emoji} Uploaded SPOILER file: <span data-mx-spoiler><a href="${attachment.url}">View</a></span> (${pb(attachment.size)})</blockquote>`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// for large files, always link them instead of uploading so I don't use up all the space in the content repo
|
// for large files, always link them instead of uploading so I don't use up all the space in the content repo
|
||||||
else if (attachment.size > reg.ooye.max_file_size) {
|
if (attachment.size > reg.ooye.max_file_size) {
|
||||||
return {
|
return {
|
||||||
$type: "m.room.message",
|
$type: "m.room.message",
|
||||||
"m.mentions": mentions,
|
"m.mentions": mentions,
|
||||||
|
|
|
@ -104,18 +104,6 @@ test("message2event: attachment with no content", async t => {
|
||||||
}])
|
}])
|
||||||
})
|
})
|
||||||
|
|
||||||
test("message2event: spoiler attachment", async t => {
|
|
||||||
const events = await messageToEvent(data.message.spoiler_attachment, data.guild.general, {})
|
|
||||||
t.deepEqual(events, [{
|
|
||||||
$type: "m.room.message",
|
|
||||||
"m.mentions": {},
|
|
||||||
msgtype: "m.text",
|
|
||||||
body: "📄 Uploaded SPOILER file: https://cdn.discordapp.com/attachments/1100319550446252084/1147465564307079258/SPOILER_69-GNDP-CADENCE.nfs.gci (74 KB)",
|
|
||||||
format: "org.matrix.custom.html",
|
|
||||||
formatted_body: "<blockquote>📄 Uploaded SPOILER file: <span data-mx-spoiler><a href=\"https://cdn.discordapp.com/attachments/1100319550446252084/1147465564307079258/SPOILER_69-GNDP-CADENCE.nfs.gci\">View</a></span> (74 KB)</blockquote>"
|
|
||||||
}])
|
|
||||||
})
|
|
||||||
|
|
||||||
test("message2event: stickers", async t => {
|
test("message2event: stickers", async t => {
|
||||||
const events = await messageToEvent(data.message.sticker, data.guild.general, {})
|
const events = await messageToEvent(data.message.sticker, data.guild.general, {})
|
||||||
t.deepEqual(events, [{
|
t.deepEqual(events, [{
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
const assert = require("assert").strict
|
const assert = require("assert").strict
|
||||||
const Ty = require("../../types")
|
|
||||||
const DiscordTypes = require("discord-api-types/v10")
|
const DiscordTypes = require("discord-api-types/v10")
|
||||||
const passthrough = require("../../passthrough")
|
const passthrough = require("../../passthrough")
|
||||||
const {sync, discord, db} = passthrough
|
const {sync, discord, db} = passthrough
|
||||||
|
@ -13,30 +12,9 @@ const eventToMessage = sync.require("../converters/event-to-message")
|
||||||
/** @type {import("../../matrix/api")}) */
|
/** @type {import("../../matrix/api")}) */
|
||||||
const api = sync.require("../../matrix/api")
|
const api = sync.require("../../matrix/api")
|
||||||
|
|
||||||
/**
|
/** @param {import("../../types").Event.Outer<any>} event */
|
||||||
* @param {DiscordTypes.RESTPostAPIWebhookWithTokenJSONBody & {pendingFiles?: {name: string, url: string}[]}} message
|
|
||||||
* @returns {Promise<DiscordTypes.RESTPostAPIWebhookWithTokenJSONBody & {files?: {name: string, file: Buffer}[]}>}
|
|
||||||
*/
|
|
||||||
async function resolvePendingFiles(message) {
|
|
||||||
if (!message.pendingFiles) return message
|
|
||||||
const files = await Promise.all(message.pendingFiles.map(async p => {
|
|
||||||
const file = await fetch(p.url).then(res => res.arrayBuffer()).then(x => Buffer.from(x))
|
|
||||||
return {
|
|
||||||
name: p.name,
|
|
||||||
file
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
const newMessage = {
|
|
||||||
...message,
|
|
||||||
files
|
|
||||||
}
|
|
||||||
delete newMessage.pendingFiles
|
|
||||||
return newMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @param {Ty.Event.M_Outer_M_Room_Message | Ty.Event.M_Outer_M_Room_Message_File | Ty.Event.M_Outer_M_Sticker} event */
|
|
||||||
async function sendEvent(event) {
|
async function sendEvent(event) {
|
||||||
// TODO: we just assume the bridge has already been created, is that really ok?
|
// TODO: we just assume the bridge has already been created
|
||||||
const row = db.prepare("SELECT channel_id, thread_parent FROM channel_room WHERE room_id = ?").get(event.room_id)
|
const row = db.prepare("SELECT channel_id, thread_parent FROM channel_room WHERE room_id = ?").get(event.room_id)
|
||||||
let channelID = row.channel_id
|
let channelID = row.channel_id
|
||||||
let threadID = undefined
|
let threadID = undefined
|
||||||
|
@ -51,15 +29,7 @@ async function sendEvent(event) {
|
||||||
|
|
||||||
// no need to sync the matrix member to the other side. but if I did need to, this is where I'd do it
|
// no need to sync the matrix member to the other side. but if I did need to, this is where I'd do it
|
||||||
|
|
||||||
let {messagesToEdit, messagesToSend, messagesToDelete} = await eventToMessage.eventToMessage(event, guild, {api})
|
const {messagesToEdit, messagesToSend, messagesToDelete} = await eventToMessage.eventToMessage(event, guild, {api})
|
||||||
|
|
||||||
messagesToEdit = await Promise.all(messagesToEdit.map(async e => {
|
|
||||||
e.message = await resolvePendingFiles(e.message)
|
|
||||||
return e
|
|
||||||
}))
|
|
||||||
messagesToSend = await Promise.all(messagesToSend.map(message => {
|
|
||||||
return resolvePendingFiles(message)
|
|
||||||
}))
|
|
||||||
|
|
||||||
let eventPart = 0 // 0 is primary, 1 is supporting
|
let eventPart = 0 // 0 is primary, 1 is supporting
|
||||||
|
|
||||||
|
@ -78,7 +48,7 @@ async function sendEvent(event) {
|
||||||
for (const message of messagesToSend) {
|
for (const message of messagesToSend) {
|
||||||
const messageResponse = await channelWebhook.sendMessageWithWebhook(channelID, message, threadID)
|
const messageResponse = await channelWebhook.sendMessageWithWebhook(channelID, message, threadID)
|
||||||
db.prepare("REPLACE INTO message_channel (message_id, channel_id) VALUES (?, ?)").run(messageResponse.id, channelID)
|
db.prepare("REPLACE INTO message_channel (message_id, channel_id) VALUES (?, ?)").run(messageResponse.id, channelID)
|
||||||
db.prepare("INSERT INTO event_message (event_id, event_type, event_subtype, message_id, part, source) VALUES (?, ?, ?, ?, ?, 0)").run(event.event_id, event.type, event.content["msgtype"] || null, messageResponse.id, eventPart) // source 0 = matrix
|
db.prepare("INSERT INTO event_message (event_id, event_type, event_subtype, message_id, part, source) VALUES (?, ?, ?, ?, ?, 0)").run(event.event_id, event.type, event.content.msgtype || null, messageResponse.id, eventPart) // source 0 = matrix
|
||||||
|
|
||||||
eventPart = 1
|
eventPart = 1
|
||||||
messageResponses.push(messageResponse)
|
messageResponses.push(messageResponse)
|
||||||
|
|
|
@ -4,7 +4,6 @@ const Ty = require("../../types")
|
||||||
const DiscordTypes = require("discord-api-types/v10")
|
const DiscordTypes = require("discord-api-types/v10")
|
||||||
const chunk = require("chunk-text")
|
const chunk = require("chunk-text")
|
||||||
const TurndownService = require("turndown")
|
const TurndownService = require("turndown")
|
||||||
const assert = require("assert").strict
|
|
||||||
|
|
||||||
const passthrough = require("../../passthrough")
|
const passthrough = require("../../passthrough")
|
||||||
const { sync, db, discord } = passthrough
|
const { sync, db, discord } = passthrough
|
||||||
|
@ -125,7 +124,7 @@ async function getMemberFromCacheOrHomeserver(roomID, mxid, api) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Ty.Event.M_Outer_M_Room_Message | Ty.Event.M_Outer_M_Room_Message_File | Ty.Event.M_Outer_M_Sticker} event
|
* @param {Ty.Event.Outer<Ty.Event.M_Room_Message>} event
|
||||||
* @param {import("discord-api-types/v10").APIGuild} guild
|
* @param {import("discord-api-types/v10").APIGuild} guild
|
||||||
* @param {{api: import("../../matrix/api")}} di simple-as-nails dependency injection for the matrix API
|
* @param {{api: import("../../matrix/api")}} di simple-as-nails dependency injection for the matrix API
|
||||||
*/
|
*/
|
||||||
|
@ -144,15 +143,12 @@ async function eventToMessage(event, guild, di) {
|
||||||
// Try to extract an accurate display name and avatar URL from the member event
|
// Try to extract an accurate display name and avatar URL from the member event
|
||||||
const member = await getMemberFromCacheOrHomeserver(event.room_id, event.sender, di?.api)
|
const member = await getMemberFromCacheOrHomeserver(event.room_id, event.sender, di?.api)
|
||||||
if (member.displayname) displayName = member.displayname
|
if (member.displayname) displayName = member.displayname
|
||||||
if (member.avatar_url) avatarURL = utils.getPublicUrlForMxc(member.avatar_url) || undefined
|
if (member.avatar_url) avatarURL = utils.getPublicUrlForMxc(member.avatar_url)
|
||||||
|
|
||||||
let content = event.content.body // ultimate fallback
|
let content = event.content.body // ultimate fallback
|
||||||
const attachments = []
|
|
||||||
/** @type {{name: string, url: string}[]} */
|
|
||||||
const pendingFiles = []
|
|
||||||
|
|
||||||
// Convert content depending on what the message is
|
// Convert content depending on what the message is
|
||||||
if (event.type === "m.room.message" && (event.content.msgtype === "m.text" || event.content.msgtype === "m.emote")) {
|
if (event.content.msgtype === "m.text" || event.content.msgtype === "m.emote") {
|
||||||
// Handling edits. If the edit was an edit of a reply, edits do not include the reply reference, so we need to fetch up to 2 more events.
|
// Handling edits. If the edit was an edit of a reply, edits do not include the reply reference, so we need to fetch up to 2 more events.
|
||||||
// this event ---is an edit of--> original event ---is a reply to--> past event
|
// this event ---is an edit of--> original event ---is a reply to--> past event
|
||||||
await (async () => {
|
await (async () => {
|
||||||
|
@ -265,7 +261,7 @@ async function eventToMessage(event, guild, di) {
|
||||||
// @ts-ignore bad type from turndown
|
// @ts-ignore bad type from turndown
|
||||||
content = turndownService.turndown(input)
|
content = turndownService.turndown(input)
|
||||||
|
|
||||||
// It's designed for commonmark, we need to replace the space-space-newline with just newline
|
// It's optimised for commonmark, we need to replace the space-space-newline with just newline
|
||||||
content = content.replace(/ \n/g, "\n")
|
content = content.replace(/ \n/g, "\n")
|
||||||
} else {
|
} else {
|
||||||
// Looks like we're using the plaintext body!
|
// Looks like we're using the plaintext body!
|
||||||
|
@ -278,23 +274,6 @@ async function eventToMessage(event, guild, di) {
|
||||||
// Markdown needs to be escaped
|
// Markdown needs to be escaped
|
||||||
content = content.replace(/([*_~`#])/g, `\\$1`)
|
content = content.replace(/([*_~`#])/g, `\\$1`)
|
||||||
}
|
}
|
||||||
} else if (event.type === "m.room.message" && (event.content.msgtype === "m.file" || event.content.msgtype === "m.video" || event.content.msgtype === "m.audio" || event.content.msgtype === "m.image")) {
|
|
||||||
content = ""
|
|
||||||
const filename = event.content.body
|
|
||||||
const url = utils.getPublicUrlForMxc(event.content.url)
|
|
||||||
assert(url)
|
|
||||||
attachments.push({id: "0", filename})
|
|
||||||
pendingFiles.push({name: filename, url})
|
|
||||||
} else if (event.type === "m.sticker") {
|
|
||||||
content = ""
|
|
||||||
let filename = event.content.body
|
|
||||||
if (event.type === "m.sticker" && event.content.info.mimetype.includes("/")) {
|
|
||||||
filename += "." + event.content.info.mimetype.split("/")[1]
|
|
||||||
}
|
|
||||||
const url = utils.getPublicUrlForMxc(event.content.url)
|
|
||||||
assert(url)
|
|
||||||
attachments.push({id: "0", filename})
|
|
||||||
pendingFiles.push({name: filename, url})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
content = replyLine + content
|
content = replyLine + content
|
||||||
|
@ -307,19 +286,6 @@ async function eventToMessage(event, guild, di) {
|
||||||
avatar_url: avatarURL
|
avatar_url: avatarURL
|
||||||
})))
|
})))
|
||||||
|
|
||||||
if (attachments.length) {
|
|
||||||
// If content is empty (should be the case when uploading a file) then chunk-text will create 0 messages.
|
|
||||||
// There needs to be a message to add attachments to.
|
|
||||||
if (!messages.length) messages.push({
|
|
||||||
content,
|
|
||||||
username: displayName,
|
|
||||||
avatar_url: avatarURL
|
|
||||||
})
|
|
||||||
messages[0].attachments = attachments
|
|
||||||
// @ts-ignore these will be converted to real files when the message is about to be sent
|
|
||||||
messages[0].pendingFiles = pendingFiles
|
|
||||||
}
|
|
||||||
|
|
||||||
const messagesToEdit = []
|
const messagesToEdit = []
|
||||||
const messagesToSend = []
|
const messagesToSend = []
|
||||||
for (let i = 0; i < messages.length; i++) {
|
for (let i = 0; i < messages.length; i++) {
|
||||||
|
|
|
@ -1110,107 +1110,3 @@ test("event2message: skips caching the member if the member does not exist, some
|
||||||
t.deepEqual(db.prepare("SELECT avatar_url, displayname, mxid FROM member_cache WHERE room_id = '!not_real:cadence.moe'").all(), [])
|
t.deepEqual(db.prepare("SELECT avatar_url, displayname, mxid FROM member_cache WHERE room_id = '!not_real:cadence.moe'").all(), [])
|
||||||
t.equal(called, 1, "getStateEvent should be called once")
|
t.equal(called, 1, "getStateEvent should be called once")
|
||||||
})
|
})
|
||||||
|
|
||||||
test("event2message: text attachments work", async t => {
|
|
||||||
t.deepEqual(
|
|
||||||
await eventToMessage({
|
|
||||||
type: "m.room.message",
|
|
||||||
content: {
|
|
||||||
body: "chiki-powerups.txt",
|
|
||||||
info: {
|
|
||||||
size: 971,
|
|
||||||
mimetype: "text/plain"
|
|
||||||
},
|
|
||||||
msgtype: "m.file",
|
|
||||||
url: "mxc://cadence.moe/zyThGlYQxvlvBVbVgKDDbiHH"
|
|
||||||
},
|
|
||||||
sender: "@cadence:cadence.moe",
|
|
||||||
event_id: "$c2WVyP6KcfAqh5imOa8e0xzt2C8JTR-cWbEd3GargEQ",
|
|
||||||
room_id: "!PnyBKvUBOhjuCucEfk:cadence.moe"
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
messagesToDelete: [],
|
|
||||||
messagesToEdit: [],
|
|
||||||
messagesToSend: [{
|
|
||||||
username: "cadence [they]",
|
|
||||||
content: "",
|
|
||||||
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
|
|
||||||
attachments: [{id: "0", filename: "chiki-powerups.txt"}],
|
|
||||||
pendingFiles: [{name: "chiki-powerups.txt", url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/zyThGlYQxvlvBVbVgKDDbiHH"}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("event2message: image attachments work", async t => {
|
|
||||||
t.deepEqual(
|
|
||||||
await eventToMessage({
|
|
||||||
type: "m.room.message",
|
|
||||||
sender: "@cadence:cadence.moe",
|
|
||||||
content: {
|
|
||||||
body: "cool cat.png",
|
|
||||||
info: {
|
|
||||||
size: 43170,
|
|
||||||
mimetype: "image/png",
|
|
||||||
w: 480,
|
|
||||||
h: 480,
|
|
||||||
"xyz.amorgan.blurhash": "URTHsVaTpdj2eKZgkkkXp{pHl7feo@lSl9Z$"
|
|
||||||
},
|
|
||||||
msgtype: "m.image",
|
|
||||||
url: "mxc://cadence.moe/IvxVJFLEuksCNnbojdSIeEvn"
|
|
||||||
},
|
|
||||||
event_id: "$CXQy3Wmg1A-gL_xAesC1HQcQTEXwICLdSwwUx55FBTI",
|
|
||||||
room_id: "!PnyBKvUBOhjuCucEfk:cadence.moe"
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
messagesToDelete: [],
|
|
||||||
messagesToEdit: [],
|
|
||||||
messagesToSend: [{
|
|
||||||
username: "cadence [they]",
|
|
||||||
content: "",
|
|
||||||
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
|
|
||||||
attachments: [{id: "0", filename: "cool cat.png"}],
|
|
||||||
pendingFiles: [{name: "cool cat.png", url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/IvxVJFLEuksCNnbojdSIeEvn"}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
test("event2message: stickers work", async t => {
|
|
||||||
t.deepEqual(
|
|
||||||
await eventToMessage({
|
|
||||||
type: "m.sticker",
|
|
||||||
sender: "@cadence:cadence.moe",
|
|
||||||
content: {
|
|
||||||
body: "get_real2",
|
|
||||||
url: "mxc://cadence.moe/NyMXQFAAdniImbHzsygScbmN",
|
|
||||||
info: {
|
|
||||||
w: 320,
|
|
||||||
h: 298,
|
|
||||||
mimetype: "image/gif",
|
|
||||||
size: 331394,
|
|
||||||
thumbnail_info: {
|
|
||||||
w: 320,
|
|
||||||
h: 298,
|
|
||||||
mimetype: "image/gif",
|
|
||||||
size: 331394
|
|
||||||
},
|
|
||||||
thumbnail_url: "mxc://cadence.moe/NyMXQFAAdniImbHzsygScbmN"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
event_id: "$PdI-KjdQ8Z_Tb4x9_7wKRPZCsrrXym4BXtbAPekypuM",
|
|
||||||
room_id: "!PnyBKvUBOhjuCucEfk:cadence.moe"
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
messagesToDelete: [],
|
|
||||||
messagesToEdit: [],
|
|
||||||
messagesToSend: [{
|
|
||||||
username: "cadence [they]",
|
|
||||||
content: "",
|
|
||||||
avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU",
|
|
||||||
attachments: [{id: "0", filename: "get_real2.gif"}],
|
|
||||||
pendingFiles: [{name: "get_real2.gif", url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/NyMXQFAAdniImbHzsygScbmN"}]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
|
@ -54,16 +54,7 @@ function guard(type, fn) {
|
||||||
|
|
||||||
sync.addTemporaryListener(as, "type:m.room.message", guard("m.room.message",
|
sync.addTemporaryListener(as, "type:m.room.message", guard("m.room.message",
|
||||||
/**
|
/**
|
||||||
* @param {Ty.Event.M_Outer_M_Room_Message | Ty.Event.M_Outer_M_Room_Message_File} event it is a m.room.message because that's what this listener is filtering for
|
* @param {Ty.Event.Outer<Ty.Event.M_Room_Message>} event it is a m.room.message because that's what this listener is filtering for
|
||||||
*/
|
|
||||||
async event => {
|
|
||||||
if (utils.eventSenderIsFromDiscord(event.sender)) return
|
|
||||||
const messageResponses = await sendEvent.sendEvent(event)
|
|
||||||
}))
|
|
||||||
|
|
||||||
sync.addTemporaryListener(as, "type:m.sticker", guard("m.sticker",
|
|
||||||
/**
|
|
||||||
* @param {Ty.Event.M_Outer_M_Sticker} event it is a m.sticker because that's what this listener is filtering for
|
|
||||||
*/
|
*/
|
||||||
async event => {
|
async event => {
|
||||||
if (utils.eventSenderIsFromDiscord(event.sender)) return
|
if (utils.eventSenderIsFromDiscord(event.sender)) return
|
||||||
|
|
38
test/data.js
38
test/data.js
|
@ -531,44 +531,6 @@ module.exports = {
|
||||||
flags: 0,
|
flags: 0,
|
||||||
components: []
|
components: []
|
||||||
},
|
},
|
||||||
spoiler_attachment: {
|
|
||||||
type: 0,
|
|
||||||
tts: false,
|
|
||||||
timestamp: '2023-09-02T09:38:29.480000+00:00',
|
|
||||||
referenced_message: null,
|
|
||||||
pinned: false,
|
|
||||||
nonce: '1147465562901708800',
|
|
||||||
mentions: [],
|
|
||||||
mention_roles: [],
|
|
||||||
mention_everyone: false,
|
|
||||||
id: '1147465564600676383',
|
|
||||||
flags: 0,
|
|
||||||
embeds: [],
|
|
||||||
edited_timestamp: null,
|
|
||||||
content: '',
|
|
||||||
components: [],
|
|
||||||
channel_id: '1100319550446252084',
|
|
||||||
author: {
|
|
||||||
username: 'cadence.worm',
|
|
||||||
public_flags: 0,
|
|
||||||
id: '772659086046658620',
|
|
||||||
global_name: 'cadence',
|
|
||||||
discriminator: '0',
|
|
||||||
avatar_decoration_data: null,
|
|
||||||
avatar: '4b5c4b28051144e4c111f0113a0f1cf1'
|
|
||||||
},
|
|
||||||
attachments: [
|
|
||||||
{
|
|
||||||
url: 'https://cdn.discordapp.com/attachments/1100319550446252084/1147465564307079258/SPOILER_69-GNDP-CADENCE.nfs.gci',
|
|
||||||
size: 73792,
|
|
||||||
proxy_url: 'https://media.discordapp.net/attachments/1100319550446252084/1147465564307079258/SPOILER_69-GNDP-CADENCE.nfs.gci',
|
|
||||||
id: '1147465564307079258',
|
|
||||||
flags: 8,
|
|
||||||
filename: 'SPOILER_69-GNDP-CADENCE.nfs.gci'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
guild_id: '1100319549670301727'
|
|
||||||
},
|
|
||||||
skull_webp_attachment_with_content: {
|
skull_webp_attachment_with_content: {
|
||||||
type: 0,
|
type: 0,
|
||||||
tts: false,
|
tts: false,
|
||||||
|
|
33
types.d.ts
vendored
33
types.d.ts
vendored
|
@ -80,39 +80,6 @@ export namespace Event {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type M_Outer_M_Room_Message = Outer<M_Room_Message> & {type: "m.room.message"}
|
|
||||||
|
|
||||||
export type M_Room_Message_File = {
|
|
||||||
msgtype: "m.file" | "m.image" | "m.video" | "m.audio"
|
|
||||||
body: string
|
|
||||||
url: string
|
|
||||||
info?: any
|
|
||||||
"m.relates_to"?: {
|
|
||||||
"m.in_reply_to": {
|
|
||||||
event_id: string
|
|
||||||
}
|
|
||||||
rel_type?: "m.replace"
|
|
||||||
event_id?: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type M_Outer_M_Room_Message_File = Outer<M_Room_Message_File> & {type: "m.room.message"}
|
|
||||||
|
|
||||||
export type M_Sticker = {
|
|
||||||
body: string
|
|
||||||
url: string
|
|
||||||
info: {
|
|
||||||
mimetype: string
|
|
||||||
w?: number
|
|
||||||
h?: number
|
|
||||||
size?: number
|
|
||||||
thumbnail_info?: any
|
|
||||||
thumbnail_url?: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type M_Outer_M_Sticker = Outer<M_Sticker> & {type: "m.sticker"}
|
|
||||||
|
|
||||||
export type M_Room_Member = {
|
export type M_Room_Member = {
|
||||||
membership: string
|
membership: string
|
||||||
displayname?: string
|
displayname?: string
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue