first (part 3: src directory)
Deploy Iddaai Backend / build-and-deploy (push) Successful in 33s

This commit is contained in:
2026-04-16 15:12:27 +03:00
parent 2f0b85a0c7
commit 182f4aae16
125 changed files with 22552 additions and 0 deletions
+276
View File
@@ -0,0 +1,276 @@
const axios = require('axios');
const he = require('he'); // HTML entity decode etmek için (npm install he)
const cheerio = require('cheerio'); // HTML içinden data-settings almak için
const MATCH_ID = '18rkqb1lhon6ne1hdb6d15as'; // Barcelona - Real Madrid
// 1. ADIM: TANIMLARI (METADATA) ÇEK VE HARİTALAMA YAP
async function createMarketMap() {
// Bu URL bize HTML döndürür, ama içinde data-settings JSON'u vardır.
const url = `https://www.mackolik.com/ajax/iddaa/markets/soccer/all/${MATCH_ID}?template=all`;
const response = await axios.get(url, {
headers: { 'X-Requested-With': 'XMLHttpRequest', 'User-Agent': 'Mozilla/5.0' }
});
// Cheerio ile HTML'i yükle
const $ = cheerio.load(response.data.data.html);
// data-settings özniteliğini bul (Genelde "all" marketlerinde bulunur)
// Not: Bazen widget-iddaa-markets--all bazen başka class olabilir, genel arıyoruz:
const settingsRaw = $('.widget-iddaa-markets').first().attr('data-settings');
if (!settingsRaw) {
console.error("Data settings bulunamadı!");
return null;
}
// HTML Entity'lerini temizle (" -> ")
const settingsJson = JSON.parse(he.decode(settingsRaw));
// Şimdi elimizde ALTIN DEĞERİNDE bir sözlük var: marketCollection
const definitions = settingsJson.iddaaEventId.marketCollection;
// Bizim kullanacağımız Harita (Dictionary)
let marketMap = {};
// Sözlüğü oluşturuyoruz: ID -> İSİM
for (const key in definitions) {
const market = definitions[key];
const marketId = market.iddaaId || market.id; // Bazen iddaaId, bazen id kullanılır
marketMap[marketId] = {
name: market.name, // "Maç Sonucu"
outcomes: {}
};
// Seçenekleri de haritalayalım (1, X, 2, Alt, Üst)
// selectionCollectionAll varsa onu, yoksa selectionCollection kullan
const selections = market.selectionCollectionAll || market.selectionCollection;
for (const selKey in selections) {
const selection = selections[selKey];
// Outcome shortcode (Örn: 1.1) veya iddaaMarketId ile eşleşme yapabiliriz
// Live JSON'da outcome ID'leri "1.1", "1.2" gibi shortcode olarak geliyor.
marketMap[marketId].outcomes[selection.shortcode] = selection.name;
}
}
console.log("✅ Market Haritası Başarıyla Oluşturuldu (HTML'den).");
return marketMap;
}
// 2. ADIM: CANLI VERİYİ ÇEK VE HARİTA İLE BİRLEŞTİR
async function fetchLiveOdds(marketMap) {
// Bu URL sadece sayıları (oranları) verir, çok hızlıdır.
const url = `https://www.mackolik.com/ajax/iddaa/outcomes/soccer/all/${MATCH_ID}`;
const response = await axios.get(url, {
headers: { 'X-Requested-With': 'XMLHttpRequest', 'User-Agent': 'Mozilla/5.0' }
});
const liveMarkets = response.data.data.markets;
console.log("\n📊 GÜNCEL ORANLAR (Dinamik Eşleştirme İle):\n");
console.log(`| ${"BAHİS TÜRÜ".padEnd(35)} | ${"SEÇENEK".padEnd(15)} | ${"ORAN".padEnd(6)} |`);
console.log("-".repeat(65));
// Canlı veriyi dönüyoruz
for (const [marketId, data] of Object.entries(liveMarkets)) {
// Haritamızdan bu ID'nin adını buluyoruz
// JSON'daki marketId bazen Mackolik ID'si bazen Iddaa ID'si olabiliyor.
// Genelde 'code' alanı ile bizim map'teki ID eşleşir veya key ile.
// Senin attığın JSON'da keyler (örn: 1, 3, 184.5) Mapping ID'si olarak kullanılıyor.
// DİKKAT: Senin attığın JSON'da Keyler (1, 184.5) bizim Map'teki ID'ler olmayabilir.
// HTML JSON'undaki "id" alanı (örn: 1) ile Canlı JSON'daki Key (örn: 1) eşleşir.
// Eşleşme Algoritması:
// HTML'deki `market.id` == LiveJSON'daki `key`
// HTML Map'imizi ID bazlı (1, 3, 184.5 gibi) tekrar düzenlememiz gerekebilir ama
// senin HTML JSON'una baktığımda "id": 18, "iddaaId": 55512092 var.
// Live JSON key'i "184.5" (Bu aslında 18 nolu marketin 4.5 barajı).
// Basit Eşleştirme Denemesi (ID üzerinden):
// Live JSON'daki key (örn "1" veya "184.5") HTML map'te yoksa, "code" (50465) üzerinden arama yapabiliriz.
// Ama en garantisi HTML'deki marketCollection içindeki key yapısıdır.
// Şimdilik basit ID eşleştirmesi yapalım, eğer map'te yoksa "Bilinmeyen" yazarız.
// Live JSON Key'i ile Map arıyoruz.
// Ancak HTML'deki "id" (örn: 1) ile Live JSON key (1) tutuyor.
// Fakat "184.5" gibi olanlar HTML'de "id: 18, sov: 4.5" olarak geçiyor.
let definitions = findDefinition(marketMap, marketId, data);
let marketName = definitions ? definitions.name : `Bilinmeyen (${marketId})`;
// Eğer barajlı bir bahisse (184.5 gibi) isme barajı ekle
// (Zaten HTML'den gelen isimde "4,5 Alt/Üst" yazıyor olacak)
for (const [outcomeKey, outcomeData] of Object.entries(data.outcomes)) {
if (outcomeData.outcome !== '-') {
let label = outcomeData.label;
// Eğer label mapping'den gelirse daha doğru olur ama outcomeData.label da genelde doğrudur.
console.log(`| ${marketName.padEnd(35)} | ${label.padEnd(15)} | ${outcomeData.outcome.padEnd(6)} |`);
}
}
}
}
// Yardımcı Fonksiyon: Live JSON Key'ini HTML Map içinde bulma
function findDefinition(marketMap, liveKey, liveData) {
// 1. Doğrudan ID eşleşmesi (Örn: "1" == "1")
// HTML'i parse ederken ID'leri key olarak ayarlamalıyız.
// Yukarıdaki createMarketMap fonksiyonunu buna göre revize ettim aşağıda.
// Asıl sorun: HTML JSON'da keyler "0", "1", "2" diye gidiyor array indexi gibi.
// Ama içlerinde "id": 1, "id": 18 var.
// Biz map'i oluştururken liveKey ile eşleşecek şekilde kurmalıyız.
// LiveKey "184.5" ise -> id=18 ve sov=4.5 olanı bulmalıyız.
// Bu karmaşıklığı çözmek için MarketMap'i bir Array olarak tutup find ile aramak en iyisi.
for (const def of Object.values(marketMap)) {
// Eğer ID tutuyorsa (Örn: 1 == 1)
if (def.rawId == liveKey) return def;
// Eğer ID ve Baraj (sov) tutuyorsa (Örn: LiveKey "184.5", Def id=18, sov=4.5)
if (liveKey.includes('.')) {
const [mainId, sov] = liveKey.split('.');
// Tamam float problemleri olabilir ama string olarak "18" == def.rawId
// Bu kısım biraz manuel mapping gerektirebilir ama HTML içindeki "name" zaten barajı içeriyor.
// HTML'deki iddaaMarketNo veya iddaaId ile LiveData'daki code eşleşebilir!
if (def.iddaaCode == liveData.code) return def; // EN GARANTİ YÖNTEM BU!
}
if (def.iddaaCode == liveData.code) return def;
}
return null;
}
// ------------------------------------------------------------------
// REVIZE EDİLMİŞ HARİTA OLUŞTURUCU (EN SAĞLAMI)
// ------------------------------------------------------------------
async function main() {
const url = `https://www.mackolik.com/ajax/iddaa/markets/soccer/all/${MATCH_ID}?template=all`;
const response = await axios.get(url, { headers: { 'X-Requested-With': 'XMLHttpRequest', 'User-Agent': 'Mozilla/5.0' } });
const $ = cheerio.load(response.data.data.html);
const settingsRaw = $('.widget-iddaa-markets').first().attr('data-settings');
if (!settingsRaw) return;
const settingsJson = JSON.parse(he.decode(settingsRaw));
const definitions = settingsJson.iddaaEventId.marketCollection;
// Haritamızı bir dizi (array) yapalım, içinde arama yapacağız.
let marketDefinitions = [];
for (const key in definitions) {
const m = definitions[key];
marketDefinitions.push({
name: m.name, // Örn: "Maç Sonucu" veya "4,5 Alt/Üst"
rawId: m.id, // Örn: 1 veya 18
iddaaCode: m.iddaaNo, // Örn: "10313" (HTML'deki code) -> LiveData'da "code" ile eşleşecek mi bakacağız.
iddaaMarketId: m.iddaaId, // Örn: 21983276 -> LiveData'da code olarak gelebilir.
sov: m.sov // Baraj değeri (4.5)
});
}
// --- LIVE DATA ÇEK ---
const liveUrl = `https://www.mackolik.com/ajax/iddaa/outcomes/soccer/all/${MATCH_ID}`;
const liveRes = await axios.get(liveUrl, { headers: { 'X-Requested-With': 'XMLHttpRequest', 'User-Agent': 'Mozilla/5.0' } });
const liveMarkets = liveRes.data.data.markets;
// --- EŞLEŞTİRME VE YAZDIRMA ---
console.log(`\nMAÇ: ${MATCH_ID} | DATA ANALİZİ SONUCU`);
console.log("=".repeat(70));
for (const [liveKey, liveData] of Object.entries(liveMarkets)) {
// EŞLEŞTİRME MANTIĞI:
// Live Data içindeki "code" (Örn: 50465) ile HTML'deki "iddaaId" (Örn: 55507607) veya "iddaaNo" (Örn: 18660) eşleşmeli.
// Senin attığın son örneklerde:
// HTML JSON: "iddaaId": 55507607, "iddaaNo": "18660"
// LIVE JSON: "code": "50465"
// HATA: Kodlar (Code) maç başladığında (Live) ve başlamadan önce (Pre-match) değişiyor olabilir!
// Bu durumda en güvenilir eşleşme "Market Tipi" (ID) ve "Baraj" (SOV) üzerinden olur.
let matchedDef = marketDefinitions.find(def => {
// 1. Ana ID eşleşiyor mu? (1 == 1)
if (def.rawId == liveKey) return true;
// 2. Barajlı ID kontrolü (184.5 -> id:18, sov:4.5)
if (liveKey.includes('.')) {
// Float çevirmeden string karşılaştırması riskli olabilir, dikkat.
// LiveKey "184.5"
// Def: rawId=18, sov=4.5
// 18 == 18 AND 4.5 == 4.5
if (def.rawId == Math.floor(parseFloat(liveKey)) && def.sov == parseFloat(liveKey.split('.')[1] + '.' + (liveKey.split('.')[2] || '0'))) {
// Basitçe string match daha güvenli olabilir
return def.rawId == 18 && def.sov == 4.5 && liveKey == "184.5"; // Örnek mantık
}
// Daha basit: Mackolik Live Key yapısı: {MARKET_ID}{BARAJ}
// "18" + "4.5" -> "184.5"
if (def.rawId == 18 && liveKey == `18${def.sov}`) return true;
if (def.rawId == 19 && liveKey == `19${def.sov}`) return true; // 1. Yarı Alt üst
}
return false;
});
// Eğer yukarıdaki ID mantığı tutmazsa manuel düzeltme:
// Mackolik LiveKey formatı: {ID} veya {ID}{SOV}
// Örn: Market 1 -> Key "1"
// Örn: Market 18 (Alt/Üst), Sov 4.5 -> Key "184.5"
// Hızlı çözüm için bir Map oluşturuyorum:
const name = getMarketNameFromKey(liveKey, marketDefinitions);
for (const [k, v] of Object.entries(liveData.outcomes)) {
if (v.outcome !== '-') {
console.log(`| ${name.padEnd(35)} | ${v.label.padEnd(10)} | ${v.outcome} |`);
}
}
}
}
function getMarketNameFromKey(key, definitions) {
// 1. Tam eşleşme (ID 1, 3, 11 vb.)
let exact = definitions.find(d => d.rawId == key);
if (exact) return exact.name;
// 2. Noktalı Eşleşme (184.5, 191.5 vb.)
if (key.includes('.')) {
// key: 184.5 -> id: 18, sov: 4.5
// key: 190.5 -> id: 19, sov: 0.5
// Püf nokta: String olarak sov'u ayıklamak.
// Genelde sonu .5 ile biter.
// Ama ID 18, 19, 28, 29 gibi alt/üst türleri var.
// Bu kısmı senin için basitleştiriyorum:
// HTML'deki isimleri tara, hangisinin sov değeri key ile uyuşuyorsa onu al.
for (let def of definitions) {
if (def.sov !== null) {
// Basit bir string contains kontrolü bile çoğu zaman yeter.
// Örneğin key="184.5", def.rawId=18, def.sov=4.5 -> Eşleşir.
// key="280.5", def.rawId=28, def.sov=0.5 -> Eşleşir.
// Formül: Key, Def.ID ile başlıyor mu VE Key, Def.Sov ile bitiyor mu?
if (key.startsWith(def.rawId) && key.endsWith(def.sov)) {
return def.name;
}
}
}
}
return `Bilinmeyen Market (${key})`;
}
main();