Handle d2m events with empty guild/user avatars #106
8 changed files with 74 additions and 6 deletions
|
|
@ -106,6 +106,7 @@ async function ensureSimJoined(pkMessage, roomID) {
|
||||||
* Generate profile data based on webhook displayname and configured avatar.
|
* Generate profile data based on webhook displayname and configured avatar.
|
||||||
* @param {Ty.PkMessage} pkMessage
|
* @param {Ty.PkMessage} pkMessage
|
||||||
* @param {Ty.WebhookAuthor} author
|
* @param {Ty.WebhookAuthor} author
|
||||||
|
* @returns {Promise<Ty.Event.M_Room_Member>}
|
||||||
*/
|
*/
|
||||||
async function memberToStateContent(pkMessage, author) {
|
async function memberToStateContent(pkMessage, author) {
|
||||||
// We prefer to use the member's avatar URL data since the image upload can be cached across channels,
|
// We prefer to use the member's avatar URL data since the image upload can be cached across channels,
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ async function ensureSimJoined(pluRalMessage, roomID) {
|
||||||
* Generate profile data based on webhook displayname and configured avatar.
|
* Generate profile data based on webhook displayname and configured avatar.
|
||||||
* @param {Ty.PluRalWebhookMessage} pluRalMessage
|
* @param {Ty.PluRalWebhookMessage} pluRalMessage
|
||||||
* @param {Ty.WebhookAuthor} author
|
* @param {Ty.WebhookAuthor} author
|
||||||
|
* @returns {Promise<Ty.Event.M_Room_Member>}
|
||||||
*/
|
*/
|
||||||
async function memberToStateContent(pluRalMessage, author) {
|
async function memberToStateContent(pluRalMessage, author) {
|
||||||
// We prefer to use the member's avatar URL data since the image upload can be cached across channels,
|
// We prefer to use the member's avatar URL data since the image upload can be cached across channels,
|
||||||
|
|
|
||||||
|
|
@ -102,8 +102,8 @@ async function userToGlobalProfile(user) {
|
||||||
globalProfile.displayname = user.username
|
globalProfile.displayname = user.username
|
||||||
if (user.global_name) globalProfile.displayname = user.global_name
|
if (user.global_name) globalProfile.displayname = user.global_name
|
||||||
|
|
||||||
if (user.avatar) {
|
const avatarPath = file.userAvatar(user) // the user avatar only
|
||||||
const avatarPath = file.userAvatar(user) // the user avatar only
|
if (avatarPath) {
|
||||||
globalProfile.avatar_url = await file.uploadDiscordFileToMxc(avatarPath)
|
globalProfile.avatar_url = await file.uploadDiscordFileToMxc(avatarPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -113,6 +113,8 @@ async function userToGlobalProfile(user) {
|
||||||
/**
|
/**
|
||||||
* @param {DiscordTypes.APIUser} user
|
* @param {DiscordTypes.APIUser} user
|
||||||
* @param {Omit<DiscordTypes.APIGuildMember, "user"> | undefined} member
|
* @param {Omit<DiscordTypes.APIGuildMember, "user"> | undefined} member
|
||||||
|
* @param {string} guildID
|
||||||
|
* @returns {Promise<Ty.Event.M_Room_Member>}
|
||||||
*/
|
*/
|
||||||
async function memberToStateContent(user, member, guildID) {
|
async function memberToStateContent(user, member, guildID) {
|
||||||
let displayname = user.username
|
let displayname = user.username
|
||||||
|
|
@ -132,9 +134,9 @@ async function memberToStateContent(user, member, guildID) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (member?.avatar || user.avatar) {
|
// const avatarPath = file.userAvatar(user) // the user avatar only
|
||||||
// const avatarPath = file.userAvatar(user) // the user avatar only
|
const avatarPath = file.memberAvatar(guildID, user, member) // the member avatar or the user avatar
|
||||||
const avatarPath = file.memberAvatar(guildID, user, member) // the member avatar or the user avatar
|
if (avatarPath) {
|
||||||
content["moe.cadence.ooye.member"].avatar = avatarPath
|
content["moe.cadence.ooye.member"].avatar = avatarPath
|
||||||
content.avatar_url = await file.uploadDiscordFileToMxc(avatarPath)
|
content.avatar_url = await file.uploadDiscordFileToMxc(avatarPath)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ async function ensureSimJoined(fakeUserID, author, roomID) {
|
||||||
/**
|
/**
|
||||||
* Generate profile data based on webhook displayname and configured avatar.
|
* Generate profile data based on webhook displayname and configured avatar.
|
||||||
* @param {Ty.WebhookAuthor} author
|
* @param {Ty.WebhookAuthor} author
|
||||||
|
* @returns {Promise<Ty.Event.M_Room_Member>}
|
||||||
*/
|
*/
|
||||||
async function authorToStateContent(author) {
|
async function authorToStateContent(author) {
|
||||||
const avatar = file.userAvatar(author)
|
const avatar = file.userAvatar(author)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
|
const DiscordTypes = require("discord-api-types/v10")
|
||||||
const passthrough = require("../passthrough")
|
const passthrough = require("../passthrough")
|
||||||
const {reg, writeRegistration} = require("./read-registration.js")
|
const {reg, writeRegistration} = require("./read-registration.js")
|
||||||
const Ty = require("../types")
|
const Ty = require("../types")
|
||||||
|
|
@ -138,14 +139,30 @@ async function _actuallyUploadDiscordFileToMxc(url) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DiscordTypes.APIGuild} guild
|
||||||
|
* @returns {string | null}
|
||||||
|
*/
|
||||||
function guildIcon(guild) {
|
function guildIcon(guild) {
|
||||||
|
if (!guild.icon) return null
|
||||||
return `/icons/${guild.id}/${guild.icon}.png?size=${IMAGE_SIZE}`
|
return `/icons/${guild.id}/${guild.icon}.png?size=${IMAGE_SIZE}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DiscordTypes.APIUser | Ty.WebhookAuthor} user
|
||||||
|
* @returns {string | null}
|
||||||
|
*/
|
||||||
function userAvatar(user) {
|
function userAvatar(user) {
|
||||||
|
if (!user.avatar) return null
|
||||||
return `/avatars/${user.id}/${user.avatar}.png?size=${IMAGE_SIZE}`
|
return `/avatars/${user.id}/${user.avatar}.png?size=${IMAGE_SIZE}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} guildID
|
||||||
|
* @param {DiscordTypes.APIUser} user
|
||||||
|
* @param {Omit<DiscordTypes.APIGuildMember, "user"> | undefined} member
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
function memberAvatar(guildID, user, member) {
|
function memberAvatar(guildID, user, member) {
|
||||||
if (!member?.avatar) return userAvatar(user)
|
if (!member?.avatar) return userAvatar(user)
|
||||||
return `/guilds/${guildID}/users/${user.id}/avatars/${member?.avatar}.png?size=${IMAGE_SIZE}`
|
return `/guilds/${guildID}/users/${user.id}/avatars/${member?.avatar}.png?size=${IMAGE_SIZE}`
|
||||||
|
|
|
||||||
|
|
@ -26,3 +26,33 @@ test("removeExpiryParams: works on media proxy and keeps quality", t => {
|
||||||
const result = file._removeExpiryParams(url)
|
const result = file._removeExpiryParams(url)
|
||||||
t.equal(result, "https://media.discordapp.net/attachments/1160894080998461480/1548665030898094240/855064e9-bdae-487a-a497-c662bd510487.png?format=webp")
|
t.equal(result, "https://media.discordapp.net/attachments/1160894080998461480/1548665030898094240/855064e9-bdae-487a-a497-c662bd510487.png?format=webp")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("guildIcon: returns icon path", t => {
|
||||||
|
t.equal(
|
||||||
|
// @ts-ignore
|
||||||
|
file.guildIcon({id: "112760669178241024", icon: "a_f83622e09ead74f0c5c527fe241f8f8c"}),
|
||||||
|
"/icons/112760669178241024/a_f83622e09ead74f0c5c527fe241f8f8c.png?size=1024"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("guildIcon: returns null if guild has no icon", t => {
|
||||||
|
t.equal(
|
||||||
|
// @ts-ignore
|
||||||
|
file.guildIcon({id: "112760669178241024", icon: null}),
|
||||||
|
null
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("userAvatar: returns avatar path", t => {
|
||||||
|
t.equal(
|
||||||
|
file.userAvatar({id: "113340068197859328", username: "kumaccino", avatar: "b48302623a12bc7c59a71328f72ccb39"}),
|
||||||
|
"/avatars/113340068197859328/b48302623a12bc7c59a71328f72ccb39.png?size=1024"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("userAvatar: returns null if user has no avatar", t => {
|
||||||
|
t.equal(
|
||||||
|
file.userAvatar({id: "113340068197859328", username: "kumaccino", avatar: null}),
|
||||||
|
null
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,11 @@ async function kstateUploadMxc(obj) {
|
||||||
for (const [k, v] of Object.entries(obj)) {
|
for (const [k, v] of Object.entries(obj)) {
|
||||||
if (v == null || typeof v !== "object") continue
|
if (v == null || typeof v !== "object") continue
|
||||||
|
|
||||||
if (v.$url) {
|
if ("$url" in v) {
|
||||||
|
if (!v.$url) {
|
||||||
|
delete obj[k]
|
||||||
|
continue
|
||||||
|
}
|
||||||
promises.push(
|
promises.push(
|
||||||
file.uploadDiscordFileToMxc(v.$url)
|
file.uploadDiscordFileToMxc(v.$url)
|
||||||
.then(mxc => obj[k] = mxc)
|
.then(mxc => obj[k] = mxc)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,18 @@ test("kstate strip: keeps true conditions while removing $if", t => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("kstateUploadMxc: removes keys where $url is null", async t => {
|
||||||
|
const input = {
|
||||||
|
"m.room.avatar/": {
|
||||||
|
url: {$url: null}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await kstateUploadMxc(input)
|
||||||
|
t.deepEqual(input, {
|
||||||
|
"m.room.avatar/": {}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
test("kstateUploadMxc: sets the mxc", async t => {
|
test("kstateUploadMxc: sets the mxc", async t => {
|
||||||
const input = {
|
const input = {
|
||||||
"m.room.avatar/": {
|
"m.room.avatar/": {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue