Add peer support functionality and UI

This commit is contained in:
Jennie Robinson Faber 2025-10-06 11:29:47 +01:00
parent 2b55ca4104
commit 1b8dacf92a
11 changed files with 1159 additions and 35 deletions

View file

@ -14,7 +14,7 @@ export class SlackService {
*/
async inviteUserToSlack(
email: string,
realName: string
realName: string,
): Promise<{
success: boolean;
userId?: string;
@ -34,7 +34,7 @@ export class SlackService {
});
console.log(
`Successfully invited existing user ${email} to vetting channel`
`Successfully invited existing user ${email} to vetting channel`,
);
return {
success: true,
@ -65,7 +65,7 @@ export class SlackService {
if (inviteResponse.ok && inviteResponse.user) {
console.log(
`Successfully invited ${email} to workspace as single-channel guest`
`Successfully invited ${email} to workspace as single-channel guest`,
);
return {
success: true,
@ -79,7 +79,7 @@ export class SlackService {
console.log(
`Admin API not available or failed: ${
adminError.data?.error || adminError.message
}`
}`,
);
// Fall back to manual process
@ -113,6 +113,67 @@ export class SlackService {
}
}
/**
* Find user ID by username (display name or real name)
*/
async findUserIdByUsername(username: string): Promise<string | null> {
try {
const cleanUsername = username.replace("@", "").toLowerCase();
// List all users and search for matching username
const response = await this.client.users.list();
if (!response.members) {
return null;
}
// Search for user by name or display_name
const user = response.members.find((member: any) => {
const name = member.name?.toLowerCase() || "";
const realName = member.real_name?.toLowerCase() || "";
const displayName = member.profile?.display_name?.toLowerCase() || "";
return (
name === cleanUsername ||
displayName === cleanUsername ||
realName.includes(cleanUsername)
);
});
return user?.id || null;
} catch (error) {
console.error("Error looking up Slack user by username:", error);
return null;
}
}
/**
* Open/get a DM channel with a user and return the channel ID
* This creates or opens a DM conversation and returns the channel ID (starts with D)
*/
async openDMChannel(userId: string): Promise<string | null> {
try {
const response = await this.client.conversations.open({
users: userId,
});
if (response.ok && response.channel?.id) {
console.log(
`Opened DM channel for user ${userId}: ${response.channel.id}`,
);
return response.channel.id;
}
return null;
} catch (error: any) {
console.error(
"Error opening DM channel:",
error.data?.error || error.message,
);
return null;
}
}
/**
* Send a notification to the vetting channel about a new member
*/
@ -121,7 +182,7 @@ export class SlackService {
memberEmail: string,
circle: string,
contributionTier: string,
invitationStatus: string = "manual_invitation_required"
invitationStatus: string = "manual_invitation_required",
): Promise<void> {
try {
let statusMessage = "";
@ -224,7 +285,7 @@ export function getSlackService(): SlackService | null {
if (!config.slackBotToken || !config.slackVettingChannelId) {
console.warn(
"Slack integration not configured - missing bot token or channel ID"
"Slack integration not configured - missing bot token or channel ID",
);
return null;
}