@atproto/bsky 0.0.79 → 0.0.81

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 (114) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/api/app/bsky/feed/getQuotes.d.ts.map +1 -1
  3. package/dist/api/app/bsky/feed/getQuotes.js +3 -1
  4. package/dist/api/app/bsky/feed/getQuotes.js.map +1 -1
  5. package/dist/config.d.ts +4 -0
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +12 -0
  8. package/dist/config.js.map +1 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +8 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/lexicon/index.d.ts +11 -0
  13. package/dist/lexicon/index.d.ts.map +1 -1
  14. package/dist/lexicon/index.js +32 -1
  15. package/dist/lexicon/index.js.map +1 -1
  16. package/dist/lexicon/lexicons.d.ts +346 -18
  17. package/dist/lexicon/lexicons.d.ts.map +1 -1
  18. package/dist/lexicon/lexicons.js +364 -24
  19. package/dist/lexicon/lexicons.js.map +1 -1
  20. package/dist/lexicon/types/app/bsky/embed/defs.d.ts +13 -0
  21. package/dist/lexicon/types/app/bsky/embed/defs.d.ts.map +1 -0
  22. package/dist/lexicon/types/app/bsky/embed/defs.js +16 -0
  23. package/dist/lexicon/types/app/bsky/embed/defs.js.map +1 -0
  24. package/dist/lexicon/types/app/bsky/embed/images.d.ts +3 -10
  25. package/dist/lexicon/types/app/bsky/embed/images.d.ts.map +1 -1
  26. package/dist/lexicon/types/app/bsky/embed/images.js +1 -11
  27. package/dist/lexicon/types/app/bsky/embed/images.js.map +1 -1
  28. package/dist/lexicon/types/app/bsky/embed/record.d.ts +2 -1
  29. package/dist/lexicon/types/app/bsky/embed/record.d.ts.map +1 -1
  30. package/dist/lexicon/types/app/bsky/embed/record.js.map +1 -1
  31. package/dist/lexicon/types/app/bsky/embed/recordWithMedia.d.ts +3 -2
  32. package/dist/lexicon/types/app/bsky/embed/recordWithMedia.d.ts.map +1 -1
  33. package/dist/lexicon/types/app/bsky/embed/recordWithMedia.js.map +1 -1
  34. package/dist/lexicon/types/app/bsky/embed/video.d.ts +33 -0
  35. package/dist/lexicon/types/app/bsky/embed/video.d.ts.map +1 -0
  36. package/dist/lexicon/types/app/bsky/embed/video.js +35 -0
  37. package/dist/lexicon/types/app/bsky/embed/video.js.map +1 -0
  38. package/dist/lexicon/types/app/bsky/feed/defs.d.ts +2 -1
  39. package/dist/lexicon/types/app/bsky/feed/defs.d.ts.map +1 -1
  40. package/dist/lexicon/types/app/bsky/feed/defs.js.map +1 -1
  41. package/dist/lexicon/types/app/bsky/feed/post.d.ts +2 -1
  42. package/dist/lexicon/types/app/bsky/feed/post.d.ts.map +1 -1
  43. package/dist/lexicon/types/app/bsky/feed/post.js.map +1 -1
  44. package/dist/lexicon/types/app/bsky/video/defs.d.ts +19 -0
  45. package/dist/lexicon/types/app/bsky/video/defs.d.ts.map +1 -0
  46. package/dist/lexicon/types/app/bsky/video/defs.js +16 -0
  47. package/dist/lexicon/types/app/bsky/video/defs.js.map +1 -0
  48. package/dist/lexicon/types/app/bsky/video/getJobStatus.d.ts +36 -0
  49. package/dist/lexicon/types/app/bsky/video/getJobStatus.d.ts.map +1 -0
  50. package/dist/lexicon/types/app/bsky/video/getJobStatus.js +3 -0
  51. package/dist/lexicon/types/app/bsky/video/getJobStatus.js.map +1 -0
  52. package/dist/lexicon/types/app/bsky/video/getUploadLimits.d.ts +38 -0
  53. package/dist/lexicon/types/app/bsky/video/getUploadLimits.d.ts.map +1 -0
  54. package/dist/lexicon/types/app/bsky/video/getUploadLimits.js +3 -0
  55. package/dist/lexicon/types/app/bsky/video/getUploadLimits.js.map +1 -0
  56. package/dist/lexicon/types/app/bsky/video/uploadVideo.d.ts +41 -0
  57. package/dist/lexicon/types/app/bsky/video/uploadVideo.d.ts.map +1 -0
  58. package/dist/lexicon/types/app/bsky/video/uploadVideo.js +3 -0
  59. package/dist/lexicon/types/app/bsky/video/uploadVideo.js.map +1 -0
  60. package/dist/lexicon/types/com/atproto/repo/applyWrites.d.ts +38 -4
  61. package/dist/lexicon/types/com/atproto/repo/applyWrites.d.ts.map +1 -1
  62. package/dist/lexicon/types/com/atproto/repo/applyWrites.js +31 -1
  63. package/dist/lexicon/types/com/atproto/repo/applyWrites.js.map +1 -1
  64. package/dist/lexicon/types/com/atproto/repo/createRecord.d.ts +5 -2
  65. package/dist/lexicon/types/com/atproto/repo/createRecord.d.ts.map +1 -1
  66. package/dist/lexicon/types/com/atproto/repo/defs.d.ts +12 -0
  67. package/dist/lexicon/types/com/atproto/repo/defs.d.ts.map +1 -0
  68. package/dist/lexicon/types/com/atproto/repo/defs.js +16 -0
  69. package/dist/lexicon/types/com/atproto/repo/defs.js.map +1 -0
  70. package/dist/lexicon/types/com/atproto/repo/deleteRecord.d.ts +14 -2
  71. package/dist/lexicon/types/com/atproto/repo/deleteRecord.d.ts.map +1 -1
  72. package/dist/lexicon/types/com/atproto/repo/putRecord.d.ts +5 -2
  73. package/dist/lexicon/types/com/atproto/repo/putRecord.d.ts.map +1 -1
  74. package/dist/views/index.d.ts +5 -2
  75. package/dist/views/index.d.ts.map +1 -1
  76. package/dist/views/index.js +24 -1
  77. package/dist/views/index.js.map +1 -1
  78. package/dist/views/types.d.ts +5 -2
  79. package/dist/views/types.d.ts.map +1 -1
  80. package/dist/views/types.js +3 -1
  81. package/dist/views/types.js.map +1 -1
  82. package/dist/views/util.d.ts +15 -0
  83. package/dist/views/util.d.ts.map +1 -1
  84. package/dist/views/util.js +42 -1
  85. package/dist/views/util.js.map +1 -1
  86. package/package.json +4 -4
  87. package/src/api/app/bsky/feed/getQuotes.ts +4 -1
  88. package/src/config.ts +17 -0
  89. package/src/index.ts +10 -1
  90. package/src/lexicon/index.ts +46 -0
  91. package/src/lexicon/lexicons.ts +367 -25
  92. package/src/lexicon/types/app/bsky/embed/defs.ts +26 -0
  93. package/src/lexicon/types/app/bsky/embed/images.ts +3 -21
  94. package/src/lexicon/types/app/bsky/embed/record.ts +2 -0
  95. package/src/lexicon/types/app/bsky/embed/recordWithMedia.ts +3 -0
  96. package/src/lexicon/types/app/bsky/embed/video.ts +67 -0
  97. package/src/lexicon/types/app/bsky/feed/defs.ts +2 -0
  98. package/src/lexicon/types/app/bsky/feed/post.ts +2 -0
  99. package/src/lexicon/types/app/bsky/video/defs.ts +32 -0
  100. package/src/lexicon/types/app/bsky/video/getJobStatus.ts +46 -0
  101. package/src/lexicon/types/app/bsky/video/getUploadLimits.ts +47 -0
  102. package/src/lexicon/types/app/bsky/video/uploadVideo.ts +48 -0
  103. package/src/lexicon/types/com/atproto/repo/applyWrites.ts +70 -3
  104. package/src/lexicon/types/com/atproto/repo/createRecord.ts +5 -2
  105. package/src/lexicon/types/com/atproto/repo/defs.ts +25 -0
  106. package/src/lexicon/types/com/atproto/repo/deleteRecord.ts +13 -1
  107. package/src/lexicon/types/com/atproto/repo/putRecord.ts +5 -2
  108. package/src/views/index.ts +30 -3
  109. package/src/views/types.ts +16 -1
  110. package/src/views/util.ts +24 -0
  111. package/tests/_util.ts +9 -0
  112. package/tests/views/__snapshots__/posts.test.ts.snap +190 -0
  113. package/tests/views/posts.test.ts +75 -0
  114. package/tests/views/quotes.test.ts +15 -0
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/views/types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,IAAI,WAAW,EACnB,IAAI,IAAI,eAAe,EACxB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EACL,IAAI,IAAI,aAAa,EACrB,IAAI,IAAI,iBAAiB,EAC1B,MAAM,0CAA0C,CAAA;AACjD,OAAO,EACL,IAAI,IAAI,WAAW,EACnB,IAAI,IAAI,eAAe,EACvB,UAAU,IAAI,aAAa,EAC5B,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EACL,IAAI,IAAI,eAAe,EACvB,IAAI,IAAI,mBAAmB,EAC5B,MAAM,iDAAiD,CAAA;AACxD,OAAO,EACL,WAAW,EACX,aAAa,EACb,YAAY,EACZ,QAAQ,EACT,MAAM,qCAAqC,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAEpE,YAAY,EACV,IAAI,IAAI,WAAW,EACnB,IAAI,IAAI,eAAe,GACxB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAChF,YAAY,EACV,IAAI,IAAI,aAAa,EACrB,IAAI,IAAI,iBAAiB,GAC1B,MAAM,0CAA0C,CAAA;AACjD,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,0CAA0C,CAAA;AACpF,YAAY,EACV,IAAI,IAAI,WAAW,EACnB,IAAI,IAAI,eAAe,EACvB,WAAW,IAAI,YAAY,EAC3B,YAAY,IAAI,aAAa,EAC7B,YAAY,IAAI,aAAa,EAC7B,UAAU,IAAI,aAAa,GAC5B,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAChF,YAAY,EACV,IAAI,IAAI,eAAe,EACvB,IAAI,IAAI,mBAAmB,GAC5B,MAAM,iDAAiD,CAAA;AACxD,OAAO,EAAE,MAAM,IAAI,iBAAiB,EAAE,MAAM,iDAAiD,CAAA;AAC7F,YAAY,EAAE,IAAI,IAAI,wBAAwB,EAAE,MAAM,iDAAiD,CAAA;AACvG,YAAY,EACV,WAAW,EACX,aAAa,EACb,YAAY,EACZ,QAAQ,GACT,MAAM,qCAAqC,CAAA;AAC5C,YAAY,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAA;AAEpE,YAAY,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,0DAA0D,CAAA;AAEhH,MAAM,MAAM,KAAK,GAAG,WAAW,GAAG,aAAa,GAAG,WAAW,GAAG,eAAe,CAAA;AAE/E,MAAM,MAAM,SAAS,GACjB,eAAe,GACf,iBAAiB,GACjB,eAAe,GACf,mBAAmB,CAAA;AAEvB,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,YAAY,GAAG,WAAW,CAAA;AAEjE,MAAM,MAAM,uBAAuB,GAC/B,aAAa,GACb,aAAa,GACb,QAAQ,GACR,WAAW,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/views/types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,IAAI,WAAW,EACnB,IAAI,IAAI,eAAe,EACxB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EACL,IAAI,IAAI,UAAU,EAClB,IAAI,IAAI,cAAc,EACvB,MAAM,uCAAuC,CAAA;AAC9C,OAAO,EACL,IAAI,IAAI,aAAa,EACrB,IAAI,IAAI,iBAAiB,EAC1B,MAAM,0CAA0C,CAAA;AACjD,OAAO,EACL,IAAI,IAAI,WAAW,EACnB,IAAI,IAAI,eAAe,EACvB,UAAU,IAAI,aAAa,EAC5B,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EACL,IAAI,IAAI,eAAe,EACvB,IAAI,IAAI,mBAAmB,EAC5B,MAAM,iDAAiD,CAAA;AACxD,OAAO,EACL,WAAW,EACX,aAAa,EACb,YAAY,EACZ,QAAQ,EACT,MAAM,qCAAqC,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAEpE,YAAY,EACV,IAAI,IAAI,WAAW,EACnB,IAAI,IAAI,eAAe,GACxB,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAChF,YAAY,EACV,IAAI,IAAI,UAAU,EAClB,IAAI,IAAI,cAAc,GACvB,MAAM,uCAAuC,CAAA;AAC9C,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,uCAAuC,CAAA;AAC9E,YAAY,EACV,IAAI,IAAI,aAAa,EACrB,IAAI,IAAI,iBAAiB,GAC1B,MAAM,0CAA0C,CAAA;AACjD,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,0CAA0C,CAAA;AACpF,YAAY,EACV,IAAI,IAAI,WAAW,EACnB,IAAI,IAAI,eAAe,EACvB,WAAW,IAAI,YAAY,EAC3B,YAAY,IAAI,aAAa,EAC7B,YAAY,IAAI,aAAa,EAC7B,UAAU,IAAI,aAAa,GAC5B,MAAM,wCAAwC,CAAA;AAC/C,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAChF,YAAY,EACV,IAAI,IAAI,eAAe,EACvB,IAAI,IAAI,mBAAmB,GAC5B,MAAM,iDAAiD,CAAA;AACxD,OAAO,EAAE,MAAM,IAAI,iBAAiB,EAAE,MAAM,iDAAiD,CAAA;AAC7F,YAAY,EAAE,IAAI,IAAI,wBAAwB,EAAE,MAAM,iDAAiD,CAAA;AACvG,YAAY,EACV,WAAW,EACX,aAAa,EACb,YAAY,EACZ,QAAQ,GACT,MAAM,qCAAqC,CAAA;AAC5C,YAAY,EAAE,QAAQ,EAAE,MAAM,sCAAsC,CAAA;AAEpE,YAAY,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,0DAA0D,CAAA;AAEhH,MAAM,MAAM,KAAK,GACb,WAAW,GACX,UAAU,GACV,aAAa,GACb,WAAW,GACX,eAAe,CAAA;AAEnB,MAAM,MAAM,SAAS,GACjB,eAAe,GACf,cAAc,GACd,iBAAiB,GACjB,eAAe,GACf,mBAAmB,CAAA;AAEvB,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,YAAY,GAAG,WAAW,CAAA;AAEjE,MAAM,MAAM,uBAAuB,GAC/B,aAAa,GACb,aAAa,GACb,QAAQ,GACR,WAAW,CAAA"}
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isRecordWithMedia = exports.isRecordEmbed = exports.isExternalEmbed = exports.isImagesEmbed = void 0;
3
+ exports.isRecordWithMedia = exports.isRecordEmbed = exports.isExternalEmbed = exports.isVideoEmbed = exports.isImagesEmbed = void 0;
4
4
  var images_1 = require("../lexicon/types/app/bsky/embed/images");
5
5
  Object.defineProperty(exports, "isImagesEmbed", { enumerable: true, get: function () { return images_1.isMain; } });
6
+ var video_1 = require("../lexicon/types/app/bsky/embed/video");
7
+ Object.defineProperty(exports, "isVideoEmbed", { enumerable: true, get: function () { return video_1.isMain; } });
6
8
  var external_1 = require("../lexicon/types/app/bsky/embed/external");
7
9
  Object.defineProperty(exports, "isExternalEmbed", { enumerable: true, get: function () { return external_1.isMain; } });
8
10
  var record_1 = require("../lexicon/types/app/bsky/embed/record");
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/views/types.ts"],"names":[],"mappings":";;;AA8BA,iEAAgF;AAAvE,uGAAA,MAAM,OAAiB;AAKhC,qEAAoF;AAA3E,2GAAA,MAAM,OAAmB;AASlC,iEAAgF;AAAvE,uGAAA,MAAM,OAAiB;AAKhC,mFAA6F;AAApF,oHAAA,MAAM,OAAqB"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/views/types.ts"],"names":[],"mappings":";;;AAkCA,iEAAgF;AAAvE,uGAAA,MAAM,OAAiB;AAKhC,+DAA8E;AAArE,qGAAA,MAAM,OAAgB;AAK/B,qEAAoF;AAA3E,2GAAA,MAAM,OAAmB;AASlC,iEAAgF;AAAvE,uGAAA,MAAM,OAAiB;AAKhC,mFAA6F;AAApF,oHAAA,MAAM,OAAqB"}
@@ -20,5 +20,20 @@ type ParsedPostgate = {
20
20
  canEmbed: boolean;
21
21
  };
22
22
  };
23
+ export declare class VideoUriBuilder {
24
+ private opts;
25
+ constructor(opts: {
26
+ playlistUrlPattern: string;
27
+ thumbnailUrlPattern: string;
28
+ });
29
+ playlist({ did, cid }: {
30
+ did: string;
31
+ cid: string;
32
+ }): string;
33
+ thumbnail({ did, cid }: {
34
+ did: string;
35
+ cid: string;
36
+ }): string;
37
+ }
23
38
  export {};
24
39
  //# sourceMappingURL=util.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/views/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC1C,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,qCAAqC,CAAA;AAC1E,OAAO,EACL,MAAM,IAAI,UAAU,EAIrB,MAAM,2CAA2C,CAAA;AAClD,OAAO,EACL,MAAM,IAAI,cAAc,EAEzB,MAAM,yCAAyC,CAAA;AAGhD,eAAO,MAAM,eAAe,eACd,MAAM,YACR,MAAM,YACN,UAAU,GAAG,IAAI,QACrB,UAAU,GAAG,IAAI,KACtB,gBAyBF,CAAA;AAED,KAAK,gBAAgB,GAAG;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;CACzB,CAAA;AAED,eAAO,MAAM,eAAe,SAAU,OAAO,WAS5C,CAAA;AAED,eAAO,MAAM,aAAa,oCAIvB;IACD,IAAI,EAAE,cAAc,GAAG,SAAS,CAAA;IAChC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;CAClB,KAAG,cAeH,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,cAAc,EAAE;QACd,QAAQ,EAAE,OAAO,CAAA;KAClB,CAAA;CACF,CAAA"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../src/views/util.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC1C,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,qCAAqC,CAAA;AAC1E,OAAO,EACL,MAAM,IAAI,UAAU,EAIrB,MAAM,2CAA2C,CAAA;AAClD,OAAO,EACL,MAAM,IAAI,cAAc,EAEzB,MAAM,yCAAyC,CAAA;AAGhD,eAAO,MAAM,eAAe,eACd,MAAM,YACR,MAAM,YACN,UAAU,GAAG,IAAI,QACrB,UAAU,GAAG,IAAI,KACtB,gBAyBF,CAAA;AAED,KAAK,gBAAgB,GAAG;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;CACzB,CAAA;AAED,eAAO,MAAM,eAAe,SAAU,OAAO,WAS5C,CAAA;AAED,eAAO,MAAM,aAAa,oCAIvB;IACD,IAAI,EAAE,cAAc,GAAG,SAAS,CAAA;IAChC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,SAAS,EAAE,MAAM,CAAA;CAClB,KAAG,cAeH,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,cAAc,EAAE;QACd,QAAQ,EAAE,OAAO,CAAA;KAClB,CAAA;CACF,CAAA;AAED,qBAAa,eAAe;IAExB,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE;QACZ,kBAAkB,EAAE,MAAM,CAAA;QAC1B,mBAAmB,EAAE,MAAM,CAAA;KAC5B;IAEH,QAAQ,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;IAOnD,SAAS,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;CAOrD"}
@@ -1,6 +1,30 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parsePostgate = exports.cidFromBlobJson = exports.parseThreadGate = void 0;
26
+ exports.VideoUriBuilder = exports.parsePostgate = exports.cidFromBlobJson = exports.parseThreadGate = void 0;
27
+ const util = __importStar(require("node:util"));
4
28
  const lexicon_1 = require("@atproto/lexicon");
5
29
  const threadgate_1 = require("../lexicon/types/app/bsky/feed/threadgate");
6
30
  const postgate_1 = require("../lexicon/types/app/bsky/feed/postgate");
@@ -54,4 +78,21 @@ const parsePostgate = ({ gate, viewerDid, authorDid, }) => {
54
78
  return { embeddingRules: { canEmbed: true } };
55
79
  };
56
80
  exports.parsePostgate = parsePostgate;
81
+ class VideoUriBuilder {
82
+ constructor(opts) {
83
+ Object.defineProperty(this, "opts", {
84
+ enumerable: true,
85
+ configurable: true,
86
+ writable: true,
87
+ value: opts
88
+ });
89
+ }
90
+ playlist({ did, cid }) {
91
+ return util.format(this.opts.playlistUrlPattern, encodeURIComponent(did), encodeURIComponent(cid));
92
+ }
93
+ thumbnail({ did, cid }) {
94
+ return util.format(this.opts.thumbnailUrlPattern, encodeURIComponent(did), encodeURIComponent(cid));
95
+ }
96
+ }
97
+ exports.VideoUriBuilder = VideoUriBuilder;
57
98
  //# sourceMappingURL=util.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/views/util.ts"],"names":[],"mappings":";;;AAAA,8CAA0C;AAE1C,0EAKkD;AAClD,sEAGgD;AAChD,oEAAoE;AAE7D,MAAM,eAAe,GAAG,CAC7B,UAAkB,EAClB,QAAgB,EAChB,QAA2B,EAC3B,IAAuB,EACL,EAAE;IACpB,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;IAC3B,CAAC;IACD,yGAAyG;IACzG,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACzB,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;IAC3B,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,0BAAa,CAAC,CAAA;IACpD,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,4BAAe,CAAC,CAAA;IACvD,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,uBAAU,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAE7E,wDAAwD;IACxD,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,WAAW,GAAG,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YACnD,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CACxB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,iBAAS,EAAC,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG,KAAK,UAAU,CACrD,CAAA;QACH,CAAC,CAAC,CAAA;QACF,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,CAAA;QACzE,CAAC;IACH,CAAC;IACD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,CAAA;AACzD,CAAC,CAAA;AA9BY,QAAA,eAAe,mBA8B3B;AASM,MAAM,eAAe,GAAG,CAAC,IAAa,EAAE,EAAE;IAC/C,IAAI,IAAI,YAAY,iBAAO,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAA;IAC5B,CAAC;IACD,oGAAoG;IACpG,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC;QAC7B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAW,CAAA;IACjD,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAW,CAAA;AACtC,CAAC,CAAA;AATY,QAAA,eAAe,mBAS3B;AAEM,MAAM,aAAa,GAAG,CAAC,EAC5B,IAAI,EACJ,SAAS,EACT,SAAS,GAKV,EAAkB,EAAE;IACnB,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAA;IAC/C,CAAC;IACD,yCAAyC;IACzC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QAClC,OAAO,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAA;IAC/C,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,wBAAqB,CAAC,CAAA;IAChE,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAA;IAChD,CAAC;IAED,OAAO,EAAE,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAA;AAC/C,CAAC,CAAA;AAvBY,QAAA,aAAa,iBAuBzB"}
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/views/util.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/bsky",
3
- "version": "0.0.79",
3
+ "version": "0.0.81",
4
4
  "license": "MIT",
5
5
  "description": "Reference implementation of app.bsky App View (Bluesky API)",
6
6
  "keywords": [
@@ -40,7 +40,7 @@
40
40
  "structured-headers": "^1.0.1",
41
41
  "typed-emitter": "^2.1.0",
42
42
  "uint8arrays": "3.0.0",
43
- "@atproto/api": "^0.13.4",
43
+ "@atproto/api": "^0.13.6",
44
44
  "@atproto/common": "^0.4.1",
45
45
  "@atproto/crypto": "^0.4.1",
46
46
  "@atproto/identity": "^0.4.1",
@@ -62,9 +62,9 @@
62
62
  "axios": "^0.27.2",
63
63
  "jest": "^28.1.2",
64
64
  "ts-node": "^10.8.2",
65
- "@atproto/api": "^0.13.4",
65
+ "@atproto/api": "^0.13.6",
66
66
  "@atproto/lex-cli": "^0.5.0",
67
- "@atproto/pds": "^0.4.54",
67
+ "@atproto/pds": "^0.4.57",
68
68
  "@atproto/xrpc": "^0.6.1"
69
69
  },
70
70
  "scripts": {
@@ -1,3 +1,4 @@
1
+ import { AtUri } from '@atproto/syntax'
1
2
  import { Server } from '../../../../lexicon'
2
3
  import AppContext from '../../../../context'
3
4
  import { createPipeline } from '../../../../pipeline'
@@ -11,6 +12,7 @@ import { Views } from '../../../../views'
11
12
  import { mapDefined } from '@atproto/common'
12
13
  import { QueryParams } from '../../../../lexicon/types/app/bsky/feed/getQuotes'
13
14
  import { parseString } from '../../../../hydration/util'
15
+ import { uriToDid } from '../../../../util/uris'
14
16
 
15
17
  export default function (server: Server, ctx: AppContext) {
16
18
  const getQuotes = createPipeline(skeleton, hydration, noBlocks, presentation)
@@ -73,7 +75,8 @@ const noBlocks = (inputs: {
73
75
  const { ctx, skeleton, hydration } = inputs
74
76
  skeleton.uris = skeleton.uris.filter((uri) => {
75
77
  const embedBlock = hydration.postBlocks?.get(uri)?.embed
76
- return !ctx.views.viewerBlockExists(uri, hydration) && !embedBlock
78
+ const authorDid = uriToDid(uri)
79
+ return !ctx.views.viewerBlockExists(authorDid, hydration) && !embedBlock
77
80
  })
78
81
  return skeleton
79
82
  }
package/src/config.ts CHANGED
@@ -24,6 +24,8 @@ export interface ServerConfigValues {
24
24
  suggestionsUrl?: string
25
25
  suggestionsApiKey?: string
26
26
  cdnUrl?: string
27
+ videoPlaylistUrlPattern?: string
28
+ videoThumbnailUrlPattern?: string
27
29
  blobRateLimitBypassKey?: string
28
30
  blobRateLimitBypassHostname?: string
29
31
  // identity
@@ -58,6 +60,11 @@ export class ServerConfig {
58
60
  ? process.env.BSKY_HANDLE_RESOLVE_NAMESERVERS.split(',')
59
61
  : []
60
62
  const cdnUrl = process.env.BSKY_CDN_URL || process.env.BSKY_IMG_URI_ENDPOINT
63
+ // e.g. https://video.invalid/watch/%s/%s/playlist.m3u8
64
+ const videoPlaylistUrlPattern = process.env.BSKY_VIDEO_PLAYLIST_URL_PATTERN
65
+ // e.g. https://video.invalid/watch/%s/%s/thumbnail.jpg
66
+ const videoThumbnailUrlPattern =
67
+ process.env.BSKY_VIDEO_THUMBNAIL_URL_PATTERN
61
68
  const blobCacheLocation = process.env.BSKY_BLOB_CACHE_LOC
62
69
  const searchUrl =
63
70
  process.env.BSKY_SEARCH_URL ||
@@ -129,6 +136,8 @@ export class ServerConfig {
129
136
  labelsFromIssuerDids,
130
137
  handleResolveNameservers,
131
138
  cdnUrl,
139
+ videoPlaylistUrlPattern,
140
+ videoThumbnailUrlPattern,
132
141
  blobCacheLocation,
133
142
  bsyncUrl,
134
143
  bsyncApiKey,
@@ -245,6 +254,14 @@ export class ServerConfig {
245
254
  return this.cfg.cdnUrl
246
255
  }
247
256
 
257
+ get videoPlaylistUrlPattern() {
258
+ return this.cfg.videoPlaylistUrlPattern
259
+ }
260
+
261
+ get videoThumbnailUrlPattern() {
262
+ return this.cfg.videoThumbnailUrlPattern
263
+ }
264
+
248
265
  get blobRateLimitBypassKey() {
249
266
  return this.cfg.blobRateLimitBypassKey
250
267
  }
package/src/index.ts CHANGED
@@ -24,6 +24,7 @@ import { AuthVerifier } from './auth-verifier'
24
24
  import { authWithApiKey as bsyncAuth, createBsyncClient } from './bsync'
25
25
  import { authWithApiKey as courierAuth, createCourierClient } from './courier'
26
26
  import { FeatureGates } from './feature-gates'
27
+ import { VideoUriBuilder } from './views/util'
27
28
 
28
29
  export * from './data-plane'
29
30
  export type { ServerConfigValues } from './config'
@@ -63,6 +64,14 @@ export class BskyAppView {
63
64
  const imgUriBuilder = new ImageUriBuilder(
64
65
  config.cdnUrl || `${config.publicUrl}/img`,
65
66
  )
67
+ const videoUriBuilder = new VideoUriBuilder({
68
+ playlistUrlPattern:
69
+ config.videoPlaylistUrlPattern ||
70
+ `${config.publicUrl}/vid/%s/%s/playlist.m3u8`,
71
+ thumbnailUrlPattern:
72
+ config.videoThumbnailUrlPattern ||
73
+ `${config.publicUrl}/vid/%s/%s/thumbnail.jpg`,
74
+ })
66
75
 
67
76
  let imgProcessingServer: ImageProcessingServer | undefined
68
77
  if (!config.cdnUrl) {
@@ -92,7 +101,7 @@ export class BskyAppView {
92
101
  rejectUnauthorized: !config.dataplaneIgnoreBadTls,
93
102
  })
94
103
  const hydrator = new Hydrator(dataplane, config.labelsFromIssuerDids)
95
- const views = new Views(imgUriBuilder)
104
+ const views = new Views(imgUriBuilder, videoUriBuilder)
96
105
 
97
106
  const bsyncClient = createBsyncClient({
98
107
  baseUrl: config.bsyncUrl,
@@ -139,6 +139,9 @@ import * as AppBskyUnspeccedGetSuggestionsSkeleton from './types/app/bsky/unspec
139
139
  import * as AppBskyUnspeccedGetTaggedSuggestions from './types/app/bsky/unspecced/getTaggedSuggestions'
140
140
  import * as AppBskyUnspeccedSearchActorsSkeleton from './types/app/bsky/unspecced/searchActorsSkeleton'
141
141
  import * as AppBskyUnspeccedSearchPostsSkeleton from './types/app/bsky/unspecced/searchPostsSkeleton'
142
+ import * as AppBskyVideoGetJobStatus from './types/app/bsky/video/getJobStatus'
143
+ import * as AppBskyVideoGetUploadLimits from './types/app/bsky/video/getUploadLimits'
144
+ import * as AppBskyVideoUploadVideo from './types/app/bsky/video/uploadVideo'
142
145
  import * as ChatBskyActorDeleteAccount from './types/chat/bsky/actor/deleteAccount'
143
146
  import * as ChatBskyActorExportAccountData from './types/chat/bsky/actor/exportAccountData'
144
147
  import * as ChatBskyConvoDeleteMessageForSelf from './types/chat/bsky/convo/deleteMessageForSelf'
@@ -1140,6 +1143,7 @@ export class AppBskyNS {
1140
1143
  notification: AppBskyNotificationNS
1141
1144
  richtext: AppBskyRichtextNS
1142
1145
  unspecced: AppBskyUnspeccedNS
1146
+ video: AppBskyVideoNS
1143
1147
 
1144
1148
  constructor(server: Server) {
1145
1149
  this._server = server
@@ -1151,6 +1155,7 @@ export class AppBskyNS {
1151
1155
  this.notification = new AppBskyNotificationNS(server)
1152
1156
  this.richtext = new AppBskyRichtextNS(server)
1153
1157
  this.unspecced = new AppBskyUnspeccedNS(server)
1158
+ this.video = new AppBskyVideoNS(server)
1154
1159
  }
1155
1160
  }
1156
1161
 
@@ -1834,6 +1839,47 @@ export class AppBskyUnspeccedNS {
1834
1839
  }
1835
1840
  }
1836
1841
 
1842
+ export class AppBskyVideoNS {
1843
+ _server: Server
1844
+
1845
+ constructor(server: Server) {
1846
+ this._server = server
1847
+ }
1848
+
1849
+ getJobStatus<AV extends AuthVerifier>(
1850
+ cfg: ConfigOf<
1851
+ AV,
1852
+ AppBskyVideoGetJobStatus.Handler<ExtractAuth<AV>>,
1853
+ AppBskyVideoGetJobStatus.HandlerReqCtx<ExtractAuth<AV>>
1854
+ >,
1855
+ ) {
1856
+ const nsid = 'app.bsky.video.getJobStatus' // @ts-ignore
1857
+ return this._server.xrpc.method(nsid, cfg)
1858
+ }
1859
+
1860
+ getUploadLimits<AV extends AuthVerifier>(
1861
+ cfg: ConfigOf<
1862
+ AV,
1863
+ AppBskyVideoGetUploadLimits.Handler<ExtractAuth<AV>>,
1864
+ AppBskyVideoGetUploadLimits.HandlerReqCtx<ExtractAuth<AV>>
1865
+ >,
1866
+ ) {
1867
+ const nsid = 'app.bsky.video.getUploadLimits' // @ts-ignore
1868
+ return this._server.xrpc.method(nsid, cfg)
1869
+ }
1870
+
1871
+ uploadVideo<AV extends AuthVerifier>(
1872
+ cfg: ConfigOf<
1873
+ AV,
1874
+ AppBskyVideoUploadVideo.Handler<ExtractAuth<AV>>,
1875
+ AppBskyVideoUploadVideo.HandlerReqCtx<ExtractAuth<AV>>
1876
+ >,
1877
+ ) {
1878
+ const nsid = 'app.bsky.video.uploadVideo' // @ts-ignore
1879
+ return this._server.xrpc.method(nsid, cfg)
1880
+ }
1881
+ }
1882
+
1837
1883
  export class ChatNS {
1838
1884
  _server: Server
1839
1885
  bsky: ChatBskyNS