Files
dc-nogi/bot/discovery.py
Minz c8359ef4bb Add DM support, friend identification, and target pruning
React in 1:1 DMs alongside servers/groups, surface the resolved friend
username at startup and in the stats panel, verify reactions actually
stick after adding them (with jump links for manual spot-checking),
and prune stale targets from stats on each run so only the currently
mutual set is shown.
2026-08-01 18:03:02 +02:00

70 lines
2.5 KiB
Python

import logging
from dataclasses import dataclass
from typing import List, Optional
import discord
log = logging.getLogger(__name__)
@dataclass
class Target:
target_id: int
target_type: str # "guild" | "group_dm" | "dm"
name: str
async def resolve_friend(client: discord.Client, friend_id: int) -> discord.User:
"""Fetch the target user object so we can display who the script is
actually reacting to (helps catch a wrong/typo'd friend_id early)."""
user = client.get_user(friend_id)
if user is None:
user = await client.fetch_user(friend_id)
return user
async def discover_targets(
client: discord.Client, friend: discord.User, manual_guild_ids: Optional[List[int]] = None
) -> List[Target]:
friend_id = friend.id
targets: List[Target] = []
guild_ids_seen = set()
try:
profile = await friend.profile(with_mutual_guilds=True, with_mutual_friends=False, with_mutual_friends_count=False)
for mutual in (profile.mutual_guilds or []):
guild = client.get_guild(mutual.id)
name = guild.name if guild else f"Unknown Guild {mutual.id}"
targets.append(Target(mutual.id, "guild", name))
guild_ids_seen.add(mutual.id)
except discord.NotFound:
log.warning(
"No mutual guild/friend relationship visible for user %s "
"(profile lookup requires already being friends or sharing a server). "
"Relying on manual_guild_ids and group DMs only.",
friend_id,
)
except discord.HTTPException:
log.warning("Mutual-guilds profile lookup failed; falling back to manual_guild_ids only", exc_info=True)
for guild_id in (manual_guild_ids or []):
if guild_id in guild_ids_seen:
continue
guild = client.get_guild(guild_id)
name = guild.name if guild else f"Manual Guild {guild_id}"
targets.append(Target(guild_id, "guild", name))
guild_ids_seen.add(guild_id)
try:
dm_channel = friend.dm_channel or await friend.create_dm()
targets.append(Target(dm_channel.id, "dm", f"DM with {friend}"))
except discord.HTTPException:
log.warning("Failed to open the 1:1 DM channel with %s", friend, exc_info=True)
for channel in client.private_channels:
if isinstance(channel, discord.GroupChannel) and any(u.id == friend_id for u in channel.recipients):
name = channel.name or ", ".join(u.name for u in channel.recipients)
targets.append(Target(channel.id, "group_dm", name))
return targets