The Brown Hats Software Depot: F' Around & Find Out!

Login | Register (Invite Only)

pagetelegram's Profile

Title: Page Telegram of Amfile.org

Description: Brown Hats Collective F' Around and Find Out user of the Interwebs and Project Developer for a Cause Toward Insuring a Future of Liberty without Illusion.

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@=:---#@@@#%@@@*=+#@%====@@@@..:--@#====@-==#@@@+===#@%=-+@... -@@@@*@@@=+@%-*@
@@@.*@-.@@@.:@@==@:=@+ -..*@@@:# @:@=.=. #%.#@@@@ ::..@.%#.@@ %+ %@@% #@@-.@+ #@
@@@.*@+.@@@:.@@.#@%*@*.@.-*@@%@#.@.@=.%..#% *@@@@ %:+:+:@@=@@ #+ %@@+..@@= %: @@
@@@..-.=@@:* %@.%#=+@+..:@@@@@@*.@@@=..:@@@ %@%%% :.@@+-@:=#@ ...@@@:+ @@+ :- @@
@@@.+@@@@@.- =@.#@.-@*.@:=@@@@@+ @@@+:@-:@% @@*=@ @=%#+-@-.#@ @*.%@@.- #@=. + @@
@@@.+@@@@+.@..@:*%.*@*.@%.@@@@%- +@@=:@%.@@.%@:=@ @@=*#:@::@@ *# =@--% -@:- * @@
@@-::#@@%::+::*@-:=%@::.::@@@@+-::@*:.:::@::...%:::::#@*:==@#==@+:*.:=::%:-=::=@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#-.  .-#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*.        .+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@-            :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@:              .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@:      .++:      .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@=     :@@@@@@-     -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@#     =@@@@@@@@+     #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@:    =@@@@@@@@@@+    .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@#    .@@@@@@@@@@@@.    *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@.    %@@@@@@@@@@@@%.    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@%    -@@@@@@@@@@@@@@-    #@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@=    #@@@@@@@@@@@@@@%    -@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@.   .@@@@@@@@@@@@@@@@.   .@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@    -@@@@%##***#%@@@@+    %@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@*    %@#:..       .:+@%    *@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@=    =.               :    -@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@:                          .@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@.                          .@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@.       .=%@@@@@@@+:       .@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@#      .%@@@@@@@@@@@@@-      -@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@#     .*@@@@@@@@@@@@@@@@%:     -@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@%.    .@@@@@@*%@@@@%#@@@@@@=     *@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@.    :@@@@@@@@:-@@*.%@@@@@@@+     %@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@+    :@@@@@@@@@@---.@@@@@@@@@@=    :@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@.    @@@@@@@@@@@.   @@@@@@@@@@@:    #@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@=    #@@@+--#@@@@    #@@@@%#@@@@@.   .@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@.   :@%-     .%@@-  .@@@*.   .+@@=    #@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@#    *+.       .@@@#*@@@=       .#@    -@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@-   .#          =@@-.@@%.         +=   .@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@.   -@.          @@. %@:          #%    %@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@.   #@-          +%  =%          .@@.   *@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@%    %@%          :+  .+          +@@.   =@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@#    @@@:         .:  .-         .@@@:   -@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@*   .@@@%         #   .#         =@@@:   :@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@*   .@@@@=       -@    @-       .@@@@:   :@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@#    @@@@@.     .@@    @@.      %@@@@:   -@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@%    %@@@@@:   :@@@    @@@.   .*@@@@@.   =@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@.   #@@@@@@#+#@@@@    @@@@=.:%@@@@@@.   *@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@.   :@@@@@@-..:*@@    @@#-..:%@@@@@#    %@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@-   .@@@@@:     .@    @.     .@@@@@-   .@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@#    *@@@%       @.  .@       *@@@@    -@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@.   .@@@+       @-  .@.      -@@@=    #@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@+    +@@%.     .@*  :@-     .*@@%.   .@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@.    %@@@-    *@%  #@%.   :%@@@.    %@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@*    .@@@@%=-+@@@. @@@*--#@@@@-    -@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@:    .@@@@@@@@@@*=@@@@@@@@@@:     @@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@.    .%@@@@@@@@@@@@@@@@@@@-    .#@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@%.     +@@@@@@@@@@@@@@@@#.     +@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@%.     .+@@@@@@@@@@@@%:      +@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@%.       -*%@@@@@#=.      .*@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@:                      .%@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@#.                   +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+.              .=@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@=.        .-%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%###%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Repositories

Viewing: plsanyindex.html.txt

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PLS/M3U On Anything Player</title>
    <script src="https://cdn.jsdelivr.net/npm/jsmediatags@latest/dist/jsmediatags.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
    <style>
        body {
            font-family: 'Courier New', Consolas, monospace;
            color: #FFC107;
            background-color: #000000;
            max-width: 600px;
            margin: 20px auto;
        }
        h1, p, span, div {
            font-family: 'Courier New', Consolas, monospace;
            color: #FFC107;
        }
        input, button {
            font-family: 'Courier New', Consolas, monospace;
            color: #FFC107;
            background-color: #000000;
            border: 1px solid #FFC107;
            padding: 5px;
            margin: 5px;
        }
        input {
            width: 100%;
            box-sizing: border-box;
        }
        button:hover {
            background-color: #FFC107;
            color: #000000;
        }
        #controls { margin-top: 10px; }
        #metadata {
            margin-top: 10px;
            padding: 10px;
            border: 1px solid #FFC107;
        }
        #player, #video-player { max-width: 100%; }
        .popup {
            display: none;
            position: fixed;
            top: 20%;
            left: 20%;
            width: 60%;
            max-height: 60%;
            overflow-y: auto;
            background: #000000;
            border: 1px solid #FFC107;
            padding: 10px;
            color: #FFC107;
        }
        .popup ul {
            list-style: none;
            padding: 0;
        }
        .popup li {
            cursor: pointer;
            padding: 5px;
        }
        .popup li:hover {
            background: #FFC107;
            color: #000000;
        }
        .popup button {
            position: sticky;
            top: 0;
            float: right;
        }
    </style>
</head>
<body>
    <h1>PLS/M3U Playlist Player</h1>
    <p>Enter a PLS, M3U, or M3U8 playlist URL (HTTP or HTTPS) or provide it in the URL (e.g., ?pls=https://example.com/playlist.m3u8). Supports audio, video, and live streams. Single-track playlists play automatically.</p>
    <input id="pls-url" type="text" placeholder="Enter PLS/M3U URL">
    <button onclick="loadPlaylist()">Load Playlist</button>
    <button onclick="togglePlaylistWindow()">Show Playlist</button>
    <button onclick="toggleRecentPlaylists()">Show Recent Playlists</button>

    <div id="player-container">
        <audio id="player" controls style="display: none;"></audio>
        <video id="video-player" controls style="display: none;"></video>
    </div>

    <div id="controls">
        <button id="prev">Previous</button>
        <button id="playpause">Play</button>
        <button id="next">Next</button>
        <button onclick="changeSpeed(0.25)">Speed +</button>
        <button onclick="changeSpeed(-0.25)">Speed -</button>
        <span>Speed: <span id="speed">1.00</span>x</span>
    </div>

    <div id="metadata">Metadata will appear here.</div>

    <div id="playlist-window" class="popup">
        <button onclick="togglePlaylistWindow()">Close</button>
        <ul id="playlist-list"></ul>
    </div>

    <div id="recent-playlists" class="popup">
        <button onclick="toggleRecentPlaylists()">Close</button>
        <ul id="recent-playlists-list"></ul>
    </div>

    <script>
        let tracks = [];
        let currentIndex = 0;
        const audioPlayer = document.getElementById('player');
        const videoPlayer = document.getElementById('video-player');
        const playPauseBtn = document.getElementById('playpause');
        const speedSpan = document.getElementById('speed');
        const metadataDiv = document.getElementById('metadata');
        const playlistList = document.getElementById('playlist-list');
        const recentPlaylistsList = document.getElementById('recent-playlists-list');
        const plsInput = document.getElementById('pls-url');
        let currentPlayer = audioPlayer;

        // Check for ?pls= query parameter on page load
        window.onload = () => {
            const params = new URLSearchParams(window.location.search);
            const plsUrl = params.get('pls');
            if (plsUrl) {
                if (plsUrl.startsWith('http://') || plsUrl.startsWith('https://')) {
                    plsInput.value = plsUrl;
                    loadPlaylist();
                } else {
                    alert('Invalid playlist URL in query parameter. Please use http:// or https://');
                }
            }
            fetchRecentPlaylists();
        };

        async function loadPlaylist() {
            const url = plsInput.value;
            if (!url) {
                alert('Please enter a playlist URL or provide it in the URL (?pls=...).');
                return;
            }
            if (!url.startsWith('http://') && !url.startsWith('https://')) {
                alert('URL must start with http:// or https://');
                return;
            }
            try {
                // Save the playlist URL to the server
                await fetch('save_playlist.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ url })
                });
                // Fetch and parse the playlist
                const response = await fetch(url, { mode: 'cors' });
                if (!response.ok) throw new Error(`Failed to fetch playlist: ${response.statusText}`);
                const text = await response.text();
                const extension = url.split('.').pop().toLowerCase();
                tracks = extension === 'pls' ? parsePLS(text) : parseM3U(text);
                if (tracks.length === 0) {
                    alert('No tracks found in playlist.');
                    return;
                }
                // Update browser URL with ?pls=
                history.pushState({}, '', `?pls=${encodeURIComponent(url)}`);
                updatePlaylistWindow();
                // Auto-play if only one track
                if (tracks.length === 1) {
                    playTrack(0);
                } else {
                    document.getElementById('playlist-window').style.display = 'block';
                    playTrack(0);
                }
                fetchRecentPlaylists();
            } catch (error) {
                console.error('Playlist load error:', error);
                alert(`Error loading playlist: ${error.message}. Check if the server allows CORS or is online.`);
            }
        }

        function parsePLS(text) {
            const lines = text.split('\n');
            let numEntries = 0;
            const trackMap = {};
            lines.forEach(line => {
                line = line.trim();
                if (!line || line.startsWith('[')) return;
                const [key, value] = line.split('=').map(part => part.trim());
                if (!key || !value) return;
                if (key === 'NumberOfEntries') {
                    numEntries = parseInt(value, 10);
                    return;
                }
                const match = key.match(/^(File|Title|Length)(\d+)$/);
                if (match) {
                    const [, type, numStr] = match;
                    const num = parseInt(numStr, 10);
                    if (!trackMap[num]) trackMap[num] = {};
                    if (type === 'File') trackMap[num].url = value;
                    else if (type === 'Title') trackMap[num].title = value;
                    else if (type === 'Length') trackMap[num].length = parseInt(value, 10);
                }
            });
            const trackList = [];
            for (let i = 1; i <= numEntries; i++) {
                if (trackMap[i] && trackMap[i].url) {
                    trackList.push({
                        url: trackMap[i].url,
                        title: trackMap[i].title || `Track ${i}`,
                        length: trackMap[i].length || -1
                    });
                }
            }
            return trackList;
        }

        function parseM3U(text) {
            const lines = text.split('\n');
            const trackList = [];
            let currentTrack = {};
            lines.forEach(line => {
                line = line.trim();
                if (!line || line.startsWith('#EXTM3U')) return;
                if (line.startsWith('#EXTINF:')) {
                    const [, duration, title] = line.match(/#EXTINF:(-?\d+),(.*)/) || [, -1, 'Unknown'];
                    currentTrack = { title: title.trim(), length: parseInt(duration, 10) };
                } else if (line.startsWith('http://') || line.startsWith('https://')) {
                    currentTrack.url = line;
                    trackList.push({ ...currentTrack, title: currentTrack.title || 'Unknown', length: currentTrack.length || -1 });
                    currentTrack = {};
                }
            });
            return trackList;
        }

        function updatePlaylistWindow() {
            playlistList.innerHTML = '';
            tracks.forEach((track, index) => {
                const li = document.createElement('li');
                li.textContent = track.title;
                li.onclick = () => playTrack(index);
                playlistList.appendChild(li);
            });
        }

        function togglePlaylistWindow() {
            const win = document.getElementById('playlist-window');
            win.style.display = win.style.display === 'none' ? 'block' : 'none';
            document.getElementById('recent-playlists').style.display = 'none';
        }

        async function fetchRecentPlaylists() {
            try {
                const response = await fetch('save_playlist.php');
                const data = await response.json();
                recentPlaylistsList.innerHTML = '';
                data.forEach(item => {
                    const li = document.createElement('li');
                    li.textContent = `${item.url} (${new Date(item.timestamp).toLocaleString()})`;
                    li.onclick = () => {
                        plsInput.value = item.url;
                        loadPlaylist();
                        toggleRecentPlaylists();
                    };
                    recentPlaylistsList.appendChild(li);
                });
            } catch (error) {
                console.error('Error fetching recent playlists:', error);
            }
        }

        function toggleRecentPlaylists() {
            const win = document.getElementById('recent-playlists');
            win.style.display = win.style.display === 'none' ? 'block' : 'none';
            document.getElementById('playlist-window').style.display = 'none';
        }

        function playTrack(index) {
            if (index < 0 || index >= tracks.length) return;
            currentIndex = index;
            const track = tracks[index];
            const isVideo = track.url.match(/\.(mp4|m3u8)$/i);
            const isHLS = track.url.endsWith('.m3u8');

            audioPlayer.style.display = isVideo ? 'none' : 'block';
            videoPlayer.style.display = isVideo ? 'block' : 'none';
            currentPlayer = isVideo ? videoPlayer : audioPlayer;

            if (isHLS && typeof Hls !== 'undefined' && Hls.isSupported()) {
                const hls = new Hls();
                hls.loadSource(track.url);
                hls.attachMedia(videoPlayer);
                hls.on(Hls.Events.MANIFEST_PARSED, () => {
                    videoPlayer.play().catch(error => {
                        console.error('HLS playback error:', error);
                        alert('Playback error: ' + error.message + '. Ensure the stream is active and CORS is enabled.');
                    });
                });
                hls.on(Hls.Events.ERROR, (event, data) => {
                    console.error('HLS error:', data);
                    alert('HLS stream error: ' + data.type + ' - ' + data.details);
                });
            } else {
                currentPlayer.src = track.url;
                currentPlayer.play().catch(error => {
                    console.error('Playback error:', error);
                    alert('Playback error: ' + error.message + '. Check if the stream is accessible.');
                });
            }

            playPauseBtn.textContent = 'Pause';
            updateMetadata();

            if (!isVideo) {
                try {
                    jsmediatags.read(track.url, {
                        onSuccess: (tag) => {
                            const tags = tag.tags;
                            metadataDiv.innerHTML = `
                                Title: ${tags.title || track.title}<br>
                                Artist: ${tags.artist || 'Unknown'}<br>
                                Album: ${tags.album || 'Unknown'}<br>
                                Length: ${track.length > 0 ? track.length + ' seconds' : 'Unknown'}
                            `;
                        },
                        onError: () => updateMetadata()
                    });
                } catch (e) {
                    updateMetadata();
                }
            } else {
                updateMetadata();
            }
        }

        function updateMetadata() {
            const track = tracks[currentIndex];
            metadataDiv.innerHTML = `
                Title: ${track.title}<br>
                Length: ${track.length > 0 ? track.length + ' seconds' : 'Unknown'}
            `;
        }

        playPauseBtn.addEventListener('click', () => {
            if (currentPlayer.paused) {
                currentPlayer.play();
                playPauseBtn.textContent = 'Pause';
            } else {
                currentPlayer.pause();
                playPauseBtn.textContent = 'Play';
            }
        });

        document.getElementById('next').addEventListener('click', () => {
            playTrack(currentIndex + 1);
        });

        document.getElementById('prev').addEventListener('click', () => {
            playTrack(currentIndex - 1);
        });

        audioPlayer.addEventListener('ended', () => {
            playTrack(currentIndex + 1);
        });

        videoPlayer.addEventListener('ended', () => {
            playTrack(currentIndex + 1);
        });

        function changeSpeed(delta) {
            currentPlayer.playbackRate = Math.max(0.25, currentPlayer.playbackRate + delta);
            speedSpan.textContent = currentPlayer.playbackRate.toFixed(2);
        }
    </script>
</body>
</html>

Language: html