Compare commits

...

2 Commits

Author SHA1 Message Date
Timo 869c64171b Fix Disney+ force sync, seek, and HCM regressions for v2.5.3
The v2.5.2 Disney+ page-API integration leaked blob-relative <video>
time into force sync, seeks, and heartbeats when the page-API bridge
had no fresh data, so force sync on Disney+ appeared broken.

- getSyncCurrentTime/getSyncDuration now refuse native values on Disney+
  (return null/0) so stale bridge data degrades to a clean no-op instead
  of broadcasting garbage to peers. The get_current_time handler and
  episode/lobby/hcmIsLive paths are routed through the same accessor.
- Validate FORCE_SYNC_PREPARE/SEEK payloads as finite before relaying;
  the internal coercion no longer treats '' as 0.
- Stop double-routing FORCE_SYNC_PREPARE from the popup path (the
  generic popup route now covers only play/pause/seek).
- popup force-sync: exclude null/empty peer times from the jump-to-others
  median (Number(null)===0 was dragging the target to 0), guard against
  NaN end-to-end, clear the dangling reset timer on failure, and retry
  without re-injecting when the content script responds but the Disney+
  bridge has not yet delivered a finite time.
- hcmIsLive skips the native-duration live signal on Disney+ only,
  preserving YouTube/Twitch Infinity-duration live detection.

Disney-specific logic remains strictly gated to disneyplus.com; no
Netflix/YouTube/Twitch/generic path is affected.
2026-07-02 16:57:48 +02:00
GitHub Action 6ccaf45f8e chore(release): update versions to v2.5.2 [skip ci] 2026-07-02 13:34:11 +00:00
12 changed files with 196 additions and 121 deletions
+2 -2
View File
@@ -6,7 +6,7 @@
<p align="center">
<a href="https://github.com/Shik3i/KoalaSync/actions/workflows/release.yml"><img src="https://github.com/Shik3i/KoalaSync/actions/workflows/release.yml/badge.svg" alt="Release Status"></a>
<a href="https://github.com/Shik3i/KoalaSync/releases"><img src="https://img.shields.io/badge/Release-v2.5.1-blue?logo=github" alt="GitHub release"></a>
<a href="https://github.com/Shik3i/KoalaSync/releases"><img src="https://img.shields.io/badge/Release-v2.5.2-blue?logo=github" alt="GitHub release"></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue" alt="License"></a>
<a href="https://addons.mozilla.org/de/firefox/addon/koalasync/"><img src="https://img.shields.io/badge/Firefox-Download-orange?logo=firefoxbrowser&logoColor=white" alt="Firefox Add-on"></a>
<a href="https://chromewebstore.google.com/detail/koalasync/obbnmkmlaaddodakcbdljknjpagklifc"><img src="https://img.shields.io/badge/Chrome-Download-blue?logo=googlechrome&logoColor=white" alt="Chrome Extension"></a>
@@ -14,7 +14,7 @@
<p align="center"><i>KoalaSync is a lightweight Browser Extension and Relay Server for synchronized video playback on almost any website with a video element—YouTube, Twitch, Netflix, Emby, Jellyfin, and beyond. Built with a focus on <b>Data Sovereignty</b> and <b>Performance</b>.</i></p>
<p align="center"><a href="docs/CHANGELOG.md"><b>New v2.5.1 Release!</b> — See what's changed</a></p>
<p align="center"><a href="docs/CHANGELOG.md"><b>New v2.5.2 Release!</b> — See what's changed</a></p>
### 🌟 Why KoalaSync?
+13
View File
@@ -8,6 +8,19 @@ All notable changes to the KoalaSync browser extension and relay server.
---
## [v2.5.3] — 2026-07-02
### Fixed
- **Extension: Disney+ force sync and seek reliability** — The v2.5.2 Disney+ page-API integration leaked blob-relative `<video>` time into force sync, seeks, and heartbeats when the page-API bridge had no fresh data, which presented as "force sync does nothing on Disney+". Time/duration accessors now refuse to return native values on Disney+ (returning null/0) so stale bridge data degrades to a clean no-op instead of broadcasting garbage. `FORCE_SYNC_PREPARE` and `SEEK` payloads are now validated as finite before being relayed, and the popup's force-sync flow fails cleanly with a clear error rather than sending NaN through.
- **Extension: Force-sync no longer routed twice** — A popup-initiated `FORCE_SYNC_PREPARE` was being delivered to the content script twice (once by the generic popup route and once by the force-sync-specific route), causing a double seek. The generic route is now scoped to play/pause/seek only.
- **Extension: Disney+ Host Control Mode classification** — `hcmIsLive` previously read the native `<video>` duration to detect live streams, which on Disney+ is blob-relative garbage and falsely classified every stream as live (disabling snap-back and the desync dialog). The native-duration live signal is now skipped on Disney+ while YouTube/Twitch live detection via `Infinity` duration is preserved.
- **Extension: Disney+ episode auto-sync and lobby readiness** — Episode-transition detection and the episode-lobby "ready" poll now read the playhead through the gated time accessor, so they no longer rely on blob-relative `currentTime` on Disney+.
- **Extension: Force-sync median no longer skewed by peers without a known time** — A peer broadcasting `currentTime: null` (e.g. a Disney+ peer whose page-API bridge was not yet ready, or a freshly joined peer) was coerced to `0` by the jump-to-others median calculation, dragging the sync target toward the start of the video. Null and empty peer times are now excluded before the median.
- **Extension: Force-sync `jump-to-me` retry on Disney+** — When the content script responds but the page-API bridge has not yet delivered a finite time (typical during the first ~250 ms after a Disney+ player loads), the popup now retries once without redundantly re-injecting the content script.
- **Extension: Empty-string seek payload rejection** — The internal seek-time coercion no longer treats `''` as `0`; an empty-string `targetTime`/`currentTime` is rejected as invalid.
---
## [v2.5.2] — 2026-07-02
### Added
+33 -2
View File
@@ -2227,12 +2227,40 @@ async function handleAsyncMessage(message, sender, sendResponse) {
return;
}
const payload = message.payload && typeof message.payload === 'object' ? message.payload : {};
const payloadNumber = (value) => value !== undefined && value !== null && value !== '' ? Number(value) : NaN;
if (message.action === EVENTS.FORCE_SYNC_PREPARE) {
const targetTime = payloadNumber(payload.targetTime);
if (!Number.isFinite(targetTime)) {
sendResponse({ status: 'invalid_params' });
return;
}
payload.targetTime = targetTime;
} else if (message.action === EVENTS.SEEK) {
const targetTime = payloadNumber(payload.targetTime !== undefined ? payload.targetTime : payload.currentTime);
if (!Number.isFinite(targetTime)) {
sendResponse({ status: 'invalid_params' });
return;
}
payload.currentTime = targetTime;
payload.targetTime = targetTime;
}
const timestamp = Date.now();
localSeq++;
chrome.storage.session.set({ localSeq });
updateLastAction(message.action, 'You', timestamp);
const payload = message.payload || {};
const hasPlaybackTime = Number.isFinite(payload.currentTime) || Number.isFinite(payload.targetTime);
if (!sender?.tab && (message.action === EVENTS.PLAY || message.action === EVENTS.PAUSE) && !hasPlaybackTime) {
const tabId = currentTabId ? parseInt(currentTabId) : NaN;
if (!isNaN(tabId)) {
const state = await getReadyTabVideoState(tabId);
if (state && !state.error && state.found && Number.isFinite(state.currentTime)) {
payload.currentTime = state.currentTime;
}
}
}
lastActionState.targetTime = payload.targetTime !== undefined ? payload.targetTime : payload.currentTime;
if (storageInitialized) chrome.storage.session.set({ lastActionState });
@@ -2246,6 +2274,10 @@ async function handleAsyncMessage(message, sender, sendResponse) {
currentTime: payload.currentTime !== undefined ? payload.currentTime : (payload.targetTime !== undefined ? payload.targetTime : undefined)
});
if (!sender?.tab && (message.action === EVENTS.PLAY || message.action === EVENTS.PAUSE || message.action === EVENTS.SEEK)) {
routeToContent(message.action, message.payload);
}
if (message.action === EVENTS.FORCE_SYNC_PREPARE) {
isForceSyncInitiator = true;
forceSyncAcks.clear();
@@ -2299,7 +2331,6 @@ async function handleAsyncMessage(message, sender, sendResponse) {
sendResponse({ status: 'error' });
});
} else {
routeToContent(message.action, message.payload);
processEvent().catch(err => {
addLog('Content event privacy error: ' + err.message, 'error');
sendResponse({ status: 'error' });
+37 -31
View File
@@ -134,18 +134,20 @@
function hostMatchesUrl(host, url) {
const normalized = String(url || '')
.replace(/^https?:\/\//i, '')
.split('/')[0]
.toLowerCase();
return normalized && (host === normalized || host.endsWith(`.${normalized}`));
}
function matchesPlayerUrls(urls) {
const host = window.location.hostname.toLowerCase();
return Array.isArray(urls) && urls.some(url => hostMatchesUrl(host, url));
}
function isDisneyPlusHost() {
.replace(/^https?:\/\//i, '')
.split('/')[0]
.toLowerCase();
return normalized && (host === normalized || host.endsWith(`.${normalized}`));
}
function matchesPlayerUrls(urls) {
const host = window.location.hostname.toLowerCase();
return Array.isArray(urls) && urls.some(url => hostMatchesUrl(host, url));
}
function isDisneyPlusHost() {
return matchesPlayerUrls(['disneyplus.com']);
}
function getDisneyPlusTimeline() {
if (!isDisneyPlusHost()) return null;
@@ -283,7 +285,7 @@
// --- Episode Auto-Sync State ---
let lastKnownMediaTitle = null;
let lastKnownMediaTitle = null;
let episodeTransitionDebounce = null;
@@ -746,17 +748,19 @@
btnRow.append(soloBtn, stayBtn);
wrap.append(title, body, btnRow);
root.appendChild(wrap);
document.body.appendChild(host);
root.appendChild(wrap);
document.body.appendChild(host);
hcmDialogHost = host;
let settled = false;
// Re-query the host's current position on click instead of using the
// potentially stale target captured at HOST_BLOCKED time (M-1).
const stay = () => {
@@ -786,13 +790,15 @@
hcmDesynced = true;
reportLog('Host-only: you chose to watch on your own (desynced)', 'warn');
reportLog('Host-only: you chose to watch on your own (desynced)', 'warn');
// Notify background so it can relay our desynced state to the host via
// Notify background so it can relay our desynced state to the host via
// heartbeats — the host's UI then knows we're not following commands
// instead of appearing silently un-ACK'd.
chrome.runtime.sendMessage({ type: 'HCM_DESYNC_STATE', desynced: true }).catch(() => {});
hcmShowBadge();
}
@@ -941,12 +947,12 @@
// Scan likely media hosts even when light-DOM videos exist; many players
// Scan likely media hosts even when light-DOM videos exist; many players
// expose a tiny preview/ad video outside Shadow DOM and the real player inside.
// expose a tiny preview/ad video outside Shadow DOM and the real player inside.
const potentialHosts = root.querySelectorAll('[id*="player" i], [class*="player" i], [id*="video" i], [class*="video" i], [id*="media" i], [class*="media" i], [id*="stream" i], [class*="stream" i], ytd-player, netflix-player, emby-player, jellyfin-player, video-player');
for (const el of potentialHosts) {
if (el.shadowRoot) {
const found = findVideo(el.shadowRoot);
+1 -1
View File
@@ -2,7 +2,7 @@
"manifest_version": 3,
"default_locale": "en",
"name": "KoalaSync",
"version": "2.5.1",
"version": "2.5.2",
"description": "Synchronize video playback on YouTube, Netflix, Emby, Jellyfin, and any HTML5 site in real-time with friends.",
"permissions": [
"storage",
+38 -17
View File
@@ -1588,8 +1588,9 @@ elements.forceSyncBtn.addEventListener('click', async () => {
}
const peers = status.peers || [];
const otherTimes = peers
.filter(p => typeof p === 'object' && p.peerId !== localPeerId && p.currentTime != null && !isNaN(p.currentTime))
.map(p => p.currentTime);
.filter(p => typeof p === 'object' && p.peerId !== localPeerId && p.currentTime != null && p.currentTime !== '')
.map(p => Number(p.currentTime))
.filter(Number.isFinite);
if (otherTimes.length === 0) {
showError(getMessage('ERR_NO_PEERS_TIME'));
@@ -1618,37 +1619,57 @@ elements.forceSyncBtn.addEventListener('click', async () => {
forceSyncResetTimer = setTimeout(forceSyncReset, syncTimeoutMs);
const tabId = parseInt(status.targetTabId);
const failForceSyncTime = () => {
if (forceSyncResetTimer) { clearTimeout(forceSyncResetTimer); forceSyncResetTimer = null; }
showError(getMessage('ERR_NO_VIDEO_TAB'));
forceSyncDone = true;
elements.forceSyncBtn.disabled = false;
elements.forceSyncBtn.textContent = originalText;
};
const sendForceSync = (time) => {
if (time === null || time === undefined) {
failForceSyncTime();
return;
}
const target = Number(time);
if (!Number.isFinite(target)) {
failForceSyncTime();
return;
}
chrome.runtime.sendMessage({
type: 'CONTENT_EVENT',
action: EVENTS.FORCE_SYNC_PREPARE,
payload: { targetTime: parseFloat(time) }
payload: { targetTime: target }
});
};
if (mode === 'jump-to-me') {
const retryQueryTime = () => {
chrome.tabs.sendMessage(tabId, { action: 'get_current_time' }, (retryResponse) => {
if (chrome.runtime.lastError || !retryResponse || !Number.isFinite(retryResponse.currentTime)) {
failForceSyncTime();
return;
}
sendForceSync(retryResponse.currentTime);
});
};
chrome.tabs.sendMessage(tabId, { action: 'get_current_time' }, (response) => {
if (chrome.runtime.lastError || !response || response.currentTime === undefined) {
if (Number.isFinite(response?.currentTime)) {
sendForceSync(response.currentTime);
return;
}
if (chrome.runtime.lastError || !response) {
chrome.runtime.sendMessage({ type: 'INJECT_CONTENT_SCRIPT', tabId }, (injectResponse) => {
if (chrome.runtime.lastError || !injectResponse || injectResponse.status !== 'ok') {
showError(getMessage('ERR_NO_VIDEO_TAB'));
forceSyncDone = true;
elements.forceSyncBtn.disabled = false;
elements.forceSyncBtn.textContent = originalText;
failForceSyncTime();
return;
}
setTimeout(() => {
chrome.tabs.sendMessage(tabId, { action: 'get_current_time' }, (retryResponse) => {
if (chrome.runtime.lastError) return;
if (retryResponse && retryResponse.currentTime !== undefined) {
sendForceSync(retryResponse.currentTime);
}
});
}, 500);
setTimeout(retryQueryTime, 500);
});
return;
}
sendForceSync(response.currentTime);
setTimeout(retryQueryTime, 500);
});
} else {
sendForceSync(targetTime);
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "koalasync",
"version": "2.5.1",
"version": "2.5.2",
"description": "KoalaSync Build Scripts",
"private": true,
"type": "module",
+5 -1
View File
@@ -122,6 +122,10 @@ const disneyVideo = makeVideo('disney-offset', 1920, 1080, {
assert.equal(disneyFns.getSyncCurrentTime(disneyVideo), 9);
assert.equal(disneyFns.getSyncDuration(disneyVideo), 10800);
assert.equal(disneyFns.toNativeSeekTime(disneyVideo, 39), 39);
assert.equal(disneyFns.getSyncCurrentTime(makeVideo('disney-native-broken', 1920, 1080, {
currentTime: Number.NaN,
duration: 0
})), 9);
const disneyNoPageApiFns = loadTimelineFns('www.disneyplus.com');
const disneyOffsetVideo = makeVideo('disney-offset', 1920, 1080, {
@@ -129,7 +133,7 @@ const disneyOffsetVideo = makeVideo('disney-offset', 1920, 1080, {
duration: 0,
seekable: makeSeekable([[20, 10820]])
});
assert.equal(disneyNoPageApiFns.getSyncCurrentTime(disneyOffsetVideo), 29);
assert.equal(disneyNoPageApiFns.getSyncCurrentTime(disneyOffsetVideo), null);
assert.equal(disneyNoPageApiFns.getSyncDuration(disneyOffsetVideo), 0);
assert.equal(disneyNoPageApiFns.toNativeSeekTime(disneyOffsetVideo, 39), 39);
+1 -1
View File
@@ -7,7 +7,7 @@
*/
export const PROTOCOL_VERSION = "1.0.0";
export const APP_VERSION = "2.5.1";
export const APP_VERSION = "2.5.2";
export const OFFICIAL_SERVER_URL = 'wss://syncserver.koalastuff.net';
export const OFFICIAL_LANDING_PAGE_URL = 'https://sync.koalastuff.net';
+62 -62
View File
@@ -3,31 +3,31 @@
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://sync.koalastuff.net/imprint</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>monthly</changefreq>
<priority>0.3</priority>
</url>
<url>
<loc>https://sync.koalastuff.net/privacy</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>monthly</changefreq>
<priority>0.3</priority>
</url>
<url>
<loc>https://sync.koalastuff.net/de/impressum</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>monthly</changefreq>
<priority>0.3</priority>
</url>
<url>
<loc>https://sync.koalastuff.net/de/datenschutz</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>monthly</changefreq>
<priority>0.3</priority>
</url>
<url>
<loc>https://sync.koalastuff.net/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -49,7 +49,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/de/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -71,7 +71,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -93,7 +93,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/de/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -115,7 +115,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -137,7 +137,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/de/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -159,7 +159,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/fr/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -181,7 +181,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/fr/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -203,7 +203,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/fr/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -225,7 +225,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/es/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -247,7 +247,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/es/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -269,7 +269,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/es/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -291,7 +291,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/it/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -313,7 +313,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/it/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -335,7 +335,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/it/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -357,7 +357,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/nl/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -379,7 +379,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/nl/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -401,7 +401,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/nl/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -423,7 +423,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/pl/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -445,7 +445,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/pl/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -467,7 +467,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/pl/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -489,7 +489,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/pt/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -511,7 +511,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/pt/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -533,7 +533,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/pt/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -555,7 +555,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/pt-BR/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -577,7 +577,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/pt-BR/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -599,7 +599,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/pt-BR/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -621,7 +621,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/ru/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -643,7 +643,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/ru/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -665,7 +665,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/ru/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -687,7 +687,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/tr/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -709,7 +709,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/tr/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -731,7 +731,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/tr/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -753,7 +753,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/ja/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -775,7 +775,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/ja/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -797,7 +797,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/ja/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -819,7 +819,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/ko/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -841,7 +841,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/ko/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -863,7 +863,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/ko/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -885,7 +885,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/zh/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -907,7 +907,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/zh/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -929,7 +929,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/zh/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -951,7 +951,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/uk/alternatives</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives"/>
@@ -973,7 +973,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/uk/alternatives/teleparty</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/teleparty"/>
@@ -995,7 +995,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/uk/alternatives/screen-sharing</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/alternatives/screen-sharing"/>
@@ -1017,7 +1017,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
@@ -1037,7 +1037,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/de/</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
@@ -1057,7 +1057,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/fr/</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
@@ -1077,7 +1077,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/es/</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
@@ -1097,7 +1097,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/pt-BR/</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
@@ -1117,7 +1117,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/ru/</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
@@ -1137,7 +1137,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/it/</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
@@ -1157,7 +1157,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/pl/</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
@@ -1177,7 +1177,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/tr/</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
@@ -1197,7 +1197,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/nl/</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
@@ -1217,7 +1217,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/ja/</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
@@ -1237,7 +1237,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/ko/</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
@@ -1257,7 +1257,7 @@
</url>
<url>
<loc>https://sync.koalastuff.net/pt/</loc>
<lastmod>2026-07-01</lastmod>
<lastmod>2026-07-02</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="en" href="https://sync.koalastuff.net/"/>
+1 -1
View File
@@ -106,7 +106,7 @@
"priceCurrency": "EUR"
},
"description": "{{SCHEMA_APP_DESC}}",
"softwareVersion": "2.5.1",
"softwareVersion": "2.5.2",
"license": "https://opensource.org/licenses/MIT",
"sameAs": "https://github.com/Shik3i/KoalaSync",
"image": "https://sync.koalastuff.net/assets/NewLogoIcon.webp",
+2 -2
View File
@@ -1,4 +1,4 @@
{
"version": "2.5.1",
"date": "2026-07-01T17:48:39Z"
"version": "2.5.2",
"date": "2026-07-02T13:34:11Z"
}