feat: 이미 읽은 메시지를 DB에서 처리

This commit is contained in:
2023-03-25 02:09:23 +09:00
parent 5294aefbbd
commit 9206b74500
6 changed files with 115 additions and 21 deletions
@@ -6,8 +6,10 @@ use sammo\Session;
use DateTimeInterface;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\GeneralStorKey;
use sammo\Enums\MessageType;
use sammo\Json;
use sammo\KVStorage;
use sammo\Message;
use sammo\TimeUtil;
use sammo\Util;
@@ -140,9 +142,19 @@ class GetRecentMessage extends \sammo\BaseAPI
array_pop($result[$lastType]);
}
$generalStor = KVStorage::getStorage($db, "general_{$generalID}");
[$latestReadDiplomacyMsg, $latestReadPrivateMsg] = $generalStor->getValuesAsArray([
GeneralStorKey::latestReadDiplomacyMsg,
GeneralStorKey::latestReadPrivateMsg
]);
$result['sequence'] = $nextSequence;
$result['nationID'] = $nationID;
$result['generalName'] = $generalName;
$result['latestRead'] = [
'diplomacy' => $latestReadDiplomacyMsg ?? 0,
'private' => $latestReadPrivateMsg ?? 0,
];
return $result;
}
@@ -0,0 +1,52 @@
<?php
namespace sammo\API\Message;
use sammo\DB;
use sammo\Enums\APIRecoveryType;
use sammo\Enums\GeneralStorKey;
use sammo\Enums\MessageType;
use sammo\KVStorage;
use sammo\Session;
use sammo\Validator;
class ReadLatestMessage extends \sammo\BaseAPI
{
public function validateArgs(): ?string
{
//type이 개인 메시지 혹은 외교 메시지여야함
$v = new Validator($this->args);
$v->rule('required', ['type', 'msgID'])
->rule('in', 'type', [MessageType::private->value, MessageType::diplomacy->value])
->rule('int', 'msgID');
if (!$v->validate()) {
return $v->errorStr();
}
return null;
}
public function getRequiredSessionMode(): int
{
return static::REQ_GAME_LOGIN | static::REQ_READ_ONLY;
}
public function launch(Session $session, ?\DateTimeInterface $modifiedSince, ?string $reqEtag): null | string | array | APIRecoveryType
{
$db = DB::db();
$generalID = $session->generalID;
$generalStor = KVStorage::getStorage($db, "general_{$generalID}");
$type = MessageType::from($this->args['type']);
$msgID = $this->args['msgID'];
$storKey = GeneralStorKey::latestReadPrivateMsg;
if($type == MessageType::diplomacy){
$storKey = GeneralStorKey::latestReadDiplomacyMsg;
}
$oldValue = $generalStor->getValue($storKey);
if($oldValue === null || $oldValue < $msgID){
$generalStor->setValue($storKey, $msgID);
}
return null;
}
}
+7
View File
@@ -0,0 +1,7 @@
<?php
namespace sammo\Enums;
enum GeneralStorKey: string{
case latestReadPrivateMsg = 'latestReadPrivateMsg';
case latestReadDiplomacyMsg = 'latestReadDiplomacyMsg';
}
+10 -6
View File
@@ -29,7 +29,7 @@ import type {
GetFrontInfoResponse,
GetHistoryResponse,
GetMenuResponse,
GetRecentRecordResponse,
GetRecentRecordResponse,
} from "./defs/API/Global";
import type { CachedMapResult, CommandTableResponse, GeneralListResponse, ItemTypeKey, MapResult } from "./defs";
import type { VoteDetailResult, VoteListResult } from "./defs/API/Vote";
@@ -71,12 +71,12 @@ const apiRealPath = {
amount: number;
}>,
GetUniqueItemAuctionDetail: GET as APICallT<{
auctionID: number;
auctionID: number;
}, UniqueItemAuctionDetail>,
GetUniqueItemAuctionList: GET as APICallT<undefined, UniqueItemAuctionList>,
OpenUniqueAuction: POST as APICallT<{
itemID: string,
amount: number,
itemID: string,
amount: number,
}, OpenAuctionResponse>,
},
Betting: {
@@ -199,7 +199,11 @@ const apiRealPath = {
SendMessage: POST as APICallT<{
mailbox: number;
text: string;
}, ValidResponse & {msgID: number, msgType: MsgType}>
}, ValidResponse & { msgID: number, msgType: MsgType }>,
ReadLatestMessage: PATCH as APICallT<{
type: 'diplomacy' | 'private';
msgID: number;
}>
},
Misc: {
UploadImage: POST as APICallT<
@@ -273,7 +277,7 @@ const apiRealPath = {
troopID: number;
troopName: string;
}>,
GetNationInfo: GET as APICallT<{full?: boolean}, NationInfoResponse>,
GetNationInfo: GET as APICallT<{ full?: boolean }, NationInfoResponse>,
},
Troop: {
NewTroop: POST as APICallT<{
+30 -15
View File
@@ -255,21 +255,8 @@ const messageIndexedList: Record<MsgType, Ref<MsgItem[]>> = {
diplomacy: messageDiplomacy,
};
function generateLatestMsgState(msgType: MsgType) {
const storageKey = `state.${serverID}.latestReadMsg.${msgType}`;
const latestReadMsgID = parseInt(localStorage.getItem(storageKey) ?? "0");
const obj = ref<[string | undefined, number, number]>([undefined, latestReadMsgID, latestReadMsgID]);
watch(obj, ([, newMsgID], [, oldMsgID]) => {
if (newMsgID == oldMsgID) {
return;
}
localStorage.setItem(storageKey, newMsgID.toString());
});
return obj;
}
const latestPrivateMsgToastInfo = generateLatestMsgState("private");
const latestDiplomacyMsgToastInfo = generateLatestMsgState("diplomacy");
const latestPrivateMsgToastInfo = ref<[string | undefined, number, number]>([undefined, 0, 0]);
const latestDiplomacyMsgToastInfo = ref<[string | undefined, number, number]>([undefined, 0, 0]);
function readLatestMsg(msgType: MsgType) {
const targetMap = {
@@ -288,6 +275,13 @@ function readLatestMsg(msgType: MsgType) {
if (toastID) {
toasts.remove(toastID);
}
if(msgType == "private" || msgType == "diplomacy"){
void SammoAPI.Message.ReadLatestMessage({
type: msgType,
msgID: lastestReceivedID,
});
}
target.value = [undefined, lastestReceivedID, lastestReceivedID];
}
@@ -403,6 +397,27 @@ function updateMsgResponse(response: MsgResponse) {
return;
}
if(response.latestRead){
const newDiplomacyIdx = response.latestRead.diplomacy;
const [diplomacyToastID, diplomacyLatestMsgID] = latestDiplomacyMsgToastInfo.value;
if(diplomacyLatestMsgID < newDiplomacyIdx){
if(diplomacyToastID){
toasts.remove(diplomacyToastID);
}
latestDiplomacyMsgToastInfo.value = [undefined, newDiplomacyIdx, newDiplomacyIdx];
}
const newPrivateIdx = response.latestRead.private;
const [privateToastID, privateLatestMsgID] = latestPrivateMsgToastInfo.value;
if(privateLatestMsgID < newPrivateIdx){
if(privateToastID){
toasts.remove(privateToastID);
}
latestPrivateMsgToastInfo.value = [undefined, newPrivateIdx, newPrivateIdx];
}
}
lastSequence.value = Math.max(lastSequence.value, response.sequence);
for (const msgType of Object.keys(messageIndexedList) as (keyof typeof messageIndexedList)[]) {
+4
View File
@@ -58,6 +58,10 @@ export type MsgResponse = {
nationID: number;
generalName: string;
sequence: number;
latestRead?: {
private: number;
diplomacy: number;
}
};
export type MailboxItem = {