返回提交历史
Modified
src/controllers/api/inboxController.ts
+9
-17
Modified
src/controllers/api/loginController.ts
+8
-9
Modified
src/models/inboxModel.ts
+15
-4
Modified
src/services/inboxService.ts
+18
-4
Modified
src/services/loginService.ts
+5
-0
Modified
static/webui/script.js
+2
-2
XFEstudio/SpaceNinjaServer
feat: minBuildVersion for inbox messages (#3733)
Also moved the responsibility of filtering out old messages for the delta request to MongoDB. Closes #3729 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/3733 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
0f74aacf
代码差异
6 个文件
+57
-36
@@ -6,10 +6,11 @@ import {
6
6
deleteAllMessagesReadNonCin,
7
7
deleteMessageRead,
8
8
exportInboxMessage,
9
getAllMessagesSorted,
9
getMessagesSorted,
10
10
type IMessageCreationTemplate
11
11
} from "../../services/inboxService.ts";
12
12
import {
13
buildVersionToInt,
13
14
getAccountForRequest,
14
15
getAccountFromSuffixedName,
15
16
getSuffixedName,
@@ -37,6 +38,7 @@ export const inboxController: RequestHandler = async (req, res) => {
37
38
const { deleteId, lastMessage: latestClientMessageId, messageId } = req.query;
38
39
39
40
const account = await getAccountForRequest(req);
41
const buildLabel = "ignoreBuildLabel" in req.query ? undefined : account.BuildLabel;
40
42
41
43
if (deleteId) {
42
44
if (deleteId === "DeleteAllRead") {
@@ -124,30 +126,19 @@ export const inboxController: RequestHandler = async (req, res) => {
124
126
res.json({ InventoryChanges: inventoryChanges });
125
127
} else if (latestClientMessageId) {
126
128
await createNewEventMessages(account);
127
const messages = await Inbox.find({ ownerId: account._id }).sort({ date: 1 });
128
129
const latestClientMessage = messages.find(m => m._id.toString() === parseOid(latestClientMessageId as string));
130
131
if (!latestClientMessage) {
132
logger.debug(`this should only happen after DeleteAllRead `);
133
res.json({
134
Inbox: messages.map(x => exportInboxMessage(x, account.BuildLabel)) satisfies IMessageClient[]
135
});
136
return;
137
}
138
const newMessages = messages.filter(m => m.date > latestClientMessage.date);
129
const newMessages = await getMessagesSorted(account._id, buildLabel, parseOid(latestClientMessageId as string));
139
130
140
131
if (newMessages.length === 0) {
141
132
res.send("no-new");
142
133
return;
143
134
}
144
135
145
res.json({ Inbox: newMessages.map(x => exportInboxMessage(x, account.BuildLabel)) satisfies IMessageClient[] });
136
res.json({ Inbox: newMessages.map(x => exportInboxMessage(x, buildLabel)) satisfies IMessageClient[] });
146
137
} else {
147
138
//newly created event messages must be newer than account.LatestEventMessageDate
148
139
await createNewEventMessages(account);
149
const messages = await getAllMessagesSorted(account._id);
150
const inbox = messages.map(x => exportInboxMessage(x, account.BuildLabel));
140
const messages = await getMessagesSorted(account._id, buildLabel);
141
const inbox = messages.map(x => exportInboxMessage(x, buildLabel));
151
142
res.json({ Inbox: inbox satisfies IMessageClient[] });
152
143
}
153
144
};
@@ -289,7 +280,8 @@ const createNewEventMessages = async (account: TAccountDocument): Promise<void>
289
280
transmission: "/Lotus/Sounds/Dialog/Shadowgrapher/Vendor/DSGInbox0011AspirantZorba",
290
281
startDate: new Date(),
291
282
QuestReq: "/Lotus/Types/Keys/PriestFrameQuest/PriestQuestKeyChain",
292
CrossPlatform: true
283
CrossPlatform: true,
284
minBuildVersion: buildVersionToInt(gameToBuildVersion["42.0.0"])
293
285
});
294
286
}
295
287
@@ -4,7 +4,13 @@ import { config, getReflexiveAddress } from "../../services/configService.ts";
4
4
import { buildConfig } from "../../services/buildConfigService.ts";
5
5
6
6
import { Account } from "../../models/loginModel.ts";
7
import { createAccount, createNonce, getUsernameFromEmail, isCorrectPassword } from "../../services/loginService.ts";
7
import {
8
buildVersionToInt,
9
createAccount,
10
createNonce,
11
getUsernameFromEmail,
12
isCorrectPassword
13
} from "../../services/loginService.ts";
8
14
import {
9
15
Platform,
10
16
type IDatabaseAccountJson,
@@ -203,14 +209,7 @@ const createLoginResponse = (request: Request, account: IDatabaseAccountJson, bu
203
209
resp.HUB = `${myUrlBase}/api/`;
204
210
205
211
// The MatchmakingBuildId is a 64-bit integer represented as a decimal string. On live, the value is seemingly random per build, but really any value that is different across builds should work.
206
const [year, month, day, hour, minute] = buildLabel.split(".").map(x => parseInt(x));
207
resp.MatchmakingBuildId = (
208
year * 1_00_00_00_00 +
209
month * 1_00_00_00 +
210
day * 1_00_00 +
211
hour * 1_00 +
212
minute
213
).toString();
212
resp.MatchmakingBuildId = buildVersionToInt(buildLabel).toString();
214
213
}
215
214
if (version_compare(buildLabel, gameToBuildVersion["33.0.0"]) >= 0) {
216
215
if (version_compare(buildLabel, gameToBuildVersion["40.0.0"]) >= 0) {
@@ -6,7 +6,15 @@ import type { IMongoDateWithLegacySupport, IOid, IOidWithLegacySupport, ITypeCou
6
6
7
7
export interface IMessageClient extends Omit<
8
8
IMessageDatabase,
9
"_id" | "globaUpgradeId" | "date" | "startDate" | "endDate" | "ownerId" | "attVisualOnly" | "expiry"
9
| "_id"
10
| "globaUpgradeId"
11
| "date"
12
| "startDate"
13
| "endDate"
14
| "ownerId"
15
| "attVisualOnly"
16
| "expiry"
17
| "minBuildVersion"
10
18
> {
11
19
_id?: IOid;
12
20
globaUpgradeId?: IOidWithLegacySupport; // [sic]
@@ -17,10 +25,11 @@ export interface IMessageClient extends Omit<
17
25
}
18
26
19
27
export interface IMessageDatabase extends IMessage {
20
ownerId: Types.ObjectId;
28
ownerId: Types.ObjectId; // SNS-specific
21
29
globaUpgradeId?: Types.ObjectId; // [sic]
22
30
date: Date; //created at
23
attVisualOnly?: boolean;
31
attVisualOnly?: boolean; // SNS-specific
32
minBuildVersion?: number; // SNS-specific
24
33
_id: Types.ObjectId;
25
34
}
26
35
@@ -143,7 +152,8 @@ const messageSchema = new Schema<IMessageDatabase>(
143
152
acceptAction: String,
144
153
declineAction: String,
145
154
hasAccountAction: Boolean,
146
RegularCredits: Number
155
RegularCredits: Number,
156
minBuildVersion: Number
147
157
},
148
158
{ id: false }
149
159
);
@@ -160,6 +170,7 @@ messageSchema.set("toJSON", {
160
170
delete returnedObject.ownerId;
161
171
delete returnedObject.attVisualOnly;
162
172
delete returnedObject.expiry;
173
delete returnedObject.minBuildVersion;
163
174
164
175
// oid & date conversions done in inboxService's exportInboxMessage
165
176
}
@@ -1,11 +1,25 @@
1
1
import { toMongoDate2, toOid2 } from "../helpers/inventoryHelpers.ts";
2
2
import type { IMessageClient, IMessageDatabase, TMessageDocument } from "../models/inboxModel.ts";
3
3
import { Inbox } from "../models/inboxModel.ts";
4
import type { Types } from "mongoose";
4
import type { FilterQuery, Types } from "mongoose";
5
import { buildVersionToInt } from "./loginService.ts";
5
6
6
export const getAllMessagesSorted = async (accountId: string | Types.ObjectId): Promise<TMessageDocument[]> => {
7
const inbox = await Inbox.find({ ownerId: accountId }).sort({ date: -1 });
8
return inbox;
7
export const getMessagesSorted = async (
8
accountId: string | Types.ObjectId,
9
buildLabel: string | undefined,
10
afterId?: string | Types.ObjectId
11
): Promise<TMessageDocument[]> => {
12
const query: FilterQuery<IMessageDatabase> = { ownerId: accountId };
13
if (buildLabel) {
14
query.$or = [
15
{ minBuildVersion: { $exists: false } },
16
{ minBuildVersion: { $lte: buildVersionToInt(buildLabel) } }
17
];
18
}
19
if (afterId) {
20
query._id = { $gt: afterId };
21
}
22
return await Inbox.find(query).sort({ date: -1 });
9
23
};
10
24
11
25
export const deleteMessageRead = async (messageId: string | Types.ObjectId): Promise<void> => {
@@ -159,3 +159,8 @@ export const stripUnicodeSuffix = (name: string): string => {
159
159
}
160
160
return name;
161
161
};
162
163
export const buildVersionToInt = (buildVersion: string): number => {
164
const [year, month, day, hour, minute] = buildVersion.split(".").map(x => parseInt(x));
165
return year * 1_00_00_00_00 + month * 1_00_00_00 + day * 1_00_00 + hour * 1_00 + minute;
166
};
@@ -5013,11 +5013,11 @@ document.querySelectorAll("#sidebar .nav-link").forEach(function (elm) {
5013
5013
5014
5014
async function markAllAsRead() {
5015
5015
await revalidateAuthz();
5016
const { Inbox } = await fetch("/api/inbox.php?" + window.authz).then(x => x.json());
5016
const { Inbox } = await fetch("/api/inbox.php?" + window.authz + "&ignoreBuildLabel=1").then(x => x.json());
5017
5017
let any = false;
5018
5018
for (const msg of Inbox) {
5019
5019
if (!msg.r) {
5020
await fetch("/api/inbox.php?" + window.authz + "&messageId=" + msg.messageId.$oid);
5020
await fetch("/api/inbox.php?" + window.authz + "&ignoreBuildLabel=1&messageId=" + msg.messageId.$oid);
5021
5021
any = true;
5022
5022
}
5023
5023
}