The proxy keeps the person's library in a cache folder (hub-products in its data folder), one pack per product, served like any other pack: the hub says which revision to load and which catalogs host it, each file comes from a catalog and is checked against the hub's sha256 (files are kept by hash, so a new revision only downloads what changed), and adult files are fetched with the hub's access token. Products someone wears in a room that aren't here yet are fetched too, and put on them when they arrive. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
93fa2f5d90
commit
c281fb572c
6 files changed
+579
-3
No files matched your search
@@ -48,10 +48,38 @@ type Products struct {
|
||||
// chats it's in (the hub client).
|
||||
Observer Observer
|
||||
|
||||
// Want, if set, is asked for products someone in a room wears that aren't here (the fetcher gets hub products).
|
||||
Want func(id string)
|
||||
|
||||
roomMu sync.Mutex
|
||||
room room
|
||||
}
|
||||
|
||||
// Ready is told a product arrived (the fetcher wrote it): it's served from now on, and given to the client for
|
||||
// anyone in a room who wears it.
|
||||
func (p *Products) Ready(id string) {
|
||||
p.refresh(true)
|
||||
p.roomMu.Lock()
|
||||
p.room.init()
|
||||
var chats []string
|
||||
for chat, avatars := range p.room.last {
|
||||
for _, a := range avatars {
|
||||
for _, it := range a.Items {
|
||||
if it.ID == id {
|
||||
chats = append(chats, chat)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p.roomMu.Unlock()
|
||||
for _, chat := range chats {
|
||||
p.roomMu.Lock()
|
||||
avatars := p.room.last[chat]
|
||||
p.roomMu.Unlock()
|
||||
p.Others(chat, avatars)
|
||||
}
|
||||
}
|
||||
|
||||
// Observer hears about the client's IMVU account, its community outfit, and the chats it's in.
|
||||
type Observer interface {
|
||||
Session(imvuID int64)
|
||||
@@ -120,7 +148,7 @@ func (p *Products) refresh(force bool) {
|
||||
}
|
||||
for _, e := range entries {
|
||||
dir := filepath.Join(root, e.Name())
|
||||
if !e.IsDir() {
|
||||
if !e.IsDir() || strings.HasPrefix(e.Name(), ".") { // hidden: the fetcher's work in progress
|
||||
continue
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(dir, "t5de-product.json")); err != nil {
|
||||
|
||||
@@ -30,6 +30,7 @@ type room struct {
|
||||
applied map[string]map[int64][]int64 // chat -> user -> local IDs the client was given for them
|
||||
userIDs map[int64]string // user -> the gateway's user_id for them, as last seen
|
||||
missing map[string]bool // products others wear that aren't in the packs (logged once)
|
||||
last map[string][]hub.Avatar // chat -> what the hub last said about the others in it
|
||||
}
|
||||
|
||||
func (r *room) init() {
|
||||
@@ -39,6 +40,7 @@ func (r *room) init() {
|
||||
r.applied = map[string]map[int64][]int64{}
|
||||
r.userIDs = map[int64]string{}
|
||||
r.missing = map[string]bool{}
|
||||
r.last = map[string][]hub.Avatar{}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,13 +186,16 @@ func (p *Products) Others(chat string, avatars []hub.Avatar) {
|
||||
locals = append(locals, s.local)
|
||||
continue
|
||||
}
|
||||
if p.Want != nil {
|
||||
p.Want(it.ID) // given to the client when it arrives (Ready)
|
||||
}
|
||||
p.roomMu.Lock()
|
||||
p.room.init()
|
||||
first := !p.room.missing[it.ID]
|
||||
p.room.missing[it.ID] = true
|
||||
p.roomMu.Unlock()
|
||||
if first {
|
||||
p.logf("products: someone in the room wears %q (%s), which isn't in your packs", it.Name, it.ID)
|
||||
p.logf("products: someone in the room wears %q (%s), which isn't here yet", it.Name, it.ID)
|
||||
}
|
||||
}
|
||||
slices.Sort(locals)
|
||||
@@ -201,9 +206,11 @@ func (p *Products) Others(chat string, avatars []hub.Avatar) {
|
||||
p.room.init()
|
||||
if avatars == nil {
|
||||
delete(p.room.applied, chat)
|
||||
delete(p.room.last, chat)
|
||||
p.roomMu.Unlock()
|
||||
return
|
||||
}
|
||||
p.room.last[chat] = avatars
|
||||
had := p.room.applied[chat]
|
||||
var lines []line
|
||||
for user, old := range had {
|
||||
|
||||
Reference in new issue
Block a user