package kinds // TODO: rename this to `construct` // TODO: I think this should be moved to // package request, then Fetch will return an Object // directly by calling Create, and Create will // still work fine import ( "errors" "net/url" "mimicry/shared" "mimicry/request" ) type Object interface { String() string Kind() (string, error) Identifier() (*url.URL, error) Category() string } // TODO, add a verbose debugging output mode // to debug problems that arise with this thing // looping too much and whatnot // source is where it came from, if source is different // from the element's id, it will be refetched // maybe change back to taking in a unstructured shared.JSON func Create(input any, source *url.URL) (Object, error) { unstructured, ok := input.(shared.JSON) if !ok { return nil, errors.New("Cannot construct with a non-object JSON") } kind, err := shared.Get[string](unstructured, "type") if err != nil { return nil, err } id, err := shared.GetURL(unstructured, "id") if err != nil { return nil, err } // if the JSON came from a source (e.g. inline in another collection), with a // different hostname than its ID, refetch // if the JSON only has two keys (type and id), refetch if source != nil && source.Hostname() != id.Hostname() || len(unstructured) <= 2 { response, err := request.Fetch(id) if err != nil { return nil, err } return Create(response, nil) } // TODO: if the only keys are id and type, // you need to do a fetch to get the other keys switch kind { case "Article": fallthrough case "Audio": fallthrough case "Document": fallthrough case "Image": fallthrough case "Note": fallthrough case "Page": fallthrough case "Video": // TODO: figure out the way to do this directly post := Post{} post = unstructured return post, nil // case "Create": // fallthrough // case "Announce": // fallthrough // case "Dislike": // fallthrough // case "Like": // fallthrough // case "Question": // return Activity{unstructured}, nil case "Application": fallthrough case "Group": fallthrough case "Organization": fallthrough case "Person": fallthrough case "Service": // TODO: nicer way to do this? actor := Actor{} actor = unstructured return actor, nil // case "Link": // return Link{unstructured}, nil // case "Collection": // fallthrough // case "OrderedCollection": // return Collection{unstructured}, nil // case "CollectionPage": // fallthrough // case "OrderedCollectionPage": // return CollectionPage{unstructured}, nil default: return nil, errors.New("Object of Type " + kind + " unsupported") } }