/* The MIT License (MIT) Copyright (c) 2013-2014 Zimny Lech Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // DESCRIPTION: CyTube Plus - JavaScript and CSS library for CyTube channels enhancements // CURRENT VERSION: 4.0 // DATE OF MODIFICATION: 2014-04-03 // PROJECT URL: https://github.com/zimny-lech/CyTube-Plus ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // INSTALLATION NOTES: // 0. Choose simple or custom installation (simple one has ready-to-use library with limited functionality). // SIMPLE: use 'https://dl.dropboxusercontent.com/s/6bg3lo29fk1tlmo/main-ready.js' as default URL, go to -> 3. // CUSTOM: go to -> 1. // 1. Configure this library according to your wishes (see configuration sections below). // 2. Save customized library to your file hosting (e.g. Dropbox) or to your own server. // WARNING! You must be able to access .js file directly (browser's URL must contain .js extension, not .php etc.). // WARNING FOR DROPBOX USERS! Always use 'dl.dropboxusercontent.com' URL instead of 'www.dropbox.com' URL. // 3. Enter your JS file location into 'External Javascript' field in 'Channel Settings' modal window. // 4. Enter library CSS file location into 'External CSS' field in 'Channel Settings' modal window. // NOTE: use default 'https://dl.dropboxusercontent.com/s/adzglmczhmymv8h/main.css' URL, or copy it to your location. // 5. Congratulations, your have just installed CyTube Plus! // Problems? Something doesn't work? Go to https://github.com/zimny-lech/CyTube-Plus/wiki/Troubleshooting ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // CONFIGURE BELOW BEFORE INSTALLING IF YOU WANT TO CUSTOMIZE THIS LIBRARY ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* ----- STARTING CONFIGURATION - USER INTERFACE (UI) ----- */ // CONFIGURATION NOTES: // In this section you can immediately enable and disable every option (set '1' to enable, '0' to disable) // Every option marked as [&] requires additional configuration (see other sections below) // IMPORTANT: change 'FuckNoStorage' with unique, random name using basic letters and numbers // FILTERS INSTALLATION: open 'Channel Settings' modal window, go to 'Edit' -> 'Chat Filters', // click 'Prepare fonts filters' button, and import // WARNING! apostrophe sign (') in all text/html values must be prepend with "\" sign (e.g. "don\'t") // If you need more explanations, go to https://github.com/zimny-lech/CyTube-Plus/wiki/Library-settings UI_Favicon = 1; // [&] channel favicon UI_MiniLogo = 1; // [&] small channel logo/avatar in the top navbar UI_ChannelName = 1; // [&] channel custom brand name UI_HeaderDropMenu = 1; // [&] additional header dropdown menu UI_RemoveHomeMenu = 1; // removing 'Layout' menu from the header UI_MOTDAutoLogo = 0; // [&] big channel logo inserted into MOTD UI_RulesBtn = 0; // [&] button displaying channel rules UI_AttentionBar = 0; // [&] imageboard-style attention bar UI_ChannelAnnouncement = 0; // [&] additional custom channel announcement UI_FullTitleBar = 0; // full-width video title bar UI_ProgressBar = 1; // YouTube/Dailymotion progress bar // [ REQUIRE: UI_FullTitleBar enabled ] UI_TitleIcon = 1; // [&] full-width title bar icon // [ REQUIRE: UI_FullTitleBar enabled ] UI_TitleBarDescription = 1; // [&] custom title bar description UI_UserCommands = 1; // [&] additional commands in the chat window UI_UserSpecialSigns = 0; // [&] special signs preceding messages in the chat window for selected users UI_ChatSuffix = 1; // [&] text added to random chat messages UI_IndependentFilters = 1; // [&] additional filters visible only in current chat session UI_JoinText = 1; // [&] chat message after user joining UI_LeaveText = 1; // [&] chat message after user leaving UI_PlayerOptions = 1; // [&] additional player options UI_TransformationBtns = 1; // player transformation buttons UI_FontsBtn = 1; // button displaying box with clickable chat fonts // [ REQUIRE: INSTALLATION (see above) ] UI_UnicodeChars = 1; // [&] additional buttons in the fonts panel with unicode characters // [ REQUIRE: UI_FontsBtn enabled ] UI_EmotesBtn = 1; // button displaying box with clickable chat emotes UI_CommandsBtn = 1; // button displaying modal window with chat commands help UI_ModPanel = 1; // [&] panel with messages and help for moderators UI_DefaultNonTemp = 0; // default adding non-temporary media for registered users UI_ExtendedGetURLs = 1; // extended 'Get URLs' function UI_DisplayModeSel = 1; // selector with player display modes UI_ChannelTheme = 0; // [&] additional default theme channel UI_QuickCommandsBtns = 1; // buttons with '/clear' and '/afk' functions UI_VolumeBtns = 1; // additional volume buttons for YouTube player UI_ChannelDatabase = 1; // [&] box with embed additional media database UI_ChannelGalleries = 1; // [&] box with embed galleries UI_WaifuCorner = 1; // [&] random background image for empty playlist row corner UI_CustomFooter = 0; // [&] custom channel footer UI_FlagCounter = 1; // [&] channel right-sided footer box UI_UserStatistics = 1; // displaying in the footer user visits number and current online time UI_DefaultSynchtube = 0; // default Synchtube layout UI_ExternalScript = 0; // [&] additional external script file UI_ChannelCache = 1; // caching script emotes, additional media database and default gallery FuckNoStorage='fucknostreams'; // local storage name random prefix ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* ----- DETAILED BASIC CONFIGURATION ----- */ // NOTES: // a) in 'HeaderDropMenu_Items' leave empty URL field to create section title // b) values for 'MOTDAutoLogo_Mode': 1 = first logo; 2 = random logo; 3 = logo rotation; 7 = weekdays logos // c) in 'ModPanel_Array' leave empty username field to make a message to all moderators // d) in 'UnicodeChars_Array' use 1 character for an item for the best effect (although it's not the limitation) Favicon_URL = 'http://i.imgur.com/OzAC4l0.png'; MiniLogo_URL = 'http://i.imgur.com/MrZWOgq.png'; ChannelName_Caption = 'FuckNoStreams'; HeaderDropMenu_Title = 'Stuff'; HeaderDropMenu_Items = [ ['Stream Schedule', 'https://docs.google.com/spreadsheets/d/15VDOAKJmp_PIfqnd7scoOUHT4cd9ynLfO_EL2LUCSaQ/edit#gid=162211195'], ['Emotes', 'https://drive.google.com/folderview?id=0ByZgrUw4okC-STQyNUE0UXh5UU0&usp=sharing#grid'], ['tsukari\'s Drive','https://drive.google.com/folderview?id=0B0ET7gwxjjJIMWtVaTdxa1F3Njg&usp=drive_web'],['Calzone IRC', 'http://webchat.6irc.net/?channels=cytube'], ['_North\'s Pixels','http://imgur.com/a/s8s80'] ]; MOTDAutoLogo_Mode = 2; MOTDAutoLogo_Array = [ 'https://dl.dropboxusercontent.com/s/7mrz85gl29eiiks/logo.png', ]; MOTDAutoLogo_Interval = 20; RulesBtn_Caption = ''; RulesBtn_HTML = ''; AttentionBar_URL = ''; ChannelAnnouncement_Title = 'Administration Message'; ChannelAnnouncement_HTML = 'This channel has been created with CyTube Plus 4.0.'; TitleIcon_URL = 'http://i.imgur.com/OzAC4l0.png'; TitleBarDescription_Caption = '>Streaming:'; RandomQuotes = [ 'tsukari is a lolicon.', 'Pyro and Kolt OTP. ', 'Dicks are a marvelous thing.', 'TTGL, not so good.', 'Kill La Kill is best anime.', 'We suffer together.', 'Anyone can love anyone they want.', 'Love knows no age.', 'Girls can\'t love girls', 'league','Your taste is shit!', '30 MinutE NaP', 'StreaminG', ]; AskAnswers = [ '100% for sure.', 'Definitely yes.', 'Yes.', 'Probably.', 'Not any chance.', 'Definitely no.', 'A little chance.', 'No.', '50/50', 'Fairy is tired and will not answer.', 'I refuse to answer.', 'Your question is so stupid you should just leave.', ]; UserSpecialSigns_Array = {'Happy':'','tsukari':'', '_North':'','Kirakira_Tsundere':'', 'Achilles':'','ChinatsuKougou':'', 'Dehry':'','dragonslayer':'', 'FuckNo':'','Kolt':'', 'MassiveFaggot':'','Mikanrin':'', 'Mioo-chi':'','NikolainnDuke':'', 'PingPongYeti':'','Pyro':'', 'Shake_it':'','Shizuruanon':'', 'SilentHonorArk':'','SoupySauce':'', 'SuperSassy':'','Thuglyfegg':'', 'Toradorafag':'','Verty':'', 'zzaz3':'',} ChatSuffix_Text = ':dicks:'; ChatSuffix_Percentage = .01; JoinText_Message = 'joined'; LeaveText_Message = 'left'; PlayerHiding_URL = 'https://googledrive.com/host/0ByZgrUw4okC-STQyNUE0UXh5UU0/stop.jpg'; UnicodeChars_Array = [ '★', '☆', '▲', '▼', '♥', '♪', '♿', '⚒', '♕', '✉', '☏', '♠', '→', '☑', '☒', '✡', '☪', '✝', '☭', '☯', 'Ⓐ', '☕', '♨', '¥', '©', '∞', ]; ModPanel_Array = [ ['', 'Welcome to the moderators panel. You can find here messages, news and help for all channel moderators.'], ['', 'To temporary insert to the playlist any website instead of media files, click "Embed a custom frame" button in the l controls section. Then paste example code to the textarea: <iframe src="URL_of_your_page"></iframe>, and add.'], ]; ChannelGalleries_Array = [ ['Anime pictures', 'http://imgur.com/a/SjwJb/embed'], ['Pixel Characters', 'http://imgur.com/a/s8s80/embed'], ['Waifu Sidebar', 'http://imgur.com/a/XW3EC/embed'] ]; CustomFooter_HTML = ''; FlagCounter_HTML = 'Flag Counter'; ExternalScript_URL = 'https://googledrive.com/host/0ByZgrUw4okC-STQyNUE0UXh5UU0/spin.js'; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* ----- THEMES CONFIGURATION ----- */ ChannelThemeURL = ''; ThemesCSS = [ ['Kobato', 'https://dl.dropboxusercontent.com/s/1r3twlb0loipybw/kobato.css'], ]; TopUserLogo = [ ['anime girl', 'https://dl.dropboxusercontent.com/s/knxd7dpup1u8lm3/azuki.png', 200], ['cosmos', 'https://dl.dropboxusercontent.com/s/v6dx49yqk5e3i2d/cosmos.jpg', 200], ['disco ball', 'https://dl.dropboxusercontent.com/s/ahpfm25pglc8j01/disco.jpg', 162], ['japanese landscape', 'https://dl.dropboxusercontent.com/s/llylt832evxrp6e/japan.jpg', 200], ]; WaifuBG = [ 'http://i.imgur.com/D6cawlR.jpg', 'http://i.imgur.com/gh8EyCU.jpg', 'http://i.imgur.com/6RNicu2.jpg', ]; WaifuCorner = [ 'http://i.imgur.com/mg1d0fJ.png', 'http://i.imgur.com/eNDteKv.png', 'http://i.imgur.com/LL4IyKt.png', 'http://i.imgur.com/FqUONue.png', 'http://i.imgur.com/xujHHTm.png', 'http://i.imgur.com/H2pLa9u.png', 'http://i.imgur.com/Zsufsgw.png', 'http://i.imgur.com/VURSyjI.png', 'http://i.imgur.com/d3rtwZX.png', 'http://i.imgur.com/qGImXXX.png', 'http://i.imgur.com/NK570xv.png', 'http://i.imgur.com/rEqDYct.png', 'http://i.imgur.com/3dJL1uN.png', 'http://i.imgur.com/w0L3Y2K.png', 'http://i.imgur.com/rFqgK5K.png', 'http://i.imgur.com/o5z7yK5.png', 'http://i.imgur.com/7fgfbB1.png', 'http://i.imgur.com/IrMdjbw.png', 'http://i.imgur.com/sMLlG2O.png', 'http://i.imgur.com/hbPVG3z.png', ]; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* ----- INDEPENDENT FILTERS CONFIGURATION ----- */ // NOTES AND DEFAULT FILTERS EXAMPLES: // If you use regular expression, you must put it between // signs // a) [mq]text[/mq] - fast scrolling text // b) [mq0]text[/mq0] - slow scrolling text // c) [imgur]suok1xr.jpg[/imgur] - imgur picture // d) [drop]7mrz85gl29eiiks/logo.png[/drop] - dropbox picture // e) [minus/i5]ig0qs6fvWvgBu.jpg[/minus] - minus.com picture // f) [vi/b]1r8ih4t1.vichan.png[/vi] - vichan imageboard picture IndependentFilters=[ { before:/\[mq\]([^\*]+)\[\/mq\]/, after:'$1' }, { before:/\[mq0\]([^\*]+)\[\/(mq0|mq)\]/, after:'$1' }, { before:/\[imgur\]([^\*]+)\[\/(i|imgur)\]/, after:'' }, { before:/\[drop\]([^\*]+)\[\/(d|drop)\]/, after:'' + '' }, { before:/\[minus\/([^\*]+)\]([^\*]+)\[\/(m|minus)\]/, after:'' + '' }, { before:/\[vi\/([^\*]+)\]([^\*]+)\[\/(v|vi)\]/, after:'' + '' }, ]; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* ----- MEDIA DATABASE CONFIGURATION ----- */ // WARNING! Use ChannelDatabase_URL only if you want to use external database file, it overwrites database below. // If so, copy and configure 'https://raw.github.com/zimny-lech/CyTube-Plus/master/external-db.js' file. ChannelDatabase_URL='https://googledrive.com/host/0ByZgrUw4okC-dnBUOWU1VTJvaXM/externaldb.js'; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* ----- END OF CONFIGURATION, DO NOT CHANGE ANYTHING BELOW ----- */ /* ----- Initial channel options ----- */ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // reload script after unexpected re-connection or script URL change var LOADED = (typeof LOADED==="undefined") ? false : true; LOADED ? location.reload() : ''; /* ----- getting channel options ----- */ if (UI_DefaultSynchtube=="1") { defplayer="left"; defuserlist="right"; defqueue="left"; } else { defplayer="right"; defuserlist="left"; defqueue="right"; } var USERCONFIG = { "player":getOrDefault(FuckNoStorage+"_player", defplayer), "userlist":getOrDefault(FuckNoStorage+"_userlist", defuserlist), "queue":getOrDefault(FuckNoStorage+"_queue", defqueue), "qsize":getOrDefault(FuckNoStorage+"_qsize", "wide"), "main":getOrDefault(FuckNoStorage+"_main", "top"), "motd":getOrDefault(FuckNoStorage+"_motd", "top"), "logo":getOrDefault(FuckNoStorage+"_logo", "no"), "logourl":getOrDefault(FuckNoStorage+"_logourl", ""), "logoht":getOrDefault(FuckNoStorage+"_logoht", "200"), "header":getOrDefault(FuckNoStorage+"_header", "detached"), "css":getOrDefault(FuckNoStorage+"_css", "no"), "csscode":getOrDefault(FuckNoStorage+"_csscode", ""), "modhash":getOrDefault(FuckNoStorage+"_modhash", ""), } var DEFTHEME = (UI_ChannelTheme=="1" && ChannelThemeURL!="") ? ChannelThemeURL : "/css/themes/slate.css"; var USERTHEME = getOrDefault(FuckNoStorage+"_theme", DEFTHEME); var USERVISITS = getOrDefault(FuckNoStorage+"_visits", "0"); var USERONLINE = 0; var PREVTIME = 0; var DEFDESCR = true; var NOPLAYER = false; var COMMAND = false; var CHATSTAT = {"n":0, "l":0, "m":[]}; var EMOTES = false; var FULLPL = false; var FLUID = false; var MINIMIZED = false; var PINNED = false; var HASH = ''; var CHANDB = false; var GALLERY = false; var LASTADD = 0; var ADDEDLINKS = new Array(); var WEBKIT = "webkitRequestAnimationFrame" in window; var BGCHANGE = 0; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* ----- Global functions ----- */ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // toggle elements visibility function toggleDiv(a) { $(a).css('display')=="none" ? $(a).show() : $(a).hide(); } // refresh player function refreshPlayer() { PLAYER.type=""; PLAYER.id=""; socket.emit("playerReady"); } // add link to playlist function addToPlaylist(link,position) { parsed=parseMediaLink(link); parsed["id"]!=null ? socket.emit("queue", {id:parsed["id"], pos:position, type:parsed["type"]}) : ''; } // create modal window function createModal(title) { hidePlayer(); outer=$('
').addClass('modal fade').appendTo($("body")); modal=$('
').addClass('modal-dialog').appendTo(outer); modal=$('
').addClass('modal-content').appendTo(modal); head=$('
').addClass('modal-header').appendTo(modal); $('' + '
    '; for (i=1; i' + ChannelDatabase[i][1] + '' + '
      '; } else { item_nr++; count_nr++; link=ChannelDatabase[i][0]; html+='
    • ' + ''; parsed=parseMediaLink(link); if (parsed["type"]=="yt") { a=parsed["id"]; html+=''; } html+='' + item_nr + '' + ChannelDatabase[i][1] + '
      ' + link + ''; } } html+='


    ' + '' + '
    '; item_count[layer_nr-1]=count_nr; opening[layer_nr-1]=0; $("#db-well").html(html); for(i=1; i<=item_count.length; i++) { $("#la"+i).append(' ['+item_count[i-1]+']'); } CHANDB=true; dbcat = $(".db-cat"); cleardbbtn = $("#cleardb-btn"); dbcat.hide(); for (i in opening) { opening[i]=0; } cleardbbtn.on("click", function() { toggleDiv("#dbwrap"); $("#db-well").html(''); item_nr = 0; CHANDB=false; }); } // toggle database sections function toggleCat(a) { b=a-1; if (opening[b]==0) { dbcat.hide(); for (i in opening) { opening[i]=0; } $("#l"+a).show(); opening[b]=1; } else { $("#l"+a).hide(); opening[b]=0; } } // add database link to playlist function addVideo(link) { parsed=parseMediaLink(link); idx=parsed["id"]; if (idx!=null) { a=(new Date()).getTime(); if (!hasPermission("playlistadd")) { alert('You have no permission to add a link.'); } else if (ADDEDLINKS[idx]!=undefined && a-ADDEDLINKS[idx]<120000) { alert('You have just added this link.'); } else { socket.emit("queue", {id: idx, pos: "end", type: parsed["type"]}); ADDEDLINKS[idx]=a; } } } // create channel gallery function createGallery() { galleryframe = $('