mirror of
https://github.com/skylanix/MamieHenriette.git
synced 2026-02-06 06:40:35 +01:00
Compare commits
1 Commits
d5d3e45a62
...
api-timeou
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45347be85b |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,4 +3,5 @@
|
||||
**/.venv
|
||||
__pycache__
|
||||
instance
|
||||
logs
|
||||
.tio.tokens.json
|
||||
|
||||
@@ -5,6 +5,7 @@ WORKDIR /app
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV LANG=fr_FR.UTF-8
|
||||
ENV LC_ALL=fr_FR.UTF-8
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
apt-utils \
|
||||
@@ -34,7 +35,7 @@ RUN python3 -m venv /app/venv && \
|
||||
chmod +x /start.sh && \
|
||||
mkdir -p /app/logs
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||
HEALTHCHECK --interval=1s --timeout=10s --start-period=5s --retries=3 \
|
||||
CMD pgrep python > /dev/null && ! (tail -n 1000 $(ls -t /app/logs/*.log 2>/dev/null | head -1) 2>/dev/null | grep -iE "(ERROR|CRITICAL|Exception|sqlite3\.OperationalError)")
|
||||
|
||||
CMD ["/start.sh"]
|
||||
|
||||
@@ -44,10 +44,13 @@ class DiscordBot(discord.Client):
|
||||
return channels
|
||||
|
||||
|
||||
def begin(self) :
|
||||
def begin(self) :
|
||||
token = Configuration.query.filter_by(key='discord_token').first()
|
||||
if token :
|
||||
self.run(token.value)
|
||||
try:
|
||||
self.run(token.value)
|
||||
except Exception as e:
|
||||
logging.error(f'Erreur fatale lors du démarrage du bot Discord : {e}')
|
||||
else :
|
||||
logging.error('Aucun token Discord configuré. Le bot ne peut pas être démarré')
|
||||
|
||||
@@ -66,8 +69,10 @@ async def on_message(message: Message):
|
||||
commande = Commande.query.filter_by(discord_enable=True, trigger=command_name).first()
|
||||
if commande:
|
||||
try:
|
||||
await message.channel.send(commande.response, suppress_embeds=True)
|
||||
await asyncio.wait_for(message.channel.send(commande.response, suppress_embeds=True), timeout=30.0)
|
||||
return
|
||||
except asyncio.TimeoutError:
|
||||
logging.error(f'Timeout lors de l\'envoi de la commande Discord : {command_name}')
|
||||
except Exception as e:
|
||||
logging.error(f'Échec de l\'exécution de la commande Discord : {e}')
|
||||
|
||||
@@ -89,7 +94,9 @@ async def on_message(message: Message):
|
||||
if (rest > 0):
|
||||
msg += f'- et encore {rest} autres jeux'
|
||||
try :
|
||||
await message.channel.send(msg, suppress_embeds=True)
|
||||
await asyncio.wait_for(message.channel.send(msg, suppress_embeds=True), timeout=30.0)
|
||||
except asyncio.TimeoutError:
|
||||
logging.error(f'Timeout lors de l\'envoi du message ProtonDB')
|
||||
except Exception as e:
|
||||
logging.error(f'Échec de l\'envoi du message ProtonDB : {e}')
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import asyncio
|
||||
import datetime
|
||||
import logging
|
||||
import json
|
||||
@@ -14,11 +15,18 @@ def _isEnable():
|
||||
return helper.getValue('humble_bundle_enable') and helper.getIntValue('humble_bundle_channel') != 0
|
||||
|
||||
def _callGithub():
|
||||
response = requests.get("https://raw.githubusercontent.com/shionn/HumbleBundleGamePack/refs/heads/master/data/game-bundles.json")
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
logging.error(f"Échec de la connexion à la ressource Humble Bundle. Code de statut HTTP : {response.status_code}")
|
||||
return None
|
||||
try:
|
||||
response = requests.get("https://raw.githubusercontent.com/shionn/HumbleBundleGamePack/refs/heads/master/data/game-bundles.json", timeout=30)
|
||||
if response.status_code == 200:
|
||||
return response.json()
|
||||
logging.error(f"Échec de la connexion à la ressource Humble Bundle. Code de statut HTTP : {response.status_code}")
|
||||
return None
|
||||
except (requests.exceptions.SSLError, requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
|
||||
logging.error(f"Erreur de connexion à la ressource Humble Bundle : {e}")
|
||||
return None
|
||||
except Exception as e:
|
||||
logging.error(f"Erreur inattendue lors de la récupération des bundles : {e}")
|
||||
return None
|
||||
|
||||
def _isNotAlreadyNotified(bundle):
|
||||
return GameBundle.query.filter_by(url=bundle['url']).first() == None
|
||||
@@ -46,9 +54,14 @@ async def checkHumbleBundleAndNotify(bot: Client):
|
||||
bundle = _findFirstNotNotified(bundles)
|
||||
if bundle != None :
|
||||
message = _formatMessage(bundle)
|
||||
await bot.get_channel(ConfigurationHelper().getIntValue('humble_bundle_channel')).send(message)
|
||||
db.session.add(GameBundle(url=bundle['url'], name=bundle['name'], json = json.dumps(bundle)))
|
||||
db.session.commit()
|
||||
try:
|
||||
await asyncio.wait_for(bot.get_channel(ConfigurationHelper().getIntValue('humble_bundle_channel')).send(message), timeout=30.0)
|
||||
db.session.add(GameBundle(url=bundle['url'], name=bundle['name'], json = json.dumps(bundle)))
|
||||
db.session.commit()
|
||||
except asyncio.TimeoutError:
|
||||
logging.error(f'Timeout lors de l\'envoi du message Humble Bundle')
|
||||
except Exception as send_error:
|
||||
logging.error(f'Erreur lors de l\'envoi du message Humble Bundle : {send_error}')
|
||||
except Exception as e:
|
||||
logging.error(f"Échec de la vérification des offres Humble Bundle : {e}")
|
||||
else:
|
||||
|
||||
@@ -8,24 +8,38 @@ from database.helpers import ConfigurationHelper
|
||||
from database.models import GameAlias
|
||||
from sqlalchemy import desc,func
|
||||
|
||||
def _call_algoliasearch(search_name:str):
|
||||
config = SearchConfig(ConfigurationHelper().getValue('proton_db_api_id'),
|
||||
ConfigurationHelper().getValue('proton_db_api_key'))
|
||||
config.set_default_hosts()
|
||||
client = SearchClientSync(config=config)
|
||||
return client.search_single_index(index_name="steamdb",
|
||||
search_params={
|
||||
"query":search_name,
|
||||
"facetFilters":[["appType:Game"]],
|
||||
"hitsPerPage":50},
|
||||
request_options= {'headers':{'Referer':'https://www.protondb.com/'}})
|
||||
def _call_algoliasearch(search_name:str):
|
||||
try:
|
||||
config = SearchConfig(ConfigurationHelper().getValue('proton_db_api_id'),
|
||||
ConfigurationHelper().getValue('proton_db_api_key'))
|
||||
config.set_default_hosts()
|
||||
client = SearchClientSync(config=config)
|
||||
return client.search_single_index(index_name="steamdb",
|
||||
search_params={
|
||||
"query":search_name,
|
||||
"facetFilters":[["appType:Game"]],
|
||||
"hitsPerPage":50},
|
||||
request_options= {
|
||||
'headers':{'Referer':'https://www.protondb.com/'},
|
||||
'timeout': 30
|
||||
})
|
||||
except Exception as e:
|
||||
logging.error(f'Erreur lors de la recherche Algolia pour "{search_name}" : {e}')
|
||||
return None
|
||||
|
||||
def _call_summary(id):
|
||||
response = requests.get(f'http://jazzy-starlight-aeea19.netlify.app/api/v1/reports/summaries/{id}.json')
|
||||
if (response.status_code == 200) :
|
||||
return response.json()
|
||||
logging.error(f'Échec de la récupération des données ProtonDB pour le jeu {id}. Code de statut HTTP : {response.status_code}')
|
||||
return None
|
||||
try:
|
||||
response = requests.get(f'http://jazzy-starlight-aeea19.netlify.app/api/v1/reports/summaries/{id}.json', timeout=30)
|
||||
if (response.status_code == 200) :
|
||||
return response.json()
|
||||
logging.error(f'Échec de la récupération des données ProtonDB pour le jeu {id}. Code de statut HTTP : {response.status_code}')
|
||||
return None
|
||||
except (requests.exceptions.SSLError, requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
|
||||
logging.error(f'Erreur de connexion ProtonDB pour le jeu {id} : {e}')
|
||||
return None
|
||||
except Exception as e:
|
||||
logging.error(f'Erreur inattendue lors de la récupération ProtonDB pour le jeu {id} : {e}')
|
||||
return None
|
||||
|
||||
def _is_name_match(name:str, search_name:str) -> bool:
|
||||
normalized_game_name = re.sub("[^a-z0-9]", "", name.lower())
|
||||
@@ -37,10 +51,12 @@ def _apply_game_aliases(search_name:str) -> str:
|
||||
search_name = re.sub(re.escape(alias.alias), alias.name, search_name, flags=re.IGNORECASE)
|
||||
return search_name
|
||||
|
||||
def searhProtonDb(search_name:str):
|
||||
def searhProtonDb(search_name:str):
|
||||
results = []
|
||||
search_name = _apply_game_aliases(search_name)
|
||||
responses = _call_algoliasearch(search_name)
|
||||
if responses is None:
|
||||
return results
|
||||
for hit in responses.model_dump().get('hits'):
|
||||
id = hit.get('object_id')
|
||||
name:str = hit.get('name')
|
||||
|
||||
@@ -37,14 +37,16 @@ class TwitchBot() :
|
||||
if _isConfigured() :
|
||||
try :
|
||||
helper = ConfigurationHelper()
|
||||
self.twitch = await Twitch(helper.getValue('twitch_client_id'), helper.getValue('twitch_client_secret'))
|
||||
await self.twitch.set_user_authentication(helper.getValue('twitch_access_token'), USER_SCOPE, helper.getValue('twitch_refresh_token'))
|
||||
self.chat = await Chat(self.twitch)
|
||||
self.twitch = await asyncio.wait_for(Twitch(helper.getValue('twitch_client_id'), helper.getValue('twitch_client_secret')), timeout=30.0)
|
||||
await asyncio.wait_for(self.twitch.set_user_authentication(helper.getValue('twitch_access_token'), USER_SCOPE, helper.getValue('twitch_refresh_token')), timeout=30.0)
|
||||
self.chat = await asyncio.wait_for(Chat(self.twitch), timeout=30.0)
|
||||
self.chat.register_event(ChatEvent.READY, _onReady)
|
||||
self.chat.register_event(ChatEvent.MESSAGE, _onMessage)
|
||||
# chat.register_event(ChatEvent.SUB, on_sub)
|
||||
self.chat.register_command('hello', _helloCommand)
|
||||
self.chat.start()
|
||||
except asyncio.TimeoutError:
|
||||
logging.error('Timeout lors de la connexion à Twitch. Vérifiez votre connexion réseau.')
|
||||
except Exception as e:
|
||||
logging.error(f'Échec de l\'authentification Twitch. Vérifiez vos identifiants et redémarrez après correction : {e}')
|
||||
else:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from twitchAPI.twitch import Twitch
|
||||
@@ -36,14 +37,24 @@ async def _notifyAlert(alert : LiveAlert, stream : Stream):
|
||||
|
||||
async def _sendMessage(channel : int, message : str) :
|
||||
logger.info(f'Envoi de notification : {message}')
|
||||
await bot.get_channel(channel).send(message)
|
||||
logger.info(f'Notification envoyé')
|
||||
try:
|
||||
await asyncio.wait_for(bot.get_channel(channel).send(message), timeout=30.0)
|
||||
logger.info(f'Notification envoyée')
|
||||
except asyncio.TimeoutError:
|
||||
logger.error(f'Timeout lors de l\'envoi de notification live alert')
|
||||
except Exception as e:
|
||||
logger.error(f'Erreur lors de l\'envoi de notification live alert : {e}')
|
||||
|
||||
async def _retreiveStreams(twitch: Twitch, alerts : list[LiveAlert]) -> list[Stream] :
|
||||
streams : list[Stream] = []
|
||||
logger.info(f'Recherche de streams pour : {alerts}')
|
||||
async for stream in twitch.get_streams(user_login = [alert.login for alert in alerts]):
|
||||
streams.append(stream)
|
||||
logger.info(f'Ces streams sont en ligne : {streams}')
|
||||
try:
|
||||
async for stream in asyncio.wait_for(twitch.get_streams(user_login = [alert.login for alert in alerts]), timeout=30.0):
|
||||
streams.append(stream)
|
||||
logger.info(f'Ces streams sont en ligne : {streams}')
|
||||
except asyncio.TimeoutError:
|
||||
logger.error('Timeout lors de la récupération des streams Twitch')
|
||||
except Exception as e:
|
||||
logger.error(f'Erreur lors de la récupération des streams Twitch : {e}')
|
||||
return streams
|
||||
|
||||
|
||||
@@ -17,34 +17,53 @@ auth: UserAuthenticator
|
||||
def twitchConfigurationHelp():
|
||||
return render_template("twitch-aide.html", token_redirect_url = _buildUrl())
|
||||
|
||||
@webapp.route("/configurations/twitch/request-token")
|
||||
async def twitchRequestToken():
|
||||
@webapp.route("/configurations/twitch/request-token")
|
||||
async def twitchRequestToken():
|
||||
global auth
|
||||
helper = ConfigurationHelper()
|
||||
twitch = await Twitch(helper.getValue('twitch_client_id'), helper.getValue('twitch_client_secret'))
|
||||
auth = UserAuthenticator(twitch, USER_SCOPE, url=_buildUrl())
|
||||
return redirect(auth.return_auth_url())
|
||||
try:
|
||||
helper = ConfigurationHelper()
|
||||
import asyncio
|
||||
twitch = await asyncio.wait_for(
|
||||
Twitch(helper.getValue('twitch_client_id'), helper.getValue('twitch_client_secret')),
|
||||
timeout=30.0
|
||||
)
|
||||
auth = UserAuthenticator(twitch, USER_SCOPE, url=_buildUrl())
|
||||
return redirect(auth.return_auth_url())
|
||||
except asyncio.TimeoutError:
|
||||
logging.error('Timeout lors de la connexion à Twitch API pour la demande de token')
|
||||
return redirect(url_for('openConfigurations'))
|
||||
except TwitchAPIException as e:
|
||||
logging.error(f'Erreur API Twitch lors de la demande de token : {e}')
|
||||
return redirect(url_for('openConfigurations'))
|
||||
except Exception as e:
|
||||
logging.error(f'Erreur inattendue lors de la demande de token Twitch : {e}')
|
||||
return redirect(url_for('openConfigurations'))
|
||||
|
||||
@webapp.route("/configurations/twitch/receive-token")
|
||||
@webapp.route("/configurations/twitch/receive-token")
|
||||
async def twitchReceiveToken():
|
||||
global auth
|
||||
state = request.args.get('state')
|
||||
code = request.args.get('code')
|
||||
if state != auth.state :
|
||||
logging('bad returned state')
|
||||
logging.error('bad returned state')
|
||||
return redirect(url_for('openConfigurations'))
|
||||
if code == None :
|
||||
logging('no returned state')
|
||||
logging.error('no returned code')
|
||||
return redirect(url_for('openConfigurations'))
|
||||
|
||||
|
||||
try:
|
||||
token, refresh = await auth.authenticate(user_token=code)
|
||||
import asyncio
|
||||
token, refresh = await asyncio.wait_for(auth.authenticate(user_token=code), timeout=30.0)
|
||||
helper = ConfigurationHelper()
|
||||
helper.createOrUpdate('twitch_access_token', token)
|
||||
helper.createOrUpdate('twitch_refresh_token', refresh)
|
||||
db.session.commit()
|
||||
except asyncio.TimeoutError:
|
||||
logging.error('Timeout lors de l\'authentification Twitch')
|
||||
except TwitchAPIException as e:
|
||||
logging(e)
|
||||
logging.error(f'Erreur API Twitch lors de l\'authentification : {e}')
|
||||
except Exception as e:
|
||||
logging.error(f'Erreur inattendue lors de l\'authentification Twitch : {e}')
|
||||
return redirect(url_for('openConfigurations'))
|
||||
|
||||
# hack pas fou mais on estime qu'on sera toujours en ssl en connecté
|
||||
|
||||
Reference in New Issue
Block a user