使

使用 Python 和 Fauna 构建电子商务电报机器人。

2025-06-08

使用 Python 和 Fauna 构建电子商务电报机器人。

本文将向您展示如何为小型企业主构建一个 Telegram 机器人。该机器人的功能与热门平台 WhatsApp Business 非常相似。我们将了解如何实现这些功能,并在 Fauna 的无服务器系统上设置数据库来托管用户数据。

在我们开始之前,让我通知您,在本教程的其余部分中,我将把这个机器人称为telegram-business 。

TELEGRAM-BUSINESS 能做什么

首先,用户有两种类型:客户和企业主。机器人的功能根据平台允许的用户类型进行分类。以下是 Telegram-business 的功能:

客户特点:

  • 客户可以查看四个不同类别的业务。
  • 客户可以查看来自任何这些企业的产品。
  • 顾客可以订购产品。

企业主特点:

  • 企业主可以创建目录并添加产品。
  • 当用户下订单时,企业主将收到通知。

先决条件

在本教程中,我将使用 Python 3 以及 Fauna 平台。要学习本教程,您需要安装 Python 并拥有 Fauna 帐户。如果您没有 Fauna 帐户,可以点击此处注册。为了学习本教程,您最好具备 Python 的基础知识。我还将使用 Cloudinary 存储产品图片。您可以点击此处注册一个免费的 Cloudinary 帐户。以下是此机器人所需资源的详细列表:

  • Python3
  • 动物账户
  • Cloudinary 帐户

准备数据库

我们要做的第一件事是在 Fauna 上设置数据库。前往 fleeta.com 并登录到你的仪表盘。登录后,点击仪表盘上的“新建数据库”按钮创建一个新的数据库。

替代文本

这将带您进入如上图所示的页面。填写必填字段,然后单击“保存”为我们的机器人创建一个新的数据库。

创建集合

接下来,我们将为平台上的每个实体创建三个集合:用户、企业和产品。点击“新建集合”。它将带您进入如下所示的新页面:

替代文本

将此集合命名为“ Users”,然后点击“保存”按钮即可创建集合。完成后,创建另外两个集合:Business 和 Products。完成后,集合菜单选项中应该会显示三个集合。

替代文本

让我们继续创建索引,以便从数据库中轻松检索信息。

创建索引

对于我们的电商系统,我们需要创建多个索引,以便更快地获取所需信息。要创建索引,请转到“索引”菜单选项,然后点击“新建索引”按钮。它会带您进入一个类似于以下页面的新页面:

替代文本

我们要创建的第一个索引允许我们通过姓名查找用户。因此,我们将选择源集合,即第一个索引的User集合,然后将索引命名为“user_by_name”,接着选择要搜索的词条,即用户的“姓名”,并在“词条”字段中输入“姓名”,您可以将“值”字段保留为空。完成后,您的表单应如下所示:

替代文本

接下来使用以下信息创建另外三个索引:

  • business_by_name:{来源集合:企业,术语:名称}
  • product_by_business:{来源集合:产品,术语:中小企业}
  • business_by_category:{来源集合:商业,术语:类别}

生成 API_KEY

我们需要从 Fauna 获取的最后一项是数据库的 API_KEY,以便通过互联网向其发送查询。前往“安全”选项,然后点击“新密钥”选项——它会带你进入一个带有表单的新页面。点击“保存”,它会生成一个密钥供你复制。复制该密钥并将其保存在一个文本文件中,我们稍后会用到它。

构建机器人

与 BotFather 对话

要构建 Telegram 机器人,我们必须在 Telegram 的“机器人父”那里注册。要创建你的机器人,请打开 Telegram 并搜索“机器人父”,或者直接点击此处进入“机器人父”的聊天室。

到达那里后,输入“/start”开始与机器人之父对话,它会向您显示可用于与其交互的命令列表;可以输入或单击这些命令来执行它们。

替代文本

选择/newbot命令创建一个新的机器人。完成后,botfather 会要求输入名称和用户名。完成后,botfather 会向我们提供有关新机器人的信息,例如机器人的链接和访问令牌(这是我们目前需要的)。复制此信息并保存在某个地方。

替代文本

编写 Telegram 业务脚本

我们首先为项目创建一个虚拟环境,打开命令提示符,并将目录更改为你希望的位置(最好是一个新的空文件夹)。到达那里后,使用任何你想要的 Python 虚拟环境管理器创建一个虚拟环境。例如,我使用virtualenv创建一个名为“env”的虚拟环境,我将运行以下命令:

virtualenv env

接下来,我们将激活虚拟环境并安装以下 Python 包:

  • Python-telegram-bot:帮助我们编写控制机器人的代码。

  • Faunadb:这是一个 Python 包,可以帮助我们通过脚本与 Fauna 的 api 进行交互。

  • python-dotenv:它将帮助我们轻松读取配置变量。

  • Cloudinary:我们照片存储 API 的客户端库。请务必注册一个 Cloudinary 帐户,并从仪表板获取 api_key 和 secret。我们稍后会用到它们。

终端的屏幕截图显示了用于激活虚拟环境以及用于安装列出的包的命令。

我们首先在项目文件夹中创建以下文件:

  • 处理程序.py
  • 主程序
  • 配置.py
  • .env

我将把处理程序的实现分为两部分:

  • 客户功能
  • 业务功能

我们将从业务功能开始,其中包括机器人与企业主用户的交互。我们需要做的第一件事是将来自 botFather、cloudinary 和 Fauna 的令牌和密钥添加到.env文件中,如下所示:

BOT_TOKEN=***486**:*******-****ro
API_SECRET=-****OcAGV****
API_KEY=********21
FAUNA_KEY=f****8sZ*****J****Gd4****Q
Enter fullscreen mode Exit fullscreen mode

完成后,我们转到config.py文件,在其中,我们通过之前安装的python-dotenv包读取.env文件中的一些变量,并将其指向这些环境变量。这个包允许我们从文件中读取环境变量,甚至可以直接从命令提示符中读取。

import os
from dotenv import load_dotenv

load_dotenv()

TOKEN = os.getenv('BOT_TOKEN')
api_secret = os.getenv('API_SECRET')
api_key = os.getenv('API_KEY')
FAUNA_KEY = os.getenv('FAUNA_KEY')
Enter fullscreen mode Exit fullscreen mode

现在,我们可以在代码中使用这些变量,而无需从 env 文件中读取。接下来,我们从处理程序方法开始,这些方法将处理机器人如何与 Telegram 上的用户进行交互。

我们将从负责管理机器人与注册成为企业主的用户的交互的处理程序方法开始。此代码的文件是handlers.py,并导入所需的依赖项。

from telegram import (
    ReplyKeyboardMarkup,
    ReplyKeyboardRemove, Update,
    InlineKeyboardButton, InlineKeyboardMarkup
)
from telegram.ext import (
    CommandHandler, CallbackContext,
    ConversationHandler, MessageHandler,
    Filters, Updater, CallbackQueryHandler
)
from config import (
    api_key, sender_email,
    api_secret,
    FAUNA_KEY
)
import cloudinary
from cloudinary.uploader import upload
from faunadb import query as q
from faunadb.client import FaunaClient
from faunadb.errors import NotFound
Enter fullscreen mode Exit fullscreen mode

我们将为一些依赖项添加一些样板配置,因此在导入所有这些配置后添加以下内容:

# configure cloudinary
cloudinary.config(
    cloud_name="curiouspaul",
    api_key=api_key,
    api_secret=api_secret
)

# fauna client config
client = FaunaClient(secret=FAUNA_KEY)

# Define Options
CHOOSING, CLASS_STATE, SME_DETAILS, CHOOSE_PREF, \
    SME_CAT, ADD_PRODUCTS, SHOW_STOCKS, POST_VIEW_PRODUCTS = range(8)
Enter fullscreen mode Exit fullscreen mode

第一个配置用于我们的 Cloudinary 实例,第二个配置用于我们的 Fauna 客户端实例,后面的变量代表机器人的状态,或者至少是用户与机器人交互时可能的状态。这是“conversationhandler”方法所必需的,该方法允许我们编写脚本,使机器人与人类的交互更加自然。每个变量的名称略微表明了它们代表的状态。例如,SME_DETAILS状态与某些向用户询问其业务详细信息的方法相关联。

添加处理程序方法

从这里开始,我们将继续在脚本中添加处理程序方法。我们需要添加的第一个处理程序方法是处理通过/start命令与机器人发起对话时发生的情况

当有人在我们的机器人上使用/start命令时,将调用以下代码行,因此将其添加到处理程序代码中。

def start(update, context: CallbackContext) -> int:
    print("You called")
    bot = context.bot
    chat_id = update.message.chat.id
    bot.send_message(
        chat_id=chat_id,
        text= "Hi fellow, Welcome to SMEbot ,"
        "Please tell me about yourself, "
        "provide your full name, email, and phone number, "
        "separated by comma each e.g: "
        "John Doe, JohnD@gmail.com, +234567897809"
    )
    return CHOOSING
Enter fullscreen mode Exit fullscreen mode

看看我如何返回机器人对话的新状态,这是我们之前预定义的状态之一。此函数返回一条介绍消息并向用户请求信息。

接下来的状态是CHOOSING,此状态与另一个方法绑定,该方法接收用户输入并进行解析,以确保其正确无误,之后再使用该信息注册用户。然后,它会提示用户选择他/她是哪种类型的用户,即客户还是企业主。添加以下代码行来添加此方法:

# get data generic user data from user and store
def choose(update, context):
    bot = context.bot
    chat_id = update.message.chat.id
    # create new data entry
    data = update.message.text.split(',')
    if len(data) < 3 or len(data) > 3:
        bot.send_message(
            chat_id=chat_id,
            text="Invalid entry, please make sure to input the details "
            "as requested in the instructions"
        )
        bot.send_message(
            chat_id=chat_id,
            text="Type /start, to restart bot"
        )
        return ConversationHandler.END
    #TODO: Check if user already exists before creating new user
    new_user = client.query(
        q.create(q.collection('User'), {
            "data":{
                "name":data[0],
                "email":data[1],
                "telephone":data[2],
                "is_smeowner":False,
                "preference": "",
                "chat_id":chat_id
            }
        })
    )
    context.user_data["user-id"] = new_user["ref"].id()
    context.user_data["user-name"] = data[0]
    context.user_data['user-data'] = new_user['data']
    reply_keyboard = [
    [
        InlineKeyboardButton(
            text="SME",
            callback_data="SME"
        ),
        InlineKeyboardButton(
            text="Customer",
            callback_data="Customer"
        )
    ]
  ]
  markup = InlineKeyboardMarkup(reply_keyboard, one_time_keyboard=True)
    bot.send_message(
        chat_id=chat_id,
        text="Collected information succesfully!..🎉🎉 \n"
        "Which of the following do you identify as ?",
        reply_markup=markup
    )
    return CLASS_STATE

Enter fullscreen mode Exit fullscreen mode

该函数接受用户输入,对其进行解析,并使用结果将用户信息保存到 Fauna 上的数据库中,方法是使用 Fauna 库中的查询方法向 Fauna API 发送写入数据库的 post 请求。

我们还使用context.user_data[]属性将一些关于用户的信息存储在内存中——稍后我们将在其他处理程序方法中用到这些信息。最后,我们返回一个响应以及一个新的对话状态,此状态(CLASS_STATE)用于确定我们正在处理的用户类型,即客户还是企业主

def classer(update, context):
    bot = context.bot
    chat_id = update.callback_query.message.chat.id
    name = context.user_data["user-name"]
    if update.callback_query.data.lower() == "sme":
        # update user as smeowner
        client.query(
            q.update(
                q.ref(q.collection("User"), context.user_data["user-id"]),
                {"data": {"is_smeowner":True}}
            )
        )
        bot.send_message(
            chat_id=chat_id,
            text=f"Great! {name}, please tell me about your business, "
            "provide your BrandName, Brand email, Address, and phone number"
            "in that order, each separated by comma(,) each e.g: "
            "JDWears, JDWears@gmail.com, 101-Mike Avenue-Ikeja, +234567897809",
            reply_markup=ReplyKeyboardRemove()
        )

        return SME_DETAILS
    categories = [  
        [
            InlineKeyboardButton(
                text="Clothing/Fashion",
                callback_data="Clothing/Fashion"
            ),
            InlineKeyboardButton(
                text="Hardware Accessories",
                callback_data="Hardware Accessories"
            )
        ],
        [
            InlineKeyboardButton(
                text="Food/Kitchen Ware",
                callback_data="Food/Kitchen Ware"
            ),
            InlineKeyboardButton(
                text="ArtnDesign",
                callback_data="ArtnDesign"
            )
        ]
    ]
    bot.send_message(
        chat_id=chat_id,
        text="Here's a list of categories available"
        "Choose one that matches your interest",
        reply_markup=InlineKeyboardMarkup(categories)
    )
    return CHOOSE_PREF

Enter fullscreen mode Exit fullscreen mode

但是,如果用户的身份是客户,该函数会向用户发送不同的响应。系统会提供一个类别菜单供客户选择,以便查看所选类别下的业务。如果用户的身份是客户,这些类别将作为响应发送给用户,并返回与客户功能相关的新状态。

让我们添加一个“取消”命令处理程序,以帮助用户随时取消与机器人的交互。接下来添加以下函数:

# Control
def cancel(update: Update, context: CallbackContext) -> int: 
    update.message.reply_text(
        'Bye! I hope we can talk again some day.',
        reply_markup=ReplyKeyboardRemove()
    )

    return ConversationHandler.END
Enter fullscreen mode Exit fullscreen mode

此时,我们可以测试我们的机器人,看看它如何响应我们的交互。为了测试机器人,我们需要在main.py中使用对话处理程序方法注册我们的处理程序,并将它们映射到每个状态,如下所示:

import handlers
from telegram.ext import (
    CommandHandler, CallbackContext,
    ConversationHandler, MessageHandler,
    Filters, Updater, CallbackQueryHandler
)
from config import TOKEN

updater = Updater(token=TOKEN, use_context=True)
print(updater)
dispatcher = updater.dispatcher


def main():
    conv_handler = ConversationHandler(
        entry_points=[CommandHandler('start', handlers.start)],
        states={
            handlers.CHOOSING: [
                MessageHandler(
                    Filters.all, handlers.choose
                )
            ],
            handlers.CLASS_STATE: [
                CallbackQueryHandler(handlers.classer)
            ]
        },
        fallbacks=[CommandHandler('cancel', handlers.cancel)],
        allow_reentry=True
    )
    dispatcher.add_handler(conv_handler)
    updater.start_polling()
    updater.idle()

if __name__ == '__main__':
    main()
Enter fullscreen mode Exit fullscreen mode

保存此内容,转到您的终端,然后通过main.py文件运行机器人,如下所示:

显示从终端运行文件的命令的屏幕截图

运行此命令后,您可能不会立即在终端看到任何提示,直到您开始与机器人交互。让我们转到我们的机器人并发起对话。使用 botFather 提供的链接,或者在 Telegram 中搜索您的机器人名称。

到达那里后,使用/start命令,或者直接点击聊天框中的“开始”按钮,与你的机器人初始化对话。你应该会看到你的机器人做出如下回应:

屏幕截图显示了我们的机器人(telegram-business)的响应,正如我们在之前的步骤中编程的那样

按照提示,输入所需信息,并将其作为消息发送以激活对话的下一个状态,该状态将要求您选择您识别为哪种类型的用户,中小企业所有者还是客户

在我们向机器人提供其所要求的详细信息后,该屏幕截图显示了机器人的响应。

选择“SME”选项会提示我们输入有关“业务”的详细信息,正如我们之前定义的classer()方法中所述。但是,如果我们选择“客户”选项作为首选项,那么机器人会返回一个类别选项列表供您选择。

机器人的另一个响应的屏幕截图,提示用户输入有关他/她的业务的详细信息,正如我们对其进行编程一样。

我们的机器人目前只能做到这里了,因为我们还没有添加剩余功能的处理方法。接下来,让我们继续编写机器人脚本。

以下是一系列负责所有业务功能的处理程序方法。请按以下顺序添加以下处理程序方法。我根据它们的功能列出它们,有些方法可能涉及多个处理程序方法:

  • 收集业务详细信息并存储:为此,有两个功能;第一个功能从业务的最后阶段获取用户输入,对其进行解析并将数据存储在内存中,将数据传递给以下处理程序方法,最后提示用户选择其业务所属的类别。

第二个方法获取所有数据并使用它们在我们的 Faunadb 实例中创建一个新的业务文档,提示用户添加新产品,然后返回一个新的
对话状态,该状态与负责向新创建的业务添加产品的处理程序方法相关联。

def business_details(update, context):
    bot = context.bot
    chat_id = update.message.chat.id
    data = update.message.text.split(',')
    if len(data) < 4 or len(data) > 4:
        bot.send_message(
            chat_id=chat_id,
            text="Invalid entry, please make sure to input the details "
            "as requested in the instructions"
        )
        return SME_DETAILS
    context.user_data["sme_dets"] = data
    # categories = [
    #         ['Clothing/Fashion', 'Hardware Accessories'],
    #         ['Food/Kitchen Ware', 'ArtnDesign'],
    #         ['Other']
    # ]
    categories = [  
        [
            InlineKeyboardButton(
                text="Clothing/Fashion",
                callback_data="Clothing/Fashion"
            ),
            InlineKeyboardButton(
                text="Hardware Accessories",
                callback_data="Hardware Accessories"
            )
        ],
        [
            InlineKeyboardButton(
                text="Food/Kitchen Ware",
                callback_data="Food/Kitchen Ware"
            ),
            InlineKeyboardButton(
                text="ArtnDesign",
                callback_data="ArtnDesign"
            )
        ]
    ]
    markup = InlineKeyboardMarkup(categories, one_time_keyboard=True)
    bot.send_message(
        chat_id=chat_id,
        text="Pick a category for your business from the options",
        reply_markup=markup
    )
    return SME_CAT

def business_details_update(update, context):
    bot = context.bot
    chat_id = update.callback_query.message.chat.id
    choice = update.callback_query.data
    # create business
    new_sme = client.query(
        q.create(
            q.collection("Business"),
            {"data":{
                "name":context.user_data["sme_dets"][0],
                "email":context.user_data["sme_dets"][1],
                "address":context.user_data["sme_dets"][2],
                "telephone":context.user_data["sme_dets"][3],
                "category":choice.lower()
            }}
        )
    )
    context.user_data["sme_name"] = context.user_data["sme_dets"][0]
    context.user_data["sme_id"] = new_sme["ref"].id()
    context.user_data["sme_cat"] = choice
    button = [[
        InlineKeyboardButton(
            text="Add a product",
            callback_data=choice.lower()
        )
    ]]
    bot.send_message(
        chat_id=chat_id,
        text="Business account created successfully, "
        "let's add some products shall we!.",
        reply_markup=InlineKeyboardMarkup(button)
    )
    return ADD_PRODUCTS
Enter fullscreen mode Exit fullscreen mode
  • 添加产品:这也涉及两种处理程序方法,第一种方法提示用户并提供如何添加产品的说明,而第二种方法接受用户输入,对其进行解析并使用它来创建新产品,将其作为新文档添加到我们的Fauna 实例上的产品集合中。
def add_product(update, context):
    bot = context.bot
    chat_id = update.callback_query.message.chat.id
    bot.send_message(
        chat_id=chat_id,
        text="Add the Name, Description, and Price of product, "
        "separated by commas(,) as caption to the product's image"
    )
    return ADD_PRODUCTS

def product_info(update: Update, context: CallbackContext):
    data = update.message
    bot = context.bot
    photo = bot.getFile(update.message.photo[-1].file_id)
    file_ = open('product_image', 'wb')
    photo.download(out=file_)
    data = update.message.caption.split(',')
    # upload image to cloudinary
    send_photo = upload('product_image', width=200, height=150, crop='thumb')
    # create new product
    newprod = client.query(
        q.create(
            q.collection("Product"),
            {"data": {
                    "name":data[0],
                    "description":data[1],
                    "price":float(data[2]),
                    "image":send_photo["secure_url"],
                    "sme":context.user_data["sme_name"],
                    "sme_chat_id": update.message.chat.id,
                    "category":context.user_data["sme_cat"]
                }
            }
        )
    )
    # add new product as latest
    client.query(
        q.update(
            q.ref(q.collection("Business"), context.user_data["sme_id"]),
            {"data": {
                "latest": newprod["ref"].id()
            }}
        )
    )
    # context.user_data["product_data"] = newprod['data']
    button = [[InlineKeyboardButton(
        text='Add another product',
        callback_data=context.user_data["sme_name"]
    )]]
    update.message.reply_text(
        "Added product successfully",
        reply_markup=InlineKeyboardMarkup(button)
    )
    return ADD_PRODUCTS
Enter fullscreen mode Exit fullscreen mode

机器人的业务部分到此结束。现在我们将添加更多处理方法来覆盖客户功能,如下所示:

  • 查看任何类别的企业:这涉及一个处理程序方法,该方法接受用户的选择并使用我们的business_by_category索引来查找该类别中的所有企业,然后显示企业列表及其最新商品作为缩略图,以及两个选项。
## CUSTOMER
def customer_pref(update, context):
    bot = context.bot
    chat_id = update.callback_query.message.chat.id
    data = update.callback_query.data
    print(data)
    # get all businesses in category
    try:
        smes_ = client.query(
            q.map_(
                lambda var: q.get(var),
                q.paginate(
                    q.match(
                        q.index("business_by_category"),
                        str(data).lower()
                    )
                )
            )
        )
        print(smes_)
        for sme in smes_["data"]:
            button = [
                [
                    InlineKeyboardButton(
                        text="View Products",
                        callback_data=sme["data"]["name"]
                    )
                ],
                [
                    InlineKeyboardButton(
                        text="Select for updates",
                        callback_data="pref"+','+sme["data"]["name"]
                    )
                ]
            ]
            if "latest" in sme['data'].keys():
                thumbnail = client.query(q.get(q.ref(q.collection("Product"), sme["data"]["latest"])))
                print(thumbnail)
                bot.send_photo(
                    chat_id=chat_id,
                    photo=thumbnail["data"]["image"],
                    caption=f"{sme['data']['name']}",
                    reply_markup=InlineKeyboardMarkup(button)
                )
            else:
                bot.send_message(
                    chat_id=chat_id,
                    text=f"{sme['data']['name']}",
                    reply_markup=InlineKeyboardMarkup(button)
                )
    except NotFound:
        button = [[
            InlineKeyboardButton(
                text="Select another Category?",
                callback_data="customer"
            )
        ]]
        bot.send_message(
            chat_id=chat_id,
            text="Nothing here yet",
            reply_markup=InlineKeyboardMarkup(button)
        )
        return CLASS_STATE
    return SHOW_STOCKS
Enter fullscreen mode Exit fullscreen mode
  • 查看产品:这部分功能非常直观,它列出了用户想要查看的任何商家的所有产品。借助我们之前在 Fauna 实例上创建的products_by_business索引,我们可以显示某个商家的所有产品。这意味着我们可以发送查询来获取该商家目录中的所有产品(使用products_by_business索引),然后将结果显示给用户。
def show_products(update, context):
    bot = context.bot
    chat_id = update.callback_query.message.chat.id
    data = update.callback_query.data
    if "pref" in  data:
        data = data.split(',')[0].replace(' ', '')
        print(data)
        user = client.query(
            q.get(
                q.ref(
                    q.match(q.index('user_by_name'), context.user_data['user-data']['name']),

                )
            )
        )
        # update preference
        client.query(
            q.update(
                q.ref(
                    q.collection('User'), user['ref'].id()
                ),
                {'data': {'preference': user['data']['preference']+data+','}}
            )
        )
        button = [
            [
                InlineKeyboardButton(
                    text="Vieew more businesses category",
                    callback_data='customer'
                )
            ]
        ]
        bot.send_message(
            chat_id=chat_id,
            text="Updated preference successfully!!"
        )
        return CLASS_STATE
    products = client.query(
        q.map_(
            lambda x: q.get(x),
            q.paginate(
                q.match(
                    q.index("product_by_business"),
                    update.callback_query.data
                )
            )
        )
    )
    # print(products)
    if len(products) <= 0:
        bot.send_message(
            chat_id=chat_id,
            text="'Nothing here yet, user hasn't added any products!, check back later"
        )
        return CLASS_STATE
    for product in products["data"]:
        context.user_data["sme_id"] = product['data']['sme']
        button = [
            [
                InlineKeyboardButton(
                    text="Send Order",
                    callback_data="order;" + product["ref"].id()
                )
            ],
            [
                InlineKeyboardButton(
                    text="Contact business owner",
                    callback_data="contact;" + product["data"]["sme"]
                )
            ]
        ]
        bot.send_photo(
            chat_id=chat_id,
            photo=product["data"]["image"],
            caption=f"{product['data']['name']} \nDescription: {product['data']['description']}\nPrice:{product['data']['price']}",
            reply_markup=InlineKeyboardMarkup(button)
        )
    return POST_VIEW_PRODUCTS
Enter fullscreen mode Exit fullscreen mode

这段代码负责从企业获取所有产品并将其显示给用户,并提供下订单联系企业主的选项。

  • 下订单和企业主的联系方式:以下模块负责下订单并向客户提供企业主的详细信息。当用户下订单时,机器人会向企业主发送一条消息,其中包含有关将要出售的产品的信息以及潜在买家的电报联系方式。
def post_view_products(update, context):
    bot = context.bot
    chat_id = update.callback_query.message.chat.id
    data = update.callback_query.data
    product = client.query(
        q.get(
            q.ref(
                q.collection("Product"),
                data.split(';')[1]
            )
        )
    )["data"]
    if "order" in data:
        bot.send_message(
            chat_id=product['sme_chat_id'],
            text="Hey you have a new order"
        )
        bot.send_photo(
            chat_id=product['sme_chat_id'],
            caption=f"Name: {product['name']}\n\nDescription: {product['description']}\n\nPrice: {product['price']}"
            f"\n\n Customer's Name: {context.user_data['user-name']}",
            photo=product['image']
        )  
        bot.send_contact(
            chat_id=product['sme_chat_id'],
            phone_number=context.user_data['user-data']['telephone'],
            first_name=context.user_data['user-data']['name']
        )
        bot.send_message(
            chat_id=chat_id,
            text="Placed order successfully"
        )
    elif 'contact' in data:
        sme_ = client.query(
            q.get( 
                q.match(
                    q.index("business_by_name"), 
                    product['sme']
                )
            )
        )['data']
        bot.send_message(
            chat_id=chat_id,
            text=f"Name: {sme_['name']}\n\nTelephone: {sme_['telephone']}\n\nEmail:{sme_['email']}"
        )

Enter fullscreen mode Exit fullscreen mode

测试机器人

我们可以将更改保存到我们的handlers.py文件中,然后继续将新添加的方法注册到main.py中的对话处理程序,就像前几个函数一样,如下所示:

import handlers
from telegram.ext import (
    CommandHandler, CallbackContext,
    ConversationHandler, MessageHandler,
    Filters, Updater, CallbackQueryHandler
)
from config import TOKEN

updater = Updater(token=TOKEN, use_context=True)
print(updater)
dispatcher = updater.dispatcher


def main():
    conv_handler = ConversationHandler(
        entry_points=[CommandHandler('start', handlers.start)],
        states={
            handlers.CHOOSING: [
                MessageHandler(
                    Filters.all, handlers.choose
                )
            ],
            handlers.CLASS_STATE: [
                CallbackQueryHandler(handlers.classer)
            ],
            handlers.SME_DETAILS: [
                MessageHandler(
                    Filters.all, handlers.business_details
                )
            ],
            handlers.SME_CAT: [
                CallbackQueryHandler(handlers.business_details_update)
            ],
            handlers.ADD_PRODUCTS: [
                CallbackQueryHandler(handlers.add_product),
                MessageHandler(Filters.all, handlers.product_info)
            ],
            handlers.CHOOSE_PREF: [
                CallbackQueryHandler(handlers.customer_pref)
            ],
            handlers.SHOW_STOCKS: [
                CallbackQueryHandler(handlers.show_products)
            ],
            handlers.POST_VIEW_PRODUCTS: [
                CallbackQueryHandler(handlers.post_view_products)
            ]
        },
        fallbacks=[CommandHandler('cancel', handlers.cancel)],
        allow_reentry=True
    )
    dispatcher.add_handler(conv_handler)
    updater.start_polling()
    updater.idle()

if __name__ == '__main__':
    main()
Enter fullscreen mode Exit fullscreen mode

更新main.py中的代码,使其具有我们添加的其他功能,如上所示。完成后,我们可以像以前一样从 cmd 运行我们的代码来测试我们的机器人。

启动并运行后,前往 Telegram 上的机器人,创建商家并添加产品。您也可以使用其他 Telegram 帐户以客户身份与机器人互动并下订单。

电报机器人回复的截图

屏幕截图显示了机器人在下新订单时向企业主发送的内容。

第二张图片显示的是每次客户下订单时企业主所看到的内容。

结论

在本文中,我们了解了如何使用 Fauna 的无服务器平台创建和托管数据库、索引和集合。我们还了解了如何生成 API 密钥,以便在其他 Python 应用(在本例中为 telegram-business)内部与数据库进行通信。我们还了解了如何使用 Python 和所需的库从头构建一个 Telegram 机器人。

然而,本文中的演示并不是Telegram 业务的终结,我将添加更多功能并尽快将其部署到实际环境中。我希望本文能够启发您思考新的方法来解决您周围的问题,并且当您最终找到解决方案时,您知道您可以随时依靠 Fauna 来轻松地托管您的数据,就像它在本文中帮助我们一样。

鏂囩珷鏉ユ簮锛�https://dev.to/curiouspaul1/building-an-e-commerce-telegram-bot-using-python-and-fauna-1hj5
PREV
每日编码问题 #1 问题 #1 我的解决方案 解释 DailyCodingProblem
NEXT
创建简单的 REST API 以进行实践自动化测试