I am following the following tutorial to understand Dialogflow Python API.
Here is how my adaptation looks:
import dialogflow_v2 as dialogflow
import json
from google.api_core.exceptions import InvalidArgument
from google.oauth2 import service_account
dialogflow_key = json.load(open(r'path_to_json_file.json'))
credentials = (service_account.Credentials.from_service_account_info(dialogflow_key))
session_client = dialogflow.SessionsClient(credentials=credentials)
DIALOGFLOW_LANGUAGE_CODE = 'en-US'
DIALOGFLOW_PROJECT_ID = 'some_project_id'
SESSION_ID = 'current-user-id'
session = session_client.session_path(DIALOGFLOW_PROJECT_ID, SESSION_ID)
text_to_be_analyzed = "mobile data"
text_input = dialogflow.types.TextInput(text=text_to_be_analyzed, language_code=DIALOGFLOW_LANGUAGE_CODE)
query_input = dialogflow.types.QueryInput(text=text_input)
try:
response = session_client.detect_intent(session=session, query_input=query_input)
except InvalidArgument:
raise
print("Query text:", response.query_result.query_text)
print("Detected intent:", response.query_result.intent.display_name)
print("Detected intent confidence:", response.query_result.intent_detection_confidence)
print("Fulfillment text:", response.query_result.fulfillment_text)
Here is what program outputs:
Query text: mobile data
Detected intent: support.problem
Detected intent confidence: 0.41999998688697815
Fulfillment text: Make sure mobile data is enabled and Wi-Fi is turned off.
Now my intent support.problem has follow up intent support.problem-yes, where customer replies Done it and gets back another response Let us try another step
How do I pass text/query to follow up intent and how do I get response in Python?
The response.query_result object should also contain an output_context field, which should be an array of Context objects. This array should be passed in query_parameters.context you pass to detect_intent().
You should be able to create a dictionary with the query parameters fields (including one for context) that you pass to session_client.detect_intent.
Related
The issue is that the third function never seems to respond.
I haven't been able to find a reason why this happens in the telegram documentation.
Please let me know if you have this issue or seen it and know the solution.
Even a post that references an issue like this would work.
Thank you so much for the assistance.
from email import message
import os
import re
import html
import json
import telebot
import requests
import http.client
from pytube import *
from dotenv import load_dotenv
load_dotenv()
# Creating hiding, and using API Keys
API_KEY = os.getenv("API_KEY")
RAPID_KEY = os.getenv("RAPID_API")
bot = telebot.TeleBot(API_KEY)
#bot.message_handler(commands="start")
# Creating a help message for guidance on how to use bot.
def help(message):
# Trying to send help message, if unable to send, throw an error message for the user.
try:
bot.send_message(message.chat.id, "Use \"Youtube\" and the video name to search for a video.\n")
except:
bot.send_message(message.chat.id, "There was an error fetching help, the bot may be offline.\n")
# Checking data and seeing if the word "YouTube" was used in order to start the search
def data_validation(message):
query = message.text.split()
if("youtube" not in query[0].lower()): # Set flag false if regular text
return False
else:
return True
#bot.message_handler(func=data_validation)
# Searching for youtube videos
# using RAPID API
def search(message):
query = message.text.split()
# Check if data is valid, and change variable to be lowercase for easy use.
if(data_validation(message) == True and query[0].lower() == "youtube"):
try:
if(data_validation(message) == True and query[1].lower() != "-d"):
# Removing the word "YouTube" and sending the results to the YouTube search engine.
for item in query[:]:
if(item.lower() == "youtube"):
query.remove(item)
search_query = ' '.join(query)
else:
pass #If it's not term we're looking to convert, ignore it.
# RAPID API for Youtube
try:
url = "https://youtube-search-results.p.rapidapi.com/youtube-search/"
querystring = {"q":search_query}
headers = {
"X-RapidAPI-Key": RAPID_KEY,
"X-RapidAPI-Host": "youtube-search-results.p.rapidapi.com"
}
response = requests.request("GET", url, headers=headers, params=querystring) # Grabbing response information from URL
request = json.loads(response.text) # Parsing json string for python use
# Testing to see if the RAPID API service responds and is online.
if(response.status_code == 503):
# If the service is not online, let the user know.
bot.send_message(message.chat.id, f"The RAPID API service appears to be offline try back later.\n")
if(response.status_code == 429):
# If the service has reached max quota for the day, let the user know.
bot.send_message(message.chat.id, f"Max quota reached, try back in 24 hours.\n")
# Grabbing first link from json text and sending direct url and title.
first_link = str((request["items"][0]["url"]))
bot.send_message(message.chat.id, f"{first_link}\n") # Sending first link that was queried.
# If there are no results found for the requested video, sending an error message to alert the user.
except:
bot.send_message(message.chat.id, "Unable to load video.\n")
except:
pass #ignoring if not the phrase we're looking for.
def test(message):
string = message.text.split()
print(string)
if(string[0] == "test" and data_validation(message) == True):
print("This is a test and i should be printed")
bot.send_message(message.chat.id, "Test message")
# Stay alive function for bot pinging / communication
bot.infinity_polling(1440)
The first problem in your code is your first line
from email import message
You import the message from email and also pass a parameter to the data_validation function with the same name, then return False in the data_validation function. If you return false, the function never will be executed.
first give an alias to first line you imported
Try This
from email import message as msg
import os
import re
import html
import json
import telebot
import requests
import http.client
from pytube import *
from dotenv import load_dotenv
load_dotenv()
# Creating hiding, and using API Keys
API_KEY = os.getenv("API_KEY")
RAPID_KEY = os.getenv("RAPID_API")
bot = telebot.TeleBot(API_KEY)
# Creating a help message for guidance on how to use bot.
#bot.message_handler(commands=["start"])
def help(message):
# Trying to send help message, if unable to send, throw an error message for the user.
try:
bot.send_message(message.chat.id, "Use \"Youtube\" and the video name to search for a video.\n")
except:
bot.send_message(message.chat.id, "There was an error fetching help, the bot may be offline.\n")
# Checking data and seeing if the word "YouTube" was used in order to start the search
def data_validation(message):
query = message.text.split()
print(query)
if("youtube" not in query[0].lower()): # Set flag false if regular text
return False # if you return false, the function never will be executed
else:
return True
# Searching for youtube videos
# using RAPID API
#bot.message_handler(func=data_validation)
def search(message):
query = message.text.split()
print(query) # if function executed you see the query result
# Check if data is valid, and change variable to be lowercase for easy use.
if(data_validation(message) == True and query[0].lower() == "youtube"):
try:
if(data_validation(message) == True and query[1].lower() != "-d"):
# Removing the word "YouTube" and sending the results to the YouTube search engine.
for item in query[:]:
if(item.lower() == "youtube"):
query.remove(item)
search_query = ' '.join(query)
else:
pass #If it's not term we're looking to convert, ignore it.
# RAPID API for Youtube
try:
url = "https://youtube-search-results.p.rapidapi.com/youtube-search/"
querystring = {"q":search_query}
headers = {
"X-RapidAPI-Key": RAPID_KEY,
"X-RapidAPI-Host": "youtube-search-results.p.rapidapi.com"
}
response = requests.request("GET", url, headers=headers, params=querystring) # Grabbing response information from URL
request = json.loads(response.text) # Parsing json string for python use
# Testing to see if the RAPID API service responds and is online.
if(response.status_code == 503):
# If the service is not online, let the user know.
bot.send_message(message.chat.id, f"The RAPID API service appears to be offline try back later.\n")
if(response.status_code == 429):
# If the service has reached max quota for the day, let the user know.
bot.send_message(message.chat.id, f"Max quota reached, try back in 24 hours.\n")
# Grabbing first link from json text and sending direct url and title.
first_link = str((request["items"][0]["url"]))
bot.send_message(message.chat.id, f"{first_link}\n") # Sending first link that was queried.
# If there are no results found for the requested video, sending an error message to alert the user.
except:
bot.send_message(message.chat.id, "Unable to load video.\n")
except:
pass #ignoring if not the phrase we're looking for.
def test(message):
string = message.text.split()
print(string)
if(string[0] == "test" and data_validation(message) == True):
print("This is a test and i should be printed")
bot.send_message(message.chat.id, "Test message")
# Stay alive function for bot pinging / communication
bot.infinity_polling(1440)
I found that using "if name == 'main':" and keeping all the functions in "main():" as a function handler everything ran smoothly.
I'm still trying to figure out why this works.
I'm trying to start a conversation from dialogflow cx python API. I have seen this question Start a conversation at the beginning of a flow using flow ID that solves the problem using Node.js but I'm not able to replicate in python.
In my code I have:
text_input = session.TextInput(text=msg)
query_input = session.QueryInput(text=text_input, language_code=language_code)
request = session.DetectIntentRequest(session=session_path, query_input=query_input)
response = session_client.detect_intent(request=request)
I would like to change session.TextInput() to session.EventInput, for example, as here but it does not work with dialogflow CX and the library dialogflowcx_v3beta1
To use an event as query_input, you should use type EventInput() in your QueryInput(). See code below on how to implement it.
from google.cloud import dialogflowcx_v3beta1 as dialogflow
from google.cloud.dialogflowcx_v3beta1 import types
import uuid
project_id = "your-project"
location = "us-central1" # my project is located here hence us-central1
session_id = uuid.uuid4()
agent_id = "999999-aaaa-aaaa" # to get your agent_id see https://stackoverflow.com/questions/65389964/where-can-i-find-the-dialogflow-cx-agent-id
session_path = f"projects/{project_id}/locations/{location}/agents/{agent_id}/sessions/{session_id}"
api_endpoint = f"{location}-dialogflow.googleapis.com"
client_options = {"api_endpoint": api_endpoint}
client = dialogflow.services.sessions.SessionsClient(client_options=client_options)
event = "custom_event"
event_input = types.EventInput(event=event)
query_input = types.QueryInput(event=event_input,language_code="en-US")
request = types.DetectIntentRequest(
session=session_path,query_input=query_input
)
response = client.detect_intent(request=request)
print(response.query_result.response_messages[0])
Custom event:
Output using the custom event created:
I'm creating a chatbot with Dialogflow and Django-python. Right now, I already created an agent in Dialogflow, already have a Django app, used ngork, and other necessary stuffs except for connecting Dialogflow to Django app's fulfillment/and calling APIs.
I stumbled across this documentation https://github.com/googleapis/dialogflow-python-client-v2 and successfully did all the steps needed. In the last part of the documentation, it seems that what I finally need to do is use the dialogflow detect intent text , so I copied it and put it into my Django app(views.py).
def detect_intent_texts(project_id, session_id, texts, language_code):
"""Returns the result of detect intent with texts as inputs.
Using the same `session_id` between requests allows continuation
of the conversation."""
import dialogflow_v2 as dialogflow
session_client = dialogflow.SessionsClient()
session = session_client.session_path(project_id, session_id)
print('Session path: {}\n'.format(session))
for text in texts:
text_input = dialogflow.types.TextInput(
text=text, language_code=language_code)
query_input = dialogflow.types.QueryInput(text=text_input)
response = session_client.detect_intent(
session=session, query_input=query_input)
print('=' * 20)
print('Query text: {}'.format(response.query_result.query_text))
print('Detected intent: {} (confidence: {})\n'.format(
response.query_result.intent.display_name,
response.query_result.intent_detection_confidence))
print('Fulfillment text: {}\n'.format(
response.query_result.fulfillment_text))
Now, I don't know what to do next. Unfortunately, I don't know how to use it or how it exactly works as I am still new to this. I already searched for answers in the web but I didn't get a clear understanding about it and got overwhelmed a bit(as it seems that there is a lot to do with this). I hope I could get an example or step by step procedure about it.
I am assuming you know the basic functionalities of Django, and you are using v2 of Dialogflow.
You need to pass the user text request from front-end to the views.py. YOu will get it in request object, then you need to extract it.
After extracting the text, you need to call dialogflow's detect_intent() function with text and session_id (text requests with same session_id will be treated as same part of conversation).
Also, you would need to get a json file from GCP console in order to authenticate the dialogflow request. You can read more about that here.
Here is sample code which you can extend according to your use:
import dialogflow
from django.http import HttpResponse
def your_view(request):
text = request.POST.get("text_request")
session_id = 'some_session_id'
res = detect_intent(text)
return HttpResponse(res)
def detect_intent(text, session_id):
language_code = 'en'
project_id = 'your_dialogflow_project_id'
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'path_to_your_json_file'
session_client = dialogflow.SessionsClient()
session = session_client.session_path(project_id, session_id)
text_input = dialogflow.types.TextInput(text=text, language_code=language_code)
query_input = dialogflow.types.QueryInput(text=text_input)
response = session_client.detect_intent(session=session, query_input=query_input)
print('Query text: {}'.format(response.query_result.query_text))
print('Detected intent: {} (confidence: {})\n'.format(
response.query_result.intent.display_name,
response.query_result.intent_detection_confidence))
print('Fulfillment text: {}\n'.format(
response.query_result.fulfillment_text))
return response.query_result.fulfillment_text
Hope it helps.
What is the way to pull out all emails from Gmail?
I did full_sync, but that didn't return all of my email - only about 3000 emails, while I know I have more. In the documentation they did not mention about this.
My code snippet:
history = service.users().history().list(
userId='me',
startHistoryId=start_history_id,
maxResults=500,
labelId='INBOX'
).execute()
if "history" in history:
try:
for message in history["history"]:
batch.add(
service.users().messages().get(userId='me', id=message["messages"][0]["id"]),
callback="somecallbak",
request_id=request_id
)
batch.execute()
while 'nextPageToken' in history:
If you are doing a full sync, you should refer to this documentation, that recommends two steps:
listing all the messages with the users.messages.list method
for each of the entry get the required information using the users.messages.get method
So you don't need use the users.history.list as you will have an hard time finding the startHistoryId from which to start.
You can achieve this with a snipped similar to the one below (tested and working on my python 3.x console). As suggested by others I used the python client pagination and batch request functionalities.
from httplib2 import Http
from googleapiclient.discovery import build
from oauth2client import client, tools, file
# callback for the batch request (see below)
def print_gmail_message(request_id, response, exception):
if exception is not None:
print('messages.get failed for message id {}: {}'.format(request_id, exception))
else:
print(response)
# Scopes
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly', ]
# where do we store our credentials?
creds_store = file.Storage('gmail-list.json')
start_creds = creds_store.get()
# standard oauth2 authentication flow
if not start_creds or start_creds.invalid:
# client_id.json is exported from your gcp project
start_flow = client.flow_from_clientsecrets('client_id.json', SCOPES)
start_creds = tools.run_flow(start_flow, creds_store)
# Gmail SDK
http = Http()
gmail_sdk = build('gmail', 'v1', http=start_creds.authorize(http))
# messages.list parameters
msg_list_params = {
'userId': 'me'
}
# messages.list API
message_list_api = gmail_sdk.users().messages()
# first request
message_list_req = message_list_api.list(**msg_list_params)
while message_list_req is not None:
gmail_msg_list = message_list_req.execute()
# we build the batch request
batch = gmail_sdk.new_batch_http_request(callback=print_gmail_message)
for gmail_message in gmail_msg_list['messages']:
msg_get_params = {
'userId': 'me',
'id': gmail_message['id'],
'format': 'full',
}
batch.add(gmail_sdk.users().messages().get(**msg_get_params), request_id=gmail_message['id'])
batch.execute(http=http)
# pagination handling
message_list_req = message_list_api.list_next(message_list_req, gmail_msg_list)
As suggested in this link, you may use batch requests.
Use batch and request 100 messages at a time. You will need to make 1000 requests but the good news is that's quite fine and it'll be easier for everyone (no downloading 1GB response in a single request!).
Also based from this thread, you could save the next page token on every request and use it in your next request. If there is no next page token in the response, you know that you have gotten all messages.
I want to send transactional and marketing emails using 'SendInBlue'. I also want to use Python language to do the same. I have visited the API doc of SendInBlue and followed the same procedure, still unsuccessful in sending the emails.
from mailin import Mailin
m = Mailin("https://api.sendinblue.com/v2.0","ScrWGqd296ya0CWq")
data = { "to" : {"aman#gmail.com":"to whom!"},
"from" : ["amandeep#gmail.com", "from email!"],
"subject" : "Subject...",
"html" : "This is the <h1>HTML</h1>",
"attachment" : ["https://example.com/path-to-file/filename1.pdf", "https://example.com/path-to-file/filename2.jpg"]
}
result = m.send_email(data)
print(result)
I have also downloaded mailin-api-python from github and ran this script. I don't have any idea where to setup to my smtp details.
**I have changed the API key just for security purpose.
I would strongly recommend you to use the latest version of SendinBlue's Python wrapper where they have provided an example
from __future__ import print_function
import time
import sib_api_v3_sdk
from sib_api_v3_sdk.rest import ApiException
from pprint import pprint
# Configure API key authorization: api-key
configuration = sib_api_v3_sdk.Configuration()
configuration.api_key['api-key'] = 'API-KEY'
# create an instance of the API class
api_instance = sib_api_v3_sdk.SMTPApi(sib_api_v3_sdk.ApiClient(configuration))
senderSmtp = sib_api_v3_sdk.SendSmtpEmailSender(name="test",email="youremail#gmail.com")
sendTo = sib_api_v3_sdk.SendSmtpEmailTo(email="recipientEmail#gmail.com",name="Recipient Name")
arrTo = [sendTo] #Adding `to` in a list
send_smtp_email = sib_api_v3_sdk.SendSmtpEmail(sender=senderSmtp,to=arrTo,html_content="This is a test",subject="This is a test subject") # SendSmtpEmail | Values to send a transactional email
try:
# Send a transactional email
api_response = api_instance.send_transac_email(send_smtp_email)
pprint(api_response)
except ApiException as e:
print("Exception when calling SMTPApi->send_transac_email: %s\n" % e)
I got a sample script working:
I successfully received the email and the messageId as the response.
Please let me know if it helps!