Diff
checker
テキスト
テキスト
画像
ドキュメント
Excel
フォルダ
Legal
Enterprise
デスクトップ
料金
ログイン
Diffchecker デスクトップのダウンロード
テキスト比較
2 つのテキスト ファイルの違いを見つける
ツール
履歴
ライブエディター
空白の変更を非表示
未変更行を折りたたむ
折り返しなし
レイアウト
分割
統合
比較精度
スマート
単語
文字
テキストスタイル
外観を変更
シンタックスハイライト
構文を選択
無視
テキスト変換
最初の差分へ移動
入力を編集
Diffchecker Desktop
Diffcheckerを実行する最も安全な方法。Diffchecker Desktopアプリを入手:あなたの差分はコンピューターから出ることはありません!
Desktopを入手
Untitled diff
作成日
9 年前
差分は期限切れになりません
クリア
エクスポート
共有
説明
22 削除
行
合計
削除
文字
合計
削除
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
715 行
すべてコピー
19 追加
行
合計
追加
文字
合計
追加
この機能を引き続き使用するには、アップグレードしてください
Diff
checker
Pro
価格を見る
712 行
すべてコピー
"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
保存された差分
原文
ファイルを開く
"use strict"; var settings = new Store("settings", { "preferFriendSummons": true, "preferNonFriendSummonsInFavorites": true, "preferLimitBrokenSummons": true, "preferHighLevelSummons": true, "notifyOnFullAP": false, "notifyOnFullBP": false, "showSkillCooldowns": true, "showDebuffTimers": true, "showBuffTimers": true, "monitorRaidDebuffs": true, "keyboardShortcuts": true, "showBookmarks": true, "preferredSummonElement": "", "submenuSize": 1.0, "bookmarksSize": 1.0, "bookmarksMenuSize": 1.0, "recentQuest": null, "showQuickPanels": true, "showGaugeOverlays": true, "openBookmarksOnClick": false, "fixJPFontRendering": true, "enableCoOpEnhancements": true, "dropdownFix": true, "disableMiddleRightClick": true, "statusPanel": true, "itemsPanel": true, "raidsPanel": false, "clockBrightness": 0.65, "oneClickQuickSummons": true, "bookmarksInactiveIcon": null, "bookmarksActiveIcon": null, "bookmarksIconPadding": 100, "horizontalBookmarks": false, "statusPanelBuffs": false, "statusPanelExpiringBuffs": true, "betterEnglishFont": false, "showItemWatchButtons": true, "showPartyNames": true, "filterEnemyTimers": true, "showPerformanceHud": false, "showNetworkHud": false, "showWeaponAttack": true, "showSkillActivationIndicator": true, "autofillBackupTweets": true, "moveCoOpFooter": true, "largeQuickPanels": false, "showPartyHelp": false, "keepSoundOnBlur": true, "stuckButtonWorkaround2": true, "showLastActionTimer": true, "smartSupports": true, "defaultToSmartSupports": false, "disablePhalanxSticker": true, "summonOrder": "{}", "password": "", "minimumPopupWait": 350, "maximumPopupWait": 1750, "focusQuickPanels": true, "newSkillSystem": true }); var failedUpdateMinimumDelay = 10 * 1000; var minimumUpdateDelay = 60 * 4 * 1000; var minimumRaidUpdateDelay = 30 * 1000; var minimumItemUpdateDelay = 60 * 30 * 1000; var minimumHaloUpdateDelay = 60 * 30 * 1000; var secretKeysByTabId = {}; var lastFailure = -1; var users = {}; var lastRaidCodes = {}; var isDead = true; var isShutdown = false; var lastLocation = null; var idleRedirectPending = false; var lastRedirectTarget = null; chrome.runtime.onMessage.addListener(onRuntimeMessage); chrome.alarms.onAlarm.addListener(onAlarm); chrome.runtime.onInstalled.addListener(function () { var dc = chrome.declarativeContent; dc.onPageChanged.removeRules(undefined, function () { dc.onPageChanged.addRules([ { conditions: [ new dc.PageStateMatcher({ pageUrl: { hostEquals: 'game.granbluefantasy.jp', schemes: ["https", "http"] }, }), new dc.PageStateMatcher({ pageUrl: { hostEquals: 'gbf.game.mbga.jp', schemes: ["https", "http"] }, }) ], actions: [new dc.ShowPageAction()] } ]); }); }); log("Started"); function getAdjustedSettings() { var result = settings.toObject(); result.allowDragSelect = false; // result.autoSkipToQuestResults = false; // result.oneClickQuickSummons = false; result.realtimeRaidList = false; // result.raidsPanel = false; // result.showQuickPanels = false; result.touchInputSupport = false; // Cygamesssssssssssssss result.autofillBackupTweets = false; // API changes broke this result.detailedUpgradePage = false; return result; } ; function log(...args) { args.unshift((new Date()).toLocaleString() + " |"); console.log.apply(console, args); } ; function getWatchedItems() { var result = JSON.parse(settings.get("watchedItems") || "[]"); if ((result.length === 1) && (result[0] === null)) result = []; var targetCounts = JSON.parse(settings.get("targetItemCounts") || "{}"); return { items: result, counts: targetCounts }; } ; function setItemWatchTarget(id, count) { var targetCounts = JSON.parse(settings.get("targetItemCounts") || "{}"); targetCounts[id] = count; settings.set("targetItemCounts", JSON.stringify(targetCounts)); } ; function addWatchedItem(id) { var items = getWatchedItems().items; if (items.indexOf(id) >= 0) return items; if (!id) return items; items.push(id); settings.set("watchedItems", JSON.stringify(items)); return items; } ; function removeWatchedItem(id) { var items = getWatchedItems().items; var index = items.indexOf(id); if (index < 0) return items; items.splice(index, 1); settings.set("watchedItems", JSON.stringify(items)); return items; } ; function getFavedSummons() { var result = JSON.parse(settings.get("favedSummons") || "[]"); if ((result.length === 1) && (result[0] === null)) result = []; return result; } ; function addFavedSummon(id) { var items = getFavedSummons(); if (items.indexOf(id) >= 0) return items; if (!id) return items; items.push(id); settings.set("favedSummons", JSON.stringify(items)); return items; } ; function removeFavedSummon(id) { var items = getFavedSummons(); var index = items.indexOf(id); if (index < 0) return items; items.splice(index, 1); settings.set("favedSummons", JSON.stringify(items)); return items; } ; function getUserDict(uid) { var dict = users[uid]; if (!dict) dict = users[uid] = { lastUpdate: [] }; return dict; } ; function setUserData(uid, key, data) { var dict = getUserDict(uid); if (data) { dict.lastUpdate[key] = Date.now(); dict[key] = data; } else { dict.lastUpdate[key] = 0; dict[key] = null; } } ; function getUserData(uid, key) { var dict = getUserDict(uid); return dict[key]; } ; function getLastDataUpdate(uid, key) { var dict = getUserDict(uid); return dict.lastUpdate[key]; } ; function formatItemCounters(uid) { var itemCounters = getUserDict(uid).itemCounters; if (!itemCounters) return null; var counterDict = {}; for (var i = 0, l = itemCounters.length; i < l; i++) { var item = itemCounters[i]; counterDict[item.item_id] = item; } return counterDict; } ; function onRuntimeMessage(msg, sender, sendResponse) { if (chrome.runtime.lastError) log(chrome.runtime.lastError); var key = msg.type; var userDict; if (msg.uid) userDict = getUserDict(msg.uid); var tabId; if (sender.tab && sender.tab.id) tabId = sender.tab.id; else if (msg.tabId) tabId = msg.tabId; if (tabId <= 0) { log("Message has no tab id", key); return; } var senderUrl = sender.url || ""; if ((senderUrl.indexOf("granbluefantasy.jp") >= 0) || (senderUrl.indexOf("mbga.jp") >= 0)) { } else if ((senderUrl.indexOf("chrome-extension://") >= 0) && (senderUrl.indexOf("api.html") >= 0)) { switch (key) { case "apiRequest": case "getSettings": break; default: log("Rejected disallowed API request", msg); return; } } switch (key) { case "apiRequest": if (!settings.get("webAPI")) { log("Rejected API request because API is disabled", msg); sendResponse(null); return; } log("Processing API request", msg.request.type); switch (msg.request.type) { case "getUserIds": sendResponse(JSON.stringify(Object.keys(users))); break; case "getVersion": sendResponse(chrome.app.getDetails().version); break; case "tryJoinRaid": case "getCombatState": log("Preparing to send api request", msg); chrome.tabs.query({}, function (tabs) { if (tabs.length === 0) { log("Found no granblue tab"); sendResponse({ type: "result", error: "No granblue tab found" }); return; } for (var i = 0, l = tabs.length; i < l; i++) { var tab = tabs[i]; var tabUrl = tab.url; if (!tabUrl || ((tabUrl.indexOf("game.granbluefantasy.jp") < 0) && (tabUrl.indexOf("gbf.game.mbga.jp") < 0))) { continue; } log("Sending api request", msg); actuallySendMessage(msg, tab.id, function (result) { log("Got result for api request"); sendResponse(result); }); return; } log("Found no granblue tab"); sendResponse({ type: "result", error: "No granblue tab found" }); }); return true; default: sendResponse({ type: "result", error: "Unknown message" }); break; } break; case "getUserIds": sendResponse(JSON.stringify(Object.keys(users))); break; case "setPassword": settings.set("password", msg.password); break; case "pleaseInjectStylesheets": injectStylesheetsIntoTab(sender); break; case "heartbeat": isDead = false; break; case "cancelSuspend": if (userDict.isSuspended) log("Canceling idle/maintenance suspend for " + msg.uid); userDict.isSuspended = false; lastFailure = -1; break; case "isShutdown": sendResponse(isShutdown); break; case "setCompatibility": var newState = (msg.state === false); if (newState !== isShutdown) { log("Compatibility shutdown state set to", newState); isShutdown = newState; } break; case "openNewTab": chrome.tabs.create({ url: msg.url }); break; case "getVersion": sendResponse(chrome.app.getDetails().version); break; case "setRecentCoOpHost": settings.set("recentCoOpHost", msg.data); break; case "getRecentCoOpHost": sendResponse(settings.get("recentCoOpHost") || null); break; case "setCurrentEvent": if (msg.href !== settings.get("currentEvent")) log("Event changed to '" + msg.href + "'"); settings.set("currentEvent", msg.href); break; case "setCurrentGuildWar": if (msg.href !== settings.get("currentGuildWar")) log("Guild war changed to '" + msg.href + "'"); settings.set("currentGuildWar", msg.href); break; case "getCurrentEvent": sendResponse(settings.get("currentEvent") || null); break; case "getCurrentGuildWar": sendResponse(settings.get("currentGuildWar") || null); break; case "setRecentQuest": settings.set("recentQuest", msg.url); break; case "getRecentQuest": sendResponse(settings.get("recentQuest") || null); break; case "setLastLocation": // FIXME: Track per-tab lastLocation = msg.url; break; case "setIdleRedirectPending": // FIXME: Track per-tab idleRedirectPending = msg.state; if (msg.url) lastRedirectTarget = msg.url; break; case "getLastLocation": sendResponse(lastLocation || null); break; case "getIdleRedirectInfo": if (idleRedirectPending) { sendResponse({ pending: true, location: lastLocation, lastRedirectTarget: lastRedirectTarget }); } else { sendResponse({ pending: false }); } break; case "getSettings": sendResponse(getAdjustedSettings()); break; case "getRaidCode": sendResponse(lastRaidCodes[tabId]); break; case "updateRaidCode": lastRaidCodes[tabId] = msg.raidCode; break; case "getItemCounters": return maybeDoUpdate(userDict.nextCounterUpdate, minimumUpdateDelay, formatItemCounters, updateItemCounters, sendResponse, msg.force, tabId, msg.uid); case "updateItemCounters": userDict.nextCounterUpdate = Date.now() + minimumUpdateDelay; userDict.itemCounters = msg.counters; break; case "invalidateStatus": if (userDict.lastStatus) log("Status invalidated"); userDict.nextStatusUpdate = 0; userDict.lastStatus = null; break; case "getStatus": var getLastStatus = function (uid) { var s = getUserDict(uid).lastStatus; if (s) fixupStatus(s, uid); return s; }; if (msg.lazy) { var lastStatus = getLastStatus(msg.uid); if (lastStatus) { sendResponse(lastStatus); return; } else { // log("Lazy status update failed"); } } return maybeDoUpdate(userDict.nextStatusUpdate, minimumUpdateDelay, getLastStatus, updateStatus, sendResponse, msg.force, tabId, msg.uid); case "updateStatus": handleNewStatus(msg.status, msg.uid); break; case "invalidateBuffs": userDict.nextGuildBuffUpdate = 0; userDict.nextPersonalBuffUpdate = 0; userDict.guildBuffs = null; userDict.personalBuffs = null; log("Buffs invalidated"); break; case "updateGuildBuffs": userDict.lastGuildBuffUpdate = Date.now(); userDict.nextGuildBuffUpdate = Date.now() + minimumUpdateDelay; userDict.guildBuffs = msg.buffs; break; case "updatePersonalBuffs": userDict.lastPersonalBuffUpdate = Date.now(); userDict.nextPersonalBuffUpdate = Date.now() + minimumUpdateDelay; userDict.personalBuffs = msg.buffs; break; case "getNextRankRp": // if not force, don't actually update since this is a heavy call if (!msg.force) { if (userDict.nextNextRankRpUpdate) { sendResponse(userDict.nextRankRp); break; } sendResponse(null); break; } return maybeDoUpdate(userDict.nextNextRankRpUpdate, minimumUpdateDelay, function (uid) { return getUserDict(uid).nextRankRp; }, updateNextRankRp, sendResponse, msg.force, tabId, msg.uid); case "updateNextRankRp": userDict.nextNextRankRpUpdate = Date.now() + minimumUpdateDelay; userDict.nextRankRp = getRpToNextRank(msg.data); break; case "getRaids": return maybeDoUpdate(userDict.nextRaidUpdate, minimumRaidUpdateDelay, function (uid) { return getUserDict(uid).lastRaids; }, updateRaids, sendResponse, msg.force, tabId, msg.uid); case "invalidateRaids": if (msg.raids) { handleNewRaids(msg.raids, msg.uid); } else { if (userDict.lastRaids) log("Raids invalidated"); userDict.nextRaidUpdate = 0; userDict.lastRaids = null; } break; case "getItems": return maybeDoUpdate(userDict.nextItemUpdate, minimumItemUpdateDelay, function (uid) { return getUserDict(uid).lastItems; }, updateItems, sendResponse, msg.force, tabId, msg.uid); case "invalidateItems": if (msg.items) { handleNewItems(msg.items, msg.uid); } else { if (userDict.lastItems) log("Items invalidated"); userDict.nextItemUpdate = 0; userDict.lastItems = null; } break; case "getWatchedItems": sendResponse(getWatchedItems()); break; case "setItemWatchState": if (msg.state) sendResponse(addWatchedItem(msg.id)); else sendResponse(removeWatchedItem(msg.id)); break; case "setItemWatchTarget": setItemWatchTarget(msg.id, msg.count); break; case "getFavedSummons": sendResponse(getFavedSummons()); break; case "setSummonFaveState": if (msg.state) sendResponse(addFavedSummon(msg.id)); else sendResponse(removeFavedSummon(msg.id)); break; case "setSummonOrder": settings.set("summonOrder", msg.data); break; case "getIsDead": sendResponse(isDead); break; case "doGameAjax": doGameAjax(msg, tabId, msg.uid, sendResponse); // retain sendResponse return true; case "doGamePopup": case "doGameRedirect": actuallySendMessage(msg, tabId); break; case "getTabId": sendResponse(tabId); break; case "getUserIdAndTabId": msg.tabId = tabId; actuallySendMessage(msg, tabId, sendResponse); return true; case "getIsSuspended": sendResponse(!!userDict.isSuspended); return true; case "recordRewards": handleQuestRewards(msg); break; case "recordRaidInfo": handleRaidInfo(msg); break; case "registerSecretKey": secretKeysByTabId[tabId] = msg.key; break; case "actionStarted": userDict.lastActionStartedWhen = msg.when; userDict.lastActionId = msg.actionId; broadcastActionTimestamps(msg.uid, userDict); break; case "actionEnded": if (msg.succeeded) { userDict.lastSuccessfulActionStartedWhen = userDict.lastActionStartedWhen; } if (userDict.lastActionId === msg.actionId) { if (msg.succeeded) { userDict.lastSuccessfulActionId = userDict.lastActionId; } else { userDict.lastActionId = null; } } userDict.lastActionEndedWhen = msg.when; broadcastActionTimestamps(msg.uid, userDict); break; case "actionCompletedAnimation": // When an action's animation is complete, we disable // the timer since the lockout is definitely over if (msg.actionId === userDict.lastActionId) { userDict.lastActionStartedWhen = userDict.lastActionId = null; broadcastActionTimestamps(msg.uid, userDict); } break; case "getLastActionTimestamps": sendResponse(makeActionTimestamps(userDict)); break; default: log("Unknown message " + key); sendResponse({ error: true }); break; } } ; function broadcastActionTimestamps(uid, userDict) { var obj = makeActionTimestamps(userDict); var msg = { type: "actionTimestampsChanged", data: obj, uid: uid }; chrome.tabs.query( // FIXME: Can we narrow this to granblue tabs without the 'tabs' permission? {}, function (tabs) { if (!tabs) return; for (var i = 0; i < tabs.length; i++) { var tab = tabs[i]; chrome.tabs.sendMessage(tab.id, msg); if (chrome.runtime.lastError) log(chrome.runtime.lastError); } }); } ; function makeActionTimestamps(userDict) { return { actionId: userDict.lastActionId, successfulActionId: userDict.lastSuccessfulActionId, started: userDict.lastActionStartedWhen, successfulStarted: userDict.lastSuccessfulActionStartedWhen, ended: userDict.lastActionEndedWhen }; } ; function handleQuestRewards(msg) { var userDict = getUserDict(msg.uid); if (!userDict.raids) return; var urlFragment = msg.url.substr(msg.url.lastIndexOf("/") + 1); urlFragment = urlFragment.substr(0, urlFragment.indexOf("?")); var raidId = parseInt(urlFragment); var questId = userDict.raids[raidId]; } ; function handleRaidInfo(msg) { var userDict = getUserDict(msg.uid); if (!userDict.raids) userDict.raids = {}; userDict.raids[msg.raidId] = msg.questId; } ; function parseTimeInMinutes(text) { var parts = text.split(/[\D]+/); var result = 0; for (var i = 0, len = Math.min(parts.length, 2); i < len; i++) { if (parts[i].length === 0) { break; } result = result * 60 + parseInt(parts[i]); } return result; } ; function estimateValue(truncated, maximum, timeRemaining, elapsedTimeMs, minutesPerUnit) { if (truncated >= maximum) return truncated; // HACK: Add 59 seconds to the remaining time since they round down the number of minutes timeRemaining += 59 / 60; var durationFromFull = maximum * minutesPerUnit; timeRemaining = Math.max(0, timeRemaining - (elapsedTimeMs / 60000)); var fract = (timeRemaining / durationFromFull); fract = Math.max(0.0, Math.min(1.0, fract)); var estimatedValue = maximum * (1.0 - fract); return estimatedValue; } ; function fixupStatus(status, uid) { if (!status) return status; var userDict = getUserDict(uid); // FIXME var lastUpdate = userDict.lastStatusUpdate; status._lastUpdate = lastUpdate; status._now = Date.now(); 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_bp = estimateValue(status.bp, parseInt(status.max_battle_point), parseTimeInMinutes(status.battle_point_remain), age, 10); status.buffs = []; if (userDict.guildBuffs) { // FIXME age = (status._now - userDict.lastGuildBuffUpdate); for (var i = 0, l = userDict.guildBuffs.length; i < l; i++) { var gb = userDict.guildBuffs[i]; var timeRemaining = (parseTimeInMinutes(gb.time) * 60 * 1000) - age; if (timeRemaining <= 0) continue; status.buffs.push({ comment: gb.comment, timeRemaining: timeRemaining, imageUrl: "http://game-a.granbluefantasy.jp/assets_en/img/sp/assets/item/support/support_" + gb.image + "_" + gb.level + ".png" }); } } if (userDict.personalBuffs) { // FIXME age = (status._now - userDict.lastPersonalBuffUpdate); for (var k in userDict.personalBuffs) { if (!userDict.personalBuffs.hasOwnProperty(k)) continue; var pb = userDict.personalBuffs[k]; var timeRemaining = (parseTimeInMinutes(pb.remain_time) * 60 * 1000) - age; if (timeRemaining <= 0) 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_point_remain); var minutesUntilBpRefill = parseTimeInMinutes(status.battle_point_remain); if ((minutesUntilApRefill > 1) && settings.get("notifyOnFullAP")) chrome.alarms.create("apFull", { delayInMinutes: minutesUntilApRefill + 1 }); else chrome.alarms.clear("apFull"); if ((minutesUntilBpRefill > 1) && settings.get("notifyOnFullBP")) chrome.alarms.create("bpFull", { delayInMinutes: minutesUntilBpRefill + 1 }); else chrome.alarms.clear("bpFull"); // log("ap time", minutesUntilApRefill, "bp time", minutesUntilBpRefill); } ; function maybeDoUpdate(nextTime, minimumUpdateDelay, getValue, doUpdate, sendResponse, force, tabId, uid) { var shouldUpdate = false; var userDict = getUserDict(uid); var now = Date.now(); if (!nextTime) shouldUpdate = true; else if (now >= nextTime) shouldUpdate = true; else if (force) shouldUpdate = true; if ((now - lastFailure) < failedUpdateMinimumDelay) { log("Rate-limiting update due to failure"); shouldUpdate = false; } if (userDict.isSuspended && shouldUpdate) { log("Rejecting update request due to idle timeout"); sendResponse(null); return false; } if (!userDict.inFlightRequests) userDict.inFlightRequests = {}; var requestName = doUpdate.name; var ifr = userDict.inFlightRequests[requestName]; if (ifr) { var elapsed = now - ifr.startedWhen.getTime(); if (elapsed >= 30000) { log("Request of type '" + requestName + "' in-flight since " + ifr.startedWhen.toLocaleString() + "; that's too long, so we're going again anyway."); } else { log("Request of type '" + requestName + "' in-flight since " + ifr.startedWhen.toLocaleString() + "; waiting for it."); ifr.then(function (result) { log("In-flight '" + requestName + "' request completed with value", result); sendResponse(result); }); return true; } } if (shouldUpdate) { var pr = new PromiseResolver(); pr.promise.startedWhen = new Date(); userDict.inFlightRequests[requestName] = pr.promise; doUpdate(tabId, uid, function (_uid) { var response = getValue(_uid); delete userDict.inFlightRequests[requestName]; sendResponse(response); pr.resolve(response); }); return true; } else { sendResponse(getValue(uid)); return false; } } ; function doGameAjax(msg, tabId, uid, callback) { /* if (Math.random() < 0.33) { console.log("Injecting error for request", msg); callback(null, "fake error"); return; } */ actuallySendMessage(msg, tabId, function (bundle) { if (!bundle) { callback({ error: true }, "no response"); return; } var response = bundle[0]; var error = bundle[1]; var url = bundle[2]; if (chrome.runtime.lastError) { isDead = true; log(chrome.runtime.lastError); } else { isDead = false; } if (error) { if (error.indexOf("-- abort") >= 0) { log("xhr aborted", url); } else { log("Error from server", error, url); lastFailure = Date.now(); } } if (typeof (response) === "string") { try { response = JSON.parse(response); } catch (exc) { } } if (isIdleTimeoutRedirect(response)) { handleIdleTimeout(uid); callback({ idleTimeout: true }, error); } else if (isMaintenanceRedirect(response)) { handleMaintenance(uid); callback({ maintenance: true }, error); } else { callback(response, error); } }); } ; function isIdleTimeoutRedirect(jsonBody) { if (jsonBody && jsonBody.redirect && (jsonBody.redirect.indexOf("top") >= 0)) return true; return false; } ; function isMaintenanceRedirect(jsonBody) { if (jsonBody && jsonBody.redirect && (jsonBody.redirect.indexOf("maintenance") >= 0)) return true; return false; } ; function handleIdleTimeout(uid) { log("Idle timeout"); getUserDict(uid).isSuspended = true; lastFailure = Date.now() + 5000; } ; function handleMaintenance(uid) { log("Maintenance"); getUserDict(uid).isSuspended = true; lastFailure = Date.now() + 5000; } ; function updateStatus(tabId, uid, callback) { var msg = { type: "doGameAjax", url: "/user/status" }; // log("Triggering status update"); doGameAjax(msg, tabId, uid, function (result) { getUserDict(uid).nextStatusUpdate = Date.now() + minimumUpdateDelay; if (!result) { log("Status update failed"); callback(uid); } else if (result.idleTimeout) { log("Status update failed: idle timeout"); callback(uid); } else if (result.maintenance) { log("Status update failed: maintenance"); callback(uid); } else { getUserDict(uid).lastStatusUpdate = Date.now(); getUserDict(uid).lastStatus = result.status; // log("Status updated -> ", lastStatus); callback(uid); } }); } ; function getRpToNextRank(data) { data = decodeURIComponent(data); /* Data is of the following form: [garbage] <div class="txt-next-value">Next ###Rankポイント</div> OR (depending on language) <div class="txt-next-value">Next lvl in ### Rank Points</div> [garbage] */ var result = parseInt(data.replace(/^[^]*txt-next-value[\D]+([\d]+)[^]*$/, "$1")); // in case of something unexpected being passed in if (isNaN(result)) { return "?"; } return result; } function updateNextRankRp(tabId, uid, callback) { var msg = { type: "doGameAjax", url: "/profile/content/index/" + uid }; doGameAjax(msg, tabId, uid, function (result) { if (!result) { log("RP to next rank update failed"); callback(uid); } else if (result.idleTimeout) { log("RP to next rank update failed: idle timeout"); callback(uid); } else { getUserDict(uid).lastNextRankRpUpdate = Date.now(); getUserDict(uid).nextNextRankRpUpdate = Date.now() + minimumUpdateDelay; getUserDict(uid).nextRankRp = getRpToNextRank(result.data); callback(uid); } }); } ; function getStrikeTime(data) { data = decodeURIComponent(data); /* Data is of the following form: [garbage] <div class="txt-next-value">Next ###Rankポイント</div> OR (depending on language) <div class="txt-next-value">Next lvl in ### Rank Points</div> [garbage] */ /* var strikeTimes = []; var re = /\<div class="prt\-assault\-guildinfo"\>.*?\<div class="prt\-item\-status"\>(.*?)\<\/div/gms var m; while (m = re.exec(data)) { strikeTimes.push(m[1]); } log(strikeTimes); return strikeTimes; */ } function updateStrikeTime(tabId, uid, callback) { var msg = { type: "doGameAjax", url: "/guild_main/content/index/" }; doGameAjax(msg, tabId, uid, function (result) { if (!result) { log("Strike time update failed"); callback(uid); } else if (result.idleTimeout) { log("Strike time update failed: idle timeout"); callback(uid); } else { getUserDict(uid).lastStrikeTimeUpdate = Date.now(); getUserDict(uid).nextStrikeTimeUpdate = Date.now() + minimumUpdateDelay; getUserDict(uid).strikeTime = getStrikeTime(result.data); callback(uid); } }); } ; function updateItemCounters(tabId, uid, callback) { var msg = { type: "doGameAjax", url: "/item/normal_item_list/1" }; // log("Triggering counter update"); doGameAjax(msg, tabId, uid, function (result) { if (!result) { log("Counter update failed"); getUserDict(uid).nextCounterUpdate = Date.now() + minimumUpdateDelay; callback(uid); } else if (result.idleTimeout) { log("Counter update failed: idle timeout"); getUserDict(uid).nextCounterUpdate = Date.now() + minimumUpdateDelay; callback(uid); } else { getUserDict(uid).lastCounterUpdate = Date.now(); getUserDict(uid).nextCounterUpdate = Date.now() + minimumItemUpdateDelay; getUserDict(uid).itemCounters = result; // log("Counters updated -> ", itemCounters); callback(uid); } }); } ; function onAlarm(alarm) { log("Alarm '" + alarm.name + "' fired"); if (alarm.name.indexOf("Full") >= 0) { var resourceName = alarm.name.replace("Full", "").toUpperCase(); chrome.notifications.create({ type: "basic", iconUrl: "../../icons/active-256.png", title: resourceName + " full", message: "Your Granblue Fantasy " + resourceName + " is full." }); return; } } ; function actuallySendMessage(message, tabId, callback) { // *$!@)%KAKLMRSJ chrome garbage APIs if (tabId) { chrome.tabs.sendMessage(tabId, message, callback); } else { log("No granblue tab found as target for message", message, tabId); } } ; function handleNewRaids(raids, uid) { if (!raids) { log("Failed raid update"); return; } getUserDict(uid).lastRaids = raids; getUserDict(uid).lastRaidUpdate = Date.now(); getUserDict(uid).nextRaidUpdate = Date.now() + minimumRaidUpdateDelay; // log("ap time", minutesUntilApRefill, "bp time", minutesUntilBpRefill); } ; function handleNewItems(items, uid) { if (!items) { log("Failed item update"); return; } getUserDict(uid).lastItems = items; getUserDict(uid).lastItemUpdate = Date.now(); getUserDict(uid).nextItemUpdate = Date.now() + minimumItemUpdateDelay; // log("ap time", minutesUntilApRefill, "bp time", minutesUntilBpRefill); } ; function updateRaids(tabId, uid, callback) { var msg = { type: "doGameAjax", url: "/quest/assist_list/0" }; // log("Triggering status update"); doGameAjax(msg, tabId, uid, function (result) { if (!result) { log("Raid update failed"); callback(uid); } else if (result.idleTimeout) { log("Raid update failed: idle timeout"); lastFailure = Date.now() + 5000; callback(uid); } else if (result.maintenance) { log("Raid update failed: maintenance"); lastFailure = Date.now() + 15000; callback(uid); } else { handleNewRaids(result, uid); callback(uid); } }); } ; function updateItems(tabId, uid, callback) { var msg = { type: "doGameAjax", url: "/item/article_list" }; // log("Triggering status update"); doGameAjax(msg, tabId, uid, function (result) { if (!result) { log("Item update failed"); callback(uid); } else if (result.idleTimeout) { log("Item update failed: idle timeout"); lastFailure = Date.now() + 5000; callback(uid); } else if (result.maintenance) { log("Item update failed: maintenance"); lastFailure = Date.now() + 15000; callback(uid); } else { handleNewItems(result, uid); callback(uid); } }); } ; function injectStylesheetsIntoTab(sender) { var injectStylesheet = function (uri) { var cb = function () { }; chrome.tabs.insertCSS(sender.tab.id, { file: uri, runAt: "document_start" }, cb); }; // log(sender.tab.id, sender.url); var currentSettings = settings.toObject(); injectStylesheet("/content/viramate.css"); injectStylesheet("/css/watch-button.css"); if (currentSettings.condensedUI) injectStylesheet("/css/condensed-ui.css"); if ((navigator.userAgent.indexOf("Chrome/53.0") >= 0) || (navigator.userAgent.indexOf("Chrome/54.0") >= 0) || (navigator.userAgent.indexOf("Chrome/55.0") >= 0) || (navigator.userAgent.indexOf("Chrome/56.0") >= 0) || (navigator.userAgent.indexOf("Chrome/57.0") >= 0) || (navigator.userAgent.indexOf("Chrome/58.0") >= 0)) injectStylesheet("/css/chrome-53.css"); if (currentSettings.betterEnglishFont) { injectStylesheet("/content/lato-woff.css"); injectStylesheet("/css/lato.css"); } if (currentSettings.showGaugeOverlays) injectStylesheet("/content/gauge-overlays.css"); if (currentSettings.showQuickPanels) injectStylesheet("/css/quick-panels.css"); if (currentSettings.moveCoOpFooter) injectStylesheet("/css/move-coop-footer.css"); if (currentSettings.enableCoOpEnhancements) injectStylesheet("/css/coop.css"); if (currentSettings.smartSupports) injectStylesheet("/css/smart-supports.css"); if (currentSettings.singlePageStickers) injectStylesheet("/css/single-page-stickers.css"); if (currentSettings.keyboardShortcuts2) injectStylesheet("/css/keyboard.css"); if (currentSettings.permanentTurnCounter) injectStylesheet("/css/permanent-turn-counter.css"); if (currentSettings.disablePerCharacterOugiSkip) injectStylesheet("/css/per-character-ougi-skip.css"); if (currentSettings.tinySupportSummons) injectStylesheet("/css/tiny-support-summons.css"); if (currentSettings.popupPositionFix) injectStylesheet("/css/popup-position-fix.css"); // chrome.tabs.insertCSS(tabId, {code: "body{border:1px solid red}"}); } ; //# sourceMappingURL=background.js.map
変更されたテキスト
ファイルを開く
"use strict"; var settings = new Store("settings", { "preferFriendSummons": true, "preferNonFriendSummonsInFavorites": true, "preferLimitBrokenSummons": true, "preferHighLevelSummons": true, "notifyOnFullAP": false, "notifyOnFullBP": false, "showSkillCooldowns": true, "showDebuffTimers": true, "showBuffTimers": true, "monitorRaidDebuffs": true, "keyboardShortcuts": true, "showBookmarks": true, "preferredSummonElement": "", "submenuSize": 1.0, "bookmarksSize": 1.0, "bookmarksMenuSize": 1.0, "recentQuest": null, "showQuickPanels": true, "showGaugeOverlays": true, "openBookmarksOnClick": false, "fixJPFontRendering": true, "enableCoOpEnhancements": true, "dropdownFix": true, "disableMiddleRightClick": true, "statusPanel": true, "itemsPanel": true, "raidsPanel": false, "clockBrightness": 0.65, "oneClickQuickSummons": true, "bookmarksInactiveIcon": null, "bookmarksActiveIcon": null, "bookmarksIconPadding": 100, "horizontalBookmarks": false, "statusPanelBuffs": false, "statusPanelExpiringBuffs": true, "betterEnglishFont": false, "showItemWatchButtons": true, "showPartyNames": true, "filterEnemyTimers": true, "showPerformanceHud": false, "showNetworkHud": false, "showWeaponAttack": true, "showSkillActivationIndicator": true, "autofillBackupTweets": true, "moveCoOpFooter": true, "largeQuickPanels": false, "showPartyHelp": false, "keepSoundOnBlur": true, "stuckButtonWorkaround2": true, "showLastActionTimer": true, "smartSupports": true, "defaultToSmartSupports": false, "disablePhalanxSticker": true, "summonOrder": "{}", "password": "", "minimumPopupWait": 350, "maximumPopupWait": 1750, "focusQuickPanels": true, "newSkillSystem": true }); var failedUpdateMinimumDelay = 10 * 1000; var minimumUpdateDelay = 60 * 4 * 1000; var minimumRaidUpdateDelay = 30 * 1000; var minimumItemUpdateDelay = 60 * 30 * 1000; var minimumHaloUpdateDelay = 60 * 30 * 1000; var secretKeysByTabId = {}; var lastFailure = -1; var users = {}; var lastRaidCodes = {}; var isDead = true; var isShutdown = false; var lastLocation = null; var idleRedirectPending = false; var lastRedirectTarget = null; chrome.runtime.onMessage.addListener(onRuntimeMessage); chrome.alarms.onAlarm.addListener(onAlarm); chrome.runtime.onInstalled.addListener(function () { var dc = chrome.declarativeContent; dc.onPageChanged.removeRules(undefined, function () { dc.onPageChanged.addRules([ { conditions: [ new dc.PageStateMatcher({ pageUrl: { hostEquals: 'game.granbluefantasy.jp', schemes: ["https", "http"] }, }), new dc.PageStateMatcher({ pageUrl: { hostEquals: 'gbf.game.mbga.jp', schemes: ["https", "http"] }, }) ], actions: [new dc.ShowPageAction()] } ]); }); }); log("Started"); function getAdjustedSettings() { var result = settings.toObject(); result.allowDragSelect = false; // result.autoSkipToQuestResults = false; // result.oneClickQuickSummons = false; result.realtimeRaidList = false; // result.raidsPanel = false; // result.showQuickPanels = false; result.touchInputSupport = false; // Cygamesssssssssssssss result.autofillBackupTweets = false; // API changes broke this result.detailedUpgradePage = false; return result; } ; function log(...args) { args.unshift((new Date()).toLocaleString() + " |"); console.log.apply(console, args); } ; function getWatchedItems() { var result = JSON.parse(settings.get("watchedItems") || "[]"); if ((result.length === 1) && (result[0] === null)) result = []; var targetCounts = JSON.parse(settings.get("targetItemCounts") || "{}"); var itemGroups = JSON.parse(settings.get("itemGroups") || "{}"); return { items: result, counts: targetCounts, groups: itemGroups }; } ; function setItemWatchTarget(id, count) { var targetCounts = JSON.parse(settings.get("targetItemCounts") || "{}"); targetCounts[id] = count; 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) { var items = getWatchedItems().items; if (items.indexOf(id) >= 0) return items; if (!id) return items; items.push(id); settings.set("watchedItems", JSON.stringify(items)); return items; } ; function removeWatchedItem(id) { var items = getWatchedItems().items; var index = items.indexOf(id); if (index < 0) return items; items.splice(index, 1); settings.set("watchedItems", JSON.stringify(items)); return items; } ; function getFavedSummons() { var result = JSON.parse(settings.get("favedSummons") || "[]"); if ((result.length === 1) && (result[0] === null)) result = []; return result; } ; function addFavedSummon(id) { var items = getFavedSummons(); if (items.indexOf(id) >= 0) return items; if (!id) return items; items.push(id); settings.set("favedSummons", JSON.stringify(items)); return items; } ; function removeFavedSummon(id) { var items = getFavedSummons(); var index = items.indexOf(id); if (index < 0) return items; items.splice(index, 1); settings.set("favedSummons", JSON.stringify(items)); return items; } ; function getUserDict(uid) { var dict = users[uid]; if (!dict) dict = users[uid] = { lastUpdate: [] }; return dict; } ; function setUserData(uid, key, data) { var dict = getUserDict(uid); if (data) { dict.lastUpdate[key] = Date.now(); dict[key] = data; } else { dict.lastUpdate[key] = 0; dict[key] = null; } } ; function getUserData(uid, key) { var dict = getUserDict(uid); return dict[key]; } ; function getLastDataUpdate(uid, key) { var dict = getUserDict(uid); return dict.lastUpdate[key]; } ; function formatItemCounters(uid) { var itemCounters = getUserDict(uid).itemCounters; if (!itemCounters) return null; var counterDict = {}; for (var i = 0, l = itemCounters.length; i < l; i++) { var item = itemCounters[i]; counterDict[item.item_id] = item; } return counterDict; } ; function onRuntimeMessage(msg, sender, sendResponse) { if (chrome.runtime.lastError) log(chrome.runtime.lastError); var key = msg.type; var userDict; if (msg.uid) userDict = getUserDict(msg.uid); var tabId; if (sender.tab && sender.tab.id) tabId = sender.tab.id; else if (msg.tabId) tabId = msg.tabId; if (tabId <= 0) { log("Message has no tab id", key); return; } var senderUrl = sender.url || ""; if ((senderUrl.indexOf("granbluefantasy.jp") >= 0) || (senderUrl.indexOf("mbga.jp") >= 0)) { } else if ((senderUrl.indexOf("chrome-extension://") >= 0) && (senderUrl.indexOf("api.html") >= 0)) { switch (key) { case "apiRequest": case "getSettings": break; default: log("Rejected disallowed API request", msg); return; } } switch (key) { case "apiRequest": if (!settings.get("webAPI")) { log("Rejected API request because API is disabled", msg); sendResponse(null); return; } log("Processing API request", msg.request.type); switch (msg.request.type) { case "getUserIds": sendResponse(JSON.stringify(Object.keys(users))); break; case "getVersion": sendResponse(chrome.app.getDetails().version); break; case "tryJoinRaid": case "getCombatState": log("Preparing to send api request", msg); chrome.tabs.query({}, function (tabs) { if (tabs.length === 0) { log("Found no granblue tab"); sendResponse({ type: "result", error: "No granblue tab found" }); return; } for (var i = 0, l = tabs.length; i < l; i++) { var tab = tabs[i]; var tabUrl = tab.url; if (!tabUrl || ((tabUrl.indexOf("game.granbluefantasy.jp") < 0) && (tabUrl.indexOf("gbf.game.mbga.jp") < 0))) { continue; } log("Sending api request", msg); actuallySendMessage(msg, tab.id, function (result) { log("Got result for api request"); sendResponse(result); }); return; } log("Found no granblue tab"); sendResponse({ type: "result", error: "No granblue tab found" }); }); return true; default: sendResponse({ type: "result", error: "Unknown message" }); break; } break; case "getUserIds": sendResponse(JSON.stringify(Object.keys(users))); break; case "setPassword": settings.set("password", msg.password); break; case "pleaseInjectStylesheets": injectStylesheetsIntoTab(sender); break; case "heartbeat": isDead = false; break; case "cancelSuspend": if (userDict.isSuspended) log("Canceling idle/maintenance suspend for " + msg.uid); userDict.isSuspended = false; lastFailure = -1; break; case "isShutdown": sendResponse(isShutdown); break; case "setCompatibility": var newState = (msg.state === false); if (newState !== isShutdown) { log("Compatibility shutdown state set to", newState); isShutdown = newState; } break; case "openNewTab": chrome.tabs.create({ url: msg.url }); break; case "getVersion": sendResponse(chrome.app.getDetails().version); break; case "setRecentCoOpHost": settings.set("recentCoOpHost", msg.data); break; case "getRecentCoOpHost": sendResponse(settings.get("recentCoOpHost") || null); break; case "setCurrentEvent": if (msg.href !== settings.get("currentEvent")) log("Event changed to '" + msg.href + "'"); settings.set("currentEvent", msg.href); break; case "setCurrentGuildWar": if (msg.href !== settings.get("currentGuildWar")) log("Guild war changed to '" + msg.href + "'"); settings.set("currentGuildWar", msg.href); break; case "getCurrentEvent": sendResponse(settings.get("currentEvent") || null); break; case "getCurrentGuildWar": sendResponse(settings.get("currentGuildWar") || null); break; case "setRecentQuest": settings.set("recentQuest", msg.url); break; case "getRecentQuest": sendResponse(settings.get("recentQuest") || null); break; case "setLastLocation": // FIXME: Track per-tab lastLocation = msg.url; break; case "setIdleRedirectPending": // FIXME: Track per-tab idleRedirectPending = msg.state; if (msg.url) lastRedirectTarget = msg.url; break; case "getLastLocation": sendResponse(lastLocation || null); break; case "getIdleRedirectInfo": if (idleRedirectPending) { sendResponse({ pending: true, location: lastLocation, lastRedirectTarget: lastRedirectTarget }); } else { sendResponse({ pending: false }); } break; case "getSettings": sendResponse(getAdjustedSettings()); break; case "getRaidCode": sendResponse(lastRaidCodes[tabId]); break; case "updateRaidCode": lastRaidCodes[tabId] = msg.raidCode; break; case "getItemCounters": return maybeDoUpdate(userDict.nextCounterUpdate, minimumUpdateDelay, formatItemCounters, updateItemCounters, sendResponse, msg.force, tabId, msg.uid); case "updateItemCounters": userDict.nextCounterUpdate = Date.now() + minimumUpdateDelay; userDict.itemCounters = msg.counters; break; case "invalidateStatus": if (userDict.lastStatus) log("Status invalidated"); userDict.nextStatusUpdate = 0; userDict.lastStatus = null; break; case "getStatus": var getLastStatus = function (uid) { var s = getUserDict(uid).lastStatus; if (s) fixupStatus(s, uid); return s; }; if (msg.lazy) { var lastStatus = getLastStatus(msg.uid); if (lastStatus) { sendResponse(lastStatus); return; } else { // log("Lazy status update failed"); } } return maybeDoUpdate(userDict.nextStatusUpdate, minimumUpdateDelay, getLastStatus, updateStatus, sendResponse, msg.force, tabId, msg.uid); case "updateStatus": handleNewStatus(msg.status, msg.uid); break; case "invalidateBuffs": userDict.nextGuildBuffUpdate = 0; userDict.nextPersonalBuffUpdate = 0; userDict.guildBuffs = null; userDict.personalBuffs = null; log("Buffs invalidated"); break; case "updateGuildBuffs": userDict.lastGuildBuffUpdate = Date.now(); userDict.nextGuildBuffUpdate = Date.now() + minimumUpdateDelay; userDict.guildBuffs = msg.buffs; break; case "updatePersonalBuffs": userDict.lastPersonalBuffUpdate = Date.now(); userDict.nextPersonalBuffUpdate = Date.now() + minimumUpdateDelay; userDict.personalBuffs = msg.buffs; break; case "getNextRankRp": // if not force, don't actually update since this is a heavy call if (!msg.force) { if (userDict.nextNextRankRpUpdate) { sendResponse(userDict.nextRankRp); break; } sendResponse(null); break; } return maybeDoUpdate(userDict.nextNextRankRpUpdate, minimumUpdateDelay, function (uid) { return getUserDict(uid).nextRankRp; }, updateNextRankRp, sendResponse, msg.force, tabId, msg.uid); case "updateNextRankRp": userDict.nextNextRankRpUpdate = Date.now() + minimumUpdateDelay; userDict.nextRankRp = getRpToNextRank(msg.data); break; case "getRaids": return maybeDoUpdate(userDict.nextRaidUpdate, minimumRaidUpdateDelay, function (uid) { return getUserDict(uid).lastRaids; }, updateRaids, sendResponse, msg.force, tabId, msg.uid); case "invalidateRaids": if (msg.raids) { handleNewRaids(msg.raids, msg.uid); } else { if (userDict.lastRaids) log("Raids invalidated"); userDict.nextRaidUpdate = 0; userDict.lastRaids = null; } break; case "getItems": return maybeDoUpdate(userDict.nextItemUpdate, minimumItemUpdateDelay, function (uid) { return getUserDict(uid).lastItems; }, updateItems, sendResponse, msg.force, tabId, msg.uid); case "invalidateItems": if (msg.items) { handleNewItems(msg.items, msg.uid); } else { if (userDict.lastItems) log("Items invalidated"); userDict.nextItemUpdate = 0; userDict.lastItems = null; } break; case "getWatchedItems": sendResponse(getWatchedItems()); break; case "setItemWatchState": if (msg.state) sendResponse(addWatchedItem(msg.id)); else sendResponse(removeWatchedItem(msg.id)); break; case "setItemWatchTarget": setItemWatchTarget(msg.id, msg.count); break; case "setItemGroup": setItemGroup(msg.id, msg.group); break; case "getFavedSummons": sendResponse(getFavedSummons()); break; case "setSummonFaveState": if (msg.state) sendResponse(addFavedSummon(msg.id)); else sendResponse(removeFavedSummon(msg.id)); break; case "setSummonOrder": settings.set("summonOrder", msg.data); break; case "getIsDead": sendResponse(isDead); break; case "doGameAjax": doGameAjax(msg, tabId, msg.uid, sendResponse); // retain sendResponse return true; case "doGamePopup": case "doGameRedirect": actuallySendMessage(msg, tabId); break; case "getTabId": sendResponse(tabId); break; case "getUserIdAndTabId": msg.tabId = tabId; actuallySendMessage(msg, tabId, sendResponse); return true; case "getIsSuspended": sendResponse(!!userDict.isSuspended); return true; case "recordRewards": handleQuestRewards(msg); break; case "recordRaidInfo": handleRaidInfo(msg); break; case "registerSecretKey": secretKeysByTabId[tabId] = msg.key; break; case "actionStarted": userDict.lastActionStartedWhen = msg.when; userDict.lastActionId = msg.actionId; broadcastActionTimestamps(msg.uid, userDict); break; case "actionEnded": if (msg.succeeded) { userDict.lastSuccessfulActionStartedWhen = userDict.lastActionStartedWhen; } if (userDict.lastActionId === msg.actionId) { if (msg.succeeded) { userDict.lastSuccessfulActionId = userDict.lastActionId; } else { userDict.lastActionId = null; } } userDict.lastActionEndedWhen = msg.when; broadcastActionTimestamps(msg.uid, userDict); break; case "actionCompletedAnimation": // When an action's animation is complete, we disable // the timer since the lockout is definitely over if (msg.actionId === userDict.lastActionId) { userDict.lastActionStartedWhen = userDict.lastActionId = null; broadcastActionTimestamps(msg.uid, userDict); } break; case "getLastActionTimestamps": sendResponse(makeActionTimestamps(userDict)); break; default: log("Unknown message " + key); sendResponse({ error: true }); break; } } ; function broadcastActionTimestamps(uid, userDict) { var obj = makeActionTimestamps(userDict); var msg = { type: "actionTimestampsChanged", data: obj, uid: uid }; chrome.tabs.query( // FIXME: Can we narrow this to granblue tabs without the 'tabs' permission? {}, function (tabs) { if (!tabs) return; for (var i = 0; i < tabs.length; i++) { var tab = tabs[i]; chrome.tabs.sendMessage(tab.id, msg); if (chrome.runtime.lastError) log(chrome.runtime.lastError); } }); } ; function makeActionTimestamps(userDict) { return { actionId: userDict.lastActionId, successfulActionId: userDict.lastSuccessfulActionId, started: userDict.lastActionStartedWhen, successfulStarted: userDict.lastSuccessfulActionStartedWhen, ended: userDict.lastActionEndedWhen }; } ; function handleQuestRewards(msg) { var userDict = getUserDict(msg.uid); if (!userDict.raids) return; var urlFragment = msg.url.substr(msg.url.lastIndexOf("/") + 1); urlFragment = urlFragment.substr(0, urlFragment.indexOf("?")); var raidId = parseInt(urlFragment); var questId = userDict.raids[raidId]; } ; function handleRaidInfo(msg) { var userDict = getUserDict(msg.uid); if (!userDict.raids) userDict.raids = {}; userDict.raids[msg.raidId] = msg.questId; } ; function parseTimeInMinutes(text) { var parts = text.split(/[\D]+/); var result = 0; for (var i = 0, len = Math.min(parts.length, 2); i < len; i++) { if (parts[i].length === 0) { break; } result = result * 60 + parseInt(parts[i]); } return result; } ; function estimateValue(truncated, maximum, timeRemaining, elapsedTimeMs, minutesPerUnit) { if (truncated >= maximum) return truncated; // HACK: Add 59 seconds to the remaining time since they round down the number of minutes timeRemaining += 59 / 60; var durationFromFull = maximum * minutesPerUnit; timeRemaining = Math.max(0, timeRemaining - (elapsedTimeMs / 60000)); var fract = (timeRemaining / durationFromFull); fract = Math.max(0.0, Math.min(1.0, fract)); var estimatedValue = maximum * (1.0 - fract); return estimatedValue; } ; function fixupStatus(status, uid) { if (!status) return status; var userDict = getUserDict(uid); // FIXME var lastUpdate = userDict.lastStatusUpdate; status._lastUpdate = lastUpdate; status._now = Date.now(); 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_bp = estimateValue(status.bp, parseInt(status.max_battle_point), parseTimeInMinutes(status.battle_point_remain), age, 10); status.buffs = []; if (userDict.guildBuffs) { // FIXME age = (status._now - userDict.lastGuildBuffUpdate); for (var i = 0, l = userDict.guildBuffs.length; i < l; i++) { var gb = userDict.guildBuffs[i]; var timeRemaining = (parseTimeInMinutes(gb.time) * 60 * 1000) - age; if (timeRemaining <= 0) continue; status.buffs.push({ comment: gb.comment, timeRemaining: timeRemaining, imageUrl: "http://game-a.granbluefantasy.jp/assets_en/img/sp/assets/item/support/support_" + gb.image + "_" + gb.level + ".png" }); } } if (userDict.personalBuffs) { // FIXME age = (status._now - userDict.lastPersonalBuffUpdate); for (var k in userDict.personalBuffs) { if (!userDict.personalBuffs.hasOwnProperty(k)) continue; var pb = userDict.personalBuffs[k]; var timeRemaining = (parseTimeInMinutes(pb.remain_time) * 60 * 1000) - age; if (timeRemaining <= 0) 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_point_remain); var minutesUntilBpRefill = parseTimeInMinutes(status.battle_point_remain); if ((minutesUntilApRefill > 1) && settings.get("notifyOnFullAP")) chrome.alarms.create("apFull", { delayInMinutes: minutesUntilApRefill + 1 }); else chrome.alarms.clear("apFull"); if ((minutesUntilBpRefill > 1) && settings.get("notifyOnFullBP")) chrome.alarms.create("bpFull", { delayInMinutes: minutesUntilBpRefill + 1 }); else chrome.alarms.clear("bpFull"); // log("ap time", minutesUntilApRefill, "bp time", minutesUntilBpRefill); } ; function maybeDoUpdate(nextTime, minimumUpdateDelay, getValue, doUpdate, sendResponse, force, tabId, uid) { var shouldUpdate = false; var userDict = getUserDict(uid); var now = Date.now(); if (!nextTime) shouldUpdate = true; else if (now >= nextTime) shouldUpdate = true; else if (force) shouldUpdate = true; if ((now - lastFailure) < failedUpdateMinimumDelay) { log("Rate-limiting update due to failure"); shouldUpdate = false; } if (userDict.isSuspended && shouldUpdate) { log("Rejecting update request due to idle timeout"); sendResponse(null); return false; } if (!userDict.inFlightRequests) userDict.inFlightRequests = {}; var requestName = doUpdate.name; var ifr = userDict.inFlightRequests[requestName]; if (ifr) { var elapsed = now - ifr.startedWhen.getTime(); if (elapsed >= 30000) { log("Request of type '" + requestName + "' in-flight since " + ifr.startedWhen.toLocaleString() + "; that's too long, so we're going again anyway."); } else { log("Request of type '" + requestName + "' in-flight since " + ifr.startedWhen.toLocaleString() + "; waiting for it."); ifr.then(function (result) { log("In-flight '" + requestName + "' request completed with value", result); sendResponse(result); }); return true; } } if (shouldUpdate) { var pr = new PromiseResolver(); pr.promise.startedWhen = new Date(); userDict.inFlightRequests[requestName] = pr.promise; doUpdate(tabId, uid, function (_uid) { var response = getValue(_uid); delete userDict.inFlightRequests[requestName]; sendResponse(response); pr.resolve(response); }); return true; } else { sendResponse(getValue(uid)); return false; } } ; function doGameAjax(msg, tabId, uid, callback) { /* if (Math.random() < 0.33) { console.log("Injecting error for request", msg); callback(null, "fake error"); return; } */ actuallySendMessage(msg, tabId, function (bundle) { if (!bundle) { callback({ error: true }, "no response"); return; } var response = bundle[0]; var error = bundle[1]; var url = bundle[2]; if (chrome.runtime.lastError) { isDead = true; log(chrome.runtime.lastError); } else { isDead = false; } if (error) { if (error.indexOf("-- abort") >= 0) { log("xhr aborted", url); } else { log("Error from server", error, url); lastFailure = Date.now(); } } if (typeof (response) === "string") { try { response = JSON.parse(response); } catch (exc) { } } if (isIdleTimeoutRedirect(response)) { handleIdleTimeout(uid); callback({ idleTimeout: true }, error); } else if (isMaintenanceRedirect(response)) { handleMaintenance(uid); callback({ maintenance: true }, error); } else { callback(response, error); } }); } ; function isIdleTimeoutRedirect(jsonBody) { if (jsonBody && jsonBody.redirect && (jsonBody.redirect.indexOf("top") >= 0)) return true; return false; } ; function isMaintenanceRedirect(jsonBody) { if (jsonBody && jsonBody.redirect && (jsonBody.redirect.indexOf("maintenance") >= 0)) return true; return false; } ; function handleIdleTimeout(uid) { log("Idle timeout"); getUserDict(uid).isSuspended = true; lastFailure = Date.now() + 5000; } ; function handleMaintenance(uid) { log("Maintenance"); getUserDict(uid).isSuspended = true; lastFailure = Date.now() + 5000; } ; function updateStatus(tabId, uid, callback) { var msg = { type: "doGameAjax", url: "/user/status" }; // log("Triggering status update"); doGameAjax(msg, tabId, uid, function (result) { getUserDict(uid).nextStatusUpdate = Date.now() + minimumUpdateDelay; if (!result) { log("Status update failed"); callback(uid); } else if (result.idleTimeout) { log("Status update failed: idle timeout"); callback(uid); } else if (result.maintenance) { log("Status update failed: maintenance"); callback(uid); } else { getUserDict(uid).lastStatusUpdate = Date.now(); getUserDict(uid).lastStatus = result.status; // log("Status updated -> ", lastStatus); callback(uid); } }); } ; function getRpToNextRank(data) { data = decodeURIComponent(data); /* Data is of the following form: [garbage] <div class="txt-next-value">Next ###Rankポイント</div> OR (depending on language) <div class="txt-next-value">Next lvl in ### Rank Points</div> [garbage] */ var result = parseInt(data.replace(/^[^]*txt-next-value[\D]+([\d]+)[^]*$/, "$1")); // in case of something unexpected being passed in if (isNaN(result)) { return "?"; } return result; } function updateNextRankRp(tabId, uid, callback) { var msg = { type: "doGameAjax", url: "/profile/content/index/" + uid }; doGameAjax(msg, tabId, uid, function (result) { if (!result) { log("RP to next rank update failed"); callback(uid); } else if (result.idleTimeout) { log("RP to next rank update failed: idle timeout"); callback(uid); } else { getUserDict(uid).lastNextRankRpUpdate = Date.now(); getUserDict(uid).nextNextRankRpUpdate = Date.now() + minimumUpdateDelay; getUserDict(uid).nextRankRp = getRpToNextRank(result.data); callback(uid); } }); } ; function getStrikeTime(data) { data = decodeURIComponent(data); /* Data is of the following form: [garbage] <div class="txt-next-value">Next ###Rankポイント</div> OR (depending on language) <div class="txt-next-value">Next lvl in ### Rank Points</div> [garbage] */ /* var strikeTimes = []; var re = /\<div class="prt\-assault\-guildinfo"\>.*?\<div class="prt\-item\-status"\>(.*?)\<\/div/gms var m; while (m = re.exec(data)) { strikeTimes.push(m[1]); } log(strikeTimes); return strikeTimes; */ } function updateStrikeTime(tabId, uid, callback) { var msg = { type: "doGameAjax", url: "/guild_main/content/index/" }; doGameAjax(msg, tabId, uid, function (result) { if (!result) { log("Strike time update failed"); callback(uid); } else if (result.idleTimeout) { log("Strike time update failed: idle timeout"); callback(uid); } else { getUserDict(uid).lastStrikeTimeUpdate = Date.now(); getUserDict(uid).nextStrikeTimeUpdate = Date.now() + minimumUpdateDelay; getUserDict(uid).strikeTime = getStrikeTime(result.data); callback(uid); } }); } ; function updateItemCounters(tabId, uid, callback) { var msg = { type: "doGameAjax", url: "/item/normal_item_list/1" }; // log("Triggering counter update"); doGameAjax(msg, tabId, uid, function (result) { if (!result) { log("Counter update failed"); getUserDict(uid).nextCounterUpdate = Date.now() + minimumUpdateDelay; callback(uid); } else if (result.idleTimeout) { log("Counter update failed: idle timeout"); getUserDict(uid).nextCounterUpdate = Date.now() + minimumUpdateDelay; callback(uid); } else { getUserDict(uid).lastCounterUpdate = Date.now(); getUserDict(uid).nextCounterUpdate = Date.now() + minimumItemUpdateDelay; getUserDict(uid).itemCounters = result; // log("Counters updated -> ", itemCounters); callback(uid); } }); } ; function onAlarm(alarm) { log("Alarm '" + alarm.name + "' fired"); if (alarm.name.indexOf("Full") >= 0) { var resourceName = alarm.name.replace("Full", "").toUpperCase(); chrome.notifications.create({ type: "basic", iconUrl: "../../icons/active-256.png", title: resourceName + " full", message: "Your Granblue Fantasy " + resourceName + " is full." }); return; } } ; function actuallySendMessage(message, tabId, callback) { // *$!@)%KAKLMRSJ chrome garbage APIs if (tabId) { chrome.tabs.sendMessage(tabId, message, callback); } else { log("No granblue tab found as target for message", message, tabId); } } ; function handleNewRaids(raids, uid) { if (!raids) { log("Failed raid update"); return; } getUserDict(uid).lastRaids = raids; getUserDict(uid).lastRaidUpdate = Date.now(); getUserDict(uid).nextRaidUpdate = Date.now() + minimumRaidUpdateDelay; // log("ap time", minutesUntilApRefill, "bp time", minutesUntilBpRefill); } ; function handleNewItems(items, uid) { if (!items) { log("Failed item update"); return; } getUserDict(uid).lastItems = items; getUserDict(uid).lastItemUpdate = Date.now(); getUserDict(uid).nextItemUpdate = Date.now() + minimumItemUpdateDelay; // log("ap time", minutesUntilApRefill, "bp time", minutesUntilBpRefill); } ; function updateRaids(tabId, uid, callback) { var msg = { type: "doGameAjax", url: "/quest/assist_list/0" }; // log("Triggering status update"); doGameAjax(msg, tabId, uid, function (result) { if (!result) { log("Raid update failed"); callback(uid); } else if (result.idleTimeout) { log("Raid update failed: idle timeout"); lastFailure = Date.now() + 5000; callback(uid); } else if (result.maintenance) { log("Raid update failed: maintenance"); lastFailure = Date.now() + 15000; callback(uid); } else { handleNewRaids(result, uid); callback(uid); } }); } ; function updateItems(tabId, uid, callback) { var msg = { type: "doGameAjax", url: "/item/article_list" }; // log("Triggering status update"); doGameAjax(msg, tabId, uid, function (result) { if (!result) { log("Item update failed"); callback(uid); } else if (result.idleTimeout) { log("Item update failed: idle timeout"); lastFailure = Date.now() + 5000; callback(uid); } else if (result.maintenance) { log("Item update failed: maintenance"); lastFailure = Date.now() + 15000; callback(uid); } else { handleNewItems(result, uid); callback(uid); } }); } ; function injectStylesheetsIntoTab(sender) { var injectStylesheet = function (uri) { var cb = function () { }; chrome.tabs.insertCSS(sender.tab.id, { file: uri, runAt: "document_start" }, cb); }; // log(sender.tab.id, sender.url); var currentSettings = settings.toObject(); injectStylesheet("/content/viramate.css"); injectStylesheet("/css/watch-button.css"); if (currentSettings.condensedUI) injectStylesheet("/css/condensed-ui.css"); if ((navigator.userAgent.indexOf("Chrome/53.0") >= 0) || (navigator.userAgent.indexOf("Chrome/54.0") >= 0) || (navigator.userAgent.indexOf("Chrome/55.0") >= 0) || (navigator.userAgent.indexOf("Chrome/56.0") >= 0) || (navigator.userAgent.indexOf("Chrome/57.0") >= 0) || (navigator.userAgent.indexOf("Chrome/58.0") >= 0)) injectStylesheet("/css/chrome-53.css"); if (currentSettings.betterEnglishFont) { injectStylesheet("/content/lato-woff.css"); injectStylesheet("/css/lato.css"); } if (currentSettings.showGaugeOverlays) injectStylesheet("/content/gauge-overlays.css"); if (currentSettings.showQuickPanels) injectStylesheet("/css/quick-panels.css"); if (currentSettings.moveCoOpFooter) injectStylesheet("/css/move-coop-footer.css"); if (currentSettings.enableCoOpEnhancements) injectStylesheet("/css/coop.css"); if (currentSettings.smartSupports) injectStylesheet("/css/smart-supports.css"); if (currentSettings.singlePageStickers) injectStylesheet("/css/single-page-stickers.css"); if (currentSettings.keyboardShortcuts2) injectStylesheet("/css/keyboard.css"); if (currentSettings.permanentTurnCounter) injectStylesheet("/css/permanent-turn-counter.css"); if (currentSettings.disablePerCharacterOugiSkip) injectStylesheet("/css/per-character-ougi-skip.css"); if (currentSettings.tinySupportSummons) injectStylesheet("/css/tiny-support-summons.css"); if (currentSettings.popupPositionFix) injectStylesheet("/css/popup-position-fix.css"); // chrome.tabs.insertCSS(tabId, {code: "body{border:1px solid red}"}); } ; //# sourceMappingURL=background.js.map
違いを見つける