flask - Slack API in python,buttons working with ngrok, not working after moving to vultr? - solved - Stack Overflow

import osimport jsonimport loggingfrom slack_bolt import Appfrom slack_bolt.adapter.flask import Sl

import os
import json
import logging
from slack_bolt import App
from slack_bolt.adapter.flask import SlackRequestHandler
from flask import Flask, request, jsonify
from dotenv import load_dotenv


os.environ.pop("SLACK_SIGNING_SECRET", None)
os.environ.pop("SLACK_BOT_TOKEN", None)
load_dotenv()  # Reload .env values
# Configure logging
logging.basicConfig(level=logging.INFO)

# Initialize your Flask application and Slack app
app = App(token=os.environ['SLACK_BOT_TOKEN'], signing_secret=os.environ['SLACK_SIGNING_SECRET'])
flask_app = Flask(__name__)
handler = SlackRequestHandler(app)

# List of admin user IDs
ADMIN_USER_IDS = ["user"]  # Replace with actual admin user IDs

# Dictionary to store polls with votes
polls = {}

# Function to send a message with buttons for the poll
def send_poll_message(channel_id, question, button1_text, button2_text, poll_id):
    button_elements = [
        {"type": "button", "text": {"type": "plain_text", "text": button1_text}, 
         "action_id": "button_1_click", "value": poll_id},
        {"type": "button", "text": {"type": "plain_text", "text": button2_text}, 
         "action_id": "button_2_click", "value": poll_id}
    ]

    app.client.chat_postMessage(channel=channel_id, text=question, blocks=[
        {"type": "section", "text": {"type": "mrkdwn", "text": question}},
        {"type": "actions", "elements": button_elements}
    ])

# Endpoint to receive the slash command to start a poll
@flask_app.route("/send_poll", methods=["POST"])
def send_poll_endpoint():
    data = request.form
    channel_id = data.get("channel_id")
    user_id = data.get("user_id")  # Get the user ID of the person who initiated the poll
    text = data.get("text").strip().split('|')

    if len(text) != 3:
        return jsonify({"response_type": "ephemeral", "text": "Correct format: `/send_poll <Question> | <Button1> | <Button2>`"}), 200

    question, button1_text, button2_text = map(str.strip, text)
    poll_id = str(len(polls) + 1)

    polls[poll_id] = {
        "question": question,
        "button1_text": button1_text,
        "button2_text": button2_text,
        "button1_votes": [],
        "button2_votes": []
    }

    send_poll_message(channel_id, question, button1_text, button2_text, poll_id)

    # Send poll ID only to admins
    if user_id in ADMIN_USER_IDS:
        return jsonify({"response_type": "ephemeral", "text": f"Poll initiated! Your poll ID is: {poll_id}"}), 200

    return jsonify({"response_type": "ephemeral", "text": "Poll initiated!"}), 200

# Endpoint to receive the slash command for poll results
@flask_app.route("/poll_results", methods=["POST"])
def poll_results_command():
    data = request.form
    user_id = data.get("user_id")  # Get the user ID who initiated the command
    text = data.get("text").strip()  # Get the poll ID from the command text

    # Check if the user is an admin
    if user_id not in ADMIN_USER_IDS:
        return jsonify({"response_type": "ephemeral", "text": "Sorry, this command is restricted to admins only."}), 200

    if not text:
        return jsonify({"response_type": "ephemeral", "text": "Please provide a poll ID. Usage: `/poll_results <poll_id>`"}), 200

    poll_id = text

    # Check if the poll_id exists
    if poll_id not in polls:
        return jsonify({"response_type": "ephemeral", "text": "Poll ID not found!"}), 404

    poll = polls[poll_id]
    
    # Format voter IDs into @user format
    button1_voters = [f"<@{user}>" for user in poll['button1_votes']]
    button2_voters = [f"<@{user}>" for user in poll['button2_votes']]

    results_message = (
        f"*Poll Question:* {poll['question']}\n"
        f"*Votes for {poll['button1_text']}:* {len(poll['button1_votes'])}\n"
        f"*Voters for {poll['button1_text']}:* {', '.join(button1_voters) if button1_voters else 'No votes yet'}\n"
        f"*Votes for {poll['button2_text']}:* {len(poll['button2_votes'])}\n"
        f"*Voters for {poll['button2_text']}:* {', '.join(button2_voters) if button2_voters else 'No votes yet'}\n"
    )
    
    return jsonify({"response_type": "ephemeral", "text": results_message}), 200

# Endpoint to receive interactions from Slack
@flask_app.route("/slack/actions", methods=["POST"])
def slack_actions():
    raw_body = request.get_data(as_text=True)
    logging.info("Received raw request body: %s", raw_body)

    content_type = request.headers.get('Content-Type')
    logging.info("Received interaction with Content-Type: %s", content_type)

    if content_type == 'application/x-www-form-urlencoded':
        payload = request.form.get('payload')
        if payload:
            payload_data = json.loads(payload)
            logging.info("Processing interaction: %s", payload_data)
            return handler.handle(request)
    elif content_type == 'application/json':
        return handler.handle(request)

    return jsonify({"error": "Unsupported Media Type"}), 415

# Handle button clicks for option 1
@app.action("button_1_click")
def handle_button_click_1(ack, body):
    ack()
    logging.info("Button 1 clicked: %s", body)

    poll_id = body['actions'][0]['value']
    user_id = body['user']['id']

    # Check if the user has already voted
    if user_id in polls[poll_id]["button1_votes"] or user_id in polls[poll_id]["button2_votes"]:
        app.client.chat_postMessage(channel=user_id, text="You have already voted in this poll!")
    else:
        # Append user vote if not already voted
        polls[poll_id]["button1_votes"].append(user_id)
        app.client.chat_postMessage(channel=user_id, text="Thank you for voting for " + polls[poll_id]["button1_text"] + "!")

# Handle button clicks for option 2
@app.action("button_2_click")
def handle_button_click_2(ack, body):
    ack()
    logging.info("Button 2 clicked: %s", body)

    poll_id = body['actions'][0]['value']
    user_id = body['user']['id']

    # Check if the user has already voted
    if user_id in polls[poll_id]["button1_votes"] or user_id in polls[poll_id]["button2_votes"]:
        app.client.chat_postMessage(channel=user_id, text="You have already voted in this poll!")
    else:
        # Append user vote if not already voted
        polls[poll_id]["button2_votes"].append(user_id)
        app.client.chat_postMessage(channel=user_id, text="Thank you for voting for " + polls[poll_id]["button2_text"] + "!")

# Starting the Flask server
if __name__ == "__main__":
    flask_app.run(port=3000)

the problem is 404 problem when pressing buttons after initiating a message with 2 buttons with this app. in ngrok it works properly no error, but in gunicorn from vultr it returns the 404 error.

this code i put, work correctly in my tests with ngrok, but the moment i move it to vultr and run it with gunicorn the buttons return errors(404) i tried going through it with chatgpt but his solutions only brought me different error codes like 415 or keyError 1. i cant understand how it will work in ngrok and not in my actual server? i am very new to this and its my first time try to deploy something on a server, but things i did for clarification are: running the vultr server, installing nginx and running certbot on a domain, replaced my slack app config routes for interactivity and slash commands from the ngrok address to my domain address(also tried direct ip from vultr with no luck as well) and running the app with gunicorn. really hope someone can help me shed light what im doing wrong. thank you so much!

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742379460a4432837.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信