PluginProbe
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI / 6.0.3
AutomatorWP – No-Code Workflow Automation, Integration & Webhooks Plugin, now with AI v6.0.3
6.0.3 6.0.2 6.0.1 6.0.0 5.8.6 5.8.5 5.8.4 5.8.3 5.8.2 5.8.1 5.8.0 5.7.9.2 5.7.9.1 5.7.8 5.7.9 5.7.6 5.7.7 5.7.5 5.7.4 5.7.3 5.7.2 5.7.1 trunk 5.6.0 5.6.1 All 34 releases
← All changes | integrations/bluesky/includes/functions.php +486 -0 5.7.6 → 6.0.3 View file →
@@ -1,0 +1,486 @@
1 +<?php
2 +
3 +/**
4 + * Helper function to get the Bluesky API parameters
5 + *
6 + * @since 1.0.0
7 + *
8 + * @return array|false
9 + */
10 +function automatorwp_bluesky_get_api() {
11 +
12 + $user_handle = automatorwp_bluesky_get_option( 'user_handle', '' );
13 + $user_password = automatorwp_bluesky_get_option( 'user_password', '' );
14 + $base_url = 'https://bsky.social/xrpc';
15 + $chat_url = 'https://api.bsky.chat/xrpc';
16 +
17 + if( empty( $user_handle ) || empty( $user_password ) ) {
18 + return false;
19 + }
20 +
21 + return array(
22 + 'user_handle' => $user_handle,
23 + 'user_password' => $user_password,
24 + 'base_url' => $base_url,
25 + 'chat_url' => $chat_url,
26 + );
27 +}
28 +
29 +/**
30 + * Function to check the user credentials with a POST request to the Bluesky API
31 + * Also saving the refresh token and user DID
32 + *
33 + * @param mixed $credentials - User credentials
34 + *
35 + * @return bool - True if the credentials are correct, false otherwise
36 + */
37 +function automatorwp_bluesky_check_settings_status( $credentials ) {
38 +
39 + $return = false;
40 +
41 + // Preparar los datos en formato JSON
42 + $body = json_encode( array(
43 + 'identifier' => $credentials['user_handle'],
44 + 'password' => $credentials['user_password'],
45 + ) );
46 +
47 + // Arguments for the POST request
48 + $args = array(
49 + 'body' => $body,
50 + 'headers' => array(
51 + 'Content-Type' => 'application/json',
52 + ),
53 + 'timeout' => 20,
54 + 'data_format' => 'body',
55 + );
56 +
57 +
58 + // POST request to the Bluesky API
59 + $response = wp_remote_post( 'https://bsky.social/xrpc/com.atproto.server.createSession', $args );
60 +
61 + $status_code = wp_remote_retrieve_response_code( $response );
62 +
63 + if ( 200 !== $status_code ) {
64 + wp_send_json_error( array( 'message' => __( 'Please, check your API credentials', 'automatorwp' ) ) );
65 + return $return;
66 + } else {
67 + $data = json_decode( wp_remote_retrieve_body( $response ), true );
68 +
69 + // Check if the response has the refresh token
70 + if ( isset( $data['refreshJwt'] ) ) {
71 + // Update refresh token and user did
72 + update_option( 'bluesky_refresh_token', $data['refreshJwt'] );
73 + update_option( 'bluesky_did', $data['did'] );
74 + $return = true;
75 + } else {
76 + wp_send_json_error( array( 'message' => __( 'Refresh token not found in the response.', 'automatorwp' ) ) );
77 + return $return;
78 + }
79 + $return = true;
80 + }
81 +
82 + return $return;
83 +}
84 +
85 +/**
86 + * Get access token from Bluesky and save the new refresh token
87 + *
88 + * @return string|false - Access token
89 + */
90 +function automatorwp_bluesky_get_access_token( ) {
91 + $api = automatorwp_bluesky_get_api();
92 +
93 + $refresh_token = get_option( 'bluesky_refresh_token' );
94 +
95 + if ( !$refresh_token || !$api ) {
96 + return false;
97 + }
98 +
99 + $args = array(
100 + 'headers' => array(
101 + 'Content-Type' => 'application/json',
102 + 'Authorization' => 'Bearer ' . $refresh_token,
103 + ),
104 + 'timeout' => 20,
105 + 'data_format' => 'body',
106 + );
107 +
108 + $response = wp_remote_post( $api["base_url"] . '/com.atproto.server.refreshSession', $args );
109 +
110 + $status_code = wp_remote_retrieve_response_code( $response );
111 +
112 + if ( 200 !== $status_code ) {
113 + return false;
114 + }
115 +
116 + $data = json_decode( wp_remote_retrieve_body( $response ), true );
117 +
118 + if ( isset( $data['accessJwt'] ) ) {
119 + if ( isset( $data['refreshJwt'] ) ) {
120 + update_option( 'bluesky_refresh_token', $data['refreshJwt'] );
121 + }
122 + return $data['accessJwt'];
123 + } else {
124 + return false;
125 + }
126 +}
127 +
128 +/**
129 + * Add post to bluesky
130 + *
131 + * @since 1.0.0
132 + *
133 + * @param string $post_content Content of the post
134 + *
135 + * @return int - Status code
136 + */
137 +function automatorwp_bluesky_create_post( $post_content ) {
138 +
139 + $api = automatorwp_bluesky_get_api();
140 +
141 + if( ! $api ) {
142 + return;
143 + }
144 +
145 + $access_token = automatorwp_bluesky_get_access_token();
146 +
147 + if ( ! $access_token ) {
148 + return;
149 + }
150 +
151 + $date = new DateTime( 'now', new DateTimeZone('UTC'));
152 + $created_at = $date->format('Y-m-d\TH:i:s\Z');
153 +
154 + $body = array(
155 + 'repo' => $api['user_handle'],
156 + 'collection'=> 'app.bsky.feed.post',
157 + 'record' => array(
158 + 'text' => $post_content,
159 + 'createdAt' => $created_at,
160 + ),
161 + );
162 +
163 + $args = array(
164 + 'body' => json_encode( $body ),
165 + 'headers' => array(
166 + 'Content-Type' => 'application/json',
167 + 'Authorization' => 'Bearer ' . $access_token,
168 + ),
169 + 'timeout' => 20,
170 + );
171 +
172 + $response = wp_remote_post( $api['base_url'] . '/com.atproto.repo.createRecord', $args );
173 +
174 + $status_code = wp_remote_retrieve_response_code( $response );
175 +
176 + return $status_code;
177 +}
178 +
179 +/**
180 + * Get user DID from bluesky
181 + *
182 + * @param mixed $handle - User handle
183 + * @param mixed $access_token - Access token
184 + *
185 + * @return string|false - User DID
186 + */
187 +function automatorwp_bluesky_get_user_did($handle, $access_token) {
188 + $api = automatorwp_bluesky_get_api();
189 +
190 + if (!$handle || !$access_token) {
191 + return false;
192 + }
193 +
194 + $args = array(
195 + 'headers' => array(
196 + 'Content-Type' => 'application/json',
197 + 'Authorization' => 'Bearer ' . $access_token,
198 + ),
199 + 'timeout' => 20,
200 + );
201 +
202 + $response = wp_remote_get( $api["base_url"] . "/app.bsky.actor.getProfile?actor=" . $handle, $args );
203 +
204 + if ( is_wp_error( $response ) ) {
205 + return false;
206 + }
207 +
208 + $status_code = wp_remote_retrieve_response_code( $response );
209 +
210 + if ($status_code != 200) {
211 + return false;
212 + }
213 +
214 + $data = json_decode( wp_remote_retrieve_body( $response ), true );
215 +
216 + if ( isset( $data['did'] ) ) {
217 + return $data['did'];
218 + }
219 +}
220 +
221 +/**
222 + * Get conversation ID from bluesky
223 + *
224 + * @param mixed $to_handle - User handle to send the message
225 + * @param mixed $access_token - Access token
226 + *
227 + * @return string|false - Convo ID
228 + */
229 +function automatorwp_bluesky_get_convo($to_handle, $access_token) {
230 + $api = automatorwp_bluesky_get_api();
231 + $from_did = get_option( 'bluesky_did' );
232 + $to_did = automatorwp_bluesky_get_user_did( $to_handle, $access_token );
233 +
234 + if (!$to_did || !$from_did) {
235 + return false;
236 + }
237 +
238 + $url = $api["chat_url"] . '/chat.bsky.convo.getConvoForMembers?members=' . $from_did . '&members=' . $to_did;
239 +
240 + $args = array(
241 + 'headers' => array(
242 + 'Content-Type' => 'application/json',
243 + 'Authorization' => 'Bearer ' . $access_token,
244 + ),
245 + 'timeout' => 20,
246 + );
247 +
248 + $response = wp_remote_get( $url, $args );
249 +
250 + if ( is_wp_error( $response ) ) {
251 + $error_message = $response->get_error_message();
252 + return false;
253 + }
254 +
255 + $status_code = wp_remote_retrieve_response_code( $response );
256 +
257 + if ( 200 !== $status_code ) {
258 + return false;
259 + }
260 +
261 + $body = wp_remote_retrieve_body( $response );
262 + $data = json_decode( $body, true );
263 +
264 + if ( null === $data ) {
265 + return false;
266 + }
267 +
268 + // Check if data is array
269 + if ( !is_array(($data)) ) {
270 + return false;
271 + }
272 +
273 + if (isset($data['convo']) && isset($data['convo']['id'])) {
274 + return $data['convo']['id'];
275 + } else {
276 + return false;
277 + }
278 +}
279 +
280 +/**
281 + * Send a menssage on bluesky
282 + *
283 + * @since 1.0.0
284 + *
285 + * @param string $message_content Content of the message
286 + * @param string $to_user User handle to send the message
287 + *
288 + * @return int - Status code
289 + */
290 +function automatorwp_bluesky_send_message( $message_content, $to_user ) {
291 +
292 + $api = automatorwp_bluesky_get_api();
293 +
294 + if( ! $api ) {
295 + return;
296 + }
297 +
298 + $access_token = automatorwp_bluesky_get_access_token();
299 +
300 + if ( !$access_token ) {
301 + return;
302 + }
303 +
304 + $convo = automatorwp_bluesky_get_convo($to_user, $access_token);
305 +
306 + if (!$convo) {
307 + return;
308 + }
309 +
310 + $body = array(
311 + 'convoId' => $convo,
312 + 'message' => array(
313 + 'text' => $message_content,
314 + ),
315 + );
316 +
317 + $args = array(
318 + 'body' => json_encode( $body ),
319 + 'headers' => array(
320 + 'Content-Type' => 'application/json',
321 + 'Authorization' => 'Bearer ' . $access_token,
322 + ),
323 + 'timeout' => 20,
324 + );
325 +
326 + $response = wp_remote_post( $api["chat_url"] . '/chat.bsky.convo.sendMessage', $args );
327 +
328 + $status_code = wp_remote_retrieve_response_code( $response );
329 +
330 + return $status_code;
331 +}
332 +
333 +/**
334 + * Function to download an image from URI and upload it to bluesky
335 + *
336 + * @param mixed $post_image - Image URI
337 + * @param mixed $access_token - Access token
338 + *
339 + * @return object|false - Blob object
340 + */
341 +function automatorwp_bluesky_upload_image_to_blob( $post_image, $access_token ) {
342 + $api = automatorwp_bluesky_get_api();
343 +
344 + if (!$post_image || !$access_token || !$api) {
345 + return;
346 + }
347 +
348 + $image_response = wp_remote_get( $post_image, array( 'timeout' => 20 ) );
349 +
350 + if ( is_wp_error( $image_response ) ) {
351 + return;
352 + }
353 +
354 + $image_data = wp_remote_retrieve_body( $image_response );
355 +
356 + if ( empty( $image_data ) ) {
357 + return;
358 + }
359 +
360 + $image_size = strlen( $image_data );
361 + // 1,000,000 bytes limit
362 + if ( $image_size > 1000000 ) {
363 + return;
364 + }
365 +
366 + $image_mime = wp_remote_retrieve_header( $image_response, 'content-type' );
367 +
368 + if ( empty( $image_mime ) ) {
369 + $image_mime = 'image/jpeg';
370 + }
371 +
372 + $upload_args = array(
373 + 'body' => $image_data,
374 + 'headers' => array(
375 + 'Content-Type' => $image_mime,
376 + 'Authorization' => 'Bearer ' . $access_token,
377 + ),
378 + 'timeout' => 20,
379 + );
380 +
381 + $upload_response = wp_remote_post( $api['base_url'] . '/com.atproto.repo.uploadBlob', $upload_args );
382 + if ( is_wp_error( $upload_response ) ) {
383 + return $upload_response;
384 + }
385 +
386 + $upload_body = wp_remote_retrieve_body( $upload_response );
387 + $upload_data = json_decode( $upload_body, true );
388 +
389 + if ( ! isset( $upload_data['blob'] ) ) {
390 + return new WP_Error( 'upload_failed', 'Error uploading file.' );
391 + }
392 +
393 + $blob = $upload_data['blob'];
394 +
395 + return $blob;
396 +}
397 +
398 +/**
399 + * Create a post with an image on bluesky
400 + *
401 + * @since 1.0.0
402 + *
403 + * @param string $post_content Content of the post
404 + * @param string $post_image Image uri
405 + *
406 + * @return int - Status code
407 + */
408 +function automatorwp_bluesky_create_post_with_image( $post_content, $image ) {
409 +
410 + $api = automatorwp_bluesky_get_api();
411 +
412 + if( ! $api ) {
413 + return;
414 + }
415 +
416 + $access_token = automatorwp_bluesky_get_access_token();
417 +
418 + if ( ! $access_token ) {
419 + return;
420 + }
421 +
422 + $image_blob = automatorwp_bluesky_upload_image_to_blob( $image, $access_token );
423 +
424 + if ( ! $image_blob ) {
425 + return;
426 + }
427 +
428 + // Get current date in UTC
429 + $date = new DateTime( 'now', new DateTimeZone('UTC'));
430 + $created_at = $date->format('Y-m-d\TH:i:s\Z');
431 +
432 + // Prepare data to send on post request
433 + $embed = array(
434 + '$type' => 'app.bsky.embed.images',
435 + 'images' => array(
436 + array(
437 + 'image' => $image_blob,
438 + 'alt' => 'post image',
439 + ),
440 + ),
441 + );
442 +
443 + $body = array(
444 + 'repo' => $api['user_handle'],
445 + 'collection'=> 'app.bsky.feed.post',
446 + 'record' => array(
447 + '$type' => "app.bsky.feed.post",
448 + 'text' => $post_content,
449 + 'createdAt' => $created_at,
450 + 'embed' => $embed,
451 + ),
452 + );
453 +
454 + $args = array(
455 + 'body' => json_encode( $body ),
456 + 'headers' => array(
457 + 'Content-Type' => 'application/json',
458 + 'Authorization' => 'Bearer ' . $access_token,
459 + ),
460 + 'timeout' => 20,
461 + );
462 +
463 + $response = wp_remote_post( $api['base_url'] . '/com.atproto.repo.createRecord', $args );
464 +
465 + $status_code = wp_remote_retrieve_response_code( $response );
466 +
467 + return $status_code;
468 +}
469 +
470 +/**
471 + * Sanitize name account
472 + *
473 + * @param string $account The name account
474 + *
475 + * @since 1.0.0
476 + *
477 + * @return string|false|WP_Error
478 + */
479 +function automatorwp_bluesky_validate_name_account( $account ) {
480 +
481 + // Filter the characters from string
482 + $account = preg_replace('/[^a-zA-Z0-9.]/', '', $account);
483 +
484 + return $account;
485 +
486 +}