Отправляйте уведомления пользователям каждый час с Bot Framework NodeJS - PullRequest
2 голосов
/ 17 апреля 2020

Я занимаюсь разработкой бота, который каждый час отправляет пользователям сообщение по скайпу. Он выполняет вызов API, а затем отправляет сообщение, содержащее проанализированное сообщение. Я начал с образца welcomebot. Затем я использовал оператор switch, чтобы запустить setInterval() для отправки активности сообщения, когда пользователь отправляет определенное сообщение, но сообщение продолжает отправляться даже после того, как я вызываю clearinterval() Я установил другую строку. Как я могу заставить clearInterval() работать? Или я поступаю неправильно?

Индекс. js:

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

// Import required packages
const path = require('path');
const restify = require('restify');
const axios = require('axios');

// Import required bot services.
// See https://aka.ms/bot-services to learn more about the different parts of a bot.
const { BotFrameworkAdapter, UserState, ConversationState, MemoryStorage } = require('botbuilder');

const { WelcomeBot } = require('./bots/welcomeBot');

// Read botFilePath and botFileSecret from .env file
const ENV_FILE = path.join(__dirname, '.env');
require('dotenv').config({ path: ENV_FILE });

// Create bot adapter.
// See https://aka.ms/about-bot-adapter to learn more about bot adapter.
const adapter = new BotFrameworkAdapter({
    appId: process.env.MicrosoftAppID,
    appPassword: process.env.MicrosoftAppPassword
});

// Catch-all for errors.
adapter.onTurnError = async (context, error) => {
    // This check writes out errors to console log .vs. app insights.
    // NOTE: In production environment, you should consider logging this to Azure
    //       application insights.
    console.error(`\n [onTurnError] unhandled error: ${ error }`);

    // Send a trace activity, which will be displayed in Bot Framework Emulator
    await context.sendTraceActivity(
        'OnTurnError Trace',
        `${ error }`,
        'https://www.botframework.com/schemas/error',
        'TurnError'
    );

    // Send a message to the user
    await context.sendActivity('The bot encountered an error or bug.');
    await context.sendActivity('To continue to run this bot, please fix the bot source code.');
};

// Define a state store for your bot. See https://aka.ms/about-bot-state to learn more about using MemoryStorage.
// A bot requires a state store to persist the dialog and user state between messages.

// For local development, in-memory storage is used.
// CAUTION: The Memory Storage used here is for local bot debugging only. When the bot
// is restarted, anything stored in memory will be gone.
const memoryStorage = new MemoryStorage();
const userState = new UserState(memoryStorage);
const conversationState = new ConversationState(memoryStorage);

// Create the main dialog.
const conversationReferences = {};
const bot = new WelcomeBot(userState, conversationReferences, conversationState);

// Create HTTP server
const server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function() {
    console.log(`\n${ server.name } listening to ${ server.url }`);
    console.log('\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator');
    console.log('\nTo talk to your bot, open the emulator select "Open Bot"');
});

// Listen for incoming activities and route them to your bot main dialog.
server.post('/api/messages', (req, res) => {
    adapter.processActivity(req, res, async (context) => {
        // route to main dialog.
        await bot.run(context);
    });
});
const getBalance = async () => {
    try {
        return await axios.get('https://balance.com/getbalance', { //this returns a json object
            headers: {
                Authorization: xxxxx
            }
        });
    } catch (error) {
        console.error(error);
    }
};
const retrieveBalance = async () => {
    const balance = await getBalance();
    if (balance.data.message) {
        for (const conversationReference of Object.values(conversationReferences)) {
            await adapter.continueConversation(conversationReference, async turnContext => {
                // If you encounter permission-related errors when sending this message, see
                // https://aka.ms/BotTrustServiceUrl
                await turnContext.sendActivity(balance.data.message);
            });
        }
    }
};

module.exports.retrieveBalance = retrieveBalance;

Бот. js:

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

// Import required Bot Framework classes.
const { ActionTypes, ActivityHandler, CardFactory, TurnContext } = require('botbuilder');
const balance = require('../index.js');
// Welcomed User property name
const CONVERSATION_DATA_PROPERTY = 'conversationData';

class WelcomeBot extends ActivityHandler {
    /**
     *
     * @param {UserState}  //state to persist boolean flag to indicate
     *                    if the bot had already welcomed the user
     */
    constructor(userState, conversationReferences, conversationState) {
        super();
        // Creates a new user property accessor.
        // See https://aka.ms/about-bot-state-accessors to learn more about the bot state and state accessors.
        this.userState = userState;
        this.conversationReferences = conversationReferences;
        this.conversationDataAccessor = conversationState.createProperty(CONVERSATION_DATA_PROPERTY);

        // The state management objects for the conversation and user state.
        this.conversationState = conversationState;

        this.onConversationUpdate(async (context, next) => {
            this.addConversationReference(context.activity);

            await next();
        });

        this.onMessage(async (context, next) => {
            this.addConversationReference(context.activity);
            // Add message details to the conversation data.
            // Display state data.
            // Read UserState. If the 'DidBotWelcomedUser' does not exist (first time ever for a user)
            // set the default to false.
            // const didBotWelcomedUser = await this.welcomedUserProperty.get(context, false);

            // Your bot should proactively send a welcome message to a personal chat the first time
            // (and only the first time) a user initiates a personal chat with your bot.
            // if (didBotWelcomedUser === false) {
            //     // The channel should send the user name in the 'From' object
            //     await context.sendActivity( 'This bot will send you your paystack balance every 5 minutes. To agree reply \'ok\'');
            //     // Set the flag indicating the bot handled the user's first message.
            //     await this.welcomedUserProperty.set(context, true);
            // }
            // This example uses an exact match on user's input utterance.
            // Consider using LUIS or QnA for Natural Language Processing.
            var text = context.activity.text.toLowerCase();
            var myint;
            switch (text) {
            case 'ok':
                myint = setInterval(async () => {
                    await balance.retrieveBalance();
                }, 1000);
                // eslint-disable-next-line template-curly-spacing
                break;
            case 'balance':
                await balance.retrieveBalance();
                break;
            case 'no':
                clearInterval(myint);
                break;
            case 'hello':
            case 'hi':
                await context.sendActivity(`You said "${ context.activity.text }"`);
                break;
            case 'info':
            case 'help':
                await this.sendIntroCard(context);
                break;
            default:
                await context.sendActivity('This is a simple notification bot. ');
            }

            // By calling next() you ensure that the next BotHandler is run.
            await next();
        });

        // Sends welcome messages to conversation members when they join the conversation.
        // Messages are only sent to conversation members who aren't the bot.
        this.onMembersAdded(async (context, next) => {
            // Iterate over all new members added to the conversation
            for (const idx in context.activity.membersAdded) {
                // Greet anyone that was not the target (recipient) of this message.
                // Since the bot is the recipient for events from the channel,
                // context.activity.membersAdded === context.activity.recipient.Id indicates the
                // bot was added to the conversation, and the opposite indicates this is a user.
                if (context.activity.membersAdded[idx].id !== context.activity.recipient.id) {
                    await context.sendActivity('Welcome to the Nag Bot. If you want to get nagged with your balance type \'ok\', if you want your balance alone type \'balance. for info type \'info\'');
                }
            }

            // By calling next() you ensure that the next BotHandler is run.
            await next();
        });
    }

    /**
     * Override the ActivityHandler.run() method to save state changes after the bot logic completes.
     */
    async run(context) {
        await super.run(context);

        // Save state changes
        await this.userState.saveChanges(context);
        await this.conversationState.saveChanges(context, false);
    }

    addConversationReference(activity) {
        const conversationReference = TurnContext.getConversationReference(activity);
        this.conversationReferences[conversationReference.conversation.id] = conversationReference;
    }

    async sendIntroCard(context) {
        const card = CardFactory.heroCard(
            'Welcome to Nag Bot balance checker!',
            'Welcome to Paystack Nagbot.',
            ['https://aka.ms/bf-welcome-card-image'],
            [
                {
                    type: ActionTypes.OpenUrl,
                    title: 'Open your dashboard',
                    value: 'https://dashboard.paystack.com'
                },
                {
                    type: ActionTypes.OpenUrl,
                    title: 'Ask a question on twitter',
                    value: 'https://twitter.com/paystack'
                },
                {
                    type: ActionTypes.OpenUrl,
                    title: 'View docs',
                    value: 'https://developers.paystack.co/reference'
                }
            ]
        );

        await context.sendActivity({ attachments: [card] });
    }
}

module.exports.WelcomeBot = WelcomeBot;
...