- {presenceItem.data.name}{" "}
- {presenceItem.data.isAdmin && (
+ {presenceItem.userFullName}{" "}
+ {presenceItem.isAdmin && (
)}{" "}
- {presenceItem.data.isVIP && (
+ {presenceItem.isVIP && (
)}{" "}
- {presenceItem.clientId ===
+ {presenceItem.userId ===
roomFromDbParsed?.userId && (
);
@@ -476,15 +454,3 @@ function RoomContent() {
);
}
}
-
-export default function Room() {
- const client = new Ably.Realtime.Promise({
- authUrl: "/api/ably",
- });
-
- return (
-
-
-
- );
-}
diff --git a/app/services/schema.ts b/app/services/schema.ts
index fb96943..9d06408 100644
--- a/app/services/schema.ts
+++ b/app/services/schema.ts
@@ -73,3 +73,23 @@ export const logsRelations = relations(logs, ({ one }) => ({
references: [rooms.id],
}),
}));
+
+export const presence = sqliteTable(
+ "Presence",
+ {
+ id: text("id", { length: 255 }).notNull().primaryKey(),
+ userId: text("userId", { length: 255 }).notNull(),
+ userFullName: text("userFullName", { length: 255 }).notNull(),
+ userImageUrl: text("userImageUrl", { length: 255 }).notNull(),
+ isVIP: integer("isVIP").default(0).notNull(),
+ isAdmin: integer("isAdmin").default(0).notNull(),
+ roomId: text("roomId", { length: 255 })
+ .notNull()
+ .references(() => rooms.id, { onDelete: "cascade" }),
+ },
+ (table) => {
+ return {
+ unq: unique().on(table.userId, table.roomId),
+ };
+ }
+);
diff --git a/app/services/types.ts b/app/services/types.ts
index c9eb7c3..3c6c2d7 100644
--- a/app/services/types.ts
+++ b/app/services/types.ts
@@ -8,9 +8,12 @@ export const EventTypes = {
export type EventType = BetterEnum;
export interface PresenceItem {
- name: string;
- image: string;
- client_id: string;
+ id: string;
+ userId: string;
+ userFullName: string;
+ userImageUrl: string;
+ roomId: string;
+ value: string;
isAdmin: boolean;
isVIP: boolean;
}
@@ -66,11 +69,3 @@ export type VoteResponse =
}[]
| null
| undefined;
-
-export type AblyTokenResponse = {
- token: string;
- issued: number;
- expires: number;
- capability: string;
- clientId: string;
-};
diff --git a/package.json b/package.json
index 611f9a5..0b2c347 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
"ably": "1.2.47",
"csv42": "^5.0.0",
"drizzle-orm": "^0.29.0",
+ "ioredis": "^5.3.2",
"isbot": "^3.7.1",
"lucide-react": "^0.292.0",
"react": "^18.2.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b9a25a1..02f261f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -35,6 +35,9 @@ dependencies:
drizzle-orm:
specifier: ^0.29.0
version: 0.29.0(@libsql/client@0.4.0-pre.2)(better-sqlite3@9.1.1)
+ ioredis:
+ specifier: ^5.3.2
+ version: 5.3.2
isbot:
specifier: ^3.7.1
version: 3.7.1
@@ -1333,6 +1336,10 @@ packages:
resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==}
dev: true
+ /@ioredis/commands@1.2.0:
+ resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==}
+ dev: false
+
/@isaacs/cliui@8.0.2:
resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
engines: {node: '>=12'}
@@ -2828,6 +2835,11 @@ packages:
engines: {node: '>=0.8'}
dev: true
+ /cluster-key-slot@1.1.2:
+ resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
+ engines: {node: '>=0.10.0'}
+ dev: false
+
/color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies:
@@ -3034,7 +3046,6 @@ packages:
optional: true
dependencies:
ms: 2.1.2
- dev: true
/decode-named-character-reference@1.0.2:
resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==}
@@ -3127,6 +3138,11 @@ packages:
engines: {node: '>=0.4.0'}
dev: false
+ /denque@2.1.0:
+ resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
+ engines: {node: '>=0.10'}
+ dev: false
+
/depd@2.0.0:
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
engines: {node: '>= 0.8'}
@@ -4721,6 +4737,23 @@ packages:
side-channel: 1.0.4
dev: true
+ /ioredis@5.3.2:
+ resolution: {integrity: sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==}
+ engines: {node: '>=12.22.0'}
+ dependencies:
+ '@ioredis/commands': 1.2.0
+ cluster-key-slot: 1.1.2
+ debug: 4.3.4
+ denque: 2.1.0
+ lodash.defaults: 4.2.0
+ lodash.isarguments: 3.1.0
+ redis-errors: 1.2.0
+ redis-parser: 3.0.0
+ standard-as-callback: 2.1.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
/ipaddr.js@1.9.1:
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
engines: {node: '>= 0.10'}
@@ -5180,6 +5213,14 @@ packages:
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
dev: true
+ /lodash.defaults@4.2.0:
+ resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==}
+ dev: false
+
+ /lodash.isarguments@3.1.0:
+ resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==}
+ dev: false
+
/lodash.merge@4.6.2:
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
dev: true
@@ -5907,7 +5948,6 @@ packages:
/ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
- dev: true
/ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@@ -6739,6 +6779,18 @@ packages:
dependencies:
picomatch: 2.3.1
+ /redis-errors@1.2.0:
+ resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==}
+ engines: {node: '>=4'}
+ dev: false
+
+ /redis-parser@3.0.0:
+ resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==}
+ engines: {node: '>=4'}
+ dependencies:
+ redis-errors: 1.2.0
+ dev: false
+
/reflect.getprototypeof@1.0.4:
resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==}
engines: {node: '>= 0.4'}
@@ -7211,6 +7263,10 @@ packages:
get-source: 2.0.12
dev: true
+ /standard-as-callback@2.1.0:
+ resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==}
+ dev: false
+
/statuses@2.0.1:
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
engines: {node: '>= 0.8'}