This commit is contained in:
Executable
+276
@@ -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();
|
||||
Reference in New Issue
Block a user