您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a list of members available for OC2.0, and adds a notifier to the sidebar if you are not in an OC.
当前为
// ==UserScript== // @name [TORN] OC 2.0 Helper // @namespace Violentmonkey Scripts // @match https://www.torn.com/* // @version 5.1.1 // @author callmericky [3299880] / whatdoesthespacebardo // @description Adds a list of members available for OC2.0, and adds a notifier to the sidebar if you are not in an OC. // @require http://code.jquery.com/jquery-3.6.0.min.js // @grant GM_registerMenuCommand // @grant GM.setValue // @grant GM.getValue // @license GNU GPLv3 // ==/UserScript== /* * All edits can be done from the dropdown menu from your userscript extension */ //IF DROPDOWN MENU DOESN'T WORK, MANUALLY ADD YOUR API KEY HERE var APIKey = ""; const PDA_APIKey = "###PDA-APIKEY###" /* * STOP CHANGING THINGS FROM HERE */ //fix for tampermonkey var $ = window.jQuery; let memberInfo = {}; let pageURL = $(location).attr("href"); let totalMembers = 0; let availableMembers = 0; let activeMembers = 0; let userInfo = {}; let crimeListUninitiated = [] let crimeListRecruiting = [] let crimeListPlanning = [] let crimeList = [] let availMemberList = [] let myAPIData = null let itemIDObj = {} let containerMaxWidth = "784px" let containerBigMaxWidth = "976px" let userSettings = {} let displayIgnoreList = [ ] var alreadyLoading = false let skippedMemberCount = 0 let skippedMemberList = [] var OC2_timerID = null var membersButtonShowText = (`⏵`) //⏵ ⏵ var membersButtonHideText = (`⏷`) //⏷ ⏷ if (isPDA()) { membersButtonShowText = (`▶`) //▶ ▶ membersButtonHideText = (`▼`) //▼ ▼ } const crimeButtonShowText = (`Show Crimes`) const crimeButtonHideText = (`Hide Crimes`) const lazyMembersButtonShowText = (`Show Members`) const lazyMembersButtonHideText = (`Hide Members`) const settingsButtonAscText = (`▴`) //▴ ▴ const settingsButtonDescText = (`▾`) // ▾ ▾ const defaultUserSettings = { "memberShow": "member-show", "crimesShow": "crimes-hide", "sortType": "time-asc", //time-asc / time-desc / level-asc / level-desc "memberSort": "OC-desc", //OC-asc / OC-desc / active-asc / active-desc "lastOC_yellow": 24, "lastOC_red": 48, "lastActivity": 96, "memberIgnoreList": [ ], "showSidebarOC": "sidebar-show" } let _isWindowNormal = window.matchMedia("(min-width: 1000px)") let _isWindowSmallish = window.matchMedia("(min-width: 785px)") let _isWindowSmall = window.matchMedia("(max-width: 784px) and (min-width: 387px)") let _isWindowTiny = window.matchMedia("(max-width: 386px)") let colorObj = { "dark_bg_link": { "darkmode": "rgb(116, 192, 252)", "lightmode": "rgb(116, 192, 252)" }, "link": { "darkmode": "rgb(116, 192, 252)", "lightmode": "#006699" }, "recolor": { "green": { "darkmode": "rgb(130, 201, 30)", "lightmode": "rgb(92, 148, 13)" }, "yellow": { "darkmode": "rgb(252, 196, 25)", "lightmode": "rgb(252, 196, 25)" }, "red": { "darkmode": "rgb(255, 135, 135)", "lightmode": "rgb(224, 49, 49)" }, "blue": { "darkmode": "rgb(59, 201, 219)", "lightmode": "rgb(12, 133, 153)" } }, "userindicatorbg": { "darkmode": "rgb(63, 68, 45)", "lightmode": "rgb(238, 241, 228)" }, "footerbg": { "darkmode": "rgb(51, 51, 51)", "lightmode": "rgb(242, 242, 242)" }, "crimeselectbg": { "darkmode": "rgba(0,0,0,0.2)", "lightmode": "rgba(150,150,150,0.1)" }, "fancyBg": { "darkmode": "inherit", "lightmode": "#fff" }, "inactiveIcon": { "default": { "lightmode": "rgba(100, 100, 100, 0.5)", "darkmode": "rgba(221, 221, 221, 0.5)" }, "highlightRed": { "lightmode": "rgba(255, 135, 135, 0.8)", "darkmode": "rgba(255, 135, 135, 0.8)" } }, "crimeIcon": { "default": { "lightmode": "rgba(100, 100, 100, 0.5)", "darkmode": "rgba(221, 221, 221, 0.5)" }, "highlightYellow": { "lightmode": "rgb(230, 180, 0)", "darkmode": "rgba(252, 196, 25, 0.8)" }, "highlightRed": { "lightmode": "rgba(255, 135, 135, 1)", "darkmode": "rgba(255, 135, 135, 0.8)" }, "highlightVeryRed": { "lightmode": "rgba(200, 33, 33, 1)", "darkmode": "rgba(200, 33, 33, 1)" } }, "buttons": { "background": { "lightmode": "linear-gradient(rgb(255, 255, 255) 0%, rgb(221, 221, 221) 100%)", "darkmode": "linear-gradient(rgb(85, 85, 85) 0%, rgb(51, 51, 51) 100%)" }, "textcolor": { "lightmode": "rgb(102, 102, 102)", "darkmode": "rgb(221, 221, 221)" }, "hovercolor": { "lightmode": "rgb(200,200,200)", "darkmode": "rgb(28,28,28)" } } } let colorDisplayMode = $("body#body").hasClass("dark-mode") ? "darkmode" : "lightmode" function getUserID() { let _profileLink = $(".settings-menu > .link > a")[0] let _matchregex = /profiles\.php.+XID=(\d+)/i let _userID = _matchregex.exec(_profileLink) userInfo.id = _userID[1] return _userID[1] } //user settings functions if (!isPDA()) { const menu_command_1 = GM_registerMenuCommand("Open Settings Page", showSettingsPage) } function showSettingsPage() { window.open("https://www.torn.com/OC2_Settings_Page", "_blank") } async function getAPIKey() { if (isPDA()) { APIKey = PDA_APIKey return PDA_APIKey } else if (APIKey != null && APIKey.length > 0) { return APIKey } else { return await GM.getValue("CMR_OC2_APIKey", null) .then(function(data) { APIKey = data return data }) } } async function setUserSettings(_settings) { if (!_settings) { return } if (isPDA()) { localStorage.setItem("CMR_OC2_userSettings", JSON.stringify(_settings)) if ( $("#OC2-APIInput").val().length > 5 && $("#OC2-APITestResult-Final").hasClass("color-green") ) { localStorage.setItem("CMR_OC2_APIKey", $("#OC2-APIInput").val()) } return } else { await GM.setValue("CMR_OC2_userSettings", JSON.stringify(_settings)) } if ( $("#OC2-APIInput").val().length > 5 && $("#OC2-APITestResult-Final").hasClass("color-green") ) { await GM.setValue("CMR_OC2_APIKey", $("#OC2-APIInput").val()) } } async function getUserSettings(event) { if (isPDA()) { if (!localStorage.getItem("CMR_OC2_userSettings")) { userSettings = defaultUserSettings } else { userSettings = JSON.parse(localStorage.getItem("CMR_OC2_userSettings")) } return } return await GM.getValue("CMR_OC2_userSettings", JSON.stringify(defaultUserSettings)) .then( (data) => { userSettings = JSON.parse(data) }) } //boolean logic functions function isPDA() { const PDATestRegex = !/^(###).+(###)$/.test(PDA_APIKey); return PDATestRegex; } function checkCrimesPage() { let pageURL = $(location).attr("href") return ((pageURL.search("step=your") >= 0) && (pageURL.search("tab=crimes") >= 0)) } async function checkTravelFactionPage() { let pageURL = $(location).attr("href") if ( ($('body').attr("data-traveling") == "true") || ($('body').attr("data-traveling") == true) || ($('body').attr("data-abroad") == "true") || ($('body').attr("data-abroad") == true) ) { if (!myAPIData) { try { let _successfulGetAPIData = await getAndAnalyzeAPIData() if (_successfulGetAPIData.error) { console.log("checktravelfactionpage Error: ", _successfulGetAPIData.error) $(".OC2-memberTable").hide() $(".OC2-memberTableErrorDisplay").html(`<span style="margin-left: 20px">Error occured: ${_successfulGetAPIData.error.error}. Please visit the <a href="https://www.torn.com/OC2_Settings_Page" target="_new" style="color: inherit; font-weight: bold; text-decoration: underline">Settings Page</a> to set up an API key</span>`) $(".OC2-memberTableErrorDisplay").show() return _successfulGetAPIData.error } } catch(_err) { console.log("checktrvelfactionpage caught error:", _err) return false } } if (pageURL.search("ID="+myAPIData.basic.id) >= 0) { return true; } } return false; } //API call functions async function getAndAnalyzeAPIData() { return await $.ajax({ dataType: "json", url: (`https://api.torn.com/v2/faction/basic,crimes,members?cat=available,completed&offset=0&striptags=true&comment=OC2-helper`), headers: { Authorization: (`ApiKey ${APIKey}`) } }).done( data => { if (data.error) { return data } checkMembersInCrimes(data) myAPIData = data return data }).fail( (error) => { return error }) } async function getItemNamesFromID(_arrayOfIds) { return await $.getJSON(`https://api.torn.com/torn/${_arrayOfIds.toString()}?selections=items&key=${APIKey}&comment=OC2-helper`) } //calculations and conversions async function convertItemIDArrayToItems() { let _arrayOfIDs = [] let _matchregex = /<\#(\d+)>/i for (var _key of Object.keys(itemIDObj)) { _arrayOfIDs.push(_key) } await getItemNamesFromID(_arrayOfIDs) .then( (_data) => { for (var _itemID of Object.keys(_data.items)) { itemIDObj[_itemID].name = _data.items[_itemID].name } }) for (let i = 0; i < $(".OC2-tableCrimeMemberItem:has(*)").length; i++) { let _oldTitle = $(".OC2-tableCrimeMemberItem:has(*)").eq(i).attr("title") let _regexResult = _matchregex.exec($(".OC2-tableCrimeMemberItem:has(*)").eq(i).attr("title")) let _newTitle = _oldTitle.replace(_matchregex, `${itemIDObj[_regexResult[1]].name} <$1>`) $(".OC2-tableCrimeMemberItem:has(*)").eq(i).attr("title", _newTitle) } } function timestampDiff(laterTimestamp) { var currentTimestamp = Math.floor(Date.now()/1000) var _returnString = "" var timeDiff = 0 var _highlightClass = "" if (laterTimestamp > currentTimestamp) { timeDiff = laterTimestamp - currentTimestamp } if (timeDiff < 43200) { //12 hours = 12 * 60 * 60 = 43200 _highlightClass = "OC2-highlightText" } let _d = timeDiff < 86400 ? 0 : Math.floor(timeDiff/86400) let _h = timeDiff < 3600 ? 0 : Math.floor(timeDiff/3600) - _d*24 //24h in 1d let _m = timeDiff < 60 ? 0 : Math.floor(timeDiff/60) - _h*60 - _d*1440 //60m in 1h, 1440m in 1d let _s = timeDiff - _m*60 - _h*3600 - _d*86400 //60s in 1m, 3600s in 1h, 86400s in 1d _returnString += `<span class="${_highlightClass}">${_d.toString().padStart(2,'0')}:${_h.toString().padStart(2,'0')}:${_m.toString().padStart(2,'0')}:${_s.toString().padStart(2,'0')}</span>` return _returnString } function stringifyTimestampOld(_timeDiff) { var currentTimestamp = Math.floor(Date.now()/1000) var _returnString = "" var _highlightClass = "" if (_timeDiff == -1) { return (`User has not joined the last ${myAPIData.crimes.length} OCs`) } let _d = _timeDiff < 86400 ? 0 : Math.floor(_timeDiff/86400) let _h = _timeDiff < 3600 ? 0 : Math.floor(_timeDiff/3600) - _d*24 //24h in 1d let _m = _timeDiff < 60 ? 0 : Math.floor(_timeDiff/60) - _h*60 - _d*1440 //60m in 1h, 1440m in 1d let _s = _timeDiff - _m*60 - _h*3600 - _d*86400 //60s in 1m, 3600s in 1h, 86400s in 1d if (_d > 0) { _returnString += (`${_d.toString().padStart(1,'0')}d `) } if (_d > 0 || _h > 0) { _returnString += (`${_h.toString().padStart(2,'0')}h `) } if (_d > 0 || _h > 0 || _m > 0) { _returnString += (`${_m.toString().padStart(2,'0')}m `) } _returnString += (`ago`) return _returnString } function timestampOldDiff(olderTimestamp) { var currentTimestamp = Math.floor(Date.now()/1000) if (olderTimestamp == 0) { return -1 } return currentTimestamp - olderTimestamp //time since last OC in seconds } const timerTick = () => { let _timeList = $("span.OC2-countdown") for (let i = 0; i < _timeList.length; i++) { $(_timeList[i]).html(timestampDiff(parseInt($(_timeList[i]).attr("data-countdown")))) } OC2_timerID = setTimeout(timerTick, 1000) $(".OC2-highlightText").css({ "color": "rgb(252, 196, 25)", "font-weight": "bold" }) if ($("body").css("background-color") == "rgb(204, 204, 204)") { $(".OC2-highlightText").css({ "color": "rgb(230, 119, 0)" }) } } //the nitty gritty functions function checkMembersInCrimes(_data) { //console.log(`checkMembersInCrimes`, _data) //put all member ids into a list for (let i = 0; i < (_data.members).length; i++) { if (_data.members[i].status.state == "Fallen") { //skip fallen members } else if (_data.members[i].position == "Recruit") { //skip recruits since they can't join OC skippedMemberCount += 1; skippedMemberList.push({ "id": _data.members[i].id, "name": _data.members[i].name }) } else { memberInfo[_data.members[i].id] = { "id": _data.members[i].id, "name": _data.members[i].name, "last_action": _data.members[i].last_action, "statusDesc": _data.members[i].status.description, "status": _data.members[i].status.state, "lastCrime": 0 } } } totalMembers = (_data.members).length - skippedMemberCount; activeMembers = 0 //if this doesn't reset, hashchange will cause the following part to re-fire and get activemembers count wrong. //go through crime list for (let i = 0; i < (_data.crimes).length; i++) { if (_data.crimes[i].status == 'Expired') { continue; //skip all expired crimes } //sort members into objects if ((_data.crimes[i].status == 'Successful' || _data.crimes[i].status == 'Failure')) { //for crimes that were complete, put that crime's info to member's last crime completed section for (let j=0; j<(_data.crimes[i].slots).length; j++) { //skip slots that are empty if (_data.crimes[i].slots[j].user_id) { //ignore members that left the faction if (!memberInfo[_data.crimes[i].slots[j].user_id]) { continue } let _lastCrimeTime = _data.crimes[i].ready_at if (_data.crimes[i].executed_at) { //take into account executed at, for crimes that were stalled _lastCrimeTime = _data.crimes[i].executed_at } if (memberInfo[_data.crimes[i].slots[j].user_id].lastCrime < _lastCrimeTime) { //make sure that the lastCrime in the memberInfo is the latest crime so far memberInfo[_data.crimes[i].slots[j].user_id].lastCrime = _lastCrimeTime } } } } if ((_data.crimes[i].status == 'Recruiting' || _data.crimes[i].status == 'Planning')) { //only if (_data.crimes[i].planning_at) { //if crime is not initiated, it will be null for planning_at. No point looking for members because there won't be any. for (let k=0; k<(_data.crimes[i].slots).length; k++) { if (_data.crimes[i].slots[k].user_id) { //ignore members that left the faction if (!memberInfo[_data.crimes[i].slots[k].user_id]) { continue } memberInfo[_data.crimes[i].slots[k].user_id].crimeInfo = { "crimeName": _data.crimes[i].name, "crimeDifficulty": _data.crimes[i].difficulty, "crimeId": _data.crimes[i].id, "crimePosition": _data.crimes[i].slots[k].position, "crimeSuccess": _data.crimes[i].slots[k].success_chance, } activeMembers = activeMembers + 1; if ((_data.crimes[i].slots[k].user_id) == getUserID()) { userInfo = memberInfo[_data.crimes[i].slots[k].user_id] userInfo.crimeInfo.crimeTime = _data.crimes[i].slots[k].ready_at } } } } } //sort crimes into arrays //crimes in recruiting include both crimes with members (has planning_at and with no members (don't have planning_at) if (_data.crimes[i].status == "Recruiting") { //get crimes with no members if (_data.crimes[i].planning_at == null) { crimeListUninitiated.push(_data.crimes[i]) } else { crimeListRecruiting.push(_data.crimes[i]) } } //crimes filled with members move to status = planning if (_data.crimes[i].status == "Planning") { crimeListPlanning.push(_data.crimes[i]) } } availableMembers = totalMembers - activeMembers; } function sortCrimeInfo() { //remove all crime Lis $(".OC2-memberViewer li.OC2-crimeLi").not(".OC2-memberViewer li[class*='OC2-titleLi']").remove() $("li.OC2-crimeMemberLi").remove() if (userSettings.sortType == "level-desc") { crimeListUninitiated.sort( (a,b) => a.difficulty - b.difficulty) crimeListRecruiting.sort( (a,b) => a.difficulty - b.difficulty) crimeListPlanning.sort( (a,b) => a.difficulty - b.difficulty) } else if (userSettings.sortType == "level-asc") { crimeListUninitiated.sort( (a,b) => b.difficulty - a.difficulty) crimeListRecruiting.sort( (a,b) => b.difficulty - a.difficulty) crimeListPlanning.sort( (a,b) => b.difficulty - a.difficulty) } else if (userSettings.sortType == "time-desc") { //asc and desc are swapped around. I don't know why but it works. Some math thing. I need to think about it. crimeListUninitiated.sort( (a,b) => a.expired_at - b.expired_at) crimeListRecruiting.sort( (a,b) => a.ready_at - b.ready_at) crimeListPlanning.sort( (a,b) => a.ready_at - b.ready_at) } else if (userSettings.sortType == "time-asc") { crimeListUninitiated.sort( (a,b) => b.expired_at - a.expired_at) crimeListRecruiting.sort( (a,b) => b.ready_at - a.ready_at) crimeListPlanning.sort( (a,b) => b.ready_at - a.ready_at) } } function sortAvailMembers() { $("li.OC2-memberAvailable").remove() if (userSettings.memberSort == "OC-asc") { availMemberList.sort( (a,b) => b.lastCrime - a.lastCrime ) } if (userSettings.memberSort == "OC-desc") { availMemberList.sort( (a,b) => a.lastCrime - b.lastCrime ) } if (userSettings.memberSort == "active-asc") { availMemberList.sort( (a,b) => a.last_action.timestamp - b.last_action.timestamp ) } if (userSettings.memberSort == "active-desc") { availMemberList.sort( (a,b) => b.last_action.timestamp - a.last_action.timestamp ) } } function putAvailMembersIntoTable(_memberArray, _afterElm) { if (_memberArray.length < 1) { return //don't do anything if there are no members } let _ignoreTitleText = "" let _skipTitleText = "" if (skippedMemberList.length > 0) { _skipTitleText = "Recruits unavailable for OCs:" skippedMemberList.forEach( (_skippedMemberName) => { _skipTitleText += (`<br />${_skippedMemberName.name} [${_skippedMemberName.id}]`) }) } _memberArray.forEach( (_member) => { if (userSettings.memberIgnoreList) { if (userSettings.memberIgnoreList.includes((_member.id).toString())) { if (_ignoreTitleText == "") { _ignoreTitleText = "Ignored members:" } _ignoreTitleText += `<br />${_member.name} [${_member.id}]` return //skip member to be ignored } } let _outputHTML = "" let _memberHighlight = "OC2-memberAvailable" let _memberInactiveTitle = `Last Action: ${_member.last_action.relative}` let _memberInactiveFill = colorObj.inactiveIcon.default[colorDisplayMode] let _memberCrimeFill = colorObj.crimeIcon.default[colorDisplayMode] if (_member.id == userInfo.id) { _memberHighlight += " OC2-userIndicator" } if (_member.lastCrime == 0) { //user is not found in the crimes obtained from the API _memberCrimeFill = colorObj.crimeIcon.highlightVeryRed[colorDisplayMode] } if (timestampOldDiff(_member.lastCrime) > parseInt(userSettings.lastOC_yellow) * 60 * 60) { _memberCrimeFill = colorObj.crimeIcon.highlightYellow[colorDisplayMode] } if (timestampOldDiff(_member.lastCrime) > parseInt(userSettings.lastOC_red) * 60 * 60) { _memberCrimeFill = colorObj.crimeIcon.highlightRed[colorDisplayMode] } if ( (Math.floor(Date.now()/1000) - _member.last_action.timestamp) > parseInt(userSettings.lastActivity) * 60 * 60) { _memberInactiveFill = colorObj.inactiveIcon.highlightRed[colorDisplayMode] } let _lastOnlineIcon = (`<svg xmlns="http://www.w3.org/2000/svg" stroke="transparent" stroke-width="0" width="11" height="11" viewBox="0 1 16 16"><g><path fill="${_memberInactiveFill}" d="M13.88,13.06c-2.29-.53-4.43-1-3.39-2.94C13.63,4.18,11.32,1,8,1S2.36,4.3,5.51,10.12c1.07,2-1.15,2.43-3.39,2.94C.13,13.52,0,14.49,0,16.17V17H16v-.83C16,14.49,15.87,13.52,13.88,13.06Z"></path></g></svg>`) let _lastCrimeIcon = (`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="11" height="11" viewBox="0 0 30 40"><path fill="${_memberCrimeFill} "d="M397,168c-7.573,0-15,5.76-15,13.333,0,4.589,3.375,10.129,6.512,14.524a10.05,10.05,0,0,1,16.935-.067c3.22-4.457,6.553-9.865,6.553-14.457C412,173.76,404.573,168,397,168Zm-5.83,18.333a4.166,4.166,0,1,1,4.167-4.166A4.167,4.167,0,0,1,391.17,186.333Zm11.667,0A4.166,4.166,0,1,1,407,182.167,4.166,4.166,0,0,1,402.837,186.333ZM397,194.52a6.74,6.74,0,1,0,6.74,6.74A6.741,6.741,0,0,0,397,194.52Zm1.752,2.458a1.07,1.07,0,1,1-1.07,1.07A1.071,1.071,0,0,1,398.752,196.978Zm-3.574,0a1.07,1.07,0,1,1-1.068,1.07A1.071,1.071,0,0,1,395.178,196.978Zm-1.918,5.35a1.07,1.07,0,1,1,1.07-1.07A1.071,1.071,0,0,1,393.26,202.328Zm1.918,3.212a1.069,1.069,0,1,1,1.07-1.07A1.07,1.07,0,0,1,395.178,205.54Zm.752-4.28a1.07,1.07,0,1,1,1.07,1.07A1.071,1.071,0,0,1,395.93,201.26Zm2.822,4.28a1.069,1.069,0,1,1,1.07-1.07A1.071,1.071,0,0,1,398.752,205.54Zm1.988-3.212a1.07,1.07,0,1,1,1.07-1.07A1.069,1.069,0,0,1,400.74,202.328Z" transform="translate(-382 -168)"></path></svg>`) _outputHTML = (`<li class="table-cell ${_memberHighlight}"> <div class="OC2-tableCell OC2-tableMember" title="${_member.name} [${_member.id}]<br />Last OC joined: ${stringifyTimestampOld(timestampOldDiff(_member.lastCrime))}<br />${_memberInactiveTitle}"> <div class="OC2-tableLastCrime OC2-lazyCountup" data-countup="${timestampOldDiff(_member.lastCrime)}"><span>${_lastCrimeIcon}</span></div> <div class="OC2-tableLastActive"><span class="">${_lastOnlineIcon}</span></div><a href="https://www.torn.com/profiles.php?XID=${_member.id}"> <span>${_member.name}</span><span class="screen-reader-hidden">: Last OC joined: ${stringifyTimestampOld(timestampOldDiff(_member.lastCrime))}: ${_memberInactiveTitle}</span></a> </div> <div class="OC2-tableCell OC2-tableStatus"><span class="screen-reader-hidden">Status:</span>${styleMemberStatus(_member.status,_member.statusDesc)}</div> </li>`) _afterElm.after(_outputHTML) }) $(".OC2-memberTableFooter").not(".OC2-settingsFooter").html(`<span title="${_skipTitleText}">${availableMembers} / ${totalMembers} members available</span> <span title="${_ignoreTitleText}">(${userSettings.memberIgnoreList.length} member${userSettings.memberIgnoreList.length == 1 ? "":"s"} manually ignored)</span>`) } function putMemberInfoIntoTable() { //fix for tornPDA, idk why but checking the li.tablecell works but checking the ul.table doesn't if ($(".OC2-memberTable .OC2-tableCell")[0]) { return } availMemberList = [] for (var _key of Object.keys(memberInfo)) { if (memberInfo[_key].crimeInfo) { continue //skip all members in crimes } availMemberList.push(memberInfo[_key]) } sortAvailMembers() putAvailMembersIntoTable(availMemberList, $(".OC2-memberTable li.OC2-titleLiAvailableMembers")) sortCrimeInfo() putCrimeInfoIntoTable(crimeListUninitiated, $(".OC2-memberTable li.OC2-titleLiUninitiated").eq(0)) putCrimeInfoIntoTable(crimeListRecruiting, $(".OC2-memberTable li.OC2-titleLiRecruiting").eq(0)) putCrimeInfoIntoTable(crimeListPlanning, $(".OC2-memberTable li.OC2-titleLiPlanning").eq(0)) convertItemIDArrayToItems() styleTable() checkDefaultHideState() if (OC2_timerID) { clearTimeout(OC2_timerID) } timerTick() } function putCrimeInfoIntoTable(_crimeArray, _afterElm) { let _countdownText = "" let _countdownToTimestamp = "" let _countdownMouseover = "" let _memberOutputHTML = "" let _userIndicatorClass = "" let _userIndicatorCrimeClass = "" if (_crimeArray.length > 0) { for (let i = 0; i < _crimeArray.length; i++) { //crimes in recruiting include both crimes with members (has planning_at) and with no members (don't have planning_at) if (_crimeArray[i].status == "Recruiting") { //get crimes with no members if (_crimeArray[i].planning_at == null) { _countdownText = "Expires: " _countdownToTimestamp = _crimeArray[i].expired_at _countdownMouseover = "Time until this crime is no longer be available" } else { _countdownText = "Join in:" _countdownToTimestamp = _crimeArray[i].ready_at _countdownMouseover = "Time until this crime needs a new member to join to continue planning" } } //crimes filled with members move to status = planning if (_crimeArray[i].status == "Planning") { _countdownText = "Ready in:" _countdownToTimestamp = _crimeArray[i].ready_at _countdownMouseover = "Time until this crime is ready to start" } _memberOutputHTML = "" _userIndicatorCrimeClass = "" let _memberCount = 0 //count number of slots filled for (let j = 0; j < (_crimeArray[i].slots).length; j++) { let _crimeSlotMemberName = `<span class="OC2-textGray"> N/A</span>` let _crimeSlotMemberID = "" let _crimeSlotMemberStatus = "" let _crimeSlotPosition = "" let _crimeItem = "" let _crimeItemMouseover = "" let _crimeItemIcon = (`🛠`) //🛠 🛠 if (isPDA()) { _crimeItemIcon = (`⚒`) // ⚒ $#9874; } let _crimeSuccess = "" let _crimeSuccessWrapper = "" _userIndicatorClass = "" if (_crimeArray[i].slots[j].item_requirement) { if(!(_crimeArray[i].slots[j].item_requirement.id in itemIDObj)) { itemIDObj[_crimeArray[i].slots[j].item_requirement.id] = { "name": "" }; } _crimeItemMouseover = (`Required item: <#${_crimeArray[i].slots[j].item_requirement.id}>`) if (_crimeArray[i].slots[j].item_requirement.is_reusable) { _crimeItemMouseover += (` (reusable)`) _crimeItemIcon += (`<span style="vertical-align:top">∞</span>`) } if (_crimeArray[i].slots[j].item_requirement.is_available) { _crimeItemMouseover += (`<br />Item is owned by member`) } _crimeItem = (`<span class="OC2-itemHave${_crimeArray[i].slots[j].item_requirement.is_available}">${_crimeItemIcon}</span>`) } if (_crimeArray[i].slots[j].user_id) { if (_crimeArray[i].slots[j].user_id == userInfo.id) { _userIndicatorClass = "OC2-userIndicator" _userIndicatorCrimeClass = "OC2-userIndicator" } _memberCount = _memberCount + 1 _crimeSlotMemberName = `<a href="https://www.torn.com/profiles.php?XID=${_crimeArray[i].slots[j].user_id}">${memberInfo[_crimeArray[i].slots[j].user_id].name}</a>` _crimeSlotMemberStatus = styleMemberStatus(memberInfo[_crimeArray[i].slots[j].user_id].status, memberInfo[_crimeArray[i].slots[j].user_id].statusDesc) if (_crimeArray[i].slots[j].success_chance > 75) { _crimeSuccessWrapper = "OC2-highSuccess" } else if (_crimeArray[i].slots[j].success_chance > 50) { _crimeSuccessWrapper = "OC2-midSuccess" } else { _crimeSuccessWrapper = "OC2-lowSuccess" } _crimeSuccess = (`<span class="${_crimeSuccessWrapper}">${_crimeArray[i].slots[j].success_chance}</span>`) } else { _crimeSuccess = (`<span class="OC2-textGray">-</span>`) } _memberOutputHTML += (`<li class="table-cell OC2-crimeMemberLi OC2-crimeID_${_crimeArray[i].id} ${_userIndicatorClass}"> <div class="OC2-tableCell OC2-tableCrimeMemberSuccess">${_crimeSuccess}</div> <div class="OC2-tableCell OC2-tableCrimeMemberItem" title="${_crimeItemMouseover}" >${_crimeItem}</div> <div class="OC2-tableCell OC2-hideSmall OC2-tableCrimePosition">${_crimeArray[i].slots[j].position}</div> <div class="OC2-tableCell OC2-tableCrimeMemberName">${_crimeSlotMemberName}</div> <div class="OC2-tableCell OC2-tableCrimeMemberStatus">${_crimeSlotMemberStatus}</div> </li>`) } let _outputHTML = (`<li class="table-cell OC2-crimeLi OC2-crimeID_${_crimeArray[i].id} ${_userIndicatorCrimeClass}"> <div class="OC2-tableCell OC2-tableCrimeMemberCount OC2-crimeID_${_crimeArray[i].id}">${_memberCount} / ${(_crimeArray[i].slots).length} <span class="hideMembersButton">${membersButtonShowText}</span></div> <div class="OC2-tableCell OC2-tableCrime"><a href="https://www.torn.com/factions.php?step=your&type=12#/tab=crimes&crimeId=${_crimeArray[i].id}">Lv${_crimeArray[i].difficulty} ${_crimeArray[i].name}</a></div> <div class="OC2-tableCell OC2-tableCountdown OC2-crimeID_${_crimeArray[i].id}" title="${_countdownMouseover}"><span class="OC2-countdownText OC2-hideSmall">${_countdownText}</span> <span class="OC2-countdown" data-countdown="${_countdownToTimestamp}">${_countdownToTimestamp}</span></div> </li>`) _afterElm.after(_outputHTML) $("li.OC2-crimeID_"+_crimeArray[i].id).after(_memberOutputHTML) $("div.OC2-crimeID_"+_crimeArray[i].id).off().on("click", (event) => { toggleMemberView(((event.currentTarget.attributes.class.value).split("OC2-crimeID_"))[1]) if ($(event.currentTarget).parent(".OC2-crimeLi").hasClass("OC2-crimeLiActive")) { $(event.currentTarget).parent(".OC2-crimeLi.OC2-crimeLiActive").removeClass("OC2-crimeLiActive") } else { $(event.currentTarget).parent(".OC2-crimeLi").not(".OC2-crimeLiActive").addClass("OC2-crimeLiActive") } styleCrimeLiActive() }).css({"cursor": "pointer"}) } } else { _afterElm.after(`<li class="table-cell OC2-crimeLi"><div class="OC2-tableCell OC2-tableCrime">None</div></li>`) } } //templating functions async function generateInsertHTML() { if ($(".OC2-memberViewer .OC2-memberTable")[0]) { return } let _insertHTML = (` <div class="category-wrap OC2-memberViewer m-top10"> <div class="title-black top-round t-overflow">OC 2.0 Overview <a href="https://www.torn.com/OC2_Settings_Page" target="_new"><span title="Go to Settings Page" class="extraSettingsButton">⚙</span></a><span class="hideLazyMembersButton">${lazyMembersButtonShowText}</span><span class="hideCrimesButton">${crimeButtonShowText}</span></div> <div class="cont-gray OC2-memberTableErrorDisplay" style="display:none; padding: 5px 0"></div> <div class="cont-gray OC2-memberTable" style="display:none"><ul class="table-body"> <li class="table-cell OC2-availableMembers OC2-titleLiAvailableMembers"><div class="OC2-titleCell OC2-fancyBg">Members not in an OC<div class="OC2-sortTypeMember">Sort: <div id="sortOCButton">OC</div><div id="sortActiveButton">active</div></div></div></li> <li class="table-cell OC2-crimeLi OC2-titleLiCrimeSeciton"><div class="OC2-titleCell OC2-fancyBg">Crimes<div class="OC2-sortType">Sort: <div id="sortLevelButton">level</div><div id="sortTimeButton">time</div></div></div></li> <li class="table-cell OC2-crimeLi OC2-titleLiUninitiated"><div class="OC2-titleCell">Uninitiated Crimes</div></li> <li class="table-cell OC2-crimeLi OC2-horizLine"></li> <li class="table-cell OC2-crimeLi OC2-titleLiRecruiting"><div class="OC2-titleCell">Recruiting Crimes</div></li> <li class="table-cell OC2-crimeLi OC2-horizLine"></li> <li class="table-cell OC2-crimeLi OC2-titleLiPlanning"><div class="OC2-titleCell">Full Crimes</div></li> </ul></div> <div class="OC2-memberTableFooter"></div> </div>`) //what to do in normal crimes2.0 page if (checkCrimesPage()) { $("div#faction-crimes").before(_insertHTML) checkDefaultSortState() styleTable() $(".hideCrimesButton").off().on("click", event => { toggleCrimeView() }) $(".OC2-sortType div").off().on("click", event => { resortCrimeTable(event.currentTarget) }) $(".OC2-sortTypeMember div").off().on("click", event => { resortAvailMemberTable(event.currentTarget) }) $(".hideLazyMembersButton").off().on("click", event => { toggleLazyMembersView() }) } else //this "else" is important to like the two if statements. Without it, it won't load on the faction -> crimes OC page because the second if statement takes precidence due to await //what to do if traveling AND on faction page if (await checkTravelFactionPage()) { waitForElm('div#react-root').then((elm) => { $(elm).before(_insertHTML) checkDefaultSortState() styleTable() $(".hideCrimesButton").off().on("click", event => { toggleCrimeView() }) $(".OC2-sortType div").off().on("click", event => { resortCrimeTable(event.currentTarget) }) $(".OC2-sortTypeMember div").off().on("click", event => { resortAvailMemberTable(event.currentTarget) }) $(".hideLazyMembersButton").off().on("click", event => { toggleLazyMembersView() }) if (myAPIData) { putMemberInfoIntoTable() } }) } } function checkDefaultHideState() { $(".OC2-memberTable").show() if (userSettings.memberShow == "member-hide") { $(".hideLazyMembersButton").html(lazyMembersButtonShowText) $(".OC2-availableMembers").hide() $(".OC2-memberAvailable").hide() } else { $(".hideLazyMembersButton").addClass("text-hide") $(".hideLazyMembersButton").html(lazyMembersButtonHideText) } if (userSettings.crimesShow == "crimes-hide") { $(".hideCrimesButton").html(crimeButtonShowText) $(".OC2-crimeMemberLi").hide() $(".OC2-crimeLi").hide() } else { $(".hideCrimesButton").addClass("text-hide") $(".hideCrimesButton").html(crimeButtonHideText) $(".OC2-crimeMemberLi").hide(); } } function checkDefaultSortState() { //userSettings.memberSort "OC-desc", //OC-asc / OC-desc / active-asc / active-desc //userSettings.sortType "time-asc", //time-asc / time-desc / level-asc / level-desc let _memberTarget = userSettings.memberSort.split("-")[0] let _memberDirection = userSettings.memberSort.split("-")[1] let _crimeTarget = userSettings.sortType.split("-")[0] let _crimeDirection = userSettings.sortType.split("-")[1] _memberTarget = _memberTarget[0].toUpperCase() + _memberTarget.slice(1) _crimeTarget = _crimeTarget[0].toUpperCase() + _crimeTarget.slice(1) let _arrowDisplayMember = settingsButtonAscText let _arrowDisplayCrime = settingsButtonAscText if (_memberDirection == "desc") { _arrowDisplayMember = settingsButtonDescText } if (_crimeDirection == "desc") { _arrowDisplayCrime= settingsButtonDescText } $(`.OC2-sortTypeMember div[id=sort${_memberTarget}Button]`).addClass("text-underline") $(`.OC2-sortTypeMember div[id=sort${_memberTarget}Button]`).html(`${_memberTarget.toLowerCase()}${_arrowDisplayMember}`) $(`.OC2-sortType div[id=sort${_crimeTarget}Button]`).addClass("text-underline") $(`.OC2-sortType div[id=sort${_crimeTarget}Button]`).html(`${_crimeTarget.toLowerCase()}${_arrowDisplayCrime}`) } function insertOCNotifier() { let _userNotice = (`<a href="https://www.torn.com/factions.php?step=your#/tab=crimes"><span class="OC2-redtext">No active OC.</span></a>`) let _userMouseover = (`You are not currently participating in an OC.`) if (userInfo.crimeInfo) { _userNotice = (`<span class="OC2-normaltext"><a href="https://www.torn.com/factions.php?step=your&type=5#/tab=crimes&crimeId=${userInfo.crimeInfo.crimeId}">Lv ${userInfo.crimeInfo.crimeDifficulty} ${userInfo.crimeInfo.crimeName}</a></span>`) _userMouseover = (`${userInfo.crimeInfo.crimePosition} (${userInfo.crimeInfo.crimeSuccess}%)`) } let _insertHTML = (`<div class="OC2-sidebarNotice" title="${_userMouseover}"><a href="https://www.torn.com/factions.php?step=your#/tab=crimes"><span style="font-weight: bold">OC 2.0:</span></a> ${_userNotice} </div>`) $('div[class^="sidebar_"] div[class^="user-information_"] div[class^="toggle-block_"] div[class^="toggle-content_"] div[class^="content_"]').append(_insertHTML) styleOCNotifier() } //on click functions function toggleCrimeView() { if ($(".hideCrimesButton").hasClass("text-hide")) { $(".hideCrimesButton").html(crimeButtonShowText) $(".hideCrimesButton").removeClass("text-hide") $(".OC2-crimeLi").slideUp() } else { $(".hideCrimesButton").html(crimeButtonHideText) $(".hideCrimesButton").addClass("text-hide") $(".OC2-crimeLi").slideDown() } $(".hideMembersButton").html(membersButtonShowText) $(".hideMembersButton").removeClass("text-hide") $(".OC2-crimeMemberLi").hide() $(".OC2-crimeLi.OC2-crimeLiActive").removeClass("OC2-crimeLiActive") styleCrimeLiActive() } function toggleMemberView(_crimeID) { if ($(".OC2-crimeID_"+_crimeID+" .hideMembersButton").hasClass("text-hide")) { $(".OC2-crimeID_"+_crimeID+" .hideMembersButton").html(membersButtonShowText) $(".OC2-crimeID_"+_crimeID+" .hideMembersButton").removeClass("text-hide") $(".OC2-crimeMemberLi.OC2-crimeID_"+_crimeID).slideUp() } else { $(".OC2-crimeID_"+_crimeID+" .hideMembersButton").html(membersButtonHideText) $(".OC2-crimeID_"+_crimeID+" .hideMembersButton").addClass("text-hide") $(".OC2-crimeMemberLi.OC2-crimeID_"+_crimeID).slideDown() } } //OC2-availableMembers function toggleLazyMembersView() { if ($(".hideLazyMembersButton").hasClass("text-hide")) { $(".hideLazyMembersButton").html(lazyMembersButtonShowText) $(".hideLazyMembersButton").removeClass("text-hide") $(".OC2-availableMembers").slideUp() $(".OC2-memberAvailable").slideUp() } else { $(".hideLazyMembersButton").html(lazyMembersButtonHideText) $(".hideLazyMembersButton").addClass("text-hide") $(".OC2-availableMembers").slideDown() $(".OC2-memberAvailable").slideDown() } } //<div class="OC2-sortType">Sort: <span id="sortLevelButton">level</span><span id="sortTimeButton">time</span></div> function resortCrimeTable(_target) { $(".OC2-sortType div").removeClass("text-underline") $(".OC2-sortType div#sortLevelButton").html("level") $(".OC2-sortType div#sortTimeButton").html("time") $(_target).addClass("text-underline") if ($(_target).attr("id") == "sortLevelButton") { if (userSettings.sortType == "level-asc") { userSettings.sortType = "level-desc" $(_target).html(`level${settingsButtonDescText}`) } else { userSettings.sortType = "level-asc" $(_target).html(`level${settingsButtonAscText}`) } } if ($(_target).attr("id") == "sortTimeButton") { if (userSettings.sortType == "time-asc") { userSettings.sortType = "time-desc" $(_target).html(`time${settingsButtonDescText}`) } else { userSettings.sortType = "time-asc" $(_target).html(`time${settingsButtonAscText}`) } } sortCrimeInfo() putCrimeInfoIntoTable(crimeListUninitiated, $(".OC2-memberTable li.OC2-titleLiUninitiated").eq(0)) putCrimeInfoIntoTable(crimeListRecruiting, $(".OC2-memberTable li.OC2-titleLiRecruiting").eq(0)) putCrimeInfoIntoTable(crimeListPlanning, $(".OC2-memberTable li.OC2-titleLiPlanning").eq(0)) convertItemIDArrayToItems() styleTable() timerTick() $("li.OC2-crimeLi .hideMembersButton").removeClass("text-hide") $("li.OC2-crimeMemberLi").hide() if ( !$(".hideLazyMembersButton").eq(0).hasClass("text-hide") ) { $("li.OC2-availableMembers").hide() $("li.OC2-memberAvailable").hide() } } //<div class="OC2-sortTypeMember">Sort: <div id="sortOCButton">last OC</div><div id="sortActiveButton">last active</div></div> function resortAvailMemberTable(_target) { $(".OC2-sortTypeMember div").removeClass("text-underline") $(".OC2-sortTypeMember div#sortOCButton").html("OC") $(".OC2-sortTypeMember div#sortActiveButton").html("active") $(_target).addClass("text-underline") if ($(_target).attr("id") == "sortOCButton") { if (userSettings.memberSort == "OC-asc") { userSettings.memberSort = "OC-desc" $(_target).html(`OC${settingsButtonAscText}`) } else { userSettings.memberSort = "OC-asc" $(_target).html(`OC${settingsButtonDescText}`) } } if ($(_target).attr("id") == "sortActiveButton") { if (userSettings.memberSort == "active-desc") { userSettings.memberSort = "active-asc" $(_target).html(`active${settingsButtonAscText}`) } else { userSettings.memberSort = "active-desc" $(_target).html(`active${settingsButtonDescText}`) } } sortAvailMembers() putAvailMembersIntoTable(availMemberList, $(".OC2-memberTable li.OC2-titleLiAvailableMembers")) styleTable() $("li.OC2-crimeLi .hideMembersButton").removeClass("text-hide") $("li.OC2-crimeLi.OC2-crimeLiActive").removeClass("OC2-crimeLiActive") styleCrimeLiActive() $("li.OC2-crimeMemberLi").hide() if ( !$(".hideCrimesButton").eq(0).hasClass("text-hide") ) { $("li.OC2-crimeLi").hide() } } //prettifying functions function styleCrimeLiActive() { $(".OC2-crimeLi.OC2-crimeLiActive").not(".OC2-userIndicator").css({ "background-color": "rgba(150,150,150,0.2)" }) $(".OC2-crimeLi").not(".OC2-crimeLiActive").not(".OC2-userIndicator").css({ "background-color": "transparent" }) if ($("#dark-mode-state").prop("checked")) { $(".OC2-crimeLi.OC2-crimeLiActive").not(".OC2-userIndicator").css({ "background-color": "rgba(0,0,0,0.3)" }) } } function styleMemberStatus(_statusState, _statusDesc) { return (`<span title="${_statusDesc}" class="OC2-statusText ${_statusState.toLowerCase()}">${_statusState}</span><span title="${_statusDesc}" class="OC2-statusText OC2-hideSmall ${_statusState.toLowerCase()}">${_statusDesc}</span>`) } function styleTable() { /* notes to self * Small: 386px * Tiny: 320px * Normal: 784px */ $(".OC2-memberTable ul.table-body").css({ "display": "flex", "flex-direction": "row", "flex-wrap": "wrap" }) $(".OC2-memberTable a").css({ "color": colorObj.link[colorDisplayMode], "text-decoration": "none" }) $(".extraSettingsButton").css({ "color": colorObj.dark_bg_link[colorDisplayMode], "text-decoration": "none" }) $(".extraSettingsButton").on("mouseenter", function(event) { $(event.currentTarget).css({ "color": colorObj.recolor.yellow[colorDisplayMode] }) }) $(".extraSettingsButton").on("mouseleave", function(event) { $(event.currentTarget).css({ "color": colorObj.dark_bg_link[colorDisplayMode] }) }) $(".OC2-memberTable a").hover( function() { $(this).css({ "text-decoration": "underline" }) }, function() { $(this).css({ "text-decoration": "none" }) }) $(".OC2-memberTable div.OC2-tableCrimeMemberName a").css({ "color": "inherit", }) $(".OC2-memberTable div.OC2-tableMember a").css({ "color": "inherit", }) $(".OC2-memberTable li.table-cell").css({ "display": "flex", "flex-direction": "row", }) $(".OC2-memberTable li.OC2-memberAvailable").css({ "font-weight": "normal", }) $(".OC2-memberTable .OC2-textGray").css({ "color": "rgb(153, 153, 153)", }) $(".OC2-memberTable div").css({ "font-size": "11px", "line-height": "12px", "padding": "5px 0" }) $(".OC2-memberTable div.OC2-titleCell").css({ "display": "inline", "font-family": "Fjalla One", "padding-left": "10px", "width": containerMaxWidth, "box-sizing": "border-box", }) $(".OC2-memberTable div.OC2-titleCell.OC2-fancyBg").css({ "background": "repeating-linear-gradient(90deg, #2e2e2e, #2e2e2e 2px, #282828 0, #282828 4px)", "color": colorObj.fancyBg[colorDisplayMode] }) $(".OC2-horizLine").css({ "border-bottom": "1px solid rgb(34,34,34)", "width": containerMaxWidth, "box-sizing": "border-box", "height": "3px", }) $(".OC2-memberTable div.OC2-tableLastCrime").css({ "width": "13px", "display": "inline-block", "padding": "0" }) $(".OC2-memberTable div.OC2-tableLastActive").css({ "width": "15px", "display": "inline-block", "padding": "0" }) $(".OC2-memberTable div.OC2-tableMember").css({ "width": "148px", }) $(".OC2-memberTable div.OC2-tableStatus").css({ "width": "222px", "text-align": "left" }) $(".OC2-statusText.okay").css({ "color": colorObj.recolor.green[colorDisplayMode] }) $(".OC2-statusText.abroad, .OC2-statusText.traveling").css({ "color": colorObj.recolor.blue[colorDisplayMode] }) $(".OC2-statusText.hospital").css({ "color": colorObj.recolor.red[colorDisplayMode] }) $(".OC2-statusText.jail").css({ "color": colorObj.recolor.red[colorDisplayMode] }) $(".OC2-memberTable div.OC2-tableStatus img").css({ "height": "11px" }) $(".OC2-memberTable div.OC2-tableCrimeMemberCount").css({ "width": "50px", }) $(".OC2-memberTable div.OC2-tableCrimePosition").css({ "width": "100px", "font-size": "10px", }) $(".OC2-memberTable div.OC2-tableCrimeMemberName").css({ "width": "230px", }) $(".OC2-memberTable div.OC2-tableCrimeMemberStatus").css({ "width": "auto", }) $(".OC2-memberTable div.OC2-tableCrimeMemberSuccess").css({ "width": "25px", "text-align": "center" }) $(".OC2-memberTable div.OC2-tableCrimeMemberItem").css({ "width": "40px", "text-align": "center" }) $(".OC2-memberTable .OC2-tableCrimeMemberSuccess .OC2-highSuccess").css({ "color": colorObj.recolor.green[colorDisplayMode] }) $(".OC2-memberTable .OC2-tableCrimeMemberSuccess .OC2-midSuccess").css({ "color": colorObj.recolor.yellow[colorDisplayMode] }) $(".OC2-memberTable .OC2-tableCrimeMemberSuccess .OC2-lowSuccess").css({ "color": colorObj.recolor.red[colorDisplayMode] }) $(".OC2-memberTable .OC2-itemHavetrue").css({ "color": colorObj.recolor.green[colorDisplayMode] }) $(".OC2-memberTable .OC2-itemHavefalse").css({ "color": colorObj.recolor.red[colorDisplayMode] }) $(".OC2-memberTable div.OC2-tableCrime").css({ "width": "337px", }) $(".OC2-memberTable div.OC2-tableCountdown").css({ "width": "auto" }) $(".OC2-memberTableFooter").css({ "border-radius": "0 0 5px 5px", "background-color": colorObj.footerbg[colorDisplayMode], "padding": "5px 5px 5px 10px", "text-align": "center" }) $(".hideCrimesButton").css({ "position": "absolute", "right": "10px", "cursor": "pointer" }) $(".hideLazyMembersButton").css({ "position": "absolute", "right": "100px", "cursor": "pointer" }) $(".OC2-memberTable li.OC2-memberAvailable").css({ "padding-left": "20px" }) $(".OC2-memberTable li.OC2-crimeMemberLi").css({ "padding-left": "25px", "background-color": colorObj.crimeselectbg[colorDisplayMode], "width": containerMaxWidth }) $(".OC2-memberTable li.OC2-crimeLi").not(".OC2-memberTable li[class*='OC2-titleLi']").css({ "padding-left": "20px", "width": containerMaxWidth }) $(".OC2-crimeLi").prev(".OC2-crimeMemberLi").css({ "border-radius": "0 0 15px 15px" }) $(".OC2-sortType").css({ "display": "inline-block", "padding-left": parseInt(containerMaxWidth) - 158 + "px", }) $(".OC2-sortType div").css({ "display": "inline-block", "font-family": "Arial", "padding": "0 0 0 5px", "width": "35px" }) $(".OC2-memberTable .OC2-sortType div").css({ "text-decoration": "none" }) $(".OC2-memberTable .OC2-sortType div.text-underline").css({ "text-decoration": "underline" }) $(".OC2-sortTypeMember").css({ "display": "inline", "padding-left": parseInt(containerMaxWidth) - 220 + "px", }) $(".OC2-sortTypeMember div").css({ "display": "inline-block", "font-family": "Arial", "padding": "0 0 0 5px", "width": "35px" }) $(".OC2-memberTable .OC2-sortTypeMember div").css({ "text-decoration": "none" }) $(".OC2-memberTable .OC2-sortTypeMember div.text-underline").css({ "text-decoration": "underline" }) $(".OC2-userIndicator").css({ "background-color": colorObj.userindicatorbg[colorDisplayMode] }) if (_isWindowTiny.matches) { styleTableTinyScreen() } else if (_isWindowSmall.matches) { styleTableSmallScreen() } else { styleTableBigScreen() } if (($(".OC2-crimeMemberLi").last().next()).length < 1) { $(".OC2-crimeMemberLi").last().css({ "border-radius": "0 0 15px 15px", }) } //hide screen reader fields $(".screen-reader-hidden").css({ "position": "absolute", "overflow": "hidden", "width": "1px", "height": "1px", "clip": "rect(1px, 1px, 1px, 1px)", "padding": "0", "border": "0", "white-space": "nowrap" }) } function styleTableSmallScreen() { //console.log("Smallscreen!") //total row length: 386 //margins: 20px <item> 10px //OC2-tableMember 260px $(".OC2-memberTable li.OC2-memberAvailable").css({ "padding-left": "15px" }) $(".OC2-hideSmall").css({ "display": "none" }) $(".OC2-memberTable div.OC2-tableStatus").css({ "width": "55px", "text-align": "left" }) $(".OC2-memberTable div.OC2-tableMember").css({ "width": "120px", }) $(".OC2-memberTable div.OC2-tableCrime").css({ "width": "210px", }) $(".OC2-memberTable div.OC2-tableCrimeMemberName").css({ "width": "220px", }) $(".OC2-statusText").not(".OC2-hideSmall").css({ "display": "" }) $(".OC2-memberTable div.OC2-tableCrimePosition").css({ "width": "70px", "font-size": "10px", }) $(".OC2-memberTable div.OC2-tableCrimeMemberName").css({ "width": "220px", }) $(".OC2-memberTable div.OC2-tableCrimeMemberStatus").css({ "width": "90px", "text-align": "left" }) $(".OC2-memberTable div.OC2-tableCrimeMemberSuccess").css({ "width": "18px", "text-align": "center" }) $(".OC2-memberTable div.OC2-tableCrimeMemberItem").css({ "width": "30px", "text-align": "center" }) } function styleTableTinyScreen() { //console.log("Tinyscreen!") $(".OC2-memberTable li.OC2-crimeLi").not(".OC2-memberTable li[class*='OC2-titleLi']").css({ "padding-left": "15px", "width": containerMaxWidth }) $(".OC2-hideSmall").css({ "display": "none" }) $(".OC2-tableCrimeMemberCount").css({ "width": "40px" }) $(".OC2-memberTable div.OC2-tableStatus").css({ "width": "90px", "text-align": "left" }) $(".OC2-memberTable div.OC2-tableCrime").css({ "width": "190px", }) $(".OC2-memberTable div.OC2-tableCrimeMemberName").css({ "width": "165px", }) $(".OC2-statusText").not(".OC2-hideSmall").css({ "display": "" }) $(".OC2-memberTable li.OC2-crimeMemberLi").css({ "padding-left": "18px", }) $(".OC2-memberTable li.OC2-memberAvailable").css({ "padding-left": "12px" }) $(".OC2-memberTable li.OC2-crimeLi").not(".OC2-memberTable li[class*='OC2-titleLi']").css({ "padding-left": "12px" }) } function styleTableBigScreen() { $(".OC2-hideSmall").css({ "display": "" }) $(".OC2-statusText").not(".OC2-hideSmall").css({ "display": "none" }) } function styleOCNotifier() { $(".OC2-sidebarNotice a").css({ "text-decoration": "none", "color": "inherit" }) $(".OC2-sidebarNotice .OC2-redtext").css({ "text-decoration": "none", "color": "rgb(255, 121, 76)" }) } //main functions /* if page is the crimes 2.0 page * -> if memberViewer table does NOT exist, get data and fill table * -> otherwise, show the table * -> otherwise, hide the table */ async function hashChangeFunction() { if (checkCrimesPage()) { if (!$(".OC2-memberViewer .OC2-memberTable")[0]) { generateInsertHTML(); if (!myAPIData) { try { let _successfulGetAPIData = await getAndAnalyzeAPIData() if (_successfulGetAPIData.error) { $(".OC2-memberTable").hide() $(".OC2-memberTableErrorDisplay").html(`<span style="margin-left: 20px">Error occured: ${_successfulGetAPIData.error.error}. Please visit the <a href="https://www.torn.com/OC2_Settings_Page" target="_new" style="color: inherit; font-weight: bold; text-decoration: underline">Settings Page</a> to set up an API key</span>`) $(".OC2-memberTableErrorDisplay").show() } else { putMemberInfoIntoTable() } } catch(_err) { console.log("hashchangefunction caught error:", _err) return } } else { if (alreadyLoading == false) { putMemberInfoIntoTable() } } } else { $(".OC2-memberViewer").show() } } else { if ($(".OC2-memberViewer .OC2-memberTable")[0]) { $(".OC2-memberViewer").hide(); } } } async function runOnceFunction() { //load saved data await getUserSettings() await getAPIKey() //prepare settings page if on correct URL if ($(location).attr("pathname").search("OC2_Settings_Page") >= 0) { $(document).prop('title', 'OC2 Overview - Settings | TORN'); $("div.main-wrap").removeClass("error-404") $("div.content-title #skip-to-content").text("OC 2.0 Overview: Settings") prepareSettingsPage() getSavedValues() settingsFillSelect() } //insert member overview if (checkCrimesPage() || await checkTravelFactionPage()) { if (!$(".OC2-memberViewer .OC2-memberTable")[0]) { alreadyLoading = true; generateInsertHTML() if (!myAPIData) { try { let _successfulGetAPIData = await getAndAnalyzeAPIData() if (_successfulGetAPIData.error) { $(".OC2-memberTable").hide() $(".OC2-memberTableErrorDisplay").html(`<span style="margin-left: 20px">Error occured: ${_successfulGetAPIData.error.error}. Please visit the <a href="https://www.torn.com/OC2_Settings_Page" target="_new" style="color: inherit; font-weight: bold; text-decoration: underline">Settings Page</a> to set up an API key</span>`) $(".OC2-memberTableErrorDisplay").show() } else { putMemberInfoIntoTable() } } catch(_err) { console.log("runOnceFunction caught error:", _err) return } } } else { $(".OC2-memberViewer").show() } } //sidebar notifier, but not if the sidebar doesn't exist if (userSettings.showSidebarOC == "sidebar-show") { if ( ($("div[class*='sidebar_'][class*='desktop_']")[0]) && (!isPDA()) ) { if (!myAPIData) { let _successfulGetAPIData = await getAndAnalyzeAPIData() if (_successfulGetAPIData.error) { return } } insertOCNotifier() } } } //taken from stackoverflow https://stackoverflow.com/questions/5525071/how-to-wait-until-an-element-exists because mutation observer confuses me //needed because the faction page info only loads after the document is ready function waitForElm(selector) { return new Promise(resolve => { if (document.querySelector(selector)) { return resolve(document.querySelector(selector)); } const observer = new MutationObserver(mutations => { if (document.querySelector(selector)) { observer.disconnect(); resolve(document.querySelector(selector)); } }); // If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336 observer.observe(document.body, { childList: true, subtree: true }); }); } function checkWindowWidth() { if (_isWindowNormal.matches) { containerMaxWidth = "784px" containerBigMaxWidth = "976px" } else if (_isWindowSmallish.matches) { containerMaxWidth = "784px" containerBigMaxWidth = "578px" }else if (_isWindowSmall.matches) { containerMaxWidth = "386px" containerBigMaxWidth = "578px" } else if (_isWindowTiny.matches) { containerMaxWidth = "320px" containerBigMaxWidth = "320px" } if (!isPDA()) { styleTable() } } _isWindowNormal.addEventListener("change", function() { checkWindowWidth() }); _isWindowSmallish.addEventListener("change", function() { checkWindowWidth() }); _isWindowSmall.addEventListener("change", function() { checkWindowWidth() }); _isWindowTiny.addEventListener("change", function() { checkWindowWidth() }); checkWindowWidth() runOnceFunction() $(window).on('hashchange', hashChangeFunction) $("#dark-mode-state").on('change', modeChangeFunction) function modeChangeFunction() { colorDisplayMode = $("body#body").hasClass("dark-mode") ? "darkmode" : "lightmode" styleTable() checkDefaultHideState() styleSettings() } /* ==== * Settings page stuff * ==== */ async function testAPIKey(_APIKey) { $(".OC2-APITestResults div[id^=OC2-APITestResult-]").remove() $(".OC2-APITestResults").append(`<div>Testing...</div>`) let _insertHTML = "" return await $.ajax({ dataType: "json", url: (`https://api.torn.com/key/?selections=info&key=${_APIKey}`) }).then( data => { try { let _testResults = { "limited": data.access_level >= 2, "basic": data.selections.faction.includes("basic"), "crimes": data.selections.faction.includes("crimes"), "members": data.selections.faction.includes("members"), "items": data.selections.torn.includes("items"), "final": false } _testResults.final = (_testResults.limited && _testResults.basic && _testResults.crimes && _testResults.members && _testResults.items) let _insertHTML = (` <div id="OC2-APITestResult-Limited" class="${_testResults.limited ? "color-green" : "color-red"}">Minimal Key (or higher) ${_testResults.limited ? "OK" : "X"}</div> <div id="OC2-APITestResult-Basic" class="${_testResults.basic ? "color-green" : "color-red"}">/v2/factions/basic ${_testResults.basic ? "OK" : "X"}</div> <div id="OC2-APITestResult-Crimes" class="${_testResults.crimes ? "color-green" : "color-red"}">/v2/factions/crimes ${_testResults.crimes ? "OK" : "X"}</div> <div id="OC2-APITestResult-Members" class="${_testResults.members ? "color-green" : "color-red"}">/v2/factions/members ${_testResults.members ? "OK" : "X"}</div> <div id="OC2-APITestResult-Items" class="${_testResults.items ? "color-green" : "color-red"}">/v1/torn/items ${_testResults.items ? "OK" : "X"}</div> <div id="OC2-APITestResult-Final" class="${_testResults.final ? "color-green" : "color-red"}">${_testResults.final ? "API Key good to go! Save settings to enable Member Ignore List" : "API Key not usable!"}</div> `) $(".OC2-APITestResults div").remove() $(".OC2-APITestResults").append(_insertHTML) } catch(err) { $(".OC2-APITestResults div").remove() $(".OC2-APITestResults").append(`<div id="OC2-APITestResult-Fail" class="color-red">Error: API Key not valid</div>`) } $(".OC2-APITestResults div[id^=OC2-APITestResult-]").css({ "margin-left": "15px" }) $("div[id^=OC2-APITestResult-].color-green").css({ "color": colorObj.recolor.green[colorDisplayMode] }) $("div[id^=OC2-APITestResult-].color-red").css({ "color": colorObj.recolor.red[colorDisplayMode] }) $(".OC2-APITestButton").off().on("click", (event) => { APITestClickEvent(event) }) }) } async function setSavedValues() { let _userValues = { "memberShow": $("input[name=OC2-display-choice-availMembers]:checked")[0].value, "crimesShow": $("input[name=OC2-display-choice-crimes]:checked")[0].value, //crimes-hide / crimes-show "sortType": $("input[name=OC2-display-choice-crimes-sort]:checked")[0].value, //time-asc / time-desc / level-asc / level-desc "memberSort": $("input[name=OC2-display-choice-availMembers-sort]:checked")[0].value, //OC-asc / OC-desc / active-asc / active-desc "lastOC_yellow": $(`input[id=OC-indicator-yellow]`).val(), "lastOC_red": $(`input[id=OC-indicator-red]`).val(), "lastActivity": $(`input[id=activity-indicator]`).val(), "memberIgnoreList": displayIgnoreList, "showSidebarOC": $("input[name=OC2-display-choice-sidebarShow]:checked")[0].value //sidebar-show / sidebar-hide } //aAAAAAAAAAAAAAAAA await setUserSettings(_userValues) await getUserSettings() if ( $("#OC2-APITestResult-Final").hasClass("color-green") ) { await saveAPIKey() $("#OC2-addToIgnoreButton").show() $("#OC2-ignoreMemberInput").prop("disabled", false) $("#OC2-ignoreMemberSelect").prop("disabled", false) $(".OC2-errorAPIKey").remove() settingsFillSelect() } getSavedValues() } async function saveAPIKey() { let _userKey = $("#OC2-APIInput").val() await GM.setValue("CMR_OC2_APIKey", _userKey) await getAPIKey() } async function replaceSavedValues() { displayIgnoreList = [] userSettings = defaultUserSettings getSavedValues() } function getSavedValues() { $(`input[name=OC2-display-choice-availMembers][id=${userSettings.memberShow}]`).prop("checked", true) $(`input[name=OC2-display-choice-crimes][id=${userSettings.crimesShow}]`).prop("checked", true) $(`input[name=OC2-display-choice-crimes-sort][id=${userSettings.sortType}]`).prop("checked", true) $(`input[name=OC2-display-choice-availMembers-sort][id=${userSettings.memberSort}]`).prop("checked", true) $(`input[name=OC2-display-choice-sidebarShow][id=${userSettings.showSidebarOC}]`).prop("checked", true) $(`input[id=OC-indicator-yellow]`).val(userSettings.lastOC_yellow) $(`input[id=OC-indicator-red]`).val(userSettings.lastOC_red) $(`input[id=activity-indicator]`).val(userSettings.lastActivity) fillMemberIgnoreList() } function APITestClickEvent(_event) { $("#OC2-APIInput").val( $("#OC2-APIInput").val().trim() ) //trim trailing spaces let _testKey = $("#OC2-APIInput").val() testAPIKey(_testKey) } async function deleteAPIKey() { $(".OC2-errorAPIKey").remove() $(".OC2-APITestResults div").remove() if (isPDA()) { $(".OC2-APITestResults").append(`<div class="color-yellow">TornPDA: Unable to remove API Key via script because it's saved on TornPDA itself.</div>`) return } GM.setValue("CMR_OC2_APIKey", null) APIKey = null $(".OC2-APITestResults").append(`<div class="color-red">API Key removed from script memory. If you wish to be sure that your API key is secure, delete the provided key from torn's settings page.</div>`) $("#OC2-APIInput").val(APIKey? APIKey : "") settingsFillSelect() } function prepareSettingsPage() { let _displayAPIKey = "API Key saved in TornPDA" if (!isPDA()) { _displayAPIKey = APIKey? APIKey : "" } let _injectHTML = (` <div id="OC2-Settings" class="category-wrap m-top10"> <div class="title-black top-round t-overflow">OC 2.0 Settings</div> <div class="cont-gray OC2-settingsTable"><ul class="table-body"> <li class="table-cell OC2-settingsTitle"><div class="OC2-titleCell OC2-fancyBg">API Key</div></li> <li class="table-cell OC2-settingsSection"> <div class="OC2-settingsCell"><input id="OC2-APIInput" type="textbox" style="line-height: 14px; padding: 10px 8px" value="${_displayAPIKey}" /><div id="OC2-APITestButton" class="OC2-button">Test API Key</div></div> </li> <li class="table-cell OC2-settingsSection"> <div class="OC2-settingsCell"><div id="OC2-deleteAPIKeyButton" class="OC2-button">Delete API Key</div></div> </li> <li class="table-cell OC2-settingsSection"> <div class="OC2-settingsCell OC2-APITestResults"> </div> </li> <li class="table-cell OC2-horizLine"></li> <li class="table-cell OC2-memberAvailable OC2-settingsTitle"><div class="OC2-titleCell OC2-fancyBg">Preferences</div></li> <li class="table-cell OC2-settingsSection"> <div class="OC2-settingsCell"> <div class="OC2-settingsSubTitle">Default View</div> <fieldset class="OC2-choice"> <legend>Show OC information in sidebar?</legend> <div class="OC2-choice-buttons"> <input type="radio" name="OC2-display-choice-sidebarShow" id="sidebar-show" value="sidebar-show" /><label for="sidebar-show">Yes</label> <input type="radio" name="OC2-display-choice-sidebarShow" id="sidebar-hide" value="sidebar-hide" /><label for="sidebar-hide">No</label> </div> </fieldset> <fieldset class="OC2-choice"> <legend>Show "Members not in an OC" section?</legend> <div class="OC2-choice-buttons"> <input type="radio" name="OC2-display-choice-availMembers" id="member-show" value="member-show" /><label for="member-show">Yes</label> <input type="radio" name="OC2-display-choice-availMembers" id="member-hide" value="member-hide" /><label for="member-hide">No</label> </div> </fieldset> <fieldset class="OC2-choice"> <legend>Default sort for "Members not in an OC"?</legend> <div class="OC2-choice-buttons"> <input type="radio" name="OC2-display-choice-availMembers-sort" id="OC-desc" value="OC-desc" /><label for="OC-desc">OC: Asc </label> <input type="radio" name="OC2-display-choice-availMembers-sort" id="OC-asc" value="OC-asc" /><label for="OC-asc">OC: Desc</label> <input type="radio" name="OC2-display-choice-availMembers-sort" id="active-asc" value="active-asc" /><label for="active-asc">Active: Asc</label> <input type="radio" name="OC2-display-choice-availMembers-sort" id="active-desc" value="active-desc" /><label for="active-desc">Active: Desc</label> </div> </fieldset> <fieldset class="OC2-choice"> <legend>Show "Crimes" section?</legend> <div class="OC2-choice-buttons"> <input type="radio" name="OC2-display-choice-crimes" id="crimes-show" value="crimes-show" /><label for="crimes-show">Yes</label> <input type="radio" name="OC2-display-choice-crimes" id="crimes-hide" value="crimes-hide" /><label for="crimes-hide">No</label> </div> </fieldset> <fieldset class="OC2-choice"> <legend>Default sort for "Crimes"?</legend> <div class="OC2-choice-buttons"> <input type="radio" name="OC2-display-choice-crimes-sort" id="time-asc" value="time-asc" /><label for="time-asc">Time: Asc</label> <input type="radio" name="OC2-display-choice-crimes-sort" id="time-desc" value="time-desc" /><label for="time-desc">Time: Desc</label> <input type="radio" name="OC2-display-choice-crimes-sort" id="level-asc" value="level-asc" /><label for="level-asc">Level: Asc</label> <input type="radio" name="OC2-display-choice-crimes-sort" id="level-desc" value="level-desc" /><label for="level-desc">Level: Desc</label> </div> </fieldset> </div> </li> <li class="table-cell OC2-horizLine"></li> <li class="table-cell OC2-settingsSection"> <div class="OC2-settingsCell"> <div class="OC2-settingsSubTitle">Highlight & Indicator settings</div> <ul> <li><div class="OC2-settingsText"><div class="OC2-settingsLabel">Time since last OC for 'yellow' highlight:</div><input id="OC-indicator-yellow" type="textbox" style="line-height: 12px; padding: 5px" placeholder="24" size="10" /> hours</div></li> <li><div class="OC2-settingsText"><div class="OC2-settingsLabel">Time since last OC for 'red' highlight:</div><input id="OC-indicator-red" type="textbox" style="line-height: 12px; padding: 5px" placeholder="48" size="10" /> hours</div></li> <li><div class="OC2-settingsText"><div class="OC2-settingsLabel">Time since last activity for 'inactive' indicator:</div><input id="activity-indicator" type="textbox" style="line-height: 12px; padding: 5px" palceholder="96" size="10" /> hours</div></li> </ul> </div> </li> <li class="table-cell OC2-horizLine"></li> <li class="table-cell OC2-settingsSection"> <div class="OC2-settingsCell"> <div class="OC2-settingsSubTitle">Member Ignore List</div> <div class="OC2-settingsText"> <div class="OC2-memberIgnoreWrapper">Add member: <input id="OC2-ignoreMemberInput" type="textbox" /> <select id="OC2-ignoreMemberSelect"> <option class="default-option" value="" selected></option> </select> <div id="OC2-addToIgnoreButton" class="OC2-button">Add</div> </div> </div> <div class="OC2-settingsText">Ignored Members: <ul class="OC2-memberIgnoreList"> <li class="OC2-ignoreTitles" style="font-weight: bold; margin-bottom: 5px"><div class="OC2-ignoreName">Member Name [id]</div> <div class="OC2-ignoreTime">Last Active Time</div><div class="OC2-ignoreButtons">Action</div></li> </ul> </div> </div> </li> <li class="table-cell OC2-horizLine"></li> <li class="table-cell OC2-settingsSection"> <div class="OC2-settingsCell"> <div id="OC2-buttonResult"></div> <div class="OC2-buttonDiv"> <div id="OC2-APIResetButton" class="OC2-button">Reset to Default</div><div id="OC2-APISaveButton" class="OC2-button">Save Changes</div> </div> </div> </li> </ul></div> <div class="OC2-memberTableFooter OC2-settingsFooter"></div> </div> `) $("div.main-wrap").html(_injectHTML) //onclick functions $("#OC2-APITestButton").off().on("click", (event) => { APITestClickEvent(event) }) $("#OC2-APISaveButton").off().on("click", (event) => { setSavedValues() .then( () => { $("#OC2-buttonResult").html("Settings saved!") if ($("#OC2-buttonResult").is(":visible")) { $("#OC2-buttonResult").slideUp("fast") } $("#OC2-buttonResult").slideDown("slow") }) }) $("#OC2-APIResetButton").off().on("click", (event) => { replaceSavedValues() .then( () => { $("#OC2-buttonResult").html("Settings reset to default") if ($("#OC2-buttonResult").is(":visible")) { $("#OC2-buttonResult").slideUp("fast") } $("#OC2-buttonResult").slideDown("slow") }) }) $("#OC2-deleteAPIKeyButton").off().on("click", (event) => { deleteAPIKey() }) if (isPDA()) { $("#OC2-APIInput").prop("disabled", true) $("#OC2-APITestButton").off() $("#OC2-deleteAPIKeyButton").off() } $("#OC2-ignoreMemberInput").off() $("#OC2-ignoreMemberSelect").off() $("#OC2-ignoreMemberInput").on("keyup", (event) => { $("#OC2-ignoreMemberSelect option").not(".default-option").remove() let _insertOption = "" let _displayMemberList = myAPIData.members.filter((member) => (member.name.toLowerCase()).search(event.currentTarget.value.toLowerCase()) > -1) _displayMemberList.forEach( (member) => { _insertOption += (`<option value="${member.id}">${member.name} [${member.id}]</option>`) }) $("#OC2-ignoreMemberSelect").append(_insertOption) $("#OC2-ignoreMemberSelect").attr("size", Math.min(7,_displayMemberList.length+1)) }) $("#OC2-ignoreMemberInput").on("focus", (event) => { $("#OC2-ignoreMemberSelect").attr("size", 7) }) $("#OC2-ignoreMemberInput").on("blur", (event) => { if (event.relatedTarget != $("#OC2-ignoreMemberSelect")[0]) { $("#OC2-ignoreMemberSelect").attr("size", 0) } }) $("#OC2-ignoreMemberSelect").on("change", (event) => { $("#OC2-ignoreMemberInput").val($("#OC2-ignoreMemberSelect :selected").text()) $("#OC2-ignoreMemberSelect").attr("size", 0) }) $("#OC2-addToIgnoreButton").off().on("click", (event) => { let _memberToIgnore = $("#OC2-ignoreMemberSelect :selected").val().toString() if (displayIgnoreList.includes(_memberToIgnore)) { return //do nothing } else { displayIgnoreList.push(_memberToIgnore) fillMemberIgnoreList() } }) styleSettings() } function styleSettings() { colorDisplayMode = $("body#body").hasClass("dark-mode") ? "darkmode" : "lightmode" $(".OC2-horizLine").css({ "border-bottom": "1px solid rgb(34,34,34)", "width": containerBigMaxWidth, "box-sizing": "border-box", "height": "3px", }) $(".OC2-buttonDiv").css({ "display": "flex", "flex-direction": "row", "justify-content": "flex-end", "width": parseInt(containerBigMaxWidth) - 30 + "px" }) $("#OC2-buttonResult").css({ "margin": "3px auto 8px -8px", "text-align": "center", "padding": "5px 0", "background-color": colorObj.userindicatorbg[colorDisplayMode], "display": "none", "width": "100%" }) $(".OC2-APITestResults").css({ "display": "flex", "flex-direction": "row", "flex-wrap": "wrap" }) $(".OC2-choice").css({ "display": "flex", "flex-direction": "row", "flex-wrap": "wrap" }) $(".OC2-settingsSubTitle").css({ "margin-bottom": "10px", "font-weight": "bold" }) $(".OC2-settingsLabel").css({ "width": "300px", "display": "inline-block" }) $("fieldset.OC2-choice").css({ "display": "inline-block", "width": "100%", "margin": "5px 0 5px 10px" }) $("fieldset.OC2-choice .OC2-choice-buttons").css({ "display": "flex", "flex-direction": "row", }) $("fieldset.OC2-choice legend").css({ "float": "left", "width": "300px" }) $("fieldset.OC2-choice label").css({ "display": "inline-block", "margin": "0 10px 0 5px" }) $(".OC2-settingsText").css({ "margin-left": "11px", }) $("#OC2-Settings ul.table-body").css({ "display": "flex", "flex-direction": "row", "flex-wrap": "wrap" }) $("#OC2-Settings li.table-cell").css({ "display": "flex", "flex-direction": "row", "width": "100%", "font-size": "12px", }) $("#OC2-Settings .OC2-titleCell.OC2-fancyBg").css({ "width": "100%", "background": "repeating-linear-gradient(90deg, #2e2e2e, #2e2e2e 2px, #282828 0, #282828 4px)", "padding": "5px 0", "padding-left": "10px", "font-weight": "bold", "color": colorObj.fancyBg[colorDisplayMode] }) $("#OC2-Settings .OC2-settingsCell").css({ "padding": "5px 0", "margin-left": "15px", "font-weight": "normal", "width": "100%" }) $(".OC2-button").css({ "margin-left": "5px", "padding": "5px 10px", "text-align": "center", "display": "inline-block", "background": colorObj.buttons.background[colorDisplayMode], "cursor": "pointer", "color": colorObj.buttons.textcolor[colorDisplayMode] }) $(".OC2-button").on("mouseenter", function(event) { $(event.currentTarget).css({ "background": colorObj.buttons.hovercolor[colorDisplayMode] }) }) $(".OC2-button").on("mouseleave", function(event) { $(event.currentTarget).css({ "background": colorObj.buttons.background[colorDisplayMode] }) }) $(".OC2-memberIgnoreWrapper").css({ "position": "relative", "margin-bottom": "15px", "margin-top": "10px", "display": "inline-block" }) $("#OC2-addToIgnoreButton").css({ "position": "absolute", "left": "310px", "top": "-4px" }) $("#OC2-ignoreMemberSelect").css({ "position": "absolute", "top": "0px", "left": "105px", "width": "200px", }) $("#OC2-ignoreMemberInput").css({ "position": "absolute", "top": "-7px", "left": "100px", "width": "200px", "padding": "5px", "z-index": "10" }) styleMemberIgnoreList() if (_isWindowTiny.matches || _isWindowSmall.matches ) { styleSettingsTiny() } else if (_isWindowSmallish.matches) { styleSettingsMiddle() } if (isPDA()) { $("#OC2-ignoreMemberInput").off() $("#OC2-ignoreMemberInput").css({ "display": "none" }) $("#OC2-APITestButton").hide() $("#OC2-deleteAPIKeyButton").hide() } } function styleSettingsMiddle() { $("fieldset.OC2-choice legend").css({ "float": "left", "width": "240px" }) } function styleSettingsTiny() { $(".OC2-settingsCell").css({ "margin-left": "10px" }) $("fieldset.OC2-choice").css({ "margin": "5px 0 5px 5px", }) $("fieldset.OC2-choice legend").css({ "float": "none", "margin-bottom": "5px", }) $("fieldset.OC2-choice .OC2-choice-buttons").css({ "margin-left": "10px", }) $("fieldset.OC2-choice label").css({ "margin": "0 3px 0 3px", "width": "50px" }) $(".OC2-settingsText").css({ "margin-left": "5px", "margin-bottom": "5px" }) $("#OC2-addToIgnoreButton").css({ "left": "240px", "top": "-4px" }) $("#OC2-ignoreMemberSelect").css({ "top": "0px", "left": "85px", "width": "150px", }) $("#OC2-ignoreMemberInput").css({ "top": "-7px", "left": "80px", "width": "150px", "padding": "5px", "z-index": "10" }) $(".OC2-memberIgnoreList").css({ "margin": "5px 0 0 0", }) $(".OC2-memberIgnoreList li").not("li.OC2-ignoreTitles").css({ "align-items": "center" }) $(".OC2-ignoreName").css({ "width": "120px" }) $(".OC2-ignoreTime").css({ "width": "120px", }) $(".OC2-buttonDiv").css({ "justify-content": "center", "padding-bottom": "50px" }) } function styleMemberIgnoreList() { colorDisplayMode = $("body#body").hasClass("dark-mode") ? "darkmode" : "lightmode" $(".OC2-memberIgnoreList a").css({ "color": "inherit" }) $(".OC2-memberIgnoreList").css({ "display": "flex", "flex-direction": "row", "margin": "5px 0 0 10px", "flex-wrap": "wrap" }) $(".OC2-memberIgnoreList li").css({ "display": "flex", "flex-direction": "row", "width": parseInt(containerBigMaxWidth) + "px", "padding": "3px 0", "align-items": "center" }) $(".OC2-ignoreName").css({ "width": "200px" }) $(".OC2-ignoreTime").css({ "width": "200px" }) $(".OC2-ignoreButtons .OC2-button").css({ "margin-top": "3px", "margin-left": "-10px", "padding": "5px 10px", "text-align": "center", "display": "inline-block", "background": colorObj.buttons.background[colorDisplayMode], "cursor": "pointer", "color": colorObj.buttons.textcolor[colorDisplayMode] }) $(".OC2-button").on("mouseenter", function(event) { $(event.currentTarget).css({ "background": colorObj.buttons.hovercolor[colorDisplayMode] }) }) $(".OC2-button").on("mouseleave", function(event) { $(event.currentTarget).css({ "background": colorObj.buttons.background[colorDisplayMode] }) }) if (_isWindowSmall.matches || _isWindowTiny.matches ) { styleSettingsTiny() } } function fillMemberIgnoreList() { $(".OC2-memberIgnoreList li").not("li.OC2-ignoreTitles").remove() //this breaks easily lol if (!userSettings.memberIgnoreList) { return } if (!displayIgnoreList) { return } if (displayIgnoreList.length == 0) { return } displayIgnoreList.forEach( (_id) => { _id = _id.toString() if (!memberInfo[_id]) { return } $(".OC2-memberIgnoreList").append(`<li data-memberid="${_id}"> <div class="OC2-ignoreName">${memberInfo[_id].name} [${_id}]</div> <div class="OC2-ignoreTime">${memberInfo[_id].last_action.relative}</div> <div class="OC2-ignoreButtons"><div class="OC2-button">Remove</div></div> </li>`) $(`li[data-memberid=${_id}] div.OC2-button`).off().on("click", (event) => { displayIgnoreList = displayIgnoreList.filter(item => item !== _id) fillMemberIgnoreList() }) }) styleMemberIgnoreList() } async function settingsFillSelect() { if (!myAPIData) { let _APITest = await getAndAnalyzeAPIData() if (_APITest.error) { $("#OC2-addToIgnoreButton").hide() $("#OC2-ignoreMemberInput").prop("disabled", true) $("#OC2-ignoreMemberSelect").prop("disabled", true) $(".OC2-memberIgnoreWrapper").parent().prepend(`<div class="color-red OC2-errorAPIKey">This function requires an API key to be registered</div>`) return } } let _insertOption = "" let _displayMemberList = myAPIData.members _displayMemberList.sort( (a,b) => (a.name).localeCompare(b.name)) _displayMemberList.forEach( (member) => { _insertOption += (`<option value="${member.id}">${member.name} [${member.id}]</option>`) }) $("#OC2-ignoreMemberSelect").append(_insertOption) //fill up displayIgnoreList, also syntax is like this as a PDA fix if (userSettings.memberIgnoreList) { displayIgnoreList = userSettings.memberIgnoreList } else { displayIgnoreList = [ ] } fillMemberIgnoreList() }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址