Sasha commited on
Commit
79047e1
·
1 Parent(s): 81cc161

fix: merge and preserve user roles during chat logging upsert

Browse files
Files changed (1) hide show
  1. server/db.js +91 -39
server/db.js CHANGED
@@ -627,11 +627,10 @@ export async function logChatMessagesBatch(messages) {
627
  VALUES (?, ?, ?, ?, ?, ?)
628
  ON CONFLICT(username) DO UPDATE SET
629
  display_name = excluded.display_name,
630
- is_mod = excluded.is_mod,
631
- is_sub = excluded.is_sub,
632
- is_vip = excluded.is_vip,
633
- last_seen = excluded.last_seen
634
- WHERE excluded.last_seen > chat_users.last_seen
635
  `);
636
 
637
  const runTransaction = sqliteDb.transaction((msgs) => {
@@ -703,16 +702,18 @@ export async function logChatMessagesBatch(messages) {
703
  is_streamer: msg.isStreamer || false
704
  });
705
 
706
- const viewerKey = `${streamId || 'null'}-${username}`;
707
- viewersToUpsert.set(viewerKey, {
708
- stream_id: streamId,
709
- username: msg.username.toLowerCase(),
710
- display_name: msg.displayName || msg.username,
711
- has_chatted: true,
712
- is_mod: msg.isMod || false,
713
- is_sub: msg.isSub || false,
714
- first_seen: ts
715
- });
 
 
716
 
717
  const userKey = username;
718
  chatUsersToUpsert.set(userKey, {
@@ -749,15 +750,44 @@ export async function logChatMessagesBatch(messages) {
749
  if (uniqueChatUsers.length > 0) {
750
  const { data: existingUsers } = await supabase
751
  .from('chat_users')
752
- .select('username, last_seen')
753
  .in('username', uniqueChatUsers.map(u => u.username));
754
 
755
- const existingMap = new Map((existingUsers || []).map(u => [u.username, new Date(u.last_seen).getTime()]));
756
- const toUpsert = uniqueChatUsers.filter(u => {
757
- const oldTime = existingMap.get(u.username) || 0;
758
- const newTime = new Date(u.last_seen).getTime();
759
- return newTime > oldTime;
760
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
761
 
762
  if (toUpsert.length > 0) {
763
  const { error: chatUserError } = await supabase
@@ -800,11 +830,10 @@ export async function logRolesBatch(users) {
800
  VALUES (?, ?, ?, ?, ?, ?)
801
  ON CONFLICT(username) DO UPDATE SET
802
  display_name = excluded.display_name,
803
- is_mod = excluded.is_mod,
804
- is_sub = excluded.is_sub,
805
- is_vip = excluded.is_vip,
806
- last_seen = excluded.last_seen
807
- WHERE excluded.last_seen > chat_users.last_seen
808
  `);
809
 
810
  const runTransaction = sqliteDb.transaction((usersToInsert) => {
@@ -829,21 +858,44 @@ export async function logRolesBatch(users) {
829
  // Supabase Mode
830
  const { data: existingUsers } = await supabase
831
  .from('chat_users')
832
- .select('username, last_seen')
833
  .in('username', uniqueChatUsers.map(u => u.username));
834
 
835
- const existingMap = new Map((existingUsers || []).map(u => [u.username, new Date(u.last_seen).getTime()]));
 
 
 
 
 
 
 
 
836
 
837
- // Always update roles (is_mod/is_sub/is_vip), but only advance last_seen if newer
838
- const toUpsert = uniqueChatUsers.map(u => {
839
- const oldTime = existingMap.get(u.username) || 0;
840
- const newTime = new Date(u.last_seen).getTime();
841
- return {
842
- ...u,
843
- // Keep last_seen as the newer of the two
844
- last_seen: newTime > oldTime ? u.last_seen : (existingUsers || []).find(e => e.username === u.username)?.last_seen || u.last_seen
845
- };
846
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
847
 
848
  if (toUpsert.length > 0) {
849
  const { error: chatUserError } = await supabase
 
627
  VALUES (?, ?, ?, ?, ?, ?)
628
  ON CONFLICT(username) DO UPDATE SET
629
  display_name = excluded.display_name,
630
+ is_mod = CASE WHEN excluded.is_mod = 1 THEN 1 ELSE chat_users.is_mod END,
631
+ is_sub = CASE WHEN excluded.is_sub = 1 THEN 1 ELSE chat_users.is_sub END,
632
+ is_vip = CASE WHEN excluded.is_vip = 1 THEN 1 ELSE chat_users.is_vip END,
633
+ last_seen = CASE WHEN excluded.last_seen > chat_users.last_seen THEN excluded.last_seen ELSE chat_users.last_seen END
 
634
  `);
635
 
636
  const runTransaction = sqliteDb.transaction((msgs) => {
 
702
  is_streamer: msg.isStreamer || false
703
  });
704
 
705
+ if (streamId) {
706
+ const viewerKey = `${streamId}-${username}`;
707
+ viewersToUpsert.set(viewerKey, {
708
+ stream_id: streamId,
709
+ username: msg.username.toLowerCase(),
710
+ display_name: msg.displayName || msg.username,
711
+ has_chatted: true,
712
+ is_mod: msg.isMod || false,
713
+ is_sub: msg.isSub || false,
714
+ first_seen: ts
715
+ });
716
+ }
717
 
718
  const userKey = username;
719
  chatUsersToUpsert.set(userKey, {
 
750
  if (uniqueChatUsers.length > 0) {
751
  const { data: existingUsers } = await supabase
752
  .from('chat_users')
753
+ .select('username, last_seen, is_mod, is_sub, is_vip')
754
  .in('username', uniqueChatUsers.map(u => u.username));
755
 
756
+ const existingMap = new Map((existingUsers || []).map(u => [
757
+ u.username,
758
+ {
759
+ last_seen: new Date(u.last_seen).getTime(),
760
+ is_mod: u.is_mod || false,
761
+ is_sub: u.is_sub || false,
762
+ is_vip: u.is_vip || false
763
+ }
764
+ ]));
765
+
766
+ const toUpsert = [];
767
+ for (const u of uniqueChatUsers) {
768
+ const existing = existingMap.get(u.username);
769
+ if (existing) {
770
+ const oldTime = existing.last_seen;
771
+ const newTime = new Date(u.last_seen).getTime();
772
+
773
+ const isUpgraded = (!existing.is_mod && u.is_mod) ||
774
+ (!existing.is_sub && u.is_sub) ||
775
+ (!existing.is_vip && u.is_vip);
776
+
777
+ u.is_mod = u.is_mod || existing.is_mod;
778
+ u.is_sub = u.is_sub || existing.is_sub;
779
+ u.is_vip = u.is_vip || existing.is_vip;
780
+
781
+ if (newTime > oldTime || isUpgraded) {
782
+ if (oldTime > newTime) {
783
+ u.last_seen = new Date(oldTime).toISOString();
784
+ }
785
+ toUpsert.push(u);
786
+ }
787
+ } else {
788
+ toUpsert.push(u);
789
+ }
790
+ }
791
 
792
  if (toUpsert.length > 0) {
793
  const { error: chatUserError } = await supabase
 
830
  VALUES (?, ?, ?, ?, ?, ?)
831
  ON CONFLICT(username) DO UPDATE SET
832
  display_name = excluded.display_name,
833
+ is_mod = CASE WHEN excluded.is_mod = 1 THEN 1 ELSE chat_users.is_mod END,
834
+ is_sub = CASE WHEN excluded.is_sub = 1 THEN 1 ELSE chat_users.is_sub END,
835
+ is_vip = CASE WHEN excluded.is_vip = 1 THEN 1 ELSE chat_users.is_vip END,
836
+ last_seen = CASE WHEN excluded.last_seen > chat_users.last_seen THEN excluded.last_seen ELSE chat_users.last_seen END
 
837
  `);
838
 
839
  const runTransaction = sqliteDb.transaction((usersToInsert) => {
 
858
  // Supabase Mode
859
  const { data: existingUsers } = await supabase
860
  .from('chat_users')
861
+ .select('username, last_seen, is_mod, is_sub, is_vip')
862
  .in('username', uniqueChatUsers.map(u => u.username));
863
 
864
+ const existingMap = new Map((existingUsers || []).map(u => [
865
+ u.username,
866
+ {
867
+ last_seen: new Date(u.last_seen).getTime(),
868
+ is_mod: u.is_mod || false,
869
+ is_sub: u.is_sub || false,
870
+ is_vip: u.is_vip || false
871
+ }
872
+ ]));
873
 
874
+ const toUpsert = [];
875
+ for (const u of uniqueChatUsers) {
876
+ const existing = existingMap.get(u.username);
877
+ if (existing) {
878
+ const oldTime = existing.last_seen;
879
+ const newTime = new Date(u.last_seen).getTime();
880
+
881
+ const isUpgraded = (!existing.is_mod && u.is_mod) ||
882
+ (!existing.is_sub && u.is_sub) ||
883
+ (!existing.is_vip && u.is_vip);
884
+
885
+ u.is_mod = u.is_mod || existing.is_mod;
886
+ u.is_sub = u.is_sub || existing.is_sub;
887
+ u.is_vip = u.is_vip || existing.is_vip;
888
+
889
+ if (newTime > oldTime || isUpgraded) {
890
+ if (oldTime > newTime) {
891
+ u.last_seen = new Date(oldTime).toISOString();
892
+ }
893
+ toUpsert.push(u);
894
+ }
895
+ } else {
896
+ toUpsert.push(u);
897
+ }
898
+ }
899
 
900
  if (toUpsert.length > 0) {
901
  const { error: chatUserError } = await supabase