最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin0浏览0评论
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!

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论