Merhabalar,
Şirket hattına ait whatsapp numarasından müşterilere mesaj atıyoruz manuel şekilde buna rağmen kısıtlama yiyoruz, bunun önüne geçen bir yazılım vs. var mıdır?
WhatsApp toplu mesaj?
12
●218
- 07-06-2026, 19:46:54bende vardı kodunu bulabilirsem buradan atayım basit bişeydi. mesajım dursun gece falan görürsem tekrar konuyu buradan atarım. dediğim gibi basit bi python koduydu.
- 07-06-2026, 19:53:06
import csv import time import random from datetime import datetime DAILY_LIMIT = 40 # yeni/riski yüksek hat için düşük tut MIN_DELAY = 90 # saniye MAX_DELAY = 240 # saniye SENT_LOG = "sent_log.txt" def already_sent(phone): try: with open(SENT_LOG, "r", encoding="utf-8") as f: return phone in f.read() except FileNotFoundError: return False def log_sent(phone): with open(SENT_LOG, "a", encoding="utf-8") as f: f.write(f"{phone},{datetime.now().isoformat()}\n") def send_whatsapp_message(phone, message): """ Buraya resmi WhatsApp Cloud API isteği bağlanmalı. Selenium/WhatsApp Web otomasyonu önermem; ban riskini artırır. """ print(f"[GÖNDERİLECEK] {phone}: {message}") return True with open("customers.csv", newline="", encoding="utf-8") as file: reader = csv.DictReader(file) sent_today = 0 for row in reader: phone = row["phone"].strip() name = row.get("name", "").strip() opted_in = row.get("opt_in", "").lower() == "yes" if not opted_in: print(f"Atlandı, izin yok: {phone}") continue if already_sent(phone): print(f"Atlandı, daha önce gönderilmiş: {phone}") continue if sent_today >= DAILY_LIMIT: print("Günlük limit doldu.") break message = ( f"Merhaba {name}, size bu hattan bilgilendirme göndermemize izin verdiğiniz için yazıyoruz. " f"Mesaj almak istemiyorsanız DUR yazmanız yeterlidir." ) ok = send_whatsapp_message(phone, message) if ok: log_sent(phone) sent_today += 1 delay = random.randint(MIN_DELAY, MAX_DELAY) print(f"{delay} saniye bekleniyor...") time.sleep(delay)python ile yazmıştım bunu, müşteri listelerini de csv dosyasında tutuyordum csv formatı da şöyleydi :
phone,name,opt_in
905551112233,Ahmet,yes
905559998877,Mehmet,no
umarım işinize yarar, AI ile falan üstünde de oynama yapabilirsiniz. - 07-06-2026, 19:54:13gwynbleidd_31 adlı üyeden alıntı: mesajı görüntüle
Teşekkürler hocam deneyeyim, bunda hiç ban yediniz mi veya kısıtlama aldınız mı hocam? - 07-06-2026, 19:54:56Merhaba,
Destek talebiniz hala devam ediyorsa, projeniz üzerinde profesyonel şekilde destek sağlayabiliriz. XipSoft olarak web, mobil ve özel yazılım süreçlerinizde temiz, sürdürülebilir ve performans odaklı çözümler üretiyoruz.
İşçiliğimiz hakkında fikir edinmeniz ve referans olması adına sitemizi inceleyebilirsiniz.
İyi çalışmalar dileriz. - 07-06-2026, 19:55:16Hala 0850'li numaramız whatsapp'da aktif, bunu sadece kendi otomasyonumuza biraz daha geliştirerek bağladık. Herhangi bir sorun yaratacağını sanmıyorum.KET WEB adlı üyeden alıntı: mesajı görüntüle
- 07-06-2026, 19:58:48Hatta biraz daha gelişmişi şöyle :
Python kodu (app.py) :
import os, csv, time, random, sqlite3, threading from datetime import datetime, date from flask import Flask, request, redirect, Response import requests from dotenv import load_dotenv load_dotenv() app = Flask(__name__) TOKEN = os.getenv("WHATSAPP_TOKEN") PHONE_NUMBER_ID = os.getenv("PHONE_NUMBER_ID") DAILY_LIMIT = int(os.getenv("DAILY_LIMIT", 40)) MIN_DELAY = int(os.getenv("MIN_DELAY", 90)) MAX_DELAY = int(os.getenv("MAX_DELAY", 240)) DB = "whatsapp_crm.db" def db(): conn = sqlite3.connect(DB) conn.row_factory = sqlite3.Row return conn def init_db(): conn = db() conn.executescript(""" CREATE TABLE IF NOT EXISTS customers ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, phone TEXT UNIQUE, opt_in INTEGER DEFAULT 1, blocked INTEGER DEFAULT 0, created_at TEXT ); CREATE TABLE IF NOT EXISTS messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, phone TEXT, message TEXT, status TEXT, response TEXT, created_at TEXT ); """) conn.commit() conn.close() def today_sent_count(): conn = db() today = date.today().isoformat() count = conn.execute( "SELECT COUNT(*) FROM messages WHERE status='sent' AND DATE(created_at)=?", (today,) ).fetchone()[0] conn.close() return count def already_sent_recent(phone): conn = db() row = conn.execute( """ SELECT id FROM messages WHERE phone=? AND status='sent' AND datetime(created_at) >= datetime('now', '-7 days') LIMIT 1 """, (phone,) ).fetchone() conn.close() return row is not None def send_whatsapp(phone, message): url = f"https://graph.facebook.com/v20.0/{PHONE_NUMBER_ID}/messages" payload = { "messaging_product": "whatsapp", "to": phone, "type": "text", "text": { "preview_url": False, "body": message } } headers = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json" } r = requests.post(url, json=payload, headers=headers, timeout=30) return r.status_code, r.text def log_message(phone, message, status, response): conn = db() conn.execute( """ INSERT INTO messages(phone, message, status, response, created_at) VALUES (?, ?, ?, ?, ?) """, (phone, message, status, response, datetime.now().isoformat()) ) conn.commit() conn.close() def campaign_worker(message_template): conn = db() customers = conn.execute( """ SELECT * FROM customers WHERE opt_in=1 AND blocked=0 ORDER BY id ASC """ ).fetchall() conn.close() for c in customers: if today_sent_count() >= DAILY_LIMIT: break phone = c["phone"] name = c["name"] or "" if already_sent_recent(phone): continue message = message_template.replace("{name}", name).strip() message += "\n\nMesaj almak istemiyorsanız DUR yazabilirsiniz." code, resp = send_whatsapp(phone, message) if 200 <= code < 300: log_message(phone, message, "sent", resp) else: log_message(phone, message, "failed", resp) time.sleep(random.randint(MIN_DELAY, MAX_DELAY)) @app.route("/") def index(): conn = db() customers = conn.execute("SELECT * FROM customers ORDER BY id DESC LIMIT 100").fetchall() sent = today_sent_count() conn.close() rows = "".join( f"<tr><td>{c['id']}</td><td>{c['name']}</td><td>{c['phone']}</td><td>{c['opt_in']}</td><td>{c['blocked']}</td></tr>" for c in customers ) return f""" <h2>WhatsApp CRM Panel</h2> <p>Bugün gönderilen: <b>{sent}/{DAILY_LIMIT}</b></p> <h3>Tek müşteri ekle</h3> <form method="post" action="/add"> <input name="name" placeholder="İsim"> <input name="phone" placeholder="905xxxxxxxxx" required> <button>Ekle</button> </form> <h3>CSV Import</h3> <p>CSV kolonları: name, phone, opt_in</p> <form method="post" action="/import" enctype="multipart/form-data"> <input type="file" name="file" required> <button>İçe Aktar</button> </form> <h3>Kampanya gönder</h3> <form method="post" action="/campaign"> <textarea name="message" rows="6" cols="70" placeholder="Merhaba {{name}}, kampanya mesajınız..." required></textarea><br> <button>Yavaş Gönderimi Başlat</button> </form> <p> <a href="/export/customers">Müşterileri CSV indir</a> | <a href="/export/messages">Mesaj loglarını CSV indir</a> </p> <h3>Son müşteriler</h3> <table border="1" cellpadding="6"> <tr><th>ID</th><th>İsim</th><th>Telefon</th><th>Opt-in</th><th>Blocked</th></tr> {rows} </table> """ @app.route("/add", methods=["POST"]) def add(): name = request.form.get("name", "").strip() phone = request.form.get("phone", "").strip() conn = db() conn.execute( """ INSERT OR IGNORE INTO customers(name, phone, opt_in, blocked, created_at) VALUES (?, ?, 1, 0, ?) """, (name, phone, datetime.now().isoformat()) ) conn.commit() conn.close() return redirect("/") @app.route("/import", methods=["POST"]) def import_csv(): file = request.files["file"] content = file.stream.read().decode("utf-8-sig").splitlines() reader = csv.DictReader(content) conn = db() for row in reader: name = row.get("name", "").strip() phone = row.get("phone", "").strip() opt_in = 1 if row.get("opt_in", "yes").lower() in ["yes", "1", "true", "evet"] else 0 if phone: conn.execute( """ INSERT OR IGNORE INTO customers(name, phone, opt_in, blocked, created_at) VALUES (?, ?, ?, 0, ?) """, (name, phone, opt_in, datetime.now().isoformat()) ) conn.commit() conn.close() return redirect("/") @app.route("/campaign", methods=["POST"]) def campaign(): message = request.form["message"] t = threading.Thread(target=campaign_worker, args=(message,)) t.daemon = True t.start() return "Kampanya arka planda başladı. Panelden logları export edebilirsin. <a href='/'>Geri dön</a>" @app.route("/export/customers") def export_customers(): conn = db() rows = conn.execute("SELECT name, phone, opt_in, blocked, created_at FROM customers").fetchall() conn.close() def generate(): yield "name,phone,opt_in,blocked,created_at\n" for r in rows: yield f"{r['name']},{r['phone']},{r['opt_in']},{r['blocked']},{r['created_at']}\n" return Response(generate(), mimetype="text/csv", headers={"Content-Disposition": "attachment; filename=customers.csv"}) @app.route("/export/messages") def export_messages(): conn = db() rows = conn.execute("SELECT phone, message, status, response, created_at FROM messages").fetchall() conn.close() def generate(): yield "phone,message,status,response,created_at\n" for r in rows: msg = str(r["message"]).replace('"', '""') resp = str(r["response"]).replace('"', '""') yield f'{r["phone"]},"{msg}",{r["status"]},"{resp}",{r["created_at"]}\n' return Response(generate(), mimetype="text/csv", headers={"Content-Disposition": "attachment; filename=messages.csv"}) @app.route("/webhook", methods=["GET", "POST"]) def webhook(): if request.method == "GET": verify_token = os.getenv("VERIFY_TOKEN") if request.args.get("hub.verify_token") == verify_token: return request.args.get("hub.challenge") return "Invalid verify token", 403 data = request.json or {} try: message = data["entry"][0]["changes"][0]["value"]["messages"][0] phone = message["from"] text = message.get("text", {}).get("body", "").strip().lower() if text in ["dur", "stop", "iptal", "çık", "cik"]: conn = db() conn.execute("UPDATE customers SET blocked=1, opt_in=0 WHERE phone=?", (phone,)) conn.commit() conn.close() send_whatsapp(phone, "Talebiniz alınmıştır. Bu numaradan artık bilgilendirme mesajı almayacaksınız.") except Exception: pass return "ok" if __name__ == "__main__": init_db() app.run(host="0.0.0.0", port=5000, debug=True)
pip:
pip install flask requests python-dotenv
.env:
WHATSAPP_TOKEN=EAAG...
PHONE_NUMBER_ID=123456789
VERIFY_TOKEN=benim_verify_tokenim
DAILY_LIMIT=40
MIN_DELAY=90
MAX_DELAY=240
Çalıştır:
python app.py
Panel:
http://localhost:5000
bu bizim aktif kullandığımız.
