ImplicitRelationships: update logic (#3338)

This commit is contained in:
dolfies 2025-04-04 17:04:20 -04:00 committed by GitHub
parent 7246bface3
commit 7450ecd6f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 33 additions and 27 deletions

View file

@ -2,6 +2,6 @@
Shows your implicit relationships in the Friends tab.
Implicit relationships on Discord are people with whom you've frecently interacted and share a mutual server; even though Discord thinks you should be friends with them, you haven't added them as friends.
Implicit relationships on Discord are people with whom you've frecently interacted and don't have a relationship with. Even though Discord thinks you should be friends with them, you haven't added them as friends!
![](https://camo.githubusercontent.com/6927161ee0c933f7ef6d61f243cca3e6ea4c8db9d1becd8cbf73c45e1bd0d127/68747470733a2f2f692e646f6c66692e65732f7055447859464662674d2e706e673f6b65793d736e3950343936416c32444c7072)

View file

@ -20,7 +20,7 @@ import { definePluginSettings } from "@api/Settings";
import { Devs } from "@utils/constants";
import definePlugin, { OptionType } from "@utils/types";
import { findStoreLazy } from "@webpack";
import { ChannelStore, Constants, FluxDispatcher, GuildStore, RelationshipStore, SnowflakeUtils, UserStore } from "@webpack/common";
import { Constants, FluxDispatcher, GuildStore, RelationshipStore, RestAPI, SnowflakeUtils, UserStore } from "@webpack/common";
import { Settings } from "Vencord";
const UserAffinitiesStore = findStoreLazy("UserAffinitiesStore");
@ -121,55 +121,61 @@ export default definePlugin({
: comparator(row);
},
async refreshUserAffinities() {
try {
await RestAPI.get({ url: "/users/@me/affinities/users", retries: 3 }).then(({ body }) => {
FluxDispatcher.dispatch({
type: "LOAD_USER_AFFINITIES_SUCCESS",
affinities: body,
});
});
} catch (e) {
// Not a critical error if this fails for some reason
}
},
async fetchImplicitRelationships() {
// Implicit relationships are defined as users that you:
// 1. Have an affinity for
// 2. Do not have a relationship with // TODO: Check how this works with pending/blocked relationships
// 3. Have a mutual guild with
// 2. Do not have a relationship with
await this.refreshUserAffinities();
const userAffinities: Set<string> = UserAffinitiesStore.getUserAffinitiesUserIds();
const relationships = RelationshipStore.getRelationships();
const nonFriendAffinities = Array.from(userAffinities).filter(
id => !RelationshipStore.getRelationshipType(id)
);
nonFriendAffinities.forEach(id => {
relationships[id] = 5;
});
RelationshipStore.emitChange();
// I would love to just check user cache here (falling back to the gateway of course)
// However, users in user cache may just be there because they share a DM or group DM with you
// So there's no guarantee that a user being in user cache means they have a mutual with you
// To get around this, we request users we have DMs with, and ignore them below if we don't get them back
const dmUserIds = new Set(
Object.values(ChannelStore.getSortedPrivateChannels()).flatMap(c => c.recipients)
);
const toRequest = nonFriendAffinities.filter(id => !UserStore.getUser(id) || dmUserIds.has(id));
const toRequest = nonFriendAffinities.filter(id => !UserStore.getUser(id));
const allGuildIds = Object.keys(GuildStore.getGuilds());
const sentNonce = SnowflakeUtils.fromTimestamp(Date.now());
let count = allGuildIds.length * Math.ceil(toRequest.length / 100);
// OP 8 Request Guild Members allows 100 user IDs at a time
const ignore = new Set(toRequest);
const relationships = RelationshipStore.getRelationships();
// Note: As we are using OP 8 here, implicit relationships who we do not share a guild
// with will not be fetched; so, if they're not otherwise cached, they will not be shown
// This should not be a big deal as these should be rare
const callback = ({ chunks }) => {
for (const chunk of chunks) {
const { nonce, members } = chunk;
if (nonce !== sentNonce) return;
members.forEach(member => {
ignore.delete(member.user.id);
});
const chunkCount = chunks.filter(chunk => chunk.nonce === sentNonce).length;
if (chunkCount === 0) return;
nonFriendAffinities.map(id => UserStore.getUser(id)).filter(user => user && !ignore.has(user.id)).forEach(user => relationships[user.id] = 5);
RelationshipStore.emitChange();
if (--count === 0) {
// @ts-ignore
FluxDispatcher.unsubscribe("GUILD_MEMBERS_CHUNK_BATCH", callback);
}
count -= chunkCount;
RelationshipStore.emitChange();
if (count <= 0) {
FluxDispatcher.unsubscribe("GUILD_MEMBERS_CHUNK_BATCH", callback);
}
};
// @ts-ignore
FluxDispatcher.subscribe("GUILD_MEMBERS_CHUNK_BATCH", callback);
for (let i = 0; i < toRequest.length; i += 100) {
FluxDispatcher.dispatch({
type: "GUILD_MEMBERS_REQUEST",
guildIds: allGuildIds,
userIds: toRequest.slice(i, i + 100),
presences: true,
nonce: sentNonce,
});
}