Skip to content

Commit

Permalink
Merge pull request #403 from meemproject/feature/custom-emoji
Browse files Browse the repository at this point in the history
Slack custom emoji
  • Loading branch information
kengoldfarb authored May 3, 2023
2 parents 59fe9c0 + 12973e1 commit 4fc98be
Show file tree
Hide file tree
Showing 10 changed files with 806 additions and 658 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"eslint.codeActionsOnSave.mode": "problems",
"cSpell.ignorePaths": [
"**/package-lock.json",
"**/node_modules/**",
Expand Down
40 changes: 29 additions & 11 deletions src/controllers/SlackController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,17 +305,6 @@ export default class SlackController {
const message = history.messages[0]
for (let i = 0; i < rules.length; i++) {
const rule = rules[i]
const isHandled = await services.rule.isMessageHandled({
agreementId: rule.AgreementId,
messageId: message.ts
})

if (isHandled) {
log.debug(
`Message w/ id ${message.ts} has already been handled`
)
return
}
await services.rule.processRule({
channelId: event.item.channel,
rule,
Expand Down Expand Up @@ -382,4 +371,33 @@ export default class SlackController {
challenge
})
}

public static async getEmojis(
req: IAuthenticatedRequest<MeemAPI.v1.GetSlackEmojis.IDefinition>,
res: IResponse<MeemAPI.v1.GetSlackEmojis.IResponseBody>
) {
const { agreementSlackId } = req.query
const agreementSlack = await orm.models.AgreementSlack.findOne({
where: {
id: agreementSlackId
},
include: [orm.models.Slack, orm.models.Agreement]
})

if (!agreementSlack || !agreementSlack.Slack || !agreementSlack.Agreement) {
throw new Error('SLACK_NOT_FOUND')
}

const isAdmin = await agreementSlack.Agreement.isAdmin(req.wallet.address)

if (!isAdmin) {
throw new Error('NOT_AUTHORIZED')
}

const emojis = await services.slack.getEmojis({
slack: agreementSlack.Slack
})

return res.json({ emojis })
}
}
5 changes: 5 additions & 0 deletions src/routers/symphonyRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ export default (app: Express, _express: typeof coreExpress) => {
router.getAsync('/twitter/auth', TwitterController.auth)
router.getAsync('/twitter/callback', TwitterController.callback)
router.getAsync('/slack/auth', SlackController.auth)
router.getAsync(
'/slack/emojis',
userLoggedInPolicy,
SlackController.getEmojis
)
router.getAsync('/slack/callback', SlackController.callback)
router.getAsync(
'/slack/channels',
Expand Down
12 changes: 0 additions & 12 deletions src/services/Discord.ts
Original file line number Diff line number Diff line change
Expand Up @@ -395,18 +395,6 @@ export default class Discord {
try {
log.debug('handleMessageReactionForAgreement')

const isHandled = await services.rule.isMessageHandled({
agreementId,
messageId: reaction.message.id
})

if (isHandled) {
log.debug(
`Message w/ id ${reaction.message.id} has already been handled`
)
return
}

log.debug(`Handling message for agreementId: ${agreementId}`)

const message = await reaction.message.channel.messages.fetch(
Expand Down
136 changes: 55 additions & 81 deletions src/services/Rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,42 +22,34 @@ export type IOModel =
| undefined

export default class RuleService {
public static async isMessageHandled(options: {
messageId?: string | null
agreementId?: string | null
}) {
const { agreementId, messageId } = options

const message = await orm.models.Message.findOne({
where: {
AgreementId: agreementId,
messageId
}
})

if (message) {
return true
}

return false
}

public static async processRule(options: {
channelId: string
rule: Rule
message: SlackMessage | DiscordMessage
}) {
const { channelId, rule, message } = options

const messageId =
(message as DiscordMessage).id ?? (message as SlackMessage).ts

const processedMessage = await orm.models.Message.findOne({
where: {
AgreementId: rule.AgreementId,
messageId
}
})

if (!rule.input || !rule.output) {
log.crit(`Rule ${rule.id} has no input or output`)
return
}

log.debug({ message })
if (processedMessage?.status === MeemAPI.MessageStatus.Handled) {
log.debug(`Message ${messageId} already handled`)
return
}

const messageId =
(message as DiscordMessage).id ?? (message as SlackMessage).ts
log.debug({ message })

let parentChannelId: string | undefined

Expand All @@ -70,7 +62,7 @@ export default class RuleService {
switch (rule.input) {
case MeemAPI.RuleIo.Slack:
{
const r = services.slack.countReactions({
const r = await services.slack.countReactions({
message: message as SlackMessage,
rule,
channelId
Expand Down Expand Up @@ -129,13 +121,8 @@ export default class RuleService {
totalVetoers
})

const { shouldPublish } = ruleResult
const { shouldMarkAsHandled } = ruleResult

// const ms = message as SlackMessage
// const md = message as DiscordMessage

// ms.attachments
const { shouldPublish, shouldMarkAsHandled, shouldMarkAsAwaitingApproval } =
ruleResult

if (shouldPublish) {
switch (rule.output) {
Expand Down Expand Up @@ -182,43 +169,6 @@ export default class RuleService {
partialResponse = services.discord.parseMessageForWebhook(
message as DiscordMessage
)
// const m = message as DiscordMessage
// partialResponse.messageId = m.id
// partialResponse.createdTimestamp = m.createdTimestamp
// m.reactions.cache.forEach(r => {
// if (r.emoji.name) {
// partialResponse.reactions.push({
// name: r.emoji.name,
// emoji: r.emoji.name,
// unicode: this.emojiToUnicode(r.emoji.name),
// count: r.count
// })
// }
// })

// partialResponse.user = {
// id: m.author.id,
// username: m.author.username
// }

// m.embeds.forEach(a => {
// attachments.push({
// url: a.url,
// name: a.title,
// description: a.description
// })
// })

// m.attachments?.forEach(a => {
// attachments.push({
// url: a.url,
// mimeType: a.contentType,
// width: a.width,
// height: a.height,
// name: a.name,
// description: a.description
// })
// })
} else if (typeof (message as SlackMessage).team === 'string') {
const m = message as SlackMessage
partialResponse.messageId = m.ts
Expand Down Expand Up @@ -342,17 +292,33 @@ export default class RuleService {
log.warn(`Output not supported for ${rule.output}`)
break
}
} else if (
shouldMarkAsAwaitingApproval &&
processedMessage?.status !== MeemAPI.MessageStatus.AwaitingApproval
) {
await this.sendInputReply({
rule,
channelId,
message,
content:
'This message has enough votes and is awaiting editor approval.'
})
} else {
log.debug('Not publishing for rule', { rule })
}

if (shouldMarkAsHandled) {
log.debug(`Marking message as handled: ${messageId}`)
if (shouldMarkAsAwaitingApproval || shouldMarkAsHandled) {
log.debug(`Marking message: ${messageId}`, {
shouldMarkAsHandled,
shouldMarkAsAwaitingApproval
})
await orm.models.Message.create({
AgreementId: rule.AgreementId,
messageId,
inputType: rule.input,
status: MeemAPI.MessageStatus.Handled
status: shouldMarkAsHandled
? MeemAPI.MessageStatus.Handled
: MeemAPI.MessageStatus.AwaitingApproval
})
}
}
Expand Down Expand Up @@ -428,6 +394,7 @@ export default class RuleService {
} = options
let shouldPublish = false
let shouldMarkAsHandled = false
let shouldMarkAsAwaitingApproval = false

if (
rule.definition.publishType === MeemAPI.PublishType.PublishImmediately &&
Expand All @@ -446,17 +413,23 @@ export default class RuleService {
MeemAPI.PublishType.PublishAfterApproval &&
(rule.definition.proposalChannels.includes(channelId) ||
rule.definition.proposalChannels.includes('all')) &&
totalApprovals >= rule.definition.votes &&
totalEditors &&
rule.definition.editorVotes &&
totalEditors >= rule.definition.editorVotes &&
(!rule.definition.canVeto ||
(rule.definition.vetoVotes && totalVetoers < rule.definition.vetoVotes))
totalApprovals >= rule.definition.votes
) {
log.debug('Rule matched publish after approval')
// Publish it
shouldPublish = true
shouldMarkAsHandled = true
if (
totalEditors &&
rule.definition.editorVotes &&
totalEditors >= rule.definition.editorVotes &&
(!rule.definition.canVeto ||
(rule.definition.vetoVotes &&
totalVetoers < rule.definition.vetoVotes))
) {
// Publish it
shouldPublish = true
shouldMarkAsHandled = true
} else {
shouldMarkAsAwaitingApproval = true
}
} else if (
rule.definition.publishType ===
MeemAPI.PublishType.PublishImmediatelyOrEditorApproval &&
Expand Down Expand Up @@ -506,7 +479,8 @@ export default class RuleService {

return {
shouldPublish,
shouldMarkAsHandled
shouldMarkAsHandled,
shouldMarkAsAwaitingApproval
}
}

Expand Down
Loading

0 comments on commit 4fc98be

Please sign in to comment.