Skip to content

Commit 3d68b7e

Browse files
Sidebar timer for OC 2. (#831)
* Load organized crime data. * Sidebar timer for OC 2.
1 parent 53098bc commit 3d68b7e

File tree

8 files changed

+181
-7
lines changed

8 files changed

+181
-7
lines changed

extension/changelog.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": { "major": 7, "minor": 4, "build": 3 },
44
"title": "Beta",
55
"date": false,
6-
"logs": { "features": [], "fixes": [], "changes": [], "removed": [] }
6+
"logs": { "features": [{ "message": "Sidebar timer for OC 2.", "contributor": "DeKleineKobini" }], "fixes": [], "changes": [], "removed": [] }
77
},
88
{
99
"version": { "major": 7, "minor": 4, "build": 2 },

extension/manifest.json

+2
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@
177177
"exclude_matches": ["https://www.torn.com/logout.php*", "https://www.torn.com/loader.php?sid=attack&*"],
178178
"css": [
179179
"scripts/features/oc-time/ttOCTime.css",
180+
"scripts/features/oc2-time/ttOC2Time.css",
180181
"scripts/features/faction-oc-time/ttFactionOCTime.css",
181182
"scripts/features/custom-links/ttCustomLinks.css",
182183
"scripts/features/update-notice/ttUpdateNotice.css",
@@ -193,6 +194,7 @@
193194
"resources/images/svg-icons/back.js",
194195
"scripts/features/hide-level-upgrade/ttHideLevelUpgrade.js",
195196
"scripts/features/oc-time/ttOCTime.js",
197+
"scripts/features/oc2-time/ttOC2Time.js",
196198
"scripts/features/faction-oc-time/ttFactionOCTime.js",
197199
"scripts/features/jobpoints-tooltip/ttJobPointsToolTip.js",
198200
"scripts/features/company-addiction/ttCompanyAddiction.js",

extension/pages/settings/settings.html

+15
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,13 @@ <h2>
409409
<input id="api_usage-user_properties" type="checkbox" />
410410
<label for="api_usage-user_properties">Properties</label>
411411
</div>
412+
413+
<div class="header">User Selections V2</div>
414+
<div class="note">Disabling certain selections will silently disable certain features that rely on that api selection.</div>
415+
<div class="option">
416+
<input id="api_usage-userV2_organizedcrime" type="checkbox" />
417+
<label for="api_usage-userV2_organizedcrime">Organized Crime</label>
418+
</div>
412419
</section>
413420
<section name="chat">
414421
<div class="header">Chat</div>
@@ -482,6 +489,14 @@ <h2>
482489
<input id="sidebar-ocTimer" type="checkbox" />
483490
<label for="sidebar-ocTimer">Show OC ready time in sidebar.</label>
484491
</div>
492+
<div class="option no-mobile">
493+
<input id="sidebar-oc2Timer" type="checkbox" />
494+
<label for="sidebar-oc2Timer">Show OC 2.0 ready time in sidebar.</label>
495+
</div>
496+
<div class="option tabbed no-mobile">
497+
<input id="sidebar-oc2TimerPosition" type="checkbox" />
498+
<label for="sidebar-oc2TimerPosition">Include the crime and position.</label>
499+
</div>
485500
<div class="option no-mobile">
486501
<input id="sidebar-factionOCTimer" type="checkbox" />
487502
<label for="sidebar-factionOCTimer">Show your Faction's next OC ready time in sidebar.</label>

extension/pages/settings/settings.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ async function setupPreferences(requireCleanup) {
626626
_preferences.find("#api_usage-essential").value = settings.apiUsage.delayEssential;
627627
_preferences.find("#api_usage-basic").value = settings.apiUsage.delayBasic;
628628
_preferences.find("#api_usage-stakeouts").value = settings.apiUsage.delayStakeouts;
629-
for (const type of ["user"]) {
629+
for (const type of ["user", "userV2"]) {
630630
for (const selection in settings.apiUsage[type]) {
631631
if (_preferences.find(`#api_usage-${type}_${selection}`))
632632
_preferences.find(`#api_usage-${type}_${selection}`).checked = settings.apiUsage[type][selection];
@@ -1071,7 +1071,7 @@ async function setupPreferences(requireCleanup) {
10711071
settings.apiUsage.delayEssential = parseInt(_preferences.find("#api_usage-essential").value);
10721072
settings.apiUsage.delayBasic = parseInt(_preferences.find("#api_usage-basic").value);
10731073
settings.apiUsage.delayStakeouts = parseInt(_preferences.find("#api_usage-stakeouts").value);
1074-
for (const type of ["user"]) {
1074+
for (const type of ["user", "userV2"]) {
10751075
for (const selection in settings.apiUsage[type]) {
10761076
if (_preferences.find(`#api_usage-${type}_${selection}`))
10771077
settings.apiUsage[type][selection] = _preferences.find(`#api_usage-${type}_${selection}`).checked;

extension/scripts/background.js

+27-4
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,7 @@ async function updateUserdata() {
491491
!hasTimePassed(userdata?.last_action?.timestamp * 1000, TO_MILLIS.MINUTES * 5)));
492492

493493
const selections = [];
494+
const selectionsV2 = [];
494495
if (updateEssential) {
495496
selections.push("profile", "timestamp");
496497

@@ -529,6 +530,11 @@ async function updateUserdata() {
529530

530531
selections.push(selection);
531532
}
533+
for (const selection of ["organizedcrime"]) {
534+
if (!settings.apiUsage.userV2[selection]) continue;
535+
536+
selectionsV2.push(selection);
537+
}
532538

533539
if (settings.apiUsage.user.education && !hasFinishedEducation()) selections.push("education");
534540

@@ -540,10 +546,16 @@ async function updateUserdata() {
540546
updatedTypes.push("attack history");
541547
}
542548
console.log("Time elapsed:", Date.now() - userdata.date);
543-
if (!selections.length) return { updated: false };
549+
if (!selections.length && !selectionsV2.length) return { updated: false };
544550

545551
const oldUserdata = { ...userdata };
546-
userdata = await fetchData("torn", { section: "user", selections });
552+
const newUserdata = selections.length ? await fetchData("torn", { section: "user", selections }) : {};
553+
const newUserdataV2 = selectionsV2.length ? await fetchData("tornv2", { section: "user", selections: selectionsV2 }) : {};
554+
555+
userdata = {
556+
...newUserdata,
557+
...newUserdataV2,
558+
};
547559
if (!userdata || !Object.keys(userdata).length) throw new Error("Aborted updating due to an unexpected response.");
548560
userdata.date = now;
549561
userdata.dateBasic = updateBasic ? now : (oldUserdata?.dateBasic ?? now);
@@ -560,7 +572,13 @@ async function updateUserdata() {
560572
if (newEventsCount < 0) newEventsCount = userdata?.notifications?.events ?? 0;
561573
else if (newEventsCount > 0) {
562574
const category = newEventsCount <= 25 ? "newevents" : "events";
563-
userdata.events = (await fetchData("torn", { section: "user", selections: [category], params: { limit: newEventsCount } })).events;
575+
userdata.events = (
576+
await fetchData("torn", {
577+
section: "user",
578+
selections: [category],
579+
params: { limit: newEventsCount },
580+
})
581+
).events;
564582
selections.push(category);
565583
}
566584
}
@@ -1297,7 +1315,12 @@ async function updateFactionStakeouts() {
12971315
const oldData = factionStakeouts[factionId]?.info ?? false;
12981316
let data;
12991317
try {
1300-
data = await fetchData("torn", { section: "faction", selections: ["basic", "chain"], id: factionId, silent: true });
1318+
data = await fetchData("torn", {
1319+
section: "faction",
1320+
selections: ["basic", "chain"],
1321+
id: factionId,
1322+
silent: true,
1323+
});
13011324
if (!data) {
13021325
console.log("Unexpected result during faction stakeout updating.");
13031326
failed++;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.tt-sidebar-information .title {
2+
font-weight: bold;
3+
text-decoration: none;
4+
color: inherit;
5+
margin: inherit;
6+
}
7+
8+
.tt-sidebar-information .countdown.short {
9+
color: var(--tt-color-red);
10+
}
11+
12+
.tt-sidebar-information .countdown.medium {
13+
color: var(--tt-color-orange);
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
"use strict";
2+
3+
(async () => {
4+
const { hasSidebar } = await checkDevice();
5+
if (!hasSidebar) return "Not supported on mobiles or tablets!";
6+
7+
featureManager.registerFeature(
8+
"OC2 Time",
9+
"sidebar",
10+
() => settings.pages.sidebar.oc2Timer && (userdata?.faction?.faction_id > 0 ?? false),
11+
null,
12+
showTimer,
13+
removeTimer,
14+
{
15+
storage: ["settings.pages.sidebar.oc2Timer", "settings.pages.sidebar.oc2TimerPosition", "userdata.organizedCrime"],
16+
},
17+
() => {
18+
if (!hasAPIData()) return "No API access.";
19+
else if (!userdata.organizedCrime) return "No OC data (still on OC 1?).";
20+
}
21+
);
22+
23+
async function showTimer() {
24+
await requireSidebar();
25+
26+
removeTimer();
27+
addInformationSection();
28+
showInformationSection();
29+
30+
const elements = [];
31+
32+
const inCrime = ["Recruiting", "Planning"].includes(userdata.organizedCrime.status);
33+
if (inCrime) {
34+
elements.push(buildTimeLeftElement());
35+
if (settings.pages.sidebar.oc2TimerPosition) {
36+
elements.push(document.newElement({ type: "span", class: "countdown", text: " - " }));
37+
elements.push(buildPositionElement());
38+
}
39+
} else {
40+
elements.push(document.newElement({ type: "span", class: "countdown", text: "No crime joined." }));
41+
}
42+
43+
document.find(".tt-sidebar-information").appendChild(
44+
document.newElement({
45+
type: "section",
46+
id: "oc2Timer",
47+
children: [document.newElement({ type: "a", class: "title", text: "OC: ", href: LINKS.organizedCrimes }), ...elements],
48+
})
49+
);
50+
}
51+
52+
function buildTimeLeftElement() {
53+
const timeLeftElement = document.newElement({ type: "span", class: "countdown" });
54+
55+
const readyAt = userdata.organizedCrime.ready_at * 1000;
56+
const timeLeft = readyAt - Date.now();
57+
58+
if (timeLeft <= TO_MILLIS.HOURS * 8) timeLeftElement.classList.add("short");
59+
else if (timeLeft <= TO_MILLIS.HOURS * 12) timeLeftElement.classList.add("medium");
60+
61+
if (timeLeft > 0) {
62+
const formatOptions = { type: "wordTimer", extraShort: true, showDays: true, truncateSeconds: true };
63+
timeLeftElement.textContent = formatTime({ milliseconds: timeLeft }, formatOptions);
64+
65+
timeLeftElement.dataset.end = readyAt;
66+
timeLeftElement.dataset.timeSettings = JSON.stringify(formatOptions);
67+
countdownTimers.push(timeLeftElement);
68+
} else {
69+
timeLeftElement.textContent = `Ready ${userdata.organizedCrime.status}`;
70+
}
71+
72+
return timeLeftElement;
73+
}
74+
75+
function buildPositionElement() {
76+
// const position = userdata.organizedCrime.slots.find(({ user_id }) => user_id === userdata.user_id)?.position ?? "???";
77+
const position = userdata.organizedCrime.slots.find(({ user_id }) => user_id === 1043377)?.position ?? "???";
78+
const name = userdata.organizedCrime.name;
79+
const level = userdata.organizedCrime.difficulty;
80+
81+
return document.newElement({ type: "span", class: "position", text: `${position} in ${name} (Lvl ${level})` });
82+
}
83+
84+
function removeTimer() {
85+
document.find("#oc2Timer")?.remove();
86+
}
87+
88+
function addInformationSection() {
89+
if (document.find(".tt-sidebar-information")) return;
90+
91+
const parent = document.find("#sidebarroot div[class*='user-information_'] div[class*='toggle-content_'] div[class*='content_']");
92+
93+
parent.appendChild(document.newElement({ type: "hr", class: "tt-sidebar-information-divider tt-delimiter tt-hidden" }));
94+
parent.appendChild(document.newElement({ type: "div", class: "tt-sidebar-information tt-hidden" }));
95+
}
96+
97+
function showInformationSection() {
98+
document.find(".tt-sidebar-information-divider").classList.remove("tt-hidden");
99+
document.find(".tt-sidebar-information").classList.remove("tt-hidden");
100+
}
101+
})();

extension/scripts/global/globalData.js

+19
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,9 @@ const DEFAULT_STORAGE = {
378378
weaponexp: new DefaultSetting({ type: "boolean", defaultValue: true }),
379379
properties: new DefaultSetting({ type: "boolean", defaultValue: true }),
380380
},
381+
userV2: {
382+
organizedcrime: new DefaultSetting({ type: "boolean", defaultValue: true }),
383+
},
381384
},
382385
themes: {
383386
pages: new DefaultSetting({ type: "string", defaultValue: "default" }),
@@ -435,6 +438,8 @@ const DEFAULT_STORAGE = {
435438
highlightEnergy: new DefaultSetting({ type: "boolean", defaultValue: true }),
436439
highlightNerve: new DefaultSetting({ type: "boolean", defaultValue: false }),
437440
ocTimer: new DefaultSetting({ type: "boolean", defaultValue: true }),
441+
oc2Timer: new DefaultSetting({ type: "boolean", defaultValue: true }),
442+
oc2TimerPosition: new DefaultSetting({ type: "boolean", defaultValue: true }),
438443
factionOCTimer: new DefaultSetting({ type: "boolean", defaultValue: false }),
439444
collapseAreas: new DefaultSetting({ type: "boolean", defaultValue: true }),
440445
settingsLink: new DefaultSetting({ type: "boolean", defaultValue: true }),
@@ -1057,6 +1062,20 @@ const API_USAGE = {
10571062
color: true,
10581063
until: true,
10591064
},
1065+
organizedCrime: {
1066+
created_at: false,
1067+
difficulty: true,
1068+
executed_at: false,
1069+
expired_at: false,
1070+
id: false,
1071+
initiated_at: false,
1072+
name: true,
1073+
planning_at: false,
1074+
ready_at: true,
1075+
rewards: false,
1076+
slots: true,
1077+
status: false,
1078+
},
10601079
travel: {
10611080
destination: true,
10621081
method: true,

0 commit comments

Comments
 (0)