Last active
May 14, 2026 21:21
-
-
Save Macadoshis/e43f033dc7091409353c898f2e3af26a to your computer and use it in GitHub Desktop.
m4u.mjs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name m3u4u playlists synchronizer | |
| // @name:fr m3u4u synchronizeur de playlists | |
| // @namespace https://m3u4u.com/ | |
| // @version 2026-05-13 | |
| // @description m3u4u.com playlists synchronizer | |
| // @description:fr m3u4u.com synchronizeur de playlists | |
| // @license MIT | |
| // @author github.com/Macadoshis | |
| // @match https://m3u4u.com/playlists | |
| // @icon https://www.google.com/s2/favicons?sz=64&domain=m3u4u.com | |
| // @grant none | |
| // @esversion 8 | |
| // @downloadURL https://update.greasyfork.org/scripts/578171/m3u4u%20playlists%20synchronizer.user.js | |
| // @updateURL https://update.greasyfork.org/scripts/578171/m3u4u%20playlists%20synchronizer.meta.js | |
| // ==/UserScript== | |
| /* jshint esversion: 11 */ | |
| (async function () { | |
| "use strict"; | |
| const BEARER = localStorage.getItem('accessToken'); | |
| const DELAY_MS = 5000; | |
| const BASE = "https://m3u4u.com/api"; | |
| const sleep = ms => new Promise(r => setTimeout(r, ms)); | |
| const m3u4uCookie = () => decodeURIComponent(document.cookie.match(/(?:^|; )M3U4U-XYZ=([^;]*)/)?.[1]); | |
| await sleep(1000); | |
| const headers = { | |
| "Accept": "application/json, text/plain, */*", | |
| "Authorization": `Bearer ${BEARER}`, | |
| "Content-Type": "application/json", | |
| "x-m3u4u-xyz": m3u4uCookie() | |
| }; | |
| console.log(`Reading cookie=${m3u4uCookie()}`); | |
| // 1. Fetch playlist ids | |
| const listResp = await fetch(`${BASE}/playlists/list`, { | |
| method: "POST", headers, | |
| body: JSON.stringify({page: 1, pageSize: 100}), | |
| referrer: "https://www.m3u4u.com/playlists", | |
| credentials: "include", | |
| }); | |
| const listBody = await listResp.json(); | |
| console.log(`Playlists status: ${listResp.status}`); | |
| const ids = listBody.items.map(p => p.id).filter(Number.isFinite); | |
| console.log(`Playlists: ${ids}`); | |
| // 2. For each playlist id : sync + sleep + dropbox | |
| for (const id of ids) { | |
| console.log(`\nProcessing ${id}...`); | |
| const syncResp = await fetch(`${BASE}/playlists/bulk-sync`, { | |
| method: "POST", headers, | |
| body: JSON.stringify({playlistIds: [id], forceRefreshSources: false}) | |
| }); | |
| console.log(` bulk-sync => ${syncResp.status}`); | |
| await sleep(DELAY_MS); | |
| const dropResp = await fetch(`${BASE}/playlists/push-to-dropbox`, { | |
| method: "POST", headers, | |
| body: JSON.stringify({playlistIds: [id]}) | |
| }); | |
| console.log(` push-to-dropbox => ${dropResp.status}`); | |
| } | |
| console.log("\nDone."); | |
| alert('SYNC DONE'); | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment