The code and data behind xeiaso.net
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

chore: fix web UI for API endpoints

Signed-off-by: Xe Iaso <me@xeiaso.net>

Xe Iaso 62e73239 211c028a

+449 -30
+3
cmd/xesite/main.go
··· 18 18 pb "xeiaso.net/v4/gen/xeiaso/net/v1" 19 19 "xeiaso.net/v4/internal" 20 20 "xeiaso.net/v4/internal/lume" 21 + "xeiaso.net/v4/proto" 21 22 ) 22 23 23 24 var ( ··· 95 96 twirp.WithServerPathPrefix("/api"), 96 97 ) 97 98 mux.Handle(es.PathPrefix(), es) 99 + 100 + mux.Handle("/api/defs/", http.StripPrefix("/api/defs/", http.FileServerFS(proto.FS))) 98 101 99 102 mux.HandleFunc("/blog.atom", func(w http.ResponseWriter, r *http.Request) { 100 103 http.Redirect(w, r, "/blog.rss", http.StatusMovedPermanently)
+7
go.mod
··· 70 70 github.com/aws/smithy-go v1.24.2 // indirect 71 71 github.com/beorn7/perks v1.0.1 // indirect 72 72 github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb // indirect 73 + github.com/blockthrough/twirp-openapi-gen v0.0.0-20231107141308-45a52eb7d856 // indirect 73 74 github.com/caarlos0/log v0.5.3 // indirect 74 75 github.com/caarlos0/pinata v0.3.4 // indirect 75 76 github.com/cavaliergopher/cpio v1.0.1 // indirect ··· 93 94 github.com/dlclark/regexp2 v1.11.4 // indirect 94 95 github.com/dop251/goja v0.0.0-20250309171923-bcd7cc6bf64c // indirect 95 96 github.com/emicklei/go-restful/v3 v3.12.2 // indirect 97 + github.com/emicklei/proto v1.11.2 // indirect 96 98 github.com/emirpasic/gods v1.18.1 // indirect 97 99 github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c // indirect 98 100 github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 // indirect 99 101 github.com/fatih/color v1.18.0 // indirect 100 102 github.com/fsnotify/fsnotify v1.9.0 // indirect 101 103 github.com/fxamacker/cbor/v2 v2.9.0 // indirect 104 + github.com/getkin/kin-openapi v0.120.0 // indirect 102 105 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect 103 106 github.com/go-git/go-billy/v5 v5.8.0 // indirect 104 107 github.com/go-logr/logr v1.4.3 // indirect ··· 118 121 github.com/goreleaser/nfpm/v2 v2.43.4 // indirect 119 122 github.com/gorilla/securecookie v1.1.2 // indirect 120 123 github.com/huandu/xstrings v1.5.0 // indirect 124 + github.com/invopop/yaml v0.2.0 // indirect 121 125 github.com/jackc/pgpassfile v1.0.0 // indirect 122 126 github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect 123 127 github.com/jackc/puddle/v2 v2.2.2 // indirect ··· 138 142 github.com/mitchellh/reflectwalk v1.0.2 // indirect 139 143 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 140 144 github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect 145 + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect 141 146 github.com/muesli/cancelreader v0.2.2 // indirect 142 147 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 143 148 github.com/natefinch/atomic v1.0.1 // indirect 149 + github.com/perimeterx/marshmallow v1.1.5 // indirect 144 150 github.com/pjbgf/sha1cd v0.3.2 // indirect 145 151 github.com/pkg/errors v0.9.1 // indirect 146 152 github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect ··· 192 198 tool ( 193 199 github.com/TecharoHQ/yeet/cmd/yeet 194 200 github.com/a-h/templ/cmd/templ 201 + github.com/blockthrough/twirp-openapi-gen/cmd/twirp-openapi-gen 195 202 github.com/caarlos0/pinata 196 203 golang.org/x/tools/cmd/goimports 197 204 golang.org/x/tools/cmd/stringer
+13
go.sum
··· 138 138 github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= 139 139 github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4= 140 140 github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= 141 + github.com/blockthrough/twirp-openapi-gen v0.0.0-20231107141308-45a52eb7d856 h1:7m7Q6EErVZWPIp1UeVSb5zUTFzV6m7ZUcUIpbWffBfs= 142 + github.com/blockthrough/twirp-openapi-gen v0.0.0-20231107141308-45a52eb7d856/go.mod h1:UN1OFH6gXrM9qKvXPcs4dOAAMB1tC4kw/eUzdA/bmI8= 141 143 github.com/caarlos0/log v0.5.3 h1:ocxCwZWjI9u9eNFMnEJN2OzS7FXkfaKxg5afC4uOltc= 142 144 github.com/caarlos0/log v0.5.3/go.mod h1:n6BAWZiYv9obEy89jSNAmBo0m3x93chRBElXhyqpg4c= 143 145 github.com/caarlos0/pinata v0.3.4 h1:7EJ6rs8oFn1EMW7QNffOSlC6sgrZ2siKCC/4RHWRVrU= ··· 208 210 github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= 209 211 github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= 210 212 github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= 213 + github.com/emicklei/proto v1.11.2 h1:DiIeyTJ+gPSyJI+RIAqvuTeKb0tLUmaGXbYg6aFKsnE= 214 + github.com/emicklei/proto v1.11.2/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= 211 215 github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= 212 216 github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 213 217 github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= ··· 230 234 github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= 231 235 github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= 232 236 github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= 237 + github.com/getkin/kin-openapi v0.120.0 h1:MqJcNJFrMDFNc07iwE8iFC5eT2k/NPUFDIpNeiZv8Jg= 238 + github.com/getkin/kin-openapi v0.120.0/go.mod h1:PCWw/lfBrJY4HcdqE3jj+QFkaFK8ABoqo7PvqVhXXqw= 233 239 github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= 234 240 github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= 235 241 github.com/go-faker/faker/v4 v4.7.0 h1:VboC02cXHl/NuQh5lM2W8b87yp4iFXIu59x4w0RZi4E= ··· 374 380 github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= 375 381 github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= 376 382 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 383 + github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY= 384 + github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q= 377 385 github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= 378 386 github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= 379 387 github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= ··· 453 461 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 454 462 github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= 455 463 github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 464 + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= 465 + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= 456 466 github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= 457 467 github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= 458 468 github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= ··· 467 477 github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= 468 478 github.com/orandin/slog-gorm v1.4.0 h1:FgA8hJufF9/jeNSYoEXmHPPBwET2gwlF3B85JdpsTUU= 469 479 github.com/orandin/slog-gorm v1.4.0/go.mod h1:MoZ51+b7xE9lwGNPYEhxcUtRNrYzjdcKvA8QXQQGEPA= 480 + github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= 481 + github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= 470 482 github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= 471 483 github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= 472 484 github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= ··· 959 971 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 960 972 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 961 973 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 974 + gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 962 975 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 963 976 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 964 977 gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
+35 -30
manifest/patreon-saasproxy/deployment.yaml
··· 2 2 kind: Deployment 3 3 metadata: 4 4 name: patreon-saasproxy 5 + annotations: 6 + keel.sh/policy: "all" 7 + keel.sh/trigger: poll 8 + keel.sh/pollSchedule: "@every 5m" 9 + keel.sh/match-tag: "true" 5 10 spec: 6 11 selector: 7 12 matchLabels: ··· 13 18 spec: 14 19 serviceAccountName: xesite-patreon-saasproxy 15 20 containers: 16 - - name: web 17 - image: ghcr.io/xe/site/patreon:latest 18 - imagePullPolicy: Always 19 - resources: 20 - limits: 21 - memory: "128Mi" 22 - cpu: "500m" 23 - env: 24 - - name: "BIND" 25 - value: ":8080" 26 - - name: "KUBERNETES_NAMESPACE" 27 - valueFrom: 28 - fieldRef: 29 - fieldPath: "metadata.namespace" 30 - - name: KUBERNETES_SECRET_NAME 31 - value: "xesite-patreon-saasproxy-state" 32 - envFrom: 33 - - secretRef: 34 - name: xesite-patreon-saasproxy-creds 35 - ports: 36 - - containerPort: 8080 37 - livenessProbe: 38 - httpGet: 39 - path: /healthz 40 - port: 8080 41 - httpHeaders: 42 - - name: X-Kubernetes 43 - value: "Is alright, I guess" 44 - initialDelaySeconds: 3 45 - periodSeconds: 3 21 + - name: web 22 + image: ghcr.io/xe/site/patreon:latest 23 + imagePullPolicy: Always 24 + resources: 25 + limits: 26 + memory: "128Mi" 27 + cpu: "500m" 28 + env: 29 + - name: "BIND" 30 + value: ":8080" 31 + - name: "KUBERNETES_NAMESPACE" 32 + valueFrom: 33 + fieldRef: 34 + fieldPath: "metadata.namespace" 35 + - name: KUBERNETES_SECRET_NAME 36 + value: "xesite-patreon-saasproxy-state" 37 + envFrom: 38 + - secretRef: 39 + name: xesite-patreon-saasproxy-creds 40 + ports: 41 + - containerPort: 8080 42 + livenessProbe: 43 + httpGet: 44 + path: /healthz 45 + port: 8080 46 + httpHeaders: 47 + - name: X-Kubernetes 48 + value: "Is alright, I guess" 49 + initialDelaySeconds: 3 50 + periodSeconds: 3
+5
manifest/xesite/deployment.yaml
··· 2 2 kind: Deployment 3 3 metadata: 4 4 name: xesite 5 + annotations: 6 + keel.sh/policy: "all" 7 + keel.sh/trigger: poll 8 + keel.sh/pollSchedule: "@every 5m" 9 + keel.sh/match-tag: "true" 5 10 spec: 6 11 selector: 7 12 matchLabels:
+8
proto/generate.go
··· 1 + package proto 2 + 3 + import "embed" 4 + 5 + //go:generate go tool twirp-openapi-gen -in ./xeiaso/net/v1/xesite.proto -in ./within/website/x/mi/v1/mi.proto -out openapi.json -path-prefix /api -servers https://xeiaso.net -title "Xe Iaso Dot Net API" -doc-version 4.0.0 6 + 7 + //go:embed openapi.json 8 + var FS embed.FS
+378
proto/openapi.json
··· 1 + { 2 + "components": { 3 + "schemas": { 4 + "protofeed.Attachment": { 5 + "description": "Attachment is an object representing a file associated with an item.", 6 + "properties": { 7 + "duration_in_seconds": { 8 + "description": "(optional, number) specifies how long it takes to listen to or watch, when\nplayed at normal speed.", 9 + "format": "int32", 10 + "type": "integer" 11 + }, 12 + "mime_type": { 13 + "description": "(required, string) specifies the type of the attachment, such as\n“audio/mpeg.”", 14 + "type": "string" 15 + }, 16 + "size_in_bytes": { 17 + "description": "(optional, number) specifies how large the file is.", 18 + "format": "int32", 19 + "type": "integer" 20 + }, 21 + "title": { 22 + "description": "(optional, string) specifies the title of the attachment.", 23 + "type": "string" 24 + }, 25 + "url": { 26 + "description": "(required, string) specifies the location of the attachment.", 27 + "type": "string" 28 + } 29 + }, 30 + "type": "object" 31 + }, 32 + "protofeed.Author": { 33 + "description": "Author is an object representing the author of the feed or item.", 34 + "properties": { 35 + "avatar": { 36 + "description": "(optional, string) is the URL for an image for the author. As with icon, it\nshould be square and relatively large — such as 512 x 512 pixels — and\nshould use transparency where appropriate, since it may be rendered on a\nnon-white background.", 37 + "type": "string" 38 + }, 39 + "name": { 40 + "description": "(optional, string) is the author’s name.", 41 + "type": "string" 42 + }, 43 + "url": { 44 + "description": "(optional, string) is the URL of a site owned by the author. It could be a\nblog, micro-blog, Twitter account, and so on. Ideally the linked-to page\nprovides a way to contact the author, but that’s not required. The URL\ncould be a mailto: link, though we suspect that will be rare.", 45 + "type": "string" 46 + } 47 + }, 48 + "type": "object" 49 + }, 50 + "protofeed.Feed": { 51 + "description": "Feed is the root of a Proto Feed document. A feed must at least contain a\ntitle and items.", 52 + "properties": { 53 + "authors": { 54 + "description": "(optional, array of objects) specifies the feed authors.", 55 + "items": { 56 + "$ref": "#/components/schemas/protofeed.Author" 57 + }, 58 + "type": "array" 59 + }, 60 + "description": { 61 + "description": "(optional, string) provides more detail, beyond the title, on what the feed\nis about. A feed reader may display this text.", 62 + "type": "string" 63 + }, 64 + "expired": { 65 + "description": "(optional, boolean) says whether or not the feed is finished — that is,\nwhether or not it will ever update again. A feed for a temporary event,\nsuch as an instance of the Olympics, could expire. If the value is true,\nthen it’s expired. Any other value, or the absence of expired, means the\nfeed may continue to update.", 66 + "type": "boolean" 67 + }, 68 + "favicon": { 69 + "description": "(optional, string) is the URL of an image for the feed suitable to be used\nin a source list. It should be square and relatively small, but not smaller\nthan 64 x 64.", 70 + "type": "string" 71 + }, 72 + "feed_url": { 73 + "description": "(optional but strongly recommended, string) is the URL of the feed, and\nserves as the unique identifier for the feed. As with home_page_url, this\nshould be considered required for feeds on the public web.", 74 + "type": "string" 75 + }, 76 + "home_page_url": { 77 + "description": "(optional but strongly recommended, string) is the URL of the resource that\nthe feed describes. This resource may or may not actually be a “home” page,\nbut it should be an HTML page. If a feed is published on the public web,\nthis should be considered as required. But it may not make sense in the\ncase of a file created on a desktop computer, when that file is not shared\nor is shared only privately.", 78 + "type": "string" 79 + }, 80 + "icon": { 81 + "description": "(optional, string) is the URL of an image for the feed suitable to be used\nin a source list. It should be square and relatively large — such as 512 x\n512 — so that it can be scaled down and so that it can look good on retina\ndisplays. It should use transparency where appropriate, since it may be\nrendered on a non-white background.", 82 + "type": "string" 83 + }, 84 + "items": { 85 + "description": "(required, array of objects) contains the items in the feed. This is the\nmost important element of the feed after the version field. Each item is a\nstory, blog post, article, photograph, video, or other thing. For example,\nif a feed contains a long article, a podcast episode, and a photo, those\nthree items would be included in items.", 86 + "items": { 87 + "$ref": "#/components/schemas/protofeed.Item" 88 + }, 89 + "type": "array" 90 + }, 91 + "language": { 92 + "description": "(optional, string) is the primary language for the feed.", 93 + "type": "string" 94 + }, 95 + "title": { 96 + "description": "(required, string) is the name of the feed, which will often correspond to\nthe name of the website (blog, for instance), though not necessarily.", 97 + "type": "string" 98 + }, 99 + "user_comment": { 100 + "description": "(optional, string) is a description of the purpose of the feed. This is for\nthe use of people looking at the raw Protobuf, and should be ignored by\nfeed readers.", 101 + "type": "string" 102 + } 103 + }, 104 + "type": "object" 105 + }, 106 + "protofeed.Item": { 107 + "description": "Item is an object representing a single story, blog post, article,\nphotograph, video, or other thing within a feed.", 108 + "properties": { 109 + "attachments": { 110 + "description": "(optional, array of objects) specifies the attachments associated with the\nitem. Attachments are files that are associated with an item. The value of\nthe attachments field is an array of objects, each of which has a url\nfield, and other fields as specified in the attachment object definition.", 111 + "items": { 112 + "$ref": "#/components/schemas/protofeed.Attachment" 113 + }, 114 + "type": "array" 115 + }, 116 + "authors": { 117 + "description": "(optional, array of objects) has the same structure as the top-level\nauthors. If not specified in an item, then the top-level authors, if\npresent, are the authors of the item.", 118 + "items": { 119 + "$ref": "#/components/schemas/protofeed.Author" 120 + }, 121 + "type": "array" 122 + }, 123 + "banner_image": { 124 + "description": "(optional, string) is the URL of an image to use as a banner. Some blogging\nsystems (such as Medium) display a different banner image in the list view\nfrom the detail view. In those systems, this image should be used in the\nlist view, and image in the detail view.", 125 + "type": "string" 126 + }, 127 + "content_html": { 128 + "description": "(optional, string) is the body of the item. It can be plain text, HTML, or\na snippet of Markdown. (It should not be the entire Markdown document; just\na snippet.) This is complete enough that it can be displayed alone in a\nreader.", 129 + "type": "string" 130 + }, 131 + "content_text": { 132 + "description": "(optional, string) is the body of the item. It can be plain text, HTML, or\na snippet of Markdown. (It should not be the entire Markdown document; just\na snippet.) This is complete enough that it can be displayed alone in a\nreader.", 133 + "type": "string" 134 + }, 135 + "date_modified": { 136 + "description": "(optional, string) specifies the modification date in RFC 3339 format.", 137 + "format": "date-time", 138 + "type": "string" 139 + }, 140 + "date_published": { 141 + "description": "(optional, string) specifies the date in RFC 3339 format.", 142 + "format": "date-time", 143 + "type": "string" 144 + }, 145 + "external_url": { 146 + "description": "(optional, string) is the URL of a page elsewhere. This is especially\nuseful for linkblogs. If url links to where you’re talking about a thing,\nthen external_url links to the thing you’re talking about.", 147 + "type": "string" 148 + }, 149 + "id": { 150 + "description": "(required, string) is unique for that item for that feed over time. If an\nitem is ever updated, the id should be unchanged. New items should never\nuse a previously-used id. If an id is presented as a number or other type,\na JSON Feed reader must coerce it to a string. Ideally, the id is the full\nURL of the resource described by the item, since URLs make great unique\nidentifiers.", 151 + "type": "string" 152 + }, 153 + "image": { 154 + "description": "(optional, string) is the URL of the main image for the item. This image\nmay also appear in the content_html — if so, it’s a hint to the feed reader\nthat this is the main, featured image. Even if it’s not, it will appear in\nthe detail view. Images should be square, with a 4:3 aspect ratio. (We will\nbe flexible on this in the future.)", 155 + "type": "string" 156 + }, 157 + "language": { 158 + "description": "(optional, string) is the language for this item, using the same format as\nthe top-level language field. The value can be different than the primary\nlanguage for the feed when a specific item is written in a different\nlanguage than other items in the feed.", 159 + "type": "string" 160 + }, 161 + "summary": { 162 + "description": "(optional, string) is a plain text sentence or two describing the item.\nThis might be presented in a timeline, for instance, where a detail view\nwould display all of content_html or content_text.", 163 + "type": "string" 164 + }, 165 + "tags": { 166 + "description": "(optional, array of strings) can have any plain text values you want. Tags\ntend to be just one word, but they may be anything. Note: they are not the\nequivalent of Twitter hashtags. Some blogging systems and other feed\nformats call these categories.", 167 + "items": { 168 + "description": "(optional, array of strings) can have any plain text values you want. Tags\ntend to be just one word, but they may be anything. Note: they are not the\nequivalent of Twitter hashtags. Some blogging systems and other feed\nformats call these categories.", 169 + "type": "string" 170 + }, 171 + "type": "array" 172 + }, 173 + "title": { 174 + "description": "(optional, string) is plain text. Microblog items in particular may omit\ntitles.", 175 + "type": "string" 176 + }, 177 + "url": { 178 + "description": "(optional, string) is the URL of the resource described by the item. It’s\nthe permalink. This may be the same as the id — but should be present\nregardless.", 179 + "type": "string" 180 + } 181 + }, 182 + "type": "object" 183 + }, 184 + "within.website.x.mi.v1.Event": { 185 + "description": "Event is a single event that Xe will be attending.", 186 + "properties": { 187 + "description": { 188 + "description": "The description of the event", 189 + "type": "string" 190 + }, 191 + "end_date": { 192 + "description": "The day the event ends", 193 + "format": "date-time", 194 + "type": "string" 195 + }, 196 + "id": { 197 + "description": "The ID of the event", 198 + "format": "int32", 199 + "type": "integer" 200 + }, 201 + "location": { 202 + "description": "The location of the event (human-readable)", 203 + "type": "string" 204 + }, 205 + "name": { 206 + "description": "The name of the event", 207 + "type": "string" 208 + }, 209 + "start_date": { 210 + "description": "The day the event starts", 211 + "format": "date-time", 212 + "type": "string" 213 + }, 214 + "url": { 215 + "description": "The URL for the event", 216 + "type": "string" 217 + } 218 + }, 219 + "type": "object" 220 + }, 221 + "within.website.x.mi.v1.EventFeed": { 222 + "description": "A feed of events, result from mi query.", 223 + "properties": { 224 + "events": { 225 + "description": "The events in the feed", 226 + "items": { 227 + "$ref": "#/components/schemas/within.website.x.mi.v1.Event" 228 + }, 229 + "type": "array" 230 + } 231 + }, 232 + "type": "object" 233 + }, 234 + "xeiaso.net.v1.BuildInfo": { 235 + "description": "BuildInfo contains metadata about a build of the site.", 236 + "properties": { 237 + "build_time": { 238 + "description": "When the site was last rebuilt", 239 + "format": "date-time", 240 + "type": "string" 241 + }, 242 + "commit": { 243 + "description": "The commit of Xe/site that was built", 244 + "type": "string" 245 + }, 246 + "deno_version": { 247 + "description": "The version of Deno used to build the site", 248 + "type": "string" 249 + }, 250 + "go_version": { 251 + "description": "The version of Go running on the server", 252 + "type": "string" 253 + }, 254 + "xesite_version": { 255 + "description": "The version of the xesite binary", 256 + "type": "string" 257 + } 258 + }, 259 + "type": "object" 260 + }, 261 + "xeiaso.net.v1.FeedServiceGetRequest": { 262 + "description": "FeedServiceGetRequest is the request for FeedService.Get.", 263 + "type": "object" 264 + }, 265 + "xeiaso.net.v1.FeedServiceGetResponse": { 266 + "description": "FeedServiceGetResponse is the response for FeedService.Get.", 267 + "properties": { 268 + "feed": { 269 + "$ref": "#/components/schemas/protofeed.Feed" 270 + } 271 + }, 272 + "type": "object" 273 + }, 274 + "xeiaso.net.v1.MetadataRequest": { 275 + "description": "MetadataRequest is the request for MetaService.Metadata.", 276 + "type": "object" 277 + }, 278 + "xeiaso.net.v1.MetadataResponse": { 279 + "description": "MetadataResponse is the response for MetaService.Metadata.", 280 + "properties": { 281 + "build_info": { 282 + "$ref": "#/components/schemas/xeiaso.net.v1.BuildInfo" 283 + } 284 + }, 285 + "type": "object" 286 + } 287 + } 288 + }, 289 + "info": { 290 + "title": "Xe Iaso Dot Net API", 291 + "version": "4.0.0" 292 + }, 293 + "openapi": "3.0.0", 294 + "paths": { 295 + "/api/within.website.x.mi.v1.Events/Get": { 296 + "post": { 297 + "description": "\nGet fetches the current feed of upcoming events.", 298 + "requestBody": { 299 + "content": { 300 + "application/json": {} 301 + } 302 + }, 303 + "responses": { 304 + "200": { 305 + "content": { 306 + "application/json": { 307 + "schema": { 308 + "$ref": "#/components/schemas/within.website.x.mi.v1.EventFeed" 309 + } 310 + } 311 + }, 312 + "description": "Success" 313 + } 314 + }, 315 + "summary": "Get" 316 + } 317 + }, 318 + "/api/xeiaso.net.v1.FeedService/Get": { 319 + "post": { 320 + "description": "\nGet fetches the current feed of posts.", 321 + "requestBody": { 322 + "content": { 323 + "application/json": { 324 + "schema": { 325 + "$ref": "#/components/schemas/xeiaso.net.v1.FeedServiceGetRequest" 326 + } 327 + } 328 + } 329 + }, 330 + "responses": { 331 + "200": { 332 + "content": { 333 + "application/json": { 334 + "schema": { 335 + "$ref": "#/components/schemas/xeiaso.net.v1.FeedServiceGetResponse" 336 + } 337 + } 338 + }, 339 + "description": "Success" 340 + } 341 + }, 342 + "summary": "Get" 343 + } 344 + }, 345 + "/api/xeiaso.net.v1.MetaService/Metadata": { 346 + "post": { 347 + "description": "\nMetadata fetches the build metadata of the version of xesite that is\ncurrently running.", 348 + "requestBody": { 349 + "content": { 350 + "application/json": { 351 + "schema": { 352 + "$ref": "#/components/schemas/xeiaso.net.v1.MetadataRequest" 353 + } 354 + } 355 + } 356 + }, 357 + "responses": { 358 + "200": { 359 + "content": { 360 + "application/json": { 361 + "schema": { 362 + "$ref": "#/components/schemas/xeiaso.net.v1.MetadataResponse" 363 + } 364 + } 365 + }, 366 + "description": "Success" 367 + } 368 + }, 369 + "summary": "Metadata" 370 + } 371 + } 372 + }, 373 + "servers": [ 374 + { 375 + "url": "https://xeiaso.net" 376 + } 377 + ] 378 + }