Upload files to "/"
This commit is contained in:
40
README.md
40
README.md
@@ -1,38 +1,10 @@
|
||||
# Tesla Inventory Auto-Buyer Bot 🇹🇷
|
||||
# Tesla Inventory Bot (No Docker)
|
||||
|
||||
This is an automated Telegram bot that monitors [Tesla Türkiye's inventory page](https://www.tesla.com/tr_TR/inventory/new/my?arrangeby=plh&zip=&range=0) and sends real-time alerts when new cars appear. It includes price, VIN, color info, and an inline "HEMEN SİPARİŞ VER" button.
|
||||
This Telegram bot monitors Tesla Türkiye inventory and notifies you of new cars.
|
||||
|
||||
## 📦 Features
|
||||
## Setup
|
||||
|
||||
- 🚗 Detects all new inventory vehicles (Model Y)
|
||||
- 💬 Sends Telegram messages (with order button)
|
||||
- 🖼️ Includes exterior/interior color & price
|
||||
- 🧠 Avoids duplicates using VIN tracking
|
||||
- 📅 Cronjob support (run every X minutes)
|
||||
- 🐳 Docker-based installation
|
||||
- 🛠 Menu-based installer script
|
||||
1. Run `install.sh`.
|
||||
2. Follow prompts to install Python, pip, and configure Telegram.
|
||||
3. Use menu options to run manually or set up a cronjob.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Installation (Recommended via `install.sh`)
|
||||
|
||||
> This method clones the repo, builds Docker, prompts for Telegram info, and lets you configure a cronjob.
|
||||
|
||||
### 1. Download and run:
|
||||
|
||||
```bash
|
||||
git clone https://git.bitmaster.cc/BitMaster/tesla-bot.git
|
||||
cd tesla-bot
|
||||
chmod +x install.sh
|
||||
./install.sh
|
||||
```
|
||||
|
||||
✅ curl One-liner
|
||||
```bash
|
||||
bash <(curl -sSL https://git.bitmaster.cc/BitMaster/tesla-bot/raw/branch/main/install.sh)
|
||||
```
|
||||
|
||||
✅ wget One-liner
|
||||
```bash
|
||||
bash <(wget -qO- https://git.bitmaster.cc/BitMaster/tesla-bot/raw/branch/main/install.sh)
|
||||
```
|
||||
117
bot.py
117
bot.py
@@ -7,111 +7,88 @@ 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"
|
||||
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"
|
||||
|
||||
def detect_chat_id(token):
|
||||
try:
|
||||
resp = requests.get(f"https://api.telegram.org/bot{token}/getUpdates")
|
||||
data = resp.json()
|
||||
if not data.get("ok"):
|
||||
return None
|
||||
for update in reversed(data.get("result", [])):
|
||||
chat = update.get("message", {}).get("chat", {})
|
||||
chat_id = chat.get("id")
|
||||
if chat_id:
|
||||
return chat_id
|
||||
except Exception as e:
|
||||
print(f"Chat ID detection failed: {e}")
|
||||
return None
|
||||
|
||||
scraper = cloudscraper.create_scraper(browser={'browser': 'chrome', 'platform': 'windows'}, delay=5)
|
||||
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 Chrome/114.0.0.0 Safari/537.36",
|
||||
"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):
|
||||
def notify_telegram_with_button(msg, btn_text, btn_url):
|
||||
payload = {
|
||||
"chat_id": CHAT_ID,
|
||||
"text": message,
|
||||
"text": msg,
|
||||
"parse_mode": "HTML",
|
||||
"reply_markup": json.dumps({
|
||||
"inline_keyboard": [[{
|
||||
"text": button_text,
|
||||
"url": button_url
|
||||
}]]
|
||||
"inline_keyboard": [[{"text": btn_text, "url": btn_url}]]
|
||||
})
|
||||
}
|
||||
requests.post(f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage", data=payload)
|
||||
requests.post(
|
||||
f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage",
|
||||
data=payload,
|
||||
headers=HEADERS,
|
||||
timeout=30
|
||||
)
|
||||
|
||||
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())
|
||||
return set(open(SEEN_VINS_FILE).read().splitlines())
|
||||
|
||||
def save_seen_vins(vins):
|
||||
with open(SEEN_VINS_FILE, "w") as f:
|
||||
f.writelines(f"{vin}\n" for vin in vins)
|
||||
f.write("\n".join(vins))
|
||||
|
||||
def get_page(url):
|
||||
time.sleep(random.uniform(10, 60))
|
||||
try:
|
||||
return scraper.get(url, headers=HEADERS, timeout=30)
|
||||
return scraper.get(url, headers=HEADERS, timeout=60)
|
||||
except Exception as e:
|
||||
print("Request failed:", e)
|
||||
notify_telegram_with_button(f"⚠️ Failed to fetch Tesla page: {e}", "Retry", TESLA_URL)
|
||||
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)
|
||||
if not resp or resp.status_code in (403,429) or "captcha" in resp.text.lower():
|
||||
notify_telegram_with_button(f"⚠️ Bot likely detected. Status: {getattr(resp,'status_code','N/A')}", "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()
|
||||
|
||||
m = re.search(r'"results"\s*:\s*(\[\{.*?\}\])', resp.text, re.DOTALL)
|
||||
cars = json.loads(m.group(1)) if m else []
|
||||
seen = load_seen_vins()
|
||||
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)
|
||||
|
||||
if not vin or vin in seen: continue
|
||||
price = car.get("price","N/A")
|
||||
ext = car.get("paint",{}).get("value","N/A").upper()
|
||||
inn = car.get("interior",{}).get("value","N/A").upper()
|
||||
link= f"https://www.tesla.com/tr_TR/my/order/{vin}"
|
||||
msg = (f"🚨 <b>NEW CAR!</b>\n"
|
||||
f"💰 Price: {price:,} TL\n"
|
||||
f"🎨 Exterior: {ext}\n"
|
||||
f"🪑 Interior: {inn}\n"
|
||||
f"🔑 VIN: {vin}")
|
||||
notify_telegram_with_button(msg,"🚗 ORDER NOW",link)
|
||||
seen.add(vin)
|
||||
save_seen_vins(seen)
|
||||
except Exception as e:
|
||||
print("Error parsing inventory:", e)
|
||||
notify_telegram_with_button("❌ Bot error during parsing.", "Retry", TESLA_URL)
|
||||
print("Parsing error:",e)
|
||||
notify_telegram_with_button("❌ Parsing error occurred.","Retry",TESLA_URL)
|
||||
|
||||
check_inventory()
|
||||
if __name__=="__main__":
|
||||
check_inventory()
|
||||
|
||||
88
install.sh
88
install.sh
@@ -29,7 +29,6 @@ function check_requirements() {
|
||||
PYTHON_OK=true
|
||||
else
|
||||
echo -e "${RED}Missing${NC}"
|
||||
PYTHON_OK=false
|
||||
fi
|
||||
|
||||
echo -n "📦 pip3: "
|
||||
@@ -38,20 +37,18 @@ function check_requirements() {
|
||||
PIP_OK=true
|
||||
else
|
||||
echo -e "${RED}Missing${NC}"
|
||||
PIP_OK=false
|
||||
fi
|
||||
|
||||
echo -n "📁 Project folder '$CLONE_DIR': "
|
||||
if [ -d "$CLONE_DIR" ]; then
|
||||
echo -e "${YELLOW}Exists${NC}"
|
||||
echo -e "${GREEN}Exists${NC}"
|
||||
else
|
||||
echo -e "${RED}Not present${NC}"
|
||||
fi
|
||||
|
||||
if [ "$PYTHON_OK" = false ]; then
|
||||
echo -e "${YELLOW}❓ Python3 is required. Do you want to install it now? [Y/n]${NC}"
|
||||
read -rp "> " confirm
|
||||
confirm="${confirm,,}"
|
||||
echo -e "${YELLOW}❓ Python3 is required. Install now? [Y/n]${NC}"
|
||||
read -rp "> " confirm; confirm="${confirm,,}"
|
||||
if [[ "$confirm" =~ ^(y|yes| )?$ ]]; then
|
||||
sudo apt update && sudo apt install -y python3
|
||||
else
|
||||
@@ -60,9 +57,8 @@ function check_requirements() {
|
||||
fi
|
||||
|
||||
if [ "$PIP_OK" = false ]; then
|
||||
echo -e "${YELLOW}❓ pip3 is required. Do you want to install it now? [Y/n]${NC}"
|
||||
read -rp "> " confirm
|
||||
confirm="${confirm,,}"
|
||||
echo -e "${YELLOW}❓ pip3 is required. Install now? [Y/n]${NC}"
|
||||
read -rp "> " confirm; confirm="${confirm,,}"
|
||||
if [[ "$confirm" =~ ^(y|yes| )?$ ]]; then
|
||||
sudo apt update && sudo apt install -y python3-pip
|
||||
else
|
||||
@@ -74,8 +70,8 @@ function check_requirements() {
|
||||
function clone_and_setup() {
|
||||
echo -e "${GREEN}📥 Cloning repo...${NC}"
|
||||
rm -rf "$CLONE_DIR"
|
||||
git clone "$REPO_URL" "$CLONE_DIR"
|
||||
cd "$CLONE_DIR" || exit 1
|
||||
git clone "$REPO_URL" "$CLONE_DIR" || { echo -e "${RED}❌ git clone failed${NC}"; return; }
|
||||
cd "$CLONE_DIR"
|
||||
|
||||
echo -e "${GREEN}📦 Installing Python dependencies...${NC}"
|
||||
pip3 install -r requirements.txt
|
||||
@@ -83,33 +79,37 @@ function clone_and_setup() {
|
||||
echo -e "${YELLOW}📨 Enter your Telegram bot token:${NC}"
|
||||
read -rp "🔑 TELEGRAM_TOKEN: " token
|
||||
|
||||
echo -e "${YELLOW}🤖 Auto detecting the Telegram chat-ID...${NC}"
|
||||
auto_chat_id=$(curl -s "https://api.telegram.org/bot$token/getUpdates" | grep -oE '"id":[0-9-]+' | head -n1 | cut -d: -f2)
|
||||
echo -e "${YELLOW}🤖 Auto-detecting your Telegram chat ID...${NC}"
|
||||
auto_chat_id=$(python3 - <<PYCODE
|
||||
import requests, json
|
||||
try:
|
||||
h = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/114.0.0.0 Safari/537.36"}
|
||||
r = requests.get(f"https://api.telegram.org/bot{token}/getUpdates", headers=h, timeout=30)
|
||||
data = r.json().get("result",[])
|
||||
if data:
|
||||
print(data[-1]["message"]["chat"]["id"])
|
||||
except:
|
||||
pass
|
||||
PYCODE
|
||||
)
|
||||
|
||||
if [ -n "$auto_chat_id" ]; then
|
||||
echo -e "${GREEN}✅ Auto-detected chat ID: $auto_chat_id${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ Could not auto-detect chat ID. You may enter it manually.${NC}"
|
||||
echo -e "${RED}❌ Could not auto-detect chat ID. You will need to enter it manually.${NC}"
|
||||
fi
|
||||
|
||||
read -rp "🆔 TELEGRAM_CHAT_ID [default: $auto_chat_id]: " chat_id
|
||||
chat_id="${chat_id:-$auto_chat_id}"
|
||||
[ -z "$chat_id" ] && { echo -e "${RED}❌ No chat ID provided. Aborting.${NC}"; exit 1; }
|
||||
|
||||
if [ -z "$chat_id" ]; then
|
||||
echo -e "${RED}❌ No chat ID provided or detected. Aborting.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sed -i "s|^TELEGRAM_TOKEN = .*|TELEGRAM_TOKEN = \"$token\"|" bot.py
|
||||
sed -i "s|^CHAT_ID = .*|CHAT_ID = \"$chat_id\"|" bot.py
|
||||
sed -i "s|^TELEGRAM_TOKEN = .*|TELEGRAM_TOKEN = "$token"|" bot.py
|
||||
sed -i "s|^CHAT_ID = .*|CHAT_ID = "$chat_id"|" bot.py
|
||||
echo -e "${GREEN}✅ Credentials updated in bot.py${NC}"
|
||||
|
||||
echo -e "${YELLOW}📤 Sending test Telegram message...${NC}"
|
||||
curl -s -X POST "https://api.telegram.org/bot$token/sendMessage" \
|
||||
-d chat_id="$chat_id" \
|
||||
-d text="✅ Tesla bot kuruldu ve Telegram bağlantısı başarılı!" \
|
||||
-d parse_mode="HTML" > /dev/null
|
||||
echo -e "${GREEN}✅ Test message sent. Check your Telegram!${NC}"
|
||||
curl -s -X POST "https://api.telegram.org/bot$token/sendMessage" -d chat_id="$chat_id" -d text="✅ Tesla bot installed and ready!" -d parse_mode="HTML"
|
||||
echo -e "${GREEN}✅ Test message sent!${NC}"
|
||||
|
||||
cd ..
|
||||
read -rp "$(echo -e "${GREEN}🔁 Press Enter to return to the main menu...${NC}")"
|
||||
@@ -117,12 +117,12 @@ function clone_and_setup() {
|
||||
|
||||
function run_bot_now() {
|
||||
if [ ! -f "$CLONE_DIR/bot.py" ]; then
|
||||
echo -e "${RED}❌ Bot not installed. Please run option 1 first.${NC}"
|
||||
echo -e "${RED}❌ Bot not installed. Run option 1 first.${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚙️ Running bot.py...${NC}"
|
||||
python3 "$CLONE_DIR/bot.py"
|
||||
fi
|
||||
read -rp "$(echo -e "${GREEN}🔁 Press Enter to return to the main menu...${NC}")"
|
||||
read -rp "$(echo -e "${GREEN}🔁 Press Enter to return...${NC}")"
|
||||
}
|
||||
|
||||
function setup_cronjob() {
|
||||
@@ -130,43 +130,37 @@ function setup_cronjob() {
|
||||
if [ ! -d "$CLONE_DIR" ]; then
|
||||
echo -e "${RED}❌ Bot not installed. Run option 1 first.${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⏱ How often should the bot run? (in minutes, 1-60)${NC}"
|
||||
read -rp "Interval: " interval
|
||||
read -rp "⏱ Run interval in minutes (1–60): " interval
|
||||
if ! [[ "$interval" =~ ^[0-9]+$ ]] || [ "$interval" -lt 1 ] || [ "$interval" -gt 60 ]; then
|
||||
echo -e "${RED}❌ Invalid input. Must be between 1 and 60.${NC}"
|
||||
echo -e "${RED}❌ Invalid interval.${NC}"
|
||||
else
|
||||
(crontab -l 2>/dev/null | grep -v "$CRON_NAME"; echo "*/$interval * * * * cd $(pwd)/$CLONE_DIR && python3 bot.py >> cron.log 2>&1") | crontab -
|
||||
echo -e "${GREEN}✅ Cronjob installed to run every $interval minute(s).${NC}"
|
||||
(crontab -l 2>/dev/null | grep -v "$CRON_NAME"; echo "*/$interval * * * * cd $(pwd)/$CLONE_DIR && python3 bot.py >> cron.log 2>&1") | crontab -
|
||||
echo -e "${GREEN}✅ Cronjob set for every $interval min.${NC}"
|
||||
fi
|
||||
fi
|
||||
read -rp "$(echo -e "${GREEN}🔁 Press Enter to return to the main menu...${NC}")"
|
||||
read -rp "$(echo -e "${GREEN}🔁 Press Enter to return...${NC}")"
|
||||
}
|
||||
|
||||
function remove_cronjob() {
|
||||
echo -e "${YELLOW}Removing bot cronjob...${NC}"
|
||||
crontab -l 2>/dev/null | grep -v "$CRON_NAME" | crontab -
|
||||
crontab -l | grep -v "$CRON_NAME" | crontab -
|
||||
echo -e "${GREEN}✅ Cronjob removed.${NC}"
|
||||
read -rp "$(echo -e "${GREEN}🔁 Press Enter to return to the main menu...${NC}")"
|
||||
read -rp "$(echo -e "${GREEN}🔁 Press Enter to return...${NC}")"
|
||||
}
|
||||
|
||||
while true; do
|
||||
clear
|
||||
banner
|
||||
check_requirements
|
||||
clear; banner; check_requirements
|
||||
echo -e "${YELLOW}1. Install bot and configure"
|
||||
echo -e "2. Run bot manually now"
|
||||
echo -e "3. Setup new cronjob (every X min)"
|
||||
echo -e "3. Setup new cronjob"
|
||||
echo -e "4. Remove existing cronjob"
|
||||
echo -e "5. Exit${NC}"
|
||||
echo ""
|
||||
read -rp "$(echo -e "${YELLOW}🔗 Choose [1-5]: ${NC}")" choice
|
||||
|
||||
case $choice in
|
||||
1) clone_and_setup ;;
|
||||
2) run_bot_now ;;
|
||||
3) setup_cronjob ;;
|
||||
4) remove_cronjob ;;
|
||||
2) run_bot_now ;;
|
||||
3) setup_cronjob ;;
|
||||
4) remove_cronjob ;;
|
||||
5) echo -e "${RED}❌ Exiting...${NC}"; exit 0 ;;
|
||||
*) echo -e "${RED}❌ Invalid option.${NC}"; sleep 1 ;;
|
||||
esac
|
||||
done
|
||||
done
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
requests
|
||||
|
||||
cloudscraper
|
||||
|
||||
Reference in New Issue
Block a user