如何实现异步任务来处理Dialogflow的超时?

时间:2019-02-11 08:11:29

标签: python flask celery dialogflow python-asyncio

我是Python的新手,它试图构建一个电子邮件提取器,该提取器从dialogflow的bot接收输入,然后将请求发送到我的python webhook。我想从以请求形式发送的Dialogflow的已处理输入中提取信息,以使用提取的信息进一步从服务器提取电子邮件。

我基本上要面对的问题是,默认情况下,通过Dialogflow发送的请求的超时为5秒,整个处理过程要花更多的时间。 截至目前,我正在同步进行,因此超时。我发现可以通过Python中的asyncio来完成,但不了解如何为Flask应用程序实现同样的功能。

Main.py

from imap import ImapClient
import pandas as pd
import argparse
from flask import Flask, jsonify, make_response, request
import requests
from pprint import pprint
import datetime

app = Flask(__name__)

@app.route('/')
def index():
    return ('Hello World')

# @app.route('/webhook')
# def hello():
#     return ('Hello World')

def results():
    # build a request object
    req = request.get_json(force=True)
    pprint(req)
    # fetch action from json
    action = req.get('queryResult').get('action')
    date = req.get('queryResult').get('parameters').get('date')
    # guests = 
    # time = 
    print(date)
    # return a fulfillment response
    return {'fulfillmentText': 'Extracting mails for you....'}

def extractParam():

    req = request.get_json(force=True)
    date = req.get('queryResult').get('parameters').get('date')
    return (date)


# create a route for webhook
@app.route('/webhook', methods=['GET', 'POST'])
def webhook():
    # return response
    date = extractParam()
    #print('Date is', date)
    #print(datetime.datetime.now())
    main(date)
    #print('CHCEKINGGGGG',datetime.datetime.now())
    return (make_response(jsonify(results())))


def main(date_rec):
    """
    You will need to store your email password in your environment, e.g.
    export mailpwd=password
    """
    # parser = argparse.ArgumentParser()
    # parser.add_argument('uid', help='User ID to login')
    # parser.add_argument('pwd', help='Password')
    # parser.add_argument('rid', help='Extracting Mail address')
    # args = parser.parse_args()
    #print(args.uid, args.pwd)

    data_unformatted = date_rec
    mon = {'01':'Jan', '02':'Feb', '03':'Mar', '04':'Apr', '05':'May',
       '06':'Jun', '07':'Jul', '08':'Aug', '09':'Sep', '10':'Oct',
       '11':'Nov', '12':'Dec'}
    data_unformatted = data_unformatted.split('-')
    year = data_unformatted[0]
    month = mon[data_unformatted[1]]
    date = data_unformatted[2][0:2]

    now = datetime.datetime.now()
    if int(year) > now.year:
        year = str(now.year)

    final_date = ('{}-{}-{}').format(date, month, year)
    print('Proceseed date is',final_date)
    imap = ImapClient(recipient='<emailid>')
    imap.login('<PWD>')
    # retrieve messages from a given sender
    messages, subjects = imap.get_messages(sender='<senderEmailID>', date=final_date)
    # Do something with the messages
    print("Messages in my inbox:")
    lis = []
    for msg in messages:
        # msg is a dict of {'num': num, 'body': body}
        lis.append(msg['body'])
        # you could delete them after viewing
        # imap.delete_message(msg['num'])
    # when done, you should log out
    imap.logout()
    d= {'Subject': subjects, 'Body': lis}
    df = pd.DataFrame(data=d)
    print(df)
    df.to_excel('Messages.xlsx', index=None)
    return

if __name__ == "__main__":
    #main()
    app.run()

imap.py

import email
import email.header
import imaplib
import os
import sys


class ImapClient:
    imap = None

    def __init__(self,
                 recipient,
                 server='<mailServerAddress>',
                 use_ssl=True,
                 move_to_trash=True):
        # check for required param
        if not recipient:
            raise ValueError('You must provide a recipient email address')
        self.recipient = recipient
        self.use_ssl = use_ssl
        self.move_to_trash = move_to_trash
        self.recipient_folder = 'INBOX'
        # instantiate our IMAP client object
        if self.use_ssl:
            self.imap = imaplib.IMAP4_SSL(server)
        else:
            self.imap = imaplib.IMAP4(server)

    def login(self, pwd):
        try:
            print('Trying loggin with {} username and {} password'.format(self.recipient, pwd))
            rv, data = self.imap.login(self.recipient,password=pwd)
        except (imaplib.IMAP4_SSL.error, imaplib.IMAP4.error) as err:
            print('LOGIN FAILED!')
            print(err)
            sys.exit(1)

    def logout(self):
        self.imap.close()
        self.imap.logout()

    def select_folder(self, folder):
        """
        Select the IMAP folder to read messages from. By default
        the class will read from the INBOX folder
        """
        self.recipient_folder = folder

    def get_messages(self, sender, date='', subject=''):
        """
        Scans for email messages from the given sender and optionally
        with the given subject

        :param sender Email address of sender of messages you're searching for
        :param subject (Partial) subject line to scan for
        :return List of dicts of {'num': num, 'body': body}
        """
        if not sender:
            raise ValueError('You must provide a sender email address')
        print('Extracting mail from', sender)
        # select the folder, by default INBOX
        resp, _ = self.imap.select(self.recipient_folder)
        if resp != 'OK':
            print(f"ERROR: Unable to open the {self.recipient_folder} folder")
            sys.exit(1)

        messages = []
        subject_mail = []
        print('Searching for', date)
        mbox_response, msgnums = self.imap.search(None, 'SENTON', date)
        if mbox_response == 'OK':
            for num in msgnums[0].split():
                retval, rawmsg = self.imap.fetch(num, '(RFC822)')
                if retval != 'OK':
                    print('ERROR getting message', num)
                    continue
                msg = email.message_from_bytes(rawmsg[0][1])
                msg_subject = msg["Subject"]
                subject_mail.append(msg_subject)
                if subject in msg_subject:
                    body = ""
                    if msg.is_multipart():
                        for part in msg.walk():
                            type = part.get_content_type()
                            disp = str(part.get('Content-Disposition'))
                            # look for plain text parts, but skip attachments
                            if type == 'text/plain' and 'attachment' not in disp:
                                charset = part.get_content_charset()
                                # decode the base64 unicode bytestring into plain text
                                body = part.get_payload(decode=True).decode(encoding=charset, errors="ignore")
                                # if we've found the plain/text part, stop looping thru the parts
                                break
                    else:
                        # not multipart - i.e. plain text, no attachments
                        charset = msg.get_content_charset()
                        body = msg.get_payload(decode=True).decode(encoding=charset, errors="ignore")
                    messages.append({'num': num, 'body': body})
        return messages, subject_mail

    def delete_message(self, msg_id):

        if not msg_id:
            return
        if self.move_to_trash:
            # move to Trash folder
            self.imap.store(msg_id, '+X-GM-LABELS', '\\Trash')
            self.imap.expunge()
        else:
            self.imap.store(msg_id, '+FLAGS', '\\Deleted')
            self.imap.expunge()

0 个答案:

没有答案