Initial commit
This commit is contained in:
115
main.py
Normal file
115
main.py
Normal file
@@ -0,0 +1,115 @@
|
||||
import time
|
||||
import random
|
||||
import requests
|
||||
from datetime import datetime
|
||||
|
||||
# ===== SMS GATEWAY =====
|
||||
SMS_USER = "weatherbot"
|
||||
SMS_PASS = "Cupakabra17"
|
||||
|
||||
RECEIVE_URL = "https://sms.internet-master.cz/receive/"
|
||||
SEND_URL = "https://sms.internet-master.cz/send/"
|
||||
|
||||
BASE_POLL_INTERVAL = 15 # seconds (was 3)
|
||||
MAX_BACKOFF = 300 # 5 minutes
|
||||
|
||||
seen_offsets = set()
|
||||
|
||||
HEADERS = {
|
||||
"User-Agent": "weatherbot/1.0 (jakub@jimbuntu)"
|
||||
}
|
||||
|
||||
# =======================
|
||||
|
||||
# Reuse TCP connections (important)
|
||||
session = requests.Session()
|
||||
session.headers.update(HEADERS)
|
||||
|
||||
def fetch_inbox():
|
||||
params = {
|
||||
"username": SMS_USER,
|
||||
"password": SMS_PASS,
|
||||
"limit": 5
|
||||
}
|
||||
r = session.get(RECEIVE_URL, params=params, timeout=10)
|
||||
r.raise_for_status()
|
||||
return r.json()
|
||||
|
||||
def send_sms(number, message):
|
||||
params = {
|
||||
"number": number,
|
||||
"message": message,
|
||||
"username": SMS_USER,
|
||||
"password": SMS_PASS
|
||||
}
|
||||
r = session.get(SEND_URL, params=params, timeout=10)
|
||||
r.raise_for_status()
|
||||
print("SEND RESPONSE:", r.text)
|
||||
|
||||
def get_weather(city):
|
||||
url = f"https://wttr.in/{city}?format=j1"
|
||||
r = session.get(url, timeout=10)
|
||||
|
||||
if r.status_code != 200:
|
||||
return f"❌ Weather unavailable for {city}"
|
||||
|
||||
data = r.json()
|
||||
weather = data.get("weather", [])
|
||||
|
||||
if len(weather) < 3:
|
||||
return f"❌ Weather unavailable for {city}"
|
||||
|
||||
msg = f"🌦 Weather for {city}:\n"
|
||||
|
||||
for day in weather[:3]:
|
||||
date = day["date"]
|
||||
avgtemp = day["avgtempC"]
|
||||
desc = day["hourly"][0]["weatherDesc"][0]["value"]
|
||||
|
||||
weekday = datetime.strptime(date, "%Y-%m-%d").strftime("%a")
|
||||
msg += f"{weekday}: {avgtemp}°C, {desc}\n"
|
||||
|
||||
return msg.strip()
|
||||
|
||||
# ===== MAIN LOOP =====
|
||||
print("📡 SMS Weather Bot started (no API key)")
|
||||
|
||||
poll_interval = BASE_POLL_INTERVAL
|
||||
|
||||
while True:
|
||||
try:
|
||||
data = fetch_inbox()
|
||||
inbox = data.get("inbox", [])
|
||||
|
||||
# reset backoff on success
|
||||
poll_interval = BASE_POLL_INTERVAL
|
||||
|
||||
if not inbox:
|
||||
time.sleep(poll_interval)
|
||||
continue
|
||||
|
||||
for sms in inbox:
|
||||
offset = sms["offset"]
|
||||
if offset in seen_offsets:
|
||||
continue
|
||||
|
||||
phone = sms["phone"]
|
||||
text = sms["message"].strip()
|
||||
|
||||
print(f"📨 {phone}: {text}")
|
||||
|
||||
reply = get_weather(text)
|
||||
send_sms(phone, reply)
|
||||
|
||||
print(f"📤 Sent reply to {phone}")
|
||||
seen_offsets.add(offset)
|
||||
|
||||
except Exception as e:
|
||||
print("⚠ Error:", e)
|
||||
|
||||
# exponential backoff + jitter
|
||||
poll_interval = min(poll_interval * 2, MAX_BACKOFF)
|
||||
|
||||
# jitter prevents perfectly periodic polling
|
||||
time.sleep(poll_interval + random.randint(0, 5))
|
||||
|
||||
Reference in New Issue
Block a user