From: Lady Date: Mon, 29 Aug 2022 00:32:10 +0000 (-0700) Subject: Add SIOC types to resources X-Git-Tag: 0.1.1~1 X-Git-Url: https://git.ladys.computer/x_status_git/commitdiff_plain/8e2067811887c23a4b41beae30f6f7cca9465a08 Add SIOC types to resources + `sioc:Forum` for lists of topics + `sioc:Thread` for individual collections of statuses + `sioct:MicroblogPost` for statuses themselves --- diff --git a/README.markdown b/README.markdown index 2c71b22..31f9ac5 100644 --- a/README.markdown +++ b/README.markdown @@ -227,41 +227,86 @@ The intention is that the simple nature of these files will make them ## I Am Computer, How Do I Get Status? -Assume you are given a U·R·L to a status collection, like `/statuses`, - `/YYYY-MM`, or `/topics/my_topic`. -Make a `HEAD` request to this U·R·L. -If there is a `Link` header with a `rel` of `meta` and a `type` of - `application/ld+json`, make a `GET` request to that U·R·L instead. -Otherwise, make a `GET` request to the U·R·L you were given. - -Assuming the U·R·L you were given was valid, you will receive a - Json‐L·D response with a `@type` which is either an - `OrderedCollection` or an `OrderedCollectionPage`. -One of the following will be true :— - - + The response is an `OrderedCollectionPage`. - Its `items` will be an array of statuses, and the `prev` and - `next` properties will give U·R·Ls for previous and next - pages of statuses (if any exist). - - + The response is an `OrderedCollection` with `first` and - `current` properties. - These properies give the U·R·Ls for the first and latest pages - of statuses, which you can fetch and process as above. - - + Otherwise, the `items` property will be an array of every - status in the collection. - - > If you receive a `Collection` instead of an `OrderedCollection`, - > you are probably looking at a topics listing. - > You will need to choose a topic from the `items` and then fetch it - > to receive the list of statuses. +Assume you are given a U·R·L `resource_url` which you think points to + some kind of Status.git resource. +Start by resolving it as follows :— + +01. Make a `HEAD` request to `resource_url`. + +02. If there is a `Link` header with a `rel` of `meta` and a `type` of + `application/ld+json`, set `resource_url` to the URL provided in + that header and restart these steps from step 1. + +03. Make a `GET` request to `resource_url` and let `response` be the + response. + +04. Set `document` as follows :— + + 01. If the `Content-Type` header of `response` has a type of `text` + and subtype of `html`, let `document` be the result of + processing the body of `response` into a D·O·M tree as an + H·T·M·L document . + It is an error if this process fails. + + 02. If the `Content-Type` header of `response` has a type of + `application` and a subtype which is `xml` or which ends in + `+xml`, let `document` be the result of processing the body + of `response` into a D·O·M tree as an X·M·L document . + It is an error if this process fails. + + 03. Otherwise, let `document` be null. + +05. If `document` is not null :— + + 01. If there is a `` element in either the H·T·M·L namespace + or the Atom namespace in `document` with a `rel` of `meta` + and a `type` of `application/ld+json`, set `resource_url` to + the `href` of that `` element and restart these steps + from step 1. + If multiple such elements exist, choose the first one. + + 02. Otherwise, it is an error. + +06. If the body of `response` is not a Json document, it is an error. + +Assuming the U·R·L you were given was valid, you will end this + algorithm with a Json‐L·D response, and you can use the `@type` + attribute to determine the response type. +`@type` will be either a string or an array. + + + If the `@type` is or contains `Forum`, the resource is a collection + of topics. + + + If the `@type` is or contains `Thread`, the resource is a + collection of statuses. + +The items in the collection may be determined through one of the + following methods :— + + + If the `@type` is or contains `OrderedCollectionPage`, then its + `items` will be an array of resources. + This is a partial collection, and the `prev` and `next` properties + can be used to access further items from the parent collection + (indicated by `partOf`). + + + If the `@type` is or contains `OrderedCollection`, and the resource + has `first` and `current` properties, then the `items` property + will not be present. + `first` and `current` can be accessed to provide + `OrderedCollectionPage`s listing the items of the collection as + above. + + + Otherwise, the `items` property will contain every item in the + collection. Statuses themselves have the following properties :— + **`@id`**: The identifier of the status. + + **`@type`**: + The value `MicroblogPost`. + + **`created`** [`dcterms:created`]: The creation date for the status, as an `xsd:dateTime`. diff --git a/post-receive b/post-receive index 1b20aa8..94620be 100755 --- a/post-receive +++ b/post-receive @@ -58,7 +58,7 @@ if stdin.read().split()[-1] == f"refs/heads/{LIVE_BRANCH}": # # The provided path must be to a `text` object. def statusmap (topic, path): - status = { } + status = { "@type": "MicroblogPost" } version_path = next(path.parent.glob("0=*")) if version_path and version_path.name != "0=x_status_git_1.0": warn(f"Unrecognized version for {path}; skipping.") @@ -113,12 +113,12 @@ if stdin.read().split()[-1] == f"refs/heads/{LIVE_BRANCH}": if "subject" in status: topic = status["subject"] if topic not in topics: - topics[topic] = { "@context": { "@language": LANG, "activity": "https://www.w3.org/ns/activitystreams#", "dct": "http://purl.org/dc/terms/", "foaf": "http://xmlns.com/foaf/0.1/", "sioc": "http://rdfs.org/sioc/ns#", "OrderedCollection": "activity:OrderedCollection", "items": { "@id": "activity:items", "@type": "@id", "@container": "@list" }, "created": { "@id": "dct:created", "@type": "http://www.w3.org/2001/XMLSchema#dateTime" }, "creator": { "@id": "dct:creator", "@type": "@id" }, "identifier": { "@id": "dct:identifier", "@type": "http://www.w3.org/2001/XMLSchema#anyURI" }, "subject": "dct:subject", "name": "foaf:name", "content": { "@id": "sioc:content", "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral" } }, "@id": f"{PUBLIC_URL}/topics/{topic}", "@type": "OrderedCollection", "items": [], "subject": topic } + topics[topic] = { "@context": { "@language": LANG, "activity": "https://www.w3.org/ns/activitystreams#", "dct": "http://purl.org/dc/terms/", "foaf": "http://xmlns.com/foaf/0.1/", "sioc": "http://rdfs.org/sioc/ns#", "sioct": "http://rdfs.org/sioc/types#", "OrderedCollection": "activity:OrderedCollection", "Thread": "sioc:Thread", "MicroblogPost": "sioct:MicroblogPost", "items": { "@id": "activity:items", "@type": "@id", "@container": "@list" }, "created": { "@id": "dct:created", "@type": "http://www.w3.org/2001/XMLSchema#dateTime" }, "creator": { "@id": "dct:creator", "@type": "@id" }, "identifier": { "@id": "dct:identifier", "@type": "http://www.w3.org/2001/XMLSchema#anyURI" }, "subject": "dct:subject", "name": "foaf:name", "content": { "@id": "sioc:content", "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral" } }, "@id": f"{PUBLIC_URL}/topics/{topic}", "@type": ["OrderedCollection", "Thread"], "items": [], "subject": topic } topics[topic]["items"].append(status) else: yyyy_mm = datetime[0:7] if yyyy_mm not in months: - months[yyyy_mm] = { "@context": { "@language": LANG, "activity": "https://www.w3.org/ns/activitystreams#", "dct": "http://purl.org/dc/terms/", "foaf": "http://xmlns.com/foaf/0.1/", "sioc": "http://rdfs.org/sioc/ns#", "OrderedCollectionPage": "activity:OrderedCollectionPage", "current": { "@id": "activity:current", "@type": "@id" }, "first": { "@id": "activity:first", "@type": "@id" }, "items": { "@id": "activity:items", "@type": "@id", "@container": "@list" }, "partOf": { "@id": "activity:partOf", "@type": "@id" }, "prev": { "@id": "activity:prev", "@type": "@id" }, "next": { "@id": "activity:next", "@type": "@id" }, "created": { "@id": "dct:created", "@type": "http://www.w3.org/2001/XMLSchema#dateTime" }, "creator": { "@id": "dct:creator", "@type": "@id" }, "identifier": { "@id": "dct:identifier", "@type": "http://www.w3.org/2001/XMLSchema#anyURI" }, "name": "foaf:name", "content": { "@id": "sioc:content", "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral" } }, "@id": f"{PUBLIC_URL}/{yyyy_mm}", "@type": "OrderedCollectionPage", "items": [], "partOf": f"{PUBLIC_URL}/statuses" } + months[yyyy_mm] = { "@context": { "@language": LANG, "activity": "https://www.w3.org/ns/activitystreams#", "dct": "http://purl.org/dc/terms/", "foaf": "http://xmlns.com/foaf/0.1/", "sioc": "http://rdfs.org/sioc/ns#", "sioct": "http://rdfs.org/sioc/types#", "OrderedCollectionPage": "activity:OrderedCollectionPage", "Thread": "sioc:Thread", "MicroblogPost": "sioct:MicroblogPost", "current": { "@id": "activity:current", "@type": "@id" }, "first": { "@id": "activity:first", "@type": "@id" }, "items": { "@id": "activity:items", "@type": "@id", "@container": "@list" }, "partOf": { "@id": "activity:partOf", "@type": "@id" }, "prev": { "@id": "activity:prev", "@type": "@id" }, "next": { "@id": "activity:next", "@type": "@id" }, "created": { "@id": "dct:created", "@type": "http://www.w3.org/2001/XMLSchema#dateTime" }, "creator": { "@id": "dct:creator", "@type": "@id" }, "identifier": { "@id": "dct:identifier", "@type": "http://www.w3.org/2001/XMLSchema#anyURI" }, "name": "foaf:name", "content": { "@id": "sioc:content", "@type": "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral" } }, "@id": f"{PUBLIC_URL}/{yyyy_mm}", "@type": ["OrderedCollectionPage", "Thread"], "items": [], "partOf": f"{PUBLIC_URL}/statuses" } months[yyyy_mm]["items"].append(status) # Set up the public directory. @@ -149,7 +149,7 @@ if stdin.read().split()[-1] == f"refs/heads/{LIVE_BRANCH}": if not exists(f"{PUBLIC_DIRECTORY}/statuses"): mkdir(f"{PUBLIC_DIRECTORY}/statuses") with open(f"{PUBLIC_DIRECTORY}/statuses/index.jsonld", "w", encoding="utf-8") as f: - json.dump({ "@context": { "@language": LANG, "activity": "https://www.w3.org/ns/activitystreams#", "OrderedCollection": "activity:OrderedCollection", "current": { "@id": "activity:current", "@type": "@id" }, "first": { "@id": "activity:first", "@type": "@id" } }, "@id": f"{PUBLIC_URL}/statuses", "@type": "OrderedCollection", "first": f"{PUBLIC_URL}/{statuspairs[0][1][0]}", "current": f"{PUBLIC_URL}/{statuspairs[-1][1][0]}" }, f, ensure_ascii=False, allow_nan=False) + json.dump({ "@context": { "@language": LANG, "activity": "https://www.w3.org/ns/activitystreams#", "sioc": "http://rdfs.org/sioc/ns#", "OrderedCollection": "activity:OrderedCollection", "Thread": "sioc:Thread", "current": { "@id": "activity:current", "@type": "@id" }, "first": { "@id": "activity:first", "@type": "@id" } }, "@id": f"{PUBLIC_URL}/statuses", "@type": ["OrderedCollection", "Thread"], "first": f"{PUBLIC_URL}/{statuspairs[0][1][0]}", "current": f"{PUBLIC_URL}/{statuspairs[-1][1][0]}" }, f, ensure_ascii=False, allow_nan=False) # Output topic‐based listings and the topic index if not exists(f"{PUBLIC_DIRECTORY}/topics"): @@ -160,7 +160,7 @@ if stdin.read().split()[-1] == f"refs/heads/{LIVE_BRANCH}": with open(f"{PUBLIC_DIRECTORY}/topics/{topic}/index.jsonld", "w", encoding="utf-8") as f: json.dump(ld, f, ensure_ascii=False, allow_nan=False) with open(f"{PUBLIC_DIRECTORY}/topics/index.jsonld", "w", encoding="utf-8") as f: - json.dump({ "@context": { "@language": LANG, "activity": "https://www.w3.org/ns/activitystreams#", "dct": "http://purl.org/dc/terms/", "Collection": "activity:Collection", "items": { "@id": "activity:items", "@type": "@id" }, "subject": "dct:subject" }, "@id": f"{PUBLIC_URL}/topics", "@type": "Collection", "items": list(map(lambda a: { "@id": a["@id"], "subject": a["subject"] }, topics.values())) }, f, ensure_ascii=False, allow_nan=False) + json.dump({ "@context": { "@language": LANG, "activity": "https://www.w3.org/ns/activitystreams#", "dct": "http://purl.org/dc/terms/", "sioc": "http://rdfs.org/sioc/ns#", "Collection": "activity:Collection", "Forum": "sioc:Forum", "items": { "@id": "activity:items", "@type": "@id" }, "subject": "dct:subject" }, "@id": f"{PUBLIC_URL}/topics", "@type": ["Collection", "Forum"], "items": list(map(lambda a: { "@id": a["@id"], "subject": a["subject"] }, topics.values())) }, f, ensure_ascii=False, allow_nan=False) # Remove the build directory. rmtree(BUILD_DIRECTORY)