120 lines
3.5 KiB
Python
120 lines
3.5 KiB
Python
import os
|
|
import requests
|
|
import schedule
|
|
import hashlib
|
|
import time
|
|
from datetime import datetime
|
|
from bs4 import BeautifulSoup
|
|
|
|
|
|
URL_TO_MONITOR = "https://univesp.br/vestibular"
|
|
HASH_FILE = os.path.join("/data", "last_hash.txt")
|
|
NTFY_URL = os.getenv("NTFY_URL")
|
|
FLARESOLVERR_URL = os.getenv("FLARESOLVERR_URL")
|
|
MONITOR_SELECTOR = os.getenv("MONITOR_SELECTOR", "div.conteudo")
|
|
|
|
|
|
def send_notification(message):
|
|
if not NTFY_URL:
|
|
print(f"[{datetime.now()}] ⚠️ NTFY_URL not set. Skipping notification.")
|
|
return
|
|
|
|
try:
|
|
headers = {
|
|
"Title": "Univesper Notification",
|
|
"Priority": "high",
|
|
"Tags": "univesper"
|
|
}
|
|
requests.post(NTFY_URL, data=message.encode("utf-8"), headers=headers)
|
|
print(f"[{datetime.now()}] ✅ Notification sent to ntfy.")
|
|
except Exception as e:
|
|
print(f"[{datetime.now()}] ❌ Failed to send notification: {e}")
|
|
|
|
|
|
|
|
def get_page_hash(url):
|
|
print(f"[{datetime.now()}] Requesting page via FlareSolverr...")
|
|
|
|
payload = {
|
|
"cmd": "request.get",
|
|
"url": url,
|
|
"maxTimeout": 60000
|
|
}
|
|
|
|
headers = {
|
|
"Content-Type": "application/json"
|
|
}
|
|
|
|
try:
|
|
response = requests.post(FLARESOLVERR_URL, json=payload, headers=headers)
|
|
response.raise_for_status()
|
|
|
|
fs_response = response.json()
|
|
if fs_response['status'] == 'ok':
|
|
html_content = fs_response['solution']['response']
|
|
print(f"[{datetime.now()}] FlareSolverr request successful.")
|
|
|
|
soup = BeautifulSoup(html_content, 'html.parser')
|
|
element = soup.select_one(MONITOR_SELECTOR)
|
|
|
|
if element:
|
|
return hashlib.sha256(str(element).encode('utf-8')).hexdigest()
|
|
else:
|
|
print(f"[{datetime.now()}] ❌ Element '{MONITOR_SELECTOR}' not found in the page.")
|
|
return None
|
|
else:
|
|
print(f"[{datetime.now()}] FlareSolverr failed to solve the challenge. Status: {fs_response.get('status')}. Error: {fs_response.get('message')}")
|
|
return None
|
|
except requests.exceptions.ConnectionError:
|
|
print(f"[{datetime.now()}] Error: Could not connect to FlareSolverr at {FLARESOLVERR_URL}. Is the service running and accessible?")
|
|
return None
|
|
except Exception as e:
|
|
print(f"[{datetime.now()}] Error during FlareSolverr request: {e}")
|
|
return None
|
|
|
|
|
|
|
|
def check_for_updates():
|
|
print(f"[{datetime.now()}] Running scheduled check...")
|
|
current_hash = get_page_hash(URL_TO_MONITOR)
|
|
|
|
if current_hash is None:
|
|
return
|
|
|
|
if os.path.exists(HASH_FILE):
|
|
with open(HASH_FILE, 'r') as f:
|
|
previous_hash = f.read().strip()
|
|
|
|
if current_hash != previous_hash:
|
|
print(f"[{datetime.now()}] 🚨 CHANGE DETECTED!")
|
|
send_notification(f"Change detected on {URL_TO_MONITOR}!")
|
|
|
|
with open(HASH_FILE, 'w') as f:
|
|
f.write(current_hash)
|
|
else:
|
|
print(f"[{datetime.now()}] No changes found.")
|
|
else:
|
|
print(f"[{datetime.now()}] First run. Storing initial hash.")
|
|
with open(HASH_FILE, 'w') as f:
|
|
f.write(current_hash)
|
|
|
|
return
|
|
|
|
|
|
|
|
def main():
|
|
check_for_updates()
|
|
|
|
print(f"[{datetime.now()}] Scheduler started. Waiting for 08:00 and 20:00...")
|
|
|
|
schedule.every().day.at("08:00").do(check_for_updates)
|
|
schedule.every().day.at("20:00").do(check_for_updates)
|
|
|
|
while True:
|
|
schedule.run_pending()
|
|
time.sleep(60)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|