From 4023ba4859391282edb694ad2a1c9ff88e0fa36e Mon Sep 17 00:00:00 2001 From: Dmytro Zelenetskyi Date: Sun, 25 Feb 2024 20:50:55 +0100 Subject: [PATCH] flickr client simplified (#3) * flickr initial client --- .changeset/tender-dolphins-ring.md | 5 + apis/figma/README.md | 9 +- apis/flickr/LICENSE | 202 +++++++++++++++ apis/flickr/README.md | 80 ++++++ apis/flickr/package.json | 44 ++++ apis/flickr/src/api/activity.ts | 74 ++++++ apis/flickr/src/api/photosets.ts | 386 +++++++++++++++++++++++++++++ apis/flickr/src/index.ts | 59 +++++ apis/flickr/tsconfig.json | 17 ++ 9 files changed, 870 insertions(+), 6 deletions(-) create mode 100644 .changeset/tender-dolphins-ring.md create mode 100644 apis/flickr/LICENSE create mode 100644 apis/flickr/README.md create mode 100644 apis/flickr/package.json create mode 100644 apis/flickr/src/api/activity.ts create mode 100644 apis/flickr/src/api/photosets.ts create mode 100644 apis/flickr/src/index.ts create mode 100644 apis/flickr/tsconfig.json diff --git a/.changeset/tender-dolphins-ring.md b/.changeset/tender-dolphins-ring.md new file mode 100644 index 0000000..42ddc6c --- /dev/null +++ b/.changeset/tender-dolphins-ring.md @@ -0,0 +1,5 @@ +--- +"@zemd/flickr-rest-api": patch +--- + +initial version diff --git a/apis/figma/README.md b/apis/figma/README.md index 43a9245..47d0913 100644 --- a/apis/figma/README.md +++ b/apis/figma/README.md @@ -5,10 +5,10 @@ This is a Figma API implementation for javascript projects. ## Installation ```sh -bun install @zemd/figma-rest-api +bun add @zemd/figma-rest-api npm install @zemd/figma-rest-api -yarn install @zemd/figma-rest-api -pnpm install @zemd/figma-rest-api +yarn add @zemd/figma-rest-api +pnpm add @zemd/figma-rest-api ``` ## Usage @@ -28,9 +28,6 @@ some experimental features. In this case, you can construct your own api call us Since the library is built on top of `@zemd/http-client` you can compose different configurations together. -```ts - -``` ## License diff --git a/apis/flickr/LICENSE b/apis/flickr/LICENSE new file mode 100644 index 0000000..faa2310 --- /dev/null +++ b/apis/flickr/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2024] Dmytro Zelenetskyi + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/apis/flickr/README.md b/apis/flickr/README.md new file mode 100644 index 0000000..b929cff --- /dev/null +++ b/apis/flickr/README.md @@ -0,0 +1,80 @@ +# @zemd/flickr-rest-api + +This is a Flickr API implementation for javascript projects. + +**WARNING**: This is a work in progress and not all API methods are implemented yet. + +## Installation + +```sh +bun add @zemd/flickr-rest-api +npm install @zemd/flickr-rest-api +yarn add @zemd/flickr-rest-api +pnpm add @zemd/flickr-rest-api +``` + +## Usage + +```ts +import { flickr } from "@zemd/flickr-rest-api"; + +const client = figma("your-flickr-token"); +const response = await client.photosets.getPhotos({ ... params ... }); +console.log(await response.json()); +``` + +## Implemented API Methods + +See documentation [https://www.flickr.com/services/api/](https://www.flickr.com/services/api/) + +- [x] activity +- [ ] auth +- [ ] auth.oauth +- [ ] blogs +- [ ] cameras +- [ ] collections +- [ ] commons +- [ ] contacts +- [ ] favorites +- [ ] galleries +- [ ] groups.discuss.replies +- [ ] groups.discuss.topics +- [ ] groups +- [ ] groups.members +- [ ] groups.pools +- [ ] interestingness +- [ ] machinetags +- [ ] panda +- [ ] people +- [ ] photos +- [ ] photos.comments +- [ ] photos.geo +- [ ] photos.licenses +- [ ] photos.notes +- [ ] photos.people +- [ ] photos.suggestions +- [ ] photos.transform +- [ ] photos.upload +- [x] photosets +- [ ] photosets.comments +- [ ] places +- [ ] prefs +- [ ] profile +- [ ] push +- [ ] reflection +- [ ] stats +- [ ] tags +- [ ] test +- [ ] testimonials +- [ ] urls + + +## License + +`@zemd/flickr-rest-api` released under the Apache 2.0 license + +## Donate + +[![](https://img.shields.io/badge/patreon-donate-yellow.svg)](https://www.patreon.com/red_rabbit) +[![](https://img.shields.io/static/v1?label=UNITED24&message=support%20Ukraine&color=blue)](https://u24.gov.ua/) + diff --git a/apis/flickr/package.json b/apis/flickr/package.json new file mode 100644 index 0000000..fd1f1c0 --- /dev/null +++ b/apis/flickr/package.json @@ -0,0 +1,44 @@ +{ + "name": "@zemd/flickr-rest-api", + "type": "module", + "version": "0.0.0", + "license": "Apache-2.0", + "description": "Flickr API client simplified.", + "author": { + "name": "Dmytro Zelenetskyi", + "email": "dmytro.zelenetskyi@gmail.com", + "url": "https://codeandgin.co" + }, + "homepage": "https://github.com/zemd/apis/apis/flickr", + "repository": { + "type": "git", + "url": "https://github.com/zemd/apis.git" + }, + "bugs": { + "url": "https://github.com/zemd/apis/issues" + }, + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } + }, + "module": "./dist/index.js", + "types": "./dist/index.js", + "files": [ + "dist" + ], + "scripts": { + "build": "tsc", + "dev": "tsc --watch" + }, + "devDependencies": { + "@types/bun": "latest", + "@zemd/tsconfig": "^1.2.0", + "typescript": "^5.3.3" + }, + "dependencies": { + "@zemd/http-client": "^1.0.0", + "zod": "^3.22.4" + } +} \ No newline at end of file diff --git a/apis/flickr/src/api/activity.ts b/apis/flickr/src/api/activity.ts new file mode 100644 index 0000000..85ddedf --- /dev/null +++ b/apis/flickr/src/api/activity.ts @@ -0,0 +1,74 @@ +import { method, query, type TEndpointDec } from "@zemd/http-client"; +import { z } from "zod"; + +export const GetUserCommentsQuerySchema = z.object({ + per_page: z + .number() + .int() + .min(1) + .max(50) + .optional() + .describe( + "Number of items to return per page. If this argument is omitted, it defaults to 10. The maximum allowed value is 50. ", + ), + page: z + .number() + .int() + .min(1) + .optional() + .describe("The page of results to return. If this argument is omitted, it defaults to 1."), +}); + +export interface GetUserCommentsQuery extends z.infer {} +/** + * Returns a list of recent activity on photos commented on by the calling user. + * Do not poll this method more than once an hour. + */ +export const userComments = (params: GetUserCommentsQuery): TEndpointDec => { + return [ + `/`, + [ + method("GET"), + query(GetUserCommentsQuerySchema.passthrough().parse(params)), + query({ method: "flickr.activity.userComments" }), + ], + ]; +}; + +export const GetUserPhotosQuerySchema = z.object({ + timeframe: z + .string() + .regex(/^\d+(d|h)$/) + .optional() + .describe( + "The timeframe in which to return updates for. This can be specified in days ('2d') or hours ('4h'). The default behavoir is to return changes since the beginning of the previous user session.", + ), + per_page: z + .number() + .int() + .min(1) + .max(50) + .optional() + .describe( + "Number of items to return per page. If this argument is omitted, it defaults to 10. The maximum allowed value is 50.", + ), + page: z + .number() + .int() + .min(1) + .optional() + .describe("The page of results to return. If this argument is omitted, it defaults to 1."), +}); + +export interface GetUserPhotosQuery extends z.infer {} + +export const userPhotos = (params: GetUserPhotosQuery): TEndpointDec => { + return [ + `/`, + [ + method("GET"), + query(GetUserPhotosQuerySchema.passthrough().parse(params)), + query({ method: "flickr.activity.userPhotos" }), + ], + ]; +}; diff --git a/apis/flickr/src/api/photosets.ts b/apis/flickr/src/api/photosets.ts new file mode 100644 index 0000000..5209a99 --- /dev/null +++ b/apis/flickr/src/api/photosets.ts @@ -0,0 +1,386 @@ +import { method, query, type TEndpointDec } from "@zemd/http-client"; +import { z } from "zod"; + +const PRIVACY_FILTER_PUBLIC_PHOTOS = "1"; +const PRIVACY_FILTER_PRIVATE_FRIENDS = "2"; +const PRIVACY_FILTER_PRIVATE_FAMILY = "3"; +const PRIVACY_FILTER_PRIVATE_FRIENDS_AND_FAMILY = "4"; +const PRIVACY_FILTER_PRIVATE = "5"; +const PRIVACY_FILTER = [ + PRIVACY_FILTER_PUBLIC_PHOTOS, + PRIVACY_FILTER_PRIVATE_FRIENDS, + PRIVACY_FILTER_PRIVATE_FAMILY, + PRIVACY_FILTER_PRIVATE_FRIENDS_AND_FAMILY, + PRIVACY_FILTER_PRIVATE, +] as const; + +export const GetPhotosQuerySchema = z.object({ + photoset_id: z.string().describe("The id of the photoset to return the photos for."), + user_id: z.string().describe("The user_id here is the owner of the set passed in photoset_id."), + // TODO: implement validation and transform + extras: z + .string() + .optional() + .describe( + "A comma-delimited list of extra information to fetch for each returned record. Currently supported fields are: license, date_upload, date_taken, owner_name, icon_server, original_format, last_update, geo, tags, machine_tags, o_dims, views, media, path_alias, url_sq, url_t, url_s, url_m, url_o", + ), + per_page: z + .number() + .int() + .max(500) + .min(1) + .default(500) + .optional() + .describe( + "Number of photos to return per page. If this argument is omitted, it defaults to 500. The maximum allowed value is 500.", + ), + page: z + .number() + .int() + .min(1) + .optional() + .describe("The page of results to return. If this argument is omitted, it defaults to 1."), + privacy_filter: z + .enum(PRIVACY_FILTER) + .optional() + .describe( + "Return photos only matching a certain privacy level. This only applies when making an authenticated call to view a photoset you own.", + ), + media: z.enum(["all", "photos", "videos"]).default("all").optional().describe("Filter results by media type."), +}); + +export interface GetPhotosQuery extends z.infer {} + +/** + * Get the list of photos in a set. + */ +export const getPhotos = (params: GetPhotosQuery): TEndpointDec => { + return [ + `/`, + [ + method("GET"), + query(GetPhotosQuerySchema.passthrough().parse(params)), + query({ method: "flickr.photosets.getPhotos" }), + ], + ]; +}; + +export const AddPhotoQuerySchema = z.object({ + photoset_id: z.string(), + photo_id: z.string(), +}); + +export interface AddPhotoQuery extends z.infer {} + +/** + * Add a photo to the end of an existing photoset. + */ +export const addPhoto = (params: AddPhotoQuery): TEndpointDec => { + return [ + `/`, + [ + method("GET"), + query(AddPhotoQuerySchema.passthrough().parse(params)), + query({ method: "flickr.photosets.addPhoto" }), + ], + ]; +}; + +export const CreatePhotosetQuerySchema = z.object({ + title: z.string().describe("A title for the photoset."), + primary_photo_id: z + .string() + .describe("The id of the photo to represent this set. The photo must belong to the calling user."), + description: z.string().optional().describe("A description of the photoset. May contain limited html."), +}); + +export interface CreateQuery extends z.infer {} + +/** + * Create a new photoset for the calling user. + */ +export const createPhotoset = (params: CreateQuery): TEndpointDec => { + return [ + "/", + [ + method("GET"), + query(CreatePhotosetQuerySchema.passthrough().parse(params)), + query({ method: "flickr.photosets.create" }), + ], + ]; +}; + +export const DeletePhotosetQuerySchema = z.object({ + photoset_id: z.string().describe("The id of the photoset to delete. It must be owned by the calling user."), +}); + +export interface DeletePhotosetQuery extends z.infer {} + +/** + * Delete a photoset. + */ +export const deletePhotoset = (params: DeletePhotosetQuery): TEndpointDec => { + return [ + "/", + [ + method("GET"), + query(DeletePhotosetQuerySchema.passthrough().parse(params)), + query({ method: "flickr.photosets.delete" }), + ], + ]; +}; + +export const EditMetaPhotosetQuerySchema = z.object({ + photoset_id: z.string().describe("The id of the photoset to modify."), + title: z.string().describe("The new title for the photoset."), + description: z.string().describe("A description of the photoset. May contain limited html."), +}); + +export interface EditMetaPhotosetQuery extends z.infer {} + +/** + * Modify the meta-data for a photoset. + */ +export const editMeta = (params: EditMetaPhotosetQuery): TEndpointDec => { + return [ + "/", + [ + method("POST"), + query(EditMetaPhotosetQuerySchema.passthrough().parse(params)), + query({ method: "flickr.photosets.editMeta" }), + ], + ]; +}; + +export const EditPhotosPhotosetQuerySchema = z.object({ + photoset_id: z.string().describe("The id of the photoset to modify. The photoset must belong to the calling user."), + primary_photo_id: z + .string() + .describe( + "The id of the photo to use as the 'primary' photo for the set. This id must also be passed along in photo_ids list argument.", + ), + photo_ids: z + .string() + .describe( + "A comma-delimited list of photo ids to include in the set. They will appear in the set in the order sent. This list must contain the primary photo id. All photos must belong to the owner of the set. This list of photos replaces the existing list. Call flickr.photosets.addPhoto to append a photo to a set.", + ), +}); + +export interface EditPhotosPhotosetQuery extends z.infer {} + +/** + * Modify the photos in a photoset. Use this method to add, remove and re-order photos. + */ +export const editPhotos = (params: EditPhotosPhotosetQuery): TEndpointDec => { + return [ + "/", + [ + method("POST"), + query(EditPhotosPhotosetQuerySchema.passthrough().parse(params)), + query({ method: "flickr.photosets.editPhotos" }), + ], + ]; +}; + +export const GetContextPhotosetQuerySchema = z.object({ + photo_id: z.string().describe("The id of the photo to fetch the context for."), + photoset_id: z.string().describe("The id of the photoset for which to fetch the photo's context."), +}); + +export interface GetContextPhotosetQuery extends z.infer {} + +/** + * Returns next and previous photos for a photo in a set. + */ +export const getContext = (params: GetContextPhotosetQuery): TEndpointDec => { + return [ + "/", + [ + method("GET"), + query(GetContextPhotosetQuerySchema.passthrough().parse(params)), + query({ method: "flickr.photosets.getContext" }), + ], + ]; +}; + +export const GetInfoPhotosetQuerySchema = z.object({ + photoset_id: z.string().describe("The ID of the photoset to fetch information for."), + user_id: z.string().describe("The user_id here is the owner of the set passed in photoset_id."), +}); + +export interface GetInfoPhotosetQuery extends z.infer {} + +/** + * Gets information about a photoset. + */ +export const getInfo = (params: GetInfoPhotosetQuery): TEndpointDec => { + return [ + "/", + [ + method("GET"), + query(GetInfoPhotosetQuerySchema.passthrough().parse(params)), + query({ method: "flickr.photosets.getInfo" }), + ], + ]; +}; + +export const GetListPhotosetQuerySchema = z.object({ + user_id: z + .string() + .optional() + .describe("The NSID of the user to get a photoset list for. If none is specified, the calling user is assumed."), + page: z + .string() + .optional() + .describe( + "The page of results to get. Currently, if this is not provided, all sets are returned, but this behaviour may change in future.", + ), + per_page: z + .number() + .int() + .min(1) + .max(500) + .optional() + .describe("The number of sets to get per page. If paging is enabled, the maximum number of sets per page is 500."), + // TODO: implement validation and transform + primary_photo_extras: z + .string() + .optional() + .describe( + "A comma-delimited list of extra information to fetch for the primary photo. Currently supported fields are: license, date_upload, date_taken, owner_name, icon_server, original_format, last_update, geo, tags, machine_tags, o_dims, views, media, path_alias, url_sq, url_t, url_s, url_m, url_o", + ), + photo_ids: z + .string() + .optional() + .describe( + "A comma-separated list of photo ids. If specified, each returned set will include a list of these photo ids that are present in the set as 'has_requested_photos'", + ), + sort_groups: z + .string() + .optional() + .describe( + "A comma-separated list of groups used to sort the output sets. If has_photo is present, any of the calling user's galleries containing photos referred to in photo_ids will be returned before other galleries. The order of the sort_groups will dictate the order that the groups are returned in. Only available if continuation is used. The resulting output will include a 'sort_group' parameter indicating the sort_group that each set is part of, or null if not applicable", + ), +}); + +export interface GetListPhotosetQuery extends z.infer {} + +/** + * Returns the photosets belonging to the specified user. + */ +export const getList = (params: GetListPhotosetQuery): TEndpointDec => { + return [ + "/", + [ + method("GET"), + query(GetListPhotosetQuerySchema.passthrough().parse(params)), + query({ method: "flickr.photosets.getList" }), + ], + ]; +}; + +export const OrderSetsPhotosetQuerySchema = z.object({ + photoset_ids: z + .string() + .describe( + "A comma delimited list of photoset IDs, ordered with the set to show first, first in the list. Any set IDs not given in the list will be set to appear at the end of the list, ordered by their IDs.", + ), +}); + +export interface OrderSetsPhotosetQuery extends z.infer {} + +/** + * Set the order of photosets for the calling user. + */ +export const orderSets = (params: OrderSetsPhotosetQuery): TEndpointDec => { + return [ + "/", + [ + method("POST"), + query(OrderSetsPhotosetQuerySchema.passthrough().parse(params)), + query({ method: "flickr.photosets.orderSets" }), + ], + ]; +}; + +export const RemovePhotoPhotosetQuerySchema = z.object({ + photoset_id: z.string().describe("The id of the photoset to remove a photo from."), + photo_id: z.string().describe("The id of the photo to remove from the set"), +}); + +export interface RemovePhotoPhotosetQuery extends z.infer {} + +/** + * Remove a photo from a photoset. + */ +export const removePhoto = (params: RemovePhotoPhotosetQuery): TEndpointDec => { + return [ + "/", + [ + method("POST"), + query(RemovePhotoPhotosetQuerySchema.passthrough().parse(params)), + query({ method: "flickr.photosets.removePhoto" }), + ], + ]; +}; + +export const RemovePhotosPhotosetQuerySchema = z.object({ + photoset_id: z.string().describe("The id of the photoset to remove photos from."), + photo_ids: z.string().describe("Comma-delimited list of photo ids to remove from the photoset."), +}); + +export interface RemovePhotosPhotosetQuery extends z.infer {} + +/** + * Remove multiple photos from a photoset. + */ +export const removePhotos = (params: RemovePhotosPhotosetQuery): TEndpointDec => { + return [ + "/", + [ + method("POST"), + query(RemovePhotosPhotosetQuerySchema.passthrough().parse(params)), + query({ method: "flickr.photosets.removePhotos" }), + ], + ]; +}; + +export const ReorderPhotosPhotosetQuerySchema = z.object({ + photoset_id: z.string().describe("The id of the photoset to reorder. The photoset must belong to the calling user."), + photo_ids: z + .string() + .describe( + "Ordered, comma-delimited list of photo ids. Photos that are not in the list will keep their original order.", + ), +}); + +export interface ReorderPhotosPhotosetQuery extends z.infer {} + +export const reorderPhotos = (params: ReorderPhotosPhotosetQuery): TEndpointDec => { + return [ + "/", + [ + method("POST"), + query(ReorderPhotosPhotosetQuerySchema.passthrough().parse(params)), + query({ method: "flickr.photosets.reorderPhotos" }), + ], + ]; +}; + +export const SetPrimaryPhotoPhotosetQuerySchema = z.object({}); + +export interface SetPrimaryPhotoPhotosetQuery extends z.infer {} + +/** + * Set photoset primary photo + */ +export const setPrimaryPhoto = (params: SetPrimaryPhotoPhotosetQuery): TEndpointDec => { + return [ + "/", + [ + method("POST"), + query(SetPrimaryPhotoPhotosetQuerySchema.passthrough().parse(params)), + query({ method: "flickr.photosets.setPrimaryPhoto" }), + ], + ]; +}; diff --git a/apis/flickr/src/index.ts b/apis/flickr/src/index.ts new file mode 100644 index 0000000..3a4f108 --- /dev/null +++ b/apis/flickr/src/index.ts @@ -0,0 +1,59 @@ +import * as photosets from "./api/photosets.js"; +import * as activity from "./api/activity.js"; +import { + debug, + endpoint, + json, + prefix, + query, + type TEndpointDec, + type TEndpointDeclarationFn, + type TEndpointResFn, + type TTransformer, +} from "@zemd/http-client"; + +export const flickr = (apiKey: string, opts?: { url?: string; debug?: boolean }) => { + const build = >( + fn: ArgFn, + ): TEndpointResFn => { + const globalTransformers: Array = [ + prefix(opts?.url ?? "https://api.flickr.com/services/rest"), + query({ api_key: apiKey, format: "json", nojsoncallback: 1 }), + json(), + ]; + + if (opts?.debug === true) { + globalTransformers.push(debug()); + } + + const endpointDecFn = (...params: ArgFnParams): TEndpointDec => { + const [path, transformers]: TEndpointDec = fn(...params); + return [path, [...transformers, ...globalTransformers]]; + }; + + return endpoint(endpointDecFn as ArgFn); + }; + + return { + photosets: { + getPhotos: build(photosets.getPhotos), + addPhoto: build(photosets.addPhoto), + create: build(photosets.createPhotoset), + delete: build(photosets.deletePhotoset), + editMeta: build(photosets.editMeta), + editPhotos: build(photosets.editPhotos), + getContext: build(photosets.getContext), + getInfo: build(photosets.getInfo), + getList: build(photosets.getList), + orderSets: build(photosets.orderSets), + removePhoto: build(photosets.removePhoto), + removePhotos: build(photosets.removePhotos), + reorderPhotos: build(photosets.reorderPhotos), + setPrimaryPhoto: build(photosets.setPrimaryPhoto), + }, + activity: { + userComments: build(activity.userComments), + userPhotos: build(activity.userPhotos), + }, + }; +}; diff --git a/apis/flickr/tsconfig.json b/apis/flickr/tsconfig.json new file mode 100644 index 0000000..2b1961c --- /dev/null +++ b/apis/flickr/tsconfig.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "@zemd/http-client", + "extends": "@zemd/tsconfig/tsconfig-base.json", + "compilerOptions": { + "outDir": "dist", + "moduleDetection": "force", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "target": "ES2022", + "sourceMap": false, + "declarationMap": false, + "skipLibCheck": true + }, + "include": ["src"], + "exclude": ["node_modules", "dist"] +}