Did some modifications...
This commit is contained in:
247
app/helpers.py
247
app/helpers.py
@@ -1,3 +1,4 @@
|
||||
import datetime
|
||||
import logging
|
||||
import requests
|
||||
from database import * # Import all DB functions
|
||||
@@ -389,9 +390,9 @@ def format_last_participants_list(participants_list: list) -> str:
|
||||
if numbers_str:
|
||||
num_list = numbers_str.split(',')
|
||||
if len(num_list) == 1:
|
||||
line = f" - {user_name}, con la papeleta: {num_list[0]}"
|
||||
line = f" - {user_name}, con la participación: {num_list[0]}"
|
||||
else:
|
||||
line = f" - {user_name}, con las papeletas: {', '.join(num_list)}"
|
||||
line = f" - {user_name}, con las participaciones: {', '.join(num_list)}"
|
||||
formatted_lines.append(line)
|
||||
|
||||
return "\n".join(formatted_lines) # Add a trailing newline
|
||||
@@ -482,3 +483,245 @@ def get_paypal_amounts_for_invoice(invoice_id):
|
||||
net_amount = float(breakdown.get("net_amount", {}).get("value", gross_amount))
|
||||
|
||||
return gross_amount, net_amount, fee_amount
|
||||
|
||||
def is_vip_member_of_homelabs(user_id):
|
||||
"""Checks if a Telegram user ID is a VIP member of HomeLabs via the Homelabs API."""
|
||||
if not HOMELABS_API_TOKEN or not HOMELABS_API_URL:
|
||||
logger.warning("Homelabs API configuration is missing.")
|
||||
return False # If not configured, treat as non-member
|
||||
|
||||
url = f"{HOMELABS_API_URL}/users/{user_id}"
|
||||
headers = {
|
||||
"X-API-Key": HOMELABS_API_TOKEN,
|
||||
"Accept": "application/json",
|
||||
}
|
||||
|
||||
try:
|
||||
response = requests.get(url, headers=headers, timeout=5)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
if data.get("is_lifetime") == True:
|
||||
return True
|
||||
if data.get("member_until") >= datetime.datetime.now(datetime.timezone.utc).date().isoformat():
|
||||
return True
|
||||
return False
|
||||
elif response.status_code == 404:
|
||||
return False # User not found, hence not a member
|
||||
else:
|
||||
logger.error(f"Unexpected response from Homelabs API: {response.status_code} - {response.text}")
|
||||
return False
|
||||
except requests.RequestException as e:
|
||||
logger.error(f"Error connecting to Homelabs API: {e}")
|
||||
return False
|
||||
|
||||
def send_raffle_update_image(raffle_id, current_user_name=None, numbers=None, bot_token=None):
|
||||
"""
|
||||
Sends or updates the raffle table image to the appropriate channel.
|
||||
Can be used for payment confirmations or manual updates from admin.
|
||||
|
||||
Args:
|
||||
raffle_id: The ID of the raffle
|
||||
current_user_name: Name of the user who just joined (optional, for payment updates)
|
||||
numbers: List of numbers the user selected (optional, for payment updates)
|
||||
bot_token: Telegram bot token for API calls
|
||||
|
||||
Returns:
|
||||
bool: True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
# Import here to avoid circular imports
|
||||
import json
|
||||
|
||||
if not bot_token:
|
||||
bot_token = BOT_TOKEN
|
||||
|
||||
TELEGRAM_API_URL = f"https://api.telegram.org/bot{bot_token}"
|
||||
|
||||
# Generate table image
|
||||
if not generate_table_image(raffle_id):
|
||||
logger.error(f"Failed to generate raffle table image for {raffle_id}")
|
||||
return False
|
||||
|
||||
image_path = f"/app/data/raffles/raffle_table_{raffle_id}.png"
|
||||
|
||||
# Get raffle details
|
||||
raffle_details = get_raffle(raffle_id)
|
||||
if not raffle_details:
|
||||
logger.error(f"Could not fetch raffle details for ID {raffle_id}")
|
||||
return False
|
||||
|
||||
raffle_name = raffle_details['name']
|
||||
raffle_description_for_announce = raffle_details['description'][:350]
|
||||
channel_id_to_announce = raffle_details['channel_id']
|
||||
original_price_per_number = raffle_details['price']
|
||||
remaining_numbers_amount = get_remaining_numbers_amount(raffle_id)
|
||||
|
||||
# Determine keyboard and caption based on remaining numbers
|
||||
keyboard = None
|
||||
if remaining_numbers_amount == 0:
|
||||
# Raffle is complete
|
||||
main_announcement = f"🎯🏆🎯 <b>Sorteo '{raffle_name}' terminado</b> 🎯🏆🎯\n\n"
|
||||
main_announcement += f"{raffle_description_for_announce}\n\n"
|
||||
main_announcement += f"🌍 Envío internacional: {'Sí ✅' if raffle_details['international_shipping'] else 'No ❌'}\n"
|
||||
main_announcement += f"💵 <b>Donación mínima:</b> {original_price_per_number}€\n"
|
||||
main_announcement += f"📜 <b>Normas y condiciones:</b> {TYC_DOCUMENT_URL}"
|
||||
|
||||
# Update main message to remove participate button
|
||||
main_message_id = get_main_message_id(raffle_id)
|
||||
if main_message_id:
|
||||
requests.post(f"{TELEGRAM_API_URL}/editMessageCaption", json={
|
||||
"chat_id": channel_id_to_announce,
|
||||
"message_id": main_message_id,
|
||||
"caption": main_announcement,
|
||||
"reply_markup": None,
|
||||
"parse_mode": "HTML"
|
||||
})
|
||||
else:
|
||||
# Raffle still in progress
|
||||
url = f"https://t.me/{BOT_NAME}?start=join_{raffle_id}"
|
||||
keyboard = {
|
||||
"inline_keyboard": [
|
||||
[
|
||||
{"text": "✅ ¡Participar Ahora! ✅", "url": url}
|
||||
]
|
||||
]
|
||||
}
|
||||
main_announcement = f"🏆 Sorteo '{raffle_name}' en progreso 🏆\n\n"
|
||||
main_announcement += f"{raffle_description_for_announce}\n\n"
|
||||
main_announcement += f"🌍 Envío internacional: {'Sí ✅' if raffle_details['international_shipping'] else 'No ❌'}\n"
|
||||
main_announcement += f"💵 <b>Donación mínima:</b> {original_price_per_number}€\n"
|
||||
main_announcement += f"🗒️ Quedan {remaining_numbers_amount} participaciones disponibles. ¡Date prisa! 🗒️\n\n"
|
||||
main_announcement += f"📜 <b>Normas y condiciones:</b> {TYC_DOCUMENT_URL}"
|
||||
|
||||
# Update main message
|
||||
main_message_id = get_main_message_id(raffle_id)
|
||||
if main_message_id:
|
||||
requests.post(f"{TELEGRAM_API_URL}/editMessageCaption", json={
|
||||
"chat_id": channel_id_to_announce,
|
||||
"message_id": main_message_id,
|
||||
"caption": main_announcement,
|
||||
"reply_markup": keyboard,
|
||||
"parse_mode": "HTML"
|
||||
})
|
||||
|
||||
# Build caption for update message
|
||||
caption = ""
|
||||
|
||||
# Add participant info if provided (for payment confirmations)
|
||||
if current_user_name and numbers:
|
||||
escaped_current_user_name = current_user_name
|
||||
numbers_text = ""
|
||||
if len(numbers) > 1:
|
||||
numbers_text = f"con las participaciones: {', '.join(numbers)}"
|
||||
else:
|
||||
numbers_text = f"con la participación: {', '.join(numbers)}"
|
||||
|
||||
new_participant_line = f"🗳️ @{escaped_current_user_name} se ha unido al sorteo {numbers_text}. ¡Mucha suerte! 🗳️"
|
||||
caption += f"{new_participant_line}\n\n"
|
||||
|
||||
# Add last participants
|
||||
last_other_participants = get_last_n_other_participants(raffle_id, n=4)
|
||||
last_participants_text = format_last_participants_list(last_other_participants)
|
||||
caption += f"{last_participants_text}\n\n"
|
||||
|
||||
# Add remaining numbers info
|
||||
remaining_numbers_text = ""
|
||||
if remaining_numbers_amount > 10:
|
||||
remaining_numbers_text = f"🗒️ Todavía hay {remaining_numbers_amount} participaciones disponibles. 🗒️"
|
||||
elif remaining_numbers_amount == 1:
|
||||
remaining_numbers = get_remaining_numbers(raffle_id)
|
||||
remaining_numbers_text = f"⏰⏰⏰ ¡Última participación! ⏰⏰⏰\n\n"
|
||||
remaining_numbers_text += f"Queda la participación: {remaining_numbers[0]}"
|
||||
elif remaining_numbers_amount == 0:
|
||||
remaining_numbers_text = "⌛ ¡Ya no hay participaciones! ⌛\n\n"
|
||||
remaining_numbers_text += "¡El resultado del sorteo se dará a conocer a las 21:45h!"
|
||||
else:
|
||||
remaining_numbers = get_remaining_numbers(raffle_id)
|
||||
remaining_numbers_text = f"🔔🔔🔔 ¡Últimas {remaining_numbers_amount} participaciones disponibles! 🔔🔔🔔\n\n"
|
||||
remaining_numbers_text += f"Quedan las participaciones: {', '.join(remaining_numbers)}"
|
||||
|
||||
caption += f"{remaining_numbers_text}\n\n"
|
||||
|
||||
# Add raffle description and details
|
||||
caption += (
|
||||
f"{raffle_description_for_announce}\n\n"
|
||||
f"🔎 Ver detalles: https://t.me/{REVERSE_CHANNELS.get(channel_id_to_announce)}/{get_main_message_id(raffle_id)}\n\n"
|
||||
f"🌍 Envío internacional: {'Sí ✅' if raffle_details['international_shipping'] else 'No ❌'}\n"
|
||||
f"💵 Donación mínima: {original_price_per_number}€\n\n"
|
||||
f"📜 Normas y condiciones: {TYC_DOCUMENT_URL} \n\n"
|
||||
)
|
||||
|
||||
# Send or update the image message
|
||||
update_message_id = get_update_message_id(raffle_id)
|
||||
sent_or_edited_message_id = None
|
||||
|
||||
if update_message_id:
|
||||
logger.info(f"Attempting to delete old message {update_message_id} and send new one in channel {channel_id_to_announce}")
|
||||
|
||||
# Try deleting old message first
|
||||
try:
|
||||
delete_payload = {'chat_id': channel_id_to_announce, 'message_id': update_message_id}
|
||||
delete_response = requests.post(f"{TELEGRAM_API_URL}/deleteMessage", data=delete_payload)
|
||||
if delete_response.status_code == 200:
|
||||
logger.info(f"Successfully deleted old message {update_message_id} in channel {channel_id_to_announce}")
|
||||
else:
|
||||
logger.warning(f"Failed to delete old message {update_message_id} in channel {channel_id_to_announce}: {delete_response.text}")
|
||||
except Exception as e_del:
|
||||
logger.warning(f"Error deleting old message {update_message_id}: {e_del}")
|
||||
|
||||
# Always send new photo after delete attempt
|
||||
files = {'photo': open(image_path, 'rb')}
|
||||
data = {
|
||||
'chat_id': channel_id_to_announce,
|
||||
'caption': caption,
|
||||
'parse_mode': 'HTML'
|
||||
}
|
||||
if keyboard:
|
||||
data['reply_markup'] = json.dumps(keyboard)
|
||||
|
||||
try:
|
||||
response = requests.post(f"{TELEGRAM_API_URL}/sendPhoto", data=data, files=files)
|
||||
response.raise_for_status()
|
||||
logger.info(f"Sent new photo to channel {channel_id_to_announce}")
|
||||
message_data = response.json().get('result')
|
||||
if message_data and 'message_id' in message_data:
|
||||
sent_or_edited_message_id = message_data['message_id']
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Error sending new photo to channel {channel_id_to_announce}: {e}")
|
||||
return False
|
||||
finally:
|
||||
files['photo'].close()
|
||||
else:
|
||||
# No previous message, send new
|
||||
logger.info(f"No previous message found for raffle {raffle_id} in channel {channel_id_to_announce}. Sending new.")
|
||||
files = {'photo': open(image_path, 'rb')}
|
||||
data = {
|
||||
'chat_id': channel_id_to_announce,
|
||||
'caption': caption,
|
||||
'parse_mode': 'HTML'
|
||||
}
|
||||
if keyboard:
|
||||
data['reply_markup'] = json.dumps(keyboard)
|
||||
|
||||
try:
|
||||
response = requests.post(f"{TELEGRAM_API_URL}/sendPhoto", data=data, files=files)
|
||||
response.raise_for_status()
|
||||
logger.info(f"Sent photo to channel {channel_id_to_announce}")
|
||||
message_data = response.json().get('result')
|
||||
if message_data and 'message_id' in message_data:
|
||||
sent_or_edited_message_id = message_data['message_id']
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Error sending photo to channel {channel_id_to_announce}: {e}")
|
||||
return False
|
||||
finally:
|
||||
files['photo'].close()
|
||||
|
||||
# Store the new message ID for future updates
|
||||
if sent_or_edited_message_id:
|
||||
store_update_message_id(raffle_id, sent_or_edited_message_id)
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in send_raffle_update_image for raffle {raffle_id}: {e}")
|
||||
return False
|
||||
Reference in New Issue
Block a user