111 lines
3.5 KiB
Python
111 lines
3.5 KiB
Python
import time
|
||
import random
|
||
import cloudscraper
|
||
import re
|
||
import json
|
||
import os
|
||
import requests
|
||
|
||
TELEGRAM_TOKEN = "your_token_here"
|
||
CHAT_ID = "your_chat_id_here"
|
||
TESLA_URL = "https://www.tesla.com/tr_TR/inventory/new/my?arrangeby=plh&zip=&range=0"
|
||
SEEN_VINS_FILE = "seen_vins.txt"
|
||
|
||
# Create a Cloudflare-aware scraper
|
||
scraper = cloudscraper.create_scraper(
|
||
browser={'browser': 'chrome', 'platform': 'windows'},
|
||
delay=5
|
||
)
|
||
|
||
HEADERS = {
|
||
"User-Agent": (
|
||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||
"Chrome/114.0.0.0 Safari/537.36"
|
||
),
|
||
"Accept-Language": "tr-TR,tr;q=0.9",
|
||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9",
|
||
"Referer": "https://www.tesla.com/"
|
||
}
|
||
|
||
def notify_telegram_with_button(message, button_text, button_url):
|
||
payload = {
|
||
"chat_id": CHAT_ID,
|
||
"text": message,
|
||
"parse_mode": "HTML",
|
||
"reply_markup": json.dumps({
|
||
"inline_keyboard": [[{
|
||
"text": button_text,
|
||
"url": button_url
|
||
}]]
|
||
})
|
||
}
|
||
requests.post(f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage", data=payload)
|
||
|
||
def load_seen_vins():
|
||
if not os.path.exists(SEEN_VINS_FILE):
|
||
return set()
|
||
with open(SEEN_VINS_FILE, "r") as f:
|
||
return set(line.strip() for line in f.readlines())
|
||
|
||
def save_seen_vins(vins):
|
||
with open(SEEN_VINS_FILE, "w") as f:
|
||
f.writelines(f"{vin}\n" for vin in vins)
|
||
|
||
def get_page(url):
|
||
time.sleep(random.uniform(10, 60)) # Random delay to avoid detection
|
||
try:
|
||
return scraper.get(url, headers=HEADERS, timeout=30)
|
||
except Exception as e:
|
||
print("Request failed:", e)
|
||
return None
|
||
|
||
def check_inventory():
|
||
resp = get_page(TESLA_URL)
|
||
if resp is None:
|
||
notify_telegram_with_button("⚠️ Bot failed to get Tesla page (no response).", "Retry", TESLA_URL)
|
||
return
|
||
|
||
if resp.status_code in (403, 429) or "captcha" in resp.text.lower():
|
||
notify_telegram_with_button(f"⚠️ Tesla bot likely detected. Status: {resp.status_code}", "Open Tesla", TESLA_URL)
|
||
return
|
||
|
||
try:
|
||
page_text = resp.text
|
||
json_data_match = re.search(r'\"results\"\s*:\s*(\[\{.*?\}\])', page_text, re.DOTALL)
|
||
if not json_data_match:
|
||
raise Exception("Could not find inventory JSON")
|
||
|
||
cars = json.loads(json_data_match.group(1))
|
||
seen_vins = load_seen_vins()
|
||
new_seen = seen_vins.copy()
|
||
|
||
for car in cars:
|
||
vin = car.get("vin")
|
||
if not vin or vin in seen_vins:
|
||
continue
|
||
|
||
price = car.get("price", "N/A")
|
||
ext_color = car.get("paint", {}).get("value", "N/A")
|
||
int_color = car.get("interior", {}).get("value", "N/A")
|
||
order_link = f"https://www.tesla.com/tr_TR/my/order/{vin}"
|
||
|
||
message = (
|
||
f"🚨 <b>YENİ ARAÇ GELDİ!</b>\n"
|
||
f"<b>💰 Fiyat:</b> {price:,} TL\n"
|
||
f"<b>🎨 Dış Renk:</b> {ext_color.upper()}\n"
|
||
f"<b>🪑 İç Renk:</b> {int_color.upper()}\n"
|
||
f"<b>🔑 VIN:</b> {vin}"
|
||
)
|
||
|
||
notify_telegram_with_button(message, "🚗 HEMEN SİPARİŞ VER", order_link)
|
||
new_seen.add(vin)
|
||
|
||
save_seen_vins(new_seen)
|
||
|
||
except Exception as e:
|
||
print("Error parsing inventory:", e)
|
||
notify_telegram_with_button("❌ Bot error during parsing.", "Retry", TESLA_URL)
|
||
|
||
check_inventory()
|