Commit inicial: Sales Bot - Sistema de Automatización de Ventas
- Stack completo con Mattermost, NocoDB y Sales Bot - Procesamiento OCR de tickets con Tesseract - Sistema de comisiones por tubos de tinte - Comandos slash /metas y /ranking - Documentación completa del proyecto Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
201
sales-bot/mattermost_client.py
Normal file
201
sales-bot/mattermost_client.py
Normal file
@@ -0,0 +1,201 @@
|
||||
import requests
|
||||
import logging
|
||||
import os
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class MattermostClient:
|
||||
def __init__(self, url, token):
|
||||
self.url = url.rstrip('/')
|
||||
self.token = token
|
||||
self.api_url = f"{self.url}/api/v4"
|
||||
self.headers = {
|
||||
'Authorization': f'Bearer {self.token}',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
self.webhook_url = os.getenv('MATTERMOST_WEBHOOK_URL')
|
||||
|
||||
def test_connection(self):
|
||||
"""Prueba la conexión con Mattermost"""
|
||||
try:
|
||||
response = requests.get(
|
||||
f"{self.api_url}/users/me",
|
||||
headers=self.headers,
|
||||
timeout=10
|
||||
)
|
||||
response.raise_for_status()
|
||||
user = response.json()
|
||||
logger.info(f"Conexión exitosa con Mattermost. Bot: {user.get('username')}")
|
||||
return {
|
||||
'status': 'success',
|
||||
'bot_username': user.get('username'),
|
||||
'bot_id': user.get('id')
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Error conectando con Mattermost: {str(e)}")
|
||||
return {'status': 'error', 'message': str(e)}
|
||||
|
||||
def get_channel_by_name(self, team_name, channel_name):
|
||||
"""Obtiene información de un canal por nombre"""
|
||||
try:
|
||||
# Primero obtener el team
|
||||
response = requests.get(
|
||||
f"{self.api_url}/teams/name/{team_name}",
|
||||
headers=self.headers,
|
||||
timeout=10
|
||||
)
|
||||
response.raise_for_status()
|
||||
team = response.json()
|
||||
team_id = team['id']
|
||||
|
||||
# Luego obtener el canal
|
||||
response = requests.get(
|
||||
f"{self.api_url}/teams/{team_id}/channels/name/{channel_name}",
|
||||
headers=self.headers,
|
||||
timeout=10
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
logger.error(f"Error obteniendo canal {channel_name}: {str(e)}")
|
||||
return None
|
||||
|
||||
def post_message(self, channel_id, message, props=None):
|
||||
"""Publica un mensaje en un canal"""
|
||||
try:
|
||||
payload = {
|
||||
'channel_id': channel_id,
|
||||
'message': message
|
||||
}
|
||||
if props:
|
||||
payload['props'] = props
|
||||
|
||||
response = requests.post(
|
||||
f"{self.api_url}/posts",
|
||||
headers=self.headers,
|
||||
json=payload,
|
||||
timeout=10
|
||||
)
|
||||
response.raise_for_status()
|
||||
logger.info(f"Mensaje publicado en canal {channel_id}")
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
logger.error(f"Error publicando mensaje: {str(e)}")
|
||||
return None
|
||||
|
||||
def post_message_webhook(self, message, username=None, icon_emoji=None):
|
||||
"""Publica un mensaje usando webhook incoming"""
|
||||
try:
|
||||
payload = {'text': message}
|
||||
if username:
|
||||
payload['username'] = username
|
||||
if icon_emoji:
|
||||
payload['icon_emoji'] = icon_emoji
|
||||
|
||||
response = requests.post(
|
||||
self.webhook_url,
|
||||
json=payload,
|
||||
timeout=10
|
||||
)
|
||||
response.raise_for_status()
|
||||
logger.info("Mensaje publicado via webhook")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Error publicando via webhook: {str(e)}")
|
||||
return False
|
||||
|
||||
def get_file(self, file_id):
|
||||
"""Descarga un archivo de Mattermost"""
|
||||
try:
|
||||
response = requests.get(
|
||||
f"{self.api_url}/files/{file_id}",
|
||||
headers=self.headers,
|
||||
timeout=30
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.content
|
||||
except Exception as e:
|
||||
logger.error(f"Error descargando archivo {file_id}: {str(e)}")
|
||||
return None
|
||||
|
||||
def get_file_info(self, file_id):
|
||||
"""Obtiene información de un archivo"""
|
||||
try:
|
||||
response = requests.get(
|
||||
f"{self.api_url}/files/{file_id}/info",
|
||||
headers=self.headers,
|
||||
timeout=10
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
logger.error(f"Error obteniendo info de archivo {file_id}: {str(e)}")
|
||||
return None
|
||||
|
||||
def upload_file(self, channel_id, file_content, filename):
|
||||
"""Sube un archivo a Mattermost"""
|
||||
try:
|
||||
files = {
|
||||
'files': (filename, file_content)
|
||||
}
|
||||
data = {
|
||||
'channel_id': channel_id
|
||||
}
|
||||
headers = {
|
||||
'Authorization': f'Bearer {self.token}'
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
f"{self.api_url}/files",
|
||||
headers=headers,
|
||||
files=files,
|
||||
data=data,
|
||||
timeout=30
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
logger.error(f"Error subiendo archivo: {str(e)}")
|
||||
return None
|
||||
|
||||
def add_reaction(self, post_id, emoji_name):
|
||||
"""Agrega una reacción a un post"""
|
||||
try:
|
||||
# Obtener el user_id del bot
|
||||
me = requests.get(
|
||||
f"{self.api_url}/users/me",
|
||||
headers=self.headers,
|
||||
timeout=10
|
||||
).json()
|
||||
|
||||
payload = {
|
||||
'user_id': me['id'],
|
||||
'post_id': post_id,
|
||||
'emoji_name': emoji_name
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
f"{self.api_url}/reactions",
|
||||
headers=self.headers,
|
||||
json=payload,
|
||||
timeout=10
|
||||
)
|
||||
response.raise_for_status()
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"Error agregando reacción: {str(e)}")
|
||||
return False
|
||||
|
||||
def get_user_by_username(self, username):
|
||||
"""Obtiene información de un usuario por username"""
|
||||
try:
|
||||
response = requests.get(
|
||||
f"{self.api_url}/users/username/{username}",
|
||||
headers=self.headers,
|
||||
timeout=10
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except Exception as e:
|
||||
logger.error(f"Error obteniendo usuario {username}: {str(e)}")
|
||||
return None
|
||||
Reference in New Issue
Block a user