176 lines
6.2 KiB
JavaScript
176 lines
6.2 KiB
JavaScript
import { useState, useEffect } from 'react'
|
|
import { atproto, collections } from '../api/atproto.js'
|
|
import { getApiConfig, isSyuIsHandle, getPdsFromHandle } from '../utils/pds.js'
|
|
import { env } from '../config/env.js'
|
|
|
|
export function useUserData(adminData) {
|
|
const [userComments, setUserComments] = useState([])
|
|
const [chatRecords, setChatRecords] = useState([])
|
|
const [loading, setLoading] = useState(false)
|
|
const [error, setError] = useState(null)
|
|
|
|
useEffect(() => {
|
|
if (!adminData?.did || !adminData?.apiConfig) return
|
|
|
|
const fetchUserData = async () => {
|
|
setLoading(true)
|
|
setError(null)
|
|
|
|
try {
|
|
// 1. Get user list from admin account
|
|
const userListRecords = await collections.getUserList(
|
|
adminData.apiConfig.pds,
|
|
adminData.did,
|
|
env.collection
|
|
)
|
|
|
|
// 2. Get chat records from ai.syui.log.chat
|
|
const chatRecords = await collections.getChat(
|
|
adminData.apiConfig.pds,
|
|
adminData.did,
|
|
env.collection
|
|
)
|
|
setChatRecords(chatRecords)
|
|
|
|
// 3. Get base collection records which contain user comments
|
|
const baseRecords = await collections.getBase(
|
|
adminData.apiConfig.pds,
|
|
adminData.did,
|
|
env.collection
|
|
)
|
|
|
|
// Extract comments from base records
|
|
const allUserComments = []
|
|
|
|
for (const record of baseRecords) {
|
|
if (record.value?.comments && Array.isArray(record.value.comments)) {
|
|
// Each comment already has author info, so we can use it directly
|
|
const commentsWithMeta = record.value.comments.map(comment => ({
|
|
uri: record.uri,
|
|
cid: record.cid,
|
|
value: {
|
|
...comment,
|
|
post: {
|
|
url: record.value.url
|
|
}
|
|
}
|
|
}))
|
|
allUserComments.push(...commentsWithMeta)
|
|
}
|
|
}
|
|
|
|
// Also try to get individual user records from the user list
|
|
// Currently skipping user list processing since users contain placeholder DIDs
|
|
if (userListRecords.length > 0 && userListRecords[0].value?.users) {
|
|
console.log('User list found, but skipping placeholder users for now')
|
|
|
|
// Filter out placeholder users
|
|
const realUsers = userListRecords[0].value.users.filter(user =>
|
|
user.handle &&
|
|
user.did &&
|
|
!user.did.includes('placeholder') &&
|
|
!user.did.includes('example')
|
|
)
|
|
|
|
if (realUsers.length > 0) {
|
|
console.log(`Processing ${realUsers.length} real users`)
|
|
|
|
for (const user of realUsers) {
|
|
const userHandle = user.handle
|
|
|
|
try {
|
|
// Get user's DID and PDS using PDS detection logic
|
|
let userDid, userPds, userApiConfig
|
|
|
|
if (user.did && user.pds) {
|
|
// Use DID and PDS from user record
|
|
userDid = user.did
|
|
userPds = user.pds.replace('https://', '')
|
|
userApiConfig = getApiConfig(userPds)
|
|
} else {
|
|
// Always get actual PDS from describeRepo first
|
|
try {
|
|
// Try bsky.social first for most handles
|
|
const bskyPds = 'bsky.social'
|
|
userDid = await atproto.getDid(bskyPds, userHandle)
|
|
|
|
// Get the actual PDS endpoint from DID
|
|
const realPds = await getPdsFromHandle(userHandle)
|
|
userPds = realPds.replace('https://', '')
|
|
userApiConfig = getApiConfig(realPds)
|
|
} catch (error) {
|
|
// Fallback to syu.is if bsky.social fails
|
|
console.warn(`Failed to get PDS for ${userHandle} from bsky.social, trying syu.is:`, error)
|
|
userPds = env.pds
|
|
userApiConfig = getApiConfig(env.pds)
|
|
userDid = await atproto.getDid(userPds, userHandle)
|
|
}
|
|
}
|
|
|
|
// Get user's own ai.syui.log records
|
|
const userRecords = await collections.getUserComments(
|
|
userApiConfig.pds,
|
|
userDid,
|
|
env.collection
|
|
)
|
|
|
|
// Skip if no records found
|
|
if (!userRecords || userRecords.length === 0) {
|
|
continue
|
|
}
|
|
|
|
// Get user's profile for enrichment
|
|
let profile = null
|
|
try {
|
|
profile = await atproto.getProfile(userApiConfig.bsky, userDid)
|
|
} catch (profileError) {
|
|
console.warn(`Failed to get profile for ${userHandle}:`, profileError)
|
|
}
|
|
|
|
// Add profile info to each record
|
|
const enrichedRecords = userRecords.map(record => ({
|
|
...record,
|
|
value: {
|
|
...record.value,
|
|
author: {
|
|
did: userDid,
|
|
handle: profile?.data?.handle || userHandle,
|
|
displayName: profile?.data?.displayName || userHandle,
|
|
avatar: profile?.data?.avatar || null
|
|
}
|
|
}
|
|
}))
|
|
|
|
allUserComments.push(...enrichedRecords)
|
|
} catch (userError) {
|
|
console.warn(`Failed to fetch data for user ${userHandle}:`, userError)
|
|
}
|
|
}
|
|
} else {
|
|
console.log('No real users found in user list - all appear to be placeholders')
|
|
}
|
|
}
|
|
|
|
setUserComments(allUserComments)
|
|
} catch (err) {
|
|
setError(err.message)
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
fetchUserData()
|
|
}, [adminData])
|
|
|
|
const refresh = () => {
|
|
if (adminData?.did && adminData?.apiConfig) {
|
|
// Re-trigger the effect by clearing and re-setting adminData
|
|
const currentAdminData = adminData
|
|
setUserComments([])
|
|
setChatRecords([])
|
|
// The useEffect will automatically run again
|
|
}
|
|
}
|
|
|
|
return { userComments, chatRecords, loading, error, refresh }
|
|
} |