Open thkaw opened 3 weeks ago
Thank you for using line-bot-sdk-python, @thkaw !
To better understand the issue, could you provide a minimal yet sufficient and reproducible code example?
For instance, this example should work: https://github.com/line/line-bot-sdk-python/blob/bdda65fd8dbc715e91564a05d146f4c2c0ed9511/examples/flask-kitchensink/app.py#L324-L351
Hi @Yang-33 , Thanks for quick replied.
The example you mention is OK, also I use that as my workaround sofar. However, it will gen following waring log if line_bot_api.reply_message have been invoked
C:\Users\ar801\PycharmProjects\egolden\playground.py:44: LineBotSdkDeprecatedIn30: Call to deprecated method reply_message. (Use 'from linebot.v3.messaging import MessagingApi' and 'MessagingApi(...).reply_message(...)' instead. See https://github.com/line/line-bot-sdk-python/blob/master/README.rst for more details.) -- Deprecated since version 3.0.0. line_bot_api.reply_message(reply_token, carousel)
Here I put the sample for my question, you should able to reproduce problem by using this code snippet
from flask import Flask, request, abort
from linebot.v3 import WebhookHandler
from linebot.v3.exceptions import InvalidSignatureError
from linebot.v3.messaging import Configuration, ApiClient, MessagingApi, ReplyMessageRequest
from linebot.v3.webhooks import MessageEvent, TextMessageContent
from linebot import LineBotApi
from linebot.models import TemplateSendMessage, CarouselTemplate, CarouselColumn, MessageAction
app = Flask(__name__)
ATOKEN = "PUT YOUR ACCESS TOKEN"
configuration = Configuration(
access_token=ATOKEN)
handler = WebhookHandler('PUT YOUR WEBHOOK CREDENTIAL HERE')
# 初始化 MessagingApi
api_client = ApiClient(configuration=configuration)
messaging_api = MessagingApi(api_client)
line_bot_api = LineBotApi(ATOKEN)
def get_carousel_template_first_use():
return TemplateSendMessage(
alt_text='this is a carousel template',
template=CarouselTemplate(
columns=[
CarouselColumn(
text='QUESTION',
actions=[
MessageAction(
label='ANS A',
text='ANS A'
),
MessageAction(
label='ANS B',
text='ANS B'
)
]
)
]
)
)
@app.route("/callback", methods=['POST'])
def callback():
signature = request.headers['X-Line-Signature']
body = request.get_data(as_text=True)
app.logger.info("Request body: " + body)
try:
handler.handle(body, signature)
except InvalidSignatureError:
app.logger.info("Invalid signature. Please check your channel access token/channel secret.")
abort(400)
return 'OK'
@handler.add(MessageEvent, message=TextMessageContent)
def handle_message(event):
user_id = event.source.user_id
message_text = event.message.text
reply_carousel(event.reply_token, get_carousel_template_first_use())
# OK case
# def reply_carousel(reply_token, carousel):
# line_bot_api.reply_message(reply_token, carousel)
# NG case
def reply_carousel(reply_token, carousel): #carousel is a TemplateSendMessage object
carousel_dict = {
"type": "template",
"altText": carousel.alt_text,
"template": {
"type": "carousel",
"columns": [
{
"text": column.text,
"actions": [
{
"type": action.type,
"label": action.label,
"text": action.text
} for action in column.actions
]
} for column in carousel.template.columns
]
}
}
messaging_api.reply_message(
ReplyMessageRequest(
reply_token=reply_token,
messages=[carousel_dict]
)
)
if __name__ == "__main__":
app.run(host="0.0.0.0")
thanks, ok let me check the example. (it takes time)
Note the example I provided uses v3 modules instead of deprecated modules.
I think there are two solutions. The v3 model does not assume passing a dictionary to a method. However, each class in the v3 model has a #from_dict
, so you can call that.
For example,
- messages=[carousel_dict]
+ from linebot.v3.messaging import TemplateMessage
+ messages=[TemplateMessage.from_dict(carousel_dict)]
Another solution is to stop using dictionaries.
I'm currently working on a project using the LINE bot SDK for Python, and I've encountered an issue with the ReplyMessageRequest when sending messages using reply_message.
In the process of converting to ReplyMessageRequest, the messages field can contain multiple different types (e.g., TextMessageContent, FlexMessage). While using .from_dict works for sending the messages, the format of the dict varies significantly.
Additionally, when running the example code from flask-kitchensink, I encounter the following error:
pydantic.v1.error_wrappers.ValidationError: 1 validation error for ReplyMessageRequest
messages -> 0
value is not a valid dict (type=type_error.dict)
Is there a more general way to handle the different message types in ReplyMessageRequest?
Could you specify in which cases the sample fails? I would like a minimal reproducible code that can demonstrate the issue. As I checked this now, no errors occurred in flask-kitchensink as you said. The error message indicates that the data you provided is not a dictionary.
Sorry, I discovered that my issue was caused by simultaneously importing
from linebot.v3.messaging import (
TextMessage
)
and
from linebot.models import *
This led to the error. It has now been resolved. Thank you.
I think there are two solutions. The v3 model does not assume passing a dictionary to a method. However, each class in the v3 model has a
#from_dict
, so you can call that. For example,- messages=[carousel_dict] + from linebot.v3.messaging import TemplateMessage + messages=[TemplateMessage.from_dict(carousel_dict)]
Another solution is to stop using dictionaries.
Thank you provide the information.
However, if I try to change carousel into TemplateSendMessage type (linebot.models.template.TemplateSendMessage)
def reply_carousel(reply_token, carousel):
try:
# OK
# line_bot_api.reply_message(reply_token, carousel)
messaging_api.reply_message(
ReplyMessageRequest(
reply_token=reply_token,
messages=carousel #NG here
)
)
Error shows:
pydantic.v1.error_wrappers.ValidationError: 1 validation error for ReplyMessageRequest messages value is not a valid list (type=type_error.list)
Is any possible to pass TemplateSendMessage type to reply_message function?
When I reply with carousel template, I found in V3 api won't work, and give folloing error code:
To make sure I really set altText & template attribute, I event write the dict sperately.
NG code
So, I tried rollback to old api method, that will be fine.
Is any limitation between new SDK API and carousel template? Thanks in advance!