Untitled diff
23 removals
715 lines
20 additions
712 lines
"use strict";
"use strict";
var settings = new Store("settings", {
var settings = new Store("settings", {
"preferFriendSummons": true,
"preferFriendSummons": true,
"preferNonFriendSummonsInFavorites": true,
"preferNonFriendSummonsInFavorites": true,
"preferLimitBrokenSummons": true,
"preferLimitBrokenSummons": true,
"preferHighLevelSummons": true,
"preferHighLevelSummons": true,
"notifyOnFullAP": false,
"notifyOnFullAP": false,
"notifyOnFullBP": false,
"notifyOnFullBP": false,
"showSkillCooldowns": true,
"showSkillCooldowns": true,
"showDebuffTimers": true,
"showDebuffTimers": true,
"showBuffTimers": true,
"showBuffTimers": true,
"monitorRaidDebuffs": true,
"monitorRaidDebuffs": true,
"keyboardShortcuts": true,
"keyboardShortcuts": true,
"showBookmarks": true,
"showBookmarks": true,
"preferredSummonElement": "",
"preferredSummonElement": "",
"submenuSize": 1.0,
"submenuSize": 1.0,
"bookmarksSize": 1.0,
"bookmarksSize": 1.0,
"bookmarksMenuSize": 1.0,
"bookmarksMenuSize": 1.0,
"recentQuest": null,
"recentQuest": null,
"showQuickPanels": true,
"showQuickPanels": true,
"showGaugeOverlays": true,
"showGaugeOverlays": true,
"openBookmarksOnClick": false,
"openBookmarksOnClick": false,
"fixJPFontRendering": true,
"fixJPFontRendering": true,
"enableCoOpEnhancements": true,
"enableCoOpEnhancements": true,
"dropdownFix": true,
"dropdownFix": true,
"disableMiddleRightClick": true,
"disableMiddleRightClick": true,
"statusPanel": true,
"statusPanel": true,
"itemsPanel": true,
"itemsPanel": true,
"raidsPanel": false,
"raidsPanel": false,
"clockBrightness": 0.65,
"clockBrightness": 0.65,
"oneClickQuickSummons": true,
"oneClickQuickSummons": true,
"bookmarksInactiveIcon": null,
"bookmarksInactiveIcon": null,
"bookmarksActiveIcon": null,
"bookmarksActiveIcon": null,
"bookmarksIconPadding": 100,
"bookmarksIconPadding": 100,
"horizontalBookmarks": false,
"horizontalBookmarks": false,
"statusPanelBuffs": false,
"statusPanelBuffs": false,
"statusPanelExpiringBuffs": true,
"statusPanelExpiringBuffs": true,
"betterEnglishFont": false,
"betterEnglishFont": false,
"showItemWatchButtons": true,
"showItemWatchButtons": true,
"showPartyNames": true,
"showPartyNames": true,
"filterEnemyTimers": true,
"filterEnemyTimers": true,
"showPerformanceHud": false,
"showPerformanceHud": false,
"showNetworkHud": false,
"showNetworkHud": false,
"showWeaponAttack": true,
"showWeaponAttack": true,
"showSkillActivationIndicator": true,
"showSkillActivationIndicator": true,
"autofillBackupTweets": true,
"autofillBackupTweets": true,
"moveCoOpFooter": true,
"moveCoOpFooter": true,
"largeQuickPanels": false,
"largeQuickPanels": false,
"showPartyHelp": false,
"showPartyHelp": false,
"keepSoundOnBlur": true,
"keepSoundOnBlur": true,
"stuckButtonWorkaround2": true,
"stuckButtonWorkaround2": true,
"showLastActionTimer": true,
"showLastActionTimer": true,
"smartSupports": true,
"smartSupports": true,
"defaultToSmartSupports": false,
"defaultToSmartSupports": false,
"disablePhalanxSticker": true,
"disablePhalanxSticker": true,
"summonOrder": "{}",
"summonOrder": "{}",
"password": "",
"password": "",
"minimumPopupWait": 350,
"minimumPopupWait": 350,
"maximumPopupWait": 1750,
"maximumPopupWait": 1750,
"focusQuickPanels": true,
"focusQuickPanels": true,
"newSkillSystem": true
"newSkillSystem": true
});
});
var failedUpdateMinimumDelay = 10 * 1000;
var failedUpdateMinimumDelay = 10 * 1000;
var minimumUpdateDelay = 60 * 4 * 1000;
var minimumUpdateDelay = 60 * 4 * 1000;
var minimumRaidUpdateDelay = 30 * 1000;
var minimumRaidUpdateDelay = 30 * 1000;
var minimumItemUpdateDelay = 60 * 30 * 1000;
var minimumItemUpdateDelay = 60 * 30 * 1000;
var minimumHaloUpdateDelay = 60 * 30 * 1000;
var minimumHaloUpdateDelay = 60 * 30 * 1000;
var secretKeysByTabId = {};
var secretKeysByTabId = {};
var lastFailure = -1;
var lastFailure = -1;
var users = {};
var users = {};
var lastRaidCodes = {};
var lastRaidCodes = {};
var isDead = true;
var isDead = true;
var isShutdown = false;
var isShutdown = false;
var lastLocation = null;
var lastLocation = null;
var idleRedirectPending = false;
var idleRedirectPending = false;
var lastRedirectTarget = null;
var lastRedirectTarget = null;
chrome.runtime.onMessage.addListener(onRuntimeMessage);
chrome.runtime.onMessage.addListener(onRuntimeMessage);
chrome.alarms.onAlarm.addListener(onAlarm);
chrome.alarms.onAlarm.addListener(onAlarm);
chrome.runtime.onInstalled.addListener(function () {
chrome.runtime.onInstalled.addListener(function () {
var dc = chrome.declarativeContent;
var dc = chrome.declarativeContent;
dc.onPageChanged.removeRules(undefined, function () {
dc.onPageChanged.removeRules(undefined, function () {
dc.onPageChanged.addRules([
dc.onPageChanged.addRules([
{
{
conditions: [
conditions: [
new dc.PageStateMatcher({
new dc.PageStateMatcher({
pageUrl: { hostEquals: 'game.granbluefantasy.jp', schemes: ["https", "http"] },
pageUrl: { hostEquals: 'game.granbluefantasy.jp', schemes: ["https", "http"] },
}),
}),
new dc.PageStateMatcher({
new dc.PageStateMatcher({
pageUrl: { hostEquals: 'gbf.game.mbga.jp', schemes: ["https", "http"] },
pageUrl: { hostEquals: 'gbf.game.mbga.jp', schemes: ["https", "http"] },
})
})
],
],
actions: [new dc.ShowPageAction()]
actions: [new dc.ShowPageAction()]
}
}
]);
]);
});
});
});
});
log("Started");
log("Started");
function getAdjustedSettings() {
function getAdjustedSettings() {
var result = settings.toObject();
var result = settings.toObject();
result.allowDragSelect = false;
result.allowDragSelect = false;
// result.autoSkipToQuestResults = false;
// result.autoSkipToQuestResults = false;
// result.oneClickQuickSummons = false;
// result.oneClickQuickSummons = false;
result.realtimeRaidList = false;
result.realtimeRaidList = false;
// result.raidsPanel = false;
// result.raidsPanel = false;
// result.showQuickPanels = false;
// result.showQuickPanels = false;
result.touchInputSupport = false;
result.touchInputSupport = false;
// Cygamesssssssssssssss
// Cygamesssssssssssssss
result.autofillBackupTweets = false;
result.autofillBackupTweets = false;
// API changes broke this
// API changes broke this
result.detailedUpgradePage = false;
result.detailedUpgradePage = false;
return result;
return result;
}
}
;
;
function log(...args) {
function log(...args) {
args.unshift((new Date()).toLocaleString() + " |");
args.unshift((new Date()).toLocaleString() + " |");
console.log.apply(console, args);
console.log.apply(console, args);
}
}
;
;
function getWatchedItems() {
function getWatchedItems() {
var result = JSON.parse(settings.get("watchedItems") || "[]");
var result = JSON.parse(settings.get("watchedItems") || "[]");
if ((result.length === 1) && (result[0] === null))
if ((result.length === 1) && (result[0] === null))
result = [];
result = [];
var targetCounts = JSON.parse(settings.get("targetItemCounts") || "{}");
var targetCounts = JSON.parse(settings.get("targetItemCounts") || "{}");
var itemGroups = JSON.parse(settings.get("itemGroups") || "{}");
return {
return {
items: result,
items: result,
counts: targetCounts
counts: targetCounts,
groups: itemGroups
};
};
}
}
;
;
function setItemWatchTarget(id, count) {
function setItemWatchTarget(id, count) {
var targetCounts = JSON.parse(settings.get("targetItemCounts") || "{}");
var targetCounts = JSON.parse(settings.get("targetItemCounts") || "{}");
targetCounts[id] = count;
targetCounts[id] = count;
settings.set("targetItemCounts", JSON.stringify(targetCounts));
settings.set("targetItemCounts", JSON.stringify(targetCounts));
}
}
;
;
function setItemGroup(id, group) {
var itemGroups = JSON.parse(settings.get("itemGroups") || "{}");
if (group!="undefined"){itemGroups[id] = group;}
else{
//hack because it's not an array so can't just be pushed to
var max = JSON.parse(settings.get("itemGroupsNumber") || "0");
var newmax = "" + (parseInt(max)+1);
settings.set("itemGroupsNumber", JSON.stringify(newmax));
itemGroups[id] = newmax;
}
settings.set("itemGroups", JSON.stringify(itemGroups));
}
;
function addWatchedItem(id) {
function addWatchedItem(id) {
var items = getWatchedItems().items;
var items = getWatchedItems().items;
if (items.indexOf(id) >= 0)
if (items.indexOf(id) >= 0)
return items;
return items;
if (!id)
if (!id)
return items;
return items;
items.push(id);
items.push(id);
settings.set("watchedItems", JSON.stringify(items));
settings.set("watchedItems", JSON.stringify(items));
return items;
return items;
}
}
;
;
function removeWatchedItem(id) {
function removeWatchedItem(id) {
var items = getWatchedItems().items;
var items = getWatchedItems().items;
var index = items.indexOf(id);
var index = items.indexOf(id);
if (index < 0)
if (index < 0)
return items;
return items;
items.splice(index, 1);
items.splice(index, 1);
settings.set("watchedItems", JSON.stringify(items));
settings.set("watchedItems", JSON.stringify(items));
return items;
return items;
}
}
;
;
function getFavedSummons() {
function getFavedSummons() {
var result = JSON.parse(settings.get("favedSummons") || "[]");
var result = JSON.parse(settings.get("favedSummons") || "[]");
if ((result.length === 1) && (result[0] === null))
if ((result.length === 1) && (result[0] === null))
result = [];
result = [];
return result;
return result;
}
}
;
;
function addFavedSummon(id) {
function addFavedSummon(id) {
var items = getFavedSummons();
var items = getFavedSummons();
if (items.indexOf(id) >= 0)
if (items.indexOf(id) >= 0)
return items;
return items;
if (!id)
if (!id)
return items;
return items;
items.push(id);
items.push(id);
settings.set("favedSummons", JSON.stringify(items));
settings.set("favedSummons", JSON.stringify(items));
return items;
return items;
}
}
;
;
function removeFavedSummon(id) {
function removeFavedSummon(id) {
var items = getFavedSummons();
var items = getFavedSummons();
var index = items.indexOf(id);
var index = items.indexOf(id);
if (index < 0)
if (index < 0)
return items;
return items;
items.splice(index, 1);
items.splice(index, 1);
settings.set("favedSummons", JSON.stringify(items));
settings.set("favedSummons", JSON.stringify(items));
return items;
return items;
}
}
;
;
function getUserDict(uid) {
function getUserDict(uid) {
var dict = users[uid];
var dict = users[uid];
if (!dict)
if (!dict)
dict = users[uid] = { lastUpdate: [] };
dict = users[uid] = { lastUpdate: [] };
return dict;
return dict;
}
}
;
;
function setUserData(uid, key, data) {
function setUserData(uid, key, data) {
var dict = getUserDict(uid);
var dict = getUserDict(uid);
if (data) {
if (data) {
dict.lastUpdate[key] = Date.now();
dict.lastUpdate[key] = Date.now();
dict[key] = data;
dict[key] = data;
}
}
else {
else {
dict.lastUpdate[key] = 0;
dict.lastUpdate[key] = 0;
dict[key] = null;
dict[key] = null;
}
}
}
}
;
;
function getUserData(uid, key) {
function getUserData(uid, key) {
var dict = getUserDict(uid);
var dict = getUserDict(uid);
return dict[key];
return dict[key];
}
}
;
;
function getLastDataUpdate(uid, key) {
function getLastDataUpdate(uid, key) {
var dict = getUserDict(uid);
var dict = getUserDict(uid);
return dict.lastUpdate[key];
return dict.lastUpdate[key];
}
}
;
;
function formatItemCounters(uid) {
function formatItemCounters(uid) {
var itemCounters = getUserDict(uid).itemCounters;
var itemCounters = getUserDict(uid).itemCounters;
if (!itemCounters)
if (!itemCounters)
return null;
return null;
var counterDict = {};
var counterDict = {};
for (var i = 0, l = itemCounters.length; i < l; i++) {
for (var i = 0, l = itemCounters.length; i < l; i++) {
var item = itemCounters[i];
var item = itemCounters[i];
counterDict[item.item_id] = item;
counterDict[item.item_id] = item;
}
}
return counterDict;
return counterDict;
}
}
;
;
function onRuntimeMessage(msg, sender, sendResponse) {
function onRuntimeMessage(msg, sender, sendResponse) {
if (chrome.runtime.lastError)
if (chrome.runtime.lastError)
log(chrome.runtime.lastError);
log(chrome.runtime.lastError);
var key = msg.type;
var key = msg.type;
var userDict;
var userDict;
if (msg.uid)
if (msg.uid)
userDict = getUserDict(msg.uid);
userDict = getUserDict(msg.uid);
var tabId;
var tabId;
if (sender.tab && sender.tab.id)
if (sender.tab && sender.tab.id)
tabId = sender.tab.id;
tabId = sender.tab.id;
else if (msg.tabId)
else if (msg.tabId)
tabId = msg.tabId;
tabId = msg.tabId;
if (tabId <= 0) {
if (tabId <= 0) {
log("Message has no tab id", key);
log("Message has no tab id", key);
return;
return;
}
}
var senderUrl = sender.url || "";
var senderUrl = sender.url || "";
if ((senderUrl.indexOf("granbluefantasy.jp") >= 0) ||
if ((senderUrl.indexOf("granbluefantasy.jp") >= 0) ||
(senderUrl.indexOf("mbga.jp") >= 0)) {
(senderUrl.indexOf("mbga.jp") >= 0)) {
}
}
else if ((senderUrl.indexOf("chrome-extension://") >= 0) &&
else if ((senderUrl.indexOf("chrome-extension://") >= 0) &&
(senderUrl.indexOf("api.html") >= 0)) {
(senderUrl.indexOf("api.html") >= 0)) {
switch (key) {
switch (key) {
case "apiRequest":
case "apiRequest":
case "getSettings":
case "getSettings":
break;
break;
default:
default:
log("Rejected disallowed API request", msg);
log("Rejected disallowed API request", msg);
return;
return;
}
}
}
}
switch (key) {
switch (key) {
case "apiRequest":
case "apiRequest":
if (!settings.get("webAPI")) {
if (!settings.get("webAPI")) {
log("Rejected API request because API is disabled", msg);
log("Rejected API request because API is disabled", msg);
sendResponse(null);
sendResponse(null);
return;
return;
}
}
log("Processing API request", msg.request.type);
log("Processing API request", msg.request.type);
switch (msg.request.type) {
switch (msg.request.type) {
case "getUserIds":
case "getUserIds":
sendResponse(JSON.stringify(Object.keys(users)));
sendResponse(JSON.stringify(Object.keys(users)));
break;
break;
case "getVersion":
case "getVersion":
sendResponse(chrome.app.getDetails().version);
sendResponse(chrome.app.getDetails().version);
break;
break;
case "tryJoinRaid":
case "tryJoinRaid":
case "getCombatState":
case "getCombatState":
log("Preparing to send api request", msg);
log("Preparing to send api request", msg);
chrome.tabs.query({}, function (tabs) {
chrome.tabs.query({}, function (tabs) {
if (tabs.length === 0) {
if (tabs.length === 0) {
log("Found no granblue tab");
log("Found no granblue tab");
sendResponse({ type: "result", error: "No granblue tab found" });
sendResponse({ type: "result", error: "No granblue tab found" });
return;
return;
}
}
for (var i = 0, l = tabs.length; i < l; i++) {
for (var i = 0, l = tabs.length; i < l; i++) {
var tab = tabs[i];
var tab = tabs[i];
var tabUrl = tab.url;
var tabUrl = tab.url;
if (!tabUrl ||
if (!tabUrl ||
((tabUrl.indexOf("game.granbluefantasy.jp") < 0) &&
((tabUrl.indexOf("game.granbluefantasy.jp") < 0) &&
(tabUrl.indexOf("gbf.game.mbga.jp") < 0))) {
(tabUrl.indexOf("gbf.game.mbga.jp") < 0))) {
continue;
continue;
}
}
log("Sending api request", msg);
log("Sending api request", msg);
actuallySendMessage(msg, tab.id, function (result) {
actuallySendMessage(msg, tab.id, function (result) {
log("Got result for api request");
log("Got result for api request");
sendResponse(result);
sendResponse(result);
});
});
return;
return;
}
}
log("Found no granblue tab");
log("Found no granblue tab");
sendResponse({ type: "result", error: "No granblue tab found" });
sendResponse({ type: "result", error: "No granblue tab found" });
});
});
return true;
return true;
default:
default:
sendResponse({ type: "result", error: "Unknown message" });
sendResponse({ type: "result", error: "Unknown message" });
break;
break;
}
}
break;
break;
case "getUserIds":
case "getUserIds":
sendResponse(JSON.stringify(Object.keys(users)));
sendResponse(JSON.stringify(Object.keys(users)));
break;
break;
case "setPassword":
case "setPassword":
settings.set("password", msg.password);
settings.set("password", msg.password);
break;
break;
case "pleaseInjectStylesheets":
case "pleaseInjectStylesheets":
injectStylesheetsIntoTab(sender);
injectStylesheetsIntoTab(sender);
break;
break;
case "heartbeat":
case "heartbeat":
isDead = false;
isDead = false;
break;
break;
case "cancelSuspend":
case "cancelSuspend":
if (userDict.isSuspended)
if (userDict.isSuspended)
log("Canceling idle/maintenance suspend for " + msg.uid);
log("Canceling idle/maintenance suspend for " + msg.uid);
userDict.isSuspended = false;
userDict.isSuspended = false;
lastFailure = -1;
lastFailure = -1;
break;
break;
case "isShutdown":
case "isShutdown":
sendResponse(isShutdown);
sendResponse(isShutdown);
break;
break;
case "setCompatibility":
case "setCompatibility":
var newState = (msg.state === false);
var newState = (msg.state === false);
if (newState !== isShutdown) {
if (newState !== isShutdown) {
log("Compatibility shutdown state set to", newState);
log("Compatibility shutdown state set to", newState);
isShutdown = newState;
isShutdown = newState;
}
}
break;
break;
case "openNewTab":
case "openNewTab":
chrome.tabs.create({
chrome.tabs.create({
url: msg.url
url: msg.url
});
});
break;
break;
case "getVersion":
case "getVersion":
sendResponse(chrome.app.getDetails().version);
sendResponse(chrome.app.getDetails().version);
break;
break;
case "setRecentCoOpHost":
case "setRecentCoOpHost":
settings.set("recentCoOpHost", msg.data);
settings.set("recentCoOpHost", msg.data);
break;
break;
case "getRecentCoOpHost":
case "getRecentCoOpHost":
sendResponse(settings.get("recentCoOpHost") || null);
sendResponse(settings.get("recentCoOpHost") || null);
break;
break;
case "setCurrentEvent":
case "setCurrentEvent":
if (msg.href !== settings.get("currentEvent"))
if (msg.href !== settings.get("currentEvent"))
log("Event changed to '" + msg.href + "'");
log("Event changed to '" + msg.href + "'");
settings.set("currentEvent", msg.href);
settings.set("currentEvent", msg.href);
break;
break;
case "setCurrentGuildWar":
case "setCurrentGuildWar":
if (msg.href !== settings.get("currentGuildWar"))
if (msg.href !== settings.get("currentGuildWar"))
log("Guild war changed to '" + msg.href + "'");
log("Guild war changed to '" + msg.href + "'");
settings.set("currentGuildWar", msg.href);
settings.set("currentGuildWar", msg.href);
break;
break;
case "getCurrentEvent":
case "getCurrentEvent":
sendResponse(settings.get("currentEvent") || null);
sendResponse(settings.get("currentEvent") || null);
break;
break;
case "getCurrentGuildWar":
case "getCurrentGuildWar":
sendResponse(settings.get("currentGuildWar") || null);
sendResponse(settings.get("currentGuildWar") || null);
break;
break;
case "setRecentQuest":
case "setRecentQuest":
settings.set("recentQuest", msg.url);
settings.set("recentQuest", msg.url);
break;
break;
case "getRecentQuest":
case "getRecentQuest":
sendResponse(settings.get("recentQuest") || null);
sendResponse(settings.get("recentQuest") || null);
break;
break;
case "setLastLocation":
case "setLastLocation":
// FIXME: Track per-tab
// FIXME: Track per-tab
lastLocation = msg.url;
lastLocation = msg.url;
break;
break;
case "setIdleRedirectPending":
case "setIdleRedirectPending":
// FIXME: Track per-tab
// FIXME: Track per-tab
idleRedirectPending = msg.state;
idleRedirectPending = msg.state;
if (msg.url)
if (msg.url)
lastRedirectTarget = msg.url;
lastRedirectTarget = msg.url;
break;
break;
case "getLastLocation":
case "getLastLocation":
sendResponse(lastLocation || null);
sendResponse(lastLocation || null);
break;
break;
case "getIdleRedirectInfo":
case "getIdleRedirectInfo":
if (idleRedirectPending) {
if (idleRedirectPending) {
sendResponse({ pending: true, location: lastLocation, lastRedirectTarget: lastRedirectTarget });
sendResponse({ pending: true, location: lastLocation, lastRedirectTarget: lastRedirectTarget });
}
}
else {
else {
sendResponse({ pending: false });
sendResponse({ pending: false });
}
}
break;
break;
case "getSettings":
case "getSettings":
sendResponse(getAdjustedSettings());
sendResponse(getAdjustedSettings());
break;
break;
case "getRaidCode":
case "getRaidCode":
sendResponse(lastRaidCodes[tabId]);
sendResponse(lastRaidCodes[tabId]);
break;
break;
case "updateRaidCode":
case "updateRaidCode":
lastRaidCodes[tabId] = msg.raidCode;
lastRaidCodes[tabId] = msg.raidCode;
break;
break;
case "getItemCounters":
case "getItemCounters":
return maybeDoUpdate(userDict.nextCounterUpdate, minimumUpdateDelay, formatItemCounters, updateItemCounters, sendResponse, msg.force, tabId, msg.uid);
return maybeDoUpdate(userDict.nextCounterUpdate, minimumUpdateDelay, formatItemCounters, updateItemCounters, sendResponse, msg.force, tabId, msg.uid);
case "updateItemCounters":
case "updateItemCounters":
userDict.nextCounterUpdate = Date.now() + minimumUpdateDelay;
userDict.nextCounterUpdate = Date.now() + minimumUpdateDelay;
userDict.itemCounters = msg.counters;
userDict.itemCounters = msg.counters;
break;
break;
case "invalidateStatus":
case "invalidateStatus":
if (userDict.lastStatus)
if (userDict.lastStatus)
log("Status invalidated");
log("Status invalidated");
userDict.nextStatusUpdate = 0;
userDict.nextStatusUpdate = 0;
userDict.lastStatus = null;
userDict.lastStatus = null;
break;
break;
case "getStatus":
case "getStatus":
var getLastStatus = function (uid) {
var getLastStatus = function (uid) {
var s = getUserDict(uid).lastStatus;
var s = getUserDict(uid).lastStatus;
if (s)
if (s)
fixupStatus(s, uid);
fixupStatus(s, uid);
return s;
return s;
};
};
if (msg.lazy) {
if (msg.lazy) {
var lastStatus = getLastStatus(msg.uid);
var lastStatus = getLastStatus(msg.uid);
if (lastStatus) {
if (lastStatus) {
sendResponse(lastStatus);
sendResponse(lastStatus);
return;
return;
}
}
else {
else {
// log("Lazy status update failed");
// log("Lazy status update failed");
}
}
}
}
return maybeDoUpdate(userDict.nextStatusUpdate, minimumUpdateDelay, getLastStatus, updateStatus, sendResponse, msg.force, tabId, msg.uid);
return maybeDoUpdate(userDict.nextStatusUpdate, minimumUpdateDelay, getLastStatus, updateStatus, sendResponse, msg.force, tabId, msg.uid);
case "updateStatus":
case "updateStatus":
handleNewStatus(msg.status, msg.uid);
handleNewStatus(msg.status, msg.uid);
break;
break;
case "invalidateBuffs":
case "invalidateBuffs":
userDict.nextGuildBuffUpdate = 0;
userDict.nextGuildBuffUpdate = 0;
userDict.nextPersonalBuffUpdate = 0;
userDict.nextPersonalBuffUpdate = 0;
userDict.guildBuffs = null;
userDict.guildBuffs = null;
userDict.personalBuffs = null;
userDict.personalBuffs = null;
log("Buffs invalidated");
log("Buffs invalidated");
break;
break;
case "updateGuildBuffs":
case "updateGuildBuffs":
userDict.lastGuildBuffUpdate = Date.now();
userDict.lastGuildBuffUpdate = Date.now();
userDict.nextGuildBuffUpdate = Date.now() + minimumUpdateDelay;
userDict.nextGuildBuffUpdate = Date.now() + minimumUpdateDelay;
userDict.guildBuffs = msg.buffs;
userDict.guildBuffs = msg.buffs;
break;
break;
case "updatePersonalBuffs":
case "updatePersonalBuffs":
userDict.lastPersonalBuffUpdate = Date.now();
userDict.lastPersonalBuffUpdate = Date.now();
userDict.nextPersonalBuffUpdate = Date.now() + minimumUpdateDelay;
userDict.nextPersonalBuffUpdate = Date.now() + minimumUpdateDelay;
userDict.personalBuffs = msg.buffs;
userDict.personalBuffs = msg.buffs;
break;
break;
case "getNextRankRp":
case "getNextRankRp":
// if not force, don't actually update since this is a heavy call
// if not force, don't actually update since this is a heavy call
if (!msg.force) {
if (!msg.force) {
if (userDict.nextNextRankRpUpdate) {
if (userDict.nextNextRankRpUpdate) {
sendResponse(userDict.nextRankRp);
sendResponse(userDict.nextRankRp);
break;
break;
}
}
sendResponse(null);
sendResponse(null);
break;
break;
}
}
return maybeDoUpdate(userDict.nextNextRankRpUpdate, minimumUpdateDelay, function (uid) { return getUserDict(uid).nextRankRp; }, updateNextRankRp, sendResponse, msg.force, tabId, msg.uid);
return maybeDoUpdate(userDict.nextNextRankRpUpdate, minimumUpdateDelay, function (uid) { return getUserDict(uid).nextRankRp; }, updateNextRankRp, sendResponse, msg.force, tabId, msg.uid);
case "updateNextRankRp":
case "updateNextRankRp":
userDict.nextNextRankRpUpdate = Date.now() + minimumUpdateDelay;
userDict.nextNextRankRpUpdate = Date.now() + minimumUpdateDelay;
userDict.nextRankRp = getRpToNextRank(msg.data);
userDict.nextRankRp = getRpToNextRank(msg.data);
break;
break;
case "getRaids":
case "getRaids":
return maybeDoUpdate(userDict.nextRaidUpdate, minimumRaidUpdateDelay, function (uid) { return getUserDict(uid).lastRaids; }, updateRaids, sendResponse, msg.force, tabId, msg.uid);
return maybeDoUpdate(userDict.nextRaidUpdate, minimumRaidUpdateDelay, function (uid) { return getUserDict(uid).lastRaids; }, updateRaids, sendResponse, msg.force, tabId, msg.uid);
case "invalidateRaids":
case "invalidateRaids":
if (msg.raids) {
if (msg.raids) {
handleNewRaids(msg.raids, msg.uid);
handleNewRaids(msg.raids, msg.uid);
}
}
else {
else {
if (userDict.lastRaids)
if (userDict.lastRaids)
log("Raids invalidated");
log("Raids invalidated");
userDict.nextRaidUpdate = 0;
userDict.nextRaidUpdate = 0;
userDict.lastRaids = null;
userDict.lastRaids = null;
}
}
break;
break;
case "getItems":
case "getItems":
return maybeDoUpdate(userDict.nextItemUpdate, minimumItemUpdateDelay, function (uid) { return getUserDict(uid).lastItems; }, updateItems, sendResponse, msg.force, tabId, msg.uid);
return maybeDoUpdate(userDict.nextItemUpdate, minimumItemUpdateDelay, function (uid) { return getUserDict(uid).lastItems; }, updateItems, sendResponse, msg.force, tabId, msg.uid);
case "invalidateItems":
case "invalidateItems":
if (msg.items) {
if (msg.items) {
handleNewItems(msg.items, msg.uid);
handleNewItems(msg.items, msg.uid);
}
}
else {
else {
if (userDict.lastItems)
if (userDict.lastItems)
log("Items invalidated");
log("Items invalidated");
userDict.nextItemUpdate = 0;
userDict.nextItemUpdate = 0;
userDict.lastItems = null;
userDict.lastItems = null;
}
}
break;
break;
case "getWatchedItems":
case "getWatchedItems":
sendResponse(getWatchedItems());
sendResponse(getWatchedItems());
break;
break;
case "setItemWatchState":
case "setItemWatchState":
if (msg.state)
if (msg.state)
sendResponse(addWatchedItem(msg.id));
sendResponse(addWatchedItem(msg.id));
else
else
sendResponse(removeWatchedItem(msg.id));
sendResponse(removeWatchedItem(msg.id));
break;
break;
case "setItemWatchTarget":
case "setItemWatchTarget":
setItemWatchTarget(msg.id, msg.count);
setItemWatchTarget(msg.id, msg.count);
break;
break;
case "setItemGroup":
setItemGroup(msg.id, msg.group);
break;
case "getFavedSummons":
case "getFavedSummons":
sendResponse(getFavedSummons());
sendResponse(getFavedSummons());
break;
break;
case "setSummonFaveState":
case "setSummonFaveState":
if (msg.state)
if (msg.state)
sendResponse(addFavedSummon(msg.id));
sendResponse(addFavedSummon(msg.id));
else
else
sendResponse(removeFavedSummon(msg.id));
sendResponse(removeFavedSummon(msg.id));
break;
break;
case "setSummonOrder":
case "setSummonOrder":
settings.set("summonOrder", msg.data);
settings.set("summonOrder", msg.data);
break;
break;
case "getIsDead":
case "getIsDead":
sendResponse(isDead);
sendResponse(isDead);
break;
break;
case "doGameAjax":
case "doGameAjax":
doGameAjax(msg, tabId, msg.uid, sendResponse);
doGameAjax(msg, tabId, msg.uid, sendResponse);
// retain sendResponse
// retain sendResponse
return true;
return true;
case "doGamePopup":
case "doGamePopup":
case "doGameRedirect":
case "doGameRedirect":
actuallySendMessage(msg, tabId);
actuallySendMessage(msg, tabId);
break;
break;
case "getTabId":
case "getTabId":
sendResponse(tabId);
sendResponse(tabId);
break;
break;
case "getUserIdAndTabId":
case "getUserIdAndTabId":
msg.tabId = tabId;
msg.tabId = tabId;
actuallySendMessage(msg, tabId, sendResponse);
actuallySendMessage(msg, tabId, sendResponse);
return true;
return true;
case "getIsSuspended":
case "getIsSuspended":
sendResponse(!!userDict.isSuspended);
sendResponse(!!userDict.isSuspended);
return true;
return true;
case "recordRewards":
case "recordRewards":
handleQuestRewards(msg);
handleQuestRewards(msg);
break;
break;
case "recordRaidInfo":
case "recordRaidInfo":
handleRaidInfo(msg);
handleRaidInfo(msg);
break;
break;
case "registerSecretKey":
case "registerSecretKey":
secretKeysByTabId[tabId] = msg.key;
secretKeysByTabId[tabId] = msg.key;
break;
break;
case "actionStarted":
case "actionStarted":
userDict.lastActionStartedWhen = msg.when;
userDict.lastActionStartedWhen = msg.when;
userDict.lastActionId = msg.actionId;
userDict.lastActionId = msg.actionId;
broadcastActionTimestamps(msg.uid, userDict);
broadcastActionTimestamps(msg.uid, userDict);
break;
break;
case "actionEnded":
case "actionEnded":
if (msg.succeeded) {
if (msg.succeeded) {
userDict.lastSuccessfulActionStartedWhen =
userDict.lastSuccessfulActionStartedWhen =
userDict.lastActionStartedWhen;
userDict.lastActionStartedWhen;
}
}
if (userDict.lastActionId === msg.actionId) {
if (userDict.lastActionId === msg.actionId) {
if (msg.succeeded) {
if (msg.succeeded) {
userDict.lastSuccessfulActionId =
userDict.lastSuccessfulActionId =
userDict.lastActionId;
userDict.lastActionId;
}
}
else {
else {
userDict.lastActionId = null;
userDict.lastActionId = null;
}
}
}
}
userDict.lastActionEndedWhen = msg.when;
userDict.lastActionEndedWhen = msg.when;
broadcastActionTimestamps(msg.uid, userDict);
broadcastActionTimestamps(msg.uid, userDict);
break;
break;
case "actionCompletedAnimation":
case "actionCompletedAnimation":
// When an action's animation is complete, we disable
// When an action's animation is complete, we disable
// the timer since the lockout is definitely over
// the timer since the lockout is definitely over
if (msg.actionId === userDict.lastActionId) {
if (msg.actionId === userDict.lastActionId) {
userDict.lastActionStartedWhen =
userDict.lastActionStartedWhen =
userDict.lastActionId = null;
userDict.lastActionId = null;
broadcastActionTimestamps(msg.uid, userDict);
broadcastActionTimestamps(msg.uid, userDict);
}
}
break;
break;
case "getLastActionTimestamps":
case "getLastActionTimestamps":
sendResponse(makeActionTimestamps(userDict));
sendResponse(makeActionTimestamps(userDict));
break;
break;
default:
default:
log("Unknown message " + key);
log("Unknown message " + key);
sendResponse({ error: true });
sendResponse({ error: true });
break;
break;
}
}
}
}
;
;
function broadcastActionTimestamps(uid, userDict) {
function broadcastActionTimestamps(uid, userDict) {
var obj = makeActionTimestamps(userDict);
var obj = makeActionTimestamps(userDict);
var msg = {
var msg = {
type: "actionTimestampsChanged",
type: "actionTimestampsChanged",
data: obj,
data: obj,
uid: uid
uid: uid
};
};
chrome.tabs.query(
chrome.tabs.query(
// FIXME: Can we narrow this to granblue tabs without the 'tabs' permission?
// FIXME: Can we narrow this to granblue tabs without the 'tabs' permission?
{}, function (tabs) {
{}, function (tabs) {
if (!tabs)
if (!tabs)
return;
return;
for (var i = 0; i < tabs.length; i++) {
for (var i = 0; i < tabs.length; i++) {
var tab = tabs[i];
var tab = tabs[i];
chrome.tabs.sendMessage(tab.id, msg);
chrome.tabs.sendMessage(tab.id, msg);
if (chrome.runtime.lastError)
if (chrome.runtime.lastError)
log(chrome.runtime.lastError);
log(chrome.runtime.lastError);
}
}
});
});
}
}
;
;
function makeActionTimestamps(userDict) {
function makeActionTimestamps(userDict) {
return {
return {
actionId: userDict.lastActionId,
actionId: userDict.lastActionId,
successfulActionId: userDict.lastSuccessfulActionId,
successfulActionId: userDict.lastSuccessfulActionId,
started: userDict.lastActionStartedWhen,
started: userDict.lastActionStartedWhen,
successfulStarted: userDict.lastSuccessfulActionStartedWhen,
successfulStarted: userDict.lastSuccessfulActionStartedWhen,
ended: userDict.lastActionEndedWhen
ended: userDict.lastActionEndedWhen
};
};
}
}
;
;
function handleQuestRewards(msg) {
function handleQuestRewards(msg) {
var userDict = getUserDict(msg.uid);
var userDict = getUserDict(msg.uid);
if (!userDict.raids)
if (!userDict.raids)
return;
return;
var urlFragment = msg.url.substr(msg.url.lastIndexOf("/") + 1);
var urlFragment = msg.url.substr(msg.url.lastIndexOf("/") + 1);
urlFragment = urlFragment.substr(0, urlFragment.indexOf("?"));
urlFragment = urlFragment.substr(0, urlFragment.indexOf("?"));
var raidId = parseInt(urlFragment);
var raidId = parseInt(urlFragment);
var questId = userDict.raids[raidId];
var questId = userDict.raids[raidId];
}
}
;
;
function handleRaidInfo(msg) {
function handleRaidInfo(msg) {
var userDict = getUserDict(msg.uid);
var userDict = getUserDict(msg.uid);
if (!userDict.raids)
if (!userDict.raids)
userDict.raids = {};
userDict.raids = {};
userDict.raids[msg.raidId] = msg.questId;
userDict.raids[msg.raidId] = msg.questId;
}
}
;
;
function parseTimeInMinutes(text) {
function parseTimeInMinutes(text) {
var parts = text.split(/[\D]+/);
var parts = text.split(/[\D]+/);
var result = 0;
var result = 0;
for (var i = 0, len = Math.min(parts.length, 2); i < len; i++) {
for (var i = 0, len = Math.min(parts.length, 2); i < len; i++) {
if (parts[i].length === 0) {
if (parts[i].length === 0) {
break;
break;
}
}
result = result * 60 + parseInt(parts[i]);
result = result * 60 + parseInt(parts[i]);
}
}
return result;
return result;
}
}
;
;
function estimateValue(truncated, maximum, timeRemaining, elapsedTimeMs, minutesPerUnit) {
function estimateValue(truncated, maximum, timeRemaining, elapsedTimeMs, minutesPerUnit) {
if (truncated >= maximum)
if (truncated >= maximum)
return truncated;
return truncated;
// HACK: Add 59 seconds to the remaining time since they round down the number of minutes
// HACK: Add 59 seconds to the remaining time since they round down the number of minutes
timeRemaining += 59 / 60;
timeRemaining += 59 / 60;
var durationFromFull = maximum * minutesPerUnit;
var durationFromFull = maximum * minutesPerUnit;
timeRemaining = Math.max(0, timeRemaining - (elapsedTimeMs / 60000));
timeRemaining = Math.max(0, timeRemaining - (elapsedTimeMs / 60000));
var fract = (timeRemaining / durationFromFull);
var fract = (timeRemaining / durationFromFull);
fract = Math.max(0.0, Math.min(1.0, fract));
fract = Math.max(0.0, Math.min(1.0, fract));
var estimatedValue = maximum * (1.0 - fract);
var estimatedValue = maximum * (1.0 - fract);
return estimatedValue;
return estimatedValue;
}
}
;
;
function fixupStatus(status, uid) {
function fixupStatus(status, uid) {
if (!status)
if (!status)
return status;
return status;
var userDict = getUserDict(uid);
var userDict = getUserDict(uid);
// FIXME
// FIXME
var lastUpdate = userDict.lastStatusUpdate;
var lastUpdate = userDict.lastStatusUpdate;
status._lastUpdate = lastUpdate;
status._lastUpdate = lastUpdate;
status._now = Date.now();
status._now = Date.now();
var age = (status._now - status._lastUpdate);
var age = (status._now - status._lastUpdate);
status._precise_ap = estimateValue(status.ap, parseInt(status.max_action_point), parseTimeInMinutes(status.action_point_remain), age, 5);
status._precise_ap = estimateValue(status.ap, parseInt(status.max_action_point), parseTimeInMinutes(status.action_point_remain), age, 5);
status._precise_bp = estimateValue(status.bp, parseInt(status.max_battle_point), parseTimeInMinutes(status.battle_point_remain), age, 10);
status._precise_bp = estimateValue(status.bp, parseInt(status.max_battle_point), parseTimeInMinutes(status.battle_point_remain), age, 10);
status.buffs = [];
status.buffs = [];
if (userDict.guildBuffs) {
if (userDict.guildBuffs) {
// FIXME
// FIXME
age = (status._now - userDict.lastGuildBuffUpdate);
age = (status._now - userDict.lastGuildBuffUpdate);
for (var i = 0, l = userDict.guildBuffs.length; i < l; i++) {
for (var i = 0, l = userDict.guildBuffs.length; i < l; i++) {
var gb = userDict.guildBuffs[i];
var gb = userDict.guildBuffs[i];
var timeRemaining = (parseTimeInMinutes(gb.time) * 60 * 1000) - age;
var timeRemaining = (parseTimeInMinutes(gb.time) * 60 * 1000) - age;
if (timeRemaining <= 0)
if (timeRemaining <= 0)
continue;
continue;
status.buffs.push({
status.buffs.push({
comment: gb.comment,
comment: gb.comment,
timeRemaining: timeRemaining,
timeRemaining: timeRemaining,
imageUrl: "http://game-a.granbluefantasy.jp/assets_en/img/sp/assets/item/support/support_" +
imageUrl: "http://game-a.granbluefantasy.jp/assets_en/img/sp/assets/item/support/support_" +
gb.image + "_" + gb.level + ".png"
gb.image + "_" + gb.level + ".png"
});
});
}
}
}
}
if (userDict.personalBuffs) {
if (userDict.personalBuffs) {
// FIXME
// FIXME
age = (status._now - userDict.lastPersonalBuffUpdate);
age = (status._now - userDict.lastPersonalBuffUpdate);
for (var k in userDict.personalBuffs) {
for (var k in userDict.personalBuffs) {
if (!userDict.personalBuffs.hasOwnProperty(k))
if (!userDict.personalBuffs.hasOwnProperty(k))
continue;
continue;
var pb = userDict.personalBuffs[k];
var pb = userDict.personalBuffs[k];
var timeRemaining = (parseTimeInMinutes(pb.remain_time) * 60 * 1000) - age;
var timeRemaining = (parseTimeInMinutes(pb.remain_time) * 60 * 1000) - age;
if (timeRemaining <= 0)
if (timeRemaining <
continue;
status.buffs.push({
comment: pb.name,
timeRemaining: timeRemaining,
imageUrl: "http://game-a.granbluefantasy.jp/assets_en/img/sp/assets/item/support/" +
pb.image_path + "_" + pb.level + ".png"
});
}
}
return status;
}
;
function handleNewStatus(status, uid) {
if (!status) {
log("Failed status update");
return;
}
getUserDict(uid).lastStatus = status;
getUserDict(uid).lastStatusUpdate = Date.now();
getUserDict(uid).nextStatusUpdate = Date.now() + minimumUpdateDelay;
var minutesUntilApRefill = parseTimeInMinutes(status.action_poin