Орландо хотын Kia Center-т зохион байгуулагдаж буй Duel Arena тэмцээний хүрээнд контент бүтээгч Gypsy Crusader болон Кинг Азулей нарын кикбоксын тулаан болох гэж байна.
Тэмцээний үндсэн тулаанд Майк Перри болон Диллон Данис нар өрсөлдөхөөр төлөвлөгдсөн байсан ч Данис тэмцээн эхлэхээс өмнө цуцалснаар түүнийг дунд жингийн туршлагатай тулаанч Брэндон Женкинс орлохоор болжээ. Энэхүү өөрчлөлтөөс үүдэн тэмцээнийг төлбөртэй нэвтрүүлгээс үнэгүй нэвтрүүлэгт шилжүүлж, Майк Перригийн шагналын сан 50 хувиар буурсан байна.
Кинг Азулей нь албан ёсны бүртгэлгүй 1000 гаруй тулаанд оролцсон гэх баримтгүй мэдээлэлтэй бол Пол Миллер нь өмнө нь сонирхогчийн түвшинд тодорхой амжилт үзүүлж байсан туршлагатай. Түүнчлэн энэ үдшийн тэмцээнд WWE-ийн од асан Патрик Кларк буюу Velveteen Dream боксын спортын гараагаа эхлүүлж, подкастер Райан Пауноллтой тулалдана.
Тэмцээний салбар тулаануудад UFC-ийн туршлагатай тулаанчид болох Фил Роу, Жими Манува, Чейз Шерман нар октагонд гарч хүчээ сорих юм. Duel Arena тэмцээний тулаануудыг олон нийтийн сүлжээгээр дамжуулан үнэгүй үзэх боломжтой.
Дэлгэрэнгүй эх сурвалжийг харах
Эх сурвалжийг нээх ↓
Gypsy Crusader is back in the ring tonight as the controversial streamer takes on King Azoulay in a kickboxing clash.
Mike Perry and Dillon Danis were supposed to headline the inaugural Duel Arena event at the Kia Center in Orlando. However, the BJJ black belt pulled out at the beginning of fight week and was replaced by middleweight veteran Brandon Jenkins.
This meant that the card was moved from pay-per-view to free-to-air and Perry has accepted a 50 per cent pay cut. It also puts the majority of drawing power on Paul Miller and Ben Azoulay, the controversial duo.
Azoulay claims to have had over 1,000 undocumented fights – but zero that were ever on the books. Meanwhile, Miller has a legitimate amateur record under a different name that can be verified, and infamously defeated Supah Hot Fire on Adin Ross’ Brand Risk Promotions back in March.
The card will be full of freak show bouts, including the boxing debut of former WWE star Patrick Clark Jr – known to fans as Velveteen Dream. He will take on podcaster and adult film star Ryan Pownall on a card that also features ex-UFC talent.
Phil Rowe will box on the undercard, while Jimi Manuwa faces Chase Sherman among other fights featuring UFC veterans.
The event is free to air on Duel Arena’s social media channels and we will be keeping you up to date here on Bloody Elbow. Make sure to sign up to Talking Points above to stay up to date with our chats throughout the night.
Welcome to the Bloody Elbow live blog from tonight’s Duel Arena event
Good evening and welcome to our live coverage from tonight’s bizarre Duel Arena fight card. We have no idea what to expect, but we will have full results right here, as well as a stream to watch the fights completely free.
const postId = 329543;
let modifiedDate = “2026-08-29T20:58:30+00:00”;
// creates a timestamp cachebuster rounded to nearest 30 seconds threshold
function getLiveBlogCacheBusterTimestamp() {
const now = new Date();
// Get current UTC time components
const minutes = now.getUTCMinutes();
const seconds = now.getUTCSeconds();
// Round up to the nearest 30 seconds
const roundedSeconds = Math.ceil(seconds / 30) * 30;
// Adjust minutes and seconds
let roundedDate = new Date(Date.UTC(
now.getUTCFullYear(),
now.getUTCMonth(),
now.getUTCDate(),
now.getUTCHours(),
minutes,
roundedSeconds
));
// Convert to Unix timestamp
return Math.floor(roundedDate.getTime() / 1000);
}
function getPollingEndpointUrl(postId) {
const baseUrl = “/wp-json/grv-live-blog/v1/post-modified-date”;
const cacheBuster = getLiveBlogCacheBusterTimestamp();
return `${baseUrl}?post_id=${postId}&t=${encodeURIComponent(cacheBuster)}`;
}
function getUpdatedEventEndpointUrl(postId) {
const baseUrl = “/wp-json/grv-live-blog/v1/get-updated-events”;
const cacheBuster = getLiveBlogCacheBusterTimestamp();
return `${baseUrl}?post_id=${postId}&t=${encodeURIComponent(cacheBuster)}`;
}
function showRefreshButton() {
const refresh_btn = document.getElementById(“glb-btn”);
refresh_btn.style.display = “block”;
}
function hideRefreshButton() {
const refresh_btn = document.getElementById(“glb-btn”);
refresh_btn.style.display = “none”;
}
function jumpToLatestEvent() {
hideRefreshButton();
const element = document.querySelector(“.wp-block-grvmedia-grv-live-blog”);
// Scroll to the element
if (element) {
element.scrollIntoView({ behavior: “smooth”, block: “start” });
}
}
function createPointItem(item) {
// Create the
const li = document.createElement(“li”);
li.appendChild(document.createTextNode(item.headline));
const a = document.createElement(“a”);
a.href = `#${item.anchorId}`; // Set the href attribute
a.innerHTML = `View post
`; // Set the text content
li.appendChild(a);
return li;
}
function addScriptSrcToHead(src) {
let s = document.createElement(“script”);
// expectation is that this is the first script element in the head
let insertion = document.getElementsByTagName(“script”)[0];
s.async = true;
s.src = src;
insertion.parentNode.insertBefore(s, insertion);
}
function refreshScripts( fragment ) {
let scripts = fragment.querySelectorAll(“script”);
for ( let script of scripts ) {
let freshScript = document.createElement(“script”);
// copy attributes
let attrs = script.attributes;
for ( let attr of attrs ) {
freshScript.setAttribute( attr.name, attr.value );
}
// copy inner script code. #718, #782
freshScript.innerHTML = script.innerHTML;
script.parentNode.replaceChild( freshScript, script );
}
}
function reverseEvents(updated_events){
const events = Object.entries(updated_events);
// Reverse the order of the entries
events.reverse();
// Convert the reversed entries back to an object
return Object.fromEntries(events);
}
function fetchUpdatedEvents() {
const apiUrl = getUpdatedEventEndpointUrl(postId);
fetch(apiUrl)
.then(response => response.json())
.then(updatedEvents => {
// Find the events container
let key_points = document.querySelector(“.grv-live-blog-key-points”);
// if we had no key points to start with but have some now we need to create the div and ul
// for it to populate
if(updatedEvents.key_points.length > 0) {
if (!key_points) {
// Element does not exist, create it
key_points = document.createElement(“div”);
key_points.className = “grv-live-blog-key-points”;
// Create and append
to the new element
const heading = document.createElement(“h5”);
heading.textContent = “Key points”;
key_points.appendChild(heading);
// Create and append
- to the new element
const ul = document.createElement(“ul”);
ul.className = “grv-live-blog-key-points-list”;
key_points.appendChild(ul);
const glb_wrapper = document.getElementById(“glb-wrapper”);
if (glb_wrapper) {
// Insert the new element before the wrapper
glb_wrapper.parentNode.insertBefore(key_points, glb_wrapper);
}
}
const key_points_list = document.querySelector(“.grv-live-blog-key-points-list”);
key_points_list.innerHTML = “”;
// Update the key points
updatedEvents.key_points.forEach(point => {
const point_item = createPointItem(point);
key_points_list.appendChild(point_item);
});
// else we have no key points so lets remove the list
}else{
if (key_points) {
key_points.remove();
}
}
// now deal with the events themselves…
const events_container = document.querySelector(“.wp-block-grvmedia-grv-live-blog”);
// get a map of the existing events keyed by id
const existingEvents = Array.from(events_container.querySelectorAll(“.wp-block-grvmedia-grv-live-blog-event”))
.reduce((map, event) => {
map[event.id] = event;
return map;
}, {});
// get the existing and updated keys so we can compare
const existingKeys = Object.keys(existingEvents);
const updatedKeys = Object.keys(updatedEvents.updated_blocks);
// find events that are in existing but not in updated
const keysToRemove = existingKeys.filter(key => !updatedKeys.includes(key));
// remove any events that have been deleted
keysToRemove.forEach(key => {
// Find the element with the corresponding id
const element = document.getElementById(key);
// Remove the element if it exists
if (element) {
element.remove();
}
});
// reverse the events so they are in the right order if we add multiple…
updatedEvents.updated_blocks = reverseEvents(updatedEvents.updated_blocks);
// loop through each updated event
Object.values(updatedEvents.updated_blocks).forEach(updatedEvent => {
// create temp elem so we can hydrate it from our rendered event and then access the id etc
const parser = new DOMParser();
const tempEvent = parser.parseFromString(updatedEvent,”text/html”);
// Select the event from our temp container
const eventElement = tempEvent.querySelector(“.wp-block-grvmedia-grv-live-blog-event”);
// Extract the id
const eventId = eventElement ? eventElement.id : null;
// Using a fragment allows us to refresh scripts before attaching to dom
let frag = document.createDocumentFragment();
if (existingEvents[eventId]) {
frag.append( …eventElement.childNodes );
} else {
frag.append( eventElement );
}
refreshScripts( frag );
// if its an existing event replace the content of the event so we dont cause a jump
if (existingEvents[eventId]) {
// get the existing event
const event = document.getElementById(eventId);
event.style.minHeight = event.offsetHeight + “px”;
// update its innerHTML and class incase we have changed to featured or breaking etc
event.className = eventElement.className;
event.replaceChildren(…frag.childNodes);
const seeMore = event.querySelector(“.see-more-wrapper.lazy”);
let seeMoreSrc = seeMore?.getAttribute(“data-src”);
if (seeMoreSrc) {
if ( seeMoreSrc.indexOf(‘instagram’) != -1 && window.instgrm ) {
window.instgrm.Embeds?.process();
} else {
addScriptSrcToHead(seeMoreSrc);
}
}
// if its a new event add to the top – TODO: sort order if multiple new events
} else {
// Create a new event
events_container.insertBefore(frag, events_container.firstChild);
}
});
})
.catch(error => {
console.error(“Error fetching updated blocks:”, error);
});
}
document.addEventListener(“DOMContentLoaded”, function() {
function startPolling(postId) {
function fetchPostModifiedDate() {
const url = getPollingEndpointUrl(postId);
fetch(url)
.then(response => response.json())
.then(data => {
// if our post modified date has changed we have an update
if(modifiedDate != data.modified_date) {
// update the modified time to be the new modified time
modifiedDate = data.modified_date;
// show the button so a user can refresh
fetchUpdatedEvents();
showRefreshButton();
}
})
.catch(error => {
console.error(“Error fetching post modified date:”, error);
});
}
// Set interval to fetch every 30 seconds
setInterval(fetchPostModifiedDate, 30000); // 30 seconds
}
// Start polling
startPolling(postId);
const refreshButton = document.getElementById(“glb-btn”);
refreshButton.addEventListener(“click”, jumpToLatestEvent);
});

