I'm writing an app which sends an automated call via Amazon Connect. The app needs to retry to another destination number should the first one fail to pick up. The app is being written in Python3 and is to be hosted in Lambda.
This is the resource is used
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/connect.html#Connect.Client.get_contact_attributes
https://docs.aws.amazon.com/connect/latest/APIReference/API_GetContactAttributes.html
The problem is that "send call" is kicked off asynchronously and so it is not immediately clear if the call has succeeded or not. To check the call I invoke "get_contact_attributes" to identify status or any attributes which could point to the status of the placed call.
response=client.start_outbound_voice_contact(
ContactFlowId='XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
DestinationPhoneNumber=event["DestinationPhoneNumber"],
SourcePhoneNumber=event["OriginationPhoneNumber"],
InstanceId="YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY",
Attributes={
"message":f'{event["message"]}'
}
)
contactid=response["ContactId"]
attr = client.get_contact_attributes(
InstanceId='YYYYYYYY-YYYY-YYYY-YYYY-YYYYYYYYYYYY',
InitialContactId=contactid
)
I expected it to return "connected_at" or something like it I could use to identify the outcome of the call, however, it only returns "custom" attributes set by myself.
this is the solution i found:
1) in the Contact Flow i added "Set Attribute" node where i set "status=1" right after the start. Basically, if a call enters Contact Flow (i.e. call picked up) it is marked as successfully completed
Set Contact Sttributes
2) inside my Python code (lambda) i check for the status to show up and if it doesn't in so many seconds i cancel the call and try another number:
attr = client.get_contact_attributes(
InstanceId=instanceid,
InitialContactId=contactid
)
stop_call=client.stop_contact(
ContactId=contactid,
InstanceId=instanceid
)
Related
If a user invokes my action, she is asked by google whether her account should be linked or not (something like: "If you want to use xxx, I got to link your account at xxx with google. Is this okay?"). Now, if she chooses "no", and my action returns an answer with expectUserResponse set to false, google assistant seems to jump into a very awkward endless loop of my returned response, even emitting the assistant's "conversation finished" sound after each response:
("In order to use xxx, I got to link your account at xxx with google. Is this okay?" - "No" - "Okay, this means you are not able to use your account at xxx. Get back to us if you change your mind.")
"Schönen Tag" (in the second speech bubble) is the response I am sending from my fulfillment.
So what we are getting here is an endless "Schönen Tag" - GoogleSound - "Schönen Tag" - GoogleSound - "Schönen Tag" - GoogleSound - Schönen Tag"- GoogleSound and so on. With no additional user input between each message. Imho, this definitely shouldn't happen, no matter if I configured sth wrongly or not.
I don't even need my fulfillment server to reproduce this. If I create a dialogflow intent, attach the actions_intent_SIGN_IN event to it and let this intent return a static response with "set this intent as end of conversation" set to true, I am able to fully reproduce this strange behaviour:
(this actually was the setup for all screenshots above)
If I recreate this intent, but change the setting to not end the conversation after sending the response, I do not get an endless loop anymore. But this isn't what I intended to do.
It also doesn't seem to matter if I require the sign in for explicit invocations or not (in the integrations-tab).
It looks like this was a bug, with a fix released this morning.
Are you still running into this issue?
I'm new to flask and currently converting an existing WSGI application to run through flask as long term it'll make life easier.
All requests are POST to specific routes however the current application inspects the post data prior to executing the route to see if the request needs to be run at all or not (i.e. if an identifier supplied in the post data already exists in our database or not).
If it does exist a 200 code and json is returned "early" and no other action is taken; if not the application continues to route as normal.
I think I can replicate the activity at the right point by calling before_request() but I'm not sure if returning a flask Response object from before_request() would terminate the request adequately at that point? Or if there's a better way of doing this?
NB: I must return this as a 200 - other examples I've seen result in a redirect or 4xx error handling (as a close parallel to this activity is authentication) so ultimately I'm doing this at the end of before_request():
if check_request_in_progress(post_data) is True:
response = jsonify({'request_status': 'already_running'})
response.status_code = 200
return response
else:
add_to_requests_in_progress(post_data)
Should this work (return and prevent further routing)?
If not how can I prevent further routing after calling before_request()?
Is there a better way?
Based on what they have said in the documents, it should do what you want it to do.
The function will be called without any arguments. If the function returns a non-None value, it’s handled as if it was the return value from the view and further request handling is stopped.
(source)
#app.route("/<name>")
def index(name):
return f"hello {name}"
#app.before_request
def thing():
if "john" in request.path:
return "before ran"
with the above code, if there is a "john" in the url_path, we will see the before ran in the output, not the actual intended view. you will see hello X for other string.
so yes, using before_request and returning something, anything other than None will stop flask from serving your actual view. you can redirect the user or send them a proper response.
I want to clear all pending_update_count in my bot!
The output of below command :
https://api.telegram.org/botxxxxxxxxxxxxxxxx/getWebhookInfo
Obviously I replaced the real API token with xxx
is this :
{
"ok":true,"result":
{
"url":"",
"has_custom_certificate":false,
"pending_update_count":5154
}
}
As you can see, I have 5154 unread updates til now!! ( I'm pretty sure this pending updates are errors! Because no one uses this Bot! It's just a test Bot)
By the way, this pending_update_count number are increasing so fast!
Now that I'm writing this post the number increased 51 and reached to 5205 !
I just want to clear this pending updates.
I'm pretty sure this Bot have been stuck in an infinite loop!
Is there any way to get rid of it?
P.S:
I also cleared the webhook url. But nothing changed!
UPDATE:
The output of getWebhookInfo is this :
{
"ok":true,
"result":{
"url":"https://somewhere.com/telegram/webhook",
"has_custom_certificate":false,
"pending_update_count":23,
"last_error_date":1482910173,
"last_error_message":"Wrong response from the webhook: 500 Internal Server Error",
"max_connections":40
}
}
Why I get Wrong response from the webhook: 500 Internal Server Error ?
I think you have two options:
set webhook that do nothing, just say 200 OK to telegram's servers. Telegram wiil send all updates to this url and the queque will be cleared.
disable webhook and after it get updates by using getUpdates method, after it, turn on webhook again
Update:
Problem with webhook on your side. You can try to emulate telegram's POST query on your URL.
It can be something like this:
{"message_id":1,"from":{"id":1,"first_name":"FirstName","last_name":"LastName","username":"username"},"chat":{"id":1,"first_name":"FirstName","last_name":"LastName","username":"username","type":"private"},"date":1460957457,"text":"test message"}
You can send this text as a POST query body with PostMan for example, and after it try to debug your backend.
For anyone looking at this in 2020 and beyond, the Telegram API now supports clearing the pending messages via a drop_pending_updates parameter in both setWebhook and deleteWebhook, as per the API documentation.
Just add return 1; at the end of your hook method.
Update:
Commonly this happens because of queries delay with the database.
I solved is like this
POST tg.api/bottoken/setWebhook to emtpy "url"
POST tg.api/bottoken/getUpdates
POST tg.api/bottoken/getUpdates with "offset" last update_id appeared before
doing this serveral times
POST tg.api/bottoken/getWebhookInfo
had a look if all away.
POST tg.api/bottoken/setWebhook with filled "url"
If you are using webhook, you can follow these steps
On your web browser, enter the following url with your right value of bot
https://api.telegram.org/bot/getWebhookInf
You will get a result like this on your screen
{"ok":true,"result":{"url":"url_value",...}}
On the displayed result, copy the entire url_value without quotes and replace it on this second url
https://api.telegram.org/bot/setWebhook?url=url_value&drop_pending_updates=True
Enter the second url with right bot and url_value in your web browser then press ENTER
Done!
i solve it by Change file access permissions file - set permissions file to 755
and second increase memory limit in php.ini file
A quick&dirty way is to get a temporary webhook here: https://webhook.site/ and
set your webhook to that (it will answer with a HTTP/200 code everytime, reseting your pending messages to zero)
I faced the same issue for my tele bot after user edited existing message. My bot receives update with editedMessage continuously, but update.hasMessage() was empty. As a result number of updates rocketly increased and my bot stack.
I solved this issue by adding handling for use case when message is missing - send 200 code:
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent event, Context context) {
update = MAPPER.readValue(event.getBody(), Update.class);
if (!update.hasMessage()) {
return new APIGatewayProxyResponseEvent()
.withStatusCode(200) // -> !!!!!! return code 200
.withBody("message is missing")
.withIsBase64Encoded(false);
}
... ... ...
I am using poplib in Python 3.3 to fetch emails from a gmail account and everything is working well, except that the mails are not marked as read after retrieving them with the retr() method, despite the fact that the documentation says "Retrieve whole message number which, and set its seen flag."
Here is the code:
pop = poplib.POP3_SSL("pop.gmail.com", "995")
pop.user("recent:mymail#gmail.com")
pop.pass_("mypassword")
numMessages = len(pop.list()[1])
for i in range(numMessages):
for j in pop.retr(i+1)[1]:
print(j)
pop.quit()
Am I doing something wrong or does the documentation lie? (or, did I just misinterpret it?)
The POP protocol has no concept of "read" or "unread" messages; the LIST command simply shows all existing messages. You may want to use another protocol, like IMAP, if the server supports it.
You could delete messages after successful retrieval, using the DELE command. Only after a successful QUIT command will the server actually delete them.
How can I run myscript.py after the transaction manager has returned. Additionally, I would prefer if the script was not blocking.
In my view, I am receiving a file from a POST. Since I'm creating the file with repoze.filesafe's create_file(), it keeps the file in a temporary location until the transaction manager returns. The file only exists on the harddisk in its correct path after transaction manager has returned without an error.
Therefore, I need to run my script after the transaction manager has returned.
You can register a hook to be run after commit via the transaction package. Register one in your view:
import transaction
def your_after_commit(success, arg1, arg2, kwarg1=None, kwarg2=None):
if success:
print "Transaction commit succeeded"
else:
print "Transaction commit failed"
def someview(request):
current_transaction = transaction.get()
current_transaction.addAfterCommitHook(your_after_commit, args=(1, 2), kws={kwarg1='foo', kwargs2='bar'})
This still runs your script in the context of the current request (e.g. the request does not complete until your script returns). If you need a full asynchronous setup, you'll need to move to a proper asynchronous solution such as Celery. You would not use that with a transaction hook; just register a task to be run with Celery instead.