Skip to content

Commit

Permalink
Check division commands and import command
Browse files Browse the repository at this point in the history
  • Loading branch information
Liesel Downes committed Jun 29, 2023
1 parent 93c71f1 commit 3d46b3f
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 16 deletions.
2 changes: 1 addition & 1 deletion src/commands/Help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ export class HelpCommand extends Subcommand {
}

public async chatInputImportFormula(interaction: Subcommand.ChatInputCommandInteraction) {
await interaction.reply('```clean\n=ArrayFormula(concatenate("[", join(", ", char(34)&B5:B54&char(34)), "]"))\n```');
await interaction.reply('```=JOIN(",", B5:B54)```');
}
}
27 changes: 18 additions & 9 deletions src/commands/Members.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@ export class MembersCommand extends Subcommand {
.addSubcommand((command) =>
command
.setName('import')
.setDescription('Import MPs from JSON list (provided on whip sheet), /help import-formula')
.setDescription('Import MPs from list (provided on whip sheet), /help import-formula')
.addStringOption((option) =>
option
.setName('json')
.setDescription('The JSON input')
.setName('input')
.setDescription('The comma delimited input')
.setRequired(true)
)
),
Expand Down Expand Up @@ -205,16 +205,25 @@ export class MembersCommand extends Subcommand {
}

public async chatInputImport(interaction: Subcommand.ChatInputCommandInteraction) {
const input = interaction.options.getString('json');
if (!input || !isValidJson(input)) {
await interaction.reply({ content: 'Please provide valid JSON.' });
const input = interaction.options.getString('input');
if (!input) {
await interaction.reply({ content: 'Please provide valid input.' });
return;
}
await interaction.deferReply();

console.log(input);

await interaction.editReply({ content: 'Test' });
const memberUsernames = (await this.memberRepository.find()).map(member => member.redditUsername);
var arr = input.split(/[ ,]+/);
arr = arr.filter(entry => entry.trim() != '');
const usernames = arr.filter(entry => !memberUsernames.includes(entry));
for (const i in usernames) {
const member = new Member();
member.redditUsername = usernames[i];
member.sendDiscordReminders = false;
await this.memberRepository.save(member);
}

await interaction.editReply({ content: `Added ${arr.length} members excluding duplicates.` });
}

private formatReminderChannelsString(member: Member) {
Expand Down
114 changes: 113 additions & 1 deletion src/commands/Whip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import { AppDataSource } from "../data-source";
import { Division } from "../entity/Division";
import { whipIssueChannelId, memberRoleId } from "../whipConfig.json";
import { ChannelType, EmbedBuilder, TextChannel } from "discord.js";
import { fetchThread } from "../reddit/Subreddit";
import { ValidVotes } from "../enums/ValidVotes";
import { Thread } from "../reddit/Thread";
import { formatDate } from "../utilities/Formatters";
import { MoreThan } from "typeorm";

export class WhipCommand extends Subcommand {
private divisionsRepository = AppDataSource.getRepository(Division);
Expand All @@ -13,7 +18,9 @@ export class WhipCommand extends Subcommand {
name: 'whip',
description: 'Whip commands',
subcommands: [
{ name: 'issue', chatInputRun: 'chatInputIssue' }
{ name: 'issue', chatInputRun: 'chatInputIssue' },
{ name: 'check', chatInputRun: 'chatInputCheck' },
{ name: 'check-active', chatInputRun: 'chatInputCheckActive' },
]
});
}
Expand Down Expand Up @@ -42,11 +49,61 @@ export class WhipCommand extends Subcommand {
.addStringOption(option =>
option.setName('notes').setDescription('Notes displayed alongside').setRequired(false)
)
)
.addSubcommand(command =>
command
.setName('check')
.setDescription('Check the status of a division')
.addStringOption(option =>
option.setName('division_id').setDescription('Division ID').setAutocomplete(true).setRequired(true)
)
)
.addSubcommand(command =>
command
.setName('check-active')
.setDescription('Check the status of all active divisions')
),
{ idHints: ['1116387569484181524'] }
);
}

private async createCheckEmbed(division: Division, thread: Thread) {
const embed = new EmbedBuilder()
.setTitle(`Status of ${division.shortName}`)
.setDescription(`${division.directive} - ends ${formatDate(division.closesAt)}`)
.setURL(division.url)
.setFooter({ text: division.longName });


console.log('Ayes'+ thread.getAyes());
let ayeField = '';
let noField = '';
let abstainField = '';
let noVoteField = '';
thread.getAyes().forEach(username => {
ayeField += `${username} \n`;
});
thread.getNoes().forEach(username => {
noField += `${username} \n`;
});
thread.getAbstentions().forEach(username => {
abstainField += `${username} \n`;
});
const notVoted = await thread.getMembersNotVoted()
notVoted.forEach(username => {
noVoteField += `${username} \n`;
});

embed.addFields(
{ name: 'Aye votes', value: ayeField != '' ? ayeField : 'None recorded.' },
{ name: 'No votes', value: noField != '' ? noField : 'None recorded.' },
{ name: 'Abstain votes', value: abstainField != '' ? abstainField : 'None recorded.' },
{ name: 'No vote recorded', value: noVoteField != '' ? noVoteField : 'None recorded.' },
);

return embed;
}

public async chatInputIssue(interaction: Subcommand.ChatInputCommandInteraction) {
await interaction.deferReply();

Expand Down Expand Up @@ -92,4 +149,59 @@ export class WhipCommand extends Subcommand {
});
await interaction.editReply({ content: `Whips issued in <#${channel.id}>` });
}

public async chatInputCheck(interaction: Subcommand.ChatInputCommandInteraction) {
await interaction.deferReply();

const divisionId = interaction.options.getString('division_id');
if (!divisionId) {
await interaction.editReply({ content: 'Please provide a division ID.' });
return;
}
const division = await this.divisionsRepository.findOneBy({ shortName: divisionId });
if (!division) {
await interaction.editReply({ content: 'Please provide a valid division ID.' });
return;
}
const thread = await fetchThread(division.url);
if (!thread) {
await interaction.reply({ content: 'Error. Re-add the division.' });
return;
}

const responseEmbed = await this.createCheckEmbed(division, thread);

await interaction.editReply({ embeds: [responseEmbed] });
}

public async chatInputCheckActive(interaction: Subcommand.ChatInputCommandInteraction) {
await interaction.deferReply();

const divisions = await this.divisionsRepository.find({
where: {
closesAt: MoreThan(new Date()),
},
order: {
closesAt: 'ASC'
}
})
if (divisions.length == 0) {
interaction.editReply('No divisions found.');
return;
}

const embeds = [];
for (const division of divisions) {
const thread = await fetchThread(division.url);
if (!thread) {
await interaction.reply({ content: `Error. Re-add the division ${division.shortName}.` });
return;
}
const responseEmbed = await this.createCheckEmbed(division, thread);
embeds.push(responseEmbed);
}


await interaction.editReply({ embeds: embeds });
}
}
2 changes: 1 addition & 1 deletion src/entity/Division.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export class Division {

public get directive(): string {
if (this.freeVote) return "Free Vote";
else return `${this.whipLine} line ${this.whipVote.toUpperCase()}`
else return `${this.whipLine} Line ${this.whipVote.toUpperCase()}`
}

public get whipEmbed(): EmbedBuilder {
Expand Down
7 changes: 6 additions & 1 deletion src/reddit/Subreddit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ import { Thread } from "./Thread";
import { container } from "@sapphire/framework";
import { VoteComment } from "./VoteComment";
import { commentToVoteEnum } from "../utilities/Formatters";
import { AppDataSource } from "../data-source";
import { Member } from "../entity/Member";

const ignore: string[] = [
'AutoModerator'
];

const membersRepository = AppDataSource.getRepository(Member);

const api = new Snoowrap({
userAgent: 'Solidarity Whip Bot version 2.0.0',
clientId: process.env.REDDIT_CLIENT_ID,
Expand All @@ -32,6 +36,7 @@ export async function fetchThread(url: string) {
const thread = new Thread();
thread.id = id;
thread.url = url;
const memberUsernames = (await membersRepository.find()).map(member => member.redditUsername);

// Fill title and comments
try {
Expand All @@ -48,7 +53,7 @@ export async function fetchThread(url: string) {
// Comments
thread.comments = [];
response.comments.forEach(Comment => {
if (ignore.includes(Comment.author.name)) {
if ((ignore.includes(Comment.author.name)) || !(memberUsernames.includes(Comment.author.name))) {
return;
}
const voteEnum = commentToVoteEnum(Comment.body);
Expand Down
28 changes: 28 additions & 0 deletions src/reddit/Thread.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { AppDataSource } from "../data-source";
import { Member } from "../entity/Member";
import { ValidVotes } from "../enums/ValidVotes";
import { VoteComment } from "./VoteComment";

const membersRepository = AppDataSource.getRepository(Member);

export class Thread {
id: string;
shortName: string;
Expand All @@ -20,4 +25,27 @@ export class Thread {
// url = url;
// comments = comments;
// }

public getCommentsByVote(whip: ValidVotes) {
return this.comments.filter((vote) => vote.vote == whip).map(vote => vote.username);
}

public getAyes(): string[] {
return this.getCommentsByVote(ValidVotes.Aye);
}

public getNoes(): string[] {
return this.getCommentsByVote(ValidVotes.No);
}

public getAbstentions(): string[] {
return this.getCommentsByVote(ValidVotes.Abstain);
}

public async getMembersNotVoted() {
const memberUsernames = (await membersRepository.find()).map(member => member.redditUsername);
const haveVoted = this.comments.map(comment => comment.username);
const notVoted = memberUsernames.filter(username => !haveVoted.some(voted => username === voted));
return notVoted;
}
}
10 changes: 7 additions & 3 deletions src/reddit/VoteComment.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { ValidVotes } from "../enums/ValidVotes";

export class VoteComment {
constructor(
username: string, vote: ValidVotes
) {}
public username: string;
public vote: ValidVotes;

public constructor(username: string, vote: ValidVotes) {
this.username = username;
this.vote = vote;
}
}
3 changes: 3 additions & 0 deletions src/utilities/ImportUsername.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
interface ImportUsername {
username: string
}

0 comments on commit 3d46b3f

Please sign in to comment.