This repository has been archived by the owner on Aug 26, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #221 from BanklessDAO/pre-release
Pre release
- Loading branch information
Showing
18 changed files
with
560 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { | ||
ApplicationCommandPermissionType, | ||
CommandContext, | ||
CommandOptionType, | ||
SlashCommand, | ||
SlashCreator, | ||
} from 'slash-create'; | ||
import roleIds from '../../service/constants/roleIds'; | ||
import ServiceUtils from '../../utils/ServiceUtils'; | ||
import CoordinapeSendForm from '../../service/coordinape/CoordinapeSendForm'; | ||
import ValidationError from '../../errors/ValidationError'; | ||
import discordServerIds from '../../service/constants/discordServerIds'; | ||
import { LogUtils } from '../../utils/Log'; | ||
|
||
module.exports = class Coordinape extends SlashCommand { | ||
constructor(creator: SlashCreator) { | ||
super(creator, { | ||
name: 'coordinape', | ||
description: 'Commands to manage Coordinape rounds', | ||
guildIDs: [discordServerIds.banklessDAO, discordServerIds.discordBotGarage], | ||
options: [ | ||
{ | ||
name: 'form-request', | ||
type: CommandOptionType.SUB_COMMAND, | ||
description: 'Send correct for to coordinape participants.', | ||
options: [], | ||
}, | ||
], | ||
throttling: { | ||
usages: 1, | ||
duration: 1, | ||
}, | ||
defaultPermission: false, | ||
permissions: { | ||
[discordServerIds.banklessDAO]: [ | ||
{ | ||
type: ApplicationCommandPermissionType.ROLE, | ||
id: roleIds.level2, | ||
permission: true, | ||
}, | ||
{ | ||
type: ApplicationCommandPermissionType.ROLE, | ||
id: roleIds.level1, | ||
permission: true, | ||
}, | ||
], | ||
[discordServerIds.discordBotGarage]: [ | ||
{ | ||
type: ApplicationCommandPermissionType.ROLE, | ||
id: roleIds.level2, | ||
permission: true, | ||
}, | ||
{ | ||
type: ApplicationCommandPermissionType.ROLE, | ||
id: roleIds.level1, | ||
permission: true, | ||
}, | ||
], | ||
}, | ||
}); | ||
} | ||
|
||
async run(ctx: CommandContext) { | ||
LogUtils.logCommandStart(ctx); | ||
if (ctx.user.bot) return; | ||
const { guildMember } = await ServiceUtils.getGuildAndMember(ctx); | ||
let command: Promise<any>; | ||
switch (ctx.subcommands[0]) { | ||
case 'form-request': | ||
command = CoordinapeSendForm(guildMember, ctx); | ||
break; | ||
default: | ||
return ctx.send(`${ctx.user.mention} Please try again.`); | ||
} | ||
|
||
this.handleCommandError(ctx, command); | ||
} | ||
|
||
handleCommandError(ctx: CommandContext, command: Promise<any>) { | ||
command.catch(e => { | ||
if (!(e instanceof ValidationError)) { | ||
LogUtils.logError('failed to handle coordinape command', e); | ||
return ctx.send('Sorry something is not working and our devs are looking into it'); | ||
} | ||
}); | ||
} | ||
|
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* eslint-disable no-console */ | ||
import { | ||
CommandContext, | ||
CommandOptionType, | ||
SlashCommand, | ||
SlashCreator, | ||
} from 'slash-create'; | ||
import ValidationError from '../../errors/ValidationError'; | ||
import ServiceUtils from '../../utils/ServiceUtils'; | ||
import Checkin from '../../service/timecard/Checkin'; | ||
import Checkout from '../../service/timecard/Checkout'; | ||
import Hours from '../../service/timecard/Hours'; | ||
import discordServerIds from '../../service/constants/discordServerIds'; | ||
import { LogUtils } from '../../utils/Log'; | ||
|
||
export default class Timecard extends SlashCommand { | ||
constructor(creator: SlashCreator) { | ||
super(creator, { | ||
name: 'timecard', | ||
description: 'Checkin, checkout, and calculate total hours', | ||
guildIDs: [process.env.DISCORD_SERVER_ID, discordServerIds.discordBotGarage], | ||
options: [ | ||
{ | ||
name: 'checkin', | ||
type: CommandOptionType.SUB_COMMAND, | ||
description: 'Initiate time card.', | ||
}, | ||
{ | ||
name: 'checkout', | ||
type: CommandOptionType.SUB_COMMAND, | ||
description: 'End and log timecard.', | ||
options: [ | ||
{ | ||
name: 'description', | ||
type: CommandOptionType.STRING, | ||
description: 'Brief description of what you are working on.', | ||
required: true, | ||
}, | ||
], | ||
}, | ||
{ | ||
name: 'hours', | ||
type: CommandOptionType.SUB_COMMAND, | ||
description: 'Calculate total hours worked.', | ||
}, | ||
], | ||
throttling: { | ||
usages: 2, | ||
duration: 1, | ||
}, | ||
defaultPermission: true, | ||
}); | ||
} | ||
|
||
async run(ctx: CommandContext): Promise<any> { | ||
LogUtils.logCommandStart(ctx); | ||
if (ctx.user.bot) return; | ||
|
||
const { guildMember } = await ServiceUtils.getGuildAndMember(ctx); | ||
let command: Promise<any>; | ||
|
||
try { | ||
switch (ctx.subcommands[0]) { | ||
case 'checkin': | ||
command = Checkin(guildMember, Date.now()); | ||
break; | ||
case 'checkout': | ||
command = Checkout(guildMember, Date.now(), ctx.options.checkout['description']); | ||
break; | ||
case 'hours': | ||
command = Hours(guildMember); | ||
break; | ||
default: | ||
return ctx.send(`${ctx.user.mention} Please try again.`); | ||
} | ||
this.handleCommandError(ctx, command); | ||
} catch (e) { | ||
console.error(e); | ||
} | ||
} | ||
|
||
handleCommandError(ctx: CommandContext, command: Promise<any>): void { | ||
command.then(() => { | ||
return ctx.send(`${ctx.user.mention} Sent you a DM with information.`); | ||
}).catch(e => { | ||
if (e instanceof ValidationError) { | ||
return ctx.send(e.message); | ||
} else { | ||
LogUtils.logError('failed to handle timecard command', e); | ||
return ctx.send('Sorry something is not working and our devs are looking into it.'); | ||
} | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// Mongosh operations to be done on database collections | ||
db.timecard.createIndex({ discordUserId: 1, isActive: 1, startTime: 1 }, { unique: true }); | ||
db.timecard.createIndex({ discordUserId: 1, duration: 1, discordServerId: 1 }, { unique: true }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
{ | ||
"$jsonSchema": { | ||
"bsonType": "object", | ||
"required": [ | ||
"discordUserId", | ||
"startTime", | ||
"endTime" | ||
], | ||
"properties": { | ||
"isActive": { | ||
"bsonType": "boolean", | ||
"description": "Indicates if the Timecard is active" | ||
}, | ||
"description": { | ||
"bsonType": "string", | ||
"description": "Brief description of what you are working on." | ||
}, | ||
"startTime": { | ||
"bsonType": ["string", "null"], | ||
"description": "ISO8601 of when the meeting started." | ||
}, | ||
"endTime": { | ||
"bsonType": ["string", "null"], | ||
"description": "ISO8601 of when the meeting ended." | ||
}, | ||
"duration": { | ||
"bsonType": ["number", "null"], | ||
"description": "Duration of the timecard session in minutes" | ||
}, | ||
"discordUserId": { | ||
"bsonType": "string", | ||
"description": "Discord Id of the user that initiated the Timecard." | ||
}, | ||
"discordServerId": { | ||
"bsonType": "string", | ||
"description": "Identifier for the discord guild where Timecard was activated" | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { DMChannel, GuildMember } from 'discord.js'; | ||
import { CommandContext } from 'slash-create'; | ||
import roleIds from '../constants/roleIds'; | ||
|
||
export default async (member: GuildMember, ctx?: CommandContext): Promise<any> => { | ||
ctx?.send(`Hi, ${ctx.user.mention}! I sent you a DM with more information.`); | ||
|
||
const dmChannel: DMChannel = await member.user.createDM(); | ||
|
||
if (member.partial) { | ||
member = await member.fetch(); | ||
} | ||
|
||
for (const role of member.roles.cache.values()) { | ||
if (role.id === roleIds.level1) { | ||
for (const role2 of member.roles.cache.values()) { | ||
if (role2.id === roleIds.level2) { | ||
await dmChannel.send({ content: 'Here is your form: <https://docs.google.com/forms/d/16qaDbz14C7d31pTZoOTRiDVShfzOimiwZlxUBit0Fmw/>' }); | ||
return; | ||
} | ||
} | ||
|
||
await dmChannel.send({ content: 'Here is your form: <https://docs.google.com/forms/d/1-_uHDxyWFjDD92hdujqsylZgLmTLLuUnbJDaMSUX_hY>' }); | ||
return; | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { GuildMember } from 'discord.js'; | ||
import { Db, Collection } from 'mongodb'; | ||
import dbInstance from '../../utils/dbUtils'; | ||
import constants from '../constants/constants'; | ||
import { Timecard } from '../../types/timecard.ts/Timecard'; | ||
import dayjs from 'dayjs'; | ||
import ValidationError from '../../errors/ValidationError'; | ||
|
||
export default async (guildMember: GuildMember, date: number): Promise<any> => { | ||
if (guildMember.user.id === null) { | ||
throw new ValidationError(`No guildMember <@${guildMember.id}>.`); | ||
} | ||
|
||
|
||
const timecard = { | ||
startTime: date, | ||
description: null, | ||
endTime: null, | ||
discordUserId: guildMember.user.id, | ||
discordServerId: guildMember.guild.id, | ||
isActive: true, | ||
}; | ||
|
||
const db: Db = await dbInstance.dbConnect(constants.DB_NAME_DEGEN); | ||
const timecardDb: Collection = await db.collection(constants.DB_COLLECTION_TIMECARDS); | ||
|
||
const activeTimecard: Timecard = await timecardDb.findOne({ | ||
discordUserId: guildMember.user.id, | ||
discordServerId: guildMember.guild.id, | ||
isActive: true, | ||
}); | ||
|
||
if (activeTimecard) { | ||
await guildMember.send('You already have an active timecard. Close out the active timecard with /timecard checkout then start a new one.'); | ||
return 'already checked in'; | ||
} | ||
|
||
const dbCheckin = await timecardDb.insertOne(timecard); | ||
await guildMember.send(`Timecard started at ${dayjs(date).format()}`); | ||
return dbCheckin; | ||
}; | ||
|
Oops, something went wrong.