fedipod-server 0.29.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (444) hide show
  1. package/README.md +16 -6
  2. package/dist/claims.d.ts +2 -0
  3. package/dist/claims.js +13 -4
  4. package/dist/door.d.ts +4 -0
  5. package/dist/door.js +31 -0
  6. package/dist/fedipod.d.ts +15 -0
  7. package/dist/fedipod.js +13 -0
  8. package/dist/front.d.ts +3 -0
  9. package/dist/front.js +92 -0
  10. package/dist/handler.d.ts +36 -101
  11. package/dist/handler.js +93 -644
  12. package/dist/handler.jsonld +2 -30
  13. package/dist/identities.d.ts +71 -0
  14. package/dist/identities.js +236 -0
  15. package/dist/mounts.d.ts +43 -0
  16. package/dist/mounts.js +123 -0
  17. package/dist/opt-in.d.ts +46 -0
  18. package/dist/opt-in.js +176 -0
  19. package/dist/private-read.d.ts +4 -0
  20. package/dist/private-read.js +34 -0
  21. package/package.json +12 -20
  22. package/lib/client/c2s.mjs +0 -636
  23. package/lib/client/localapi.mjs +0 -87
  24. package/lib/client/masto/accounts.mjs +0 -310
  25. package/lib/client/masto/body.mjs +0 -156
  26. package/lib/client/masto/index.mjs +0 -206
  27. package/lib/client/masto/instance.mjs +0 -112
  28. package/lib/client/masto/media.mjs +0 -79
  29. package/lib/client/masto/oauth.mjs +0 -656
  30. package/lib/client/masto/render.mjs +0 -518
  31. package/lib/client/masto/statuses.mjs +0 -372
  32. package/lib/client/masto/timelines.mjs +0 -438
  33. package/lib/client/oidc-auth.mjs +0 -62
  34. package/lib/client/streaming.mjs +0 -154
  35. package/lib/client/webpush.mjs +0 -98
  36. package/lib/connections/acctfeed.mjs +0 -257
  37. package/lib/connections/atproto.mjs +0 -309
  38. package/lib/connections/bskyfeed.mjs +0 -243
  39. package/lib/connections/bskygroup.mjs +0 -162
  40. package/lib/connections/fediacct.mjs +0 -253
  41. package/lib/connections/import.mjs +0 -357
  42. package/lib/connections/tagfeed.mjs +0 -212
  43. package/lib/connections/vault.mjs +0 -114
  44. package/lib/core/as2.mjs +0 -206
  45. package/lib/core/contexts/activitystreams.json +0 -379
  46. package/lib/core/contexts/anno.json +0 -126
  47. package/lib/core/contexts/did-v1.json +0 -57
  48. package/lib/core/contexts/fep-5711.json +0 -36
  49. package/lib/core/contexts/gotosocial.json +0 -86
  50. package/lib/core/contexts/identity-v1.json +0 -152
  51. package/lib/core/contexts/index.mjs +0 -63
  52. package/lib/core/contexts/join-lemmy.json +0 -33
  53. package/lib/core/contexts/joinmastodon.json +0 -28
  54. package/lib/core/contexts/litepub-0.1.json +0 -60
  55. package/lib/core/contexts/map.json +0 -19
  56. package/lib/core/contexts/miscellany.json +0 -19
  57. package/lib/core/contexts/quotes.json +0 -18
  58. package/lib/core/contexts/schemaorg.json +0 -8845
  59. package/lib/core/contexts/security-data-integrity-v1.json +0 -78
  60. package/lib/core/contexts/security-data-integrity-v2.json +0 -81
  61. package/lib/core/contexts/security-multikey-v1.json +0 -35
  62. package/lib/core/contexts/security-v1.json +0 -74
  63. package/lib/core/contexts/webfinger.json +0 -10
  64. package/lib/core/deliver.mjs +0 -387
  65. package/lib/core/graphview.mjs +0 -327
  66. package/lib/core/intake/activities.mjs +0 -649
  67. package/lib/core/intake/activity.mjs +0 -318
  68. package/lib/core/intake/channel.mjs +0 -144
  69. package/lib/core/intake/group.mjs +0 -258
  70. package/lib/core/intake/index.mjs +0 -732
  71. package/lib/core/intake/notes.mjs +0 -367
  72. package/lib/core/intake/verify.mjs +0 -142
  73. package/lib/core/keys.mjs +0 -153
  74. package/lib/core/lease.mjs +0 -206
  75. package/lib/core/place.mjs +0 -82
  76. package/lib/core/polls.mjs +0 -105
  77. package/lib/core/profile-page.mjs +0 -104
  78. package/lib/core/proof.mjs +0 -79
  79. package/lib/core/publisher/collections.mjs +0 -272
  80. package/lib/core/publisher/index.mjs +0 -522
  81. package/lib/core/publisher/notes.mjs +0 -519
  82. package/lib/core/publisher/own.mjs +0 -143
  83. package/lib/core/publisher/questions.mjs +0 -241
  84. package/lib/core/publisher/restore.mjs +0 -224
  85. package/lib/core/shapes/activitystreams.ttl +0 -157
  86. package/lib/core/shapes/index.mjs +0 -132
  87. package/lib/core/shapes/shapes-text.mjs +0 -13
  88. package/lib/core/social.mjs +0 -561
  89. package/lib/core/storage.mjs +0 -176
  90. package/lib/core/store.mjs +0 -578
  91. package/lib/core/wire-quotes.mjs +0 -71
  92. package/lib/core/wire.mjs +0 -925
  93. package/lib/device/account.mjs +0 -87
  94. package/lib/device/admin/index.mjs +0 -13
  95. package/lib/device/admin/origins.mjs +0 -35
  96. package/lib/device/admin/routes/connections.mjs +0 -144
  97. package/lib/device/admin/routes/gateway.mjs +0 -199
  98. package/lib/device/admin/routes/lifecycle.mjs +0 -200
  99. package/lib/device/admin/routes/owner.mjs +0 -322
  100. package/lib/device/admin/routes/setup.mjs +0 -428
  101. package/lib/device/admin/routes/social.mjs +0 -188
  102. package/lib/device/admin/server.mjs +0 -95
  103. package/lib/device/admin/static.mjs +0 -247
  104. package/lib/device/admin/surface.mjs +0 -315
  105. package/lib/device/certs.mjs +0 -281
  106. package/lib/device/cli/commands/account.mjs +0 -586
  107. package/lib/device/cli/commands/run.mjs +0 -278
  108. package/lib/device/cli/commands/service.mjs +0 -221
  109. package/lib/device/cli/commands/setup.mjs +0 -489
  110. package/lib/device/cli/commands/state.mjs +0 -561
  111. package/lib/device/cli/context.mjs +0 -288
  112. package/lib/device/export-collections.mjs +0 -161
  113. package/lib/device/gateway-move.mjs +0 -58
  114. package/lib/device/home.mjs +0 -161
  115. package/lib/device/migrate.mjs +0 -115
  116. package/lib/device/ports.mjs +0 -27
  117. package/lib/device/remote.mjs +0 -54
  118. package/lib/device/setup.mjs +0 -496
  119. package/lib/device/update.mjs +0 -96
  120. package/lib/gateway/caches.mjs +0 -36
  121. package/lib/gateway/directory.mjs +0 -90
  122. package/lib/gateway/front-core.mjs +0 -966
  123. package/lib/gateway/gateway-core.mjs +0 -244
  124. package/lib/gateway/headers.mjs +0 -49
  125. package/lib/gateway/httpsig.mjs +0 -159
  126. package/lib/gateway/notices.mjs +0 -84
  127. package/lib/gateway/quiet.mjs +0 -189
  128. package/lib/gateway/relay-extras.mjs +0 -89
  129. package/lib/gateway/token-claims.mjs +0 -16
  130. package/lib/pod/README.md +0 -61
  131. package/lib/pod/actor.mjs +0 -96
  132. package/lib/pod/collection.mjs +0 -77
  133. package/lib/pod/containers.mjs +0 -140
  134. package/lib/pod/discovery.mjs +0 -46
  135. package/lib/pod/featured.mjs +0 -18
  136. package/lib/pod/followers.mjs +0 -24
  137. package/lib/pod/following.mjs +0 -10
  138. package/lib/pod/http.mjs +0 -74
  139. package/lib/pod/inbox.mjs +0 -166
  140. package/lib/pod/links.mjs +0 -35
  141. package/lib/pod/location.mjs +0 -52
  142. package/lib/pod/media.mjs +0 -27
  143. package/lib/pod/notes.mjs +0 -78
  144. package/lib/pod/notifications.mjs +0 -89
  145. package/lib/pod/outbox.mjs +0 -18
  146. package/lib/pod/package.json +0 -19
  147. package/lib/pod/policy.mjs +0 -58
  148. package/lib/pod/private.mjs +0 -19
  149. package/lib/pod/root.mjs +0 -104
  150. package/lib/pod/state.mjs +0 -40
  151. package/lib/pod/transport.mjs +0 -674
  152. package/lib/pod/type-index.mjs +0 -101
  153. package/lib/pod/urls.mjs +0 -91
  154. package/lib/server/embed.mjs +0 -424
  155. package/lib/session/README.md +0 -137
  156. package/lib/session/demo.html +0 -94
  157. package/lib/session/fedi-account.mjs +0 -417
  158. package/lib/session/fedi-login.mjs +0 -123
  159. package/lib/session/oidc-session.mjs +0 -233
  160. package/lib/session/package.json +0 -49
  161. package/lib/shared/guard.mjs +0 -213
  162. package/lib/shared/links.mjs +0 -9
  163. package/lib/shared/safefetch.mjs +0 -235
  164. package/lib/shared/ua.mjs +0 -29
  165. package/phanpy/dist/404.html +0 -40
  166. package/phanpy/dist/_headers +0 -2
  167. package/phanpy/dist/apple-touch-icon.png +0 -0
  168. package/phanpy/dist/assets/ICONS-DIPJeU0C.js +0 -2
  169. package/phanpy/dist/assets/ICONS-DIPJeU0C.js.map +0 -1
  170. package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js +0 -183
  171. package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js.map +0 -1
  172. package/phanpy/dist/assets/Temml-CCjoacWt.woff2 +0 -0
  173. package/phanpy/dist/assets/__vite-browser-external-C7iut881.js +0 -2
  174. package/phanpy/dist/assets/__vite-browser-external-C7iut881.js.map +0 -1
  175. package/phanpy/dist/assets/boosts-carousel-BiOaNdMT.jpg +0 -0
  176. package/phanpy/dist/assets/catch-up-O5q5C75Z.png +0 -0
  177. package/phanpy/dist/assets/chunk-aKtaBQYM.js +0 -1
  178. package/phanpy/dist/assets/compose-CFEx7wb4.js +0 -2
  179. package/phanpy/dist/assets/compose-CFEx7wb4.js.map +0 -1
  180. package/phanpy/dist/assets/compose-ZJN5xSb4.js +0 -35
  181. package/phanpy/dist/assets/compose-ZJN5xSb4.js.map +0 -1
  182. package/phanpy/dist/assets/debug.module-YFQgwnIr.js +0 -52
  183. package/phanpy/dist/assets/debug.module-YFQgwnIr.js.map +0 -1
  184. package/phanpy/dist/assets/dom-p1YcJ5Rw.js +0 -2
  185. package/phanpy/dist/assets/dom-p1YcJ5Rw.js.map +0 -1
  186. package/phanpy/dist/assets/home-mobile-dark@2x-Dc-J8-SM.png +0 -0
  187. package/phanpy/dist/assets/home-mobile-light@2x-Bd3fod8m.png +0 -0
  188. package/phanpy/dist/assets/home-tablet-dark@2x-BgcNI8le.png +0 -0
  189. package/phanpy/dist/assets/home-tablet-light@2x-BW2RV9T6.png +0 -0
  190. package/phanpy/dist/assets/icons/add-circle-line-WD0mwORD.js +0 -1
  191. package/phanpy/dist/assets/icons/alert-line-CpFUMf9s.js +0 -1
  192. package/phanpy/dist/assets/icons/android-2-line-Bzxnrd3S.js +0 -1
  193. package/phanpy/dist/assets/icons/announcement-line-5nwaJFJm.js +0 -1
  194. package/phanpy/dist/assets/icons/arrow-down-circle-line-a7Id9-Iv.js +0 -1
  195. package/phanpy/dist/assets/icons/arrow-down-line-B8uzXzq6.js +0 -1
  196. package/phanpy/dist/assets/icons/arrow-left-line-CGrGT9C-.js +0 -1
  197. package/phanpy/dist/assets/icons/arrow-right-line-CE-HERfX.js +0 -1
  198. package/phanpy/dist/assets/icons/arrow-to-up-line-CvdQjmcy.js +0 -1
  199. package/phanpy/dist/assets/icons/arrow-up-circle-line-DEparSNF.js +0 -1
  200. package/phanpy/dist/assets/icons/arrow-up-line-C7yBeugc.js +0 -1
  201. package/phanpy/dist/assets/icons/arrows-right-line-BtbXmJGP.js +0 -1
  202. package/phanpy/dist/assets/icons/at-line-CF66Bznk.js +0 -1
  203. package/phanpy/dist/assets/icons/attachment-line-BY8It-l9.js +0 -1
  204. package/phanpy/dist/assets/icons/blockquote-line-BS6pU_hm.js +0 -1
  205. package/phanpy/dist/assets/icons/board-line-C0UWXyA6.js +0 -1
  206. package/phanpy/dist/assets/icons/bookmark-line-1CtX5JLF.js +0 -1
  207. package/phanpy/dist/assets/icons/building-5-line-Dd59MzbO.js +0 -1
  208. package/phanpy/dist/assets/icons/bus-2-line-6_dvA0GG.js +0 -1
  209. package/phanpy/dist/assets/icons/calendar-day-line-Crpl_fmu.js +0 -1
  210. package/phanpy/dist/assets/icons/calendar-month-line-vommts2C.js +0 -1
  211. package/phanpy/dist/assets/icons/calendar-time-add-line-BU_DTlQk.js +0 -1
  212. package/phanpy/dist/assets/icons/camera-line-Cv69MEei.js +0 -1
  213. package/phanpy/dist/assets/icons/celebrate-line-B8DvIoi0.js +0 -1
  214. package/phanpy/dist/assets/icons/chart-bar-line-FK-QOmtF.js +0 -1
  215. package/phanpy/dist/assets/icons/chart-line-line-BGcJAFWw.js +0 -1
  216. package/phanpy/dist/assets/icons/chat-3-line-YFK2-hwz.js +0 -1
  217. package/phanpy/dist/assets/icons/check-circle-line-DsAxFr5-.js +0 -1
  218. package/phanpy/dist/assets/icons/clipboard-line-BBp364gJ.js +0 -1
  219. package/phanpy/dist/assets/icons/close-circle-line-CICdiuGz.js +0 -1
  220. package/phanpy/dist/assets/icons/close-line-DYrFWcjv.js +0 -1
  221. package/phanpy/dist/assets/icons/cloud-line-tiQAbah8.js +0 -1
  222. package/phanpy/dist/assets/icons/code-line-fAl8iiV3.js +0 -1
  223. package/phanpy/dist/assets/icons/comment-2-line-CR3g7WeB.js +0 -1
  224. package/phanpy/dist/assets/icons/copy-2-line-CLW69yF5.js +0 -1
  225. package/phanpy/dist/assets/icons/delete-2-line-B8xmbr4n.js +0 -1
  226. package/phanpy/dist/assets/icons/document-3-line-DBGNhAg2.js +0 -1
  227. package/phanpy/dist/assets/icons/document-line-C7mb9sb7.js +0 -1
  228. package/phanpy/dist/assets/icons/down-line-BGqSSThd.js +0 -1
  229. package/phanpy/dist/assets/icons/edit-4-line-DcgGaEhx.js +0 -1
  230. package/phanpy/dist/assets/icons/emoji-2-line-D8YgnM-y.js +0 -1
  231. package/phanpy/dist/assets/icons/exit-line-Dc07BS-x.js +0 -1
  232. package/phanpy/dist/assets/icons/external-link-line-BvpSkmjO.js +0 -1
  233. package/phanpy/dist/assets/icons/eye-2-line-CiWXx-f_.js +0 -1
  234. package/phanpy/dist/assets/icons/eye-close-line-BgTaSJ4P.js +0 -1
  235. package/phanpy/dist/assets/icons/filter-2-line-B_mR2usy.js +0 -1
  236. package/phanpy/dist/assets/icons/filter-line-C_nm-3cU.js +0 -1
  237. package/phanpy/dist/assets/icons/flag-1-line-C2HB05I0.js +0 -1
  238. package/phanpy/dist/assets/icons/forbid-circle-line-D3LTT9yd.js +0 -1
  239. package/phanpy/dist/assets/icons/formula-line-DLrt2d6j.js +0 -1
  240. package/phanpy/dist/assets/icons/grid-line-CgUmEikf.js +0 -1
  241. package/phanpy/dist/assets/icons/group-line-C5fnX0wU.js +0 -1
  242. package/phanpy/dist/assets/icons/hand-finger-2-line-BGgxbuL9.js +0 -1
  243. package/phanpy/dist/assets/icons/hashtag-line-CyTEEXBb.js +0 -1
  244. package/phanpy/dist/assets/icons/heart-crack-line-BZddbO2C.js +0 -1
  245. package/phanpy/dist/assets/icons/heart-line-CJ7K47J4.js +0 -1
  246. package/phanpy/dist/assets/icons/history-2-line-kWWvFzqv.js +0 -1
  247. package/phanpy/dist/assets/icons/history-line-bGQiwbTH.js +0 -1
  248. package/phanpy/dist/assets/icons/home-3-line-fRU1zeLG.js +0 -1
  249. package/phanpy/dist/assets/icons/information-line-iNk6-sOY.js +0 -1
  250. package/phanpy/dist/assets/icons/keyboard-line-DsCyuQNz.js +0 -1
  251. package/phanpy/dist/assets/icons/layout-4-line-CZkOX52Z.js +0 -1
  252. package/phanpy/dist/assets/icons/layout-5-line-B_znt5wO.js +0 -1
  253. package/phanpy/dist/assets/icons/left-line-eUw0tya4.js +0 -1
  254. package/phanpy/dist/assets/icons/lightning-line-DaKoDdix.js +0 -1
  255. package/phanpy/dist/assets/icons/link-2-line-DCqLmMA7.js +0 -1
  256. package/phanpy/dist/assets/icons/list-check-line-BAxosBh9.js +0 -1
  257. package/phanpy/dist/assets/icons/lock-line-CPoaXeUW.js +0 -1
  258. package/phanpy/dist/assets/icons/mail-line-B0P8aa1L.js +0 -1
  259. package/phanpy/dist/assets/icons/moon-line-CEqNAToP.js +0 -1
  260. package/phanpy/dist/assets/icons/more-1-fill-Dw2e5xab.js +0 -1
  261. package/phanpy/dist/assets/icons/more-3-line-BIiVjYTz.js +0 -1
  262. package/phanpy/dist/assets/icons/notification-line-BZZq2Gtu.js +0 -1
  263. package/phanpy/dist/assets/icons/pencil-line-CKh8-A1v.js +0 -1
  264. package/phanpy/dist/assets/icons/photo-album-line-Bnfg2u40.js +0 -1
  265. package/phanpy/dist/assets/icons/pin-line-DpTolyhs.js +0 -1
  266. package/phanpy/dist/assets/icons/play-fill-B0-G_8lX.js +0 -1
  267. package/phanpy/dist/assets/icons/qrcode-2-line-B6SPCaHn.js +0 -1
  268. package/phanpy/dist/assets/icons/quill-pen-line-B6LUrnCP.js +0 -1
  269. package/phanpy/dist/assets/icons/quote-left-fill-hQZ1cj_6.js +0 -1
  270. package/phanpy/dist/assets/icons/radar-line-CKyroTth.js +0 -1
  271. package/phanpy/dist/assets/icons/react-line-CoIKhhtK.js +0 -1
  272. package/phanpy/dist/assets/icons/refresh-2-line-D0mTF97S.js +0 -1
  273. package/phanpy/dist/assets/icons/right-line-B3KWJaqc.js +0 -1
  274. package/phanpy/dist/assets/icons/rocket-line-4KZl537D.js +0 -1
  275. package/phanpy/dist/assets/icons/round-fill-C69NTrZ0.js +0 -1
  276. package/phanpy/dist/assets/icons/round-line-B9k_1uo-.js +0 -1
  277. package/phanpy/dist/assets/icons/route-line-B28ReHcE.js +0 -1
  278. package/phanpy/dist/assets/icons/rows-4-line-CrBniagM.js +0 -1
  279. package/phanpy/dist/assets/icons/scan-line-DSf74YdP.js +0 -1
  280. package/phanpy/dist/assets/icons/search-2-line-B6geIU1z.js +0 -1
  281. package/phanpy/dist/assets/icons/settings-3-line-azJwK47w.js +0 -1
  282. package/phanpy/dist/assets/icons/settings-6-line-C_5zc5YR.js +0 -1
  283. package/phanpy/dist/assets/icons/share-2-line-D5MxWjrm.js +0 -1
  284. package/phanpy/dist/assets/icons/share-forward-line-Cp61fZzZ.js +0 -1
  285. package/phanpy/dist/assets/icons/sparkles-2-line-DYYyXTaW.js +0 -1
  286. package/phanpy/dist/assets/icons/sparkles-line-C2hY1s6I.js +0 -1
  287. package/phanpy/dist/assets/icons/time-line-BF3eet1v.js +0 -1
  288. package/phanpy/dist/assets/icons/transfer-4-line-oisfvTBw.js +0 -1
  289. package/phanpy/dist/assets/icons/translate-line-BFWol2Ce.js +0 -1
  290. package/phanpy/dist/assets/icons/unlock-line-X_x5vwv3.js +0 -1
  291. package/phanpy/dist/assets/icons/upload-3-line-DgzwUJeW.js +0 -1
  292. package/phanpy/dist/assets/icons/user-4-line-BVSynZCp.js +0 -1
  293. package/phanpy/dist/assets/icons/user-add-2-line-BlGS5Q8q.js +0 -1
  294. package/phanpy/dist/assets/icons/user-add-line-BbXdHG4z.js +0 -1
  295. package/phanpy/dist/assets/icons/user-edit-line-BFAHOV0X.js +0 -1
  296. package/phanpy/dist/assets/icons/user-follow-line-BXux0wSd.js +0 -1
  297. package/phanpy/dist/assets/icons/user-star-line-DdYlpHLU.js +0 -1
  298. package/phanpy/dist/assets/icons/user-warning-line-Cj43j0_E.js +0 -1
  299. package/phanpy/dist/assets/icons/user-x-line-DIDgNlPH.js +0 -1
  300. package/phanpy/dist/assets/icons/volume-line-Bs390KQt.js +0 -1
  301. package/phanpy/dist/assets/icons/volume-mute-line-DzlzIqFZ.js +0 -1
  302. package/phanpy/dist/assets/icons/walk-line-yNXfB-md.js +0 -1
  303. package/phanpy/dist/assets/icons/world-2-line-CenkGIwj.js +0 -1
  304. package/phanpy/dist/assets/icons/zoom-in-line-CaENUphf.js +0 -1
  305. package/phanpy/dist/assets/icons/zoom-out-line-BDNk0EWo.js +0 -1
  306. package/phanpy/dist/assets/instances-BNPptnn-.json +0 -333
  307. package/phanpy/dist/assets/locales/ar-SA-CfheRbCu.js +0 -1
  308. package/phanpy/dist/assets/locales/ca-ES-DHRW86Tz.js +0 -1
  309. package/phanpy/dist/assets/locales/cs-CZ-CKoqEuA1.js +0 -1
  310. package/phanpy/dist/assets/locales/de-DE-ByRPMRFy.js +0 -1
  311. package/phanpy/dist/assets/locales/eo-UY-CPC7wLCS.js +0 -1
  312. package/phanpy/dist/assets/locales/es-ES-dJa0Fd9t.js +0 -1
  313. package/phanpy/dist/assets/locales/eu-ES-C3djlPR2.js +0 -1
  314. package/phanpy/dist/assets/locales/fa-IR-DTT490Ck.js +0 -1
  315. package/phanpy/dist/assets/locales/fi-FI-B23MCPuz.js +0 -1
  316. package/phanpy/dist/assets/locales/fr-FR-BcaQsO5C.js +0 -1
  317. package/phanpy/dist/assets/locales/gl-ES-BR-CVKBN.js +0 -1
  318. package/phanpy/dist/assets/locales/he-IL-CfheRbCu.js +0 -1
  319. package/phanpy/dist/assets/locales/hu-HU-CfheRbCu.js +0 -1
  320. package/phanpy/dist/assets/locales/it-IT-C1136UFV.js +0 -1
  321. package/phanpy/dist/assets/locales/ja-JP-CRZmRAhD.js +0 -1
  322. package/phanpy/dist/assets/locales/kab-Cz8xH_TT.js +0 -1
  323. package/phanpy/dist/assets/locales/ko-KR-CG9UiY4o.js +0 -1
  324. package/phanpy/dist/assets/locales/lt-LT-CJcI6sHZ.js +0 -1
  325. package/phanpy/dist/assets/locales/nb-NO-CfheRbCu.js +0 -1
  326. package/phanpy/dist/assets/locales/nl-NL-DxN4Yc1t.js +0 -1
  327. package/phanpy/dist/assets/locales/oc-FR-CfheRbCu.js +0 -1
  328. package/phanpy/dist/assets/locales/pl-PL-DkwGXf6P.js +0 -1
  329. package/phanpy/dist/assets/locales/pseudo-LOCALE-CQ4XxkQ0.js +0 -1
  330. package/phanpy/dist/assets/locales/pt-BR-nGL0HdFS.js +0 -1
  331. package/phanpy/dist/assets/locales/pt-PT-Cp17aj2z.js +0 -1
  332. package/phanpy/dist/assets/locales/ru-RU-0Y8cIoaK.js +0 -1
  333. package/phanpy/dist/assets/locales/th-TH-CfheRbCu.js +0 -1
  334. package/phanpy/dist/assets/locales/tok-CfheRbCu.js +0 -1
  335. package/phanpy/dist/assets/locales/tr-TR-CfheRbCu.js +0 -1
  336. package/phanpy/dist/assets/locales/uk-UA-C5E3dFBf.js +0 -1
  337. package/phanpy/dist/assets/locales/zh-CN-BHJi7_et.js +0 -1
  338. package/phanpy/dist/assets/locales/zh-TW-CfheRbCu.js +0 -1
  339. package/phanpy/dist/assets/main-BdqNbG-a.js +0 -26
  340. package/phanpy/dist/assets/main-BdqNbG-a.js.map +0 -1
  341. package/phanpy/dist/assets/mock-home-DGhR__He.js +0 -2
  342. package/phanpy/dist/assets/mock-home-DGhR__He.js.map +0 -1
  343. package/phanpy/dist/assets/multi-column-ROck0NVt.jpg +0 -0
  344. package/phanpy/dist/assets/multi-hashtag-timeline-DH5INVHi.jpg +0 -0
  345. package/phanpy/dist/assets/nested-comments-thread-hv59kZLc.jpg +0 -0
  346. package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js +0 -2
  347. package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js.map +0 -1
  348. package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js +0 -20
  349. package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js.map +0 -1
  350. package/phanpy/dist/assets/style-B1iLPTPR.css +0 -2
  351. package/phanpy/dist/assets/temml-DuyIQMei.js +0 -97
  352. package/phanpy/dist/assets/temml-DuyIQMei.js.map +0 -1
  353. package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js +0 -2
  354. package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js.map +0 -1
  355. package/phanpy/dist/assets/year-in-posts-B2lywqdx.png +0 -0
  356. package/phanpy/dist/assets/year-in-posts-DJv_star.js +0 -3
  357. package/phanpy/dist/assets/year-in-posts-DJv_star.js.map +0 -1
  358. package/phanpy/dist/compose/index.html +0 -20
  359. package/phanpy/dist/favicon.ico +0 -0
  360. package/phanpy/dist/index.html +0 -73
  361. package/phanpy/dist/logo-192.png +0 -0
  362. package/phanpy/dist/logo-512.png +0 -0
  363. package/phanpy/dist/logo-badge-72.png +0 -0
  364. package/phanpy/dist/logo-maskable-512.png +0 -0
  365. package/phanpy/dist/logo-monochrome-512.png +0 -0
  366. package/phanpy/dist/logo-monochrome-maskable-512.png +0 -0
  367. package/phanpy/dist/manifest.webmanifest +0 -1
  368. package/phanpy/dist/og-image-2.jpg +0 -0
  369. package/phanpy/dist/og-image.png +0 -0
  370. package/phanpy/dist/robots.txt +0 -2
  371. package/phanpy/dist/sw.js +0 -2
  372. package/phanpy/dist/sw.js.map +0 -1
  373. package/phanpy/dist/version.json +0 -1
  374. package/run-agent.mjs +0 -899
  375. package/vendor/gate.cjs +0 -138
  376. package/vendor/idp-grant.cjs +0 -394
  377. package/vendor/jfetch.cjs +0 -16
  378. package/web/admin/actors.js +0 -147
  379. package/web/admin/bar.css +0 -126
  380. package/web/admin/bar.js +0 -99
  381. package/web/admin/client/client.js +0 -66
  382. package/web/admin/client/index.html +0 -69
  383. package/web/admin/client-pick.js +0 -79
  384. package/web/admin/common.js +0 -23
  385. package/web/admin/connections.js +0 -112
  386. package/web/admin/gateway.js +0 -133
  387. package/web/admin/group.js +0 -258
  388. package/web/admin/index.html +0 -612
  389. package/web/admin/notices-bar.js +0 -90
  390. package/web/admin/oauth-signin.mjs +0 -37
  391. package/web/admin/record.js +0 -393
  392. package/web/admin/setup/index.html +0 -257
  393. package/web/admin/setup/setup.js +0 -339
  394. package/web/admin/tokens.css +0 -68
  395. package/web/admin/upkeep.js +0 -177
  396. package/web/admin/window.css +0 -55
  397. package/web/admin/window.js +0 -136
  398. package/web/app/README.md +0 -81
  399. package/web/app/admin-facade.mjs +0 -588
  400. package/web/app/agent.mjs +0 -672
  401. package/web/app/atproto-browser.mjs +0 -86
  402. package/web/app/authorize_interaction.html +0 -56
  403. package/web/app/authorize_interaction.js +0 -69
  404. package/web/app/boot.mjs +0 -616
  405. package/web/app/deliver-relay.mjs +0 -129
  406. package/web/app/dist/boot.js +0 -34562
  407. package/web/app/dist/boot.js.map +0 -7
  408. package/web/app/dist/sw.js +0 -73456
  409. package/web/app/dist/sw.js.map +0 -7
  410. package/web/app/fediacct-browser.mjs +0 -146
  411. package/web/app/gateway-move.mjs +0 -60
  412. package/web/app/idb-kv.mjs +0 -35
  413. package/web/app/index.html +0 -258
  414. package/web/app/keys-browser.mjs +0 -71
  415. package/web/app/keystore.mjs +0 -82
  416. package/web/app/oidc-session.mjs +0 -6
  417. package/web/app/pod-auth.mjs +0 -248
  418. package/web/app/pod-remote.mjs +0 -84
  419. package/web/app/shims/_globals.mjs +0 -2
  420. package/web/app/shims/fedify-sig.mjs +0 -77
  421. package/web/app/shims/node-crypto.mjs +0 -113
  422. package/web/app/shims/node-fs.mjs +0 -17
  423. package/web/app/shims/node-path.mjs +0 -19
  424. package/web/app/shims/node-url.mjs +0 -7
  425. package/web/app/shims/prelude.js +0 -58
  426. package/web/app/shims/safefetch.mjs +0 -58
  427. package/web/app/shims/shapes-text.mjs +0 -8
  428. package/web/app/shims/web-push.mjs +0 -14
  429. package/web/app/signup.mjs +0 -357
  430. package/web/app/sw-src.mjs +0 -220
  431. package/web/app/update.js +0 -70
  432. package/web/front/admin.html +0 -55
  433. package/web/front/admin.js +0 -89
  434. package/web/front/install.sh +0 -69
  435. package/web/front/new-account.html +0 -35
  436. package/web/front/new-account.js +0 -13
  437. package/web/front/notices.html +0 -69
  438. package/web/front/notices.js +0 -107
  439. package/web/front/run.html +0 -64
  440. package/web/front/run.js +0 -221
  441. package/web/front/solid-oidc-client.js +0 -6
  442. package/web/icons/forum.svg +0 -11
  443. package/web/icons/gateway.svg +0 -14
  444. package/web/icons/local.svg +0 -11
@@ -1,206 +0,0 @@
1
- // mastoapi.mjs — Mastodon client-API facade over ap-agent (M1: read + post).
2
- // Modeled on snac2's approach: real implementations for the endpoints
3
- // clients actually exercise, empty-collection stubs for the rest. Reached
4
- // through the router (/api/*, /oauth/* → this port), so requests carry the
5
- // gate; OAuth here is theater for a single already-trusted local user.
6
- //
7
- // Surface: oauth trio · instance v1/v2 · verify_credentials · timelines/home
8
- // (M1) · notifications, relationships, lookup, follow/unfollow, thread
9
- // context, /v2/search (M2) · favourite/reblog, media upload, markers,
10
- // DELETE status (M3) · stub farm. Unknown /api/* GETs 404 and are LOGGED —
11
- // that log is the running punch list.
12
- //
13
- // This file is the class and the dispatcher. The endpoints are in the modules
14
- // beside it, one per area — oauth.mjs, instance.mjs, accounts.mjs,
15
- // timelines.mjs, statuses.mjs, media.mjs — each exporting handle(api, ctx),
16
- // which answers and returns true or returns false; handle() below walks them
17
- // in order with the bearer gate between the public ones and the rest. The
18
- // JSON shapes are render.mjs and the request readers body.mjs; every helper
19
- // the areas reach through `api.` is a one-line delegation here.
20
-
21
- import { Push } from '../webpush.mjs';
22
- import * as oauth from './oauth.mjs';
23
- import * as render from './render.mjs';
24
- import * as instance from './instance.mjs';
25
- import * as accounts from './accounts.mjs';
26
- import * as timelines from './timelines.mjs';
27
- import * as statuses from './statuses.mjs';
28
- import * as media from './media.mjs';
29
- export { hashPassword } from './oauth.mjs';
30
- export { pollParams } from './body.mjs';
31
- export { attachmentType, extensionFor } from './media.mjs';
32
-
33
- export class MastoApi {
34
- constructor({ agent, log = console.log, allowed = null, scheme = null, embedded = false, throughDoor = null,
35
- mount = '', streaming = true, webPush = true, scheduling = true }) {
36
- this.agent = agent;
37
- // The path this identity's surface answers under, when it shares its origin
38
- // with others (a suffix pod, e.g. `/aisha`). Empty for a host-root or
39
- // subdomain pod. Folded into the self-URLs the client is handed —
40
- // pagination links, the OAuth issuer — so they name the address the client
41
- // actually reached.
42
- this.mount = mount;
43
- // A server-hosted identity has no CLI of its own, so the advice this gives
44
- // when it refuses has to name the route that identity really has.
45
- this.embedded = embedded;
46
- this.log = log;
47
- this.allowed = allowed; // authorities a redirect_uri may name
48
- // Whether a request already passed the owner's door (its key or cookie):
49
- // an owner who opened the management page is the owner at the sign-in too.
50
- this.throughDoor = throughDoor;
51
- // The scheme this identity is reached on, when the socket cannot say —
52
- // a server behind a TLS proxy terminates cleartext and still is https.
53
- this.scheme = scheme;
54
- // Whether this deployment can serve the Mastodon streaming WebSocket. A
55
- // Node agent can; the in-browser service-worker facade cannot (it is
56
- // fetch-only), so it advertises NO streaming URL. Otherwise the client
57
- // opens wss://localhost/... (the worker has no request host to name), which
58
- // not only fails but, from a public origin, trips Chrome's private-network
59
- // permission prompt ("access other apps and services on this device").
60
- // With no streaming URL the client falls back to polling, which is served.
61
- this.streaming = streaming;
62
- // The same idea for two more capabilities the browser build does not have.
63
- // A client decides what to offer from what the instance document says, so
64
- // the honest thing is to say nothing rather than advertise and no-op.
65
- //
66
- // `webPush`: the browser build's web-push is a shim that mints a random
67
- // placeholder VAPID key and whose sendNotification does nothing. Advertised,
68
- // the client shows a notifications toggle that looks on and never fires.
69
- // Omit `vapid` and it hides the toggle instead.
70
- this.webPush = webPush;
71
- // `scheduling`: a scheduled post is only a stored row until something
72
- // publishes it when its time comes, and the only such tick is the Node
73
- // agent's (run-agent.mjs). Where nothing ticks, accepting one is silent
74
- // loss — the client says "scheduled" and the post never appears. Refusing
75
- // it is worse UX and better behaviour.
76
- this.scheduling = scheduling;
77
- this.authzAttempts = []; // password-attempt timestamps
78
- }
79
-
80
- get store() { return this.agent.store; }
81
- get urls() { return this.agent.publisher?.urls; }
82
- get push() {
83
- this._push ||= new Push({
84
- store: this.store,
85
- subject: () => this.urls?.actor || 'https://localhost/',
86
- log: this.log,
87
- });
88
- return this._push;
89
- }
90
- // The host in the owner's own address: the gateway's when the identity is
91
- // fronted (its documents still live on the pod, but its name does not).
92
- get host() {
93
- if (!this.urls) return 'unconfigured.invalid';
94
- return new URL(this.urls.publicHome || this.urls.base).host;
95
- }
96
-
97
- // Where the live feed is, as the CLIENT must address it: this agent's own
98
- // origin, taken from the request, not the pod's host. An instance document
99
- // that leaves it empty is not merely unhelpful — clients read it without a
100
- // guard and fall over, and every one of them loses live updates.
101
- streamingUrl(req) {
102
- if (!this.streaming) return null; // fetch-only facade: no WebSocket, no wss://localhost prompt
103
- const host = req?.headers?.host || `localhost:${this.port || ''}`;
104
- const secure = this.scheme
105
- ? this.scheme.startsWith('https')
106
- : req?.headers?.['x-forwarded-proto'] === 'https' || !!req?.socket?.encrypted;
107
- return `${secure ? 'wss' : 'ws'}://${host}/api/v1/streaming`;
108
- }
109
-
110
- static scopeFor(...a) { return oauth.scopeFor(...a); }
111
- static scopeAllows(...a) { return oauth.scopeAllows(...a); }
112
- static redirectMatches(...a) { return oauth.redirectMatches(...a); }
113
- static provesCode(...a) { return oauth.provesCode(...a); }
114
-
115
- // ---- request handling; returns true when handled ----
116
- async handle(req, res, pathname, url) {
117
- const send = (status, obj, headers = {}) => {
118
- const body = JSON.stringify(obj);
119
- res.writeHead(status, { 'content-type': 'application/json', ...headers });
120
- res.end(body);
121
- return true;
122
- };
123
- // The address the client reached, so every self-URL handed back — the
124
- // pagination links above all — names it rather than the pod's host.
125
- const scheme = String(this.scheme
126
- || (req.headers?.['x-forwarded-proto'] === 'https' || req.socket?.encrypted ? 'https' : 'http')).replace(/:.*$/, '');
127
- let self = url;
128
- try {
129
- self = new URL(`${scheme}://${req.headers?.host || 'localhost'}${this.mount || ''}${pathname}${url.search || ''}`);
130
- } catch { /* a Host nothing can parse: the links keep the placeholder origin */ }
131
- const ctx = { req, res, pathname, url: self, send };
132
-
133
- if (await oauth.handle(this, ctx)) return true;
134
- if (!pathname.startsWith('/api/')) return false;
135
- if (await instance.handle(this, ctx)) return true;
136
-
137
- // --- everything below needs a bearer token + a configured agent ---
138
- const bearer = this.tokenOf(req);
139
- if (!bearer) return send(401, { error: 'The access token is invalid' });
140
- // One gate for every client route below, rather than a check in each of
141
- // the fifty-odd branches — which is how the scope came to be recorded and
142
- // never consulted in the first place.
143
- const need = MastoApi.scopeFor(req.method, pathname);
144
- if (!MastoApi.scopeAllows(bearer.scope, need)) {
145
- this.log(`refused ${req.method} ${pathname}: token has "${bearer.scope}", needs "${need}"`);
146
- return send(403, { error: `This action is outside the authorized scopes (needs ${need})` });
147
- }
148
- if (!this.agent.configured()) return send(503, { error: 'agent not configured' });
149
- // A viewer-mode agent (another agent holds the drain lease) may not act —
150
- // but a user acting HERE outranks the idle active agent elsewhere, so a
151
- // write attempt claims the lease and proceeds. Only a failed claim 503s.
152
- if (this.agent.viewer && req.method !== 'GET' && req.method !== 'HEAD') {
153
- const took = await this.agent.requestTakeover?.();
154
- if (!took) return send(503, { error: 'another agent is active for this pod — takeover failed, try again' });
155
- }
156
-
157
- for (const area of [accounts, timelines, statuses, media]) {
158
- if (await area.handle(this, ctx)) return true;
159
- }
160
-
161
- this.log(`mastoapi: unhandled ${req.method} ${pathname} — punch list`);
162
- return send(404, { error: `Unimplemented: ${req.method} ${pathname}` });
163
- }
164
-
165
- // oauth.mjs
166
- tokenRecords(...a) { return oauth.tokenRecords(this, ...a); }
167
- tokens(...a) { return oauth.tokens(this, ...a); }
168
- mintToken(...a) { return oauth.mintToken(this, ...a); }
169
- apps(...a) { return oauth.apps(this, ...a); }
170
- authorizationServerMetadata(...a) { return oauth.authorizationServerMetadata(this, ...a); }
171
- findApp(...a) { return oauth.findApp(this, ...a); }
172
- resolveClientDocument(...a) { return oauth.resolveClientDocument(this, ...a); }
173
- registerApp(...a) { return oauth.registerApp(this, ...a); }
174
- mintCode(...a) { return oauth.mintCode(this, ...a); }
175
- consumeCode(...a) { return oauth.consumeCode(this, ...a); }
176
- tokenOf(...a) { return oauth.tokenOf(this, ...a); }
177
- authed(...a) { return oauth.authed(this, ...a); }
178
- redirectAllowed(...a) { return oauth.redirectAllowed(this, ...a); }
179
- rateLimited(...a) { return oauth.rateLimited(this, ...a); }
180
-
181
- // render.mjs
182
- selfAccount(...a) { return render.selfAccount(this, ...a); }
183
- account(...a) { return render.account(this, ...a); }
184
- page(...a) { return render.page(this, ...a); }
185
- bskyReply(...a) { return render.bskyReply(this, ...a); }
186
- acctAction(...a) { return render.acctAction(this, ...a); }
187
- acctReply(...a) { return render.acctReply(this, ...a); }
188
- status(...a) { return render.status(this, ...a); }
189
- quoteApproval(...a) { return render.quoteApproval(this, ...a); }
190
- filtersFor(...a) { return render.filtersFor(this, ...a); }
191
- lookup(...a) { return render.lookup(this, ...a); }
192
- statusOrBoost(...a) { return render.statusOrBoost(this, ...a); }
193
- pushNotify(...a) { return render.pushNotify(this, ...a); }
194
- scheduledJson(...a) { return render.scheduledJson(this, ...a); }
195
- pollJson(...a) { return render.pollJson(this, ...a); }
196
- mediaJson(...a) { return render.mediaJson(this, ...a); }
197
- relationship(...a) { return render.relationship(this, ...a); }
198
- notificationType(...a) { return render.notificationType(this, ...a); }
199
- notification(...a) { return render.notification(this, ...a); }
200
- accountSearch(...a) { return render.accountSearch(this, ...a); }
201
-
202
- // instance.mjs
203
- instanceTitle(...a) { return instance.instanceTitle(this, ...a); }
204
- tagObject(...a) { return instance.tagObject(this, ...a); }
205
- instanceBlurb(...a) { return instance.instanceBlurb(this, ...a); }
206
- }
@@ -1,112 +0,0 @@
1
- // instance.mjs — what the instance says about itself: the v1 and v2 instance
2
- // documents, the limits a client reads from them, the title and blurb, the
3
- // tag object, and the empty-collection stubs for endpoints a single-actor
4
- // instance has nothing to say to.
5
-
6
- import { TRANSPARENT_PNG } from './render.mjs';
7
- import {
8
- MAX_OPTIONS as POLL_MAX_OPTIONS, MAX_OPTION_CHARS as POLL_MAX_OPTION_CHARS,
9
- MIN_SECONDS as POLL_MIN_SECONDS, MAX_SECONDS as POLL_MAX_SECONDS,
10
- } from '../../core/polls.mjs';
11
-
12
- const STUBS = new Map(Object.entries({
13
- '/api/v1/filters': [],
14
- '/api/v1/custom_emojis': [],
15
- '/api/v1/announcements': [],
16
- '/api/v1/instance/peers': [],
17
- '/api/v1/trends/links': [],
18
- '/api/v2/suggestions': [],
19
- '/api/v1/preferences': {},
20
- })); // followed_tags is served live from the tag feed, not stubbed
21
-
22
- export function instanceConfig() {
23
- return {
24
- statuses: { max_characters: 5000, max_media_attachments: 4, characters_reserved_per_url: 23 },
25
- media_attachments: {
26
- supported_mime_types: ['image/jpeg', 'image/png', 'image/gif', 'image/webp',
27
- 'video/mp4', 'video/webm', 'audio/mpeg', 'audio/ogg'],
28
- image_size_limit: 10 * 1024 * 1024, video_size_limit: 40 * 1024 * 1024,
29
- image_matrix_limit: 16777216, video_matrix_limit: 2304000,
30
- },
31
- polls: {
32
- max_options: POLL_MAX_OPTIONS,
33
- max_characters_per_option: POLL_MAX_OPTION_CHARS,
34
- min_expiration: POLL_MIN_SECONDS,
35
- max_expiration: POLL_MAX_SECONDS,
36
- },
37
- accounts: { max_featured_tags: 0 },
38
- };
39
- }
40
-
41
- // Every agent used to report title 'solid-activitypub', so a client holding two
42
- // of them showed two identical instances and you had to read the acct to tell
43
- // them apart. The title is free text no client parses — make it say who.
44
- export function instanceTitle(api) {
45
- const cfg = api.store.getConfig();
46
- return cfg?.handle ? `@${cfg.handle}@${api.host}` : 'FediPod';
47
- }
48
-
49
- // A Mastodon Tag object. The client reads `following` in its Followed
50
- // Hashtags view and toggles it with the follow/unfollow endpoints. No usage
51
- // history — a single-actor instance has no firehose stats to report.
52
- export function tagObject(api, name, following, req, history = []) {
53
- const host = req?.headers?.host || api.host;
54
- return { name, url: `https://${host}/tags/${name}`, history, following: !!following };
55
- }
56
-
57
- export function instanceBlurb(api) {
58
- const kind = api.store.getConfig()?.kind === 'group' ? 'group' : 'actor';
59
- return `Solid pod ActivityPub ${kind}`;
60
- }
61
-
62
- // The Mastodon API version this facade answers to. Clients read it for what
63
- // the server can do beyond the version string: grouped notifications from 2,
64
- // a filter's blur action from 5, quote posts from 7. Everything up to 7 is
65
- // served here; nothing past it is claimed.
66
- const API_VERSIONS = { mastodon: 7 };
67
-
68
- export async function handle(api, ctx) {
69
- const { req, res, pathname, url, send } = ctx; // eslint-disable-line no-unused-vars
70
-
71
- // --- instance (public) ---
72
- if (pathname === '/api/v1/instance') {
73
- const su = api.streamingUrl(req);
74
- return send(200, {
75
- uri: api.host, title: api.instanceTitle(), short_description: api.instanceBlurb(),
76
- description: api.instanceBlurb(), email: '', version: '4.2.0 (compatible; fedipod)',
77
- api_versions: API_VERSIONS,
78
- urls: su ? { streaming_api: su } : {},
79
- stats: { user_count: 1, status_count: api.store.countStatuses(), domain_count: 1 },
80
- languages: ['en'], registrations: false, approval_required: false, invites_enabled: false,
81
- configuration: instanceConfig(),
82
- contact_account: null, rules: [],
83
- });
84
- }
85
- if (pathname === '/api/v2/instance') {
86
- const su = api.streamingUrl(req);
87
- return send(200, {
88
- domain: api.host, title: api.instanceTitle(), version: '4.2.0 (compatible; fedipod)',
89
- api_versions: API_VERSIONS,
90
- source_url: 'https://github.com/jeff-zucker/FediPod', description: api.instanceBlurb(),
91
- usage: { users: { active_month: 1 } },
92
- thumbnail: { url: TRANSPARENT_PNG },
93
- languages: ['en'],
94
- // Both spellings: v2 clients read configuration.urls.streaming, older
95
- // ones the top-level urls.streaming_api, and some fall back blindly.
96
- // Omitted entirely when there is no streaming, so the client polls.
97
- urls: su ? { streaming_api: su } : {},
98
- configuration: {
99
- ...instanceConfig(),
100
- ...(su ? { urls: { streaming: su } } : {}),
101
- ...(api.webPush ? { vapid: { public_key: api.push.publicKey() } } : {}),
102
- },
103
- registrations: { enabled: false, approval_required: false, message: null },
104
- contact: { email: '', account: null }, rules: [],
105
- });
106
- }
107
-
108
- const stub = STUBS.get(pathname);
109
- if (stub !== undefined && req.method === 'GET') return send(200, stub);
110
-
111
- return false;
112
- }
@@ -1,79 +0,0 @@
1
- // media.mjs — an upload on its way to the pod's media container: what an
2
- // attachment is allowed to be and the two media endpoints. The multipart
3
- // reader moved to body.mjs, which is where a client's body is read.
4
-
5
- import crypto from 'node:crypto';
6
- import * as podMedia from '../../pod/media.mjs';
7
- import { readBody, readMultipart } from './body.mjs';
8
-
9
- // What an attachment is allowed to BE. Anything else is stored as bytes, which
10
- // a browser downloads rather than runs.
11
- const ATTACHMENT_KINDS = new Set(['image', 'video', 'audio']);
12
- // image/* with an exception: an SVG is a document, it carries script, and a
13
- // browser renders it rather than showing it. Mastodon does not take them as
14
- // media either.
15
- const NEVER = new Set(['image/svg+xml', 'image/svg']);
16
- const OPAQUE = 'application/octet-stream';
17
-
18
- export function attachmentType(claimed) {
19
- const t = String(claimed || '').split(';')[0].trim().toLowerCase();
20
- if (!/^[a-z0-9.+-]+\/[a-z0-9.+-]+$/.test(t) || NEVER.has(t)) return OPAQUE;
21
- return ATTACHMENT_KINDS.has(t.split('/')[0]) ? t : OPAQUE;
22
- }
23
-
24
- // From the TYPE we accepted, not from the name the client sent — an `.html`
25
- // suffix on a file stored as octet-stream is what a pod would serve from, and
26
- // a filename is the client's to choose.
27
- export function extensionFor(mediaType, filename = '') {
28
- if (mediaType === OPAQUE) return 'bin';
29
- const sub = mediaType.split('/')[1].replace(/[^a-z0-9]/g, '');
30
- const given = String(filename || '').includes('.')
31
- ? filename.split('.').pop().toLowerCase().replace(/[^a-z0-9]/g, '') : '';
32
- // Keep the client's suffix only when it plainly belongs to the accepted type,
33
- // so jpg/jpeg and mp4/m4v survive without a table of every media type.
34
- return given && (given === sub || sub.startsWith(given) || given.startsWith(sub)) ? given : (sub || 'bin');
35
- }
36
-
37
- export async function handle(api, ctx) {
38
- const { req, res, pathname, url, send } = ctx; // eslint-disable-line no-unused-vars
39
-
40
- // Media upload: file → remote pod /ap/media/ (public-Read), entry in the
41
- // media registry so a later POST /statuses can attach it.
42
- if ((pathname === '/api/v2/media' || pathname === '/api/v1/media') && req.method === 'POST') {
43
- const { fields, file } = await readMultipart(req);
44
- if (!file?.data?.length) return send(422, { error: 'file required' });
45
- // The client said what this is, and we used to believe it. The media
46
- // container is world-readable and sits on the pod's own origin — the same
47
- // origin as the WebID and the ACLs — so a file stored as text/html is a
48
- // page served from your identity, and script in it runs as you in any
49
- // browser already logged into that pod. A bearer is not "only you": the
50
- // facade exists so third-party clients can connect, tokens last 90 days,
51
- // and no scope is enforced. So any client you authorize could leave that
52
- // page behind.
53
- const mediaType = attachmentType(file.contentType);
54
- const ext = extensionFor(mediaType, file.filename);
55
- const slug = new Date().toISOString().slice(0, 10) + '-' + crypto.randomBytes(4).toString('hex') + '.' + ext;
56
- const mediaUrl = api.urls.media + slug;
57
- await api.agent.publisher.ensureMediaContainer();
58
- await podMedia.write(api.agent.remote, mediaUrl, file.data, mediaType);
59
- const entry = { url: mediaUrl, mediaType, description: fields.description || '' };
60
- const id = api.store.idFor(mediaUrl);
61
- api.store.setMedia(id, entry);
62
- return send(200, api.mediaJson({ id, ...entry }));
63
- }
64
- const mMedia = /^\/api\/v1\/media\/([a-f0-9]+)$/.exec(pathname);
65
- if (mMedia) {
66
- const entry = api.store.getMedia()[mMedia[1]];
67
- if (!entry) return send(404, { error: 'Record not found' });
68
- if (req.method === 'PUT') {
69
- const body = await readBody(req);
70
- if (typeof body.description === 'string') {
71
- entry.description = body.description;
72
- api.store.setMedia(mMedia[1], entry);
73
- }
74
- }
75
- return send(200, api.mediaJson({ id: mMedia[1], ...entry }));
76
- }
77
-
78
- return false;
79
- }