Sendungen auf Ö1 schnell und einfach anhören und herunterladen
当前为
// ==UserScript==
// @name Ö1 – Simple <audio> Stream and Download
// @description Sendungen auf Ö1 schnell und einfach anhören und herunterladen
// @namespace https://xmine127.tk/gm/
// @include *://oe1.orf.at/*
// @include *://loopstream01.apa.at/*#DOWNLOAD=*
// @version 1.0.0
// @grant unsafeWindow
// @run-at document-start
// ==/UserScript==
var $A = function(collection) {
return Array.prototype.slice.call(collection, 0);
};
function create_download_link(attributes) {
var DOMDownloadLink = document.createElement("a");
for(var attribute in attributes) {
if(attributes.hasOwnProperty(attribute)) {
DOMDownloadLink[attribute] = attributes[attribute];
}
}
DOMDownloadLink.className = "userscript-audio-download";
DOMDownloadLink.appendChild(document.createTextNode("Download"));
return DOMDownloadLink;
}
if(window.location.hash.startsWith("#DOWNLOAD=")) {
// Download link iframe page
var downloadAttributes = JSON.parse(decodeURIComponent(window.location.hash.substr(10)));
document.addEventListener("DOMContentLoaded", function()
{
// Inject style information
inject_content();
// Mark this page's content as not-important
document.documentElement.className = "download-proxy";
// Add the (important) download link
document.body.appendChild(create_download_link(downloadAttributes));
}, true);
return;
}
document.addEventListener("DOMContentLoaded", function()
{
// Inject extra page nodes
inject_content();
var konsole_orig = unsafeWindow.konsole;
// Define replacement function for stream window launcher
var konsole = exportFunction(function(url) {
// Determine track ID from URL
var URLQuery = url.split("#")[0].split("?")[1];
var track_id;
if(URLQuery) {
var URLOptions = URLQuery.split("&");
for(var i = 0; i < URLOptions.length; i++) {
var URLOption = URLOptions[i];
if(URLOption.substr(0, 9) == "track_id=") {
track_id = parseInt(URLOption.substr(9));
break;
}
};
}
// Guess which container contained the clicked stream
var DOMStreamContainer = document.querySelector(".has-7tage > a[href='" + url.replace("'", "\\'") + "']");
// Delegate to original handler if the target stream container could not be determined
if(!track_id || !DOMStreamContainer) {
console.log("UserScript: Failed to determine stream container or track ID for URL: " + url);
return konsole_orig(url);
}
var DOMStreamContainer = DOMStreamContainer.parentNode.parentNode;
// Generate title string from stream information
var DOMStreamTitle = DOMStreamContainer.querySelector(".textbox > h3");
var DOMStreamDate = DOMStreamContainer.querySelector(".textbox > .datum");
var title = "";
if(DOMStreamTitle) {
title += DOMStreamTitle.textContent.trim();
if(title.substr(title.length - 1) == "*") {
title = title.substr(0, title.length - 1).trim();
}
}
if(DOMStreamDate) {
title += (title != "") ? " vom " : "";
title += DOMStreamDate.textContent.split("|")[1].trim();
}
// Find or add main container below container with information text
var DOMStreamController = DOMStreamContainer.getElementsByClassName("userscript-audio-controller")[0];
if(!DOMStreamController) {
DOMStreamController = document.createElement("div");
DOMStreamController.className = "userscript-audio-controller";
DOMStreamContainer.appendChild(DOMStreamController);
}
// Show progress spinner in controller area
var DOMLoadingSpinner = document.getElementById("fountainG");
DOMLoadingSpinner.style.display = "block";
DOMStreamController.appendChild(DOMLoadingSpinner);
// Download playlist file for stream
var XHRPlaylist = new XMLHttpRequest();
XHRPlaylist.addEventListener("load", function() {
if(XHRPlaylist.status != 200 || !XHRPlaylist.responseXML) {
var status = XHRPlaylist.status + " " + XHRPlaylist.statusText;
console.log("UserScript: Could not retrieve playlist file: " + status);
return konsole_orig(url);
}
// Create list of audio tracks in stream playlist
var playlist = [];
$A(XHRPlaylist.responseXML.querySelectorAll("playlist > track")).forEach(function(XMLTrack) {
var url = XMLTrack.getAttribute("url");
if(url) {
playlist.push(url);
}
});
// Create <audio> tag (with UI) for episode
var DOMAudio = document.createElement("audio");
DOMAudio.controls = true;
DOMAudio.preload = "auto";
DOMAudio.src = playlist[0];
DOMStreamController.appendChild(DOMAudio);
// Create download link
var downloadAttributes = {
href: playlist[0],
download: title,
target: "_new",
type: "audio/mpeg"
};
if(navigator.product == "Gecko") {
// Create <iframe> that contains download link on <audio> domain (thanks Mozilla...)
var DOMDownloadFrame = document.createElement("iframe");
DOMDownloadFrame.className = "userscript-audio-download";
DOMDownloadFrame.src = "//loopstream01.apa.at/welcome.aspx#DOWNLOAD=" + JSON.stringify(downloadAttributes);
DOMStreamController.appendChild(DOMDownloadFrame);
} else {
// Other browser either support the "download" attribute – or they don't…
// The one's that don't won't support streaming the content and will therefor offer it for download
// regardless... :-)
DOMStreamController.appendChild(create_download_link(downloadAttributes));
}
// Hide progress spinner
DOMLoadingSpinner.style.display = "none";
// Start playback
DOMAudio.play();
});
XHRPlaylist.open("GET", "http://oe1.orf.at/programm/" + track_id + "/playlist", true);
XHRPlaylist.send();
}, unsafeWindow);
// Replace page read-only stream window launcher function
Object.defineProperty(unsafeWindow, "konsole", {
value: konsole
});
});
function inject_content()
{
// Inject extra HTML tags for loading indicator
var DOMLoadingSpinner = document.createElement("div");
DOMLoadingSpinner.id = "fountainG";
DOMLoadingSpinner.style.display = "none";
for(var i = 1; i <= 8; i++) {
var DOMLoadingItem = document.createElement("div");
DOMLoadingItem.id = "fountainG_" + i;
DOMLoadingItem.className = "fountainG";
DOMLoadingSpinner.appendChild(DOMLoadingItem);
}
document.body.appendChild(DOMLoadingSpinner);
// Inject extra page styles for loading indicator
var DOMStylesheet = document.createElement("style");
DOMStylesheet.type = "text/css";
DOMStylesheet.innerHTML = (function () {/*
html.download-proxy,
html.download-proxy > body {
margin: 0 !important;
padding: 0 !important;
}
html.download-proxy > body > * {
display: none !important;
}
html.download-proxy > body > .userscript-audio-download {
display: block !important;
}
.userscript-audio-controller {
display: block;
margin-top: 0.5em;
margin-left: 196px;
}
.userscript-audio-download {
text-indent: -9999px;
display: block;
width: 64px;
height: 32px;
background: transparent url("//oe1.orf.at/static/img/ico-tile.png") repeat scroll -100px -1372px;
}
.overlay-download-liste {
display: none !important;
}
#fountainG{
position:relative;
width:84px;
height:10px;
margin:auto;
}
.fountainG{
position:absolute;
top:0;
background-color:rgb(0,0,0);
width:10px;
height:10px;
animation-name:bounce_fountainG;
-o-animation-name:bounce_fountainG;
-ms-animation-name:bounce_fountainG;
-webkit-animation-name:bounce_fountainG;
-moz-animation-name:bounce_fountainG;
animation-duration:1.5s;
-o-animation-duration:1.5s;
-ms-animation-duration:1.5s;
-webkit-animation-duration:1.5s;
-moz-animation-duration:1.5s;
animation-iteration-count:infinite;
-o-animation-iteration-count:infinite;
-ms-animation-iteration-count:infinite;
-webkit-animation-iteration-count:infinite;
-moz-animation-iteration-count:infinite;
animation-direction:normal;
-o-animation-direction:normal;
-ms-animation-direction:normal;
-webkit-animation-direction:normal;
-moz-animation-direction:normal;
transform:scale(.3);
-o-transform:scale(.3);
-ms-transform:scale(.3);
-webkit-transform:scale(.3);
-moz-transform:scale(.3);
border-radius:7px;
-o-border-radius:7px;
-ms-border-radius:7px;
-webkit-border-radius:7px;
-moz-border-radius:7px;
}
#fountainG_1{
left:0;
animation-delay:0.6s;
-o-animation-delay:0.6s;
-ms-animation-delay:0.6s;
-webkit-animation-delay:0.6s;
-moz-animation-delay:0.6s;
}
#fountainG_2{
left:10px;
animation-delay:0.75s;
-o-animation-delay:0.75s;
-ms-animation-delay:0.75s;
-webkit-animation-delay:0.75s;
-moz-animation-delay:0.75s;
}
#fountainG_3{
left:21px;
animation-delay:0.9s;
-o-animation-delay:0.9s;
-ms-animation-delay:0.9s;
-webkit-animation-delay:0.9s;
-moz-animation-delay:0.9s;
}
#fountainG_4{
left:31px;
animation-delay:1.05s;
-o-animation-delay:1.05s;
-ms-animation-delay:1.05s;
-webkit-animation-delay:1.05s;
-moz-animation-delay:1.05s;
}
#fountainG_5{
left:42px;
animation-delay:1.2s;
-o-animation-delay:1.2s;
-ms-animation-delay:1.2s;
-webkit-animation-delay:1.2s;
-moz-animation-delay:1.2s;
}
#fountainG_6{
left:52px;
animation-delay:1.35s;
-o-animation-delay:1.35s;
-ms-animation-delay:1.35s;
-webkit-animation-delay:1.35s;
-moz-animation-delay:1.35s;
}
#fountainG_7{
left:63px;
animation-delay:1.5s;
-o-animation-delay:1.5s;
-ms-animation-delay:1.5s;
-webkit-animation-delay:1.5s;
-moz-animation-delay:1.5s;
}
#fountainG_8{
left:73px;
animation-delay:1.64s;
-o-animation-delay:1.64s;
-ms-animation-delay:1.64s;
-webkit-animation-delay:1.64s;
-moz-animation-delay:1.64s;
}
@keyframes bounce_fountainG{
0%{
transform:scale(1);
background-color:rgb(0,0,0);
}
100%{
transform:scale(.3);
background-color:rgb(255,255,255);
}
}
@-o-keyframes bounce_fountainG{
0%{
-o-transform:scale(1);
background-color:rgb(0,0,0);
}
100%{
-o-transform:scale(.3);
background-color:rgb(255,255,255);
}
}
@-ms-keyframes bounce_fountainG{
0%{
-ms-transform:scale(1);
background-color:rgb(0,0,0);
}
100%{
-ms-transform:scale(.3);
background-color:rgb(255,255,255);
}
}
@-webkit-keyframes bounce_fountainG{
0%{
-webkit-transform:scale(1);
background-color:rgb(0,0,0);
}
100%{
-webkit-transform:scale(.3);
background-color:rgb(255,255,255);
}
}
@-moz-keyframes bounce_fountainG{
0%{
-moz-transform:scale(1);
background-color:rgb(0,0,0);
}
100%{
-moz-transform:scale(.3);
background-color:rgb(255,255,255);
}
}
*/}).toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1];
document.head.appendChild(DOMStylesheet);
}