Skip to content

Commit

Permalink
Merge pull request #40 from iluxonchik/feature/govbot-0.0.10
Browse files Browse the repository at this point in the history
Feature/govbot 0.0.10
  • Loading branch information
iluxonchik authored Aug 29, 2024
2 parents e0ec505 + bed728c commit 5bc27af
Show file tree
Hide file tree
Showing 11 changed files with 3,144 additions and 2,658 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "mina-govbot",
"version": "0.0.9",
"version": "0.0.10",
"description": "Discord bot for collective decision making for Mina Protocol",
"main": "index.js",
"directories": {
Expand Down
4,342 changes: 2,306 additions & 2,036 deletions src/channels/admin/screens/ManageFundingRoundsScreen.ts

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/channels/admin/screens/ManageProposalStatusesScreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { EndUserError } from '../../../Errors';
import { ActiveFundingRoundPaginator } from '../../../components/FundingRoundPaginator';
import { ManageProposalStatusesPaginator } from '../../../components/ProposalsPaginator';
import { ArgumentOracle } from '../../../CustomIDOracle';
import { DiscordLimiter } from '../../../utils/DiscordLimiter';

export class ManageProposalStatusesScreen extends Screen {
public static readonly ID = 'manageProposalStatuses';
Expand Down Expand Up @@ -232,7 +233,7 @@ export class UpdateProposalStatusAction extends Action {

const embed = new EmbedBuilder()
.setColor('#0099ff')
.setTitle(`Update Proposal Status: ${proposal.name}`)
.setTitle(DiscordLimiter.StringSelectMenu.limitDescription(`Update Proposal Status: ${proposal.name}`))
.setDescription(`Current status: ${proposal.status}`)
.addFields(
{ name: 'ID', value: proposal.id.toString(), inline: true },
Expand Down
917 changes: 516 additions & 401 deletions src/channels/consider/screens/ConsiderationHomeScreen.ts

Large diffs are not rendered by default.

63 changes: 35 additions & 28 deletions src/channels/proposals/ProposalsForumManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@ import { Screen } from '../../core/BaseClasses';
import { ProposalLogic } from '../../logic/ProposalLogic';
import { ProposalStatus } from '../../types';
import { FundingRoundLogic } from '../admin/screens/FundingRoundLogic';
import { DiscordLimiter } from '../../utils/DiscordLimiter';

export function proposalStatusToPhase(status: ProposalStatus): string {
switch (status) {
case (ProposalStatus.CONSIDERATION_PHASE):
return "consideration";
case (ProposalStatus.DELIBERATION_PHASE):
return "deliberation";
case (ProposalStatus.FUNDING_VOTING_PHASE):
return "funding";
default:
throw new EndUserError(`Invalid proposal voting phase: ${status.toString()}`)
}
switch (status) {
case ProposalStatus.CONSIDERATION_PHASE:
return 'consideration';
case ProposalStatus.DELIBERATION_PHASE:
return 'deliberation';
case ProposalStatus.FUNDING_VOTING_PHASE:
return 'funding';
default:
throw new EndUserError(`Invalid proposal voting phase: ${status.toString()}`);
}
}

export class ProposalsForumManager {
Expand All @@ -34,7 +35,7 @@ export class ProposalsForumManager {
}

const thread = await forumChannel.threads.create({
name: proposal.name,
name: DiscordLimiter.limitTo100(proposal.name),
message: { content: 'Loading proposal details...' },
});

Expand All @@ -56,7 +57,7 @@ export class ProposalsForumManager {
logger.debug(`Updating forum thread ${thread.id}:`);
if (firstMessage) {
logger.debug(`\tFirst message. Editing ${firstMessage.id}...`);
await firstMessage.edit({ content: "", embeds: [embed], components: [voteButton] });
await firstMessage.edit({ content: '', embeds: [embed], components: [voteButton] });
} else {
logger.debug(`\tNo first message. Sending new message to thread ${thread.id}...`);
await thread.send({ embeds: [embed], components: [voteButton] });
Expand Down Expand Up @@ -129,39 +130,46 @@ export class ProposalsForumManager {

private static createProposalEmbed(proposal: Proposal): EmbedBuilder {
return new EmbedBuilder()
.setTitle(proposal.name)
.setTitle(DiscordLimiter.limitTo100(proposal.name))
.setDescription('See the details of the proposal and vote on it below.')
.addFields(
{ name: 'Budget', value: proposal.budget.toString(), inline: true },
{ name: 'Status', value: proposal.status, inline: true },
{ name: 'URI', value: proposal.uri }
{ name: 'Budget', value: DiscordLimiter.limitTo100(proposal.budget.toString()), inline: true },
{ name: 'Status', value: DiscordLimiter.limitTo100(proposal.status), inline: true },
{ name: 'URI', value: DiscordLimiter.limitTo100(proposal.uri) },
)
.setColor('#0099ff');
}

public static async createVoteButton(proposalId: number, fundingRoundId: number, screen: any): Promise<ActionRowBuilder<ButtonBuilder>> {
const fundingRound: FundingRound = await FundingRoundLogic.getFundingRoundByIdOrError(fundingRoundId);

if (!fundingRound.forumChannelId) {
throw new EndUserError(`Funding round ${fundingRoundId} does not have a forum channel`);
}

const dashBoardId: string = fundingRound.forumChannelId.toString();


const proposal: Proposal = await ProposalLogic.getProposalByIdOrError(proposalId);
const proposalPhase: string = proposalStatusToPhase(proposal.status);
const customId: string = CustomIDOracle.customIdFromRawParts(dashBoardId, ProjectVotingScreen.ID, SelectProjectAction.ID, SelectProjectAction.OPERATIONS.selectProject, 'prId', proposalId.toString(), ArgumentOracle.COMMON_ARGS.FUNDING_ROUND_ID, fundingRoundId.toString(), 'ph', proposalPhase);
const button = new ButtonBuilder()
.setCustomId(customId)
.setLabel('Vote On This Proposal')
.setStyle(ButtonStyle.Primary);
const customId: string = CustomIDOracle.customIdFromRawParts(
dashBoardId,
ProjectVotingScreen.ID,
SelectProjectAction.ID,
SelectProjectAction.OPERATIONS.selectProject,
'prId',
proposalId.toString(),
ArgumentOracle.COMMON_ARGS.FUNDING_ROUND_ID,
fundingRoundId.toString(),
'ph',
proposalPhase,
);
const button = new ButtonBuilder().setCustomId(customId).setLabel('Vote On This Proposal').setStyle(ButtonStyle.Primary);

return new ActionRowBuilder<ButtonBuilder>().addComponents(button);
}

private static async getForumChannelOrError(fundingRound: FundingRound): Promise<ForumChannel> {
const { client } = await import("../../bot");
const { client } = await import('../../bot');

const guild = client.guilds.cache.first();

Expand All @@ -170,15 +178,15 @@ export class ProposalsForumManager {
}

const allChannels = await guild.channels.fetch();
logger.debug(`All channels: ${allChannels.map(channel => channel?.id).join(', ')}`);
logger.debug(`All channels: ${allChannels.map((channel) => channel?.id).join(', ')}`);

const proposalChannelId: string | null = fundingRound.forumChannelId.toString();

if (!proposalChannelId) {
throw new NotFoundEndUserError(`Funding round ${fundingRound.id} does not have a forum channel`);
}

//FIXME: ensure proposal is being fetched correcly
//FIXME: ensure proposal is being fetched correctly
logger.debug(`Fetching proposal channel ${proposalChannelId}...`);
const channel = await guild.channels.fetch(proposalChannelId);

Expand All @@ -191,6 +199,5 @@ export class ProposalsForumManager {
}

return channel as ForumChannel;

}
}
}
69 changes: 45 additions & 24 deletions src/channels/propose/screens/ProposalHomeScreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { EndUserError, EndUserInfo } from '../../../Errors';
import { DiscordStatus } from '../../DiscordStatus';
import logger from '../../../logging';
import { EditMySubmittedProposalsPaginator } from '../../../components/ProposalsPaginator';
import { DiscordLimiter } from '../../../utils/DiscordLimiter';

export class ProposalHomeScreen extends Screen implements IHomeScreen {
public static readonly ID = 'proposalHome';
Expand Down Expand Up @@ -215,10 +216,20 @@ export class ManageSubmittedProposalsAction extends PaginationComponent {

const embed: EmbedBuilder = new EmbedBuilder()
.setColor('#0099ff')
.setTitle(`Proposal: ${proposal.name}`)
.setTitle(DiscordLimiter.EmbedBuilder.limitTitle(`Proposal: ${proposal.name}`))
.addFields(
{ name: 'Proposal Details', value: `Budget: ${proposal.budget}\nStatus: ${proposal.status}\nURI: ${proposal.uri}` },
{ name: 'Funding Round', value: `Name: ${fundingRound.name}\nBudget: ${fundingRound.budget}\nStatus: ${fundingRound.status}` },
{
name: 'Proposal Details',
value: DiscordLimiter.EmbedBuilder.limitFieldValue(`Budget: ${proposal.budget}
Status: ${proposal.status}
URI: ${proposal.uri}`),
},
{
name: 'Funding Round',
value: DiscordLimiter.EmbedBuilder.limitFieldValue(`Name: ${fundingRound.name}
Budget: ${fundingRound.budget}
Status: ${fundingRound.status}`),
},
);

const cancelButton: ButtonBuilder = new ButtonBuilder()
Expand Down Expand Up @@ -264,8 +275,18 @@ export class ManageSubmittedProposalsAction extends PaginationComponent {
.setTitle('Confirm Proposal Cancellation')
.setDescription('Are you sure you want to cancel this proposal? This action cannot be undone.')
.addFields(
{ name: 'Proposal Details', value: `Name: ${proposal.name}\nBudget: ${proposal.budget}\nStatus: ${proposal.status}\nURI: ${proposal.uri}` },
{ name: 'Funding Round', value: `Name: ${fundingRound.name}\nBudget: ${fundingRound.budget}\nStatus: ${fundingRound.status}` },
{
name: 'Proposal Details',
value: DiscordLimiter.EmbedBuilder.limitFieldValue(
`Name: ${DiscordLimiter.limitTo100(proposal.name)}\nBudget: ${proposal.budget}\nStatus: ${proposal.status}\nURI: ${proposal.uri}`,
),
},
{
name: 'Funding Round',
value: DiscordLimiter.EmbedBuilder.limitFieldValue(
`Name: ${fundingRound.name}\nBudget: ${fundingRound.budget}\nStatus: ${fundingRound.status}`,
),
},
)
.setFooter({
text: 'Once cancelled, this proposal cannot be re-submitted to the funding round. You will need to create a new proposal if you want to submit again.',
Expand Down Expand Up @@ -422,9 +443,9 @@ export class ManageDraftsAction extends PaginationComponent {
.setPlaceholder('Select a Draft Proposal')
.addOptions(
drafts.map((draft) => ({
label: draft.name,
label: DiscordLimiter.StringSelectMenu.limitDescription(draft.name),
value: draft.id.toString(),
description: `Budget: ${draft.budget}`,
description: DiscordLimiter.StringSelectMenu.limitDescription(`Budget: ${draft.budget}`),
})),
);

Expand Down Expand Up @@ -475,13 +496,13 @@ export class ManageDraftsAction extends PaginationComponent {

const embed: EmbedBuilder = new EmbedBuilder()
.setColor('#0099ff')
.setTitle(`Draft Proposal: ${proposal.name}`)
.setDescription(`Proposal URI: ${proposal.uri}`)
.setTitle(DiscordLimiter.EmbedBuilder.limitTitle(`Draft Proposal: ${proposal.name}`))
.setDescription(DiscordLimiter.EmbedBuilder.limitDescription(`Proposal URI: ${proposal.uri}`))
.addFields(
{ name: 'ID (auto-assigned)', value: proposal.id.toString(), inline: true },
{ name: 'Budget', value: proposal.budget.toString(), inline: true },
{ name: 'URL', value: proposal.uri, inline: true },
{ name: 'Status', value: proposal.status, inline: true },
{ name: 'Budget', value: DiscordLimiter.EmbedBuilder.limitField(proposal.budget.toString()), inline: true },
{ name: 'URL', value: DiscordLimiter.EmbedBuilder.limitField(proposal.uri), inline: true },
{ name: 'Status', value: DiscordLimiter.EmbedBuilder.limitField(proposal.status), inline: true },
);

const editButton = new ButtonBuilder()
Expand Down Expand Up @@ -620,13 +641,13 @@ export class ManageDraftsAction extends PaginationComponent {

const embed = new EmbedBuilder()
.setColor('#ff0000')
.setTitle(`Confirm Delete: ${proposal.name}`)
.setTitle(DiscordLimiter.EmbedBuilder.limitTitle(`Confirm Delete: ${proposal.name}`))
.setDescription('Are you sure you want to delete this proposal? This action cannot be undone.')
.addFields(
{ name: 'Name', value: proposal.name },
{ name: 'Name', value: DiscordLimiter.EmbedBuilder.limitFieldValue(proposal.name) },
{ name: 'ID', value: proposal.id.toString() },
{ name: 'Budget', value: proposal.budget.toString() },
{ name: 'URL', value: proposal.uri },
{ name: 'Budget', value: DiscordLimiter.EmbedBuilder.limitFieldValue(proposal.budget.toString()) },
{ name: 'URL', value: DiscordLimiter.EmbedBuilder.limitFieldValue(proposal.uri) },
);

const confirmButton = new ButtonBuilder()
Expand Down Expand Up @@ -814,9 +835,9 @@ export class CreateNewProposalAction extends Action {
.setDescription('Your new proposal draft has been created.')
.addFields(
{ name: 'ID (auto-assigned)', value: newProposal.id.toString() },
{ name: 'Name', value: newProposal.name },
{ name: 'Budget', value: newProposal.budget.toString() },
{ name: 'URL', value: newProposal.uri },
{ name: 'Name', value: DiscordLimiter.EmbedBuilder.limitFieldValue(newProposal.name) },
{ name: 'Budget', value: DiscordLimiter.EmbedBuilder.limitFieldValue(newProposal.budget.toString()) },
{ name: 'URL', value: DiscordLimiter.EmbedBuilder.limitFieldValue(newProposal.uri) },
);

const manageButton = new ButtonBuilder()
Expand Down Expand Up @@ -897,9 +918,9 @@ export class SubmitProposalToFundingRoundAction extends Action {
.setPlaceholder('Select a Draft Proposal')
.addOptions(
draftProposals.map((proposal) => ({
label: proposal.name,
label: DiscordLimiter.StringSelectMenu.limitDescription(proposal.name),
value: proposal.id.toString(),
description: `Budget: ${proposal.budget}`,
description: DiscordLimiter.StringSelectMenu.limitDescription(`Budget: ${proposal.budget}`),
})),
);

Expand Down Expand Up @@ -972,9 +993,9 @@ export class SubmitProposalToFundingRoundAction extends Action {
.setDescription('Please review the details below and confirm your submission.')
.addFields(
{ name: 'Proposal ID (auto-assigned)', value: proposal.id.toString() },
{ name: 'Proposal Name', value: proposal.name },
{ name: 'Proposal Budget', value: proposal.budget.toString() },
{ name: 'Proposal URI', value: proposal.uri },
{ name: 'Proposal Name', value: DiscordLimiter.EmbedBuilder.limitFieldValue(proposal.name) },
{ name: 'Proposal Budget', value: DiscordLimiter.EmbedBuilder.limitFieldValue(proposal.budget.toString()) },
{ name: 'Proposal URI', value: DiscordLimiter.EmbedBuilder.limitFieldValue(proposal.uri) },
{ name: 'Funding Round', value: fundingRound.name },
{ name: 'Funding Round Budget', value: fundingRound.budget.toString() },
{ name: 'Funding Round End Date', value: fundingRound.endAt.toLocaleDateString() },
Expand Down
25 changes: 15 additions & 10 deletions src/channels/vote/screens/ProjectVotingScreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { OCVLinkGenerator } from '../../../utils/OCVLinkGenerator';
import logger from '../../../logging';
import { EndUserError, EndUserInfo } from '../../../Errors';
import { proposalStatusToPhase } from '../../proposals/ProposalsForumManager';
import { DiscordLimiter } from '../../../utils/DiscordLimiter';

export class ProjectVotingScreen extends Screen {
public static readonly ID = 'prVt';
Expand Down Expand Up @@ -414,16 +415,20 @@ class VoteProjectAction extends Action {
`;
}
// TODO: add description for each phase
const embed = new EmbedBuilder().setColor('#0099ff').setTitle(`Vote on Project: ${project.name}`).setDescription(description).addFields(
{ name: 'Budget', value: project.budget.toString(), inline: true },
{ name: 'Status', value: project.status, inline: true },
{ name: 'URI', value: project.uri, inline: true },
{
name: 'Proposer Discord ID',
value: project.proposerDuid,
inline: true,
},
);
const embed = new EmbedBuilder()
.setColor('#0099ff')
.setTitle(DiscordLimiter.EmbedBuilder.limitTitle(`Vote on Project: ${project.name}`))
.setDescription(description)
.addFields(
{ name: 'Budget', value: DiscordLimiter.EmbedBuilder.limitField(project.budget.toString()), inline: true },
{ name: 'Status', value: project.status, inline: true },
{ name: 'URI', value: DiscordLimiter.EmbedBuilder.limitField(project.uri), inline: true },
{
name: 'Proposer Discord ID',
value: project.proposerDuid,
inline: true,
},
);

let components: ActionRowBuilder<MessageActionRowComponentBuilder>[] = [];
switch (proposalPhase.toLowerCase()) {
Expand Down
Loading

0 comments on commit 5bc27af

Please sign in to comment.