use matrix bot

This commit is contained in:
agatha 2024-09-15 18:02:25 -04:00
parent 544796e0ca
commit e07591b38b
4 changed files with 129 additions and 26 deletions

2
.gitignore vendored
View File

@ -4,4 +4,4 @@ venv/
__pycache__/ __pycache__/
*.py[cod] *.py[cod]
config.py config.json

89
matrix.py Normal file
View File

@ -0,0 +1,89 @@
import markdown
from loguru import logger
from nio import AsyncClient, LoginResponse
class MatrixBot:
def __init__(self, config: dict):
self.config = config
self.client = AsyncClient(
homeserver=self.config['homeserver'],
user=self.config['username']
)
self.logged_in = False
async def ensure_logged_in(self):
if not self.logged_in:
try:
response = await self.client.login(password=self.config['password'])
if isinstance(response, LoginResponse):
self.logged_in = True
logger.info(f"Logged in as {self.config['username']}")
else:
logger.error(f"Failed to login as {self.config['username']}: {response}")
logger.error("Closing nio session")
await self.client.close()
except Exception as e:
logger.error(f"Exception during login: {e}")
await self.client.close()
raise
async def send_message(self, message: str):
await self.ensure_logged_in()
if not self.logged_in:
logger.error("Unable to send message, login failed")
return
try:
await self.client.room_send(
room_id=self.config['room_id'],
message_type="m.room.message",
content={
"msgtype": "m.text",
"body": message
}
)
logger.info("Message sent")
except Exception as e:
logger.error(f"Exception during sending message: {e}")
raise
async def send_markdown(self, message: str):
await self.ensure_logged_in()
if not self.logged_in:
logger.error("Unable to send message, login failed")
return
try:
# Convert message to markdown
html = markdown.markdown(message)
# Send markdown formatted message
await self.client.room_send(
room_id=self.config['room_id'],
message_type="m.room.message",
content={
"msgtype": "m.text",
"body": message,
"format": "org.matrix.custom.html",
"formatted_body": html
}
)
logger.info("Markdown message sent")
except Exception as e:
logger.error(f"Exception during sending markdown message: {e}")
raise
async def close(self):
if self.logged_in:
try:
await self.client.logout()
self.logged_in = False
logger.info(f"Logged out from {self.config['homeserver']}")
except Exception as e:
logger.error(f"Exception during logout: {e}")
finally:
await self.client.close() # Ensure the client is closed

View File

@ -1,3 +1,5 @@
beautifulsoup4 beautifulsoup4
requests requests
loguru loguru
matrix-nio
markdown

View File

@ -1,9 +1,10 @@
"""buyvm stock checker""" """buyvm stock checker"""
import json
import asyncio
import requests import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from loguru import logger from loguru import logger
from matrix import MatrixBot
from config import DISCORD_WEBHOOK
BASE_URL = 'https://my.frantech.ca/' BASE_URL = 'https://my.frantech.ca/'
URLS = [ URLS = [
@ -14,13 +15,6 @@ URLS = [
] ]
def send_notification(payload):
try:
requests.post(DISCORD_WEBHOOK, json=payload)
except requests.RequestException as e:
logger.error(f'error sending notification: {str(e)}')
def get_url(url): def get_url(url):
try: try:
response = requests.get(url) response = requests.get(url)
@ -58,8 +52,20 @@ def get_packages(html):
return packages return packages
def main(): def load_config(filename):
with open(filename) as f:
return json.load(f)
async def main():
logger.info('checking buyvm stocks') logger.info('checking buyvm stocks')
# load configuration
config = load_config('config.json')
# initialize bot
bot = MatrixBot(config['matrix'])
for url in URLS: for url in URLS:
html = get_url(url) html = get_url(url)
@ -70,21 +76,27 @@ def main():
for package in packages: for package in packages:
if package['qty'] > 0: if package['qty'] > 0:
logger.info(f"{package['name']}: {package['qty']} in stock") logger.info(f"{package['name']}: {package['qty']} in stock")
send_notification({ await bot.send_message(f"{package['name']}: {package['qty']} in stock")
"username": "stockbot-buyvm",
"embeds": [ await bot.close()
{
"author": {
"name": "BuyVM", def main_with_shutdown():
}, loop = asyncio.get_event_loop()
"title": package['name'], main_task = loop.create_task(main())
"url": package['url'],
"description": f"{package['qty']} in stock now!" try:
} loop.run_until_complete(main_task)
], except asyncio.CancelledError:
"content": "STOCK ALERT" logger.info("Main task has been cancelled.")
}) finally:
pending_tasks = [t for t in asyncio.all_tasks(loop) if not t.done()]
if pending_tasks:
loop.run_until_complete(asyncio.gather(*pending_tasks, return_exceptions=True))
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()
logger.info("Event loop closed.")
if __name__ == '__main__': if __name__ == '__main__':
main() main_with_shutdown()