T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/domains/lavocat.ca/private_html/src/hooks/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.ca/private_html/src/hooks/useRealTimeProfile.ts
import { useState, useEffect, useCallback } from 'react';
import { useSession } from 'next-auth/react';
import { useWebSocket } from '@/context/EnhancedWebSocketContext';

interface ProfileInteraction {
  type: 'follow' | 'unfollow' | 'friend_request' | 'friend_accept' | 'endorse' | 'message' | 'profile_view';
  fromUserId: string;
  fromUserName: string;
  fromUserAvatar?: string;
  toUserId: string;
  timestamp: number;
  data?: any;
}

interface UserStatus {
  userId: string;
  status: 'online' | 'away' | 'offline';
  timestamp: number;
}

interface ProfileView {
  viewerId: string;
  viewerName: string;
  timestamp: number;
}

export function useRealTimeProfile(userId: string) {
  const { data: session } = useSession();
  const { ws, connected, sendMessage } = useWebSocket();
  
  const [interactions, setInteractions] = useState<ProfileInteraction[]>([]);
  const [userStatus, setUserStatus] = useState<UserStatus | null>(null);
  const [profileViews, setProfileViews] = useState<ProfileView[]>([]);
  const [isOnline, setIsOnline] = useState(false);
  const [lastActivity, setLastActivity] = useState<number | null>(null);
  const [notifications, setNotifications] = useState<Array<{
    id: string;
    type: string;
    message: string;
    userId?: string;
    userName?: string;
    timestamp: Date;
  }>>([]);

  // Send profile interaction
  const sendProfileInteraction = useCallback(async (
    type: ProfileInteraction['type'], 
    targetUserId: string, 
    data?: any
  ) => {
    if (!connected || !session?.user?.id) return;

    try {
      await sendMessage('PROFILE_INTERACTION', {
        type,
        toUserId: targetUserId,
        data
      });

      // Add to local interactions immediately for optimistic UI
      const interaction: ProfileInteraction = {
        type,
        fromUserId: session.user.id,
        fromUserName: session.user.name || 'Unknown',
        fromUserAvatar: session.user.image || undefined,
        toUserId: targetUserId,
        timestamp: Date.now(),
        data
      };

      setInteractions(prev => [interaction, ...prev.slice(0, 49)]); // Keep last 50 interactions
    } catch (error) {
      console.error('Error sending profile interaction:', error);
    }
  }, [connected, session, sendMessage]);

  // Track profile view
  const trackProfileView = useCallback(async (targetUserId: string) => {
    if (!connected || !session?.user?.id || session.user.id === targetUserId) return;

    try {
      await sendMessage('PROFILE_VIEW', { targetUserId });
    } catch (error) {
      console.error('Error tracking profile view:', error);
    }
  }, [connected, session, sendMessage]);

  // Update online status
  const updateOnlineStatus = useCallback(async (status: 'online' | 'away' | 'offline') => {
    if (!connected) return;

    try {
      await sendMessage('ONLINE_STATUS', { status });
      setIsOnline(status === 'online');
    } catch (error) {
      console.error('Error updating online status:', error);
    }
  }, [connected, sendMessage]);

  // Listen for real-time events
  useEffect(() => {
    if (!ws || !connected) return;

    const handleProfileInteraction = (event: MessageEvent) => {
      try {
        const message = JSON.parse(event.data);
        
        if (message.type === 'PROFILE_INTERACTION' && message.data.toUserId === userId) {
          const interaction = message.data;
          setInteractions(prev => [interaction, ...prev.slice(0, 49)]);
          
          // Create notification for profile interactions
          const newNotification = {
            id: `notification_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
            type: interaction.type,
            message: getNotificationMessage(interaction),
            userId: interaction.fromUserId,
            userName: interaction.fromUserName,
            timestamp: new Date(interaction.timestamp)
          };
          
          setNotifications(prev => [newNotification, ...prev.slice(0, 4)]);
          
          // Trigger main notification system update
          const event = new CustomEvent('notification-updated');
          window.dispatchEvent(event);
        }
        
        if (message.type === 'PROFILE_ACTIVITY' && message.data.toUserId === userId) {
          // Update activity feed
          setLastActivity(message.data.timestamp);
        }
      } catch (error) {
        console.error('Error parsing profile interaction message:', error);
      }
    };

    const handleUserStatusUpdate = (event: MessageEvent) => {
      try {
        const message = JSON.parse(event.data);
        
        if (message.type === 'USER_STATUS_UPDATE' && message.data.userId === userId) {
          setUserStatus(message.data);
          setIsOnline(message.data.status === 'online');
        }
      } catch (error) {
        console.error('Error parsing user status message:', error);
      }
    };

    const handleProfileViewed = (event: MessageEvent) => {
      try {
        const message = JSON.parse(event.data);
        
        if (message.type === 'PROFILE_VIEWED' && session?.user?.id === userId) {
          setProfileViews(prev => [message.data, ...prev.slice(0, 19)]); // Keep last 20 views
        }
      } catch (error) {
        console.error('Error parsing profile viewed message:', error);
      }
    };

    ws.addEventListener('message', handleProfileInteraction);
    ws.addEventListener('message', handleUserStatusUpdate);
    ws.addEventListener('message', handleProfileViewed);

    // Track profile view when component mounts
    if (session?.user?.id && session.user.id !== userId) {
      trackProfileView(userId);
    }

    // Set initial online status
    updateOnlineStatus('online');

    return () => {
      ws.removeEventListener('message', handleProfileInteraction);
      ws.removeEventListener('message', handleUserStatusUpdate);
      ws.removeEventListener('message', handleProfileViewed);
      
      // Set offline status when component unmounts
      updateOnlineStatus('offline');
    };
  }, [ws, connected, userId, session, trackProfileView, updateOnlineStatus]);

  // Handle page visibility changes
  useEffect(() => {
    const handleVisibilityChange = () => {
      if (document.hidden) {
        updateOnlineStatus('away');
      } else {
        updateOnlineStatus('online');
      }
    };

    document.addEventListener('visibilitychange', handleVisibilityChange);
    return () => document.removeEventListener('visibilitychange', handleVisibilityChange);
  }, [updateOnlineStatus]);

  // Helper function to get notification message
  const getNotificationMessage = (interaction: ProfileInteraction) => {
    switch (interaction.type) {
      case 'follow':
        return `${interaction.fromUserName} started following you`;
      case 'friend_request':
        return `${interaction.fromUserName} sent you a friend request`;
      case 'endorse':
        const endorsementText = interaction.data?.text || 'endorsed your profile';
        return `${interaction.fromUserName} ${endorsementText}`;
      case 'message':
        return `${interaction.fromUserName} sent you a message`;
      case 'profile_view':
        return `${interaction.fromUserName} viewed your profile`;
      default:
        return `${interaction.fromUserName} interacted with your profile`;
    }
  };

  return {
    // State
    interactions,
    userStatus,
    profileViews,
    isOnline,
    lastActivity,
    notifications,
    
    // Actions
    sendProfileInteraction,
    trackProfileView,
    updateOnlineStatus,
    
    // Utilities
    connected,
    hasRecentActivity: lastActivity ? Date.now() - lastActivity < 300000 : false // 5 minutes
  };
} 

CasperSecurity Mini