Commit c168f88d by Oleksandr Barabash

pagination added

added version to the app.zip
.gitignore updated
minor fixes on translation strings
help command updated, channel id and tenant id added
version bumped to 1.1.188
app generator updated, reflects version now in the manifest.
parent 031916c5
......@@ -2,3 +2,5 @@
__pycache__/
**.pyc
.venv
.DS_Store
**/.DS_Store
......@@ -80,12 +80,19 @@ async def v1_get_initiations(request: Request) -> Response:
""" Get Initiations by Notification ID """
# noinspection PyBroadException
try:
token = request.query.get("token") or None
notification_id = request.match_info['notification_id']
inits = await COSMOS_CLIENT.get_initiation_items(notification_id)
data = dict(data=[dict(initiator=init.initiator,
timestamp=init.timestamp,
id=init.id) for init in inits])
return Response(body=json.dumps(data), status=HTTPStatus.OK)
init_items, next_token = await COSMOS_CLIENT.get_initiation_items(
notification_id, token
)
data = dict(initiators=[dict(initiator=i.initiator,
timestamp=i.timestamp,
id=i.id) for i in init_items])
if next_token is not None:
data.update(dict(token=next_token))
body = dict(status=dict(message="OK", code=200), data=data)
return Response(body=json.dumps(body), status=HTTPStatus.OK)
except ItemNotFound:
Log.e(TAG, "v1_get_initiations::item not found", sys.exc_info())
return Response(status=HTTPStatus.NOT_FOUND)
......@@ -104,7 +111,7 @@ async def v1_get_notification(request: Request) -> Response:
acks = await COSMOS_CLIENT.get_acknowledge_items(notification_id)
data = dict(data=dict(
timestamp=notification.timestamp,
status="DELIVERED",
status="DELIVERED", # TODO(s1z): insert a real status value pls!
acknowledged=[dict(username=ack.username,
timestamp=ack.timestamp) for ack in acks],
))
......@@ -118,7 +125,7 @@ async def v1_get_notification(request: Request) -> Response:
@TOKEN_HELPER.is_auth
async def v1_notification(request: Request) -> Response:
async def v1_post_notification(request: Request) -> Response:
""" Notify channel with the link """
# noinspection PyBroadException
try:
......@@ -176,8 +183,11 @@ async def v1_health_check(_request: Request) -> Response:
async def get_app_zip(_request: Request) -> FileResponse:
""" Get zip file """
from config import APP_VERSION
filename = f"app_{APP_VERSION}.zip"
headers = {"Content-Disposition": f'inline; filename="{filename}"'}
await TeamsAppGenerator.generate_zip()
return FileResponse(path=TeamsAppConfig.zip_file)
return FileResponse(path=TeamsAppConfig.zip_file, headers=headers)
@web.middleware
......@@ -245,7 +255,7 @@ async def app_factory(bot):
app = web.Application(middlewares=[error_middleware])
app.router.add_post("/api/v1/messages", v1_messages)
app.router.add_post("/api/v1/notification", v1_notification)
app.router.add_post("/api/v1/notification", v1_post_notification)
app.router.add_get("/api/v1/notification/{notification_id}",
v1_get_notification)
app.router.add_get("/api/v1/initiations/{notification_id}",
......
......@@ -9,7 +9,7 @@
{
"type": "TextBlock",
"wrap": true,
"text": "Open task module card"
"text": "Open secured portal"
}
]
},
......
......@@ -10,18 +10,26 @@ en:
Use '%{cmd_help}' command for more info.
tenant_forbidden: |
Sorry, you dont have rights to communicate with this bot from your tenant.
Sorry, you do not have permission to communicate with this bot from your tenant.
unknown_request: |
This requires is not supported.
This request is not supported.
cmd_help: help
cmd_portal: portal
portal_text: Open secured portal
portal_button_text: Open secured portal
response_help: |
This is a help response.
Conversation ID: %{conversation_id}.
Tenant ID: %{tenant_id}
Supported commands:
%{cmd_help} - this command
%{cmd_portal} - request secured portal window.
response_unknown_cmd: |
Unknown command received.
Send "Help" to get the list of awailable commands.
Use '%{cmd_help}' command for more info.
......@@ -210,11 +210,24 @@ class TeamsMessagingExtensionsActionPreviewBot(TeamsActivityHandler):
message = turn_context.activity.text.strip().lower()
if message == i18n.t("cmd_help"):
await turn_context.send_activity(i18n.t("response_help"))
cmd_help = i18n.t("cmd_help")
cmd_portal = i18n.t("cmd_help")
if message == cmd_help.lower():
tenant_id = turn_context.activity.conversation.tenant_id
conversation_id = turn_context.activity.conversation.id
response = await turn_context.send_activity(
i18n.t("response_help",
cmd_portal=cmd_portal,
cmd_help=cmd_help,
tenant_id=tenant_id,
conversation_id=conversation_id)
)
Log.d(TAG, "on_message_activity::help_resp: {}".format(response))
return
if message == i18n.t("cmd_portal"):
if message == cmd_portal.lower():
card = CardHelper.load_portal_card(turn_context)
card = CardHelper.load_assets_card("default_card")
attachments = [CardFactory.adaptive_card(card)]
message = Activity(type=ActivityTypes.message,
......@@ -222,7 +235,8 @@ class TeamsMessagingExtensionsActionPreviewBot(TeamsActivityHandler):
await turn_context.send_activity(message)
return
await turn_context.send_activity(i18n.t("response_unknown_cmd"))
await turn_context.send_activity(i18n.t("response_unknown_cmd",
cmd_help=cmd_help))
async def on_mx_task_unsupported(self, turn_context: TurnContext) \
-> TaskModuleResponse:
......
......@@ -13,6 +13,9 @@ CARDS_PATH = os.path.join(ASSETS_PATH, "cards")
STRINGS_PATH = os.path.join(ASSETS_PATH, "strings")
APP_VERSION = "1.1.188"
class Auth:
""" Auth type """
class Types:
......
import os
from typing import Dict, Any, Optional, Mapping, Union
from botbuilder.core import TurnContext
from config import CARDS_PATH
from entities.json.notification import NotificationCosmos
from utils.functions import get_i18n
from utils.json_func import json_loads
......@@ -15,12 +18,27 @@ class CardHelper:
@staticmethod
def load_assets_card(name: str) -> Union[dict[str, Any],
Mapping[str, Any]]:
""" 123 """
""" Load a card from assets """
filename = name + ".json" if name.find(".json") < 0 else name
filename_path = os.path.join(CARDS_PATH, filename)
with open(filename_path, "r") as f:
card_data = f.read()
return json_loads(card_data)
card_json = json_loads(card_data)
return card_json
@staticmethod
def load_portal_card(turn_context: TurnContext) -> \
Union[dict[str, Any], Mapping[str, Any]]:
""" Load portal card """
u18n = get_i18n(turn_context)
# TODO(s1z): Change this crap please and create a constructor!
portal_card = CardHelper.load_assets_card("default_card")
portal_card["body"][0]["items"][0]["text"] = u18n.t("portal_text")
portal_card["body"][1]["items"][0]["actions"][0]["title"] = u18n.t(
"portal_button_text"
)
return portal_card
@staticmethod
def create_notification_card(notification: NotificationCosmos,
......
......@@ -3,7 +3,7 @@ import asyncio
import sys
import uuid
from concurrent import futures
from typing import Any, Dict, Optional, Union, List
from typing import Any, Dict, Optional, Union, List, Tuple
import azure.cosmos.cosmos_client as cosmos_client
import azure.cosmos.exceptions as exceptions
......@@ -22,6 +22,9 @@ from entities.json.notification import NotificationCosmos
from utils.log import Log
TAG = __name__
class CosmosClientException(Exception):
""" Cosmos Client base exception """
def __init__(self, message: str):
......@@ -112,26 +115,38 @@ class CosmosClient:
return await self.execute_blocking(bl)
async def get_initiation_items(self, notification_id) -> List[Initiation]:
async def get_initiation_items(self, notification_id,
token=None) -> Tuple[List[Initiation], str]:
""" Get Initiation Items """
container = await self.get_initiation_container()
def bl() -> List[Dict[str, Any]]:
def bl() -> Tuple[List[Dict[str, Any]], str]:
""" Potential blocking code """
# noinspection SqlDialectInspection,SqlNoDataSourceInspection
continuation_token = token
items = []
for item in container.query_items(
query_iterable = container.query_items(
query="SELECT * FROM r "
"WHERE r.notificationId=@notification_id "
"ORDER BY r._ts",
parameters=[
{"name": "@notification_id", "value": notification_id},
],
partition_key=notification_id
):
items.append(item)
return Initiation.get_schema(unknown=EXCLUDE).load(items,
many=True)
partition_key=notification_id,
max_item_count=1
)
if continuation_token is not None:
pager = query_iterable.by_page(token)
else:
pager = query_iterable.by_page()
current_page = list(pager.next())[0]
items.append(current_page)
continuation_token = pager.continuation_token
return (
Initiation.get_schema(unknown=EXCLUDE).load(items, many=True),
continuation_token
)
return await self.execute_blocking(bl)
......
......@@ -5,12 +5,12 @@ import os
from urllib.parse import urlparse
from zipfile import ZipFile, ZIP_DEFLATED
from config import AppConfig, TeamsAppConfig, TaskModuleConfig
from config import AppConfig, TeamsAppConfig, TaskModuleConfig, APP_VERSION
from utils.json_func import json_loads
manifest = {
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.14/MicrosoftTeams.schema.json",
"version": "1.0.0",
# "version": "1.0.0",
"manifestVersion": "1.14",
# "id": "THIS IS AN APP SERVICE ID",
# "packageName": "net.azurewebsites.bot-name",
......@@ -78,6 +78,7 @@ class TeamsAppGenerator:
@staticmethod
def gen_manifest():
""" Generate manifest """
manifest.update(dict(version=APP_VERSION))
# ID
manifest.update(dict(id=AppConfig.CLIENT_ID))
# Package name
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment