Skip to content

Commit

Permalink
Implement basic logic for 'subscribe' buttons
Browse files Browse the repository at this point in the history
only from memory for now
  • Loading branch information
manuartero committed Jan 27, 2021
1 parent 8225ba3 commit 87dbe34
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 45 deletions.
38 changes: 25 additions & 13 deletions config/bot.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
cards:
menu:
- title: Label 1
text: key1
- title: Label a
text: key2
- title: Label b
text: key3
- title: Label c
text: key4
- title: Label d
text: key5
- title: Label e
text: key6
welcomeCard:
title: Private Notifications Center
text: Lorem Ipsum

unknownCard:
title: ""
text: Unknown command...

menuCard:
title: Available Options
checkButton:
title: CHECK my subscribed topics 🧾
value: CHECK
resetButton:
title: RESET all my subscribed topics ❌
value: RESET
subscriptionButtons:
- title: Subscribe to LATAM notifications 🇦🇷
value: LATAM
- title: Subscribe to UK notifications 🇬🇧
value: UK
- title: Subscribe to SPAIN notifications 🇪🇸
value: SPAIN
- title: Subscribe to GERMANY notifications 🇩🇪
value: GERMANY
50 changes: 28 additions & 22 deletions src/bot.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,19 @@ const { readYaml } = require('./yaml')
const { log } = require('./log')

/**
* @param {string} rawText
* @param {Types.Storage} storage
*/
// eslint-disable-next-line no-unused-vars
const getKeyword = rawText => {
const text = rawText.trim().toLocaleLowerCase()
/* if chain */
if (text.includes('a')) {
return 'a'
}
return undefined
}

const createBot = conversationReferences => {
const createBot = storage => {
const bot = new ActivityHandler()
const config = readYaml('bot')
const cards = prepareCards({ config })
log.info('[STARTUP]', 'bot.yaml config read')

/**
* A party (including the bot) joins or leaves a conversation
*/
bot.onConversationUpdate(async (context, next) => {
await context.sendTraceActivity('onConversationUpdate', context.activity)
conversationReferences.add(context.activity)
storage.add(context.activity)
await next()
})

Expand All @@ -38,9 +28,7 @@ const createBot = conversationReferences => {
const membersAdded = context.activity.membersAdded
for (let cnt = 0; cnt < membersAdded.length; cnt++) {
if (membersAdded[cnt].id !== context.activity.recipient.id) {
const welcomeMessage =
'Welcome to the Proactive Bot sample. Navigate to http://localhost:3978/api/notify to proactively message everyone who has previously messaged this bot.'
await context.sendActivity(welcomeMessage)
await context.sendActivities([cards.welcomeCard(), cards.menuCard()])
}
}
await next()
Expand All @@ -50,15 +38,33 @@ const createBot = conversationReferences => {
* Main handler: Message activity received
*/
bot.onMessage(async (context, next) => {
conversationReferences.add(context.activity)

// const keyword = getKeyword(context.activity.text)
storage.add(context.activity)
const username = context.activity.from.name
const text = context.activity.text

await context.sendActivity(cards.menuCard())
const { check, reset, subscriptions } = cards.registeredKeywords()
if (text === check) {
const info = storage.readUser(username)
await context.sendActivity(JSON.stringify(info))
} else if (text === reset) {
// TODO
const info = storage.readUser(username)
await context.sendActivity(JSON.stringify(info))
} else if (subscriptions.indexOf(text) > -1) {
storage.subscribe(context.activity, text)
const info = storage.readUser(username)
await context.sendActivity(JSON.stringify(info))
} else {
await context.sendActivities([
cards.unknownCard(),
cards.menuCard()
])
}
await next()
})

log.info('[STARTUP] bot created and configured')
log.info('[STARTUP] bot ready')

return bot
}

Expand Down
44 changes: 38 additions & 6 deletions src/cards.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,51 @@ const { CardFactory, MessageFactory, ActionTypes } = require('botbuilder')

const asMessage = card => MessageFactory.attachment(card)

const simpleCard = ({ title, text }) => {
const card = CardFactory.heroCard(title, text)
return asMessage(card)
}

/**
* @param {import('botbuilder').CardAction[]} cardActions
*/
const addDefaultButton = (cardActions, { title, value }) => {
cardActions.push({
title,
value,
type: ActionTypes.ImBack
})
}

const prepareCards = ({ config }) => {
const menuCard = () => {
const cardActions = config.cards.menu.map(({ title, text }) => ({
const subscriptionButtons = config.cards.menuCard.subscriptionButtons
const cardActions = subscriptionButtons.map(({ title, value }) => ({
title,
text,
type: ActionTypes.MessageBack
value,
type: ActionTypes.ImBack
}))
const card = CardFactory.heroCard('title', 'text', null, cardActions)
return asMessage(card)
addDefaultButton(cardActions, config.cards.menuCard.checkButton)
addDefaultButton(cardActions, config.cards.menuCard.resetButton)
const title = config.cards.menuCard.title
const menuCard = CardFactory.heroCard(title, null, cardActions)
return asMessage(menuCard)
}

const registeredKeywords = () => {
const menu = config.cards.menuCard
return {
check: menu.checkButton.value,
reset: menu.resetButton.value,
subscriptions: menu.subscriptionButtons.map(({ value }) => value)
}
}

return {
menuCard
menuCard,
registeredKeywords,
welcomeCard: () => simpleCard(config.cards.welcomeCard),
unknownCard: () => simpleCard(config.cards.unknownCard)
}
}

Expand Down
44 changes: 40 additions & 4 deletions src/storage.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,51 @@
const { TurnContext } = require('botbuilder')
const { log } = require('./log')

const db = {}
/* memory object: playground */
const db = {
conversations: {},
users: {},
subscriptions: {}
}

const createStorage = () => {
return {
/**
* @param {Types.Activity} activity
*/
add: activity => {
const ref = TurnContext.getConversationReference(activity)
const id = ref.conversation.id
log.debug('[refs] updating conversation #%s', id)
db[id] = ref
const conversationId = ref.conversation.id
log.debug('[db] updating conversation #%s', conversationId)
db.conversations[conversationId] = ref
if (activity.from.role === 'user') {
const username = activity.from.name
log.debug('[db] updating user "%s"', username)
db.users[username] = conversationId
}
},
/**
* @param {Types.Activity} activity
* @param {string} topic
*/
subscribe: (activity, topic) => {
if (activity.from.role === 'user') {
const username = activity.from.name
log.debug('[db] updating <user-topic> pair: <%s, %s>', username, topic)
if (!db.subscriptions[username]) {
db.subscriptions[username] = []
}
db.subscriptions[username].push(topic)
}
},
readUser: username => {
log.debug('[db] reading info for user "%s"', username)
const conversationId = db.users[username]
return {
conversationId,
conversation: db.conversations[conversationId],
subscribedTo: db.subscriptions[username]
}
}
}
}
Expand Down
15 changes: 15 additions & 0 deletions types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
declare namespace Types {
type Activity = import("botbuilder").Activity;

interface Storage {
add: (activity: Activity) => void;
subscribe: (activity: Activity, topic: string) => void;
readUser: (
username: string
) => {
conversationId: string;
conversation: any;
subscribedTo: string[];
};
}
}

0 comments on commit 87dbe34

Please sign in to comment.