I need help to debug my problem to resume execution of a step function after receiving the user choice submitted through an api gateway. My scenario is :
1- the step function is fired by an Iam event (policy creation)
2- The second step is a lambda function that sends an email to the user through sns to request an approval. The email contains an url with a Token generated by the step function at the AskUser state.
3- The step function wait the response
4- The user makes his choice
5- The api gateway receive the response and fire a lambda funtcion ReceiveUserResponse
6- ReceiveUserResponse parse the event token and try to resume the stepfunction
Unfortunately, my step function is not resumed and continue to wait indefinitely. I verified that the token is parsed and continue the same value reveived in the first email. The error returned is InvalidToken. There is my Pyhton code:
import os
import boto3
import botocore
import json, string, random
from botocore.exceptions import ClientError
sns_client = boto3.client('sns')
stf_client = boto3.client('stepfunctions')
def lambda_handler(event, context):
TopicArn= os.environ.get('Topic')
token=event['queryStringParameters']['token']
Message_url= 'The message has been returned with the token= '+token
try:
response = stf_client.send_task_success(
taskToken=token,
output=str({'action': 'allow'})
)
except ClientError as error:
print(type(token))
print(str(error))
Message_url1= 'An to execute send_task_sucess error with this token= '+token
response = sns_client.publish (
TargetArn = 'arn:aws:sns:us-east-1:269252182839:sam-app-AlertTopic-11K3SI14PNOT',
Message = json.dumps({'default': Message_url1}),
MessageStructure = 'json'
)
response = sns_client.publish (
TargetArn = 'arn:aws:sns:us-east-1:269252182839:sam-app-AlertTopic-11K3SI14PNOT',
Message = json.dumps({'default': Message_url}),
MessageStructure = 'json'
)
return {
'statusCode': 200,
'body': json.dumps({'input': 'allow'})
}
Do you have any solution to handle with this error?
Thanks!
Related
I try to fetch data from my api in python using pyscript. Following the pyscript documentation I use the async keyword on my main function and use asyncio.ensure_future to execute it, everything before the first await work but not the await keyword and any other line of code after it.
This is my code:
async def request(url: str,
method: str = "GET",
body: Optional[str] = None,
headers: Optional[dict[str, str]] = None,
**fetch_kwargs: Any) -> FetchResponse:
kwargs = {
"method": method,
"mode": "no-cors"
} # CORS: https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
if body and method not in ["GET", "HEAD"]:
kwargs["body"] = body
if headers:
kwargs["headers"] = headers
kwargs.update(fetch_kwargs)
response = await pyfetch(url, **kwargs)
return response
async def get_barycenter(
filename: str,
base_url: str = "http://localhost:8001") -> dict[str, Any] | None:
headers = {"Content-type": "application/json"}
response = await request(f"{base_url}/barycenter/?image_name={filename}",
headers=headers)
body = await response.json()
if body.status != 200:
return None
return body.msg
async def main():
print('start')
test = await get_barycenter("img.jpg")
print(test)
print("end")
asyncio.ensure_future(main())
The result is only the print of start and nothing else no print of test are even "end".
I tested the API the data is visible in Insomnia and I set up correctly the cors Policy.
Part of the issue here is an existing issue in PyScript where exceptions raised in Coroutines aren't displayed on the page. To help with this for now, I would recommend adding the following snippet before your request function:
import js
def handler(loop, context):
js.console.error(context.message)
raise(context.exception)
pyscript.loop.set_exception_handler(handler)
This way, exceptions raised in coroutines are displayed in the browser's console log.
What the root issue of the the fetch request is I couldn't say, but at least this will get errors displaying and help you troubleshoot. For example, when I run your code, I see:
GET http://localhost:8001/barycenter/?image_name=img.jpg net::ERR_CONNECTION_REFUSED
Since I don't have a local server running - hopefully the errors that appear for you are more helpful.
I just want to send message to particular group via async to sync,
Here is my consumers file
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatRoomConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.chat_box_name = self.scope["url_route"]["kwargs"]["chat_box_name"]
self.group_name = "chat_%s" % self.chat_box_name
await self.channel_layer.group_add(self.group_name, self.channel_name)
await self.accept()
async def disconnect(self, close_code):
await self.channel_layer.group_discard(self.group_name, self.channel_name)
# This function receive messages from WebSocket.
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json["message"]
username = text_data_json["username"]
await self.channel_layer.group_send(
self.group_name,
{
"type": "chatbox_message",
"message": message,
"username": username,
},
)
# Receive message from room group.
async def chatbox_message(self, event):
message = event["message"]
username = event["username"]
#send message and username of sender to websocket
await self.send(
text_data=json.dumps(
{
"message": message,
"username": username,
}
)
)
async def chat_message(self, event):
message = event["message"]
# Send message to WebSocket
await self.send(text_data=json.dumps({"message": message}))
And this is my code for sending message to specific group
import channels.layers
from asgiref.sync import async_to_sync
channel_layer = channels.layers.get_channel_layer()
async_to_sync(channel_layer.group_send)("chat_groupone", {"type": "chatbox_message","message":"STOP","username":"admin"})
I don't know what i am doing wrong in this, it returns me none without any error
I am expecting by running this code, group should have recieved the message
Version-
Django- 4.0
channels - 3.0.4
python - 3.9
I'm attempting to invoke an AWS Lambda Function URL in Python. Using their example lambda code as follows the value for action is always returning null. How do I access the value in the json data I POST to the Function URL?
Lambda Code (taken from here):
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
result = None
action = event.get('action')
if action == 'increment':
result = event.get('number', 0) + 1
logger.info('Calculated result of %s', result)
else:
logger.error("%s is not a valid action.", action)
response = {'result': result}
return response
Invoking using a Function URL
curl -X POST 'https://[redacted].lambda-url.eu-west-1.on.aws/' -d '{"action":"increment","number": 3}'
Result:
{"result":null}
Problem:
How do I reference the value of 'action' correctly to produce the result?
Out of interest, this is how I adapted the AWS sample code to parse the required fields
import logging
import json
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
message = json.loads(event['body'])
result = None
action = message['action']
if action == 'increment':
result = message['number'] + 1
logger.info('Calculated result of %s', result)
else:
logger.error("%s is not a valid action.", action)
response = {'result': result}
return response
I know there is a method to get a member's id for example from the same guild, but can you do this if the member is not in the same server with the bot?
The answer is yes, yes you can, even when the bot isn't mutually on the server that the user is in.
I made a function for it.
import requests
import os
def find_user(id_of_user):
payload = {}
headers = {"Authorization": "Bot " + os.getenv("BOT_TOKEN")}
response = requests.request(
"GET",
f"https://discord.com/api/v9/users/{id_of_user}",
headers=headers,
data=payload,
)
return response.json()
You may replace os.getenv("BOT_TOKEN") with your bot token either in the env file or just directly paste it in the source code replacing the os.getenv(...)
Example use of this :
import requests
import os
def find_user(id_of_user):
payload = {}
headers = {"Authorization": "Bot " + os.getenv("BOT_TOKEN")}
response = requests.request(
"GET",
f"https://discord.com/api/v9/users/{id_of_user}",
headers=headers,
data=payload,
)
return response.json()
info = find_user(235148962103951360)
for x in info.keys():
print(f"{x} : {info[x]}")
Output :
id : 235148962103951360
username : Carl-bot
avatar : cececd50fdc87b29929e65c768f24ad6
discriminator : 1536
public_flags : 65536
bot : True
banner : None
banner_color : None
accent_color : None
(The bot was in 0 guilds when this code was executed)
Note : Remember that using requests is blocking if you are going to use this alongside asynchronous code, use aiohttp if you are going to use this function along with dpy.
docs
from aiohttp import web
import aiohttp
from settings import config
import asyncio
import psycopg2 as p
import json
import aiopg
import aiohttp
import asyncio
async def fetch(client):
async with client.get('https://jsonplaceholder.typicode.com/todos/1') as resp:
assert resp.status == 200
return await resp.json()
async def index():
async with aiohttp.ClientSession() as client:
html = await fetch(client)
return web.Response(html)
loop = asyncio.get_event_loop()
loop.run_until_complete(index())
this is my views.py
from aiohttp import web
from routes import setup_routes
from settings import config
app = web.Application()
setup_routes(app)
web.run_app(app,port=9090)
main.py
from views import index
def setup_routes(app):
app.router.add_get('/', index)
and here is my routes.py
but when ever i tried to fire the url of localhost:9090 i just get an internal server 500 error
saying
TypeError: index() takes 0 positional arguments but 1 was given
but t i can print the json in the terminal but couldnt fire the same as web response in the browser i dont know what is wrong in this case
Your index coroutine is a handler, so it must accept a single positional argument, which will receive a Request instance. For example:
async def index(request):
async with aiohttp.ClientSession() as client:
html = await fetch(client)
return web.Response(html)
The loop.run_until_complete(index()) at the top-level of views.py is unnecessary and won't work once index() is defined correctly.
Your index() async function should accept request argument to be a web-handler compatible.