您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a reply tracker to your profile page
// ==UserScript== // @name Last.fm Reply tracker // @description Adds a reply tracker to your profile page // @namespace [email protected] // @version 17 // // @include http://www.last.fm/home // @include http://www.lastfm.*/home // @include http://www.last.fm/user/* // @include http://www.lastfm.*/user/* // @exclude http://www.last.fm/user/*/* // @exclude http://www.lastfm.*/user/*/* // // @grant GM_getValue // @grant GM_setValue // @grant GM_xmlhttpRequest // ==/UserScript== function GMY_optionExits(key) { var value = GM_getValue(key, "undefined"); return (value != "undefined" && value != ""); } var Thread = function(properties, options) { this.options = options; this.elements = new Object(); this.url = properties.url; var parts = this.url.replace(/^.*\/forum\/(\d+?)\/_\/(\d+?)\/_\/(\d+)$/, "$1,$2,$3").split(","); this.forum_id = parts[0]; this.id = parts[1]; this.last_post_id = parts[2]; this.title = properties.title; this.title_short = this.title.replace(/^.*?\'(.*)\'$/, "$1"); this.user = properties.description.replace(/^.*<a[^>]*>(.*?)<\/a>.*$/, "$1"); this.date = properties.date; this.date_str = this.date.toLocaleString(); this.status = this.getStatus(); this.buildRow().setStyle(this.status); } Thread.prototype.setStatus = function(status) { if(status == "read" || status == "spam") GM_setValue("thread_list", this._readlist(true) + "/" + this._identifier(status == "read" ? 3 : 2)); else if(status == "unread") GM_setValue("thread_list", this._readlist(true)); this.status = status; this.setStyle(status); return this; } Thread.prototype.setStyle = function(status) { var background, opacity, img_tip = "Spam thread", spam_button = "http://cdn.last.fm/flatness/global/icon_delete.2.png"; switch(status) { case "read": background = "url(http://cdn.last.fm/flatness/icons/activity/2/created.png) left center no-repeat"; opacity = 0.4; break; case "unread": background = "url(http://cdn.last.fm/flatness/icons/activity/2/recommended.png) left center no-repeat"; opacity = 1; break; case "spam": background = "url(http://cdn.last.fm/flatness/icons/activity/2/disconnected.png) left center no-repeat"; opacity = 0.4; img_tip = "Don't spam thread"; spam_button = "http://cdn.last.fm/flatness/messageboxes/success.png"; break; } this.elements.row.style.background = background; this.elements.row.style.opacity = opacity; this.elements.spam.alt = img_tip; this.elements.spam.title = img_tip; this.elements.spam.src = spam_button; return this; } Thread.prototype.getStatus = function() { var list = this._readlist(); if(list.match(new RegExp("/" + this._identifier() + "(/|$)"))) return "read"; else if(list.match(new RegExp("/" + this._identifier(2) + "(/|$)"))) return "spam"; else return "unread"; } Thread.prototype._readlist = function(clean) { var list = GM_getValue("thread_list", ""); if(clean) return list.replace(new RegExp("/" + this._identifier(2) + ".*?(/|$)", "g"), "$1"); else return list; } Thread.prototype._identifier = function(depth) { if(!depth) var depth = 3; return new Array(this.forum_id, this.id, this.last_post_id).slice(0, depth).join("%"); } Thread.prototype.buildRow = function() { this.elements.row = document.createElement("li"); this.elements.row.style.background = "none"; this.elements.row.style.paddingLeft = "30px"; this.elements.row.addEventListener("mouseover", (function(klass) { return function() { klass.elements.spam.style.visibility = "visible"; } })(this), false); this.elements.row.addEventListener("mouseout", (function(klass) { return function() { klass.elements.spam.style.visibility = "hidden"; } })(this), false); this.elements.spam = document.createElement("img"); this.elements.spam.style.cssFloat = "right"; this.elements.spam.style.cursor = "pointer"; this.elements.spam.style.visibility = "hidden"; this.elements.spam.addEventListener("click", (function(klass) { return function() { klass.setStatus.apply(klass, [(klass.status == "spam" ? "unread" : "spam")]); } })(this), false); this.elements.row.appendChild(this.elements.spam); this.elements.link = document.createElement("a"); this.elements.link.href = this.url; this.elements.link.innerHTML = this.title_short; this.elements.link.addEventListener("mouseup", (function(klass) { return function() { klass.setStatus.apply(klass, ["read"]); } })(this), false); this.elements.row.appendChild(this.elements.link); this.elements.date = document.createElement("span"); this.elements.date.className = "date"; if(this.options.show_date == "yes") { this.elements.row.appendChild(document.createElement("br")); this.elements.date.innerHTML = this.date_str; } if(this.options.show_user == "yes") this.elements.date.innerHTML += ' from <a href="/user/' + this.user + '">' + this.user + '</a>'; this.elements.row.appendChild(this.elements.date); return this; } var ReplyTracker = function() { this.loadTracker(); } ReplyTracker.prototype.user_options = [ // these two options must be the first in the array! { name: "show_profile", label: "Display on your profile", default: "yes" }, { name: "show_home", label: "Display on your home page", default: "yes" }, // these options are not visible in the "Settings" { name: "@index", label: "Index", default: 0, hidden: true }, { name: "@max_length", label: "Max. rows", default: 5 }, { name: "@update_interval", label: "Update interval (sec)", default: 60 }, { name: "@show_date", label: "Show dates (yes/no)", default: "yes" }, { name: "@show_user", label: "Show usernames (yes/no)", default: "yes" }, { name: "@show_read", label: "Show read threads (yes/no)", default: "yes" }, { name: "@show_spam", label: "Show spammed threads (yes/no)", default: "no" } ]; ReplyTracker.prototype.options = new Object(); ReplyTracker.prototype.elements = new Object(); ReplyTracker.prototype.threads = new Array(); ReplyTracker.prototype.loadTracker = function() { if (!unsafeWindow.LFM || !unsafeWindow.LFM.Session || !unsafeWindow.LFM.Session.userName) return; this.options.username = unsafeWindow.LFM.Session.userName; if(GM_getValue("show_profile", this.user_options[0].default) == "yes" && this.isOwnProfile(this.options.username)) { this.target = "profile"; } else if(GM_getValue("show_home", this.user_options[1].default) && document.location.href.indexOf("/home") != -1) { this.target = "home"; } else { return; } this.loadOptions(); this.updateFeed(); } ReplyTracker.prototype.reloadTracker = function() { delete this.threads; this.threads = new Array(); this.options = new Object(); this.loadTracker(); } ReplyTracker.prototype.loadOptions = function() { for(var i = 0, c = this.user_options.length, name; i < c; i++) { name = this.user_options[i].name; this.options[name.replace(/@/g, "")] = GM_getValue(name.replace(/@/g, this.target+"_"), this.user_options[i].default); } return true; } ReplyTracker.prototype.isOwnProfile = function(username) { var page_username = document.location.href.replace(/^.*?\/user\/(.+?)((#|\/).*|$)/, "$1"); return username === page_username; } ReplyTracker.prototype.showOptions = function() { if(!this.buildOptions()) this.elements.options.style.display = "block"; if(typeof this.elements.feed != "undefined") this.elements.feed.style.display = "none"; this.stopUpdater(); } ReplyTracker.prototype.buildBody = function() { if(typeof this.elements.body != "undefined") return false; var klass = this, first = this.getSibling(); this.elements.header = document.createElement("h2"); this.elements.header.setAttribute("id", "gmreplytracker"); this.elements.header.setAttribute("class", "heading"); this.elements.header.innerHTML = '<span class="h2Wrapper"><span style="float:right;font-weight:normal;font-size:11px;"><a class="mEdit icon" href="#" style="background:url(http://cdn.last.fm/flatness/icons/settings.2.png) left center no-repeat;padding-left: 12px;"><span>Settings</span></a></span><a href="/user/' + this.options.username + '/replytracker" title="">Reply Tracker</a></span>'; this.elements.header.firstChild.firstChild.firstChild.addEventListener("click", function(e) { klass.showOptions.apply(klass); e.preventDefault(); return false; }, false); this.elements.body = document.createElement("div"); this.elements.footer = document.createElement("div"); this.elements.footer.style.textAlign = "right"; var button_down = document.createElement("a"); button_down.href = "#"; button_down.innerHTML = "↓"; button_down.style.padding = "3px 6px"; button_down.style.marginRight = "4px"; button_down.style.backgroundColor = "#eee"; button_down.addEventListener("click", function(e) { e.preventDefault(); var index = klass.options["index"] = parseInt(klass.options["index"]) + 1; GM_setValue(klass.target+"_index", index); klass.updateBody.call(klass); }, false); var button_up = document.createElement("a"); button_up.href = "#"; button_up.innerHTML = "↑"; button_up.style.padding = "3px 6px"; button_up.style.marginRight = "4px"; button_up.style.backgroundColor = "#eee"; button_up.addEventListener("click", function(e) { e.preventDefault(); var index = parseInt(klass.options["index"]) - 1; if(index < 0) return; klass.options["index"] = index; GM_setValue(klass.target+"_index", index); klass.updateBody.call(klass); }, false); this.elements.footer.appendChild(button_down); this.elements.footer.appendChild(button_up); if(this.target == "home") { var body = document.createElement("div"); body.setAttribute("id", "gmreplytracker"); body.setAttribute("class", "home-group"); var header = document.createElement("div"); header.setAttribute("class", "home-group-header"); header.appendChild(this.elements.header); var content = document.createElement("div"); content.setAttribute("class", "home-group-content"); content.appendChild(this.elements.body); content.appendChild(this.elements.footer); body.appendChild(header); body.appendChild(content); first.parentNode.insertBefore(body, first); } else { first.parentNode.insertBefore(this.elements.header, first); first.parentNode.insertBefore(this.elements.body, first); first.parentNode.insertBefore(this.elements.footer, first); } return true; } ReplyTracker.prototype.getSibling = function() { var element; var index = GM_getValue(this.target+"_index", 0); var first = document.getElementById("LastAd_mpu").nextElementSibling; if(this.target == "profile") { while((first.id == "gmreplytracker" || (first.className != "first heading" && first.className != "heading" && first.className != "module" || index-- > 0)) && first.nextElementSibling) first = first.nextElementSibling; } else { while((first.id == "gmreplytracker" || (index-- > 0)) && first.nextElementSibling) first = first.nextElementSibling; } if(index > 0) { this.options["index"] = GM_getValue(this.target+"_index", index) - index; GM_setValue(this.target+"_index", this.options["index"]); } return first; } ReplyTracker.prototype.updateBody = function() { var first = this.getSibling(); if(this.target == "home") { first.parentNode.insertBefore(this.elements.header.parentNode.parentNode, first); } else { first.parentNode.insertBefore(this.elements.header, first); first.parentNode.insertBefore(this.elements.body, first); first.parentNode.insertBefore(this.elements.footer, first); } } ReplyTracker.prototype.buildOptions = function() { if(typeof this.elements.options != "undefined") return false; var klass = this; this.buildBody(); this.elements.options = document.createElement("ul"); for(var i = 0, c = this.user_options.length, li, label, input, name; i < c; i++) { if(this.user_options[i].hidden) continue; name = this.user_options[i].name.replace(/@/g, ""); li = document.createElement("li"); li.style.lineHeight = "25px"; label = document.createElement("label"); label.innerHTML = this.user_options[i].label; label.setAttribute("for", name); input = document.createElement("input"); if(typeof this.options[name] != "undefined") input.setAttribute("value", this.options[name]); with(input) { setAttribute("id", name); setAttribute("name", name); setAttribute("size", 4); with(style) { border = "1px solid #999"; background = "#fff"; color = "#222"; cssFloat = "right"; } } this.user_options[i].element = input; li.appendChild(input); li.appendChild(label); this.elements.options.appendChild(li); } li = document.createElement("li"); li.style.textAlign = "center"; input = document.createElement("input"); input.setAttribute("type", "button"); input.setAttribute("value", "Save Options"); input.addEventListener("click", function() { klass.saveOptions.apply(klass); return false; }, false); li.appendChild(input); this.elements.options.appendChild(li); this.elements.body.appendChild(this.elements.options); return true; } ReplyTracker.prototype.buildFeed = function() { if(typeof this.elements.feed != "undefined") return false; this.buildBody(); this.elements.feed = document.createElement("ul"); this.elements.feed.className = "minifeedSmall"; this.elements.body.appendChild(this.elements.feed); return true; } ReplyTracker.prototype.saveOptions = function() { for(var i = 0, l = this.user_options.length, name, value; i < l; i++) { if(this.user_options[i].hidden) continue; name = this.user_options[i].name; value = this.user_options[i].element.value; this.options[name.replace(/@/, "")] = value; GM_setValue(name.replace(/@/, this.target+"_"), value); } this.elements.options.style.display = "none"; if(typeof this.elements.feed != "undefined") this.elements.feed.style.display = "block"; this.reloadTracker(); } ReplyTracker.prototype._feed = function() { return "http://ws.audioscrobbler.com/1.0/user/" + this.options.username + "/replytracker.rss"; } ReplyTracker.prototype.startUpdater = function() { var klass = this; if(!this.update) this.update = window.setInterval(function() { klass.updateFeed.apply(klass); }, this.options.update_interval * 1000); } ReplyTracker.prototype.stopUpdater = function() { window.clearInterval(this.update); delete this.update; } ReplyTracker.prototype.updateFeed = function() { this.getFeed(this._feed()); } ReplyTracker.prototype.getFeed = function(feed_url) { var klass = this; this.buildFeed(); GM_xmlhttpRequest({ "method": "GET", "url": feed_url, "onload": function(response) { var parser = new DOMParser(); var xmlDoc = parser.parseFromString(response.responseText, "text/xml"); klass.processFeed.call(klass, xmlDoc); }, "onerror": function() { } }); this.startUpdater(); } ReplyTracker.prototype.processFeed = function(xml) { this.elements.feed.innerHTML = ""; var feed = xml.getElementsByTagName("channel").item(0); var replies = feed.getElementsByTagName("item"); var feed_length = this.options.max_length > replies.length ? replies.length : this.options.max_length; for(var i = 0, added = 0; i < replies.length && added < this.options.max_length; i++) added += this.addItem(replies[i]); if(this.threads.length > 0) this.threads[this.threads.length-1].elements.row.className = "last"; } ReplyTracker.prototype.addItem = function(item) { var thread = new Thread({ "title": item.getElementsByTagName("title").item(0).firstChild.data, "description": item.getElementsByTagName("description").item(0).firstChild.data, "url": item.getElementsByTagName("link").item(0).firstChild.data, "date": new Date(item.getElementsByTagName("pubDate").item(0).firstChild.data) }, this.options); if(thread.status == "read" && this.options.show_read == "no" || thread.status == "spam" && this.options.show_spam == "no") return false; this.elements.feed.appendChild(thread.elements.row); this.threads.push(thread); return true; } new ReplyTracker();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址