Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
215 changes: 143 additions & 72 deletions src/messaging/unread.js
Original file line number Diff line number Diff line change
@@ -1,74 +1,145 @@
'use strict';

const db = require('../database');
const io = require('../socket.io');

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable import/no-import-module-exports */
var db = require("../database");
var io = require("../socket.io");
module.exports = function (Messaging) {
Messaging.getUnreadCount = async (uid) => {
if (!(parseInt(uid, 10) > 0)) {
return 0;
}

return await db.sortedSetCard(`uid:${uid}:chat:rooms:unread`);
};

Messaging.pushUnreadCount = async (uids, data = null) => {
if (!Array.isArray(uids)) {
uids = [uids];
}
uids = uids.filter(uid => parseInt(uid, 10) > 0);
if (!uids.length) {
return;
}
uids.forEach((uid) => {
io.in(`uid_${uid}`).emit('event:unread.updateChatCount', data);
});
};

Messaging.markRead = async (uid, roomId) => {
await Promise.all([
db.sortedSetRemove(`uid:${uid}:chat:rooms:unread`, roomId),
db.setObjectField(`uid:${uid}:chat:rooms:read`, roomId, Date.now()),
]);
};

Messaging.hasRead = async (uids, roomId) => {
if (!uids.length) {
return [];
}
const roomData = await Messaging.getRoomData(roomId);
if (!roomData) {
return uids.map(() => false);
}
if (roomData.public) {
const [userTimestamps, mids] = await Promise.all([
db.getObjectsFields(uids.map(uid => `uid:${uid}:chat:rooms:read`), [roomId]),
db.getSortedSetRevRangeWithScores(`chat:room:${roomId}:mids`, 0, 0),
]);
const lastMsgTimestamp = mids[0] ? mids[0].score : 0;
return uids.map(
(uid, index) => !userTimestamps[index] ||
!userTimestamps[index][roomId] ||
parseInt(userTimestamps[index][roomId], 10) > lastMsgTimestamp
);
}
const isMembers = await db.isMemberOfSortedSets(
uids.map(uid => `uid:${uid}:chat:rooms:unread`),
roomId
);
return uids.map((uid, index) => !isMembers[index]);
};

Messaging.markAllRead = async (uid) => {
await db.delete(`uid:${uid}:chat:rooms:unread`);
};

Messaging.markUnread = async (uids, roomId) => {
const exists = await Messaging.roomExists(roomId);
if (!exists) {
return;
}
const keys = uids.map(uid => `uid:${uid}:chat:rooms:unread`);
await db.sortedSetsAdd(keys, Date.now(), roomId);
};
var _this = this;
Messaging.getUnreadCount = function (uid) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(parseInt(uid, 10) > 0)) {
return [2 /*return*/, 0];
}
return [4 /*yield*/, db.sortedSetCard("uid:".concat(uid, ":chat:rooms:unread"))];
case 1:
// eslint-disable-next-line max-len
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return
return [2 /*return*/, _a.sent()];
}
});
}); };
Messaging.pushUnreadCount = function (uids, data) {
if (data === void 0) { data = null; }
if (!Array.isArray(uids)) {
uids = [uids];
}
uids = uids.filter(function (uid) { return parseInt(uid, 10) > 0; });
if (!uids.length) {
return;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
uids.forEach(function (uid) { io.in("uid_".concat(uid)).emit('event:unread.updateChatCount', data); });
};
Messaging.markRead = function (uid, roomId) { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
return [4 /*yield*/, Promise.all([db.sortedSetRemove("uid:".concat(uid, ":chat:rooms:unread"), roomId), db.setObjectField("uid:".concat(uid, ":chat:rooms:read"), roomId, Date.now()),
])];
case 1:
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
_a.sent();
return [2 /*return*/];
}
});
}); };
Messaging.hasRead = function (uids, roomId) { return __awaiter(_this, void 0, void 0, function () {
var roomData, _a, userTimestamps_1, mids, lastMsgTimestamp_1, isMembers;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!uids.length) {
return [2 /*return*/, []];
}
return [4 /*yield*/, Messaging.getRoomData(roomId)];
case 1:
roomData = _b.sent();
if (!roomData) {
return [2 /*return*/, uids.map(function () { return false; })];
}
if (!roomData.public) return [3 /*break*/, 3];
return [4 /*yield*/, Promise.all([db.getObjectsFields(uids.map(function (uid) { return "uid:".concat(uid, ":chat:rooms:read"); }), [roomId]), db.getSortedSetRevRangeWithScores("chat:room:".concat(roomId, ":mids"), 0, 0)])];
case 2:
_a = _b.sent(), userTimestamps_1 = _a[0], mids = _a[1];
lastMsgTimestamp_1 = (mids.length > 0 && mids[0].score) ? mids[0].score : 0;
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
return [2 /*return*/, uids.map(function (uid, index) { return !userTimestamps_1[index] || !userTimestamps_1[index][roomId] ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
parseInt(userTimestamps_1[index][roomId], 10) > lastMsgTimestamp_1; })];
case 3: return [4 /*yield*/, db.isMemberOfSortedSets(uids.map(function (uid) { return "uid:".concat(uid, ":chat:rooms:unread"); }), roomId)];
case 4:
isMembers = _b.sent();
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
return [2 /*return*/, uids.map(function (uid, index) { return !isMembers[index]; })];
}
});
}); };
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
Messaging.markAllRead = function (uid) { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, db.delete("uid:".concat(uid, ":chat:rooms:unread"))];
case 1:
_a.sent();
return [2 /*return*/];
}
}); }); };
Messaging.markUnread = function (uids, roomId) { return __awaiter(_this, void 0, void 0, function () {
var exists, keys;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, Messaging.roomExists(roomId)];
case 1:
exists = _a.sent();
if (!exists) {
return [2 /*return*/];
}
keys = uids.map(function (uid) { return "uid:".concat(uid, ":chat:rooms:unread"); });
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
return [4 /*yield*/, db.sortedSetsAdd(keys, Date.now(), roomId)];
case 2:
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
_a.sent();
return [2 /*return*/];
}
});
}); };
};
92 changes: 92 additions & 0 deletions src/messaging/unread.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@

/* eslint-disable import/no-import-module-exports */
import * as db from '../database';
import * as io from '../socket.io';

// Interfaces para el tipado de funciones y/o variables
interface Messaging {
getUnreadCount: (uid: string | number) => Promise<number>;
pushUnreadCount: (uids: Array<string | number>, data?: unknown) => void;
markRead: (uid: string | number, roomId: number) => Promise<void>;
hasRead: (uids: Array<string | number>, roomId: number) => Promise<boolean[]>;
markAllRead: (uid: string | number) => Promise<void>;
markUnread: (uids: Array<string | number>, roomId: number) => Promise<void>;
getRoomData: (roomId: number) => Promise<{ public: boolean } | null>;
roomExists: (roomId: number) => Promise<boolean>;
}

interface TimestampData {
[key: string]: string;
}

interface MidData {
score: number;
}

// Codigo principal
module.exports = function (Messaging: Messaging) {
Messaging.getUnreadCount = async (uid: string | number) => {
if (!(parseInt(uid as string, 10) > 0)) {
return 0;
}
// eslint-disable-next-line max-len
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return
return await db.sortedSetCard(`uid:${uid}:chat:rooms:unread`);
};

Messaging.pushUnreadCount = (uids: Array<string | number>, data: unknown = null) => {
if (!Array.isArray(uids)) {
uids = [uids];
}
uids = uids.filter(uid => parseInt(uid as string, 10) > 0);
if (!uids.length) {
return;
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
uids.forEach((uid) => { io.in(`uid_${uid}`).emit('event:unread.updateChatCount', data); });
};

Messaging.markRead = async (uid: string | number, roomId: number) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
await Promise.all([db.sortedSetRemove(`uid:${uid}:chat:rooms:unread`, roomId), db.setObjectField(`uid:${uid}:chat:rooms:read`, roomId, Date.now()),
]);
};

Messaging.hasRead = async (uids: Array<string | number>, roomId: number) => {
if (!uids.length) {
return [];
}

const roomData = await Messaging.getRoomData(roomId);
if (!roomData) {
return uids.map(() => false);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (roomData.public) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
const [userTimestamps, mids] = await Promise.all([db.getObjectsFields(uids.map(uid => `uid:${uid}:chat:rooms:read`), [roomId]) as Promise<TimestampData[]>, db.getSortedSetRevRangeWithScores(`chat:room:${roomId}:mids`, 0, 0) as Promise<MidData[]>]);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const lastMsgTimestamp = (mids.length > 0 && mids[0].score) ? mids[0].score : 0;
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
return uids.map((uid, index) => !userTimestamps[index] || !userTimestamps[index][roomId] ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
parseInt(userTimestamps[index][roomId], 10) > lastMsgTimestamp);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
const isMembers = await db.isMemberOfSortedSets(uids.map(uid => `uid:${uid}:chat:rooms:unread`), roomId) as boolean[];
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
return uids.map((uid, index) => !isMembers[index]);
};
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
Messaging.markAllRead = async (uid: string | number) => { await db.delete(`uid:${uid}:chat:rooms:unread`); };

Messaging.markUnread = async (uids: Array<string | number>, roomId: number) => {
const exists = await Messaging.roomExists(roomId);
if (!exists) {
return;
}
const keys = uids.map(uid => `uid:${uid}:chat:rooms:unread`);
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
await db.sortedSetsAdd(keys, Date.now(), roomId);
};
};