@@ -33,6 +33,8 @@ import {
3333 updateProjectGithubRepo as dbUpdateProjectGithubRepo ,
3434 getUserGithubOAuthToken as dbGetUserGithubOAuthToken ,
3535 deleteUserGithubOAuthToken as dbDeleteUserGithubOAuthToken ,
36+ getUserDiscordToken as dbGetUserDiscordToken ,
37+ deleteUserDiscordToken as dbDeleteUserDiscordToken ,
3638 getTaskByUuid as dbGetTaskByUuid ,
3739 updateProjectDiscordSettings as dbUpdateProjectDiscordSettings ,
3840 deleteProject as dbDeleteProject ,
@@ -1283,6 +1285,87 @@ export async function disconnectGithubAction(prevState: { success: boolean; erro
12831285}
12841286
12851287
1288+ export interface DiscordUserDetails {
1289+ id : string ;
1290+ username : string ;
1291+ avatar : string | null ;
1292+ discriminator : string ;
1293+ }
1294+
1295+ export async function fetchDiscordUserDetailsAction ( targetUserUuid ?: string ) : Promise < DiscordUserDetails | null > {
1296+ const session = await auth ( ) ;
1297+ const userUuidForToken = targetUserUuid || session ?. user ?. uuid ;
1298+
1299+ if ( ! userUuidForToken ) {
1300+ console . error ( "[fetchDiscordUserDetailsAction] User UUID for token not determined." ) ;
1301+ return null ;
1302+ }
1303+
1304+ const oauthToken = await dbGetUserDiscordToken ( userUuidForToken ) ;
1305+
1306+ if ( ! oauthToken ?. accessToken ) {
1307+ console . log ( `[fetchDiscordUserDetailsAction] No Discord OAuth token found for user ${ userUuidForToken } .` ) ;
1308+ return null ;
1309+ }
1310+
1311+ // Check if token is expired
1312+ if ( oauthToken . expiresAt < Date . now ( ) ) {
1313+ console . log ( `[fetchDiscordUserDetailsAction] Discord token for user ${ userUuidForToken } has expired. Needs refresh.` ) ;
1314+ await dbDeleteUserDiscordToken ( userUuidForToken ) ;
1315+ console . warn ( `[fetchDiscordUserDetailsAction] Expired Discord token for user ${ userUuidForToken } was removed.` ) ;
1316+ return null ;
1317+ }
1318+
1319+ try {
1320+ const userResponse = await fetch ( 'https://discord.com/api/users/@me' , {
1321+ headers : {
1322+ Authorization : `Bearer ${ oauthToken . accessToken } ` ,
1323+ } ,
1324+ } ) ;
1325+
1326+ if ( ! userResponse . ok ) {
1327+ const errorBody = await userResponse . text ( ) ;
1328+ console . error ( `[fetchDiscordUserDetailsAction] Failed to fetch Discord user details for user ${ userUuidForToken } : ${ userResponse . status } ` , errorBody ) ;
1329+ if ( userResponse . status === 401 ) { // Unauthorized
1330+ await dbDeleteUserDiscordToken ( userUuidForToken ) ;
1331+ console . warn ( `[fetchDiscordUserDetailsAction] Invalid Discord token for user ${ userUuidForToken } , removed from DB.` ) ;
1332+ }
1333+ return null ;
1334+ }
1335+
1336+ const userData = await userResponse . json ( ) ;
1337+ return {
1338+ id : userData . id ,
1339+ username : userData . username ,
1340+ avatar : userData . avatar ,
1341+ discriminator : userData . discriminator ,
1342+ } ;
1343+ } catch ( error : any ) {
1344+ console . error ( `[fetchDiscordUserDetailsAction] Error fetching Discord user details for user ${ userUuidForToken } :` , error ) ;
1345+ return null ;
1346+ }
1347+ }
1348+
1349+
1350+ export async function disconnectDiscordAction ( prevState : { success : boolean ; error ?: string ; message ?: string } , formData : FormData ) : Promise < { success : boolean ; error ?: string ; message ?: string } > {
1351+ const session = await auth ( ) ;
1352+ if ( ! session ?. user ?. uuid ) {
1353+ return { success : false , error : "Authentication required." } ;
1354+ }
1355+ try {
1356+ const success = await dbDeleteUserDiscordToken ( session . user . uuid ) ;
1357+ if ( success ) {
1358+ return { success : true , message : "Discord account disconnected successfully." } ;
1359+ }
1360+ return { success : false , error : "Failed to disconnect Discord account from database." } ;
1361+ } catch ( error : any ) {
1362+ console . error ( "[disconnectDiscordAction] Error:" , error ) ;
1363+ return { success : false , error : error . message || "An unexpected error occurred." } ;
1364+ }
1365+ }
1366+
1367+
1368+
12861369function sanitizeRepoName ( name : string | null | undefined ) : string {
12871370 if ( ! name ) {
12881371 return '' ;
@@ -1892,7 +1975,7 @@ export async function updateProjectDiscordSettingsAction(
18921975 return { error : "You do not have permission to change Discord settings for this project." } ;
18931976 }
18941977
1895- const updatedProject = await dbUpdateProjectDiscordSettings ( projectUuid , discordWebhookUrl , discordNotificationsEnabled , discordNotifyTasks , discordNotifyMembers , discordNotifyAnnouncements ) ;
1978+ const updatedProject = await dbUpdateProjectDiscordSettings ( projectUuid , discordWebhookUrl , discordNotificationsEnabled , notifyTasks , notifyMembers , notifyAnnouncements ) ;
18961979
18971980 if ( ! updatedProject ) {
18981981 return { error : "Failed to update project settings in the database." } ;
0 commit comments