Advertisement
MeKLiN2

3026

Jan 26th, 2024
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 176.19 KB | None | 0 0
  1. /*jshint esversion: 8 */
  2. (function () {
  3. 'use strict';
  4. let StumbleChat = {
  5. Version: "3.0.26",
  6. WebSocket: null,
  7. Room: {},
  8. Self: {},
  9. Userlist: {
  10. Resizable: true,
  11. Resized: false,
  12. list: undefined,
  13. User: new Map(),
  14. SortedUsers: [],
  15. Broadcast: new Map(),
  16. Count: () => document.querySelector("#onlinecount").innerText = StumbleChat.Userlist.User.size,
  17. Profile: (handle) => {
  18. if (StumbleChat.Userlist.User.get(handle).guest == 1) return Message.receive.public(`${(handle == StumbleChat.Self.handle) ? "You are" : StumbleChat.Userlist.User.get(handle).nick + " is"} in the room as a guest.`);
  19. let Profile = new XMLHttpRequest();
  20. Profile.onload = () => {
  21. if (Profile.status == 429) return Message.receive.public(`Please wait to view anymore profiles.`);
  22. try {
  23. let parse = JSON.parse(Profile.responseText);
  24. if (parse.error !== undefined) return;
  25. parse.handle = handle;
  26. Modal.Create(11, parse);
  27. } catch (e) {
  28. return Message.receive.public(`There was a problem loading the profile, try again.`);
  29. }
  30. };
  31. Profile.open("POST", `https://${window.location.hostname}/api/profile`, true);
  32. Profile.setRequestHeader('Content-type', 'application/json;charset=UTF-8');
  33. Profile.setRequestHeader("CSRF-Token", document.getElementsByName('_csrf')[ 0 ].getAttribute("content"));
  34.  
  35. Profile.send(JSON.stringify({ name: StumbleChat.Userlist.User.get(handle).username }));
  36. },
  37. Resize: () => {
  38. if (window.innerWidth > 652) {
  39. if (!StumbleChat.Userlist.Resizable) document.querySelector(".resizeuser").classList.remove("hidden");
  40. StumbleChat.Userlist.Resizable = true;
  41. } else {
  42. if (StumbleChat.Userlist.Resizable) {
  43. document.querySelector(".resizeuser").classList.add("hidden");
  44. document.querySelector("sc-userlist>.resizeuser").classList.remove("left");
  45. document.querySelector("sc-userlist").style = "";
  46. StumbleChat.Userlist.Resized = false;
  47. }
  48. StumbleChat.Userlist.Resizable = false;
  49. }
  50. },
  51. Organize: (handle) => {
  52. StumbleChat.Userlist.SortedUsers = StumbleChat.Userlist.SortedUsers.sort((c, a) => (a.mod > c.mod) ? 1 : (a.mod < c.mod) ? -1 : c.nick.toLowerCase().localeCompare(a.nick.toLowerCase()));
  53. for (let i = 0; i < StumbleChat.Userlist.SortedUsers.length; i++) {
  54. if (StumbleChat.Userlist.User.get(handle).mod > StumbleChat.Userlist.SortedUsers[ i ].mod) return document.querySelector(`#userlist>.list`).insertBefore(document.querySelector(`.bar[user-id="${handle}"]`), document.querySelector(`.bar[user-id="${StumbleChat.Userlist.SortedUsers[ i ].handle}"]`));
  55. if (StumbleChat.Userlist.User.get(handle).mod == StumbleChat.Userlist.SortedUsers[ i ].mod && StumbleChat.Userlist.SortedUsers[ i ].nick.toLowerCase().localeCompare(StumbleChat.Userlist.User.get(handle).nick.toLowerCase()) == 1) return document.querySelector(`#userlist>.list`).insertBefore(document.querySelector(`.bar[user-id="${handle}"]`), document.querySelector(`.bar[user-id="${StumbleChat.Userlist.SortedUsers[ i ].handle}"]`));
  56. }
  57. document.querySelector(`#userlist>.list`).lastChild.parentNode.insertBefore(document.querySelector(`.bar[user-id="${handle}"]`), document.querySelector(`#userlist>.list`).lastChild.nextSibling);
  58. },
  59. Menu: {
  60. Element: null,
  61. State: 0,
  62. Task: null,
  63. Display: (handle) => {
  64. StumbleChat.Userlist.Menu.State = 1;
  65. let menu_items = document.querySelectorAll(".user-menu-item");
  66. document.querySelector(".user-menu-name").innerText = StumbleChat.Userlist.User.get(handle).nick;
  67.  
  68. menu_items[ 0 ].classList[ (StumbleChat.Self.handle != handle) ? "add" : "remove" ]("hidden"); // Nickname
  69. menu_items[ 2 ].classList[ (StumbleChat.Self.handle == handle) ? "add" : "remove" ]("hidden"); // Private Message
  70.  
  71. menu_items[ 3 ].classList.add("hidden"); // hide
  72. menu_items[ 4 ].classList.add("hidden"); // unhide
  73.  
  74. if (StumbleChat.Userlist.User.get(handle).broadcasting.length || StumbleChat.Userlist.Broadcast.has(handle)) {
  75. if (StumbleChat.Self.handle == handle) {
  76. menu_items[ 3 ].classList[ (StumbleChat.Self.Hidden) ? "add" : "remove" ]("hidden"); // Hide
  77. menu_items[ 4 ].classList[ (StumbleChat.Self.Hidden) ? "remove" : "add" ]("hidden"); // Unhide
  78. } else {
  79. menu_items[ 3 ].classList[ (StumbleChat.Chat.Settings.HideList.includes(StumbleChat.Userlist.User.get(handle).username.toUpperCase()) || StumbleChat.Chat.Settings.TempHideList.includes(StumbleChat.Userlist.User.get(handle).username.toUpperCase())) ? "add" : "remove" ]("hidden"); // hide
  80. menu_items[ 4 ].classList[ (StumbleChat.Chat.Settings.HideList.includes(StumbleChat.Userlist.User.get(handle).username.toUpperCase()) || StumbleChat.Chat.Settings.TempHideList.includes(StumbleChat.Userlist.User.get(handle).username.toUpperCase())) ? "remove" : "add" ]("hidden"); // unhide
  81. }
  82. }
  83.  
  84. if (StumbleChat.Self.handle == handle) {
  85. menu_items[ 5 ].classList.add("hidden"); // grant super
  86. menu_items[ 6 ].classList.add("hidden"); // grant moderator
  87. menu_items[ 7 ].classList.add("hidden"); // grant operator
  88. menu_items[ 8 ].classList.add("hidden"); // revoke
  89. menu_items[ 9 ].classList.add("hidden"); // close broadcast
  90. menu_items[ 10 ].classList.add("hidden"); // kick
  91. menu_items[ 11 ].classList.add("hidden"); // ban
  92. menu_items[ 12 ].classList.add("hidden"); // ignore
  93. menu_items[ 13 ].classList.add("hidden"); // unignore
  94. menu_items[ 14 ].classList.add("hidden"); // abuse
  95. } else {
  96. if (StumbleChat.Self.mod >= 2) { // Moderator
  97. menu_items[ 5 ].classList[ (StumbleChat.Userlist.User.get(handle).mod < 4 && StumbleChat.Self.mod >= 4 && StumbleChat.Userlist.User.get(handle).mod != 3 && StumbleChat.Userlist.User.get(handle).guest == false) ? "remove" : "add" ]("hidden"); // grant super
  98. menu_items[ 6 ].classList[ (StumbleChat.Userlist.User.get(handle).mod < 4 && StumbleChat.Self.mod >= 3 && StumbleChat.Self.mod > StumbleChat.Userlist.User.get(handle).mod && StumbleChat.Userlist.User.get(handle).mod != 2 && StumbleChat.Userlist.User.get(handle).guest == false) ? "remove" : "add" ]("hidden"); // grant moderator
  99. menu_items[ 7 ].classList[ (StumbleChat.Userlist.User.get(handle).mod < 4 && StumbleChat.Self.mod >= 2 && StumbleChat.Self.mod > StumbleChat.Userlist.User.get(handle).mod && StumbleChat.Userlist.User.get(handle).mod != 1 && StumbleChat.Userlist.User.get(handle).guest == false) ? "remove" : "add" ]("hidden"); // grant operator
  100. menu_items[ 8 ].classList[ (StumbleChat.Userlist.User.get(handle).mod < 4 && StumbleChat.Self.mod >= 2 && StumbleChat.Self.mod > StumbleChat.Userlist.User.get(handle).mod && StumbleChat.Userlist.User.get(handle).mod > 0 && StumbleChat.Userlist.User.get(handle).guest == false) ? "remove" : "add" ]("hidden"); // revoke
  101.  
  102. menu_items[ 9 ].classList[ (StumbleChat.Self.mod > StumbleChat.Userlist.User.get(handle).mod && StumbleChat.Userlist.Broadcast.has(handle)) ? "remove" : "add" ]("hidden"); // close broadcast
  103. menu_items[ 10 ].classList[ (StumbleChat.Self.mod > StumbleChat.Userlist.User.get(handle).mod) ? "remove" : "add" ]("hidden"); // kick
  104. menu_items[ 11 ].classList[ (StumbleChat.Self.mod > StumbleChat.Userlist.User.get(handle).mod) ? "remove" : "add" ]("hidden"); // ban
  105. } else {
  106. menu_items[ 5 ].classList.add("hidden"); // grant super
  107. menu_items[ 6 ].classList.add("hidden"); // grant moderator
  108. menu_items[ 7 ].classList.add("hidden"); // grant operator
  109. menu_items[ 8 ].classList.add("hidden"); // revoke
  110. menu_items[ 9 ].classList.add("hidden"); // close broadcast
  111. menu_items[ 10 ].classList.add("hidden"); // kick
  112. menu_items[ 11 ].classList.add("hidden"); // ban
  113. }
  114. if (StumbleChat.Self.mod == 5) {
  115. menu_items[ 12 ].classList.add("hidden"); // ignore
  116. menu_items[ 13 ].classList.add("hidden"); // unignore
  117. } else {
  118. menu_items[ 12 ].classList[ (StumbleChat.Chat.Settings.IgnoredList.includes(StumbleChat.Userlist.User.get(handle).username.toUpperCase()) || StumbleChat.Chat.Settings.TempIgnoredList.includes(StumbleChat.Userlist.User.get(handle).username.toUpperCase())) ? "add" : "remove" ]("hidden"); // ignore
  119. menu_items[ 13 ].classList[ (StumbleChat.Chat.Settings.IgnoredList.includes(StumbleChat.Userlist.User.get(handle).username.toUpperCase()) || StumbleChat.Chat.Settings.TempIgnoredList.includes(StumbleChat.Userlist.User.get(handle).username.toUpperCase())) ? "remove" : "add" ]("hidden"); // unignore
  120. }
  121. menu_items[ 14 ].classList.remove("hidden"); // abuse
  122. }
  123.  
  124. StumbleChat.Userlist.Menu.Element.classList.add(`user-menu-active`);
  125. },
  126. Hide: () => {
  127. if (StumbleChat.Userlist.Menu.State !== 0) {
  128. StumbleChat.Userlist.Menu.State = 0;
  129. if (StumbleChat.Userlist.Menu.Element) StumbleChat.Userlist.Menu.Element.classList.remove(`user-menu-active`);
  130. }
  131. StumbleChat.Userlist.Menu.Listen();
  132. },
  133. Position: (e) => {
  134. let clickCoords = StumbleChat.GUI.Pointer.Position(e);
  135. let menuWidth = StumbleChat.Userlist.Menu.Element.offsetWidth + 4;
  136. let menuHeight = StumbleChat.Userlist.Menu.Element.offsetHeight + 4;
  137.  
  138. StumbleChat.Userlist.Menu.Element.style.left = ((window.innerWidth - clickCoords.x) < menuWidth) ? window.innerWidth - menuWidth + "px" : clickCoords.x + "px";
  139. StumbleChat.Userlist.Menu.Element.style.top = (((window.innerHeight - clickCoords.y) < menuHeight)) ? window.innerHeight - menuHeight + "px" : clickCoords.y + "px";
  140. },
  141. Listen: () => {
  142. document.addEventListener("pointerup", (e) => {
  143. StumbleChat.Userlist.Menu.Task = StumbleChat.GUI.Element.Exists(e, "bar");
  144. if (e.target.classList.contains("unreadmessage")) {
  145. StumbleChat.Chat.Scroll(true);
  146. } else if (StumbleChat.Userlist.Menu.Task) {
  147.  
  148. let handle = StumbleChat.Userlist.Menu.Task.getAttribute("user-id");
  149. StumbleChat.Userlist.Menu.Element.setAttribute("user-id", handle);
  150. e.preventDefault();
  151. StumbleChat.Userlist.Menu.Display(handle);
  152. StumbleChat.Userlist.Menu.Position(e);
  153. }
  154. }, {
  155. once: true
  156. });
  157. },
  158. Check: () => {
  159. document.addEventListener("pointerup", (e) => {
  160. let elem = StumbleChat.GUI.Element.Exists(e, `user-menu-link`);
  161. if (elem) {
  162. e.preventDefault();
  163. let handle = StumbleChat.Userlist.Menu.Element.getAttribute("user-id");
  164. if (handle != null && StumbleChat.Userlist.User.has(handle) && elem.getAttribute("data-action") !== null) StumbleChat.Userlist.Menu.Item[ elem.getAttribute("data-action") ](handle);
  165. }
  166. });
  167. },
  168. Item: {
  169. nickname: () => Modal.Create(5),
  170. profile: (handle) => StumbleChat.Userlist.Profile(handle),
  171. close: (handle) => StumbleChat.WebSocket.send(`{"stumble":"close","handle":"${handle}"}`),
  172. kick: (handle) => StumbleChat.WebSocket.send(`{"stumble":"kick","handle":"${handle}"}`),
  173. ban: (handle) => StumbleChat.WebSocket.send(`{"stumble":"ban","handle":"${handle}"}`),
  174. grantsuper: (handle) => StumbleChat.WebSocket.send(`{"stumble":"role","type":"super","handle":"${handle}"}`),
  175. grantmoderator: (handle) => StumbleChat.WebSocket.send(`{"stumble":"role","type":"moderator","handle":"${handle}"}`),
  176. grantoperator: (handle) => StumbleChat.WebSocket.send(`{"stumble":"role","type":"operator","handle":"${handle}"}`),
  177. revoke: (handle) => StumbleChat.WebSocket.send(`{"stumble":"role","type":"revoke","handle":"${handle}"}`),
  178. pvtmsg: (handle) => {
  179. if (StumbleChat.Chat.Selected !== handle) document.querySelector(".unreadmessage").classList.add("hidden");
  180. if (StumbleChat.Userlist.User.has(handle)) {
  181.  
  182. StumbleChat.Chat.Selected = handle;
  183. document.querySelector("#chat-position>#back").classList.add("show");
  184. document.querySelector("#chat-position>#back").innerHTML = `&#8249; ${StumbleChat.Userlist.User.get(handle).nick} (${(StumbleChat.Userlist.User.get(handle).guest == 0) ? StumbleChat.Userlist.User.get(handle).username : "guest"})`;
  185. document.getElementById("chat-content").innerHTML = "";
  186.  
  187. let PM = document.querySelector(".privateMessages");
  188. if (!StumbleChat.Chat.Messages.has(handle)) StumbleChat.Chat.Messages.set(handle, {
  189. username: (StumbleChat.Userlist.User.get(handle).guest == 0) ? StumbleChat.Userlist.User.get(handle).username : "guest",
  190. avatar: StumbleChat.Userlist.User.get(handle).avatar,
  191. nick: StumbleChat.Userlist.User.get(handle).nick,
  192. missedmsg: 0,
  193. message: [],
  194. namebackgroundcolor: StumbleChat.Userlist.User.get(handle).namebackgroundcolor,
  195. backgroundcolor: StumbleChat.Userlist.User.get(handle).backgroundcolor,
  196. messagetextcolor: StumbleChat.Userlist.User.get(handle).messagetextcolor
  197. });
  198.  
  199. if (!PM.querySelector(`[user-id="${handle}"]`)) {
  200. document.querySelector("#userlist>h2:nth-child(2)").classList.remove("hidden");
  201. PM.classList.remove("hidden");
  202. let element = document.createElement('div');
  203. element.setAttribute("class", "list-item");
  204. element.innerHTML = `<span class="private" user-id=${handle}><div class="nickname">${StumbleChat.Userlist.User.get(handle).nick}</div><div class="unreadpm"></div><span class="closepm">x</span></span>`;
  205. document.querySelector(".privateMessages").insertAdjacentHTML("afterBegin", element.outerHTML);
  206. } else {
  207. StumbleChat.Chat.Messages.get(handle).missedmsg = 0;
  208. PM.querySelector(".unreadpm").innerText = StumbleChat.Chat.Messages.get(handle).missedmsg;
  209. PM.querySelector(".unreadpm").classList.remove("show");
  210. }
  211.  
  212. if (document.querySelector(`.selected`)) document.querySelector(`.selected`).classList.remove("selected");
  213.  
  214. PM.querySelector(`[user-id="${handle}"]`).classList.add("selected");
  215. StumbleChat.Chat.Messages.get(handle).message.forEach((value, index) => {
  216. if (index > 0) {
  217. if (value.nick == StumbleChat.Chat.Messages.get(handle).message[ index - 1 ].nick && value.handle == StumbleChat.Chat.Messages.get(handle).message[ index - 1 ].handle) {
  218. let element = document.createElement("div");
  219. element.setAttribute("class", "content");
  220. element.innerHTML = `<span class="hidden-selectable">[${value.time}]</span><span class="timestamp">${value.time}</span><span class="message common" style="color:${value.messagetextcolor}">${value.msg}</span></div>`;
  221. document.querySelector("#chat-content>.message:last-child").appendChild(element);
  222. } else {
  223. createChatItem(value);
  224. }
  225. } else {
  226. createChatItem(value);
  227. }
  228. });
  229. StumbleChat.Chat.Scroll(true);
  230. document.querySelector("#textarea").focus();
  231. }
  232. },
  233. hide: (handle) => {
  234. if (StumbleChat.Self.handle == handle) {
  235. StumbleChat.Self.Hidden = true;
  236. Message.receive.public(`You are now hidden.`);
  237. } else {
  238. if (!StumbleChat.Userlist.User.get(handle).guest) {
  239. StumbleChat.Chat.Settings.HideList.push(StumbleChat.Userlist.User.get(handle).username.toUpperCase());
  240. localStorage.setItem('HideList', JSON.stringify(StumbleChat.Chat.Settings.HideList));
  241. } else {
  242. StumbleChat.Chat.Settings.TempHideList.push(StumbleChat.Userlist.User.get(handle).username.toUpperCase());
  243. }
  244. Message.receive.public(`${StumbleChat.Userlist.User.get(handle).nick} has been hidden, you will not see and hear them anymore.`);
  245. }
  246. StumbleChat.Videos.View(handle);
  247. },
  248. unhide: (handle) => {
  249. if (StumbleChat.Self.handle == handle) {
  250. StumbleChat.Self.Hidden = false;
  251. Message.receive.public(`You are now unhidden.`);
  252. } else {
  253.  
  254. if (!StumbleChat.Userlist.User.get(handle).guest) {
  255. for (let i = 0; i < StumbleChat.Chat.Settings.HideList.length; i++) {
  256. if (StumbleChat.Chat.Settings.HideList[ i ] == StumbleChat.Userlist.User.get(handle).username.toUpperCase()) StumbleChat.Chat.Settings.HideList.splice(i, 1);
  257. }
  258. localStorage.setItem('HideList', JSON.stringify(StumbleChat.Chat.Settings.HideList));
  259. } else {
  260. for (let i = 0; i < StumbleChat.Chat.Settings.TempHideList.length; i++) {
  261. if (StumbleChat.Chat.Settings.TempHideList[ i ] == StumbleChat.Userlist.User.get(handle).username.toUpperCase()) StumbleChat.Chat.Settings.TempHideList.splice(i, 1);
  262. }
  263. }
  264. Message.receive.public(`${StumbleChat.Userlist.User.get(handle).nick} is unhidden, you can see and hear them again.`);
  265. }
  266. StumbleChat.Videos.View(handle);
  267. },
  268. ignore: (handle) => {
  269. if (!StumbleChat.Userlist.User.has(handle)) return;
  270. document.querySelector(`.bar[user-id="${handle}"] .nickname`).innerHTML = `<s>${StumbleChat.Userlist.User.get(handle).nick}</s>`;
  271. if (!StumbleChat.Userlist.User.get(handle).guest) {
  272. StumbleChat.Chat.Settings.IgnoredList.push(StumbleChat.Userlist.User.get(handle).username.toUpperCase());
  273. localStorage.setItem('IgnoredList', JSON.stringify(StumbleChat.Chat.Settings.IgnoredList));
  274. } else {
  275. StumbleChat.Chat.Settings.TempIgnoredList.push(StumbleChat.Userlist.User.get(handle).username.toUpperCase());
  276. }
  277. Message.receive.public(`User has been ignored, you will not see their messages.`);
  278. },
  279. unignore: (handle) => {
  280.  
  281. document.querySelector(`.bar[user-id="${handle}"] .nickname`).innerHTML = `${StumbleChat.Userlist.User.get(handle).nick}`;
  282. if (!StumbleChat.Userlist.User.get(handle).guest) {
  283. for (let i = 0; i < StumbleChat.Chat.Settings.IgnoredList.length; i++) {
  284. if (StumbleChat.Chat.Settings.IgnoredList[ i ] == StumbleChat.Userlist.User.get(handle).username.toUpperCase()) StumbleChat.Chat.Settings.IgnoredList.splice(i, 1);
  285. }
  286. localStorage.setItem('IgnoredList', JSON.stringify(StumbleChat.Chat.Settings.IgnoredList));
  287. } else {
  288. for (let i = 0; i < StumbleChat.Chat.Settings.IgnoredList.length; i++) {
  289. if (StumbleChat.Chat.Settings.TempIgnoredList[ i ] == StumbleChat.Userlist.User.get(handle).username.toUpperCase()) StumbleChat.Chat.Settings.TempIgnoredList.splice(i, 1);
  290. }
  291. }
  292. Message.receive.public(`User has been unignored, you will now see their messages.`);
  293. },
  294. abuse: (handle) => {
  295. Message.receive.public(`User has been reported to admins!`);
  296. StumbleChat.WebSocket.send(`{"stumble":"abuse","handle":"${handle}"}`);
  297. },
  298. }
  299. }
  300. },
  301. Chat: {
  302. Resizable: true,
  303. Resized: false,
  304. Password: undefined,
  305. Scroll: (opt) => (StumbleChat.Chat.Settings.Scroll || opt !== undefined) ? document.getElementById("chat").scrollTop = document.getElementById("chat").scrollHeight : 0,
  306. Selected: 0,
  307. Resize: () => {
  308. if (window.innerWidth > 652) {
  309. if (!StumbleChat.Chat.Resizable) document.querySelector(".resizechat").classList.remove("hidden");
  310. StumbleChat.Chat.Resizable = true;
  311. } else {
  312. if (StumbleChat.Chat.Resizable) {
  313. document.querySelector(".resizechat").classList.add("hidden");
  314. document.querySelector("sc-chat>.resizechat").classList.remove("right");
  315. document.querySelector("sc-chat").style = "";
  316. StumbleChat.Chat.Resized = false;
  317. }
  318. StumbleChat.Chat.Resizable = false;
  319. }
  320. },
  321. Background: {
  322. Set: () => {
  323. let Image = document.getElementById("modal-text-input").value;
  324. let BGColor = document.getElementById("modal-bgcolor-input").value;
  325. if (Image == "") {
  326. if ((BGColor.match(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/) != null || BGColor.match(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/) != null)) {
  327. if (StumbleChat.Chat.Settings.background != BGColor) {
  328. StumbleChat.Chat.Settings.background = BGColor;
  329. StumbleChat.Chat.Settings.backgroundUrl = "";
  330. localStorage.setItem("background", StumbleChat.Chat.Settings.background);
  331. localStorage.setItem("backgroundUrl", "");
  332. StumbleChat.Chat.Background.Load();
  333. Modal.Destroy();
  334. }
  335. }
  336. } else {
  337. if (Image.match(/([a-z\-_0-9\/\:\.]*\.(jpg|jpeg|png|gif))/i) != null) {
  338. StumbleChat.Chat.Settings.backgroundUrl = Image;
  339. StumbleChat.Chat.Settings.background = `url("${Image}") 0% 0% / cover no-repeat rgb(1, 1, 1)`;
  340. localStorage.setItem("background", StumbleChat.Chat.Settings.background);
  341. localStorage.setItem("backgroundUrl", Image);
  342. StumbleChat.Chat.Background.Load();
  343.  
  344. Modal.Destroy();
  345. }
  346. }
  347. },
  348. Load: () => document.querySelector("body").style.background = StumbleChat.Chat.Settings.background,
  349. Reset: () => {
  350. StumbleChat.Chat.Settings.background = "#111111";
  351. StumbleChat.Chat.Settings.backgroundUrl = "";
  352. localStorage.setItem("background", StumbleChat.Chat.Settings.background);
  353. localStorage.setItem("backgroundUrl", "");
  354.  
  355. StumbleChat.Chat.Background.Load();
  356. Modal.Destroy();
  357. }
  358. },
  359. Color: {
  360. Set: () => {
  361. let Color = document.getElementById("modal-color-input").value;
  362. if (Color.match(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/) !== null || Color.match(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/) !== null) {
  363. StumbleChat.Chat.Settings.chatcolor = Color;
  364. localStorage.setItem("chatcolor", StumbleChat.Chat.Settings.chatcolor);
  365. StumbleChat.Chat.Color.Load();
  366. Modal.Destroy();
  367. }
  368. },
  369. Load: () => {
  370. document.querySelector("#chat-wrapper").style.background = StumbleChat.Chat.Settings.chatcolor + "94";
  371. document.querySelector("#userlist").style.background = StumbleChat.Chat.Settings.chatcolor + "94";
  372. },
  373. Reset: () => {
  374. StumbleChat.Chat.Settings.chatcolor = "#000000";
  375. localStorage.setItem("chatcolor", StumbleChat.Chat.Settings.chatcolor);
  376. StumbleChat.Chat.Color.Load();
  377. Modal.Destroy();
  378. }
  379. },
  380. setTopic: () => {
  381. let topic = document.getElementById("room-topic").value;
  382. if (topic === undefined) return;
  383. if (typeof topic !== "string") return;
  384. if (topic.length > 200) return Message.receive.public(`Room topic is considerably large, keep it 8-60 characters.`);
  385. StumbleChat.WebSocket.send(JSON.stringify({ "stumble": "room", "type": "topic", "topic": topic }));
  386. Modal.Destroy();
  387. },
  388. setBroadcastPassword: (clear) => {
  389. let password = document.getElementById("broadcast-password").value;
  390. if (!clear) {
  391. if (typeof password != "string") return;
  392. if (password.length > 60) return Message.receive.public(`Broadcasting password is considerably large, keep it 8-60 characters.`);
  393. if (password.length < 8) return Message.receive.public(`Broadcasting password is considerably small, keep it 8-60 characters.`);
  394. } else if (!StumbleChat.Room.broadcast_password) return Message.receive.public(`There's currently no broadcasting password set.`);
  395. StumbleChat.WebSocket.send(JSON.stringify({ "stumble": "room", "type": "broadcast_password", "password": (clear) ? null : password }));
  396. Modal.Destroy();
  397. },
  398. Settings: {
  399. Scroll: true,
  400. FeaturedResize: false,
  401. isMobile: false,
  402. SaveEnabled: false,
  403. YouTubeEnabled: true,
  404. TwitchEnabled: true,
  405. SoundCloudEnabled: true,
  406. WSHHEnabled: true,
  407. DailyMotionEnabled: true,
  408. SoundmeterEnabled: true,
  409. PrivateMessageEnabled: true,
  410. SoundsEnabled: true,
  411. IgnoredList: [],
  412. HideList: [],
  413. TempIgnoredList: [],
  414. TempHideList: [],
  415. ChatSide: true,
  416. RoomVolume: 0,
  417. LinksEnabled: true,
  418. ImgurEnabled: true,
  419. audiodevice: "NONE",
  420. videodevice: "NONE",
  421. YouTubeStartTime: 0,
  422. YouTubeQueueID: undefined,
  423. YouTubePausedTime: new Date(),
  424. YouTubeClicked: true,
  425. LargeEmbeddedVideos: false,
  426. LargeFont: false,
  427. BroadcastVolume: new Map(),
  428. TempBroadcastVolume: new Map()
  429. },
  430. Status: {
  431. Resets: 0,
  432. MissedMsg: 0,
  433. Timelastpost: new Date(),
  434. Kicked: false,
  435. AdjustingQueue: false,
  436. ModalOpened: -1,
  437. ModalState: 2,
  438. LoadedEventListenersInit: false,
  439. LoadedEventListenersJoined: false,
  440. Playing: {
  441. SoundCloud: false,
  442. WSSH: false,
  443. DailyMotion: false,
  444. Twitch: false,
  445. YouTube: false
  446. }
  447. },
  448. Sounds: {
  449. public_message: new Audio('../sounds/message.mp3'),
  450. private_message: new Audio('../sounds/private_message.mp3')
  451. },
  452. Messages: new Map(),
  453. },
  454. Videos: {
  455. Resolutions: [
  456. [ 352, 240 ],
  457. [ 480, 360 ],
  458. [ 852, 480 ],
  459. [ 1280, 720 ],
  460. [ 1920, 1080 ],
  461. [ 4096, 2160 ]
  462. ],
  463. Device: null,
  464. AudioPaused: true,
  465. OpenMic: false,
  466. AudioAwaitingPause: false,
  467. Password: undefined,
  468. Soundmeter: (handle, stream) => {
  469. if (StumbleChat.Chat.Settings.SoundmeterEnabled) {
  470. StumbleChat.Userlist.Broadcast.get(handle).spectrum = window.hark(stream, {});
  471. let parent = StumbleChat.Userlist.Broadcast.get(handle).element.parentElement;
  472. parent.classList.add("visualizer");
  473. parent.setAttribute("volume", 0);
  474. StumbleChat.Userlist.Broadcast.get(handle).spectrum.on('volume_change', (volume) => {
  475. if (volume <= -100) parent.setAttribute("volume", 0);
  476. if (volume >= -100) parent.setAttribute("volume", 1);
  477. if (volume >= -95) parent.setAttribute("volume", 2);
  478. if (volume >= -90) parent.setAttribute("volume", 3);
  479. if (volume >= -80) parent.setAttribute("volume", 4);
  480. if (volume >= -70) parent.setAttribute("volume", 5);
  481. if (volume >= -60) parent.setAttribute("volume", 6);
  482. if (volume >= -50) parent.setAttribute("volume", 7);
  483. if (volume >= -40) parent.setAttribute("volume", 8);
  484. if (volume >= -30) parent.setAttribute("volume", 9);
  485. if (volume >= -15) parent.setAttribute("volume", 10);
  486. });
  487. }
  488. },
  489. View: (handle) => {
  490. if (StumbleChat.Self.handle == handle) {
  491. if (StumbleChat.Userlist.Broadcast.get(handle).video !== null) {
  492. document.querySelector(`.bar[user-id="${handle}"] .status>div:nth-child(1)`).classList[ StumbleChat.Self.Hidden ? "remove" : "add" ]("video_badge");
  493. document.querySelector(`.bar[user-id="${handle}"] .status>div:nth-child(1)`).classList[ StumbleChat.Self.Hidden ? "add" : "remove" ]("video_badge_hide");
  494.  
  495. StumbleChat.Userlist.Broadcast.get(handle).video.track.enabled = !StumbleChat.Self.Hidden;
  496. }
  497. } else {
  498. if (StumbleChat.Userlist.User.get(handle).broadcasting.length > 0) {
  499. if (StumbleChat.Chat.Settings.HideList.includes(StumbleChat.Userlist.User.get(handle).username.toUpperCase()) || StumbleChat.Chat.Settings.TempHideList.includes(StumbleChat.Userlist.User.get(handle).username.toUpperCase())) {
  500. clearTimeout(StumbleChat.Userlist.User.get(handle).disconnecttimer);
  501.  
  502. if (StumbleChat.Userlist.Broadcast.has(handle)) {
  503. if (StumbleChat.Userlist.Broadcast.get(handle).spectrum !== undefined) StumbleChat.Userlist.Broadcast.get(handle).spectrum.stop();
  504. StumbleChat.Userlist.Broadcast.get(handle).stream.getTracks().forEach((track) => track.stop());
  505. StumbleChat.Userlist.Broadcast.get(handle).transport.close();
  506. StumbleChat.WebSocket.send(`{"stumble":"subscribe","type":"unsubscribe","handle":"${handle}"}`);
  507. }
  508.  
  509. removeBroadcastElement(handle);
  510.  
  511. document.querySelector(`.bar[user-id="${handle}"] .status>div:nth-child(2)`).classList.remove("audio_badge");
  512. document.querySelector(`.bar[user-id="${handle}"] .status>div:nth-child(2)`).classList.add("audio_badge_hide");
  513.  
  514. document.querySelector(`.bar[user-id="${handle}"] .status>div:nth-child(1)`).classList.remove("video_badge");
  515. document.querySelector(`.bar[user-id="${handle}"] .status>div:nth-child(1)`).classList.add("video_badge_hide");
  516.  
  517. StumbleChat.Videos.Update();
  518. } else {
  519. document.querySelector(`.bar[user-id="${handle}"] .status>div:nth-child(2)`).classList.add("audio_badge");
  520. document.querySelector(`.bar[user-id="${handle}"] .status>div:nth-child(2)`).classList.remove("audio_badge_hide");
  521.  
  522. document.querySelector(`.bar[user-id="${handle}"] .status>div:nth-child(1)`).classList.add("video_badge");
  523. document.querySelector(`.bar[user-id="${handle}"] .status>div:nth-child(1)`).classList.remove("video_badge_hide");
  524.  
  525. StumbleChat.Userlist.User.get(handle).broadcasting.forEach((value) => StumbleChat.WebSocket.send(JSON.stringify({ "stumble": "subscribe", "type": "request", "kind": value, "handle": handle })));
  526. }
  527. }
  528. }
  529. },
  530. Update: () => {
  531. let videos = document.querySelector("#videos");
  532. let videosItems = videos.querySelectorAll(".videos-items");
  533. let d = {
  534. featured: videos.querySelectorAll("#embeddedvideos > .js-video:not(.hidden)"),
  535. regular: videos.querySelectorAll("#regularvideos > .js-video:not(.hidden)")
  536. };
  537. if (!d.featured.length) videos.querySelector("#embeddedvideos").classList.add("hidden");
  538. if (!d.regular.length) videos.querySelector("#regularvideos").classList.add("hidden");
  539. videos.className = (d.featured.length && d.regular.length) ? (videos.clientWidth / videos.clientHeight > 1 / 0.75 ? "row" : "column") : "";
  540. videosItems.forEach((element, index) => {
  541. if ("object" == typeof videosItems[ index ]) {
  542. let wrapper = videosItems[ index ];
  543. let childs = videos.querySelectorAll(".videos-items:nth-child(" + (1 * index + 1) + ") > .js-video:not(.hidden)");
  544. if (childs.length) {
  545. wrapper.classList.remove("hidden");
  546. StumbleChat.Videos.Resize({ wrapper: wrapper, height: wrapper.clientHeight, width: wrapper.clientWidth, childs: childs });
  547. }
  548. }
  549. });
  550. },
  551. Resize: (a) => {
  552. let c = a.childs.length;
  553. let e = 100;
  554. let f = 100;
  555. let d = 0;
  556. let g = 0;
  557. for (; c;) {
  558. let d = Math.floor(a.height / c);
  559. let h = Math.floor(d / 0.75);
  560. if (h > a.width) {
  561. h = a.width;
  562. d = Math.floor(0.75 * h);
  563. }
  564. let i = Math.floor(a.width / h);
  565. for (; i * c < a.childs.length || d * c > a.height;) {
  566. i++;
  567. h = Math.floor(a.width / i);
  568. d = Math.floor(0.75 * h);
  569. }
  570. let j = d * h;
  571. let k = a.height * a.width;
  572. let l = Math.floor(1e4 * ((k - j * a.childs.length) / k)) / 100;
  573. if (0 < l && e >= l) {
  574. if (1 < c && a.childs.length % i) {
  575. let d = i;
  576. for (; d;) {
  577. if (Math.ceil(a.childs.length / d) > c) {
  578. d++;
  579. break;
  580. }
  581. d--;
  582. }
  583. g = d < i && d ? Math.floor((a.width - d * h) / 2) : 0;
  584. } else {
  585. g = 0;
  586. }
  587. e = l;
  588. f = Math.floor(100 * (100 * (h / (a.width - 2 * g)))) / 100;
  589. }
  590. c--;
  591. }
  592. for (let c in a.wrapper.style.padding = "0 " + g + "px", a.childs) {
  593. if ("object" == typeof a.childs[ c ] && (a.childs[ c ].style.width = f + "%")) {
  594. let e = a.childs[ c ].clientHeight;
  595. let g = a.childs[ c ].clientWidth;
  596. a.childs[ c ].style.width = (100 === f && a.height - d > e) ? f + "%" : Math.floor(100 * (e * g / (e + d) / (g / f))) / 100 + "%";
  597. }
  598. }
  599. },
  600. Menu: {
  601. Element: null,
  602. State: 0,
  603. Task: null,
  604. Display: (handle) => {
  605. if (!StumbleChat.Userlist.User.has(handle)) return;
  606. StumbleChat.Videos.Menu.State = 1;
  607. let menu_items = document.querySelectorAll(".video-menu-item");
  608. let SavedVolume;
  609. if (!StumbleChat.Userlist.User.get(document.querySelector("#video-menu").getAttribute("user-id")).guest) {
  610. SavedVolume = StumbleChat.Chat.Settings.BroadcastVolume[ StumbleChat.Userlist.User.get(document.querySelector("#video-menu").getAttribute("user-id")).username.toUpperCase() ];
  611. } else {
  612. SavedVolume = StumbleChat.Chat.Settings.TempBroadcastVolume[ StumbleChat.Userlist.User.get(document.querySelector("#video-menu").getAttribute("user-id")).username.toUpperCase() ];
  613. }
  614.  
  615. document.querySelector(".video-menu-name").innerText = StumbleChat.Userlist.User.get(handle).nick;
  616. document.querySelector("#video-volume").addEventListener("pointerup", (e) => StumbleChat.Videos.Menu.Item.volume(document.querySelector("#video-menu").getAttribute("user-id"), e.target.value), {
  617. once: true
  618. });
  619. document.querySelector("#video-volume").value = (SavedVolume != undefined) ? SavedVolume : 100;
  620.  
  621. // Hide Volume Meter if it's ourselves
  622. if (StumbleChat.Self.handle == handle) {
  623. menu_items[ 0 ].classList.add("hidden"); // Volume
  624. menu_items[ 2 ].classList.add("hidden"); // Private Message
  625. menu_items[ 3 ].classList[ (StumbleChat.Self.Hidden) ? "add" : "remove" ]("hidden"); // Hide
  626. menu_items[ 4 ].classList[ (StumbleChat.Self.Hidden) ? "remove" : "add" ]("hidden"); // Unhide
  627. menu_items[ 8 ].classList.add("hidden"); // Fullscreen
  628. menu_items[ 9 ].classList.add("hidden"); // PiP
  629. } else {
  630. menu_items[ 0 ].classList.remove("hidden"); // Volume
  631. menu_items[ 2 ].classList.remove("hidden"); // Private Message
  632. menu_items[ 3 ].classList[ (StumbleChat.Chat.Settings.HideList.includes(StumbleChat.Userlist.User.get(handle).username.toUpperCase()) || StumbleChat.Chat.Settings.TempHideList.includes(StumbleChat.Userlist.User.get(handle).username.toUpperCase())) ? "add" : "remove" ]("hidden"); // Hide
  633. menu_items[ 4 ].classList[ (StumbleChat.Chat.Settings.HideList.includes(StumbleChat.Userlist.User.get(handle).username.toUpperCase()) || StumbleChat.Chat.Settings.TempHideList.includes(StumbleChat.Userlist.User.get(handle).username.toUpperCase())) ? "remove" : "add" ]("hidden"); // Unhide
  634. menu_items[ 8 ].classList.remove("hidden"); // Fullscreen
  635. menu_items[ 9 ].classList.remove("hidden"); // PiP
  636. }
  637. // KICK/BAN CLOSE
  638. if (StumbleChat.Self.mod >= 2) {
  639. menu_items[ 5 ].classList[ (StumbleChat.Self.mod > StumbleChat.Userlist.User.get(handle).mod) ? "remove" : "add" ]("hidden"); // Kick
  640. menu_items[ 6 ].classList[ (StumbleChat.Self.mod > StumbleChat.Userlist.User.get(handle).mod) ? "remove" : "add" ]("hidden"); // Ban
  641. menu_items[ 7 ].classList[ (StumbleChat.Self.mod > StumbleChat.Userlist.User.get(handle).mod) ? "remove" : "add" ]("hidden"); // Close Broadcast
  642. } else {
  643. menu_items[ 5 ].classList.add("hidden"); // Kick
  644. menu_items[ 6 ].classList.add("hidden"); // Ban
  645. menu_items[ 7 ].classList.add("hidden"); // close Broadcast
  646. }
  647.  
  648. StumbleChat.Videos.Menu.Element.classList.add(`video-menu-active`);
  649. },
  650. Hide: () => {
  651. if (StumbleChat.Videos.Menu.State !== 0) {
  652. StumbleChat.Videos.Menu.State = 0;
  653. if (StumbleChat.Videos.Menu.Element) StumbleChat.Videos.Menu.Element.classList.remove(`video-menu-active`);
  654. }
  655. document.querySelector("#video-volume").removeEventListener("pointerup", (e) => StumbleChat.Videos.Menu.Item.volume(document.querySelector("#video-menu").getAttribute("user-id"), e.target.value), {
  656. once: true
  657. });
  658.  
  659. StumbleChat.Videos.Menu.Listen();
  660. },
  661. Position: (e) => {
  662. let clickCoords = StumbleChat.GUI.Pointer.Position(e);
  663. let menuWidth = StumbleChat.Videos.Menu.Element.offsetWidth + 4;
  664. let menuHeight = StumbleChat.Videos.Menu.Element.offsetHeight + 4;
  665.  
  666. StumbleChat.Videos.Menu.Element.style.left = ((window.innerWidth - clickCoords.x) < menuWidth) ? window.innerWidth - menuWidth + "px" : clickCoords.x + "px";
  667. StumbleChat.Videos.Menu.Element.style.top = (((window.innerHeight - clickCoords.y) < menuHeight)) ? window.innerHeight - menuHeight + "px" : clickCoords.y + "px";
  668. },
  669. Listen: () => {
  670. document.addEventListener("pointerup", (e) => {
  671. e.preventDefault();
  672. StumbleChat.Videos.Menu.Task = StumbleChat.GUI.Element.Exists(e, "video-wrapper");
  673. if (StumbleChat.Videos.Menu.Task) {
  674. let handle = StumbleChat.Videos.Menu.Task.firstElementChild.getAttribute("video-id");
  675. if (handle !== null) {
  676. document.querySelector("#video-menu").setAttribute("user-id", handle);
  677. StumbleChat.Videos.Menu.Display(handle);
  678. StumbleChat.Videos.Menu.Position(e);
  679. }
  680. }
  681. }, {
  682. once: true
  683. });
  684. },
  685. Check: () => {
  686. document.addEventListener("pointerup", (e) => {
  687. let elem = StumbleChat.GUI.Element.Exists(e, `video-menu-link`);
  688. if (elem) {
  689. e.preventDefault();
  690. let handle = document.querySelector("#video-menu").getAttribute("user-id");
  691. if (handle != null && StumbleChat.Userlist.User.has(handle) && elem.getAttribute("data-action") != null) StumbleChat.Videos.Menu.Item[ elem.getAttribute("data-action") ](handle);
  692. }
  693. });
  694. },
  695. Item: {
  696. volume: (handle, level) => {
  697. if (StumbleChat.Self.handle !== handle && level !== undefined) {
  698. if (StumbleChat.Userlist.Broadcast.has(handle)) {
  699. if (!StumbleChat.Userlist.User.get(handle).guest) {
  700. StumbleChat.Chat.Settings.BroadcastVolume[ StumbleChat.Userlist.User.get(handle).username.toUpperCase() ] = level;
  701. localStorage.setItem('BroadcastVolume', JSON.stringify(StumbleChat.Chat.Settings.BroadcastVolume));
  702. } else {
  703. StumbleChat.Chat.Settings.TempBroadcastVolume[ StumbleChat.Userlist.User.get(handle).username.toUpperCase() ] = level;
  704. }
  705.  
  706. StumbleChat.Userlist.Broadcast.get(handle).volume = level;
  707. StumbleChat.Userlist.Broadcast.get(handle).element.volume = (level / 100) * (StumbleChat.Chat.Settings.RoomVolume / 100);
  708. }
  709. }
  710. },
  711. profile: (handle) => StumbleChat.Userlist.Profile(handle),
  712. fullscreen: (handle) => {
  713. let elem = document.querySelector(`[video-id="${handle}"]`);
  714. if (elem.requestFullscreen) {
  715. elem.requestFullscreen();
  716. } else if (elem.mozRequestFullScreen) {
  717. elem.mozRequestFullScreen();
  718. } else if (elem.webkitRequestFullscreen) {
  719. elem.webkitRequestFullscreen();
  720. } else if (elem.msRequestFullscreen) {
  721. elem.msRequestFullscreen();
  722. }
  723. },
  724. pip: (handle) => {
  725. if (handle !== StumbleChat.Self.handle) {
  726. if (document.pictureInPictureElement) {
  727. document.exitPictureInPicture();
  728. } else {
  729. if (document.pictureInPictureEnabled) document.querySelector(`[video-id="${handle}"]`).requestPictureInPicture();
  730. }
  731. }
  732. },
  733. close: (handle) => StumbleChat.WebSocket.send(JSON.stringify({
  734. "stumble": "close",
  735. "handle": handle
  736. })),
  737. kick: (handle) => StumbleChat.WebSocket.send(JSON.stringify({
  738. "stumble": "kick",
  739. "handle": handle
  740. })),
  741. ban: (handle) => StumbleChat.WebSocket.send(JSON.stringify({
  742. "stumble": "ban",
  743. "handle": handle
  744. })),
  745. pvtmsg: (handle) => {
  746. if (StumbleChat.Chat.Selected !== handle) document.querySelector(".unreadmessage").classList.add("hidden");
  747. if (StumbleChat.Userlist.User.has(handle)) {
  748. StumbleChat.Chat.Selected = handle;
  749. document.querySelector("#chat-position>#back").classList.add("show");
  750. document.querySelector("#chat-position>#back").innerHTML = `&#8249; ${StumbleChat.Userlist.User.get(handle).nick} (${(StumbleChat.Userlist.User.get(handle).guest == 0) ? StumbleChat.Userlist.User.get(handle).username : "guest"})`;
  751. document.getElementById("chat-content").innerHTML = "";
  752.  
  753. let PM = document.querySelector(".privateMessages");
  754. if (!StumbleChat.Chat.Messages.has(handle)) StumbleChat.Chat.Messages.set(handle, {
  755. username: (StumbleChat.Userlist.User.get(handle).guest == 0) ? StumbleChat.Userlist.User.get(handle).username : "guest",
  756. avatar: StumbleChat.Userlist.User.get(handle).avatar,
  757. nick: StumbleChat.Userlist.User.get(handle).nick,
  758. missedmsg: 0,
  759. message: [],
  760. namebackgroundcolor: StumbleChat.Userlist.User.get(handle).namebackgroundcolor,
  761. backgroundcolor: StumbleChat.Userlist.User.get(handle).backgroundcolor,
  762. messagetextcolor: StumbleChat.Userlist.User.get(handle).messagetextcolor
  763. });
  764.  
  765. if (!PM.querySelector(`[user-id="${handle}"]`)) {
  766. document.querySelector("#userlist>h2:nth-child(2)").classList.remove("hidden");
  767. PM.classList.remove("hidden");
  768. let element = document.createElement('div');
  769. element.setAttribute("class", "list-item");
  770. element.innerHTML = `<span class="private" user-id=${handle}><div class="nickname">${StumbleChat.Userlist.User.get(handle).nick}</div><div class="unreadpm"></div><span class="closepm">x</span></span>`;
  771. document.querySelector(".privateMessages").insertAdjacentHTML("afterBegin", element.outerHTML);
  772. } else {
  773. StumbleChat.Chat.Messages.get(handle).missedmsg = 0;
  774. PM.querySelector(".unreadpm").innerText = StumbleChat.Chat.Messages.get(handle).missedmsg;
  775. PM.querySelector(".unreadpm").classList.remove("show");
  776. }
  777.  
  778. if (document.querySelector(`.selected`)) document.querySelector(`.selected`).classList.remove("selected");
  779.  
  780. PM.querySelector(`[user-id="${handle}"]`).classList.add("selected");
  781. StumbleChat.Chat.Messages.get(handle).message.forEach((value, index) => {
  782. if (index > 0) {
  783. if (value.nick == StumbleChat.Chat.Messages.get(handle).message[ index - 1 ].nick && StumbleChat.Chat.Messages.get(handle).message[ index - 1 ].handle == value.handle) {
  784. let element = document.createElement("div");
  785. element.setAttribute("class", "content");
  786. element.innerHTML = `<span class="hidden-selectable">[${value.time}]</span><span class="timestamp">${value.time}</span><span class="message common" style="color:${value.messagetextcolor}">${value.msg}</span></div>`;
  787. document.querySelector("#chat-content>.message:last-child").appendChild(element);
  788. } else {
  789. createChatItem(value);
  790. }
  791. } else {
  792. createChatItem(value);
  793. }
  794. });
  795. StumbleChat.Chat.Scroll(true);
  796. document.querySelector("#textarea").focus();
  797. }
  798. },
  799. hide: (handle) => {
  800. if (!StumbleChat.Userlist.User.has(handle)) return;
  801. if (StumbleChat.Self.handle === handle) {
  802. StumbleChat.Self.Hidden = true;
  803. Message.receive.public(`You are now hidden.`);
  804. } else {
  805.  
  806.  
  807. if (!StumbleChat.Userlist.User.get(handle).guest) {
  808. StumbleChat.Chat.Settings.HideList.push(StumbleChat.Userlist.User.get(handle).username.toUpperCase());
  809. localStorage.setItem('HideList', JSON.stringify(StumbleChat.Chat.Settings.HideList));
  810. } else {
  811. StumbleChat.Chat.Settings.TempHideList.push(StumbleChat.Userlist.User.get(handle).username.toUpperCase());
  812. }
  813. Message.receive.public(`${StumbleChat.Userlist.User.get(handle).nick} has been hidden.`);
  814. }
  815. StumbleChat.Videos.View(handle);
  816. },
  817. unhide: (handle) => {
  818. if (StumbleChat.Self.handle === handle) {
  819. StumbleChat.Self.Hidden = false;
  820. Message.receive.public(`You are now unhidden.`);
  821. } else {
  822.  
  823. if (!StumbleChat.Userlist.User.get(handle).guest) {
  824. for (let i = 0; i < StumbleChat.Chat.Settings.HideList.length; i++) {
  825. if (StumbleChat.Chat.Settings.HideList[ i ] == StumbleChat.Userlist.User.get(handle).username.toUpperCase()) StumbleChat.Chat.Settings.HideList.splice(i, 1);
  826. }
  827. localStorage.setItem('HideList', JSON.stringify(StumbleChat.Chat.Settings.HideList));
  828. } else {
  829. for (let i = 0; i < StumbleChat.Chat.Settings.TempHideList.length; i++) {
  830. if (StumbleChat.Chat.Settings.TempHideList[ i ] == StumbleChat.Userlist.User.get(handle).username.toUpperCase()) StumbleChat.Chat.Settings.TempHideList.splice(i, 1);
  831. }
  832. }
  833. Message.receive.public(`${StumbleChat.Userlist.User.get(handle).nick} is unhidden.`);
  834. }
  835. StumbleChat.Videos.View(handle);
  836. }
  837. }
  838. }
  839. },
  840. GUI: {
  841. Pointer: {
  842. Position: (e) => {
  843. let posx = 0;
  844. let posy = 0;
  845.  
  846. if (!e) e = window.event;
  847.  
  848. if (e.pageX || e.pageY) {
  849. posx = e.pageX;
  850. posy = e.pageY;
  851. } else if (e.clientX || e.clientY) {
  852. posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
  853. posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
  854. }
  855.  
  856. return {
  857. x: posx,
  858. y: posy
  859. };
  860. }
  861. },
  862. Element: {
  863. Exists: (e, className) => {
  864. let el = e.srcElement || e.target;
  865.  
  866. if (el.classList.contains(className)) {
  867. return el;
  868. } else {
  869. while (el == el.parentNode) {
  870. if (el.classList && el.classList.contains(className)) return el;
  871. }
  872. }
  873. return false;
  874. }
  875. }
  876. }
  877. };
  878. let ModType = [ "", "Operator", "Mod", "Super", "Owner", "Admin" ];
  879. let ModColor = [ "", " red", " green", " blue", " gold", " black" ];
  880.  
  881. let CheckCompatibility = {
  882. Storage: () => {
  883. let storage;
  884. try {
  885. storage = window.localStorage;
  886. let x = '__storage_test__';
  887. storage.setItem(x, x);
  888. storage.removeItem(x);
  889. return true;
  890. } catch (e) {
  891. return e instanceof window.DOMException && (e.code === 22 || e.code === 1014 || e.name === 'QuotaExceededError' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') && (storage && storage.length !== 0);
  892. }
  893. },
  894. Device: () => {
  895. const handlerName = window.stumblechatClient.detectDevice();
  896. if (handlerName) {
  897. console.log(`Device: ${handlerName}`);
  898. } else {
  899. console.warn("There's currently no support for this browser.");
  900. return false;
  901. }
  902.  
  903. StumbleChat.Videos.Device = null;
  904. try {
  905. StumbleChat.Videos.Device = new window.stumblechatClient.Device();
  906. } catch (error) {
  907. if (error.name === 'UnsupportedError') console.warn("There's currently no support for this browser.");
  908. return false;
  909. }
  910. StumbleChat.Videos.Device.load({
  911. routerRtpCapabilities: {
  912. codecs: [
  913. { "kind": "audio", "mimeType": "audio/opus", "clockRate": 48000, "channels": 2, "rtcpFeedback": [ { "type": "transport-cc", "parameter": "" } ], "parameters": {}, "preferredPayloadType": 100 },
  914. { "kind": "video", "mimeType": "video/VP8", "clockRate": 90000, "rtcpFeedback": [ { "type": "nack", "parameter": "" }, { "type": "nack", "parameter": "pli" }, { "type": "ccm", "parameter": "fir" }, { "type": "goog-remb", "parameter": "" }, { "type": "transport-cc", "parameter": "" } ], "parameters": { "x-google-start-bitrate": 1000 }, "preferredPayloadType": 101 },
  915. ],
  916. headerExtensions: [
  917. { "kind": "audio", "uri": "urn:ietf:params:rtp-hdrext:sdes:mid", "preferredId": 1, "preferredEncrypt": false, "direction": "sendrecv" },
  918. { "kind": "video", "uri": "urn:ietf:params:rtp-hdrext:sdes:mid", "preferredId": 1, "preferredEncrypt": false, "direction": "sendrecv" },
  919. { "kind": "video", "uri": "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id", "preferredId": 2, "preferredEncrypt": false, "direction": "recvonly" },
  920. { "kind": "video", "uri": "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id", "preferredId": 3, "preferredEncrypt": false, "direction": "recvonly" },
  921. { "kind": "audio", "uri": "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time", "preferredId": 4, "preferredEncrypt": false, "direction": "sendrecv" },
  922. { "kind": "video", "uri": "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time", "preferredId": 4, "preferredEncrypt": false, "direction": "sendrecv" },
  923. { "kind": "audio", "uri": "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01", "preferredId": 5, "preferredEncrypt": false, "direction": "recvonly" },
  924. { "kind": "video", "uri": "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01", "preferredId": 5, "preferredEncrypt": false, "direction": "sendrecv" },
  925. { "kind": "video", "uri": "http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07", "preferredId": 6, "preferredEncrypt": false, "direction": "sendrecv" },
  926. { "kind": "video", "uri": "urn:ietf:params:rtp-hdrext:framemarking", "preferredId": 7, "preferredEncrypt": false, "direction": "sendrecv" },
  927. { "kind": "audio", "uri": "urn:ietf:params:rtp-hdrext:ssrc-audio-level", "preferredId": 10, "preferredEncrypt": false, "direction": "sendrecv" },
  928. { "kind": "video", "uri": "urn:3gpp:video-orientation", "preferredId": 11, "preferredEncrypt": false, "direction": "sendrecv" },
  929. { "kind": "video", "uri": "urn:ietf:params:rtp-hdrext:toffset", "preferredId": 12, "preferredEncrypt": false, "direction": "sendrecv" }
  930. ]
  931. }
  932. });
  933. return true;
  934. },
  935. WebSocket: () => "WebSocket" in window,
  936. MouseSupport: (eventName) => {
  937. let el = document.createElement('div');
  938. eventName = 'on' + eventName;
  939. let isSupported = (eventName in el);
  940. if (!isSupported) {
  941. el.setAttribute(eventName, 'return;');
  942. isSupported = typeof el[ eventName ] == 'function';
  943. }
  944. el = null;
  945. return isSupported;
  946. }
  947. };
  948.  
  949. let SubscribeQueue = [];
  950.  
  951. let ServerResponse = {
  952. joined: (rcv) => {
  953. StumbleChat.Room = rcv.room;
  954. document.querySelector(`.topic`).innerText = rcv.room.topic || "NO TOPIC";
  955. StumbleChat.Self = rcv.self;
  956. document.getElementById("textarea").disabled = false;
  957.  
  958. if (StumbleChat.Self.guest == 1) document.getElementById("user-settings").classList.add("hidden");
  959.  
  960. Message.receive.public(`Client Version: ${StumbleChat.Version}`);
  961. Message.receive.public(`Type /help for in chat commands.`);
  962.  
  963. if (StumbleChat.Self.mod >= 2) document.getElementById("banlist").classList.remove("hidden");
  964. if (StumbleChat.Self.mod >= 3) document.getElementById("room-settings").classList.remove("hidden");
  965. if (StumbleChat.Self.mod >= 1) {
  966. document.getElementById("media").parentElement.classList.remove("hidden");
  967. document.getElementById("youtube-close-embed").classList.remove("hidden");
  968. document.getElementById("twitch-close-embed").classList.remove("hidden");
  969. document.getElementById("soundcloud-close-embed").classList.remove("hidden");
  970. document.getElementById("dailymotion-close-embed").classList.remove("hidden");
  971. document.getElementById("worldstarhiphop-close-embed").classList.remove("hidden");
  972. }
  973. if (!StumbleChat.Chat.Status.LoadedEventListenersJoined) {
  974. StumbleChat.Chat.Status.LoadedEventListenersJoined = true;
  975. document.getElementById("banlist").addEventListener("pointerup", (event) => StumbleChat.WebSocket.send(`{"stumble":"banlist"}`), {
  976. passive: true
  977. });
  978. document.getElementById("user-options").addEventListener("pointerup", (event) => {
  979. switch (event.target.id) {
  980. case "youtube":
  981. setTimeout(() => StumbleChat.WebSocket.send(`{"stumble": "youtube","type": "playlist"}`), 500);
  982. break;
  983. case "twitch":
  984. Modal.Create(12);
  985. break;
  986. case "soundcloud":
  987. Modal.Create(17);
  988. break;
  989. case "dailymotion":
  990. Modal.Create(18);
  991. break;
  992. case "worldstarhiphop":
  993. Modal.Create(16);
  994. break;
  995. case "client-settings":
  996. Modal.Create(10);
  997. break;
  998. case "theme-settings":
  999. Modal.Create(14);
  1000. break;
  1001. case "room-settings":
  1002. Modal.Create(19);
  1003. break;
  1004. default:
  1005. break;
  1006. }
  1007. }, {
  1008. passive: true
  1009. });
  1010. }
  1011. if (!StumbleChat.Chat.Settings.isMobile) document.querySelector("#media-screen").classList.remove("hidden");
  1012. document.getElementById('media-broadcast').classList.remove('hidden');
  1013. document.getElementById('media-settings').classList.remove('hidden');
  1014. document.getElementById('media-loading').classList.add('hidden');
  1015. document.getElementById('media-ptt').classList.add('hidden');
  1016. document.getElementById('media-openmic').classList.add('hidden');
  1017. document.getElementById('media-stop').classList.add('hidden');
  1018. // Userlist
  1019. rcv.userlist = rcv.userlist.sort((c, a) => (a.mod > c.mod) ? 1 : (a.mod < c.mod) ? -1 : c.nick.toLowerCase().localeCompare(a.nick.toLowerCase()));
  1020. StumbleChat.Userlist.SortedUsers = rcv.userlist;
  1021. rcv.userlist.forEach((user, index) => {
  1022. StumbleChat.Userlist.User.set(user.handle, user);
  1023. StumbleChat.Userlist.User.get(user.handle).disconnecttimer = undefined;
  1024. StumbleChat.Userlist.User.get(user.handle).broadcasting = [];
  1025. if (user.avatar == 1) {
  1026. StumbleChat.Userlist.User.get(user.handle).avatar = `/profile/${user.username.toLowerCase()}/cached/small_avatar.jpg`;
  1027. if (StumbleChat.Self.handle == user.handle) StumbleChat.Self.avatar = `/profile/${user.username.toLowerCase()}/cached/small_avatar.jpg`;
  1028. StumbleChat.Userlist.list.insertAdjacentHTML("beforeend", `<li class="bar" user-id="${user.handle}"><img src="${StumbleChat.Userlist.User.get(user.handle).avatar}" class="bar-item"><div class="bar-item"><span class="nickname">${((StumbleChat.Chat.Settings.IgnoredList.includes(user.username.toUpperCase()) || StumbleChat.Chat.Settings.TempIgnoredList.includes(user.username.toUpperCase())) ? `<s>${user.nick}</s>` : user.nick)}</span><span class="username">${(user.guest) ? `guest` : user.username}</span></div><div class="user-status"><div class="role${ModColor[ user.mod ]}">${ModType[ user.mod ]}</div><div class="status"><div class="hidden"></div><div class="hidden"></div></div></div></li>`);
  1029. } else {
  1030. StumbleChat.Userlist.User.get(user.handle).avatar = undefined;
  1031. if (StumbleChat.Self.handle == user.handle) StumbleChat.Self.avatar = undefined;
  1032. StumbleChat.Userlist.list.insertAdjacentHTML("beforeend", `<li class="bar" user-id="${user.handle}"><div class="bar-item no-image"></div><div class="bar-item"><span class="nickname">${((StumbleChat.Chat.Settings.IgnoredList.includes(user.username.toUpperCase()) || StumbleChat.Chat.Settings.TempIgnoredList.includes(user.username.toUpperCase())) ? `<s>${user.nick}</s>` : user.nick)}</span><span class="username">${(user.guest) ? `guest` : user.username}</span></div><div class="user-status"><div class="role${ModColor[ user.mod ]}">${ModType[ user.mod ]}</div><div class="status"><div class="hidden"></div><div class="hidden"></div></div></div></li>`);
  1033. }
  1034. StumbleChat.Userlist.Count();
  1035. });
  1036. // Broadcasts
  1037. ServerResponse.producers({ producers: rcv.broadcasts });
  1038. // Embeds
  1039. if (rcv.youtube != undefined) ServerResponse.youtube({ type: "play", id: rcv.youtube.id, duration: rcv.youtube.duration, queueid: rcv.youtube.queueid, time: rcv.youtube.time + Math.round((new Date() - new Date(rcv.youtube.started)) / 1000), title: rcv.youtube.title });
  1040. if (rcv.wshh.url != undefined) ServerResponse.wshh({ type: "play", url: rcv.wshh.url, embed: rcv.wshh.embed, title: rcv.wshh.title, thumbnail: rcv.wshh.thumbnail });
  1041. if (rcv.twitch.name != undefined) ServerResponse.twitch({ type: "play", name: rcv.twitch.name });
  1042. if (rcv.dailymotion.url != undefined) ServerResponse.dailymotion({ type: "play", url: rcv.dailymotion.url, embed: rcv.dailymotion.embed, title: rcv.dailymotion.title, thumbnail: rcv.dailymotion.thumbnail });
  1043. if (rcv.soundcloud.url != undefined) ServerResponse.soundcloud({ type: "play", url: rcv.soundcloud.url, embed: rcv.soundcloud.embed, title: rcv.soundcloud.title });
  1044. },
  1045. join: (rcv) => {
  1046. StumbleChat.Userlist.User.set(rcv.handle, {
  1047. handle: rcv.handle,
  1048. namebackgroundcolor: rcv.namebackgroundcolor,
  1049. messagetextcolor: rcv.messagetextcolor,
  1050. backgroundcolor: rcv.backgroundcolor,
  1051. avatar: rcv.avatar,
  1052. username: rcv.username,
  1053. guest: rcv.guest,
  1054. nick: rcv.nick,
  1055. mod: rcv.mod,
  1056. disconnecttimer: undefined,
  1057. broadcasting: []
  1058. });
  1059.  
  1060. Message.receive.public(`${rcv.nick} (${(rcv.guest) ? `guest` : rcv.username}:${rcv.handle}) has joined.`);
  1061.  
  1062. StumbleChat.Userlist.SortedUsers.push(StumbleChat.Userlist.User.get(rcv.handle));
  1063. StumbleChat.Userlist.SortedUsers = StumbleChat.Userlist.SortedUsers.sort((c, a) => (a.mod > c.mod) ? 1 : (a.mod < c.mod) ? -1 : c.nick.toLowerCase().localeCompare(a.nick.toLowerCase()));
  1064. let first;
  1065. let beforeUser;
  1066. for (let i = 0; i < StumbleChat.Userlist.SortedUsers.length; i++) {
  1067. if (StumbleChat.Userlist.User.get(rcv.handle).mod > StumbleChat.Userlist.SortedUsers[ i ].mod) {
  1068. if (i == 0) {
  1069. first = true;
  1070. break;
  1071. }
  1072. beforeUser = StumbleChat.Userlist.SortedUsers[ i ].handle;
  1073. break;
  1074. } else if (StumbleChat.Userlist.User.get(rcv.handle).mod == StumbleChat.Userlist.SortedUsers[ i ].mod) {
  1075. if (StumbleChat.Userlist.SortedUsers[ i ].nick.toLowerCase().localeCompare(StumbleChat.Userlist.User.get(rcv.handle).nick.toLowerCase()) == 1) {
  1076. beforeUser = StumbleChat.Userlist.SortedUsers[ i ].handle;
  1077. break;
  1078. }
  1079. }
  1080. }
  1081. if (rcv.avatar == 1) {
  1082. StumbleChat.Userlist.User.get(rcv.handle).avatar = `/profile/${rcv.username.toLowerCase()}/cached/small_avatar.jpg`;
  1083. } else {
  1084. StumbleChat.Userlist.User.get(rcv.handle).avatar = undefined;
  1085. }
  1086. let element = `<li class="bar" user-id="${rcv.handle}">${(StumbleChat.Userlist.User.get(rcv.handle).avatar == undefined) ? `<div class="bar-item no-image"></div>` : `<img src="/profile/${rcv.username.toLowerCase()}/cached/small_avatar.jpg" class="bar-item">`}<div class="bar-item"><span class="nickname">${((StumbleChat.Chat.Settings.IgnoredList.includes(rcv.username.toUpperCase()) || StumbleChat.Chat.Settings.TempIgnoredList.includes(rcv.username.toUpperCase())) ? `<s>${rcv.nick}</s>` : rcv.nick)}</span><span class="username">${(rcv.guest) ? `guest` : rcv.username}</span></div><div class="user-status"><div class="role${ModColor[ rcv.mod ]}">${ModType[ rcv.mod ]}</div><div class="status"><div class="hidden"></div><div class="hidden"></div></div></div></li>`;
  1087. if (first) {
  1088. StumbleChat.Userlist.list.insertAdjacentHTML("afterbegin", element);
  1089. } else {
  1090. if (beforeUser) {
  1091. StumbleChat.Userlist.list.querySelector(`li[user-id="${beforeUser}"]`).insertAdjacentHTML("beforebegin", element);
  1092. } else {
  1093. StumbleChat.Userlist.list.insertAdjacentHTML("beforeend", element);
  1094. }
  1095. }
  1096. StumbleChat.Userlist.Count();
  1097. },
  1098. room: (rcv) => {
  1099. switch (rcv.type) {
  1100. case "guests":
  1101. StumbleChat.Room.guests_allowed = rcv.enabled;
  1102. Message.receive.public(`Guest mode has been ${(rcv.enabled) ? "enabled" : "disabled"}.`);
  1103. break;
  1104. case "public":
  1105. StumbleChat.Room.public = rcv.enabled;
  1106. Message.receive.public(`Room has been made ${(rcv.enabled) ? "public" : "private"}.`);
  1107. break;
  1108. case "greenroom":
  1109. StumbleChat.Room.greenroom = rcv.enabled;
  1110. Message.receive.public(`Greenroom has been ${(rcv.enabled) ? "enabled" : "disabled"}.`);
  1111. break;
  1112. case "topic":
  1113. StumbleChat.Room.topic = rcv.topic || "NO TOPIC";
  1114. document.querySelector('.topic').innerText = StumbleChat.Room.topic;
  1115. Message.receive.public(`${StumbleChat.Userlist.User.get(rcv.handle).nick} has ${(rcv.topic == "") ? "cleared" : "changed"} the room topic.`);
  1116. break;
  1117. case "broadcast_password":
  1118. Message.receive.public(`${(rcv.enabled == true) ? "Broadcast password was enabled." : "Broadcast password was disabled."}`);
  1119. StumbleChat.Room.broadcast_password = rcv.enabled;
  1120. break;
  1121. }
  1122. },
  1123. banlist: (rcv) => Modal.Create(9, rcv.users),
  1124. quit: (rcv) => {
  1125. Broadcast.unpublish(rcv.handle);
  1126. if (StumbleChat.Userlist.User.has(rcv.handle)) {
  1127. document.querySelector(`#userlist li[user-id="${rcv.handle}"]`).remove();
  1128. if (document.querySelector(`.privateMessages > div > span[user-id="${rcv.handle}"]`) !== null) {
  1129. if (StumbleChat.Chat.Messages.has(rcv.handle)) document.querySelector(`.privateMessages > div > span[user-id="${rcv.handle}"] > .nickname`).innerText += ` (offline)`;
  1130. }
  1131. Message.receive.public(`${StumbleChat.Userlist.User.get(rcv.handle).nick} (${(StumbleChat.Userlist.User.get(rcv.handle).guest == 0) ? StumbleChat.Userlist.User.get(rcv.handle).username : "guest"}:${rcv.handle}) has left.`);
  1132.  
  1133. if (StumbleChat.Chat.Selected == rcv.handle) Message.receive.private(rcv.handle, `${StumbleChat.Userlist.User.get(rcv.handle).nick} has gone offline.`);
  1134. clearTimeout(StumbleChat.Userlist.User.get(rcv.handle).disconnecttimer);
  1135. StumbleChat.Userlist.User.delete(rcv.handle);
  1136.  
  1137. for (let i = StumbleChat.Userlist.SortedUsers.length - 1; i >= 0; i--) {
  1138. if (StumbleChat.Userlist.SortedUsers[ i ].handle == rcv.handle) {
  1139. StumbleChat.Userlist.SortedUsers.splice(i, 1);
  1140. break;
  1141. }
  1142. }
  1143. StumbleChat.Userlist.Count();
  1144. }
  1145. },
  1146. closed: (rcv) => {
  1147. StumbleChat.Chat.Status.Kicked = true;
  1148. Modal.Create(8, rcv.text);
  1149. },
  1150. msg: (rcv) => {
  1151. if (StumbleChat.Userlist.User.has(rcv.handle)) {
  1152. if (!StumbleChat.Chat.Settings.IgnoredList.includes(StumbleChat.Userlist.User.get(rcv.handle).username.toUpperCase()) && !StumbleChat.Chat.Settings.TempIgnoredList.includes(StumbleChat.Userlist.User.get(rcv.handle).username.toUpperCase())) Message.receive.public(rcv.text, StumbleChat.Userlist.User.get(rcv.handle).username, StumbleChat.Userlist.User.get(rcv.handle).nick, StumbleChat.Userlist.User.get(rcv.handle).avatar, StumbleChat.Userlist.User.get(rcv.handle).namebackgroundcolor, StumbleChat.Userlist.User.get(rcv.handle).backgroundcolor, StumbleChat.Userlist.User.get(rcv.handle).messagetextcolor);
  1153. }
  1154. },
  1155. nick: (rcv) => {
  1156. let listusers = document.querySelector(`.bar[user-id="${rcv.handle}"] .nickname`);
  1157. listusers.innerText = rcv.nick;
  1158. if (StumbleChat.Chat.Messages.has(rcv.handle)) {
  1159. let listpm = document.querySelector(`.privateMessages > div > span[user-id="${rcv.handle}"] > .nickname`);
  1160. listpm.innerText = rcv.nick;
  1161. StumbleChat.Chat.Messages.get(rcv.handle).nick = rcv.nick;
  1162. if (StumbleChat.Chat.Selected == rcv.handle) document.querySelector(`#back`).innerHTML = `< ${StumbleChat.Chat.Messages.get(rcv.handle).nick} (${(StumbleChat.Userlist.User.get(rcv.handle).guest == 0) ? StumbleChat.Chat.Messages.get(rcv.handle).username : "guest"})`;
  1163. }
  1164. if (StumbleChat.Self.handle == rcv.handle) {
  1165. Message.receive.public(`You've successfully changed your nickname!`);
  1166. StumbleChat.Self.nick = rcv.nick;
  1167. localStorage.setItem('nick', rcv.nick);
  1168. } else {
  1169. Message.receive.public(`${StumbleChat.Userlist.User.get(rcv.handle).nick} has changed their nickname to ${rcv.nick}`);
  1170. }
  1171. if (StumbleChat.Userlist.Broadcast.has(rcv.handle)) StumbleChat.Userlist.Broadcast.get(rcv.handle).element.parentElement.querySelector('.nickname').innerText = rcv.nick;
  1172. StumbleChat.Userlist.User.get(rcv.handle).nick = rcv.nick;
  1173. StumbleChat.Userlist.Organize(rcv.handle);
  1174. },
  1175. role: (rcv) => {
  1176. let role = document.querySelector(`.bar[user-id="${rcv.handle}"] .role`);
  1177. switch (rcv.type) {
  1178. case "super":
  1179. if (StumbleChat.Self.handle == rcv.handle) {
  1180. StumbleChat.Self.mod = 3;
  1181. Message.receive.public(`You are now a super!`);
  1182. document.getElementById("media").parentElement.classList.remove("hidden");
  1183. document.getElementById("youtube-close-embed").classList.remove("hidden");
  1184. document.getElementById("twitch-close-embed").classList.remove("hidden");
  1185. document.getElementById("soundcloud-close-embed").classList.remove("hidden");
  1186. document.getElementById("dailymotion-close-embed").classList.remove("hidden");
  1187. document.getElementById("worldstarhiphop-close-embed").classList.remove("hidden");
  1188. document.getElementById("banlist").classList.remove("hidden");
  1189. document.getElementById("room-settings").classList.remove("hidden");
  1190. } else {
  1191. Message.receive.public(`${StumbleChat.Userlist.User.get(rcv.handle).nick} has become a super.`);
  1192. }
  1193. role.classList = "role blue";
  1194. role.innerText = "Super";
  1195. StumbleChat.Userlist.User.get(rcv.handle).mod = 3;
  1196. StumbleChat.Userlist.Organize(rcv.handle);
  1197. break;
  1198. case "moderator":
  1199. if (StumbleChat.Self.handle == rcv.handle) {
  1200. StumbleChat.Self.mod = 2;
  1201. Message.receive.public(`You are now a moderator!`);
  1202. document.getElementById("media").parentElement.classList.remove("hidden");
  1203. document.getElementById("youtube-close-embed").classList.remove("hidden");
  1204. document.getElementById("twitch-close-embed").classList.remove("hidden");
  1205. document.getElementById("soundcloud-close-embed").classList.remove("hidden");
  1206. document.getElementById("dailymotion-close-embed").classList.remove("hidden");
  1207. document.getElementById("worldstarhiphop-close-embed").classList.remove("hidden");
  1208. document.getElementById("banlist").classList.remove("hidden");
  1209. document.getElementById("room-settings").classList.add("hidden");
  1210. } else {
  1211. Message.receive.public(`${StumbleChat.Userlist.User.get(rcv.handle).nick} has become a moderator.`);
  1212. }
  1213. role.classList = "role green";
  1214. role.innerText = "Mod";
  1215. StumbleChat.Userlist.User.get(rcv.handle).mod = 2;
  1216. StumbleChat.Userlist.Organize(rcv.handle);
  1217. break;
  1218. case "operator":
  1219. if (StumbleChat.Self.handle == rcv.handle) {
  1220. StumbleChat.Self.mod = 1;
  1221. Message.receive.public(`You are now an operator.`);
  1222. document.getElementById("media").parentElement.classList.remove("hidden");
  1223. document.getElementById("youtube-close-embed").classList.remove("hidden");
  1224. document.getElementById("twitch-close-embed").classList.remove("hidden");
  1225. document.getElementById("soundcloud-close-embed").classList.remove("hidden");
  1226. document.getElementById("dailymotion-close-embed").classList.remove("hidden");
  1227. document.getElementById("worldstarhiphop-close-embed").classList.remove("hidden");
  1228. document.getElementById("banlist").classList.add("hidden");
  1229. document.getElementById("room-settings").classList.add("hidden");
  1230. } else {
  1231. Message.receive.public(StumbleChat.Userlist.User.get(rcv.handle).nick + " has become an operator.");
  1232. }
  1233. role.classList = "role red";
  1234. role.innerText = "Operator";
  1235. StumbleChat.Userlist.User.get(rcv.handle).mod = 1;
  1236. StumbleChat.Userlist.Organize(rcv.handle);
  1237. break;
  1238. case "revoke":
  1239. if (StumbleChat.Self.handle == rcv.handle) {
  1240. StumbleChat.Self.mod = 0;
  1241. Message.receive.public(`You were stripped of your roles!`);
  1242. document.getElementById("media").parentElement.classList.add("hidden");
  1243. document.getElementById("youtube-close-embed").classList.add("hidden");
  1244. document.getElementById("twitch-close-embed").classList.add("hidden");
  1245. document.getElementById("soundcloud-close-embed").classList.add("hidden");
  1246. document.getElementById("dailymotion-close-embed").classList.add("hidden");
  1247. document.getElementById("worldstarhiphop-close-embed").classList.add("hidden");
  1248. document.getElementById("banlist").classList.add("hidden");
  1249. document.getElementById("room-settings").classList.add("hidden");
  1250. } else {
  1251. Message.receive.public(`${StumbleChat.Userlist.User.get(rcv.handle).nick} has been stripped of their roles.`);
  1252. }
  1253. role.classList = "role";
  1254. role.innerText = "";
  1255. StumbleChat.Userlist.User.get(rcv.handle).mod = 0;
  1256. StumbleChat.Userlist.Organize(rcv.handle);
  1257. break;
  1258. }
  1259. },
  1260. pvtmsg: (rcv) => {
  1261. if (!StumbleChat.Chat.Settings.IgnoredList.includes(StumbleChat.Userlist.User.get(rcv.handle).username.toUpperCase()) && !StumbleChat.Chat.Settings.TempIgnoredList.includes(StumbleChat.Userlist.User.get(rcv.handle).username.toUpperCase())) Message.receive.private(rcv.handle, rcv.text, rcv.handle, StumbleChat.Userlist.User.get(rcv.handle).nick, StumbleChat.Userlist.User.get(rcv.handle).avatar, StumbleChat.Userlist.User.get(rcv.handle).namebackgroundcolor, StumbleChat.Userlist.User.get(rcv.handle).backgroundcolor, StumbleChat.Userlist.User.get(rcv.handle).messagetextcolor);
  1262. },
  1263. sysmsg: (rcv) => Message.receive.public(rcv.text),
  1264. publish: (rcv) => Broadcast.publish[ rcv.type ](rcv),
  1265. subscribe: (rcv) => {
  1266. SubscribeQueue.push(rcv);
  1267. if (SubscribeQueue.length == 1) return Broadcast.subscribe[ rcv.type ](rcv);
  1268. },
  1269. producers: (rcv) => {
  1270. if (rcv.producers.length == 0) return;
  1271. for (let i = 0; i < rcv.producers.length; i++) {
  1272. for (let x = 0; x < rcv.producers[ i ].kind.length; x++) {
  1273. let video = document.querySelector(`.bar[user-id="${rcv.producers[ i ].handle}"] .status>div:nth-child(1)`) !== null && rcv.producers[ i ].kind[ x ] == "video";
  1274. let audio = document.querySelector(`.bar[user-id="${rcv.producers[ i ].handle}"] .status>div:nth-child(2)`) !== null && rcv.producers[ i ].kind[ x ] == "audio";
  1275. if (!StumbleChat.Chat.Settings.HideList.includes(StumbleChat.Userlist.User.get(rcv.producers[ i ].handle).username.toUpperCase()) && !StumbleChat.Chat.Settings.TempHideList.includes(StumbleChat.Userlist.User.get(rcv.producers[ i ].handle).username.toUpperCase())) {
  1276. StumbleChat.WebSocket.send(JSON.stringify({ "stumble": "subscribe", "type": "request", "kind": rcv.producers[ i ].kind[ x ], "handle": rcv.producers[ i ].handle }));
  1277. } else {
  1278. Message.receive.public(`${(StumbleChat.Userlist.User.get(rcv.producers[ i ].handle).guest == 0) ? StumbleChat.Userlist.User.get(rcv.producers[ i ].handle).username : "guest"} started broadcasting ${rcv.producers[ i ].kind[ x ]} however you have them hidden.`);
  1279. }
  1280.  
  1281. if (StumbleChat.Chat.Settings.HideList.includes(StumbleChat.Userlist.User.get(rcv.producers[ i ].handle).username.toUpperCase()) || StumbleChat.Chat.Settings.TempHideList.includes(StumbleChat.Userlist.User.get(rcv.producers[ i ].handle).username.toUpperCase())) {
  1282. if (video) document.querySelector(`.bar[user-id="${rcv.producers[ i ].handle}"] .status>div:nth-child(1)`).classList.add("video_badge_hide");
  1283. if (audio) document.querySelector(`.bar[user-id="${rcv.producers[ i ].handle}"] .status>div:nth-child(2)`).classList.add("audio_badge_hide");
  1284. } else {
  1285. if (video) document.querySelector(`.bar[user-id="${rcv.producers[ i ].handle}"] .status>div:nth-child(1)`).classList.add("video_badge");
  1286. if (audio) document.querySelector(`.bar[user-id="${rcv.producers[ i ].handle}"] .status>div:nth-child(2)`).classList.add("audio_badge");
  1287. }
  1288. if (video) document.querySelector(`.bar[user-id="${rcv.producers[ i ].handle}"] .status>div:nth-child(1)`).classList.remove("hidden");
  1289. if (audio) document.querySelector(`.bar[user-id="${rcv.producers[ i ].handle}"] .status>div:nth-child(2)`).classList.remove("hidden");
  1290.  
  1291. if (StumbleChat.Userlist.User.has(rcv.producers[ i ].handle)) StumbleChat.Userlist.User.get(rcv.producers[ i ].handle).broadcasting.push(rcv.producers[ i ].kind[ x ]);
  1292. }
  1293. }
  1294. },
  1295. unsubscribe: (rcv) => {
  1296. if (StumbleChat.Userlist.User.has(rcv.handle)) StumbleChat.Userlist.User.get(rcv.handle).broadcasting = [];
  1297. if (rcv.handle == StumbleChat.Self.handle || StumbleChat.Userlist.User.has(rcv.handle)) Message.receive.public(`${(rcv.handle !== StumbleChat.Self.handle) ? StumbleChat.Userlist.User.get(rcv.handle).nick + " has" : "You have"} stopped broadcasting.`);
  1298.  
  1299. Broadcast.unpublish(rcv.handle);
  1300. },
  1301. youtube: (rcv) => {
  1302. if (rcv.type == "play") {
  1303. StumbleChat.Chat.Status.Playing.YouTube = true;
  1304. if (StumbleChat.Chat.Settings.YouTubeEnabled == true) {
  1305. document.querySelector("#videos > div > .youtube").classList.remove("hidden");
  1306. let b = setInterval(() => StumbleChat.Videos.Update(), 4);
  1307. if (window.YouTubePlayer == undefined) {
  1308. window.YouTubePlayer = new window.YT.Player('youtubeplayer', {
  1309. videoId: rcv.id,
  1310. playerVars: {
  1311. autohide: 2,
  1312. autoplay: 1,
  1313. mute: 0,
  1314. controls: 0,
  1315. disablekb: 1,
  1316. enablejsapi: 1,
  1317. fs: 0,
  1318. iv_load_policy: 3,
  1319. loop: 0,
  1320. modestbranding: 1,
  1321. origin: window.location.hostname,
  1322. playsinline: 1,
  1323. start: rcv.time,
  1324. rel: 0,
  1325. showinfo: 0
  1326. },
  1327. events: {
  1328. onReady: Media.YouTube.Ready,
  1329. onStateChange: Media.YouTube.onPlayerStateChange
  1330. }
  1331. });
  1332. } else {
  1333. window.YouTubePlayer.loadVideoById(rcv.id, rcv.time);
  1334. }
  1335. StumbleChat.Chat.Settings.YouTubeQueueID = rcv.queueid;
  1336. StumbleChat.Chat.Settings.YouTubeStartTime = rcv.time;
  1337. setTimeout(() => clearInterval(b), 800);
  1338. }
  1339. Message.receive.public(`Playing ${rcv.title} \n\nhttps://youtube.com/watch?v=${rcv.id}\n`);
  1340. } else if (rcv.type == "stop") {
  1341. StumbleChat.Chat.Status.Playing.YouTube = false;
  1342. Media.YouTube.Stop(rcv.text);
  1343. } else if (rcv.type == "playlist") {
  1344. Modal.Create(7, rcv.tracks);
  1345. }
  1346. },
  1347. wshh: (rcv) => {
  1348. let elem;
  1349. if (rcv.type == "play") {
  1350. StumbleChat.Chat.Status.Playing.WSSH = true;
  1351. if (StumbleChat.Chat.Settings.WSHHEnabled == true) {
  1352. document.querySelector("#videos > div > .worldstarhiphop").classList.remove("hidden");
  1353. StumbleChat.Videos.Update();
  1354. elem = document.querySelector("#worldstarhiphopplayer>video");
  1355. if (elem !== null) elem.parentNode.removeChild(elem);
  1356. document.querySelector("#worldstarhiphopplayer").innerHTML = `<video id="video" poster="${rcv.thumbnail}" controls playsinline src="${rcv.embed}">Your browser does not support the video tag...</video>`;
  1357. }
  1358. Message.receive.public(StumbleChat.Userlist.User.has(rcv.handle) ? `${StumbleChat.Userlist.User.get(rcv.handle).nick} (${StumbleChat.Userlist.User.get(rcv.handle).username}) has started WSHH:\n${rcv.title}\n\n${rcv.url}` : `Playing WSHH:\n${rcv.title}\n\n${rcv.url}`);
  1359. } else if (rcv.type == "stop") {
  1360. StumbleChat.Chat.Status.Playing.WSSH = false;
  1361. document.querySelector("#videos > div > .worldstarhiphop").classList.add("hidden");
  1362. StumbleChat.Videos.Update();
  1363. elem = document.querySelector("#worldstarhiphopplayer>video");
  1364. if (elem !== null) elem.parentNode.removeChild(elem);
  1365. Message.receive.public(`${StumbleChat.Userlist.User.get(rcv.handle).nick} (${StumbleChat.Userlist.User.get(rcv.handle).username}) has stopped WSHH.`);
  1366. }
  1367. },
  1368. soundcloud: (rcv) => {
  1369. let elem;
  1370. if (rcv.type == "play") {
  1371. StumbleChat.Chat.Status.Playing.SoundCloud = true;
  1372. if (StumbleChat.Chat.Settings.SoundCloudEnabled == true) {
  1373. document.querySelector("#videos > div > .soundcloud").classList.remove("hidden");
  1374. document.querySelector("#soundcloud-volume-slider").value = 100;
  1375. StumbleChat.Videos.Update();
  1376. elem = document.querySelector("#soundcloudplayer>iframe");
  1377. if (elem !== null) elem.parentNode.removeChild(elem);
  1378. document.querySelector("#soundcloudplayer").innerHTML = rcv.embed;
  1379. }
  1380. Message.receive.public(StumbleChat.Userlist.User.has(rcv.handle) ? `${StumbleChat.Userlist.User.get(rcv.handle).nick} (${StumbleChat.Userlist.User.get(rcv.handle).username}) has started SoundCloud:\n${rcv.title}\n\n${rcv.url}` : `Playing SoundCloud:\n${rcv.title}\n\n${rcv.url}`);
  1381. } else if (rcv.type == "stop") {
  1382. StumbleChat.Chat.Status.Playing.SoundCloud = false;
  1383. document.querySelector("#videos > div > .soundcloud").classList.add("hidden");
  1384. StumbleChat.Videos.Update();
  1385. elem = document.querySelector("#soundcloudplayer>iframe");
  1386. if (elem !== null) elem.parentNode.removeChild(elem);
  1387. Message.receive.public(`${StumbleChat.Userlist.User.get(rcv.handle).nick} (${StumbleChat.Userlist.User.get(rcv.handle).username}) has stopped SoundCloud.`);
  1388. }
  1389. },
  1390. dailymotion: (rcv) => {
  1391. let elem;
  1392. if (rcv.type == "play") {
  1393. StumbleChat.Chat.Status.Playing.DailyMotion = true;
  1394.  
  1395. if (StumbleChat.Chat.Settings.DailyMotionEnabled == true) {
  1396.  
  1397. document.querySelector("#videos > div > .dailymotion").classList.remove("hidden");
  1398. StumbleChat.Videos.Update();
  1399. elem = document.querySelector("#dailymotionplayer>iframe");
  1400. if (elem !== null) elem.parentNode.removeChild(elem);
  1401. document.querySelector("#dailymotionplayer").innerHTML = rcv.embed;
  1402. }
  1403. Message.receive.public(StumbleChat.Userlist.User.has(rcv.handle) ? `${StumbleChat.Userlist.User.get(rcv.handle).nick} (${StumbleChat.Userlist.User.get(rcv.handle).username}) has started DailyMotion:\n${rcv.title}\n\n${rcv.url}` : `Playing DailyMotion:\n${rcv.title}\n\n${rcv.url}`);
  1404. } else if (rcv.type == "stop") {
  1405. StumbleChat.Chat.Status.Playing.DailyMotion = false;
  1406.  
  1407. document.querySelector("#videos > div > .dailymotion").classList.add("hidden");
  1408. StumbleChat.Videos.Update();
  1409.  
  1410. elem = document.querySelector("#dailymotionplayer>iframe");
  1411. if (elem !== null) elem.parentNode.removeChild(elem);
  1412. Message.receive.public(`${StumbleChat.Userlist.User.get(rcv.handle).nick} (${StumbleChat.Userlist.User.get(rcv.handle).username}) has stopped DailyMotion.`);
  1413. }
  1414. },
  1415. twitch: (rcv) => {
  1416. let elem;
  1417. if (rcv.type == "play") {
  1418. StumbleChat.Chat.Status.Playing.Twitch = true;
  1419.  
  1420. if (StumbleChat.Chat.Settings.TwitchEnabled == true) {
  1421. document.querySelector("#videos > div > .twitch").classList.remove("hidden");
  1422. StumbleChat.Videos.Update();
  1423. elem = document.querySelector("#twitchplayer>iframe");
  1424. if (elem !== null) elem.parentNode.removeChild(elem);
  1425. document.querySelector("#twitch-volume-slider").value = 100;
  1426. window.TwitchPlayer = new window.Twitch.Player("twitchplayer", {
  1427. autoplay: false,
  1428. controls: false,
  1429. width: "100%",
  1430. height: "100%",
  1431. channel: rcv.name,
  1432. parent: [ window.location.hostname ]
  1433. });
  1434. }
  1435. Message.receive.public(StumbleChat.Userlist.User.has(rcv.handle) ? `${StumbleChat.Userlist.User.get(rcv.handle).nick} (${StumbleChat.Userlist.User.get(rcv.handle).username}) has started Twitch:\nhttps://twitch.tv/${rcv.name}` : `Playing Twitch:\nhttps://twitch.tv/${rcv.name}`);
  1436. } else if (rcv.type == "stop") {
  1437. StumbleChat.Chat.Status.Playing.Twitch = false;
  1438.  
  1439. window.TwitchPlayer = null;
  1440. document.querySelector("#videos > div > .twitch").classList.add("hidden");
  1441. StumbleChat.Videos.Update();
  1442. elem = document.querySelector("#twitchplayer>iframe");
  1443. if (elem !== null) elem.parentNode.removeChild(elem);
  1444. Message.receive.public(`${StumbleChat.Userlist.User.get(rcv.handle).nick} (${StumbleChat.Userlist.User.get(rcv.handle).username}) has stopped Twitch.`);
  1445. }
  1446.  
  1447. }
  1448. };
  1449.  
  1450. let localScreen;
  1451.  
  1452. let Broadcast = {
  1453. unpublish: (handle) => {
  1454. if (StumbleChat.Userlist.Broadcast.has(handle)) {
  1455. if (StumbleChat.Userlist.Broadcast.get(handle).spectrum !== undefined) StumbleChat.Userlist.Broadcast.get(handle).spectrum.stop();
  1456. clearInterval(StumbleChat.Userlist.Broadcast.get(handle).iceInterval);
  1457. StumbleChat.Userlist.Broadcast.get(handle).stream.getTracks().forEach((track) => track.stop());
  1458. StumbleChat.Userlist.Broadcast.get(handle).transport.close();
  1459. }
  1460. if (StumbleChat.Userlist.User.has(handle)) clearTimeout(StumbleChat.Userlist.User.get(handle).disconnecttimer);
  1461.  
  1462. if (handle == StumbleChat.Self.handle && localScreen != undefined) {
  1463. localScreen.getTracks().forEach((track) => track.stop());
  1464. localScreen = undefined;
  1465. }
  1466.  
  1467. removeBroadcastElement(handle);
  1468. removeBroadcastBadge(handle);
  1469.  
  1470. if (handle == StumbleChat.Self.handle) resetBroadcastState();
  1471. StumbleChat.Videos.Update();
  1472. },
  1473. publish: {
  1474. create: (rcv) => {
  1475. try {
  1476. if (!StumbleChat.Userlist.Broadcast.has(StumbleChat.Self.handle)) {
  1477. let Transport = StumbleChat.Videos.Device.createSendTransport(rcv.transport);
  1478. StumbleChat.Userlist.Broadcast.set(StumbleChat.Self.handle, {
  1479. "volume": 100,
  1480. "spectrum": undefined,
  1481. "stream": new window.MediaStream(),
  1482. "video": null,
  1483. "audio": null,
  1484. "canvas": null,
  1485. "element": null,
  1486. "transport": Transport,
  1487. "iceInterval": undefined,
  1488. "connectSent": false
  1489. });
  1490.  
  1491. Transport.on('connect', ({ dtlsParameters }) => {
  1492. if (!StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).connectSent) {
  1493. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).connectSent = true;
  1494. StumbleChat.WebSocket.send(JSON.stringify({ "stumble": "publish", "type": "connect", "dtlsParameters": dtlsParameters }));
  1495. }
  1496. });
  1497. Transport.on("produce", (producer) => StumbleChat.WebSocket.send(JSON.stringify({ "stumble": "publish", "type": producer.kind, "rtpParameters": producer.rtpParameters })));
  1498. Transport.on("connectionstatechange", (connectionState) => {
  1499. if (StumbleChat.Userlist.Broadcast.has(StumbleChat.Self.handle)) {
  1500. if (connectionState == "connected") {
  1501. clearInterval(StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).iceInterval);
  1502. } else if (connectionState == "disconnected") {
  1503. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).iceInterval = setInterval((handle) => StumbleChat.WebSocket.send(`{"stumble":"publish","type":"ice","handle":"${handle}"}`), 10000, StumbleChat.Self.handle);
  1504. }
  1505. }
  1506. });
  1507. let elem = {};
  1508. if (localScreen !== undefined) {
  1509. elem = createBroadcastElement(StumbleChat.Self.handle);
  1510. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).element = elem.video;
  1511.  
  1512. if (StumbleChat.Self.directory) StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).canvas = elem.canvas;
  1513.  
  1514. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).element.srcObject = localScreen;
  1515. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).element.muted = true;
  1516. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).element.play();
  1517.  
  1518. localScreen.getTracks().forEach((track) => {
  1519. if (track.kind == "video") {
  1520. track.contentHint = "motion";
  1521.  
  1522. document.querySelector(`.bar[user-id="${StumbleChat.Self.handle}"] .status>div:nth-child(1)`).classList[ StumbleChat.Self.Hidden ? "remove" : "add" ]("video_badge");
  1523. document.querySelector(`.bar[user-id="${StumbleChat.Self.handle}"] .status>div:nth-child(1)`).classList[ StumbleChat.Self.Hidden ? "add" : "remove" ]("video_badge_hide");
  1524. document.querySelector(`.bar[user-id="${StumbleChat.Self.handle}"] .status>div:nth-child(1)`).classList.remove("hidden");
  1525.  
  1526. }
  1527. if (track.kind == "audio") {
  1528. document.querySelector(`.bar[user-id="${StumbleChat.Self.handle}"] .status>div:nth-child(2)`).classList.add("audio_badge");
  1529. document.querySelector(`.bar[user-id="${StumbleChat.Self.handle}"] .status>div:nth-child(2)`).classList.remove("hidden");
  1530.  
  1531. StumbleChat.Videos.Soundmeter(StumbleChat.Self.handle, localScreen);
  1532. }
  1533. document.querySelector(`.bar[user-id="${StumbleChat.Self.handle}"] .${track.kind}_badge`).classList.remove("hidden");
  1534. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).transport.produce({ track: track }).then((consumed) => StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle)[ track.kind ] = consumed);
  1535. });
  1536.  
  1537. document.getElementById('media-loading').classList.add('hidden');
  1538. document.getElementById('media-stop').classList.add("no-audio");
  1539. } else {
  1540. let Constraints = {};
  1541.  
  1542. if (StumbleChat.Chat.Settings.videodevice != "NONE") Constraints.video = { deviceId: StumbleChat.Chat.Settings.videodevice, width: StumbleChat.Videos.Resolutions[ StumbleChat.Chat.Settings.Resolution ][ 0 ], height: StumbleChat.Videos.Resolutions[ StumbleChat.Chat.Settings.Resolution ][ 1 ], frameRate: { ideal: StumbleChat.Videos.FrameRate, max: 60 } };
  1543. if (StumbleChat.Chat.Settings.audiodevice != "NONE") Constraints.audio = { deviceId: StumbleChat.Chat.Settings.audiodevice, channelCount: { ideal: 2 }, echoCancellation: StumbleChat.Chat.Settings.EchoCancellation, autoGainControl: StumbleChat.Chat.Settings.AutoGainControl, noiseSuppression: StumbleChat.Chat.Settings.NoiseSupression };
  1544.  
  1545.  
  1546. navigator.mediaDevices.getUserMedia(Constraints).then(stream => {
  1547. if (!StumbleChat.Userlist.Broadcast.has(StumbleChat.Self.handle)) return stream.getTracks().forEach((track) => track.stop());
  1548.  
  1549. document.getElementById('media-loading').classList.add('hidden');
  1550. document.getElementById('media-stop').classList.add("no-audio");
  1551.  
  1552. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).stream = stream;
  1553.  
  1554. elem = createBroadcastElement(StumbleChat.Self.handle);
  1555.  
  1556. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).element = elem.video;
  1557. if (StumbleChat.Self.directory) StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).canvas = elem.canvas;
  1558.  
  1559. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).element.srcObject = StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).stream;
  1560. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).element.muted = true;
  1561. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).element.play();
  1562.  
  1563. stream.getTracks().forEach((track, index) => {
  1564. if (document.querySelector(`.bar[user-id="${StumbleChat.Self.handle}"] .${track.kind}_badge`) != undefined) document.querySelector(`.bar[user-id="${StumbleChat.Self.handle}"] .${track.kind}_badge`).classList.remove("hidden");
  1565. document.getElementById('media-stop').classList.remove('hidden');
  1566. if (track.kind == "audio") {
  1567. document.getElementById('media-stop').classList.remove("no-audio");
  1568. document.getElementById('media-ptt').classList.remove('hidden');
  1569. document.getElementById('media-openmic').classList.remove('hidden');
  1570. StumbleChat.Videos.Soundmeter(StumbleChat.Self.handle, stream);
  1571. document.querySelector(`.bar[user-id="${StumbleChat.Self.handle}"] .status>div:nth-child(2)`).classList.add("audio_badge");
  1572. document.querySelector(`.bar[user-id="${StumbleChat.Self.handle}"] .status>div:nth-child(2)`).classList.remove("hidden");
  1573. }
  1574. if (track.kind == "video") {
  1575.  
  1576. document.querySelector(`.bar[user-id="${StumbleChat.Self.handle}"] .status>div:nth-child(1)`).classList[ StumbleChat.Self.Hidden ? "remove" : "add" ]("video_badge");
  1577. document.querySelector(`.bar[user-id="${StumbleChat.Self.handle}"] .status>div:nth-child(1)`).classList[ StumbleChat.Self.Hidden ? "add" : "remove" ]("video_badge_hide");
  1578. document.querySelector(`.bar[user-id="${StumbleChat.Self.handle}"] .status>div:nth-child(1)`).classList.remove("hidden");
  1579.  
  1580. if (StumbleChat.Self.Hidden) track.enabled = false;
  1581. }
  1582.  
  1583. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).transport.produce({ track: track }).then((produced) => {
  1584. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle)[ track.kind ] = produced;
  1585. if (track.kind == "audio") StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).audio.pause();
  1586. });
  1587. });
  1588. });
  1589. }
  1590. }
  1591. } catch (e) {
  1592. console.warn(e);
  1593. Broadcast.unpublish(StumbleChat.Self.handle);
  1594. Message.receive.public(`Fatal Error: Browser requires reloading to continue with anymore streams.`);
  1595. }
  1596. },
  1597. connected: () => {
  1598. Message.receive.public(`You have started broadcasting.`);
  1599. document.getElementById('media-broadcast').classList.add('hidden');
  1600. document.getElementById('media-settings').classList.add('hidden');
  1601. document.getElementById('media-screen').classList.add('hidden');
  1602. document.getElementById('media-stop').classList.remove('hidden');
  1603.  
  1604. StumbleChat.Videos.Update();
  1605. },
  1606. error: (rcv) => {
  1607. Message.receive.public(rcv.error);
  1608. if (localScreen) localScreen.removeEventListener('inactive', (event) => Broadcast.unpublish(StumbleChat.Self.handle));
  1609.  
  1610. Broadcast.unpublish(StumbleChat.Self.handle);
  1611. },
  1612. ice: (rcv) => {
  1613. if (StumbleChat.Userlist.Broadcast.has(StumbleChat.Self.handle)) StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).transport.restartIce(rcv.transport);
  1614. },
  1615. close: () => Broadcast.unpublish(StumbleChat.Self.handle),
  1616. disconnected: () => {
  1617. clearTimeout(StumbleChat.Userlist.User.get(StumbleChat.Self.handle).disconnecttimer);
  1618.  
  1619. if (StumbleChat.Userlist.Broadcast.has(StumbleChat.Self.handle)) {
  1620. if (StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).spectrum !== undefined) StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).spectrum.stop();
  1621. clearInterval(StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).iceInterval);
  1622. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).stream.getTracks().forEach((track) => track.stop());
  1623. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).transport.close();
  1624. }
  1625.  
  1626. removeBroadcastElement(StumbleChat.Self.handle);
  1627. removeBroadcastBadge(StumbleChat.Self.handle);
  1628. resetBroadcastState();
  1629.  
  1630. if (localScreen != undefined) {
  1631. Message.receive.public("Stream disconnected. Try again.");
  1632. localScreen.getTracks().forEach((track) => track.stop());
  1633. localScreen = undefined;
  1634. } else {
  1635. Message.receive.public("Stream disconnected. Reloading broadcast again.");
  1636. setTimeout(() => {
  1637. requestBroadcast(StumbleChat.Videos.Password);
  1638. }, 1000);
  1639. }
  1640. },
  1641. cheese: () => {
  1642. if (StumbleChat.Userlist.Broadcast.has(StumbleChat.Self.handle) && StumbleChat.Self.directory) {
  1643. try {
  1644. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).canvas.width = 320;
  1645. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).canvas.height = 240;
  1646. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).canvas.getContext('2d', { alpha: false }).drawImage(StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).element, 0, 0, 320, 240);
  1647. StumbleChat.WebSocket.send(JSON.stringify({
  1648. "stumble": "publish",
  1649. "type": "cheese",
  1650. "jpeg": StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).canvas.toDataURL('image/jpeg', 0.3)
  1651. }));
  1652. } catch (err) {
  1653. console.warn(err);
  1654. }
  1655. }
  1656. }
  1657. },
  1658. subscribe: {
  1659. create: (rcv) => {
  1660. try {
  1661. if (!StumbleChat.Userlist.Broadcast.has(rcv.handle)) {
  1662. let Transport = StumbleChat.Videos.Device.createRecvTransport(rcv.transport);
  1663. StumbleChat.Userlist.Broadcast.set(rcv.handle, { "volume": 100, "spectrum": undefined, "stream": new window.MediaStream(), "video": null, "audio": null, "element": null, "transport": Transport, "iceInterval": undefined, "connectSent": false });
  1664. Transport.on('connect', ({ dtlsParameters }) => {
  1665. if (!StumbleChat.Userlist.Broadcast.get(rcv.handle).connectSent) {
  1666. StumbleChat.Userlist.Broadcast.get(rcv.handle).connectSent = true;
  1667. StumbleChat.WebSocket.send(JSON.stringify({ "stumble": "subscribe", "type": "connect", "handle": rcv.handle, "dtlsParameters": dtlsParameters }));
  1668. }
  1669. });
  1670.  
  1671. Transport.on("connectionstatechange", (connectionState) => {
  1672. if (connectionState == "connected") {
  1673. clearInterval(StumbleChat.Userlist.Broadcast.get(rcv.handle).iceInterval);
  1674. } else if (connectionState == "disconnected") {
  1675. StumbleChat.Userlist.Broadcast.get(rcv.handle).iceInterval = setInterval((handle) => StumbleChat.WebSocket.send(`{"stumble":"subscribe","type":"ice","handle":"${handle}"}`), 10000, rcv.handle);
  1676. }
  1677. });
  1678. }
  1679. } catch (e) {
  1680. console.error(e);
  1681. Broadcast.unpublish(rcv.handle);
  1682. Message.receive.public(`Fatal Error: Browser requires reloading to continue with anymore streams.`);
  1683. }
  1684. StumbleChat.WebSocket.nextMessage();
  1685. },
  1686. consume: (rcv) => {
  1687. try {
  1688. if (StumbleChat.Userlist.Broadcast.has(rcv.handle)) {
  1689. StumbleChat.Userlist.Broadcast.get(rcv.handle).transport.consume({ "id": rcv.consume.id, "producerId": rcv.consume.producerId, "kind": rcv.consume.kind, "rtpParameters": rcv.consume.rtpParameters }).then((consume) => {
  1690.  
  1691. StumbleChat.Userlist.Broadcast.get(rcv.handle)[ rcv.consume.kind ] = consume;
  1692. StumbleChat.Userlist.Broadcast.get(rcv.handle)[ rcv.consume.kind ].resume();
  1693.  
  1694. StumbleChat.Userlist.Broadcast.get(rcv.handle).stream.addTrack(StumbleChat.Userlist.Broadcast.get(rcv.handle)[ rcv.consume.kind ].track);
  1695.  
  1696. if (StumbleChat.Userlist.Broadcast.get(rcv.handle).element == null) {
  1697. let elem = createBroadcastElement(rcv.handle);
  1698. StumbleChat.Userlist.Broadcast.get(rcv.handle).element = elem.video;
  1699. StumbleChat.Userlist.Broadcast.get(rcv.handle).element.srcObject = StumbleChat.Userlist.Broadcast.get(rcv.handle).stream;
  1700. StumbleChat.Userlist.Broadcast.get(rcv.handle).element.controls = false;
  1701. StumbleChat.Userlist.Broadcast.get(rcv.handle).element.play();
  1702. }
  1703. if (rcv.consume.kind == "audio") {
  1704. if (StumbleChat.Chat.Settings.SoundmeterEnabled) {
  1705. StumbleChat.Userlist.Broadcast.get(rcv.handle).spectrum = window.hark(StumbleChat.Userlist.Broadcast.get(rcv.handle).stream, {});
  1706. let parent = StumbleChat.Userlist.Broadcast.get(rcv.handle).element.parentElement;
  1707. parent.classList.add("visualizer");
  1708. parent.setAttribute("volume", 0);
  1709. StumbleChat.Userlist.Broadcast.get(rcv.handle).spectrum.on('volume_change', (volume) => {
  1710. if (volume <= -100) parent.setAttribute("volume", 0);
  1711. if (volume >= -100) parent.setAttribute("volume", 1);
  1712. if (volume >= -95) parent.setAttribute("volume", 2);
  1713. if (volume >= -90) parent.setAttribute("volume", 3);
  1714. if (volume >= -80) parent.setAttribute("volume", 4);
  1715. if (volume >= -70) parent.setAttribute("volume", 5);
  1716. if (volume >= -60) parent.setAttribute("volume", 6);
  1717. if (volume >= -50) parent.setAttribute("volume", 7);
  1718. if (volume >= -40) parent.setAttribute("volume", 8);
  1719. if (volume >= -30) parent.setAttribute("volume", 9);
  1720. if (volume >= -15) parent.setAttribute("volume", 10);
  1721. });
  1722. }
  1723. if (!StumbleChat.Userlist.User.get(rcv.handle).guest) {
  1724. if (StumbleChat.Chat.Settings.BroadcastVolume[ StumbleChat.Userlist.User.get(rcv.handle).username.toUpperCase() ] !== undefined) StumbleChat.Userlist.Broadcast.get(rcv.handle).volume = StumbleChat.Chat.Settings.BroadcastVolume[ StumbleChat.Userlist.User.get(rcv.handle).username.toUpperCase() ];
  1725. } else {
  1726. if (StumbleChat.Chat.Settings.TempBroadcastVolume[ StumbleChat.Userlist.User.get(rcv.handle).username.toUpperCase() ] !== undefined) {
  1727. StumbleChat.Userlist.Broadcast.get(rcv.handle).volume = StumbleChat.Chat.Settings.TempBroadcastVolume[ StumbleChat.Userlist.User.get(rcv.handle).username.toUpperCase() ];
  1728. } else {
  1729. StumbleChat.Chat.Settings.TempBroadcastVolume[ StumbleChat.Userlist.User.get(rcv.handle).username.toUpperCase() ] = 25;
  1730. StumbleChat.Userlist.Broadcast.get(rcv.handle).volume = 25;
  1731. }
  1732. }
  1733. StumbleChat.Userlist.Broadcast.get(rcv.handle).element.volume = (StumbleChat.Userlist.Broadcast.get(rcv.handle).volume / 100) * (StumbleChat.Chat.Settings.RoomVolume / 100);
  1734. }
  1735.  
  1736. StumbleChat.Videos.Update();
  1737. StumbleChat.WebSocket.nextMessage();
  1738. }).catch((e) => {
  1739. console.error("Consume Error:", e);
  1740. StumbleChat.WebSocket.nextMessage();
  1741. });
  1742. } else {
  1743. Message.receive.public(`Fatal Error: Couldn't consume a user, this is a developer issue and will be fixed soon. Do refresh; likely caused by server restarts.`);
  1744. StumbleChat.WebSocket.nextMessage();
  1745. }
  1746. } catch (e) {
  1747. console.error("Consume Error:", e);
  1748. StumbleChat.WebSocket.nextMessage();
  1749. }
  1750. },
  1751. connected: (rcv) => {
  1752. if (StumbleChat.Userlist.User.has(rcv.handle)) Message.receive.public(`${StumbleChat.Userlist.User.get(rcv.handle).nick} started broadcasting!`);
  1753. StumbleChat.WebSocket.nextMessage();
  1754. },
  1755. ice: (rcv) => {
  1756. StumbleChat.Userlist.Broadcast.get(rcv.handle).transport.restartIce(rcv.transport);
  1757. StumbleChat.WebSocket.nextMessage();
  1758. },
  1759. disconnected: (rcv) => {
  1760. clearTimeout(StumbleChat.Userlist.User.get(rcv.handle).disconnecttimer);
  1761.  
  1762. if (StumbleChat.Userlist.Broadcast.has(rcv.handle)) {
  1763. if (StumbleChat.Userlist.Broadcast.get(rcv.handle).spectrum !== undefined) StumbleChat.Userlist.Broadcast.get(rcv.handle).spectrum.stop();
  1764. StumbleChat.Userlist.Broadcast.get(rcv.handle).stream.getTracks().forEach((track) => track.stop());
  1765. StumbleChat.Userlist.Broadcast.get(rcv.handle).transport.close();
  1766. }
  1767.  
  1768. StumbleChat.Userlist.Broadcast.delete(rcv.handle);
  1769.  
  1770. StumbleChat.Videos.Update();
  1771.  
  1772. StumbleChat.Userlist.User.get(rcv.handle).disconnecttimer = setTimeout((handle) => {
  1773. StumbleChat.Userlist.User.get(handle).broadcasting.forEach((value) => StumbleChat.WebSocket.send(`{"stumble":"subscribe","type":"request","handle":"${handle}","kind":"${value}"}`));
  1774. }, 3000, rcv.handle);
  1775. StumbleChat.WebSocket.nextMessage();
  1776. }
  1777. }
  1778. };
  1779. function rollDiceAndDisplay () {
  1780. // Generate a random number between 1 and 6 (inclusive) for a standard six-sided die
  1781. const min = 1;
  1782. const max = 6;
  1783. const result = Math.floor(Math.random() * (max - min + 1)) + min;
  1784.  
  1785. // Define Unicode dice symbols for numbers 1 through 6
  1786. const diceSymbols = [ '⚀', '⚁', '⚂', '⚃', '⚄', '⚅' ];
  1787.  
  1788. // Display the rolled dice symbol
  1789. const diceSymbol = diceSymbols[ result - 1 ];
  1790. return diceSymbol;
  1791. }
  1792. let Message = {
  1793. send: (event) => {
  1794. if ((event.key == "Enter" || event.code == "Enter") && !event.shiftKey) {
  1795. event.preventDefault();
  1796. StumbleChat.Chat.Status.Timelastpost = new Date();
  1797. let text = document.getElementById("textarea");
  1798. if (text.value.length > 0) {
  1799. text.value = text.value.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/ +/g, ' ');
  1800. text.focus();
  1801. if (text.value.match(/^\s*$/)) {
  1802. text.value = "";
  1803. return;
  1804. }
  1805. let command = text.value.match(/^(?:!|\/)([a-z?]{1,20})/i);
  1806. if (command) {
  1807. switch (command[ 1 ]) {
  1808. case "help":
  1809. Message.receive.public(`/help\n\n/device`);
  1810. break;
  1811. case "device":
  1812. Message.receive.public(`Detected Device:\n${window.stumblechatClient.detectDevice()}`);
  1813. break;
  1814. case "roll":
  1815. if (StumbleChat.WebSocket.readyState == 1) StumbleChat.WebSocket.send(JSON.stringify({
  1816. "stumble": "msg",
  1817. "text": rollDiceAndDisplay()
  1818. }));
  1819. break;
  1820. }
  1821. } else {
  1822. if (StumbleChat.Chat.Selected == 0) {
  1823. // Main Chat Selected
  1824. if (StumbleChat.WebSocket !== null) {
  1825. StumbleChat.WebSocket.send(JSON.stringify({
  1826. "stumble": "msg",
  1827. "text": text.value
  1828. }));
  1829. }
  1830. } else {
  1831. if (StumbleChat.Userlist.User.has(StumbleChat.Chat.Selected)) {
  1832. // Private Chat Selected
  1833. Message.receive.private(StumbleChat.Chat.Selected, text.value, StumbleChat.Self.handle, StumbleChat.Self.nick, StumbleChat.Self.avatar, StumbleChat.Self.namebackgroundcolor, StumbleChat.Self.backgroundcolor, StumbleChat.Self.messagetextcolor);
  1834. StumbleChat.WebSocket.send(JSON.stringify({
  1835. "stumble": "pvtmsg",
  1836. "handle": StumbleChat.Chat.Selected,
  1837. "text": text.value
  1838. }));
  1839. } else {
  1840. Message.receive.private(StumbleChat.Chat.Selected, `User is offline. Message couldn't be delivered.`);
  1841. }
  1842. }
  1843. }
  1844. text.value = "";
  1845. }
  1846. }
  1847. },
  1848. receive: {
  1849. public: (msg, username, nick, avatar, namebackgroundcolor, backgroundcolor, messagetextcolor) => {
  1850. let Time = currentTime();
  1851. let message = msg.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/ +/g, ' ');
  1852. if (message == " ") return;
  1853. if (!StumbleChat.Chat.Messages.has(0)) StumbleChat.Chat.Messages.set(0, []);
  1854. if (StumbleChat.Chat.Settings.LinksEnabled) message = parseLink(message);
  1855. if (StumbleChat.Chat.Settings.ImgurEnabled) message = parseImgur(message);
  1856.  
  1857. StumbleChat.Chat.Messages.get(0).push({
  1858. "username": username,
  1859. "nick": nick,
  1860. "msg": message,
  1861. "time": Time,
  1862. "avatar": avatar,
  1863. "namebackgroundcolor": namebackgroundcolor,
  1864. "backgroundcolor": backgroundcolor,
  1865. "messagetextcolor": messagetextcolor
  1866. });
  1867.  
  1868. if (nick !== StumbleChat.Self.nick && nick !== undefined && StumbleChat.Chat.Settings.SoundsEnabled && StumbleChat.Userlist.User.size <= 12) {
  1869. StumbleChat.Chat.Sounds.public_message.pause();
  1870. StumbleChat.Chat.Sounds.public_message.currentTime = 0;
  1871. StumbleChat.Chat.Sounds.public_message.play();
  1872. }
  1873.  
  1874. if (StumbleChat.Chat.Selected == 0) {
  1875. Message.unread();
  1876. let len = StumbleChat.Chat.Messages.get(0).length - 2;
  1877. if (len >= 0) {
  1878. if (StumbleChat.Chat.Messages.get(0)[ len ].username == username && username != undefined && nick == StumbleChat.Chat.Messages.get(0)[ len ].nick) {
  1879. let element = document.createElement("div");
  1880. element.setAttribute("class", "content");
  1881. element.innerHTML = `<span class="hidden-selectable">[${Time}]</span><span class="timestamp">${Time}</span><span class="message common" style="color:${messagetextcolor}">${message}</span></div>`;
  1882.  
  1883. document.querySelector("#chat-content>.message:last-child").appendChild(element);
  1884. } else {
  1885. createChatItem({
  1886. nick: nick,
  1887. time: Time,
  1888. avatar: avatar,
  1889. msg: message,
  1890. backgroundcolor: backgroundcolor,
  1891. namebackgroundcolor: namebackgroundcolor,
  1892. messagetextcolor: messagetextcolor,
  1893. });
  1894. }
  1895. } else {
  1896. createChatItem({
  1897. nick: nick,
  1898. time: Time,
  1899. avatar: avatar,
  1900. msg: message,
  1901. backgroundcolor: backgroundcolor,
  1902. namebackgroundcolor: namebackgroundcolor,
  1903. messagetextcolor: messagetextcolor,
  1904. });
  1905. }
  1906.  
  1907. StumbleChat.Chat.Scroll();
  1908. }
  1909. },
  1910. private: (handle, msg, sender, nick, avatar, namebackgroundcolor, backgroundcolor, messagetextcolor) => {
  1911. if (StumbleChat.Chat.Settings.PrivateMessageEnabled == false) return;
  1912. let message = msg.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/ +/g, ' ');
  1913. if (message == " ") return;
  1914.  
  1915. if (StumbleChat.Userlist.User.has(handle)) {
  1916. let acc = StumbleChat.Userlist.User.get(handle);
  1917. if (!StumbleChat.Chat.Messages.has(handle)) {
  1918. StumbleChat.Chat.Messages.set(handle, {
  1919. username: (acc.guest == 0) ? acc.username : "guest",
  1920. nick: acc.nick,
  1921. avatar: acc.avatar,
  1922. missedmsg: 0,
  1923. message: [],
  1924. namebackgroundcolor: namebackgroundcolor,
  1925. backgroundcolor: backgroundcolor,
  1926. messagetextcolor: messagetextcolor
  1927. });
  1928. }
  1929. let PM = document.querySelector(".privateMessages");
  1930. if (!PM.querySelector(`[user-id="${handle}"]`)) {
  1931. document.querySelector("#userlist>h2:nth-child(2)").classList.remove("hidden");
  1932. PM.classList.remove("hidden");
  1933. let element = document.createElement('div');
  1934. element.setAttribute("class", "list-item");
  1935. element.innerHTML = `<span class="private" user-id=${handle}><div class="nickname">${StumbleChat.Userlist.User.get(handle).nick}</div><div class="unreadpm"></div><span class="closepm">x</span></span>`;
  1936. document.querySelector(".privateMessages").insertAdjacentHTML("afterBegin", element.outerHTML);
  1937. }
  1938. if (StumbleChat.Chat.Selected !== handle) {
  1939. StumbleChat.Chat.Messages.get(handle).missedmsg++;
  1940.  
  1941. PM.querySelector(`[user-id="${handle}"]>.unreadpm`).innerText = StumbleChat.Chat.Messages.get(handle).missedmsg;
  1942. PM.querySelector(`[user-id="${handle}"]>.unreadpm`).classList.add("show");
  1943. }
  1944. }
  1945. let Time = currentTime();
  1946.  
  1947. if (StumbleChat.Chat.Settings.LinksEnabled) message = parseLink(message);
  1948. if (StumbleChat.Chat.Settings.ImgurEnabled) message = parseImgur(message);
  1949.  
  1950. StumbleChat.Chat.Messages.get(handle).message.push({
  1951. "handle": sender,
  1952. "nick": nick,
  1953. "avatar": avatar,
  1954. "msg": message,
  1955. "time": Time,
  1956. namebackgroundcolor: namebackgroundcolor,
  1957. backgroundcolor: backgroundcolor,
  1958. messagetextcolor: messagetextcolor
  1959. });
  1960.  
  1961. if (StumbleChat.Chat.Selected === handle) {
  1962. Message.unread();
  1963. let len = StumbleChat.Chat.Messages.get(handle).message.length - 2;
  1964. if (len >= 0) {
  1965. if (StumbleChat.Chat.Messages.get(handle).message[ len ].nick == nick && StumbleChat.Chat.Messages.get(handle).message[ len ].handle == sender) {
  1966. let element = document.createElement("div");
  1967. element.setAttribute("class", "content");
  1968. element.innerHTML = `<span class="hidden-selectable">[${Time}]</span><span class="timestamp">${Time}</span><span class="message common" style="color:${messagetextcolor}">${message}</span></div>`;
  1969. document.querySelector("#chat-content>.message:last-child").appendChild(element);
  1970. } else {
  1971. createChatItem({
  1972. nick: nick,
  1973. time: Time,
  1974. avatar: avatar,
  1975. msg: message,
  1976. backgroundcolor: backgroundcolor,
  1977. namebackgroundcolor: namebackgroundcolor,
  1978. messagetextcolor: messagetextcolor,
  1979. });
  1980. }
  1981. } else {
  1982. createChatItem({
  1983. nick: nick,
  1984. time: Time,
  1985. avatar: avatar,
  1986. msg: message,
  1987. backgroundcolor: backgroundcolor,
  1988. namebackgroundcolor: namebackgroundcolor,
  1989. messagetextcolor: messagetextcolor,
  1990. });
  1991. }
  1992. StumbleChat.Chat.Scroll();
  1993. }
  1994.  
  1995. if (nick !== StumbleChat.Self.nick && StumbleChat.Chat.Settings.SoundsEnabled) {
  1996. StumbleChat.Chat.Sounds.private_message.pause();
  1997. StumbleChat.Chat.Sounds.private_message.currentTime = 0;
  1998. StumbleChat.Chat.Sounds.private_message.play();
  1999. }
  2000. }
  2001. },
  2002. unread: () => {
  2003. StumbleChat.Chat.Settings.Scroll = (Math.floor(document.getElementById("chat").scrollTop + 50) >= (document.getElementById("chat").scrollHeight - document.getElementById("chat").offsetHeight));
  2004.  
  2005. if (StumbleChat.Chat.Settings.Scroll) {
  2006. StumbleChat.Chat.Status.MissedMsg = 0;
  2007. document.querySelector(".unreadmessage").classList.add("hidden");
  2008. } else {
  2009. StumbleChat.Chat.Status.MissedMsg++;
  2010. document.querySelector(".unreadmessage").classList.remove("hidden");
  2011. document.querySelector(".unreadmessage").innerHTML = "There are " + StumbleChat.Chat.Status.MissedMsg + " unread message(s)!";
  2012. }
  2013. }
  2014. };
  2015.  
  2016. let App = {
  2017. Init: () => {
  2018. window.AudioContext = window.AudioContext || window.webkitAudioContext;
  2019. new window.AudioContext();
  2020. // Prefetch elements commonly used.
  2021. StumbleChat.Userlist.list = document.querySelector("#userlist>.list");
  2022. // Attempts
  2023. StumbleChat.Chat.Status.Resets++;
  2024. if (StumbleChat.Chat.Status.Resets >= 10) return Modal.Create(3, "Cannot connect right now, try to refresh again shortly.");
  2025. if (StumbleChat.Chat.Status.LoadedEventListenersInit == false) App.Listeners();
  2026. if (!StumbleChat.Chat.Status.Kicked) App.Auth();
  2027. },
  2028. Auth: (password) => {
  2029. Modal.Create(2);
  2030.  
  2031. let Token = new XMLHttpRequest();
  2032. Token.open("POST", `https://${window.location.hostname}/api/room/token`);
  2033. Token.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
  2034. Token.setRequestHeader("CSRF-Token", document.getElementsByName('_csrf')[ 0 ].getAttribute("content"));
  2035. Token.onload = () => {
  2036. if (Token.status != 200) return Modal.Create(3, "Server did not respond to our request");
  2037. Modal.Destroy();
  2038. let parse;
  2039. try {
  2040. parse = JSON.parse(Token.responseText);
  2041. } catch (E) {
  2042. parse = null;
  2043. return Modal.Create(3, "You're temporarily blocked");
  2044. }
  2045.  
  2046. if (parse.error != "") return Modal.Create(3, parse.error);
  2047. if (typeof parse.password == "boolean") {
  2048. if (parse.password == false) return App.Socket(parse);
  2049. Modal.Create(15);
  2050. } else {
  2051. Modal.Create(15, parse.password);
  2052. }
  2053. };
  2054. Token.onerror = () => reloadClient();
  2055. Token.send(JSON.stringify({
  2056. name: StumbleChat.Room.name,
  2057. password: password
  2058. }));
  2059. },
  2060. Listeners: () => {
  2061. StumbleChat.Userlist.Menu.Check();
  2062. StumbleChat.Videos.Menu.Check();
  2063. document.getElementById('media-stop').addEventListener('pointerdown', () => {
  2064. StumbleChat.WebSocket.send(`{"stumble":"publish","type":"close"}`);
  2065. Broadcast.unpublish(StumbleChat.Self.handle);
  2066. }, {
  2067. passive: true
  2068. });
  2069. StumbleChat.Chat.Status.LoadedEventListenersInit = true;
  2070. },
  2071. Socket: (parse) => {
  2072. Modal.Create(2);
  2073. StumbleChat.WebSocket = new WebSocket(parse.endpoint);
  2074.  
  2075. StumbleChat.WebSocket.onopen = () => {
  2076. window.wss = StumbleChat.WebSocket;
  2077. Modal.Destroy();
  2078. StumbleChat.Chat.Status.Resets = 0;
  2079.  
  2080. loadStorage();
  2081.  
  2082. let nick = (localStorage.getItem("nick") != null) ? localStorage.getItem("nick") : null;
  2083.  
  2084. if (StumbleChat.Chat.Settings.LargeEmbeddedVideos == true) document.querySelector("#videos").prepend(document.querySelector(`#videos>div:nth-child(2)`));
  2085. if (StumbleChat.Chat.Settings.LargeFont == true) document.querySelector("#chat-content").classList.add("large");
  2086. StumbleChat.WebSocket.send(`{"stumble":"join","token":"${parse.result}","room":"${StumbleChat.Room.name.toLowerCase()}","nick":"${(nick == undefined) ? "" : nick}"}`);
  2087. };
  2088.  
  2089. StumbleChat.WebSocket.onclose = (e) => reloadClient();
  2090. StumbleChat.WebSocket.nextMessage = () => {
  2091. if (SubscribeQueue.splice(0, 1) && SubscribeQueue.length >= 1) Broadcast.subscribe[ SubscribeQueue[ 0 ].type ](SubscribeQueue[ 0 ]);
  2092. };
  2093. StumbleChat.WebSocket.onmessage = (rcv) => {
  2094. try {
  2095. if (rcv.data == 0) StumbleChat.WebSocket.send(0);
  2096. let b = JSON.parse(rcv.data),
  2097. d = b.stumble;
  2098. if (typeof ServerResponse[ d ] === "function") ServerResponse[ b.stumble ](b);
  2099. } catch (e) {
  2100. console.warn(e, rcv.data);
  2101. }
  2102. };
  2103. },
  2104. Clear: () => {
  2105. StumbleChat.WebSocket = null;
  2106. let elem = document.querySelector("#twitchplayer>iframe");
  2107. if (elem !== null) elem.parentNode.removeChild(elem);
  2108. elem = document.querySelector("#worldstarhiphopplayer>video");
  2109. if (elem !== null) elem.parentNode.removeChild(elem);
  2110. elem = document.querySelector("#soundcloudplayer>video");
  2111. if (elem !== null) elem.parentNode.removeChild(elem);
  2112. elem = document.querySelector("#dailymotionplayer>video");
  2113. if (elem !== null) elem.parentNode.removeChild(elem);
  2114. if (window.YouTubePlayer) {
  2115. //document.querySelector("#youtube-volume-slider").value = 100;
  2116. window.YouTubePlayer.destroy();
  2117. window.YouTubePlayer = undefined;
  2118. }
  2119. document.querySelector("#videos > div > .youtube").classList.add("hidden");
  2120. document.querySelector("#videos > div > .twitch").classList.add("hidden");
  2121. document.querySelector("#videos > div > .soundcloud").classList.add("hidden");
  2122. document.querySelector("#videos > div > .dailymotion").classList.add("hidden");
  2123. document.querySelector("#videos > div > .worldstarhiphop").classList.add("hidden");
  2124.  
  2125. document.querySelectorAll(`.privateMessages .nickname`).forEach((value, key) => {
  2126. if (!value.innerText.includes("(offline)")) value.innerText += ` (offline)`;
  2127. });
  2128.  
  2129.  
  2130. if (!StumbleChat.Chat.Settings.isMobile) document.querySelector("#media-screen").classList.add("hidden");
  2131. document.getElementById('media-broadcast').classList.add('hidden');
  2132. document.getElementById('media-settings').classList.add('hidden');
  2133. document.getElementById('media-loading').classList.add('hidden');
  2134. document.getElementById('media-ptt').classList.add('hidden');
  2135. document.getElementById('media-openmic').classList.add('hidden');
  2136. document.getElementById('media-stop').classList.add('hidden');
  2137. document.getElementById('media-stop').classList.remove("no-audio");
  2138.  
  2139. StumbleChat.Userlist.User.forEach((value, key) => {
  2140. let element = document.querySelector(`.bar[user-id="${key}"]`);
  2141. if (element !== undefined) element.remove();
  2142. });
  2143.  
  2144. StumbleChat.Userlist.Broadcast.forEach((user, handle) => Broadcast.unpublish(handle));
  2145.  
  2146. StumbleChat.Userlist.Broadcast = new Map();
  2147. StumbleChat.Userlist.User = new Map();
  2148. StumbleChat.Userlist.Count();
  2149. },
  2150. ChangeNick: () => {
  2151. let nickname = document.getElementById("modal-text-input").value;
  2152. if (nickname.match(/^([a-z0-9_]){1,16}$/i)) {
  2153. for (let value of StumbleChat.Userlist.User) {
  2154. if (value[ 1 ].nick.toUpperCase() === nickname.toUpperCase()) {
  2155. Message.receive.public("This name is already taken, try another one.");
  2156. return;
  2157. }
  2158. }
  2159. if (nickname !== StumbleChat.Self.nick && StumbleChat.Userlist.User) {
  2160. StumbleChat.WebSocket.send(`{"stumble":"nick","nick":"${document.getElementById("modal-text-input").value}"}`);
  2161. Modal.Destroy();
  2162. }
  2163. }
  2164. }
  2165. };
  2166.  
  2167. let Modal = {
  2168. Create: (Type, msg) => {
  2169. Modal.Destroy();
  2170. StumbleChat.Chat.Status.ModalOpened = Type;
  2171. document.getElementById('modal-back').classList.add("visible");
  2172. Modal.Items[ Type ](msg);
  2173. Modal.Center();
  2174. },
  2175. Destroy: () => {
  2176. StumbleChat.Chat.Status.AdjustingQueue = false;
  2177. StumbleChat.Chat.Status.ModalOpened = -1;
  2178. document.getElementById('modal-back').classList.remove('visible');
  2179. document.getElementById('modal-exit').classList.remove('visible');
  2180. //document.querySelector("#textarea").focus();
  2181. },
  2182. Center: () => {
  2183. let el = document.querySelector("#modal");
  2184. if (el) el.style.marginTop = (window.innerHeight - el.offsetHeight) / 2 + 'px';
  2185. },
  2186. Items: {
  2187. 0: () => { // Broadcast Options
  2188. document.getElementById('modal-back').classList.remove("visible");
  2189. document.querySelector("#modal > #title > p").innerHTML = `MEDIA OPTIONS`;
  2190. document.querySelector("#modal > span").innerHTML = `<div id="broadcast-wrapper"><video id="previewvideo" autoplay="" class="hidden" playsinline="">Your browser does not support the video tag...</video><select id="videoSelect"></select><select id="audioSelect"></select><p>FRAMERATE:</p><div class="framerate-wrapper"><input class="framerate-options" type="radio" id="framerate1" name="framerate" value="15" ${(StumbleChat.Chat.Settings.FrameRate == 15) ? 'checked="checked"' : ""}"><label for="framerate1">15</label><input class="framerate-options" type="radio" id="framerate2" name="framerate" value="30" ${(StumbleChat.Chat.Settings.FrameRate == 30) ? 'checked="checked"' : ""}"><label for="framerate2">30</label><input class="framerate-options" type="radio" id="framerate3" name="framerate" value="60" ${(StumbleChat.Chat.Settings.FrameRate == 60) ? 'checked="checked"' : ""}"><label for="framerate3">60</label></div><p>RESOLUTION: </p><div class="resolution-wrapper"><input class="resolution-options" type="radio" id="resolution1" name="resolution" value="0" ${(StumbleChat.Chat.Settings.Resolution == 0) ? 'checked="checked"' : ""}><label for="resolution1">352x240 (240p)</label><br><input class="resolution-options" type="radio" id="resolution2" name="resolution" value="1" ${(StumbleChat.Chat.Settings.Resolution == 1) ? 'checked="checked"' : ""}><label for="resolution2">480x360 (360p)</label><br><input class="resolution-options" type="radio" id="resolution3" name="resolution" value="2" ${(StumbleChat.Chat.Settings.Resolution == 2) ? 'checked="checked"' : ""}><label for="resolution3">858x480 (480p)</label><br><input class="resolution-options" type="radio" id="resolution4" name="resolution" value="3" ${(StumbleChat.Chat.Settings.Resolution == 3) ? 'checked="checked"' : ""}><label for="resolution4">1280x720 (720p)</label> <br><input class="resolution-options" type="radio" id="resolution5" name="resolution" value="4" ${(StumbleChat.Chat.Settings.Resolution == 4) ? 'checked="checked"' : ""}> <label for="resolution5">1920x1080 (1080p)</label> <br><input class="resolution-options" type="radio" id="resolution6" name="resolution" value="5" ${(StumbleChat.Chat.Settings.Resolution == 5) ? 'checked="checked"' : ""}> <label for="resolution6">4096x2160 (4K)</label></div><p>ENHANCEMENTS:</p><div class="enhancement-wrapper"><input type="checkbox" id="enhancement1" name="enhancement" value="echoCancellation" ${(StumbleChat.Chat.Settings.EchoCancellation) ? 'checked="checked"' : ""}><label for="enhancement1">Echo Cancellation</label><br><input type="checkbox" id="enhancement2" name="enhancement" value="autoGainControl" ${(StumbleChat.Chat.Settings.AutoGainControl) ? 'checked="checked"' : ""}><label for="enhancement2">Auto Gain Control</label><br><input type="checkbox" id="enhancement3" name="enhancement" value="noiseSuppression" ${(StumbleChat.Chat.Settings.NoiseSupression) ? 'checked="checked"' : ""}><label for="enhancement3">Noise Supression</label></div><button id='broadcastsettings'>SAVE</button></div>`;
  2191. navigator.mediaDevices.enumerateDevices().then((Devices) => {
  2192. createBroadcastItem(window.videoSelect, StumbleChat.Chat.Settings.videodevice, (StumbleChat.Chat.Settings.videodevice == "NONE" || StumbleChat.Chat.Settings.videodevice == null) ? "NONE" : "Saved Video Device");
  2193. createBroadcastItem(window.audioSelect, StumbleChat.Chat.Settings.audiodevice, (StumbleChat.Chat.Settings.audiodevice == "NONE" || StumbleChat.Chat.Settings.audiodevice == null) ? "NONE" : "Saved Audio Device");
  2194.  
  2195. if (StumbleChat.Chat.Settings.videodevice != "NONE") createBroadcastItem(window.videoSelect, "NONE", "NONE");
  2196. if (StumbleChat.Chat.Settings.audiodevice != "NONE") createBroadcastItem(window.audioSelect, "NONE", "NONE");
  2197. let audiocount = 0;
  2198. let videocount = 0;
  2199. for (let i = 0; i !== Devices.length; ++i) {
  2200. const deviceInfo = Devices[ i ];
  2201. if (deviceInfo.kind === 'audioinput') {
  2202. createBroadcastItem(window.audioSelect, deviceInfo.deviceId, deviceInfo.label || `microphone ${++audiocount}`);
  2203. } else if (deviceInfo.kind === 'videoinput') {
  2204. createBroadcastItem(window.videoSelect, deviceInfo.deviceId, deviceInfo.label || `camera ${++videocount}`);
  2205. }
  2206. }
  2207. if (StumbleChat.Chat.Settings.videodevice != "NONE") previewBroadcast(StumbleChat.Chat.Settings.videodevice);
  2208. }).catch((err) => {
  2209. Message.receive.public(`${err}`);
  2210. });
  2211. document.getElementById('modal-back').classList.add("visible");
  2212. Modal.Center();
  2213. },
  2214. 1: () => { // Compatibility Warning
  2215. document.querySelector("#modal > #title > p").innerHTML = `COMPATIBILITY WARNING`;
  2216. document.querySelector("#modal > span").innerHTML = `You may experience issues with the app, in this case try a different browser!`;
  2217. document.getElementById('modal-exit').classList.add("visible");
  2218. },
  2219. 2: () => { // Connecting
  2220. document.querySelector("#modal > #title > p").innerHTML = `CONNECTING...`;
  2221. document.querySelector("#modal > span").innerHTML = `<div class="lds-roller"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>`;
  2222. },
  2223. 3: (msg) => { // Error
  2224. document.querySelector("#modal > #title > p").innerHTML = `ERROR...`;
  2225. document.querySelector("#modal > span").innerHTML = `${msg}`;
  2226. },
  2227. 4: () => { // Interact (First Time)
  2228. StumbleChat.Chat.Settings.background = parseStorage("background", "#111111");
  2229. StumbleChat.Chat.Settings.backgroundUrl = parseStorage("backgroundUrl", "");
  2230. StumbleChat.Chat.Settings.chatcolor = parseStorage("chatcolor", "#000000");
  2231. StumbleChat.Chat.Background.Load();
  2232. StumbleChat.Chat.Color.Load();
  2233. document.querySelector("#modal > #title > p").innerHTML = `VERIFY...`;
  2234. document.querySelector("#modal > span").innerHTML = `<button id='interact'>VERIFY</button>`;
  2235. },
  2236. 5: () => { // Change Nickname
  2237. document.querySelector("#modal > #title > p").innerHTML = `HELLO MY NAME IS`;
  2238. document.querySelector("#modal > span").innerHTML = `<form action="javascript:void(0);" autocomplete="off"><input id="modal-text-input" placeholder="${StumbleChat.Self.nick}" title="Accepted Character Range: a-z, A-Z, _, and 0-9 between 1 to 16 characters" pattern="^[A-Za-z0-9_]{1,16}$" type="text"></input><input type="submit"value="Set" id='change-nick'></input></form>`;
  2239.  
  2240. document.querySelector("#modal-text-input").focus();
  2241. document.getElementById('modal-exit').classList.add("visible");
  2242. },
  2243. 6: (msg) => { // Broadcast password
  2244. document.querySelector("#modal > #title > p").innerHTML = `Broadcast Password`;
  2245. document.querySelector("#modal > span").innerHTML = `<form action="javascript:void(0);" autocomplete="off"><input id="modal-text-hidden" type="text" value="${msg}" hidden><input id="modal-text-input" placeholder="Password" autocomplete="off" value="${(StumbleChat.Videos.Password !== undefined) ? StumbleChat.Videos.Password : ""}"></input><input type="submit" value="Submit" id='broadcastpassword'></input></form>`;
  2246. document.getElementById('modal-exit').classList.add("visible");
  2247. document.querySelector("#modal-text-input").focus();
  2248. },
  2249. 7: (msg) => { // YouTube Search
  2250. StumbleChat.Chat.Status.AdjustingQueue = true;
  2251. document.querySelector("#modal > #title > p").innerHTML = `YouTube Search`;
  2252. let Playlist = ``;
  2253. for (let i = 0; i < msg.length; i++) {
  2254. if (i === 0) {
  2255. Playlist += `<br><br><h1>PLAYING</h1><ul><li class="youtubelist" id="${msg[ i ].queueid}"><img class="youtube_thumbnail" src="${msg[ i ].thumbnail}" alt="YouTube Thumbnail"><span class="close">x</span><p class="youtube_title">${msg[ i ].title}</p><p class="youtube_title">Username: ${msg[ i ].username} | Duration: ${new Date(msg[ i ].duration * 1000).toISOString().substr(11, 8)}</p></li></ul>`;
  2256. if (msg.length > 1) Playlist += `<h1>UP NEXT</h1><ul id="youtuberemove" name="moderatorlist">`;
  2257. }
  2258. if (i !== 0) {
  2259. Playlist += `<li class="youtubelist" id="${msg[ i ].queueid}"><img class="youtube_thumbnail" src="${msg[ i ].thumbnail}" alt="YouTube Thumbnail"><span class="close">x</span><p class="youtube_title">${msg[ i ].title}</p><p class="youtube_title">Username: ${msg[ i ].username} | Duration: ${new Date(msg[ i ].duration * 1000).toISOString().substr(11, 8)}</p></li>`;
  2260. if (i == msg.length) Playlist += `</ul>`;
  2261. }
  2262. }
  2263. document.querySelector("#modal > span").innerHTML = `<form action="javascript:void(0);" autocomplete="off"><input id="modal-text-input" placeholder="Link/Keyword Search" type="text"></input><input type="submit" value="Submit" id='search'></input> ${Playlist} </form>`;
  2264. document.querySelector("#modal-text-input").focus();
  2265. document.getElementById('modal-exit').classList.add("visible");
  2266. },
  2267. 8: (msg) => { // ATTENTION / NOTICE
  2268. document.querySelector("#modal > #title > p").innerHTML = `ATTENTION...`;
  2269. document.querySelector("#modal > span").innerHTML = `${msg}`;
  2270. },
  2271. 9: (msg) => { // Ban List
  2272. document.querySelector("#modal > #title > p").innerHTML = `Ban List`;
  2273. let List = ``;
  2274. msg.forEach((value, index) => List += `<li class="banlist" user-id="${value[ 0 ]}" username="${value[ 1 ]}">${value[ 1 ]}<span class="close">x</span></li>`);
  2275. document.querySelector("#modal > span").innerHTML = `<form action="javascript:void(0);" autocomplete="off"><ul id="banremove" name="moderatorlist"> ${(List == '') ? `<li class="banlist">LIST IS EMPTY</li>` : List} </ul></form>`;
  2276. document.getElementById('modal-exit').classList.add("visible");
  2277. },
  2278. 10: () => { // User Options
  2279. document.querySelector("#modal > #title > p").innerHTML = `Client Settings`;
  2280. document.querySelector("#modal > span").innerHTML =
  2281. `<div class="optionside">
  2282. <label class="switch">
  2283. <input type="checkbox" ${(StumbleChat.Chat.Settings.SoundmeterEnabled == true) ? `checked` : ``}>
  2284. <span id="soundmeter" class="slider round"></span>
  2285. </label>
  2286. <h2>Soundmeter:</h2>
  2287. </div>
  2288. <h3>Track broadcast audio levels.</h3>
  2289. <hr>
  2290. <div class="optionside">
  2291. <label class="switch">
  2292. <input type="checkbox" ${(StumbleChat.Chat.Settings.YouTubeEnabled == true) ? `checked` : ``}>
  2293. <span id="youtube" class="slider round"></span>
  2294. </label>
  2295. <h2>YouTube:</h2>
  2296. </div>
  2297. <h3>Watch YouTube embeds.</h3>
  2298. <hr>
  2299. <div class="optionside">
  2300. <label class="switch">
  2301. <input type="checkbox" ${(StumbleChat.Chat.Settings.TwitchEnabled == true) ? `checked` : ``}>
  2302. <span id="twitch" class="slider round"></span>
  2303. </label>
  2304. <h2>Twitch:</h2>
  2305. </div>
  2306. <h3>Watch Twitch embeds.</h3>
  2307. <hr>
  2308. <div class="optionside">
  2309. <label class="switch">
  2310. <input type="checkbox" ${(StumbleChat.Chat.Settings.WSHHEnabled == true) ? `checked` : ``}>
  2311. <span id="wshh" class="slider round"></span>
  2312. </label>
  2313. <h2>WSHH:</h2>
  2314. </div>
  2315. <h3>Watch WSHH embeds.</h3>
  2316. <hr>
  2317. <div class="optionside">
  2318. <label class="switch">
  2319. <input type="checkbox" ${(StumbleChat.Chat.Settings.DailyMotionEnabled == true) ? `checked` : ``}>
  2320. <span id="dailymotion" class="slider round"></span>
  2321. </label>
  2322. <h2>DailyMotion:</h2>
  2323. </div>
  2324. <h3>Watch DailyMotion embeds.</h3>
  2325. <hr>
  2326. <div class="optionside">
  2327. <label class="switch">
  2328. <input type="checkbox" ${(StumbleChat.Chat.Settings.SoundCloudEnabled == true) ? `checked` : ``}>
  2329. <span id="soundcloud" class="slider round"></span>
  2330. </label>
  2331. <h2>SoundCloud:</h2>
  2332. </div>
  2333. <h3>Watch SoundCloud embeds.</h3>
  2334. <hr>
  2335. <div class="optionside">
  2336. <label class="switch">
  2337. <input type="checkbox" ${(StumbleChat.Chat.Settings.PrivateMessageEnabled == true) ? `checked` : ``}>
  2338. <span id="pm" class="slider round"></span>
  2339. </label>
  2340. <h2>PMs:</h2>
  2341. </div>
  2342. <h3>Allow private messages from other users.</h3>
  2343. <hr>
  2344. <div class="optionside">
  2345. <label class="switch">
  2346. <input type="checkbox" ${(StumbleChat.Chat.Settings.SoundsEnabled == true) ? `checked` : ``}>
  2347. <span id="sounds" class="slider round"></span>
  2348. </label>
  2349. <h2>Chat Sounds:</h2>
  2350. </div>
  2351. <h3>Get audio alerts when there's a message.</h3>
  2352. <hr>
  2353. <div class="optionside">
  2354. <label class="switch">
  2355. <input type="checkbox" ${(StumbleChat.Chat.Settings.ImgurEnabled == true) ? `checked` : ``}>
  2356. <span id="imgur" class="slider round"></span>
  2357. </label>
  2358. <h2>Imgur:</h2>
  2359. <h3>Show Imgur images/videos posted by other users in the chat.</h3>
  2360. </div>
  2361. <hr>
  2362. <div class="optionside">
  2363. <label class="switch">
  2364. <input type="checkbox" ${(StumbleChat.Chat.Settings.LinksEnabled == true) ? `checked` : ``}>
  2365. <span id="links" class="slider round"></span>
  2366. </label>
  2367. <h2>Links:</h2>
  2368. <h3>Show links posted by other users.</h3>
  2369. </div>`;
  2370. document.getElementById('modal-exit').classList.add("visible");
  2371. },
  2372. 11: (msg) => { // User Profile
  2373. document.querySelector("#modal > #title > p").innerHTML = `${msg.username}`;
  2374. let date = new Date(msg.created);
  2375. document.querySelector("#modal > span").innerHTML = ` <div class="card"><p class="age">CREATED: ${date.toLocaleDateString("en-US")}</p><img src="${(msg.avatar == undefined) ? "/styles/images/no-background.png" : `/profile/${msg.username.toLowerCase()}/cached/large_avatar.jpg`}" style="width:180px; height:100px;margin:0 auto;" alt="Avatar"><p class="age">AGE: ${msg.age}</p><p class="title">${(msg.description !== null) ? msg.description : "No Description"}</p><br><p>Subscription: ${msg.subscription} | Coins: ${msg.coins}</p></div>`;
  2376. document.getElementById('modal-exit').classList.add("visible");
  2377. },
  2378. 12: () => { // Twitch Search
  2379. document.querySelector("#modal > #title > p").innerHTML = `Twitch Search`;
  2380. document.querySelector("#modal > span").innerHTML = `<form action="javascript:void(0);" autocomplete="off"><input id="modal-text-input" placeholder="Channel" type="text"></input><input type="submit" id='twitch-close' value="Stop"></input><input type="submit" value="Submit" id='searchtwitch'></input></form>`;
  2381. document.querySelector("#modal-text-input").focus();
  2382. document.getElementById('modal-exit').classList.add("visible");
  2383. },
  2384. 13: () => { // Topic
  2385. document.querySelector("#modal > #title > p").innerHTML = `TOPIC`;
  2386. document.querySelector("#modal > span").innerText = (StumbleChat.Room.topic) ? `${StumbleChat.Room.topic}` : `No Topic`;
  2387. document.getElementById('modal-exit').classList.add("visible");
  2388. },
  2389. 14: () => { // Chat Color
  2390. let currentcolor = "";
  2391. if (StumbleChat.Chat.Settings.background.match(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/) !== null || StumbleChat.Chat.Settings.background.match(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/) !== null) currentcolor = `value="${StumbleChat.Chat.Settings.background}"`;
  2392. document.querySelector("#modal > #title > p").innerHTML = `Theme Settings`;
  2393. document.querySelector("#modal > span").innerHTML =
  2394. `<p>Chat Color:</p>
  2395. <br>
  2396. <form action="javascript:void(0);" autocomplete="off">
  2397. <input id="modal-color-input" value="${StumbleChat.Chat.Settings.chatcolor}" type="color"></input>
  2398. <input style="width:46px;" type="submit" id='resetchatcolor' value="Reset"></input>
  2399. <input style="width:54px;" type="submit" id='setchatcolor' value="Set"></input>
  2400. </form>
  2401. <hr>
  2402. <p>Background URL/Color:</p>
  2403. <br>
  2404. <br>
  2405. <form action="javascript:void(0);" autocomplete="off">
  2406. <input id="modal-text-input" placeholder="${StumbleChat.Chat.Settings.backgroundUrl == "" ? "Image Url" : StumbleChat.Chat.Settings.backgroundUrl}" type="text"></input>
  2407. <input type="color" id='modal-bgcolor-input' ${currentcolor}></input>
  2408. <input style="width:46px;" type="submit" id='resetbackground' value="Reset"></input>
  2409. <input style="width:54px;" type="submit" id='setbackground' value="Set"></input>
  2410. </form>
  2411. <hr>
  2412. <div class="optionside">
  2413. <label class="switch">
  2414. <input type="checkbox" ${(StumbleChat.Chat.Settings.LargeEmbeddedVideos == true) ? `checked` : ``}>
  2415. <span id="largeembeddedvideos" class="slider round"></span>
  2416. </label>
  2417. <h2>Large Embedded Videos:</h2>
  2418. </div>
  2419. <h3>Change size of broadcasts and embedded videos.</h3>
  2420. <hr>
  2421. <div class="optionside">
  2422. <label class="switch">
  2423. <input type="checkbox" ${(StumbleChat.Chat.Settings.LargeFont == true) ? `checked` : ``}>
  2424. <span id="largefont" class="slider round"></span>
  2425. </label>
  2426. <h2>Large Font:</h2>
  2427. </div>
  2428. <h3>Adjust font size.</h3>`;
  2429. document.getElementById('modal-exit').classList.add("visible");
  2430. },
  2431. 15: (msg) => { // Room password
  2432. msg = (msg) ? `<div class="warning-label">${msg}</div>` : ``;
  2433. document.querySelector("#modal > #title > p").innerHTML = `Room Password`;
  2434. document.querySelector("#modal > span").innerHTML = `<form action="javascript:void(0);" autocomplete="off">${msg}<input id="modal-text-input" placeholder="${(StumbleChat.Chat.Password == undefined) ? "Password" : StumbleChat.Chat.Password}" autocomplete="off" value="${(StumbleChat.Chat.Password !== undefined) ? StumbleChat.Chat.Password : ""}"></input><input type="submit" value="Set" id='roompassword'></input></form>`;
  2435. document.querySelector("#modal-text-input").focus();
  2436. },
  2437. 16: () => { // worldstarhiphop
  2438. document.querySelector("#modal > #title > p").innerHTML = `WSHH Search`;
  2439. document.querySelector("#modal > span").innerHTML = `<form action="javascript:void(0);" autocomplete="off"><input id="modal-text-input" placeholder="URL" type="text"></input><input type="submit" id='worldstarhiphop-close' value="Stop"></input><input type="submit" value="Submit" id='searchworldstarhiphop'></input></form>`;
  2440. document.querySelector("#modal-text-input").focus();
  2441. document.getElementById('modal-exit').classList.add("visible");
  2442. },
  2443. 17: () => { // worldstarhiphop
  2444. document.querySelector("#modal > #title > p").innerHTML = `SoundCloud Search`;
  2445. document.querySelector("#modal > span").innerHTML = `<form action="javascript:void(0);" autocomplete="off"><input id="modal-text-input" placeholder="URL" type="text"></input><input type="submit" id='soundcloud-close' value="Stop"></input><input type="submit" value="Submit" id='searchsoundcloud'></input></form>`;
  2446. document.querySelector("#modal-text-input").focus();
  2447. document.getElementById('modal-exit').classList.add("visible");
  2448. },
  2449. 18: () => { // dailymotion
  2450. document.querySelector("#modal > #title > p").innerHTML = `DailyMotion Search`;
  2451. document.querySelector("#modal > span").innerHTML = `<form action="javascript:void(0);" autocomplete="off"><input id="modal-text-input" placeholder="URL" type="text"></input><input type="submit" id='dailymotion-close' value="Stop"></input><input type="submit" value="Submit" id='searchdailymotion'></input></form>`;
  2452. document.querySelector("#modal-text-input").focus();
  2453. document.getElementById('modal-exit').classList.add("visible");
  2454. },
  2455. 19: () => { // Room Options
  2456. document.querySelector("#modal > #title > p").innerHTML = `Room Options`;
  2457. document.querySelector("#modal > span").innerHTML = `
  2458. <p>Room Topic:</p>
  2459. <br><br>
  2460. <form action="javascript:void(0);" autocomplete="off">
  2461. <input id="room-topic" placeholder="Topic" type="text"></input>
  2462. <input type="submit" value="Set" id='changeroomtopic' style="width:54px;"></input>
  2463. </form>
  2464. <hr>
  2465. <p>Broadcast Password:</p>
  2466. <br><br>
  2467. <form action="javascript:void(0);" autocomplete="off">
  2468. <input id="broadcast-password" placeholder="Password" autocomplete="off"></input>
  2469. <input type="submit" id='broadcast-password-clear' value="Clear" style="width:44px;">
  2470. <input type="submit" id='changebroadcastpassword' value="Set" style="width:54px;"></input>
  2471. </form>`;
  2472.  
  2473. if (StumbleChat.Self.mod >= 4) document.querySelector("#modal > span").innerHTML += `
  2474. <hr><div class="optionside">
  2475. <label class="switch">
  2476. <input type="checkbox" ${(StumbleChat.Room.guests_allowed == true) ? `checked` : ``}>
  2477. <span id="guestsallowed" class="slider round"></span>
  2478. </label>
  2479. <h2>Guests:</h2>
  2480. </div>
  2481. <h3>Allow unregistered users to enter the room.</h3>
  2482. <hr>
  2483. <div class="optionside">
  2484. <label class="switch">
  2485. <input type="checkbox" ${(StumbleChat.Room.public == true) ? `checked` : ``}>
  2486. <span id="publicroom" class="slider round"></span>
  2487. </label>
  2488. <h2>List room in directory:</h2>
  2489. </div>
  2490. <h3>Be found on our directory page by users browsing the rooms.</h3>`;
  2491.  
  2492. document.querySelector("#modal > span").innerHTML += `
  2493. <hr><div class="optionside">
  2494. <label class="switch">
  2495. <input type="checkbox" ${(StumbleChat.Room.greenroom == true) ? `checked` : ``}>
  2496. <span id="greenroom" class="slider round"></span>
  2497. </label>
  2498. <h2>Greenroom:</h2>
  2499. </div>
  2500. <h3>Enable a waiting area where you can moderate and choose who can broadcast.</h3>`;
  2501. document.getElementById('modal-exit').classList.add("visible");
  2502. },
  2503.  
  2504. 20: () => { // Permission Check
  2505. document.querySelector("#modal > #title > p").innerHTML = `GATHERING PERMISSIONS`;
  2506. document.querySelector("#modal > span").innerHTML = `Some devices for video to automatically play, the user must accept the prompt requesting camera access.`;
  2507. },
  2508.  
  2509. 21: () => { // Permission Failed
  2510. document.querySelector("#modal > #title > p").innerHTML = `MISSING PERMISSIONS`;
  2511. document.querySelector("#modal > span").innerHTML = `Some devices for video to automatically play, the user must accept the prompt requesting camera access.`;
  2512. },
  2513. }
  2514. };
  2515.  
  2516. let Media = {
  2517. YouTube: {
  2518. Add: () => {
  2519. let VideoID = document.getElementById("modal-text-input").value.match(/(?:www\.|https:\/\/)?(?:www\.|m\.)?youtu(?:be\.com\/v\/|be\.com\/watch\?v\=|\/v\=|be\.com\/embed\/|\.be\/)([A-Za-z0-9_\-]{11})(?:\?t=([0-9]{1,6}))?/i);
  2520. if (VideoID !== null) {
  2521. if (VideoID[ 1 ] !== undefined) {
  2522. StumbleChat.WebSocket.send(JSON.stringify({
  2523. "stumble": "youtube",
  2524. "type": "add",
  2525. "id": VideoID[ 1 ],
  2526. "time": (VideoID[ 2 ] !== undefined) ? VideoID[ 2 ] : 0
  2527. }));
  2528. Modal.Destroy();
  2529. }
  2530. } else {
  2531. let keywordsearch = document.getElementById("modal-text-input").value;
  2532. if (keywordsearch !== "") {
  2533. StumbleChat.WebSocket.send(JSON.stringify({
  2534. "stumble": "youtube",
  2535. "type": "add",
  2536. "id": keywordsearch,
  2537. "time": 0
  2538. }));
  2539. Modal.Destroy();
  2540. }
  2541. }
  2542. },
  2543. Stop: (text) => {
  2544. if (window.YouTubePlayer !== undefined) window.YouTubePlayer.stopVideo();
  2545. if (text != undefined) Message.receive.public(text);
  2546. document.querySelector("#videos > div > .youtube").classList.add("hidden");
  2547. StumbleChat.Videos.Update();
  2548.  
  2549. if (StumbleChat.Chat.Status.AdjustingQueue) setTimeout(() => StumbleChat.WebSocket.send(`{"stumble": "youtube","type": "playlist"}`), 500);
  2550. },
  2551. Ready: (event) => {
  2552. let b = setInterval(() => StumbleChat.Videos.Update(), 4);
  2553. event.target.playVideo();
  2554. document.querySelector("#youtube-volume-slider").classList.remove("hidden");
  2555. StumbleChat.Videos.Update();
  2556. setTimeout(() => clearInterval(b), 800);
  2557. },
  2558. onPlayerStateChange: (event) => {
  2559. let b = setInterval(() => StumbleChat.Videos.Update(), 4);
  2560. if (event.data == -1) {
  2561. StumbleChat.Chat.Settings.YouTubePausedTime = new Date();
  2562. StumbleChat.Chat.Settings.YouTubeClicked = false;
  2563. }
  2564. if (event.data == 1 && !StumbleChat.Chat.Settings.YouTubeClicked) {
  2565. window.YouTubePlayer.seekTo(StumbleChat.Chat.Settings.YouTubeStartTime + (Math.floor((new Date() - StumbleChat.Chat.Settings.YouTubePausedTime) / 1000)));
  2566. StumbleChat.Chat.Settings.YouTubeClicked = true;
  2567. }
  2568. setTimeout(() => clearInterval(b), 800);
  2569. }
  2570. },
  2571. Twitch: {
  2572. Add: () => {
  2573. let Channel = document.getElementById("modal-text-input").value;
  2574. if (Channel.match(/^[a-zA-Z0-9_]{3,24}$/i) !== null) {
  2575. StumbleChat.WebSocket.send(JSON.stringify({
  2576. "stumble": "twitch",
  2577. "type": "play",
  2578. "name": Channel
  2579. }));
  2580. Modal.Destroy();
  2581. }
  2582. },
  2583. Stop: () => {
  2584. if (StumbleChat.Chat.Status.Playing.Twitch) {
  2585. document.querySelector("#videos > div > .twitch").classList.add("hidden");
  2586. StumbleChat.WebSocket.send(JSON.stringify({
  2587. "stumble": "twitch",
  2588. "type": "stop"
  2589. }));
  2590. StumbleChat.Videos.Update();
  2591. }
  2592. }
  2593. },
  2594. WSHH: {
  2595. Add: () => {
  2596. let URL = document.getElementById("modal-text-input").value;
  2597. if (URL.match(/^(?:https:\/\/(?:worldstarhiphop|worldstar)\.com\/videos\/)([a-z0-9]{20})/i) !== null) {
  2598. StumbleChat.WebSocket.send(JSON.stringify({
  2599. "stumble": "wshh",
  2600. "type": "play",
  2601. "url": URL
  2602. }));
  2603. Modal.Destroy();
  2604. }
  2605. },
  2606. Stop: () => {
  2607. if (StumbleChat.Chat.Status.Playing.WSSH) {
  2608. document.querySelector("#videos > div > .worldstarhiphop").classList.add("hidden");
  2609. StumbleChat.WebSocket.send(JSON.stringify({
  2610. "stumble": "wshh",
  2611. "type": "stop"
  2612. }));
  2613. StumbleChat.Videos.Update();
  2614. }
  2615. }
  2616. },
  2617. DailyMotion: {
  2618. Add: () => {
  2619. let URL = document.getElementById("modal-text-input").value;
  2620. if (URL.match(/^(?:(?:http|https):\/\/)?(?:www.)?(dailymotion\.com|dai\.ly)\/((video\/([^_]+))|(hub\/([^_]+)|([^\/_]+)))$/i) !== null) {
  2621. StumbleChat.WebSocket.send(JSON.stringify({
  2622. "stumble": "dailymotion",
  2623. "type": "play",
  2624. "url": URL
  2625. }));
  2626. Modal.Destroy();
  2627. }
  2628. },
  2629. Stop: () => {
  2630. if (StumbleChat.Chat.Status.Playing.DailyMotion) {
  2631. document.querySelector("#videos > div > .dailymotion").classList.add("hidden");
  2632. StumbleChat.WebSocket.send(JSON.stringify({
  2633. "stumble": "dailymotion",
  2634. "type": "stop"
  2635. }));
  2636. StumbleChat.Videos.Update();
  2637. }
  2638. }
  2639. },
  2640. SoundCloud: {
  2641. Add: () => {
  2642. let URL = document.getElementById("modal-text-input").value;
  2643. if (URL.match(/((https:\/\/)|(http:\/\/)|(www.)|(m\.)|(\s))+(soundcloud.com\/)+[a-zA-Z0-9\-\.]+(\/)+[a-zA-Z0-9\-\.]+/i) !== null) {
  2644. StumbleChat.WebSocket.send(JSON.stringify({
  2645. "stumble": "soundcloud",
  2646. "type": "play",
  2647. "url": URL
  2648. }));
  2649. Modal.Destroy();
  2650. }
  2651. },
  2652. Stop: () => {
  2653. if (StumbleChat.Chat.Status.Playing.SoundCloud) {
  2654. document.querySelector("#videos > div > .soundcloud").classList.add("hidden");
  2655. StumbleChat.WebSocket.send(JSON.stringify({
  2656. "stumble": "soundcloud",
  2657. "type": "stop"
  2658. }));
  2659. StumbleChat.Videos.Update();
  2660. }
  2661. }
  2662. }
  2663. };
  2664.  
  2665. window.onload = () => {
  2666. document.getElementById("textarea").disabled = true;
  2667. if (window.innerWidth > 652) {
  2668. document.querySelector(".resizechat").classList.remove("hidden");
  2669. document.querySelector(".resizeuser").classList.remove("hidden");
  2670. StumbleChat.Userlist.Resizable = true;
  2671. StumbleChat.Chat.Resizable = true;
  2672. }
  2673. window.onresize = () => {
  2674. StumbleChat.Userlist.Menu.Hide();
  2675. StumbleChat.Videos.Menu.Hide();
  2676. StumbleChat.Userlist.Resize();
  2677. StumbleChat.Chat.Resize();
  2678. Modal.Center();
  2679. StumbleChat.Videos.Update();
  2680. };
  2681.  
  2682. if (!CheckCompatibility.WebSocket() || !CheckCompatibility.Device()) return Modal.Create(1);
  2683. if (CheckCompatibility.Storage()) StumbleChat.Chat.Settings.SaveEnabled = true;
  2684.  
  2685. StumbleChat.Userlist.Resize();
  2686.  
  2687. StumbleChat.Chat.Settings.RoomVolume = parseStorage('RoomVolume', 100);
  2688.  
  2689. StumbleChat.Chat.Sounds.public_message.volume = (StumbleChat.Chat.Settings.RoomVolume / 100);
  2690. StumbleChat.Chat.Sounds.private_message.volume = (StumbleChat.Chat.Settings.RoomVolume / 100);
  2691. StumbleChat.Chat.Settings.isMobile = CheckCompatibility.MouseSupport("touchend");
  2692.  
  2693. document.addEventListener("contextmenu", (e) => {
  2694. if (e.target.id == "userlist" || e.target.id == "embeddedvideos" || e.target.id == "videos" || e.target.id == "regularvideos ") e.preventDefault();
  2695. });
  2696.  
  2697. document.querySelector(".RoomVolume").setAttribute("value", StumbleChat.Chat.Settings.RoomVolume);
  2698.  
  2699. StumbleChat.Userlist.Menu.Element = document.querySelector("#user-menu");
  2700. StumbleChat.Userlist.Menu.State = 0;
  2701. StumbleChat.Videos.Menu.Element = document.querySelector("#video-menu");
  2702. StumbleChat.Videos.Menu.State = 0;
  2703.  
  2704. document.getElementById("textarea").addEventListener("keypress", Message.send, { passive: false });
  2705.  
  2706. window.addEventListener("keypress", (event) => {
  2707. if (event.defaultPrevented) return;
  2708. if (event.key == "Enter" || event.code == "Enter") {
  2709. switch (StumbleChat.Chat.Status.ModalOpened) {
  2710. case 0:
  2711. saveBroadcast();
  2712. break;
  2713. case 5:
  2714. App.ChangeNick();
  2715. break;
  2716. case 6:
  2717. Modal.Destroy();
  2718. StumbleChat.Videos.Password = document.querySelector("#modal-text-input").value;
  2719. if (document.querySelector("#modal-text-hidden").value == 0) {
  2720. requestBroadcast(StumbleChat.Videos.Password);
  2721. } else if (document.querySelector("#modal-text-hidden").value == 1) {
  2722. requestScreenshare(StumbleChat.Videos.Password);
  2723. }
  2724. break;
  2725. case 7:
  2726. Media.YouTube.Add();
  2727. break;
  2728. case 9:
  2729. case 10:
  2730. case 11:
  2731. case 13:
  2732. Modal.Destroy();
  2733. break;
  2734. case 12:
  2735. Media.Twitch.Add();
  2736. break;
  2737. case 15:
  2738. StumbleChat.Chat.Password = document.querySelector("#modal-text-input").value;
  2739. App.Auth(document.querySelector("#modal-text-input").value);
  2740. break;
  2741. case 16:
  2742. Media.WSHH.Add();
  2743. break;
  2744. case 17:
  2745. Media.SoundCloud.Add();
  2746. break;
  2747. case 18:
  2748. Media.DailyMotion.Add();
  2749. break;
  2750. }
  2751. if (StumbleChat.Chat.Status.ModalOpened > -1) event.preventDefault();
  2752. }
  2753. }, { passive: true });
  2754.  
  2755. document.getElementById("chat").addEventListener("scroll", (event) => {
  2756. if (Math.floor(event.target.scrollTop + 50) >= (event.target.scrollHeight - event.target.offsetHeight)) Message.unread(true);
  2757. }, {
  2758. passive: true
  2759. });
  2760.  
  2761. document.getElementById("media-settings").addEventListener("pointerdown", () => Modal.Create(0), {
  2762. passive: true
  2763. });
  2764.  
  2765. document.getElementById("media-broadcast").addEventListener("pointerdown", () => {
  2766. if (StumbleChat.Chat.Settings.videodevice != "NONE" || StumbleChat.Chat.Settings.audiodevice != "NONE") {
  2767. if (StumbleChat.Room.broadcast_password == true) {
  2768. Modal.Create(6, 0);
  2769. } else {
  2770. requestBroadcast(StumbleChat.Videos.Password);
  2771. }
  2772. } else {
  2773. Message.receive.public(`You need to select an audio and/ or video device to use.`);
  2774. Modal.Create(0);
  2775. }
  2776. }, {
  2777. passive: true
  2778. });
  2779.  
  2780. document.getElementById("media-screen").addEventListener("pointerdown", () => {
  2781. if (!StumbleChat.Userlist.Broadcast.has(StumbleChat.Self.handle)) {
  2782. if (StumbleChat.Room.broadcast_password == true) {
  2783. Modal.Create(6, 1);
  2784. } else {
  2785. requestScreenshare();
  2786. }
  2787. }
  2788. }, {
  2789. passive: true
  2790. });
  2791.  
  2792. window.addEventListener("pointerdown", (event) => {
  2793. if (event.target.id == "media-ptt") {
  2794. if (StumbleChat.Userlist.Broadcast.has(StumbleChat.Self.handle)) {
  2795. if (StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).audio !== undefined) {
  2796. event.target.innerText = "TALKING...";
  2797. StumbleChat.Videos.AudioPaused = false;
  2798. StumbleChat.Videos.AudioAwaitingPause = true;
  2799. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).audio.resume();
  2800. }
  2801. }
  2802. }
  2803.  
  2804. }, {
  2805. passive: true
  2806. });
  2807.  
  2808. window.addEventListener("pointerup", (event) => {
  2809. // Audio Control
  2810. event.preventDefault();
  2811. if (!StumbleChat.Videos.AudioPaused && StumbleChat.Userlist.Broadcast.has(StumbleChat.Self.handle) && StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).audio !== null) muteBroadcast();
  2812.  
  2813. if (event.target.classList.contains("closepm")) {
  2814. let handle = event.target.parentElement.attributes[ "user-id" ].value;
  2815. if (StumbleChat.Chat.Selected === handle) {
  2816. document.querySelector(".unreadmessage").classList.add("hidden");
  2817.  
  2818. StumbleChat.Chat.Selected = 0;
  2819.  
  2820. document.querySelector("#chat-position>#back").classList.remove("show");
  2821. document.getElementById("chat-content").innerHTML = "";
  2822. StumbleChat.Chat.Messages.get(0).forEach((value, index) => {
  2823. if (index > 0) {
  2824. if (StumbleChat.Chat.Messages.get(0)[ index - 1 ].username == value.username && value.username != undefined && value.nick == StumbleChat.Chat.Messages.get(0)[ index - 1 ].nick) {
  2825. let element = document.createElement("div");
  2826. element.setAttribute("class", "content");
  2827. element.innerHTML = `<span class="hidden-selectable">[ ${value.time} ]</span><span class="timestamp">${value.time}</span><span class="message common" style="color:${value.messagetextcolor}">${value.msg}</span></div> `;
  2828. document.querySelector("#chat-content>.message:last-child").appendChild(element);
  2829. } else {
  2830. createChatItem(value);
  2831. }
  2832. } else {
  2833. createChatItem(value);
  2834. }
  2835. });
  2836. StumbleChat.Chat.Scroll();
  2837. document.querySelector("#textarea").focus();
  2838. }
  2839. event.target.parentElement.parentElement.remove();
  2840.  
  2841. if (document.querySelector(`.privateMessages > div > span`) === null) {
  2842. document.querySelector(`#userlist > h2:nth-child(2)`).classList.add(`hidden`);
  2843. document.querySelector(`#userlist > .privateMessages`).classList.add(`hidden`);
  2844. }
  2845. } else if (event.target.classList.contains("private")) {
  2846. let handle = event.target.attributes[ "user-id" ].value;
  2847. if (StumbleChat.Chat.Selected !== handle) document.querySelector(".unreadmessage").classList.add("hidden");
  2848.  
  2849. StumbleChat.Chat.Selected = handle;
  2850. if (StumbleChat.Chat.Messages.has(handle)) {
  2851. document.querySelector("#chat-position>#back").classList.add("show");
  2852. document.querySelector("#chat-position>#back").innerHTML = `&#8249; ${StumbleChat.Chat.Messages.get(handle).nick} (${StumbleChat.Chat.Messages.get(handle).username})`;
  2853. document.getElementById("chat-content").innerHTML = "";
  2854.  
  2855. let PM = document.querySelector(`.privateMessages > div > span[ user-id="${handle}"]`);
  2856. if (document.querySelector(`.selected`)) document.querySelector(`.selected`).classList.remove("selected");
  2857.  
  2858. PM.classList.add("selected");
  2859. StumbleChat.Chat.Messages.get(handle).missedmsg = 0;
  2860. PM.querySelector(".unreadpm").innerText = StumbleChat.Chat.Messages.get(handle).missedmsg;
  2861. PM.querySelector(".unreadpm").classList.remove("show");
  2862. StumbleChat.Chat.Messages.get(handle).message.forEach((value, index) => {
  2863. if (index > 0) {
  2864. if (value.nick == StumbleChat.Chat.Messages.get(handle).message[ index - 1 ].nick && value.handle == StumbleChat.Chat.Messages.get(handle).message[ index - 1 ].handle) {
  2865. let element = document.createElement("div");
  2866. element.setAttribute("class", "content");
  2867. element.innerHTML = `<span class="hidden-selectable">[ ${value.time} ]</span><span class="timestamp">${value.time}</span><span class="message common" style="color:${value.messagetextcolor}">${value.msg}</span></div> `;
  2868. document.querySelector("#chat-content>.message:last-child").appendChild(element);
  2869. } else {
  2870. createChatItem(value);
  2871. }
  2872. } else {
  2873. createChatItem(value);
  2874. }
  2875. });
  2876.  
  2877. StumbleChat.Chat.Scroll();
  2878. document.querySelector("#textarea").focus();
  2879. }
  2880. } else if (event.target.id == "back") {
  2881. event.preventDefault();
  2882. let PM = document.querySelector(`.privateMessages > div > span[ user-id="${StumbleChat.Chat.Selected}"]`);
  2883. PM.classList.remove("selected");
  2884. if (StumbleChat.Chat.Messages.get(StumbleChat.Chat.Selected).length == 0) {
  2885. PM.parentElement.remove();
  2886. StumbleChat.Chat.Messages.delete(StumbleChat.Chat.Selected);
  2887. if (StumbleChat.Chat.Messages.size == 1) {
  2888. document.querySelector("#userlist>h2:nth-child(2)").classList.add("hidden");
  2889. PM.classList.add("hidden");
  2890. }
  2891. }
  2892. StumbleChat.Chat.Selected = 0;
  2893. document.querySelector(".unreadmessage").classList.add("hidden");
  2894.  
  2895. document.querySelector("#chat-position>#back").classList.remove("show");
  2896. document.getElementById("chat-content").innerHTML = "";
  2897.  
  2898. StumbleChat.Chat.Messages.get(0).forEach((value, index) => {
  2899. if (index > 0) {
  2900. if (StumbleChat.Chat.Messages.get(0)[ index - 1 ].username == value.username && value.username != undefined && value.nick == StumbleChat.Chat.Messages.get(0)[ index - 1 ].nick) {
  2901. let element = document.createElement("div");
  2902. element.setAttribute("class", "content");
  2903. element.innerHTML = `<span class="hidden-selectable">[ ${value.time} ]</span><span class="timestamp">${value.time}</span><span class="message common" style="color:${value.messagetextcolor}">${value.msg}</span></div> `;
  2904. document.querySelector("#chat-content>.message:last-child").appendChild(element);
  2905. } else {
  2906. createChatItem(value);
  2907. }
  2908. } else {
  2909. createChatItem(value);
  2910. }
  2911. });
  2912.  
  2913. StumbleChat.Chat.Scroll(true);
  2914. document.querySelector("#textarea").focus();
  2915. } else if (event.target.id == "search") {
  2916. Media.YouTube.Add();
  2917. } else if (event.target.id == "broadcastpassword") {
  2918. Modal.Destroy();
  2919. StumbleChat.Videos.Password = document.querySelector("#modal-text-input").value;
  2920. if (document.querySelector("#modal-text-hidden").value == 0) {
  2921. requestBroadcast(StumbleChat.Videos.Password);
  2922. } else if (document.querySelector("#modal-text-hidden").value == 1) {
  2923. requestScreenshare(StumbleChat.Videos.Password);
  2924. }
  2925. } else if (event.target.id == "broadcastsettings") {
  2926. saveBroadcast();
  2927. } else if (event.target.id == "roompassword") {
  2928. StumbleChat.Chat.Password = document.querySelector("#modal-text-input").value;
  2929. App.Auth(document.querySelector("#modal-text-input").value);
  2930. } else if (event.target.id == "resetbackground") {
  2931. StumbleChat.Chat.Background.Reset();
  2932. } else if (event.target.id == "setbackground") {
  2933. StumbleChat.Chat.Background.Set();
  2934. } else if (event.target.id == "resetchatcolor") {
  2935. StumbleChat.Chat.Color.Reset();
  2936. } else if (event.target.id == "setchatcolor") {
  2937. StumbleChat.Chat.Color.Set();
  2938. } else if (event.target.id == "searchtwitch") {
  2939. Media.Twitch.Add();
  2940. } else if (event.target.id == "searchsoundcloud") {
  2941. Media.SoundCloud.Add();
  2942. } else if (event.target.id == "searchdailymotion") {
  2943. Media.DailyMotion.Add();
  2944. } else if (event.target.id == "searchworldstarhiphop") {
  2945. Media.WSHH.Add();
  2946. } else if (event.target.id == "broadcast-password-clear") {
  2947. StumbleChat.Chat.setBroadcastPassword(true);
  2948. } else if (event.target.id == "twitch-close") {
  2949. Media.Twitch.Stop();
  2950. } else if (event.target.id == "soundcloud-close") {
  2951. Media.SoundCloud.Stop();
  2952. } else if (event.target.id == "dailymotion-close") {
  2953. Media.DailyMotion.Stop();
  2954. } else if (event.target.id == "worldstarhiphop-close") {
  2955. Media.WSHH.Stop();
  2956. } else if (event.target.id == "youtube-close-embed") {
  2957. StumbleChat.WebSocket.send(`{"stumble":"youtube","type":"remove","id":${StumbleChat.Chat.Settings.YouTubeQueueID} } `);
  2958. } else if (event.target.id == "changeroomtopic") {
  2959. StumbleChat.Chat.setTopic();
  2960. } else if (event.target.id == "changebroadcastpassword") {
  2961. StumbleChat.Chat.setBroadcastPassword(false);
  2962. } else if (event.target.id == "twitch-close-embed") {
  2963. Media.Twitch.Stop();
  2964. } else if (event.target.id == "soundcloud-close-embed") {
  2965. Media.SoundCloud.Stop();
  2966. } else if (event.target.id == "dailymotion-close-embed") {
  2967. Media.DailyMotion.Stop();
  2968. } else if (event.target.id == "worldstarhiphop-close-embed") {
  2969. Media.WSHH.Stop();
  2970. } else if (event.target.id == "modal-exit") {
  2971. Modal.Destroy();
  2972. } else if (event.target.id == "interact") {
  2973. App.Init();
  2974. } else if (event.target.id == "change-nick") {
  2975. App.ChangeNick();
  2976. } else if (event.target.classList.contains("resizeuser")) {
  2977. document.querySelector("sc-userlist>.resizeuser").classList.toggle("left");
  2978. if (!StumbleChat.Userlist.Resized) {
  2979. document.querySelector("sc-userlist").style = "left:-210px;position:absolute;";
  2980. StumbleChat.Userlist.Resized = true;
  2981. } else {
  2982. document.querySelector("sc-userlist").style = "";
  2983. StumbleChat.Userlist.Resized = false;
  2984. }
  2985.  
  2986. StumbleChat.Videos.Update();
  2987. } else if (event.target.classList.contains("resizechat")) {
  2988. document.querySelector("sc-chat>.resizechat").classList.toggle("right");
  2989. if (!StumbleChat.Chat.Resized) {
  2990. document.querySelector("sc-chat").style = "right:-500px;position:absolute;";
  2991. StumbleChat.Chat.Resized = true;
  2992. } else {
  2993. document.querySelector("sc-chat").style = "";
  2994. StumbleChat.Chat.Resized = false;
  2995. }
  2996. StumbleChat.Videos.Update();
  2997. } else if (event.target.classList.contains("resizetopic")) {
  2998. Modal.Create(13);
  2999. } else if (event.target.classList.contains("slider")) {
  3000. switch (event.target.id) {
  3001. case "youtube":
  3002. if (StumbleChat.Chat.Settings.YouTubeEnabled == true) {
  3003. let elem = document.querySelector("#youtubeplayer");
  3004. if (elem !== null) elem.parentNode.removeChild(elem);
  3005. document.querySelector("#videos > div > .youtube").classList.add("hidden");
  3006. StumbleChat.Chat.Settings.YouTubeStartTime = 0;
  3007. StumbleChat.Chat.Settings.YouTubeQueueID = undefined;
  3008. StumbleChat.Chat.Settings.YouTubePausedTime = new Date();
  3009. StumbleChat.Chat.Settings.YouTubeClicked = true;
  3010. window.YouTubePlayer = undefined;
  3011. let newNode = document.createElement("div");
  3012. newNode.setAttribute("id", "youtubeplayer");
  3013. document.querySelector(".youtube>.video>.video-wrapper").prepend(newNode);
  3014. document.querySelector("#youtube-volume-slider").value = 100;
  3015. }
  3016. StumbleChat.Chat.Settings.YouTubeEnabled = !StumbleChat.Chat.Settings.YouTubeEnabled;
  3017. localStorage.setItem('YouTubeEnabled', StumbleChat.Chat.Settings.YouTubeEnabled);
  3018. break;
  3019. case "twitch":
  3020. if (StumbleChat.Chat.Settings.TwitchEnabled == true) {
  3021. let elem = document.querySelector("#twitchplayer>iframe");
  3022. if (elem !== null) elem.parentNode.removeChild(elem);
  3023. document.querySelector("#videos > div > .twitch").classList.add("hidden");
  3024. }
  3025. StumbleChat.Chat.Settings.TwitchEnabled = !StumbleChat.Chat.Settings.TwitchEnabled;
  3026. localStorage.setItem('TwitchEnabled', StumbleChat.Chat.Settings.TwitchEnabled);
  3027. break;
  3028. case "soundcloud":
  3029. if (StumbleChat.Chat.Settings.SoundCloudEnabled == true) {
  3030. let elem = document.querySelector("#soundcloudplayer>iframe");
  3031. if (elem !== null) elem.parentNode.removeChild(elem);
  3032. document.querySelector("#videos > div > .soundcloud").classList.add("hidden");
  3033. }
  3034. StumbleChat.Chat.Settings.SoundCloudEnabled = !StumbleChat.Chat.Settings.SoundCloudEnabled;
  3035. localStorage.setItem('SoundCloudEnabled', StumbleChat.Chat.Settings.SoundCloudEnabled);
  3036. break;
  3037. case "dailymotion":
  3038. if (StumbleChat.Chat.Settings.DailyMotionEnabled == true) {
  3039. let elem = document.querySelector("#dailymotion>iframe");
  3040. if (elem !== null) elem.parentNode.removeChild(elem);
  3041. document.querySelector("#videos > div > .dailymotion").classList.add("hidden");
  3042. }
  3043. StumbleChat.Chat.Settings.DailyMotionEnabled = !StumbleChat.Chat.Settings.DailyMotionEnabled;
  3044. localStorage.setItem('DailyMotionEnabled', StumbleChat.Chat.Settings.DailyMotionEnabled);
  3045. break;
  3046. case "wshh":
  3047. if (StumbleChat.Chat.Settings.WSHHEnabled == true) {
  3048. let elem = document.querySelector("#worldstarhiphopplayer>video");
  3049. if (elem !== null) elem.parentNode.removeChild(elem);
  3050. document.querySelector("#videos > div > .worldstarhiphop").classList.add("hidden");
  3051. }
  3052. StumbleChat.Chat.Settings.WSHHEnabled = !StumbleChat.Chat.Settings.WSHHEnabled;
  3053. localStorage.setItem('WSHHEnabled', StumbleChat.Chat.Settings.WSHHEnabled);
  3054. break;
  3055. case "largeembeddedvideos":
  3056. if (StumbleChat.Chat.Settings.LargeEmbeddedVideos == false) {
  3057. document.querySelector("#videos").prepend(document.querySelector(`#videos > div:nth-child(2)`));
  3058. } else {
  3059. document.querySelector("#videos").appendChild(document.querySelector(`#videos > div:nth-child(1)`));
  3060. }
  3061. StumbleChat.Videos.Update();
  3062. StumbleChat.Chat.Settings.LargeEmbeddedVideos = !StumbleChat.Chat.Settings.LargeEmbeddedVideos;
  3063. localStorage.setItem('LargeEmbeddedVideos', StumbleChat.Chat.Settings.LargeEmbeddedVideos);
  3064. break;
  3065. case "largefont":
  3066. if (StumbleChat.Chat.Settings.LargeFont == false) {
  3067. document.querySelector("#chat-content").classList.add("large");
  3068. } else {
  3069. document.querySelector("#chat-content").classList.remove("large");
  3070. }
  3071. StumbleChat.Chat.Settings.LargeFont = !StumbleChat.Chat.Settings.LargeFont;
  3072. localStorage.setItem('LargeFont', StumbleChat.Chat.Settings.LargeFont);
  3073. break;
  3074. case "soundmeter":
  3075. StumbleChat.Chat.Settings.SoundmeterEnabled = !StumbleChat.Chat.Settings.SoundmeterEnabled;
  3076. localStorage.setItem('SoundmeterEnabled', StumbleChat.Chat.Settings.SoundmeterEnabled);
  3077. break;
  3078. case "pm":
  3079. StumbleChat.Chat.Settings.PrivateMessageEnabled = !StumbleChat.Chat.Settings.PrivateMessageEnabled;
  3080. localStorage.setItem('PrivateMessageEnabled', StumbleChat.Chat.Settings.PrivateMessageEnabled);
  3081. break;
  3082. case "sounds":
  3083. StumbleChat.Chat.Settings.SoundsEnabled = !StumbleChat.Chat.Settings.SoundsEnabled;
  3084. localStorage.setItem('SoundsEnabled', StumbleChat.Chat.Settings.SoundsEnabled);
  3085. break;
  3086. case "links":
  3087. StumbleChat.Chat.Settings.LinksEnabled = !StumbleChat.Chat.Settings.LinksEnabled;
  3088. localStorage.setItem('LinksEnabled', StumbleChat.Chat.Settings.LinksEnabled);
  3089. break;
  3090. case "imgur":
  3091. StumbleChat.Chat.Settings.ImgurEnabled = !StumbleChat.Chat.Settings.ImgurEnabled;
  3092. localStorage.setItem('ImgurEnabled', StumbleChat.Chat.Settings.ImgurEnabled);
  3093. break;
  3094. case "guestsallowed":
  3095. StumbleChat.Room.guests_allowed = !StumbleChat.Room.guests_allowed;
  3096. StumbleChat.WebSocket.send(JSON.stringify({ "stumble": "room", "type": "guests", "enabled": (StumbleChat.Room.guests_allowed) ? 1 : 0 }));
  3097. break;
  3098. case "publicroom":
  3099. StumbleChat.Room.public = !StumbleChat.Room.public;
  3100. StumbleChat.WebSocket.send(JSON.stringify({ "stumble": "room", "type": "public", "enabled": (StumbleChat.Room.public) ? 1 : 0 }));
  3101. break;
  3102. case "greenroom":
  3103. StumbleChat.Room.greenroom = !StumbleChat.Room.greenroom;
  3104. StumbleChat.WebSocket.send(JSON.stringify({ "stumble": "room", "type": "greenroom", "enabled": (StumbleChat.Room.greenroom) ? 1 : 0 }));
  3105. break;
  3106. }
  3107. StumbleChat.Videos.Update();
  3108. } else if (event.target.parentElement !== null && event.target.parentElement !== undefined) {
  3109. if (event.target.parentElement.classList.contains("banlist")) {
  3110. event.target.parentElement.remove();
  3111. StumbleChat.WebSocket.send(JSON.stringify({
  3112. "stumble": "unban",
  3113. "username": event.target.parentElement.attributes.username.value,
  3114. "id": event.target.parentElement.attributes[ "user-id" ].value
  3115. }));
  3116. } else if (event.target.parentElement.classList.contains("youtubelist")) {
  3117. if (event.target.classList.contains("youtube_title")) return;
  3118. if (event.target.classList.contains("youtube_thumbnail")) return;
  3119. event.target.parentElement.remove();
  3120. StumbleChat.WebSocket.send(`{"stumble":"youtube","type":"remove","id":${event.target.parentElement.id} } `);
  3121. }
  3122. }
  3123. // Close context
  3124. StumbleChat.Userlist.Menu.Task = StumbleChat.GUI.Element.Exists(event, "bar");
  3125. if (!StumbleChat.Userlist.Menu.Task) {
  3126. StumbleChat.Userlist.Menu.Task = null;
  3127. StumbleChat.Userlist.Menu.Hide();
  3128. }
  3129. if (event.target.classList.contains("bar")) StumbleChat.Userlist.Menu.Listen();
  3130. StumbleChat.Videos.Menu.Task = StumbleChat.GUI.Element.Exists(event, "video-wrapper");
  3131. if (!StumbleChat.Videos.Menu.Task) {
  3132. StumbleChat.Videos.Menu.Task = null;
  3133. StumbleChat.Videos.Menu.Hide();
  3134. }
  3135. if (event.target.classList.contains("video-wrapper")) StumbleChat.Videos.Menu.Listen();
  3136. }, {
  3137. passive: false
  3138. });
  3139.  
  3140. window.addEventListener("pointermove", (event) => {
  3141. if (!StumbleChat.Videos.AudioPaused && StumbleChat.Userlist.Broadcast.has(StumbleChat.Self.handle) && event.target.id !== "media-ptt") {
  3142. if (StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).audio !== null && !StumbleChat.Videos.AudioAwaitingPause) {
  3143. if (!StumbleChat.Chat.Settings.isMobile) window.addEventListener("pointerup", muteBroadcast, {
  3144. passive: true,
  3145. once: true
  3146. });
  3147. }
  3148. }
  3149. }, {
  3150. passive: true
  3151. });
  3152.  
  3153. document.querySelector("sc-videolist").addEventListener("dragstart", (e) => e.preventDefault());
  3154.  
  3155. window.addEventListener("input", (e) => {
  3156. if (e.target.classList.contains("RoomVolume")) {
  3157. StumbleChat.Userlist.Broadcast.forEach((value, key) => {
  3158. if (value.audio !== null && key !== StumbleChat.Self.handle) value.element.volume = (value.volume / 100) * (e.target.value / 100);
  3159. });
  3160. StumbleChat.Chat.Sounds.public_message.volume = (e.target.value / 100);
  3161. StumbleChat.Chat.Sounds.private_message.volume = (e.target.value / 100);
  3162. StumbleChat.Chat.Settings.RoomVolume = e.target.value;
  3163. localStorage.setItem('RoomVolume', e.target.value);
  3164. } else if (e.target.id == "twitch-volume-slider") {
  3165. if (window.TwitchPlayer !== undefined) window.TwitchPlayer.setVolume((e.target.value / 100));
  3166. } else if (e.target.id == "soundcloud-volume-slider") {
  3167. let audio_iframe = document.querySelector('#soundcloudplayer>iframe');
  3168. if (audio_iframe !== null) {
  3169. let widget = window.SC.Widget(audio_iframe);
  3170. widget.setVolume((e.target.value));
  3171. }
  3172. } else if (e.target.id == "youtube-volume-slider") {
  3173. if (window.YouTubePlayer !== undefined) window.YouTubePlayer.setVolume((e.target.value / 100) * 100);
  3174. }
  3175. }, { passive: true });
  3176.  
  3177. window.addEventListener("change", (e) => {
  3178. if (e.target.parentElement.id == "media-openmic") {
  3179. StumbleChat.Videos.OpenMic = e.target.checked;
  3180. if (!StumbleChat.Videos.OpenMic) return muteBroadcast();
  3181. document.querySelector("#media-ptt").innerText = "TALKING...";
  3182. StumbleChat.Videos.AudioPaused = false;
  3183. StumbleChat.Videos.AudioAwaitingPause = true;
  3184. StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).audio.resume();
  3185. } else if (e.target.id == "videoSelect") {
  3186. previewBroadcast(window.videoSelect.value);
  3187. }
  3188. }, { passive: true });
  3189.  
  3190. if (StumbleChat.Chat.Settings.isMobile) {
  3191. document.querySelector("#media-screen").classList.add("hidden");
  3192.  
  3193. window.addEventListener('touchend', e => {
  3194. if (!StumbleChat.Videos.AudioPaused && StumbleChat.Userlist.Broadcast.has(StumbleChat.Self.handle)) {
  3195. if (StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).audio !== null && StumbleChat.Videos.AudioAwaitingPause) muteBroadcast();
  3196. }
  3197. }, {
  3198. passive: true
  3199. });
  3200. }
  3201.  
  3202. StumbleChat.Room.name = location.pathname.replace(/[\/]+(room)[\/]{1,}/gi, "").toUpperCase();
  3203.  
  3204. Modal.Create(20);
  3205. navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then((stream) => stream.getTracks().forEach((track) => track.stop())).then(() => Modal.Create(4)).catch((err) => Modal.Create(4));
  3206. };
  3207.  
  3208. function parseStorage (key, defaultval) {
  3209. if (StumbleChat.Chat.Settings.SaveEnabled == true) {
  3210. if (localStorage.getItem(key) === null) localStorage.setItem(key, defaultval);
  3211. try {
  3212. return JSON.parse(localStorage.getItem(key));
  3213. } catch (e) {
  3214. return localStorage.getItem(key);
  3215. }
  3216. }
  3217. return defaultval;
  3218. }
  3219. function loadStorage () {
  3220. // Personal Settings
  3221. StumbleChat.Chat.Settings.IgnoredList = parseStorage('IgnoredList', JSON.stringify([]));
  3222. StumbleChat.Chat.Settings.HideList = parseStorage('HideList', JSON.stringify([]));
  3223. StumbleChat.Chat.Settings.BroadcastVolume = parseStorage('BroadcastVolume', JSON.stringify({}));
  3224.  
  3225. // User Settings
  3226. StumbleChat.Chat.Settings.YouTubeEnabled = parseStorage('YouTubeEnabled', !StumbleChat.Chat.Settings.isMobile);
  3227. StumbleChat.Chat.Settings.TwitchEnabled = parseStorage('TwitchEnabled', !StumbleChat.Chat.Settings.isMobile);
  3228. StumbleChat.Chat.Settings.SoundCloudEnabled = parseStorage('SoundCloudEnabled', !StumbleChat.Chat.Settings.isMobile);
  3229. StumbleChat.Chat.Settings.WSHHEnabled = parseStorage('WSHHEnabled', !StumbleChat.Chat.Settings.isMobile);
  3230. StumbleChat.Chat.Settings.DailyMotionEnabled = parseStorage('DailyMotionEnabled', !StumbleChat.Chat.Settings.isMobile);
  3231. StumbleChat.Chat.Settings.LargeEmbeddedVideos = parseStorage('LargeEmbeddedVideos', false);
  3232. StumbleChat.Chat.Settings.LargeFont = parseStorage('LargeFont', false);
  3233. StumbleChat.Chat.Settings.SoundmeterEnabled = parseStorage('SoundmeterEnabled', true);
  3234. StumbleChat.Chat.Settings.PrivateMessageEnabled = parseStorage('PrivateMessageEnabled', true);
  3235. StumbleChat.Chat.Settings.SoundsEnabled = parseStorage('SoundsEnabled', true);
  3236. StumbleChat.Chat.Settings.LinksEnabled = parseStorage('LinksEnabled', true);
  3237. StumbleChat.Chat.Settings.ImgurEnabled = parseStorage('ImgurEnabled', true);
  3238.  
  3239. // Media Settings
  3240. StumbleChat.Chat.Settings.audiodevice = parseStorage('audiodevice', "NONE");
  3241. StumbleChat.Chat.Settings.videodevice = parseStorage('videodevice', "NONE");
  3242.  
  3243. StumbleChat.Chat.Settings.Resolution = parseStorage('Resolution', 2);
  3244. StumbleChat.Chat.Settings.FrameRate = parseStorage('FrameRate', 30);
  3245.  
  3246. StumbleChat.Chat.Settings.EchoCancellation = parseStorage('EchoCancellation', true);
  3247. StumbleChat.Chat.Settings.AutoGainControl = parseStorage('AutoGainControl', true);
  3248. StumbleChat.Chat.Settings.NoiseSupression = parseStorage('NoiseSupression', true);
  3249. }
  3250. function currentTime () {
  3251. return new Date().toLocaleString("en-US", {
  3252. hour: "numeric",
  3253. minute: "numeric",
  3254. second: "numeric",
  3255. hour12: true
  3256. });
  3257. }
  3258. function parseLink (message) {
  3259. return message.replace(/(?:(?:(?:https?|ftps?):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?/igm, (url) => {
  3260. try {
  3261. return (new URL(url).hostname.includes('xn--')) ? 'URL BLOCKED' : `<a target="_blank" href="${url}">${url}</a>`;
  3262. } catch (e) {
  3263. return `URL BLOCKED`;
  3264. }
  3265. });
  3266. }
  3267. function parseImgur (message) {
  3268. let url = message.match(/https?:\/\/i\.imgur\.com\/[a-zA-Z0-9]*\.(jpeg|jpg|gif|png|mp4)/);
  3269. if (url !== null) message = (url[ 1 ] == "mp4") ? `<center><video width="288px" height="162px" controls><source src="${url[ 0 ]}" type="video/mp4" /></video>\n<a href="${url[ 0 ]}" target="_blank">Direct Link</a></center>` : `<center><img src="${url[ 0 ]}" width="320px" height="240px" />\n<a href="${url[ 0 ]}" target="_blank">Direct Link</a></center>`;
  3270. return message;
  3271. }
  3272. function reloadClient () {
  3273. App.Clear();
  3274. StumbleChat.Videos.Update();
  3275. if (!StumbleChat.Chat.Status.Kicked) {
  3276. Modal.Create(2);
  3277. setTimeout(App.Init, 5000);
  3278. }
  3279. }
  3280.  
  3281. function createChatItem (value) {
  3282. let element = document.createElement("div");
  3283. element.style.background = `${value.backgroundcolor}a3`;
  3284. element.setAttribute("class", "message " + ((value.nick !== undefined) ? (value.avatar == undefined) ? "noavatar" : "common" : "system"));
  3285. element.innerHTML = (value.nick !== undefined) ? ((value.avatar == undefined) ? `` : `<span class="avatar"><img src="${value.avatar}" alt="Avatar"></span>`) + `<span class="nickname" style = "background:${value.namebackgroundcolor}">${value.nick}</span><div class="content"><span class="hidden-selectable">[${value.time}]</span><span class="timestamp">${value.time}</span><span class="message common" style="color:${value.messagetextcolor}">${value.msg}</span>` : `<span class="hidden-selectable" > System Message\n[ ${value.time}]</span><span class="timestamp">${value.time}</span>${value.msg} `;
  3286. document.getElementById("chat-content").appendChild(element);
  3287. }
  3288. function createBroadcastItem (el, deviceId, label) {
  3289. let option = document.createElement('option');
  3290. option.value = deviceId;
  3291. option.innerText = label;
  3292. el.appendChild(option);
  3293. }
  3294. function previewBroadcast (videodeviceId) {
  3295. let Select = document.querySelector("#videoSelect");
  3296. Select.disabled = true;
  3297. let PreviewVideo = document.querySelector("#previewvideo");
  3298. if (PreviewVideo.srcObject != undefined) {
  3299. PreviewVideo.srcObject.getTracks().forEach((track) => track.stop());
  3300. PreviewVideo.classList.add("hidden");
  3301. }
  3302. if (videodeviceId != undefined && videodeviceId != "NONE") {
  3303. navigator.mediaDevices.getUserMedia({ video: { deviceId: { exact: videodeviceId } } }).then((stream) => {
  3304. PreviewVideo.srcObject = stream;
  3305. PreviewVideo.classList.remove("hidden");
  3306. Select.disabled = false;
  3307. PreviewVideo.play();
  3308. }).catch(() => {
  3309. Select.disabled = false;
  3310. });
  3311. } else {
  3312. Select.disabled = false;
  3313. }
  3314. }
  3315. function requestBroadcast (password) {
  3316. StumbleChat.WebSocket.send(`{"stumble":"publish","type":"request","password":"${password}"}`);
  3317.  
  3318. document.getElementById('media-broadcast').classList.add('hidden');
  3319. document.getElementById('media-settings').classList.add('hidden');
  3320. document.getElementById('media-screen').classList.add('hidden');
  3321. document.getElementById('media-loading').classList.remove('hidden');
  3322. document.getElementById('media-stop').classList.remove('hidden');
  3323. document.getElementById('media-stop').classList.remove('no-audio');
  3324. }
  3325. function requestScreenshare (password) {
  3326. navigator.mediaDevices.getDisplayMedia({
  3327. video: {
  3328. width: StumbleChat.Videos.Resolutions[ StumbleChat.Chat.Settings.Resolution ][ 0 ],
  3329. height: StumbleChat.Videos.Resolutions[ StumbleChat.Chat.Settings.Resolution ][ 1 ],
  3330. frameRate: { ideal: StumbleChat.Videos.FrameRate, max: 60 }
  3331. },
  3332. audio: true
  3333. }).then((screen) => {
  3334. localScreen = screen;
  3335. localScreen.addEventListener('inactive', (event) => {
  3336. if (localScreen != undefined) StumbleChat.WebSocket.send(`{"stumble":"publish","type":"close"} `);
  3337. Broadcast.unpublish(StumbleChat.Self.handle);
  3338. });
  3339. requestBroadcast(password);
  3340. }).catch(err => { });
  3341. }
  3342. function createBroadcastElement (handle) {
  3343. let user = StumbleChat.Userlist.User.get(handle);
  3344. if (user == undefined) user = { nick: "" };
  3345. if (!document.querySelector(`#video[video-id= "${handle}"]`)) document.querySelector(`#regularvideos`).insertAdjacentHTML("afterBegin", ` <div class="js-video"><div class="video"><div class="video-wrapper"><video id="video" video-id="${handle}" autoplay playsinline>Your browser does not support the video tag...</video>${(handle == StumbleChat.Self.handle && StumbleChat.Self.directory) ? "<canvas canvas-id='" + handle + "' style='display:none;'></canvas>" : ""}<span class="nickname" title="${user.nick}" style="">${user.nick}</span></div></div></div> `);
  3346. StumbleChat.Videos.Update();
  3347. return {
  3348. video: document.querySelector(`#video[ video-id= "${handle}"]`),
  3349. canvas: (handle == StumbleChat.Self.handle && StumbleChat.Self.directory) ? document.querySelector(`canvas[ canvas-id= "${handle}"]`) : undefined
  3350. };
  3351. }
  3352. function saveBroadcast () {
  3353. if (window.videoSelect != undefined) {
  3354. let PreviewVideo = document.querySelector("#previewvideo");
  3355. if (PreviewVideo.srcObject != undefined) PreviewVideo.srcObject.getTracks().forEach((track) => track.stop());
  3356.  
  3357. let SelectedFrameRate;
  3358. let framerate = document.getElementsByName('framerate');
  3359. for (let i = 0, length = framerate.length; i < length; i++) {
  3360. if (framerate[ i ].checked) {
  3361. SelectedFrameRate = framerate[ i ].value;
  3362. break;
  3363. }
  3364. }
  3365.  
  3366. let SelectedResolution;
  3367. let resolution = document.getElementsByName('resolution');
  3368. for (let i = 0, length = resolution.length; i < length; i++) {
  3369. if (resolution[ i ].checked) {
  3370. SelectedResolution = resolution[ i ].value;
  3371. break;
  3372. }
  3373. }
  3374.  
  3375. StumbleChat.Chat.Settings.audiodevice = window.audioSelect.value;
  3376. localStorage.setItem("audiodevice", window.audioSelect.value);
  3377. StumbleChat.Chat.Settings.videodevice = window.videoSelect.value;
  3378. localStorage.setItem("videodevice", window.videoSelect.value);
  3379.  
  3380. StumbleChat.Chat.Settings.FrameRate = SelectedFrameRate;
  3381. localStorage.setItem('FrameRate', SelectedFrameRate);
  3382. StumbleChat.Chat.Settings.Resolution = SelectedResolution;
  3383. localStorage.setItem('Resolution', SelectedResolution);
  3384.  
  3385. let enhancement = document.getElementsByName('enhancement');
  3386.  
  3387. StumbleChat.Chat.Settings.EchoCancellation = enhancement[ 0 ].checked;
  3388. localStorage.setItem('EchoCancellation', enhancement[ 0 ].checked);
  3389. StumbleChat.Chat.Settings.AutoGainControl = enhancement[ 1 ].checked;
  3390. localStorage.setItem('AutoGainControl', enhancement[ 1 ].checked);
  3391. StumbleChat.Chat.Settings.NoiseSupression = enhancement[ 2 ].checked;
  3392. localStorage.setItem('NoiseSupression', enhancement[ 2 ].checked);
  3393. }
  3394. Modal.Destroy();
  3395. }
  3396. function removeBroadcastElement (handle) {
  3397. StumbleChat.Userlist.Broadcast.delete(handle);
  3398.  
  3399. let uservid = document.querySelector(`#video[video-id="${handle}"]`);
  3400. if (uservid !== null) uservid.parentElement.parentElement.parentElement.parentElement.removeChild(uservid.parentElement.parentElement.parentElement);
  3401. }
  3402. function removeBroadcastBadge (handle) {
  3403. if (document.querySelector(`.bar[user-id="${handle}"]`)) {
  3404. document.querySelector(`.bar[user-id="${handle}"] .status>div:nth-child(1)`).classList.add("hidden");
  3405. document.querySelector(`.bar[user-id="${handle}"] .status>div:nth-child(2)`).classList.add("hidden");
  3406. }
  3407. }
  3408. function resetBroadcastState () {
  3409. StumbleChat.Videos.OpenMic = false;
  3410. document.querySelector("#media-openmic>input").checked = false;
  3411. muteBroadcast();
  3412. if (!StumbleChat.Chat.Settings.isMobile) document.querySelector("#media-screen").classList.remove("hidden");
  3413. document.getElementById('media-broadcast').classList.remove('hidden');
  3414. document.getElementById('media-settings').classList.remove('hidden');
  3415. document.getElementById('media-loading').classList.add('hidden');
  3416. document.getElementById('media-ptt').classList.add('hidden');
  3417. document.getElementById('media-openmic').classList.add('hidden');
  3418. document.getElementById('media-stop').classList.add('hidden');
  3419. StumbleChat.Videos.Update();
  3420. }
  3421. function muteBroadcast () {
  3422. if (!StumbleChat.Videos.OpenMic) {
  3423. StumbleChat.Videos.AudioPaused = true;
  3424. StumbleChat.Videos.AudioAwaitingPause = false;
  3425. document.querySelector("#media-ptt").innerText = "TALK";
  3426. if (StumbleChat.Userlist.Broadcast.has(StumbleChat.Self.handle)) StumbleChat.Userlist.Broadcast.get(StumbleChat.Self.handle).audio.pause();
  3427. }
  3428. }
  3429. })();
  3430.  
  3431.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement