1
votes

I am trying to run an Microsoft Teams BOT as an Azure Web App - complete code can be found here

application.py:

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

import sys
import traceback
from datetime import datetime

from aiohttp import web
from aiohttp.abc import HTTPException
from aiohttp.web import Request, Response, json_response
from botbuilder.core import (BotFrameworkAdapterSettings, TurnContext, BotFrameworkAdapter, )
from botbuilder.core.integration import aiohttp_error_middleware
from botbuilder.schema import Activity, ActivityTypes

from bots import EchoBot
from config import DefaultConfig

CONFIG = DefaultConfig()

# Create adapter.
# See https://aka.ms/about-bot-adapter to learn more about how bots work.
SETTINGS = BotFrameworkAdapterSettings(CONFIG.APP_ID, CONFIG.APP_PASSWORD)
ADAPTER = BotFrameworkAdapter(SETTINGS)


# Catch-all for errors.
async def on_error(context: TurnContext, error: Exception):
    # This check writes out errors to console log .vs. app insights.
    # NOTE: In production environment, you should consider logging this to Azure
    #       application insights.
    print(f"\n [on_turn_error] unhandled error: {error}", file=sys.stderr)
    traceback.print_exc()

    # Send a message to the user
    await context.send_activity("The bot encountered an error or bug.")
    await context.send_activity(
        "To continue to run this bot, please fix the bot source code."
    )
    # Send a trace activity if we're talking to the Bot Framework Emulator
    if context.activity.channel_id == "emulator":
        # Create a trace activity that contains the error object
        trace_activity = Activity(
            label="TurnError",
            name="on_turn_error Trace",
            timestamp=datetime.utcnow(),
            type=ActivityTypes.trace,
            value=f"{error}",
            value_type="https://www.botframework.com/schemas/error",
        )
        # Send a trace activity, which will be displayed in Bot Framework Emulator
        await context.send_activity(trace_activity)


ADAPTER.on_turn_error = on_error

# Create the Bot
BOT = EchoBot()


# Listen for incoming requests on /api/messages
async def messages(req: Request) -> Response:
    # Main bot message handler.
    if "application/json" in req.headers["Content-Type"]:
        body = await req.json()
    else:
        return Response(status=415)

    activity = Activity().deserialize(body)
    auth_header = req.headers["Authorization"] if "Authorization" in req.headers else ""

    response = await ADAPTER.process_activity(activity, auth_header, BOT.on_turn)

    if response:
        return json_response(data=response.body, status=response.status)
    return Response(status=201)

APP = web.Application(middlewares=[aiohttp_error_middleware])
APP.router.add_post("/api/messages", messages)
if __name__ == "__main__":


    try:
        web.run_app(APP, host="localhost", port=CONFIG.PORT)
    except Exception as error:
        raise error

When running locally I can set the port to 8000 for example, point ngrok to localhost and specify the url in my bot channels registration and everything works fine. I've been trying literally everything to get my code to work in Azure, but I just can't manage to get it done. I've configured the script to run on port 8000 and set the parameters in the application settings (I tried PORT and WEBSITES_PORT cause I've read that sometimes one of the Flags doesn't work: Application Settings on Azure

Still it says in logging:

Container mycontainer for site leobot-msbot has exited, failing site start ERROR - Container mycontainer didn't respond to HTTP pings on port: 8000, failing site start. See container logs for debugging.

I've also tried dozen of startup commands but I just can't figure it out. Edit: Found https://docs.microsoft.com/en-us/azure/app-service/containers/how-to-configure-python and added "python3.7 -m aiohttp.web -H localhost -P 8000 application:init_func" as startup command and changed the code to

def init_func(argv):
    APP = web.Application(middlewares=[aiohttp_error_middleware])
    APP.router.add_post("/api/messages", messages)
    return APP
if __name__ == "__main__":
    APP = init_func(None)

    try:
        web.run_app(APP, host="localhost", port=CONFIG.PORT)
    except Exception as error:
        raise error

then in the log it says -> see picture :log extract ... OSError: [Errno 99] error while attempting to bind on address ('::1', 8000, 0, 0): cannot assign requested address

Maybe someone has experience with that and can help me :)

1
How are you running your script locally from terminal and what did you do so it runs that command on Azure?Tin Nguyen
@TinNguyen Locally I just run the application.py file... the code is deployed via GitHub to the Azure Web App using Deployment Center. I've also thought about the missing information to tell Azure what file to execute... Any idea how to do that ? Thanks for your helpjackygeee

1 Answers

1
votes

So after struggling with setting up my Bot for 2 days, I've finally found the answer. With the help of this article and this article from Microsoft.

Under Settings-Configuration I added the startup command

python3.7 -m aiohttp.web -H 0.0.0.0 -P 8000 application:init_func

Important here is to do not use localhost but 0.0.0.0 !

In my application.py file, I added a init func as mentioned earlier and changed the code to

def init_func(argv):
    APP = web.Application(middlewares=[aiohttp_error_middleware])
    APP.router.add_post("/api/messages", messages)
    return APP
if __name__ == "__main__":
    APP = init_func(None)

    try:
        web.run_app(APP, host="0.0.0.0", port=CONFIG.PORT)
    except Exception as error:
        raise error