Don't display full host in mentions if user is local

This commit is contained in:
Jesse Wierzbinski 2024-04-11 15:52:09 -10:00
parent a1b251dfdf
commit 2b02cfa00a
No known key found for this signature in database
2 changed files with 107 additions and 46 deletions

View file

@ -44,6 +44,7 @@ import {
sql, sql,
isNotNull, isNotNull,
inArray, inArray,
isNull,
} from "drizzle-orm"; } from "drizzle-orm";
import { import {
status, status,
@ -731,7 +732,21 @@ export const parseTextMentions = async (
if (mentionedPeople.length === 0) return []; if (mentionedPeople.length === 0) return [];
const found = await db const remoteUsers = mentionedPeople.filter(
(person) =>
person.split("@").length === 3 &&
person.split("@")[2] !== new URL(config.http.base_url).host,
);
const localUsers = mentionedPeople.filter(
(person) =>
person.split("@").length <= 2 ||
person.split("@")[2] === new URL(config.http.base_url).host,
);
const foundRemote =
remoteUsers.length > 0
? await db
.select({ .select({
id: user.id, id: user.id,
username: user.username, username: user.username,
@ -741,36 +756,57 @@ export const parseTextMentions = async (
.innerJoin(instance, eq(user.instanceId, instance.id)) .innerJoin(instance, eq(user.instanceId, instance.id))
.where( .where(
or( or(
...mentionedPeople.map((person) => ...remoteUsers.map((person) =>
and( and(
eq(user.username, person.split("@")[1]), eq(user.username, person.split("@")[1]),
person.split("@").length > 2 eq(instance.baseUrl, person.split("@")[2]),
? eq(instance.baseUrl, person.split("@")[2])
: undefined,
), ),
), ),
), ),
); )
: [];
const notFound = mentionedPeople.filter( const foundLocal =
localUsers.length > 0
? await db
.select({
id: user.id,
})
.from(user)
.where(
and(
inArray(
user.username,
localUsers.map((person) => person.split("@")[1]),
),
isNull(user.instanceId),
),
)
: [];
const combinedFound = [
...foundLocal.map((user) => user.id),
...foundRemote.map((user) => user.id),
];
const finalList =
combinedFound.length > 0
? await findManyUsers({
where: (user, { inArray }) => inArray(user.id, combinedFound),
})
: [];
const notFoundRemote = remoteUsers.filter(
(person) => (person) =>
!found.find( !foundRemote.find(
(user) => (user) =>
user.username === person.split("@")[1] && user.username === person.split("@")[1] &&
user.baseUrl === person.split("@")[2], user.baseUrl === person.split("@")[2],
), ),
); );
const finalList = await findManyUsers({
where: (user, { inArray }) =>
inArray(
user.username,
found.map((f) => f.username),
),
});
// Attempt to resolve mentions that were not found // Attempt to resolve mentions that were not found
for (const person of notFound) { for (const person of notFoundRemote) {
if (person.split("@").length < 2) continue; if (person.split("@").length < 2) continue;
const user = await resolveWebFinger( const user = await resolveWebFinger(
@ -802,7 +838,15 @@ export const replaceTextMentions = async (
); );
} else { } else {
finalText = finalText.replace( finalText = finalText.replace(
`@${mention.username}`, // Only replace @username if it doesn't have another @ right after
new RegExp(`@${mention.username}(?![a-zA-Z0-9_@])`, "g"),
`<a class="u-url mention" rel="nofollow noopener noreferrer" target="_blank" href="${getUserUri(
mention,
)}">@${mention.username}</a>`,
);
finalText = finalText.replace(
`@${mention.username}@${new URL(config.http.base_url).host}`,
`<a class="u-url mention" rel="nofollow noopener noreferrer" target="_blank" href="${getUserUri( `<a class="u-url mention" rel="nofollow noopener noreferrer" target="_blank" href="${getUserUri(
mention, mention,
)}">@${mention.username}</a>`, )}">@${mention.username}</a>`,
@ -836,8 +880,8 @@ export const createNewStatus = async (
if (content["text/html"]) { if (content["text/html"]) {
htmlContent = content["text/html"].content; htmlContent = content["text/html"].content;
} else if (content["text/markdown"]) { } else if (content["text/markdown"]) {
htmlContent = linkifyHtml( htmlContent = await sanitizeHtml(
await sanitizeHtml(await parse(content["text/markdown"].content)), await parse(content["text/markdown"].content),
); );
} else if (content["text/plain"]) { } else if (content["text/plain"]) {
// Split by newline and add <p> tags // Split by newline and add <p> tags
@ -845,7 +889,14 @@ export const createNewStatus = async (
.split("\n") .split("\n")
.map((line) => `<p>${line}</p>`) .map((line) => `<p>${line}</p>`)
.join("\n"); .join("\n");
} else {
htmlContent = "";
}
// Replace mentions text
htmlContent = await replaceTextMentions(htmlContent, mentions ?? []);
// Linkify
htmlContent = linkifyHtml(htmlContent, { htmlContent = linkifyHtml(htmlContent, {
defaultProtocol: "https", defaultProtocol: "https",
validate: { validate: {
@ -854,12 +905,6 @@ export const createNewStatus = async (
target: "_blank", target: "_blank",
rel: "nofollow noopener noreferrer", rel: "nofollow noopener noreferrer",
}); });
} else {
htmlContent = "";
}
// Replace mentions text
htmlContent = await replaceTextMentions(htmlContent, mentions ?? []);
// Parse emojis and fuse with existing emojis // Parse emojis and fuse with existing emojis
let foundEmojis = emojis; let foundEmojis = emojis;
@ -1142,6 +1187,23 @@ export const statusToAPI = async (
})) }))
: false; : false;
// Convert mentions of local users from @username@host to @username
const mentionedLocalUsers = statusToConvert.mentions.filter(
(mention) => mention.instanceId === null,
);
let replacedContent = statusToConvert.content;
for (const mention of mentionedLocalUsers) {
replacedContent = replacedContent.replace(
new RegExp(
`@${mention.username}@${new URL(config.http.base_url).host}`,
"g",
),
`@${mention.username}`,
);
}
return { return {
id: statusToConvert.id, id: statusToConvert.id,
in_reply_to_id: statusToConvert.inReplyToPostId || null, in_reply_to_id: statusToConvert.inReplyToPostId || null,
@ -1152,7 +1214,7 @@ export const statusToAPI = async (
? applicationToAPI(statusToConvert.application) ? applicationToAPI(statusToConvert.application)
: null, : null,
card: null, card: null,
content: statusToConvert.content, content: replacedContent,
emojis: statusToConvert.emojis.map((emoji) => emojiToAPI(emoji)), emojis: statusToConvert.emojis.map((emoji) => emojiToAPI(emoji)),
favourited: !!(statusToConvert.likes ?? []).find( favourited: !!(statusToConvert.likes ?? []).find(
(like) => like.likerId === userFetching?.id, (like) => like.likerId === userFetching?.id,

View file

@ -709,7 +709,6 @@ export const userToAPI = (
userToConvert: UserWithRelations, userToConvert: UserWithRelations,
isOwnAccount = false, isOwnAccount = false,
): APIAccount => { ): APIAccount => {
console.log(userToConvert);
return { return {
id: userToConvert.id, id: userToConvert.id,
username: userToConvert.username, username: userToConvert.username,