Skip to content

Commit

Permalink
Handle DM problems better, notify the assigned user when bounty is cr…
Browse files Browse the repository at this point in the history
…eated (#108)

* Handle DM problems better, notify the assigned user about their bounty when created

* Clean up comments
  • Loading branch information
tescher authored May 23, 2023
1 parent 8479e25 commit 0af2ce2
Show file tree
Hide file tree
Showing 18 changed files with 130 additions and 82 deletions.
4 changes: 2 additions & 2 deletions src/app/activity/bounty/Apply.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ export const finishApply = async (request: ApplyRequest, pitch: string) => {
`Their pitch: ${pitch ? pitch : '<none given>'} \n` +
'Use the "/bounty assign" command to select an applicant who can claim.';

await DiscordUtils.activityNotification(creatorDM, createdByUser, cardMessage.url);
await DiscordUtils.activityNotification(creatorDM, createdByUser, request.guildId, cardMessage.url);
const activityMessage = `<@${applyingUser.user.id}>, You have applied for this bounty! Reach out to <@${createdByUser.id}> with any questions.`;
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, activityMessage, cardMessage.url);
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, activityMessage, applyingUser.id, request.guildId, cardMessage.url);
return;
};

Expand Down
4 changes: 2 additions & 2 deletions src/app/activity/bounty/Assign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export const assignBounty = async (request: AssignRequest): Promise<any> => {
let assignedContent = `You have been assigned this bounty! Click Claim It to claim. Reach out to <@${assigningUser.id}> with any questions.\n`;
let assigneeBountyEmbed = await assigneeBountySummaryEmbed(cardMessage, request.guildId);

await DiscordUtils.activityNotification(assignedContent, assignedUser, cardMessage.url, assigneeBountyEmbed);
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, assigningContent, cardMessage.url);
await DiscordUtils.activityNotification(assignedContent, assignedUser, request.guildId, cardMessage.url, assigneeBountyEmbed);
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, assigningContent, assigningUser.id, request.guildId, cardMessage.url);
return;
};

Expand Down
12 changes: 6 additions & 6 deletions src/app/activity/bounty/Claim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ export const claimBounty = async (request: ClaimRequest): Promise<any> => {
} catch (e) {
if (e instanceof ValidationError) {
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, `Unable to complete this operation.\n` +
'Please try entering your wallet address with the command `/register-wallet` and then try claiming the bounty again.\n');
'Please try entering your wallet address with the command `/register-wallet` and then try claiming the bounty again.\n', request.userId, request.guildId);
return;
}
if (e instanceof ModalTimeoutError) {
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, `Unable to complete this operation - form timeout.`);
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, `Unable to complete this operation - form timeout.`, request.userId, request.guildId);
return;
}
throw new RuntimeError(e);
Expand All @@ -57,7 +57,7 @@ export const finishClaim = async (request: any) => {
// Check to make sure they didn't enter DELETE when putting in the wallet address
if ( !request.clientSyncRequest && walletStillNeeded ) {
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, `You must enter a wallet address to claim a bounty.\n` +
'Please try entering your wallet address with the command `/register-wallet` and then try claiming the bounty again.\n');
'Please try entering your wallet address with the command `/register-wallet` and then try claiming the bounty again.\n', request.userId, request.guildId);
return;
}

Expand Down Expand Up @@ -94,13 +94,13 @@ export const finishClaim = async (request: any) => {
}

const createdByUser = await DiscordUtils.getGuildMemberFromUserId(getDbResult.dbBountyResult.createdBy.discordId, request.guildId);
await DiscordUtils.activityNotification(creatorNotification, createdByUser, claimedBountyCard.url);
await DiscordUtils.activityNotification(creatorNotification, createdByUser, request.guildId, claimedBountyCard.url);

const claimaintResponse = `<@${claimedByUser.user.id}>, you have claimed this bounty! Reach out to <@${createdByUser.user.id}> with any questions.`;
if (!request.clientSyncRequest) {
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, claimaintResponse, claimedBountyCard.url);
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, claimaintResponse, request.userId, request.guildId, claimedBountyCard.url);
} else {
await DiscordUtils.activityNotification(claimaintResponse, claimedByUser, claimedBountyCard.url)
await DiscordUtils.activityNotification(claimaintResponse, claimedByUser, request.guildId, claimedBountyCard.url)
if (walletStillNeeded) {
const walletMessage = `Please click the button below to enter your ethereum wallet address (non-ENS) to receive the reward amount for this bounty`;
const walletButton = new MessageButton().setStyle('SECONDARY').setCustomId('👛').setLabel('Register Wallet');
Expand Down
4 changes: 2 additions & 2 deletions src/app/activity/bounty/Complete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ export const completeBounty = async (request: CompleteRequest): Promise<void> =>
if (!getDbResult.dbBountyResult.paidStatus || getDbResult.dbBountyResult.paidStatus === PaidStatus.unpaid) {
submitterCompleteDM = submitterCompleteDM.concat(`<@${completedByUser.id}> should be paying you with ${getDbResult.dbBountyResult.reward.amount} ${getDbResult.dbBountyResult.reward.currency} soon.`);
}
await DiscordUtils.activityNotification(submitterCompleteDM, submittedByUser, cardMessage.url);
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, creatorCompleteDM, cardMessage.url);
await DiscordUtils.activityNotification(submitterCompleteDM, submittedByUser, request.guildId, cardMessage.url);
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, creatorCompleteDM, request.userId, request.guildId, cardMessage.url);
return;
}

Expand Down
35 changes: 22 additions & 13 deletions src/app/activity/bounty/Create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import { BountyStatus } from '../../constants/bountyStatus';
import { Clients } from '../../constants/clients';
import { PaidStatus } from '../../constants/paidStatus';
import { Activities } from '../../constants/activities';
import DMPermissionError from '../../errors/DMPermissionError';
import { ComponentType, ModalInteractionContext, TextInputStyle } from 'slash-create';
import { AssignRequest } from '../../requests/AssignRequest';
import { assignBounty } from './Assign';

export const createBounty = async (createRequest: CreateRequest): Promise<any> => {
Log.debug('In Create activity');
Expand Down Expand Up @@ -168,8 +169,8 @@ export const finishCreate = async (createRequest: CreateRequest, description: st

if (createRequest.isIOU) {
// await createRequest.commandContext.sendFollowUp({ content: "Your IOU was created." } , { ephemeral: true });
const IOUContent = `<@${owedTo.id}> An IOU was created for you by <@${guildMember.user.id}>: ${cardMessage.url}`;
await owedTo.send({ content: IOUContent }).catch(() => { throw new DMPermissionError(IOUContent) });
const IOUContent = `<@${owedTo.id}> An IOU was created for you by <@${guildMember.user.id}>:`;
await DiscordUtils.activityNotification(IOUContent, owedTo, createRequest.guildId, cardMessage.url);

const walletNeeded = !(await BountyUtils.userWalletRegistered(owedTo.id));

Expand All @@ -180,13 +181,29 @@ export const finishCreate = async (createRequest: CreateRequest, description: st
const iouWalletMessage = `Please click the button below to enter your ethereum wallet address (non-ENS) to receive the reward amount for this bounty`;
const walletButton = new MessageButton().setStyle('SECONDARY').setCustomId('👛').setLabel('Register Wallet');

await owedTo.send({ content: iouWalletMessage, components: [new MessageActionRow().addComponents(walletButton)] });
await DiscordUtils.attemptDM({ content: iouWalletMessage, components: [new MessageActionRow().addComponents(walletButton)] }, owedTo, createRequest.guildId);
}

await DiscordUtils.activityResponse(createRequest.commandContext, null, 'IOU created successfully.' + (walletNeeded ? "\n" +
`${owedTo} has not registered a wallet. Remind them to check their DMs for a register wallet button, or to use the /register-wallet command.` : ""));
`${owedTo} has not registered a wallet. Remind them to check their DMs for a register wallet button, or to use the /register-wallet command.` : ""), createRequest.userId, createRequest.guildId);
} else {
await modalContext?.send('Bounty created, see below...');
if (createRequest.assign) {
const assignRequest = new AssignRequest({
commandContext: null,
messageReactionRequest: null,
buttonInteraction: null,
directRequest: {
guildId: createRequest.guildId,
bountyId: newBounty._id,
userId: createRequest.userId,
assign: createRequest.assign,
activity: Activities.assign,
bot: false,
}
});
await assignBounty(assignRequest);
}
return;
}
}
Expand Down Expand Up @@ -310,14 +327,6 @@ export const generateBountyRecord = async (
}
}

if (createRequest.assign) {
bountyRecord.assignTo = {
discordId: assignedTo.user.id,
discordHandle: assignedTo.user.tag,
iconUrl: assignedTo.user.avatarURL(),
}
}

if (createRequest.requireApplication) {
bountyRecord.requireApplication = true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/app/activity/bounty/Delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const deleteBounty = async (request: DeleteRequest): Promise<void> => {
getDbResult.dbBountyResult.childrenIds !== undefined && getDbResult.dbBountyResult.childrenIds.length > 0) {
creatorDeleteDM += 'Children bounties created from this multi-claimant bounty will remain.\n';
}
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, creatorDeleteDM);
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, creatorDeleteDM, request.userId, request.guildId);
return;
}

Expand Down
4 changes: 2 additions & 2 deletions src/app/activity/bounty/Help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ export const helpBounty = async (request: HelpRequest): Promise<void> => {
const userHelpDM =
`<@${bountyCreator.id}> has been notified of your request for help with the following bounty.\n`;

await DiscordUtils.activityNotification(creatorHelpDM, bountyCreator, bountyUrl);
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, userHelpDM, bountyUrl);
await DiscordUtils.activityNotification(creatorHelpDM, bountyCreator, request.guildId, bountyUrl);
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, userHelpDM, request.userId, request.guildId, bountyUrl);
} else {
const bountyChannel: TextChannel = await client.channels.fetch(request.commandContext.channelID) as TextChannel;

Expand Down
4 changes: 2 additions & 2 deletions src/app/activity/bounty/List.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ export const listBounty = async (request: ListRequest, preventResponse ?: boolea
if (!!request.message) { // List from a refresh reaction
listMessage = request.message;
await listMessage.edit({ embeds: [listCard], components: [componentActions] });
!preventResponse && await DiscordUtils.activityResponse(null, request.buttonInteraction, 'Bounty list refreshed successfully');
!preventResponse && await DiscordUtils.activityResponse(null, request.buttonInteraction, 'Bounty list refreshed successfully', request.userId, request.guildId);
} else { // List from a slash command
const channel = await DiscordUtils.getTextChannelfromChannelId(request.commandContext.channelID);
listMessage = await channel.send({ embeds: [listCard], components: [componentActions] });
Expand All @@ -176,7 +176,7 @@ export const listBounty = async (request: ListRequest, preventResponse ?: boolea
} catch (e) {
throw new DMPermissionError(e);
}
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, 'Please check your DM for bounty list');
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, 'Please check your DM for bounty list', request.userId, request.guildId);

}
};
Expand Down
4 changes: 2 additions & 2 deletions src/app/activity/bounty/Paid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ export const paidBounty = async (request: PaidRequest): Promise<void> => {
`Your bounty has been marked as paid: ${getDbResult.dbBountyResult.title}.\n` +
`If you don't see a payment post, contact the bounty creator <@${paidByUser.user.id}>`;

await DiscordUtils.activityNotification(payeeDMContent, payee, cardMessage.url);
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, creatorPaidDM, cardMessage.url);
await DiscordUtils.activityNotification(payeeDMContent, payee, request.guildId, cardMessage.url);
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, creatorPaidDM, request.userId, request.guildId, cardMessage.url);
return;
}

Expand Down
2 changes: 1 addition & 1 deletion src/app/activity/bounty/Publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export const publishBounty = async (publishRequest: PublishRequest): Promise<any
}
const bountyMessage: Message = await BountyUtils.canonicalCard(dbBountyResult._id, publishRequest.activity, bountyChannel, guildMember);
if (dbBountyResult.status == BountyStatus.draft || publishRequest.commandContext) {
await DiscordUtils.activityResponse(publishRequest.commandContext, publishRequest.buttonInteraction, `Bounty published to \`${(bountyMessage.channel as any).name || bountyChannel.name}\` and the website! <${process.env.BOUNTY_BOARD_URL}${bountyId}>`, bountyMessage.url);
await DiscordUtils.activityResponse(publishRequest.commandContext, publishRequest.buttonInteraction, `Bounty published to \`${(bountyMessage.channel as any).name || bountyChannel.name}\` and the website! <${process.env.BOUNTY_BOARD_URL}${bountyId}>`, publishRequest.userId, publishRequest.guildId, bountyMessage.url);
}

Log.info(`bounty published to ${(bountyMessage.channel as any).name || bountyChannel.name}`);
Expand Down
4 changes: 2 additions & 2 deletions src/app/activity/bounty/Submit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ export const submitBounty = async (request: SubmitRequest): Promise<void> => {
if (request.notes) {
creatorSubmitDM += `\nNotes included in submission:\n${request.notes}`
}
await DiscordUtils.activityNotification(creatorSubmitDM, createdByUser, cardMessage.url);
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, `Bounty in review! Expect a message from <@${createdByUser.id}>.`, cardMessage.url);
await DiscordUtils.activityNotification(creatorSubmitDM, createdByUser, request.guildId, cardMessage.url);
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, `Bounty in review! Expect a message from <@${createdByUser.id}>.`, request.userId, request.guildId, cardMessage.url);
return;

}
Expand Down
4 changes: 3 additions & 1 deletion src/app/activity/bounty/Tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ export const tagBounty = async (request: TagRequest): Promise<void> => {
await DiscordUtils.activityResponse(
request.commandContext,
request.buttonInteraction,
tagResponse,
tagResponse,
request.userId,
request.guildId,
bountyCard.url
);
return;
Expand Down
5 changes: 3 additions & 2 deletions src/app/activity/user/RegisterWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,14 +125,15 @@ export const upsertUserWallet = async (request: UpsertUserWalletRequest): Promis
}

export const finishRegister = async (request: UpsertUserWalletRequest) => {
// Not passing user to activityResponse - don't want this on the public channel even if the DM fails
if (ADDRESS_DELETE_REGEX.test(request.address)) {
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, "Your wallet address has been deleted.");
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, "Your wallet address has been deleted.", null, null);

} else {
const activityMessage = `<@${request.userDiscordId}>, your wallet address has been registered as ${request.address}.\n`+
`You can change it by using the /register-wallet command.`;
const etherscanUrl = `https://etherscan.io/address/${request.address}`;
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, activityMessage, etherscanUrl, "View on Etherscan");
await DiscordUtils.activityResponse(request.commandContext, request.buttonInteraction, activityMessage, null, null, etherscanUrl, "View on Etherscan");
}
}

Expand Down
9 changes: 1 addition & 8 deletions src/app/commands/bounty/Bounty.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,14 +306,6 @@ export default class Bounty extends SlashCommand {
buttonInteraction: null,
});
break;
case Activities.assign:
request = new AssignRequest({
commandContext: commandContext,
messageReactionRequest: null,
buttonInteraction: null,

});
break;
case Activities.apply:
request = new ApplyRequest({
commandContext: commandContext,
Expand All @@ -326,6 +318,7 @@ export default class Bounty extends SlashCommand {
commandContext: commandContext,
messageReactionRequest: null,
buttonInteraction: null,
directRequest: null,
});
break;
case Activities.submit:
Expand Down
4 changes: 2 additions & 2 deletions src/app/commands/bounty/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ export default class IOU extends SlashCommand {
}
catch (e) {
if (e instanceof ValidationError) {
await DiscordUtils.activityResponse(commandContext, null, `<@${commandContext.user.id}>\n` + e.message);
await DiscordUtils.activityResponse(commandContext, null, `<@${commandContext.user.id}>\n` + e.message, request.userId, request.guildId);
} else if (e instanceof AuthorizationError) {
await DiscordUtils.activityResponse(commandContext, null, `<@${commandContext.user.id}>\n` + e.message);
await DiscordUtils.activityResponse(commandContext, null, `<@${commandContext.user.id}>\n` + e.message, request.userId, request.guildId);
} else if (e instanceof NotificationPermissionError) {
await ErrorUtils.sendToDefaultChannel(e.message, request);
} else if (e instanceof DMPermissionError) {
Expand Down
2 changes: 1 addition & 1 deletion src/app/events/InteractionCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ export default class implements DiscordEvent {
errorContent = 'Sorry something is not working and our devs are looking into it.';
}

return await DiscordUtils.interactionResponse(interaction, errorContent);
return await DiscordUtils.interactionResponse(interaction, {content: errorContent});
}
}
}
Loading

0 comments on commit 0af2ce2

Please sign in to comment.