Chaturbate MULTI-CAM Viewer

Adds a new tab to Chaturbate, and allows you to watch multiple webcams at once

Från och med 2015-12-10. Se den senaste versionen.

  1. // ==UserScript==
  2. // @name Chaturbate MULTI-CAM Viewer
  3. // @namespace https://tesomayn.com
  4. // @description Adds a new tab to Chaturbate, and allows you to watch multiple webcams at once
  5. // @version 1.5.2
  6. // @include http://chaturbate.com/
  7. // @include http://chaturbate.com/#*
  8. // @include http://chaturbate.com/#live*
  9. // @include http://chaturbate.com/*-cams/*
  10. // @include http://*.chaturbate.com/
  11. // @include http://*.chaturbate.com/#*
  12. // @include http://*.chaturbate.com/*-cams/*
  13. // @include https://chaturbate.com/
  14. // @include https://chaturbate.com/#*
  15. // @include https://chaturbate.com/#live*
  16. // @include https://chaturbate.com/*-cams/*
  17. // @include https://*.chaturbate.com/
  18. // @include https://*.chaturbate.com/#*
  19. // @include https://*.chaturbate.com/*-cams/*
  20. // @exclude http://serve.ads.chaturbate.com/*
  21. // @grant GM_getValue
  22. // @grant GM_setValue
  23. // @license MIT
  24. // ==/UserScript==
  25.  
  26. if (window.top != window.self)
  27. return;
  28.  
  29. var gm = function(){
  30. var self = this;
  31. this.STORAGE_KEY_NAME = "chaturbate_girls";
  32. this.LAYOUT_KEY_NAME = "chaturbate_layout";
  33. this.get_layout = function(){
  34. setTimeout(function(){
  35. var temp = 2;
  36. var layout_id = GM_getValue(self.LAYOUT_KEY_NAME);
  37. if (typeof layout_id == "undefined")
  38. layout_id = temp;
  39.  
  40. var adder = function(lid){
  41. viewer.layout_id = lid;
  42. viewer.layout(lid);
  43. }
  44. var script = document.createElement("script");
  45. script.textContent = "(" + adder.toString() + ")("+layout_id+");";
  46. //document.body.appendChild(script);
  47. },0);
  48. }
  49. this.get_girls = function(){
  50. setTimeout(function(){
  51. var temp = '[]';
  52. var sJSON = GM_getValue(self.STORAGE_KEY_NAME);
  53. if (typeof sJSON == "undefined")
  54. sJSON = temp;
  55. var adder = function(savedGirls){
  56. $.each(savedGirls,function(){
  57. viewer.girls.push(new Girl(this));
  58. });
  59. if ( location.hash == "#live" )
  60. viewer.show();
  61. }
  62. var script = document.createElement("script");
  63. script.textContent = "(" + adder.toString() + ")("+sJSON+");";
  64. document.body.appendChild(script);
  65. },0);
  66. }
  67. this.set_girls = function(){
  68. setTimeout(function(){
  69. var data = JSON.stringify(unsafeWindow.jQuery.map(unsafeWindow.viewer.girls,function(o){ return o.username }));
  70. GM_setValue(self.STORAGE_KEY_NAME, data);
  71. },0);
  72. }
  73. this.set_layout = function(){
  74. setTimeout(function(){
  75. GM_setValue(self.LAYOUT_KEY_NAME, unsafeWindow.viewer.layout_id);
  76. },0);
  77. }
  78. return self;
  79. };
  80.  
  81. if (cloneInto){
  82. var insideGM = new gm();
  83. var outsideGM = createObjectIn(unsafeWindow, {defineAs: "gm"});
  84. Object.keys(insideGM).forEach(function(key){
  85. try {
  86. if (typeof insideGM[key] == 'function'){
  87. exportFunction(insideGM[key], outsideGM, {defineAs: key});
  88. }
  89. } catch(e){
  90. }
  91. });
  92. }
  93. else {
  94. unsafeWindow.gm = new gm;
  95. }
  96.  
  97. function main() {
  98. if (typeof jQuery != "undefined"){
  99. jQuery(document).ready(function(){
  100. function getKey(e) {
  101. if(window.event) { // IE
  102. return e.keyCode;
  103. } else if(e.which) { // Netscape/Firefox/Opera
  104. return e.which
  105. }
  106. }
  107. var exports = "getKey,toHtml,websiteHostName,Girl,viewer";
  108. var toHtml = function(data, template){
  109. return template.replace(/#(?:\{|%7B)(.*?)(?:\}|%7D)/g, function($1, $2){
  110. return ($2 in data) ? data[$2] : '';
  111. })
  112. }
  113. var websiteHostName = location.protocol + "//" + location.host + "/";
  114. var Girl = function(name){
  115. var user = name.replace(/\//g,"");
  116. var self = this;
  117. this.href = websiteHostName + user;
  118. this.username = user;
  119. this.src = websiteHostName + "embed/" + self.username + "/?join_overlay=1&room=" + self.username;
  120. }
  121. var viewer = new (function(){
  122. var self = this;
  123.  
  124. var list_template = '<li id="#{username}">'+
  125. ' <img src="http://ccstatic.highwebmedia.com/static/images/ico-01.png" class="remove" onclick="viewer.remove(\'#{username}\',this)">'+
  126. ' <a target="_blank" href="#{href}"><img src="http://ccstatic.highwebmedia.com/static/images/ico-cams.png" class="handle" title="#{username}"></a>'+
  127. ' <iframe src="#{src}"></iframe>'+
  128. ' </li>';
  129. this.layout_id = 2;
  130. this.girls = [];
  131. this.all_girls = [];
  132. this.loaded = false;
  133. this.init = function(){
  134. $('.content').prepend("<div style='width:1500px; margin:3px 32px; padding:3px; border:1px solid #CCC;'> Use the <img src='http://ccstatic.highwebmedia.com/static/images/ico-cams.png' align='absmiddle'> icon to add girls to the 'MULTI-CAM' tab </div>");
  135. var template = '<div id="camGirls" style="visibility:hidden;">'+
  136. '<div id="camControls">'+
  137. 'Username: <input type="text" name="camGirlUsername" id="camGirlUsername" onkeyup="if (getKey(event) == 13) viewer.add()" >'+
  138. '<input type="Button" value="Add" onclick="viewer.add()">'+
  139. '<input type="Button" value="Add Top 12" onclick="viewer.addTop12()">'+
  140. '<input type="Button" value="Remove All" onclick="viewer.removeAll()">'+
  141. '<input type="Button" value="Remove Offlines" onclick="viewer.clearEmptyCams()">'+
  142. '<input type="Button" value="Save" onclick="viewer.save()">'+
  143. '[ Layout: '+
  144. '<input type="Button" value="Semi-Compact" onclick="viewer.layout(1)" id="layout_1">'+
  145. '<input type="Button" value="Compact" onclick="viewer.layout(2)" id="layout_2">'+
  146. '<input type="Button" value="Full" onclick="viewer.layout(3)" id="layout_3">]'+
  147. '</div>'+
  148. '<ul id="girls_list"></ul>'+
  149. '</div>';
  150. $("#main .content").after(template);
  151. var css = '<style type="text/css">' +
  152. '#camGirls ul { margin: 0; padding:0; display:inline-block;}'+
  153. '#camGirls li { margin: 0; padding:0; width:500px; overflow:hidden; display:inline-block; height:456px; }'+
  154. '#camGirls iframe { margin: 0; padding:0; border:none; position:relative; width:1030px; height:528px; }'+
  155. '#camGirls .remove { cursor:pointer; display:inline; top:2px; left:1px; position:relative; float:left; z-index:99; }'+
  156. '#camGirls .handle { cursor:pointer; display:inline; top:2px; left:2px; position:relative; float:left; z-index:99; }'+
  157. '#camControls { border:1px solid #CCC; margin:2px; padding:3px; }'+
  158. '#camControls .active { border:1px solid black; background:#fff; color:#dc5500; }'+
  159. '</style>';
  160. $('body').append(css);
  161. self.getSaved();
  162. self.fixRefresh();
  163. self.updateLayout();
  164. $(".sub-nav li").click(function(){
  165. var page = location.href;
  166. if (page.indexOf('#') >- 1)
  167. page = location.href.split("#")[0];
  168. var target = location.origin + $(this).find('a').attr('href');
  169. if (page != target){
  170. return true;
  171. }
  172. else {
  173. $("#main .content").show();
  174. $("#main #camGirls").css({"visibility":"hidden","height":"0px"});
  175. $(".sub-nav li").removeClass("active");
  176. $(this).addClass("active");
  177. location.hash = "#tab"
  178. return false;
  179. }
  180. });
  181. var li = $("<li>").html("<a href='javascript:viewer.show();'>MULTI-CAM</a>");
  182. $(".sub-nav").append(li);
  183. }
  184. this.fixRefresh = function(){
  185. jQuery( "li.cams" ).live("click", function() {
  186. viewer.add_girl($(this).parents('li').find('a').attr('href'),this);
  187. }).css("cursor","pointer").attr("title","Add girl to MULTI-CAM");
  188. }
  189. this.show = function(){
  190. $(".sub-nav li").removeClass("active");
  191. $(".sub-nav li:last").addClass("active");
  192. $("#main .content").hide();
  193. $("#main #camGirls").css({"visibility":"","height":"auto"});
  194. location.hash = "#live"
  195. if (self.loaded == false){
  196. self.loaded = true;
  197. self.updateLayout();
  198. }
  199. }
  200. this.addTop12 = function(){
  201. $(".list > li:lt(12)").each(function(){
  202. self.add_girl($(this).find('a').attr('href'));
  203. });
  204. self.updateLayout();
  205. }
  206. this.add = function(){
  207. viewer.girls.push(new Girl($('#camGirlUsername').val()));
  208. $("#camGirlUsername").val("");
  209. self.updateLayout()
  210. }
  211. this.add_girl = function(username,obj){
  212. self.girls.push(new Girl(username));
  213. $(obj).html("Girl added to MULTI-CAM");
  214. self.loaded = false;
  215. }
  216. this.remove = function(username,elem){
  217. $.each(self.girls, function(i,o){
  218. if (typeof o != "undefined" && o.username.toLowerCase().indexOf(username.toLowerCase()) >-1 ){
  219. self.girls.splice(i,1);
  220. $(elem).parent().remove();
  221. }
  222. });
  223. self.updateLayout();
  224. }
  225. this.clearEmptyCams = function(){
  226. $("#girls_list iframe").each(function(){
  227. var username = $(this).parents("li")[0].id;
  228. //need to find a window variable that'll indicate when the flash object is there and it's offline
  229. if ($(this.contentWindow.document).find('#movie').length == 0)
  230. self.remove(username);
  231. });
  232. }
  233. this.removeAll = function(){
  234. self.girls = [];
  235. self.updateLayout();
  236. }
  237. this.updateLayout = function(){
  238. if ($("#camGirls:visible").length > 0) {
  239. $.each(self.girls, function(){
  240. if ($("li#"+this.username).length == 0)
  241. $("#girls_list").append(toHtml(this,list_template));
  242. });
  243. $("#girls_list li").each(function(){
  244. var user = this.id;
  245. var isIncluded = $.map(viewer.girls,function(o,i){
  246. if (o.username == user){
  247. return true;
  248. }
  249. }).length > 0;
  250. if (isIncluded == false)
  251. $(this).remove();
  252. });
  253. self.layout(self.layout_id);
  254. }
  255. }
  256. this.getSaved = function(){
  257. gm.get_layout();
  258. gm.get_girls();
  259. }
  260. this.save = function(){
  261. gm.set_girls();
  262. gm.set_layout();
  263. alert("Saved");
  264. }
  265. this.layout = function(id){
  266. self.layout_id = id;
  267. if (id == 1){
  268. var columWidth = 500;
  269. var columnHeight = 470;
  270. var top = 0;
  271. }
  272. else if (id == 2){
  273. var minWidth = 400;
  274. var columns = Math.floor($(window).width() / minWidth);
  275. var columWidth = Math.floor($(window).width() / columns) - 5;
  276. var columnHeight = 375;
  277. var top = -66;
  278. }
  279. else if (id == 3){
  280. var columWidth = 1030;
  281. var columnHeight = 544;
  282. var top = 0;
  283. }
  284. $("#camControls input").removeClass('active')
  285. $("#layout_" + id).addClass('active')
  286. $("#camGirls li").width(columWidth);
  287. $("#camGirls li").height(columnHeight);
  288. $("#camGirls iframe").css({ top: top+"px" });
  289. }
  290. });
  291. $.each(exports.split(","),function(i,o){
  292. window[o] = eval(o);
  293. });
  294. window.viewer.init();
  295. });
  296. }
  297. }
  298.  
  299. var script = document.createElement("script");
  300. script.textContent = "(" + main.toString() + ")();";
  301. document.body.appendChild(script);