Black Mesa, 19 Mayıs tarihine kadar %90 indirime girmiş ve böyle bir eseri daha çok kişi oynasın görsün diye bir çekiliş düzenlemeye karar verdim.

Katılım şartları:
  • Techolay Sosyal'e üye olmak.
  • Herhangi bir mesaj ya da üyelik süresi kısıtı yoktur.
  • Katılmak için "katılıyorum." yazmanız gerekli. Düzgün yazmanız çekilişi yapacak olan kod açısından daha yararlı olacaktır.

Çekilişi 17 Mayıs cumartesi günü saat 20:00'da bitirip sonucu açıklamayı düşünüyorum.

Çekilişte çıkan kişilere oyunu Steam üzerinden hediye edeceğim.
Çekilişi aşağıdaki sürprizbozan içinde paylaşacağım kod yapacak, kdou @2426'in konusundan alıp ChatGPT ve claude 3.7 ile bir şekilde düzenleyip mevcut formuna getirdim. Kendilerine teşekkür ederim. Kodda bir sorun ya da fazlalık varsa da artık görmezden gelin ne olacak 😝

Python:
import random.
import re.
import requests.
from bs4 import BeautifulSoup.
import time.
from datetime import datetime.

# 1) Tarayıcı gibi görünmek için header.
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"
 )
}

# 2) Kontrol edilecek kelimeler (küçük harf, noktalama olmadan)
KEYWORDS = [
 "katılıyorum", "katiliyorum", "katıldım", "katildim",
 "katılyorum", "katildin", "katiliyrum", "katıliyrum",
 "katiliyom", "katılıyom", "katlıyorum"
]

def fuzzy_match(text, keywords, tolerance=2):
 text_lower = text.lower()
 # Önce tam eşleşme.
 for kw in keywords:
 if kw in text_lower:
 return True.
 # Yaklaşık eşleşme.
 words = re.findall(r'\b\w+\b', text_lower)
 for word in words:
 if len(word) < 5:
 continue.
 for kw in keywords:
 if abs(len(word) - len(kw)) > tolerance:
 continue.
 # Basitleştirilmiş Levenshtein-benzeri kontrol.
 diff = sum(1 for i in range(min(len(word), len(kw))) if word[i] != kw[i])
 diff += abs(len(word) - len(kw))
 if diff <= tolerance:
 return True.
 return False.

def get_usernames(url, page_count=1, delay=1, fuzzy=True, exclude_op=True):
 usernames = []
 seen = set()
 ignored = [] # Neden atlandılar loglamak için.
 op_user = None.

 print(f"\n📊 Toplam {page_count} sayfa taranıyor…")

 # OP'yi bul.
 try:
 res = requests.get(url, headers=HEADERS, timeout=10)
 res.raise_for_status()
 soup = BeautifulSoup(res.text, "html.parser")
 first = soup.find("article", class_="message--post")
 if first and exclude_op:
 tag = first.find("a", class_="username")
 op_user = tag.get_text(strip=True) if tag else None.
 print(f"👤 OP tespit edildi: {op_user}")
 except Exception as e:
 print("⚠️ OP belirlenirken hata:", e)

 # Sayfaları dolaş.
 for p in range(1, page_count+1):
 full_url = url if p==1 else f"{url}page-{p}/"
 print(f"\n📄 Sayfa {p}: {full_url}")
 try:
 res = requests.get(full_url, headers=HEADERS, timeout=10)
 res.raise_for_status()
 except Exception as e:
 print(f"⚠️ Sayfa {p} alınamadı:", e)
 continue.

 soup = BeautifulSoup(res.text, "html.parser")
 posts = soup.find_all("article", class_="message--post")
 if not posts:
 print("⚠️ Hiç post bulunamadı!")
 continue.

 start = 1 if (p==1 and exclude_op) else 0
 print(f" {len(posts)-start} post işleniyor…")

 for post in posts[start:]:
 # 1) Yazar.
 a = post.find("a", class_="username")
 if not a:
 continue.
 author = a.get_text(strip=True)
 if exclude_op and author == op_user:
 continue.

 voted = False.
 content_snippet = ""

 # 2) bbWrapper içi gerçek mesajları tara.
 for body in post.find_all("div", class_="bbWrapper"):
 if body.find_parent("blockquote"):
 continue.
 txt = body.get_text(strip=True)
 content_snippet += txt + " "
 lw = txt.lower()

 # tam keyword kontrolü.
 if any(re.search(rf"\b{kw}\b", lw) for kw in KEYWORDS):
 voted = True.
 # fuzzy kontrolü.
 elif fuzzy and fuzzy_match(lw, KEYWORDS):
 voted = True.

 if voted:
 break.

 # 3) embed tespiti (js-xf-embed sınıfı)
 if not voted and post.find("div", class_=re.compile(r"\bjs-xf-embed\b")):
 voted = True.

 # 4) Listeye ekle veya atlanma sebebini kaydet.
 if voted:
 key = author.lower()
 if key not in seen:
 seen.add(key)
 usernames.append(author)
 print(f" ✅ Katılımcı: {author}")
 else:
 print(f" ℹ️ Önceden kaydedilmiş: {author}")
 else:
 if content_snippet.strip():
 ignored.append((author, content_snippet[:80]))

 if p < page_count:
 time.sleep(delay)

 # Atlanılan örnekleri göster (ilk 10)
 if ignored:
 print("\n⚠️ Atlanan kullanıcılar ve içerik snippet'leri:")
 for usr, snippet in ignored[:10]:
 print(f" - {usr}: \"{snippet}...\"")
 if len(ignored) > 10:
 print(f" ... ve {len(ignored)-10} kişi daha")

 return usernames.

def main():
 print("=== Xenforo Çekiliş Aracı ===")
 link = input("Link (sonunda / olacak): ").strip()
 if not link.endswith("/"):
 link += "/"
 try:
 pages = int(input("Kaç sayfa?: ") or "1")
 except:
 pages = 1
 users = get_usernames(link, pages)

 print(f"\n📋 Toplam katılımcı: {len(users)}")
 if users:
 for u in users:
 print("•", u)

 # 5 kazanan ve 5 yedek seçimi.
 kazanan_sayisi = min(5, len(users))
 if kazanan_sayisi > 0:
 # Asıl kazananları seç.
 asil_kazananlar = []
 temp_users = users.copy()
 for i in range(kazanan_sayisi):
 if not temp_users:
 break.
 winner = random.choice(temp_users)
 asil_kazananlar.append(winner)
 temp_users.remove(winner)

 print("\n🎉 Kazananlar:")
 for i, winner in enumerate(asil_kazananlar, 1):
 print(f"{i}. Kazanan: {winner}")

 # Her kazanan için kendi yedeğini seç.
 if temp_users: # Eğer hala seçilebilecek kullanıcı kaldıysa.
 backup = random.choice(temp_users)
 print(f" 🔄 {i}. Kazananın Yedeği: {backup}")
 temp_users.remove(backup)
 else:
 print(f" ⚠️ {i}. Kazanan için yedek seçilemedi (yeterli katılımcı yok)")
 else:
 print("❌ Seçilecek kazanan kalmadı.")
 else:
 print("❌ Kimse listelenmedi.")

if __name__ == "__main__":
 main()


Katılıyorum.