From 8536bc460f68f9aa1a6d083a53df861aacfed10f Mon Sep 17 00:00:00 2001 From: rubynguyen1510 <50710444+rubynguyen1510@users.noreply.github.com> Date: Tue, 18 Jul 2023 18:25:31 +0000 Subject: [PATCH 1/6] Final Commit --- .gitignore | 28 + LICENSE | 21 + README.md | 47 + dart/.gitignore | 28 + dart/compress_image/README.md | 82 + dart/compress_image/lib/main.dart | 79 + dart/compress_image/pubspec.yaml | 9 + .../README.md | 60 + .../lib/main.dart | 71 + .../pubspec.yaml | 9 + dart/deepgram_Topic_Detection/README.md | 93 + dart/deepgram_Topic_Detection/lib/main.dart | 78 + dart/deepgram_Topic_Detection/pubspec.yaml | 10 + dart/deepgram_audio_summary/README.md | 77 + dart/deepgram_audio_summary/lib/main.dart | 66 + dart/deepgram_audio_summary/pubspec.yaml | 9 + dart/deepgram_language_detection/README.md | 77 + .../deepgram_language_detection/lib/main.dart | 70 + dart/deepgram_language_detection/pubspec.yaml | 9 + dart/deepgram_transcribe_audio/README.md | 99 + dart/deepgram_transcribe_audio/lib/main.dart | 62 + dart/deepgram_transcribe_audio/pubspec.yaml | 8 + dart/deepgram_transcribe_video/README.md | 92 + dart/deepgram_transcribe_video/lib/main.dart | 67 + dart/deepgram_transcribe_video/pubspec.yaml | 9 + dart/generate-website-screenshot/README.md | 70 + .../generate-website-screenshot/lib/main.dart | 58 + dart/generate-website-screenshot/pubspec.yaml | 9 + dart/generate_giphy_gif/README.md | 53 + dart/generate_giphy_gif/lib/main.dart | 37 + dart/generate_giphy_gif/pubspec.yaml | 9 + dart/generate_map/README.md | 72 + dart/generate_map/lib/main.dart | 82 + dart/generate_map/pubspec.yaml | 9 + dart/generate_short_url/README.md | 99 + dart/generate_short_url/lib/main.dart | 123 + dart/generate_short_url/pubspec.yaml | 8 + dart/object_detection/README.md | 58 + dart/object_detection/lib/main.dart | 46 + dart/object_detection/pubspec.yaml | 9 + dart/send-email-with-mailgun/README.md | 56 + dart/send-email-with-mailgun/lib/main.dart | 127 + dart/send-email-with-mailgun/pubspec.yaml | 9 + dart/send_push_notification/README.md | 93 + .../lib/fcm_service.dart | 28 + dart/send_push_notification/lib/main.dart | 66 + dart/send_push_notification/pubspec.yaml | 13 + .../test/send_push_notification_test.dart | 92 + deno/.gitignore | 35 + deno/compress_image/README.md | 58 + deno/compress_image/src/deps.ts | 6 + deno/compress_image/src/mod.ts | 116 + .../README.md | 60 + .../deps.ts | 1 + .../mod.ts | 74 + deno/deepgram-language-detection/README.md | 65 + deno/deepgram-language-detection/src/mod.ts | 60 + deno/deepgram-topic-detection/README.md | 47 + deno/deepgram-topic-detection/src/deps.ts | 1 + deno/deepgram-topic-detection/src/mod.ts | 38 + deno/deepgram-transcribe-audio/README.md | 47 + deno/deepgram-transcribe-audio/src/deps.ts | 1 + deno/deepgram-transcribe-audio/src/mod.ts | 37 + deno/deepgram-transcribe-video/README.md | 65 + deno/deepgram-transcribe-video/src/mod.ts | 61 + deno/deepgram_audio_summary/README.md | 70 + deno/deepgram_audio_summary/src/mod.ts | 59 + deno/generate_giphy_gif/README.md | 53 + deno/generate_giphy_gif/src/mod.ts | 32 + deno/generate_short_url/README.md | 78 + deno/generate_short_url/src/mod.ts | 67 + deno/generate_website_screenshot/README.md | 60 + deno/generate_website_screenshot/src/deps.ts | 6 + deno/generate_website_screenshot/src/mod.ts | 44 + deno/get_price/README.md | 66 + deno/get_price/src/mod.ts | 100 + deno/object_detection/README.md | 56 + deno/object_detection/src/mod.ts | 39 + deno/send_email_with_mailgun/README.md | 53 + deno/send_email_with_mailgun/src/mod.ts | 28 + deno/send_http_request/README.md | 66 + deno/send_http_request/src/mod.ts | 24 + deno/send_sms_with_twilio/README.md | 56 + deno/send_sms_with_twilio/src/mod.ts | 30 + deno/translate_text_with_google/README.md | 52 + deno/translate_text_with_google/src/mod.ts | 28 + deno/wipe_appwrite_bucket/README.md | 41 + deno/wipe_appwrite_bucket/src/deps.ts | 1 + deno/wipe_appwrite_bucket/src/mod.ts | 50 + dotnet/generateShortUrl/.gitignore | 158 ++ dotnet/generateShortUrl/Function.csproj | 12 + dotnet/generateShortUrl/README.md | 57 + dotnet/generateShortUrl/src/Index.cs | 156 ++ .../AppwriteDatabaseClient.cs | 33 + dotnet/wipe_appwrite_collection/Index.cs | 65 + .../Models/Document.cs | 9 + .../Models/ListDocumentsResponse.cs | 12 + dotnet/wipe_appwrite_collection/README.md | 68 + .../wipeAppwriteCollection.csproj | 12 + java/deepgramLanguageDetection/Index.java | 170 ++ java/deepgramLanguageDetection/README.md | 72 + java/deepgramLanguageDetection/deps.gradle | 4 + java/deepgram_audio_summary/Index.java | 182 ++ java/deepgram_audio_summary/README.md | 59 + java/deepgram_audio_summary/deps.gradle | 4 + java/generate_invoice/Index.java | 116 + java/generate_invoice/README.md | 69 + java/generate_invoice/deps.gradle | 4 + java/get_price/Index.java | 52 + java/get_price/README.md | 61 + java/get_price/deps.gradle | 4 + java/short_url_generator/Index.java | 283 +++ java/short_url_generator/README.md | 91 + java/short_url_generator/deps.gradle | 4 + kotlin/deepgram-transcribe-audio/README.md | 63 + kotlin/deepgram-transcribe-audio/deps.gradle | 3 + kotlin/deepgram-transcribe-audio/src/Index.kt | 86 + kotlin/generate-short-url/README.md | 78 + kotlin/generate-short-url/deps.gradle | 3 + kotlin/generate-short-url/src/Index.kt | 113 + kotlin/wipeAppwriteBucket/README.md | 57 + kotlin/wipeAppwriteBucket/deps.gradle | 4 + kotlin/wipeAppwriteBucket/src/Index.kt | 82 + node/.gitignore | 131 ++ .../README.md | 60 + .../index.js | 69 + .../package-lock.json | 175 ++ .../package.json | 15 + node/deepgram-transcribe-video/README.md | 69 + node/deepgram-transcribe-video/index.js | 66 + .../package-lock.json | 58 + node/deepgram-transcribe-video/package.json | 15 + node/deepgram_audio_summary/README.md | 70 + node/deepgram_audio_summary/package-lock.json | 169 ++ node/deepgram_audio_summary/package.json | 15 + node/deepgram_audio_summary/src/index.js | 36 + node/deepgram_topic_detection/README.md | 75 + .../package-lock.json | 119 + node/deepgram_topic_detection/package.json | 15 + node/deepgram_topic_detection/src/index.js | 40 + node/generate_giphy_gif/README.md | 53 + node/generate_giphy_gif/package-lock.json | 560 +++++ node/generate_giphy_gif/package.json | 15 + node/generate_giphy_gif/src/index.js | 32 + node/generate_invoice/README.md | 59 + .../Screenshot from 2022-10-03 23-09-25.png | Bin 0 -> 470857 bytes .../Screenshot from 2022-10-03 23-10-49.png | Bin 0 -> 250853 bytes node/generate_invoice/package-lock.json | 1395 +++++++++++ node/generate_invoice/package.json | 15 + node/generate_invoice/src/index.js | 49 + node/generate_map/README.md | 48 + node/generate_map/package.json | 17 + node/generate_map/src/index.js | 80 + node/get_covid_stats/README.md | 53 + node/get_covid_stats/package-lock.json | 58 + node/get_covid_stats/package.json | 15 + node/get_covid_stats/src/index.js | 35 + node/object_detection/README.md | 58 + node/object_detection/package-lock.json | 560 +++++ node/object_detection/package.json | 16 + node/object_detection/src/index.js | 26 + node/send_email_with_mailgun/README.md | 54 + node/send_email_with_mailgun/package.json | 16 + node/send_email_with_mailgun/src/index.js | 27 + node/send_http_request/README.md | 63 + node/send_http_request/index.js | 37 + node/send_http_request/package-lock.json | 69 + node/send_http_request/package.json | 15 + node/send_sms_with_twilio/README.md | 56 + node/send_sms_with_twilio/package-lock.json | 58 + node/send_sms_with_twilio/package.json | 15 + node/send_sms_with_twilio/src/index.js | 30 + node/translate_text/README.md | 73 + node/translate_text/package-lock.json | 2057 +++++++++++++++++ node/translate_text/package.json | 16 + node/translate_text/src/aws_provider.js | 31 + node/translate_text/src/azure_provider.js | 43 + node/translate_text/src/google_provider.js | 14 + node/translate_text/src/index.js | 33 + node/translate_text_with_google/README.md | 52 + .../package-lock.json | 721 ++++++ node/translate_text_with_google/package.json | 15 + node/translate_text_with_google/src/index.js | 18 + node/url-shortener/README.md | 69 + node/url-shortener/index.js | 65 + node/url-shortener/package.json | 10 + node/wipe_appwrite_bucket/.gitignore | 149 ++ node/wipe_appwrite_bucket/README.md | 38 + node/wipe_appwrite_bucket/package-lock.json | 175 ++ node/wipe_appwrite_bucket/package.json | 15 + node/wipe_appwrite_bucket/src/index.js | 103 + node/wipe_appwrite_collection/README.md | 89 + node/wipe_appwrite_collection/index.js | 46 + .../package-lock.json | 72 + node/wipe_appwrite_collection/package.json | 14 + php/.gitignore | 477 ++++ .../README.md | 60 + .../composer.json | 11 + .../index.php | 75 + php/deepgram-audio-summary/README.md | 62 + php/deepgram-audio-summary/index.php | 55 + php/deepgram_language_detection/README.md | 61 + php/deepgram_language_detection/composer.json | 10 + php/deepgram_language_detection/index.php | 56 + php/deepgram_transcribe_audio/README.md | 59 + php/deepgram_transcribe_audio/composer.json | 11 + php/deepgram_transcribe_audio/index.php | 73 + php/generate-short-url/README.md | 94 + php/generate-short-url/index.php | 77 + php/generate_giphy_gif/README.md | 53 + php/generate_giphy_gif/composer.json | 10 + php/generate_giphy_gif/index.php | 37 + php/object_detection/README.md | 59 + php/object_detection/composer.json | 10 + php/object_detection/index.php | 52 + php/send-http-request/README.md | 54 + php/send-http-request/composer.json | 11 + php/send-http-request/index.php | 51 + php/send_message/README.md | 113 + php/send_message/composer.json | 11 + php/send_message/index.php | 41 + php/send_message/src/Contracts/Channel.php | 6 + php/send_message/src/Contracts/Validator.php | 6 + php/send_message/src/DiscordChannel.php | 67 + php/send_message/src/EmailChannel.php | 87 + php/send_message/src/NullChannel.php | 14 + php/send_message/src/SMSChannel.php | 104 + php/send_message/src/Traits/HasReceiver.php | 11 + php/send_message/src/TwitterChannel.php | 101 + .../src/Validators/EmailValidator.php | 11 + .../src/Validators/PhoneNumberValidator.php | 39 + php/wipe_appwrite_bucket/README.md | 67 + php/wipe_appwrite_bucket/composer.json | 11 + php/wipe_appwrite_bucket/index.php | 77 + python/.DS_Store | Bin 0 -> 8196 bytes python/compress-image/README.md | 81 + python/compress-image/main.py | 148 ++ python/compress-image/requirements.txt | 1 + python/compress-image/secret.py | 8 + python/compress-image/test/1kb.png | Bin 0 -> 739 bytes .../test/1kb_result_encoded_krakenio.txt | 1 + .../test/1kb_result_encoded_tinypng.txt | 1 + python/compress-image/test_main.py | 410 ++++ .../README.md | 60 + .../main.py | 65 + .../requirements.txt | 1 + python/deepgram-audio-summary/README.md | 66 + python/deepgram-audio-summary/main.py | 39 + .../deepgram-audio-summary/requirements.txt | 1 + python/deepgram-language-detection/README.md | 59 + python/deepgram-language-detection/main.py | 39 + .../requirements.txt | 1 + python/deepgram-topic-detection/README.md | 61 + python/deepgram-topic-detection/main.py | 37 + .../deepgram-topic-detection/requirements.txt | 2 + python/deepgram-transcribe-audio/README.md | 96 + python/deepgram-transcribe-audio/main.py | 75 + .../requirements.txt | 1 + python/deepgram-transcribe-video/README.md | 66 + python/deepgram-transcribe-video/main.py | 25 + .../requirements.txt | 11 + python/generate-giphy-gif/README.md | 55 + python/generate-giphy-gif/main.py | 29 + python/generate-giphy-gif/requirements.txt | 1 + python/generate-map/README.md | 54 + python/generate-map/main.py | 32 + python/generate-map/requirements.txt | 1 + python/generate-short-url/README.md | 93 + python/generate-short-url/main.py | 104 + python/generate-short-url/requirements.txt | 1 + python/object-detection/README.md | 60 + python/object-detection/main.py | 57 + python/object-detection/requirements.txt | 2 + python/send-http-request/README.md | 72 + python/send-http-request/main.py | 54 + python/send-http-request/requirements.txt | 1 + python/send_message/README.md | 119 + .../functions/send_email_mailgun.py | 38 + .../functions/send_message_discord_webhook.py | 27 + .../send_message/functions/send_sms_twilio.py | 39 + python/send_message/functions/send_tweet.py | 41 + python/send_message/main.py | 38 + python/send_message/requirements.txt | 9 + ruby/.gitignore | 58 + ruby/compress-image/Gemfile | 4 + ruby/compress-image/README.md | 65 + ruby/compress-image/index.rb | 119 + .../Gemfile | 2 + .../README.md | 60 + .../index.rb | 66 + ruby/deepgram-audio-summary/Gemfile | 3 + ruby/deepgram-audio-summary/README.md | 67 + ruby/deepgram-audio-summary/index.rb | 54 + ruby/deepgram-transcribe-video/Gemfile | 3 + ruby/deepgram-transcribe-video/README.md | 67 + ruby/deepgram-transcribe-video/index.rb | 54 + ruby/send-http-request/Gemfile | 2 + ruby/send-http-request/README.md | 99 + ruby/send-http-request/index.rb | 45 + ruby/send-sms-with-twilio/Gemfile | 2 + ruby/send-sms-with-twilio/README.md | 59 + ruby/send-sms-with-twilio/index.rb | 45 + ruby/translate-text-with-google/Gemfile | 2 + ruby/translate-text-with-google/README.md | 54 + ruby/translate-text-with-google/index.rb | 35 + ruby/wipe-appwrite-bucket/Gemfile | 3 + ruby/wipe-appwrite-bucket/README.md | 50 + ruby/wipe-appwrite-bucket/index.rb | 62 + ruby/wipe-appwrite-collection/Gemfile | 3 + ruby/wipe-appwrite-collection/README.md | 53 + ruby/wipe-appwrite-collection/index.rb | 71 + swift/.gitignore | 91 + .../Package.swift | 22 + .../README.md | 60 + .../Sources/index.swift | 97 + swift/get-covid-stats/CovidData.swift | 39 + swift/get-covid-stats/Index.swift | 46 + swift/get-covid-stats/Package.swift | 22 + swift/get-covid-stats/README.md | 53 + swift/send-email-with-mailgun/.gitignore | 8 + swift/send-email-with-mailgun/Index.swift | 49 + .../MultipartUtils.swift | 81 + swift/send-email-with-mailgun/Package.swift | 18 + swift/send-email-with-mailgun/README.md | 57 + 324 files changed, 21778 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 dart/.gitignore create mode 100644 dart/compress_image/README.md create mode 100644 dart/compress_image/lib/main.dart create mode 100644 dart/compress_image/pubspec.yaml create mode 100644 dart/convert-phone-number-to-country-name/README.md create mode 100644 dart/convert-phone-number-to-country-name/lib/main.dart create mode 100644 dart/convert-phone-number-to-country-name/pubspec.yaml create mode 100644 dart/deepgram_Topic_Detection/README.md create mode 100644 dart/deepgram_Topic_Detection/lib/main.dart create mode 100644 dart/deepgram_Topic_Detection/pubspec.yaml create mode 100644 dart/deepgram_audio_summary/README.md create mode 100644 dart/deepgram_audio_summary/lib/main.dart create mode 100644 dart/deepgram_audio_summary/pubspec.yaml create mode 100644 dart/deepgram_language_detection/README.md create mode 100644 dart/deepgram_language_detection/lib/main.dart create mode 100644 dart/deepgram_language_detection/pubspec.yaml create mode 100644 dart/deepgram_transcribe_audio/README.md create mode 100644 dart/deepgram_transcribe_audio/lib/main.dart create mode 100644 dart/deepgram_transcribe_audio/pubspec.yaml create mode 100644 dart/deepgram_transcribe_video/README.md create mode 100644 dart/deepgram_transcribe_video/lib/main.dart create mode 100644 dart/deepgram_transcribe_video/pubspec.yaml create mode 100644 dart/generate-website-screenshot/README.md create mode 100644 dart/generate-website-screenshot/lib/main.dart create mode 100644 dart/generate-website-screenshot/pubspec.yaml create mode 100644 dart/generate_giphy_gif/README.md create mode 100644 dart/generate_giphy_gif/lib/main.dart create mode 100644 dart/generate_giphy_gif/pubspec.yaml create mode 100644 dart/generate_map/README.md create mode 100644 dart/generate_map/lib/main.dart create mode 100644 dart/generate_map/pubspec.yaml create mode 100644 dart/generate_short_url/README.md create mode 100644 dart/generate_short_url/lib/main.dart create mode 100644 dart/generate_short_url/pubspec.yaml create mode 100644 dart/object_detection/README.md create mode 100644 dart/object_detection/lib/main.dart create mode 100644 dart/object_detection/pubspec.yaml create mode 100644 dart/send-email-with-mailgun/README.md create mode 100644 dart/send-email-with-mailgun/lib/main.dart create mode 100644 dart/send-email-with-mailgun/pubspec.yaml create mode 100644 dart/send_push_notification/README.md create mode 100644 dart/send_push_notification/lib/fcm_service.dart create mode 100644 dart/send_push_notification/lib/main.dart create mode 100644 dart/send_push_notification/pubspec.yaml create mode 100644 dart/send_push_notification/test/send_push_notification_test.dart create mode 100644 deno/.gitignore create mode 100644 deno/compress_image/README.md create mode 100644 deno/compress_image/src/deps.ts create mode 100644 deno/compress_image/src/mod.ts create mode 100644 deno/convert-phone-number-to-country-name/README.md create mode 100644 deno/convert-phone-number-to-country-name/deps.ts create mode 100644 deno/convert-phone-number-to-country-name/mod.ts create mode 100644 deno/deepgram-language-detection/README.md create mode 100644 deno/deepgram-language-detection/src/mod.ts create mode 100644 deno/deepgram-topic-detection/README.md create mode 100644 deno/deepgram-topic-detection/src/deps.ts create mode 100644 deno/deepgram-topic-detection/src/mod.ts create mode 100644 deno/deepgram-transcribe-audio/README.md create mode 100644 deno/deepgram-transcribe-audio/src/deps.ts create mode 100644 deno/deepgram-transcribe-audio/src/mod.ts create mode 100644 deno/deepgram-transcribe-video/README.md create mode 100644 deno/deepgram-transcribe-video/src/mod.ts create mode 100644 deno/deepgram_audio_summary/README.md create mode 100644 deno/deepgram_audio_summary/src/mod.ts create mode 100644 deno/generate_giphy_gif/README.md create mode 100644 deno/generate_giphy_gif/src/mod.ts create mode 100644 deno/generate_short_url/README.md create mode 100644 deno/generate_short_url/src/mod.ts create mode 100644 deno/generate_website_screenshot/README.md create mode 100644 deno/generate_website_screenshot/src/deps.ts create mode 100644 deno/generate_website_screenshot/src/mod.ts create mode 100644 deno/get_price/README.md create mode 100644 deno/get_price/src/mod.ts create mode 100644 deno/object_detection/README.md create mode 100644 deno/object_detection/src/mod.ts create mode 100644 deno/send_email_with_mailgun/README.md create mode 100644 deno/send_email_with_mailgun/src/mod.ts create mode 100644 deno/send_http_request/README.md create mode 100644 deno/send_http_request/src/mod.ts create mode 100644 deno/send_sms_with_twilio/README.md create mode 100644 deno/send_sms_with_twilio/src/mod.ts create mode 100644 deno/translate_text_with_google/README.md create mode 100644 deno/translate_text_with_google/src/mod.ts create mode 100644 deno/wipe_appwrite_bucket/README.md create mode 100644 deno/wipe_appwrite_bucket/src/deps.ts create mode 100644 deno/wipe_appwrite_bucket/src/mod.ts create mode 100644 dotnet/generateShortUrl/.gitignore create mode 100644 dotnet/generateShortUrl/Function.csproj create mode 100644 dotnet/generateShortUrl/README.md create mode 100644 dotnet/generateShortUrl/src/Index.cs create mode 100644 dotnet/wipe_appwrite_collection/AppwriteDatabaseClient.cs create mode 100644 dotnet/wipe_appwrite_collection/Index.cs create mode 100644 dotnet/wipe_appwrite_collection/Models/Document.cs create mode 100644 dotnet/wipe_appwrite_collection/Models/ListDocumentsResponse.cs create mode 100644 dotnet/wipe_appwrite_collection/README.md create mode 100644 dotnet/wipe_appwrite_collection/wipeAppwriteCollection.csproj create mode 100644 java/deepgramLanguageDetection/Index.java create mode 100644 java/deepgramLanguageDetection/README.md create mode 100644 java/deepgramLanguageDetection/deps.gradle create mode 100644 java/deepgram_audio_summary/Index.java create mode 100644 java/deepgram_audio_summary/README.md create mode 100644 java/deepgram_audio_summary/deps.gradle create mode 100644 java/generate_invoice/Index.java create mode 100644 java/generate_invoice/README.md create mode 100644 java/generate_invoice/deps.gradle create mode 100644 java/get_price/Index.java create mode 100644 java/get_price/README.md create mode 100644 java/get_price/deps.gradle create mode 100644 java/short_url_generator/Index.java create mode 100644 java/short_url_generator/README.md create mode 100644 java/short_url_generator/deps.gradle create mode 100644 kotlin/deepgram-transcribe-audio/README.md create mode 100644 kotlin/deepgram-transcribe-audio/deps.gradle create mode 100644 kotlin/deepgram-transcribe-audio/src/Index.kt create mode 100644 kotlin/generate-short-url/README.md create mode 100644 kotlin/generate-short-url/deps.gradle create mode 100644 kotlin/generate-short-url/src/Index.kt create mode 100644 kotlin/wipeAppwriteBucket/README.md create mode 100644 kotlin/wipeAppwriteBucket/deps.gradle create mode 100644 kotlin/wipeAppwriteBucket/src/Index.kt create mode 100644 node/.gitignore create mode 100644 node/convert-phone-number-to-country-name/README.md create mode 100644 node/convert-phone-number-to-country-name/index.js create mode 100644 node/convert-phone-number-to-country-name/package-lock.json create mode 100644 node/convert-phone-number-to-country-name/package.json create mode 100644 node/deepgram-transcribe-video/README.md create mode 100644 node/deepgram-transcribe-video/index.js create mode 100644 node/deepgram-transcribe-video/package-lock.json create mode 100644 node/deepgram-transcribe-video/package.json create mode 100644 node/deepgram_audio_summary/README.md create mode 100644 node/deepgram_audio_summary/package-lock.json create mode 100644 node/deepgram_audio_summary/package.json create mode 100644 node/deepgram_audio_summary/src/index.js create mode 100644 node/deepgram_topic_detection/README.md create mode 100644 node/deepgram_topic_detection/package-lock.json create mode 100644 node/deepgram_topic_detection/package.json create mode 100644 node/deepgram_topic_detection/src/index.js create mode 100644 node/generate_giphy_gif/README.md create mode 100644 node/generate_giphy_gif/package-lock.json create mode 100644 node/generate_giphy_gif/package.json create mode 100644 node/generate_giphy_gif/src/index.js create mode 100644 node/generate_invoice/README.md create mode 100644 node/generate_invoice/Screenshot from 2022-10-03 23-09-25.png create mode 100644 node/generate_invoice/Screenshot from 2022-10-03 23-10-49.png create mode 100644 node/generate_invoice/package-lock.json create mode 100644 node/generate_invoice/package.json create mode 100644 node/generate_invoice/src/index.js create mode 100644 node/generate_map/README.md create mode 100644 node/generate_map/package.json create mode 100644 node/generate_map/src/index.js create mode 100644 node/get_covid_stats/README.md create mode 100644 node/get_covid_stats/package-lock.json create mode 100644 node/get_covid_stats/package.json create mode 100644 node/get_covid_stats/src/index.js create mode 100644 node/object_detection/README.md create mode 100644 node/object_detection/package-lock.json create mode 100644 node/object_detection/package.json create mode 100644 node/object_detection/src/index.js create mode 100644 node/send_email_with_mailgun/README.md create mode 100644 node/send_email_with_mailgun/package.json create mode 100644 node/send_email_with_mailgun/src/index.js create mode 100644 node/send_http_request/README.md create mode 100644 node/send_http_request/index.js create mode 100644 node/send_http_request/package-lock.json create mode 100644 node/send_http_request/package.json create mode 100644 node/send_sms_with_twilio/README.md create mode 100644 node/send_sms_with_twilio/package-lock.json create mode 100644 node/send_sms_with_twilio/package.json create mode 100644 node/send_sms_with_twilio/src/index.js create mode 100644 node/translate_text/README.md create mode 100644 node/translate_text/package-lock.json create mode 100644 node/translate_text/package.json create mode 100644 node/translate_text/src/aws_provider.js create mode 100644 node/translate_text/src/azure_provider.js create mode 100644 node/translate_text/src/google_provider.js create mode 100644 node/translate_text/src/index.js create mode 100644 node/translate_text_with_google/README.md create mode 100644 node/translate_text_with_google/package-lock.json create mode 100644 node/translate_text_with_google/package.json create mode 100644 node/translate_text_with_google/src/index.js create mode 100644 node/url-shortener/README.md create mode 100644 node/url-shortener/index.js create mode 100644 node/url-shortener/package.json create mode 100644 node/wipe_appwrite_bucket/.gitignore create mode 100644 node/wipe_appwrite_bucket/README.md create mode 100644 node/wipe_appwrite_bucket/package-lock.json create mode 100644 node/wipe_appwrite_bucket/package.json create mode 100644 node/wipe_appwrite_bucket/src/index.js create mode 100644 node/wipe_appwrite_collection/README.md create mode 100644 node/wipe_appwrite_collection/index.js create mode 100644 node/wipe_appwrite_collection/package-lock.json create mode 100644 node/wipe_appwrite_collection/package.json create mode 100644 php/.gitignore create mode 100644 php/convert-phone-number-to-country-name/README.md create mode 100644 php/convert-phone-number-to-country-name/composer.json create mode 100644 php/convert-phone-number-to-country-name/index.php create mode 100644 php/deepgram-audio-summary/README.md create mode 100644 php/deepgram-audio-summary/index.php create mode 100644 php/deepgram_language_detection/README.md create mode 100644 php/deepgram_language_detection/composer.json create mode 100644 php/deepgram_language_detection/index.php create mode 100644 php/deepgram_transcribe_audio/README.md create mode 100644 php/deepgram_transcribe_audio/composer.json create mode 100644 php/deepgram_transcribe_audio/index.php create mode 100644 php/generate-short-url/README.md create mode 100644 php/generate-short-url/index.php create mode 100644 php/generate_giphy_gif/README.md create mode 100644 php/generate_giphy_gif/composer.json create mode 100644 php/generate_giphy_gif/index.php create mode 100644 php/object_detection/README.md create mode 100644 php/object_detection/composer.json create mode 100644 php/object_detection/index.php create mode 100644 php/send-http-request/README.md create mode 100644 php/send-http-request/composer.json create mode 100644 php/send-http-request/index.php create mode 100644 php/send_message/README.md create mode 100644 php/send_message/composer.json create mode 100644 php/send_message/index.php create mode 100644 php/send_message/src/Contracts/Channel.php create mode 100644 php/send_message/src/Contracts/Validator.php create mode 100644 php/send_message/src/DiscordChannel.php create mode 100644 php/send_message/src/EmailChannel.php create mode 100644 php/send_message/src/NullChannel.php create mode 100644 php/send_message/src/SMSChannel.php create mode 100644 php/send_message/src/Traits/HasReceiver.php create mode 100644 php/send_message/src/TwitterChannel.php create mode 100644 php/send_message/src/Validators/EmailValidator.php create mode 100644 php/send_message/src/Validators/PhoneNumberValidator.php create mode 100644 php/wipe_appwrite_bucket/README.md create mode 100644 php/wipe_appwrite_bucket/composer.json create mode 100644 php/wipe_appwrite_bucket/index.php create mode 100644 python/.DS_Store create mode 100644 python/compress-image/README.md create mode 100644 python/compress-image/main.py create mode 100644 python/compress-image/requirements.txt create mode 100644 python/compress-image/secret.py create mode 100644 python/compress-image/test/1kb.png create mode 100644 python/compress-image/test/1kb_result_encoded_krakenio.txt create mode 100644 python/compress-image/test/1kb_result_encoded_tinypng.txt create mode 100644 python/compress-image/test_main.py create mode 100644 python/convert-phone-number-to-country-name/README.md create mode 100644 python/convert-phone-number-to-country-name/main.py create mode 100644 python/convert-phone-number-to-country-name/requirements.txt create mode 100644 python/deepgram-audio-summary/README.md create mode 100644 python/deepgram-audio-summary/main.py create mode 100644 python/deepgram-audio-summary/requirements.txt create mode 100644 python/deepgram-language-detection/README.md create mode 100644 python/deepgram-language-detection/main.py create mode 100644 python/deepgram-language-detection/requirements.txt create mode 100644 python/deepgram-topic-detection/README.md create mode 100644 python/deepgram-topic-detection/main.py create mode 100644 python/deepgram-topic-detection/requirements.txt create mode 100644 python/deepgram-transcribe-audio/README.md create mode 100644 python/deepgram-transcribe-audio/main.py create mode 100644 python/deepgram-transcribe-audio/requirements.txt create mode 100644 python/deepgram-transcribe-video/README.md create mode 100644 python/deepgram-transcribe-video/main.py create mode 100644 python/deepgram-transcribe-video/requirements.txt create mode 100644 python/generate-giphy-gif/README.md create mode 100644 python/generate-giphy-gif/main.py create mode 100644 python/generate-giphy-gif/requirements.txt create mode 100644 python/generate-map/README.md create mode 100644 python/generate-map/main.py create mode 100644 python/generate-map/requirements.txt create mode 100644 python/generate-short-url/README.md create mode 100644 python/generate-short-url/main.py create mode 100644 python/generate-short-url/requirements.txt create mode 100644 python/object-detection/README.md create mode 100644 python/object-detection/main.py create mode 100644 python/object-detection/requirements.txt create mode 100644 python/send-http-request/README.md create mode 100644 python/send-http-request/main.py create mode 100644 python/send-http-request/requirements.txt create mode 100644 python/send_message/README.md create mode 100644 python/send_message/functions/send_email_mailgun.py create mode 100644 python/send_message/functions/send_message_discord_webhook.py create mode 100644 python/send_message/functions/send_sms_twilio.py create mode 100644 python/send_message/functions/send_tweet.py create mode 100644 python/send_message/main.py create mode 100644 python/send_message/requirements.txt create mode 100644 ruby/.gitignore create mode 100644 ruby/compress-image/Gemfile create mode 100644 ruby/compress-image/README.md create mode 100644 ruby/compress-image/index.rb create mode 100644 ruby/convert-phone-number-to-country-name/Gemfile create mode 100644 ruby/convert-phone-number-to-country-name/README.md create mode 100644 ruby/convert-phone-number-to-country-name/index.rb create mode 100644 ruby/deepgram-audio-summary/Gemfile create mode 100644 ruby/deepgram-audio-summary/README.md create mode 100644 ruby/deepgram-audio-summary/index.rb create mode 100644 ruby/deepgram-transcribe-video/Gemfile create mode 100644 ruby/deepgram-transcribe-video/README.md create mode 100644 ruby/deepgram-transcribe-video/index.rb create mode 100644 ruby/send-http-request/Gemfile create mode 100644 ruby/send-http-request/README.md create mode 100644 ruby/send-http-request/index.rb create mode 100644 ruby/send-sms-with-twilio/Gemfile create mode 100644 ruby/send-sms-with-twilio/README.md create mode 100644 ruby/send-sms-with-twilio/index.rb create mode 100644 ruby/translate-text-with-google/Gemfile create mode 100644 ruby/translate-text-with-google/README.md create mode 100644 ruby/translate-text-with-google/index.rb create mode 100644 ruby/wipe-appwrite-bucket/Gemfile create mode 100644 ruby/wipe-appwrite-bucket/README.md create mode 100644 ruby/wipe-appwrite-bucket/index.rb create mode 100644 ruby/wipe-appwrite-collection/Gemfile create mode 100644 ruby/wipe-appwrite-collection/README.md create mode 100644 ruby/wipe-appwrite-collection/index.rb create mode 100644 swift/.gitignore create mode 100644 swift/convert-phone-number-to-country-name/Package.swift create mode 100644 swift/convert-phone-number-to-country-name/README.md create mode 100644 swift/convert-phone-number-to-country-name/Sources/index.swift create mode 100644 swift/get-covid-stats/CovidData.swift create mode 100644 swift/get-covid-stats/Index.swift create mode 100644 swift/get-covid-stats/Package.swift create mode 100644 swift/get-covid-stats/README.md create mode 100644 swift/send-email-with-mailgun/.gitignore create mode 100644 swift/send-email-with-mailgun/Index.swift create mode 100644 swift/send-email-with-mailgun/MultipartUtils.swift create mode 100644 swift/send-email-with-mailgun/Package.swift create mode 100644 swift/send-email-with-mailgun/README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..7aa21da6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +## Open-Runtime specific rules +code.tar.gz + +## General rules, taken from https://gist.github.com/octocat/9257657 + +# Compiled source # +################### +*.com +*.dll +*.exe +*.o +*.so + +# Logs and databases # +###################### +*.log +*.sql +*.sqlite + +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..90fca436 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Open Runtimes + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..5447f630 --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +# Open Runtimes Functions Examples ⚡️ + +![open-runtimes-box-bg-cover](https://user-images.githubusercontent.com/1297371/151676246-0e18f694-dfd7-4bab-b64b-f590fec76ef1.png) + +[![Discord](https://img.shields.io/discord/937092945713172480?label=discord&style=flat-square)](https://discord.gg/fP6W2qEzfQ) +[![Twitter Account](https://img.shields.io/twitter/follow/appwrite?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite) + +Example functions to show off what you can achieve with Open Runtimes. + +## List of Examples + +| Example | Dart | Deno | Node | PHP | Python | Ruby | Swift | +|-----------------------------|-----------------------------|------|------|-----|--------|------|-------| +| Send email with Mailgun | [✅](/dart/send_email_with_mailgun) | [✅](/deno/send_email_with_mailgun) | [✅](/node/send_email_with_mailgun) | | | | [✅](/swift/send-email-with-mailgun) | +| Convert phone number to country name | [✅](/dart/convert-phone-number-to-country-name) | [✅](/deno/convert-phone-number-to-country-name) | [✅](/node/convert-phone-number-to-country-name) | [✅](/php/convert-phone-number-to-country-name) | [✅](/python/convert-phone-number-to-country-name) | [✅](/ruby/convert-phone-number-to-country-name) | [✅](/swift/convert-phone-number-to-country-name) | +| Send SMS with Twilio | | [✅](/deno/send_sms_with_twilio) | [✅](/node/send_sms_with_twilio) | | | [✅](/ruby/send-sms-with-twilio) | | +| Translate text with Google | | [✅](/deno/translate_text_with_google) | [✅](/node/translate_text_with_google) | | | [✅](/ruby/translate-text-with-google) | | +| Object Detection |[✅](/dart/object_detection) | [✅](/deno/object_detection) | [✅](/node/object_detection) | [✅](/php/object_detection) | [✅](/python/object-detection) | | | +| Generate Giphy GIF | [✅](/dart/generate_giphy_gif) | [✅](/deno/generate-giphy-gif) | [✅](/node/generate_giphy_gif) | | [✅](/python/generate-giphy-gif) | | | +| Get COVID-19 Stats | | | | | | | [✅](/swift/get-covid-stats) | +| Compresss Imagse | | | | | |[✅](/ruby/compress-image)| | +| Send a HTTP Request | | | | | | [✅](/ruby/send-http-request) | | +| Wipe Appwrite Bucket | | | [✅](/node/wipe_appwrite_bucket) | | | | | +| Detect Language with Deepgram | | | | | [✅](/python/deepgram-language-detection) | | | +| Summarize Audio with Deepgram | | | | | |[✅](/ruby/deepgram-audio-summary)| | +| Summarize Audio with Deepgram | | | | | [✅](/python/deepgram-audio-summary) | | | + +## Contributing + +All code contributions - including those of people having commit access - must go through a pull request and be approved by a core developer before being merged. This is to ensure a proper review of all the code. + +All functions should have the exactly same functionality as their other language counterparts and if possible you should avoid using any third-party libraries to keep the functions simple and secure. + +We truly ❤️ pull requests! If you wish to help, you can learn more about how you can contribute to this project in the [contribution guide](https://github.com/open-runtimes/.github/blob/main/CONTRIBUTING.md). + + +## Security + +For security issues, kindly email us at [security@appwrite.io](mailto:security@appwrite.io) instead of posting a public issue on GitHub. + +## Discord Server + +Join our live [Discord server](https://discord.gg/fP6W2qEzfQ) for more help, ideas, and discussions. + +## License + +This repository is available under the [MIT License](./LICENSE). diff --git a/dart/.gitignore b/dart/.gitignore new file mode 100644 index 00000000..57abd337 --- /dev/null +++ b/dart/.gitignore @@ -0,0 +1,28 @@ +## Dart Gitignore +# See https://www.dartlang.org/guides/libraries/private-files + +# Files and directories created by pub +.dart_tool/ +.packages +build/ +# If you're building an application, you may want to check-in your pubspec.lock +pubspec.lock + +# Directory created by dartdoc +# If you don't generate documentation locally you can remove this line. +doc/api/ + +# dotenv environment variables file +.env* + +# Avoid committing generated Javascript files: +*.dart.js +*.info.json # Produced by the --dump-info flag. +*.js # When generated by dart2js. Don't specify *.js if your + # project includes source files written in JavaScript. +*.js_ +*.js.deps +*.js.map + +.flutter-plugins +.flutter-plugins-dependencies \ No newline at end of file diff --git a/dart/compress_image/README.md b/dart/compress_image/README.md new file mode 100644 index 00000000..947658e8 --- /dev/null +++ b/dart/compress_image/README.md @@ -0,0 +1,82 @@ +# 🌐 Compress any Image + +A Dart Cloud Function that perform a lossless compression of an image. Input image is in base64 format. + +_Example input 1:_ + +```json +{ + "provider":"tinypng", + "image":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAf0lEQVR4nO2Wuw2AMAxEbw1gpMwDDMBcGQpooDKydGVAoXCK6J7k6qyc83MCCFGP/Yz+CkDF4KHmjgowbQF0CKFrCDUiwztqxabHCL0/xwcNhoI2UdsjC8g0mQvaSs1zwkg0uQAsAEaGm9/UPCeU7eMj6loTEpf6ZOQWMxd98gAhZnS6XEZcNQAAAABJRU5ErkJggg==" +} +``` + +_Example output 1:_ + +```json +{ + "success":true, + "image":"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAAG1BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUUeIgAAAACHRSTlMA8712Sxr5g97cFtUAAAA9SURBVCjPY6Aa6AADfAIcDSA8KoBTgLGVgSFCAEmAqZmBwUIBSYClzTQ4wwE52Cs6OtpR4oFFUciBerEKAP58HnyLtZsYAAAAAElFTkSuQmCC" +} +``` + +_Example input 2:_ + +```json +{ + "provider": "tinypng", + "image": "wrong-image" +} +``` + +_Example output 2:_ + +```json +{ + "success": false, + "message": "Payload is invalid" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +* **TINYPNG_API_KEY** - API Key for [tinyPNG](https://tinypng.com/developers) + + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +```shell +git clone https://github.com/open-runtimes/examples.git && cd examples +cd dart/compress_image +``` + +2. Enter this function folder and build the code: + +```shell +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=lib/main.dart --rm --interactive --tty --volume $PWD:/usr/code openruntimes/dart:v2-2.16 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +```shell +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/dart:v2-2.16 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Dart runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dart-2.16). + +4. Execute function: + +```shell +curl http://localhost:3000/ -d '{"variables":{"TINYPNG_API_KEY":"YOUR_TINYPNG_API_KEY"},"payload":"{\"provider\":\"tinypng\",\"image\":\"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAf0lEQVR4nO2Wuw2AMAxEbw1gpMwDDMBcGQpooDKydGVAoXCK6J7k6qyc83MCCFGP/Yz+CkDF4KHmjgowbQF0CKFrCDUiwztqxabHCL0/xwcNhoI2UdsjC8g0mQvaSs1zwkg0uQAsAEaGm9/UPCeU7eMj6loTEpf6ZOQWMxd98gAhZnS6XEZcNQAAAABJRU5ErkJggg==\"}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +## 📝 Notes + +* This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +* This example is compatible with Dart 2.16. Other versions may work but are not guaranteed to work as they haven't been tested. Versions below Dart 2.14 will not work, because Apwrite SDK requires Dart 2.14, diff --git a/dart/compress_image/lib/main.dart b/dart/compress_image/lib/main.dart new file mode 100644 index 00000000..69e03c3e --- /dev/null +++ b/dart/compress_image/lib/main.dart @@ -0,0 +1,79 @@ +import 'dart:convert'; +import 'dart:typed_data'; +import 'package:http/http.dart' as http; + +Future _tinypng( + final res, final Uint8List binaryImage, final String token) async { + final reqUrl = Uri.parse("https://api.tinify.com/shrink"); + final headers = { + "Authorization": "Basic ${base64.encode(utf8.encode('api:$token'))}", + }; + + try { + var tinypngRes = + await http.post(reqUrl, headers: headers, body: binaryImage); + + if (tinypngRes.statusCode == 200 || tinypngRes.statusCode == 201) { + final output = jsonDecode(tinypngRes.body)['output']; + final compressedImageURL = output['url']; + final compressedImageBytes = + await http.get(Uri.parse(compressedImageURL)); + markSuccess(res, base64Encode(compressedImageBytes.bodyBytes)); + return; + } else { + throw Exception(tinypngRes.reasonPhrase); + } + } catch (e) { + print("Failure in tinpng $e"); + markFailure(res, e.toString()); + return; + } +} + +void markSuccess(final res, final String image) { + res.json({ + 'success': true, + 'image': image, + }); +} + +void markFailure(final res, final String message) { + res.json({ + 'success': false, + 'message': message, + }); +} + +Future start(final request, final resonse) async { + late final payload; + late final String provider, imageBase64, apiKey; + late final Uint8List image; + try { + payload = jsonDecode(request.payload); + provider = payload['provider'].toLowerCase(); + imageBase64 = payload['image']; + } catch (err) { + markFailure(resonse, "Payload is invalid"); + return; + } + + try { + image = base64Decode(imageBase64); + } catch (err) { + markFailure(resonse, imageBase64); + return; + } + + switch (provider) { + case "tinypng": + try { + apiKey = request.variables["TINYPNG_API_KEY"]; + } catch (err) { + markFailure(resonse, "TINYPNG_API_KEY is not provided"); + return; + } + await _tinypng(resonse, image, apiKey); + break; + default: + } +} diff --git a/dart/compress_image/pubspec.yaml b/dart/compress_image/pubspec.yaml new file mode 100644 index 00000000..52a3107f --- /dev/null +++ b/dart/compress_image/pubspec.yaml @@ -0,0 +1,9 @@ +name: compress_image +description: "" +version: 1.0.0 + +environment: + sdk: ">=2.14.0 <3.0.0" + +dependencies: + http: ^0.13.5 diff --git a/dart/convert-phone-number-to-country-name/README.md b/dart/convert-phone-number-to-country-name/README.md new file mode 100644 index 00000000..08596127 --- /dev/null +++ b/dart/convert-phone-number-to-country-name/README.md @@ -0,0 +1,60 @@ +# 📱 Validate phone number and get it's country information + +A Dart Cloud Function that figures out country in which a phone number is registered. + +_Example input:_ + +```json +{ + "phoneNumber": "+421957215740" +} +``` + +> Function can also accept phone numbers with spaces, for instance `+421 957 215 740`. + + +_Example output:_ + + +```json +{ + "phoneNumber": "+421957215740", + "phonePrefix": "+421", + "countryCode": "SK", + "countryName": "Slovakia" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of your Appwrite server +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key +- **APPWRITE_FUNCTION_PROJECT_ID** - Appwrite project ID. If running on Appwrite, this variable is provided automatically. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd dart/convert_phone_number_to_country_name +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=lib/main.dart --rm --interactive --tty --volume $PWD:/usr/code openruntimes/dart:v2-2.16 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/dart:v2-2.16 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Dart runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dart-2.16). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Dart 2.16. Other versions may work but are not guaranteed to work as they haven't been tested. Versions below Dart 2.14 will not work, because Apwrite SDK requires Dart 2.14, \ No newline at end of file diff --git a/dart/convert-phone-number-to-country-name/lib/main.dart b/dart/convert-phone-number-to-country-name/lib/main.dart new file mode 100644 index 00000000..b942ca10 --- /dev/null +++ b/dart/convert-phone-number-to-country-name/lib/main.dart @@ -0,0 +1,71 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:dart_appwrite/dart_appwrite.dart'; + +/* +Globally scoped cache used by function. Example value: +[ + { + "code": "+1", + "countryCode": "US", + "countryName": "United States" + } +] +*/ +var phonePrefixList = null; + +Future start(final req, final res) async { + // Input validation + var phoneNumber = ""; + try { + final payload = jsonDecode(req.payload); + phoneNumber = payload['phoneNumber'].replaceAll(' ', ''); + } catch(err) { + print(err); + throw Exception('Payload is invalid.'); + } + + if(phoneNumber == null || !phoneNumber.startsWith('+')) { + throw Exception('Invalid phone number.'); + } + + // Make sure we have envirnment variables required to execute + if( + req.variables['APPWRITE_FUNCTION_ENDPOINT'] == null || + req.variables['APPWRITE_FUNCTION_PROJECT_ID'] == null || + req.variables['APPWRITE_FUNCTION_API_KEY'] == null + ) { + throw Exception('Please provide all required environment variables.'); + } + + // If we don't have cached list of phone number prefixes (first execution only) + if(phonePrefixList == null) { + // Init Appwrite SDK + final client = new Client(); + final locale = new Locale(client); + + client + .setEndpoint(req.variables['APPWRITE_FUNCTION_ENDPOINT'] ?? '') + .setProject(req.variables['APPWRITE_FUNCTION_PROJECT_ID'] ?? '') + .setKey(req.variables['APPWRITE_FUNCTION_API_KEY'] ?? ''); + + // Fetch and store phone number prefixes + final serverResponse = await locale.getCountriesPhones(); + phonePrefixList = serverResponse.phones; + } + + // Get phone prefix + final phonePrefix = phonePrefixList.firstWhere((prefix) => phoneNumber.startsWith(prefix.code)); + + if(phonePrefix == null) { + throw Exception('Invalid phone number.'); + } + + // Return phone number prefix + res.json({ + 'phoneNumber': phoneNumber, + 'phonePrefix': phonePrefix.code, + 'countryCode': phonePrefix.countryCode, + 'countryName': phonePrefix.countryName + }); +} \ No newline at end of file diff --git a/dart/convert-phone-number-to-country-name/pubspec.yaml b/dart/convert-phone-number-to-country-name/pubspec.yaml new file mode 100644 index 00000000..2257d2a9 --- /dev/null +++ b/dart/convert-phone-number-to-country-name/pubspec.yaml @@ -0,0 +1,9 @@ +name: convert_phone_number_to_country_name +description: "" +version: 1.0.0 + +environment: + sdk: '>=2.14.0 <3.0.0' + +dependencies: + dart_appwrite: ^4.0.0 \ No newline at end of file diff --git a/dart/deepgram_Topic_Detection/README.md b/dart/deepgram_Topic_Detection/README.md new file mode 100644 index 00000000..5cfbc03f --- /dev/null +++ b/dart/deepgram_Topic_Detection/README.md @@ -0,0 +1,93 @@ +# 📝 Topic detection using Deepgram + +A Dart Cloud Function that detects topics from pre-recorded audio using [Deepgram](https://developers.deepgram.com/). + +_Example input 1:_ + +```json +{ + "fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Example output 1:_ + +```json +{ + "success": true, + "deepgramData": { } +} +``` + +_Example input 2:_ + +```json +{ + "fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Example output 2:_ + +```json +{ + "success": false, + "message": "Please provide a valid file URL." +} +``` + +_Example input 3:_ + +```json +{ } +``` + +_Example output 3:_ + +```json +{ + "success": false, + "message": "Please provide a valid file URL." +} +``` + +If the API Key is not provided, you would get: + +```json +{ + "success": false, + "message": "Please provide a valid deepgram API key" +} +``` + +## 📝 Variables + +List of variables used by this cloud function: + +- **DEEPGRAM_API_KEY** - API Key for Deepgram + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd dart/deepgram_Topic_Detection +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=lib/main.dart --rm --interactive --tty --volume $PWD:/usr/code openruntimes/dart:v2-2.16 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/dart:v2-2.16 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Dart runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dart-2.16). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Dart 2.16. Other versions may work but are not guaranteed to work as they haven't been tested. Versions below Dart 2.14 will not work, because Apwrite SDK requires Dart 2.14, \ No newline at end of file diff --git a/dart/deepgram_Topic_Detection/lib/main.dart b/dart/deepgram_Topic_Detection/lib/main.dart new file mode 100644 index 00000000..2bd256d6 --- /dev/null +++ b/dart/deepgram_Topic_Detection/lib/main.dart @@ -0,0 +1,78 @@ +import 'dart:async'; +import 'dart:convert'; +import 'package:http/http.dart' as https; + +/* Example function payload + + {"fileUrl":"https://static.deepgram.com/examples/interview_speech-analytics.wav"} +Successful function response: + +{"success":true,"deepgramData":{}} + +Error function response: + +{"success":false,"message":"Please provide a valid file URL."} +*/ + +void returnSuccess(final res, final data) { + res.json({ + 'success': true, + 'deepgramData': data, + }); +} + +void returnFailure(final res, final message) { + res.json({ + 'success': false, + 'message': message, + }); +} + +Future start(final req, final res) async { + String? fileUrl; + final RegExp regex = RegExp( + r'^(http(s?):)([/|.|\w|\s|-])*\.(?:wav|mp3|flac|ogg|wma)$', + ); + final String deepgramTopicDetectionUrl = + "https://api.deepgram.com/v1/listen?detect_topics=true&punctuate=true"; + + String? deepgramApiKey; + try { + final payload = jsonDecode(req.payload); + fileUrl = payload['fileUrl']; + deepgramApiKey = req.variables["DEEPGRAM_API_KEY"]; + } catch (err) { + print(err); + returnFailure(res, err.toString()); + } + + if (fileUrl == null) { + returnFailure(res, "Please provide a valid file URL."); + } else if (deepgramApiKey == null) { + returnFailure(res, "Please provide a valid deepgram API key"); + } else { + //check if the url is valid using regex + if (!regex.hasMatch(fileUrl)) { + returnFailure(res, "Please provide a valid file URL."); + } else { + //http post request to deepgram + final response = await https.post( + Uri.parse(deepgramTopicDetectionUrl), + headers: { + "Authorization": "Token $deepgramApiKey", + "Content-Type": "application/json", + }, + body: jsonEncode({ + "url": fileUrl, + }), + ); + + //check if the response is successful + if (response.statusCode == 200) { + returnSuccess(res, response.body); + } else { + returnFailure(res, response.body); + } + } + } +} diff --git a/dart/deepgram_Topic_Detection/pubspec.yaml b/dart/deepgram_Topic_Detection/pubspec.yaml new file mode 100644 index 00000000..7260f2b4 --- /dev/null +++ b/dart/deepgram_Topic_Detection/pubspec.yaml @@ -0,0 +1,10 @@ +name: appwrite_function +description: Dart starter for Appwrite function. +version: 1.0.0 +publish_to: "none" + +environment: + sdk: '>=2.14.0 <3.0.0' + +dependencies: + http: ^0.13.5 diff --git a/dart/deepgram_audio_summary/README.md b/dart/deepgram_audio_summary/README.md new file mode 100644 index 00000000..140c1b83 --- /dev/null +++ b/dart/deepgram_audio_summary/README.md @@ -0,0 +1,77 @@ +# 📝 Audio Summary + +A Dart Cloud Function that generates a summary text from spoken audio using [Deepgram](https://developers.deepgram.com/). + + _Example input 1:_ + ```json + { + "payload": "{\"fileUrl\": \"https://static.deepgram.com/examples/interview_speech-analytics.wav\"}" + } + ``` + _Example output 1:_ + ```json + { + "success": true, + "deepgramData": { "A big": "Object" } + } + ``` + _Example input 2:_ + ```json + { + "payload": "{\"fileUrl\": \"Wrong\"}" + } + ``` + _Example output 2:_ + ```json + { + "success": false, + "message": "Failed to parse URL." + } + ``` + _Example input 3:_ + ```json + { + "payload": "{}" + } + ``` + _Example output 3:_ + ```json + { + "success": false, + "message": "Please provide a valid file URL in payload" + } + ``` + If the API Key is not provided, you would get: + ```json + { + "success": false, + "message": "Provide the API key in environment variables" + } + ``` + ## 📝 Variables + + List of variables used by this cloud function: + + * **DEEPGRAM_API_KEY** - API Key for Deepgram + + ## 🚀 Deployment + + 1. Clone this repository, and enter this function folder: + ``` + $ git clone https://github.com/open-runtimes/examples.git && cd examples + $ cd dart/deepgram_audio_summary + ``` + 2. Enter this function folder and build the code: + ``` + docker run -e INTERNAL_RUNTIME_ENTRYPOINT=lib/main.dart --rm --interactive --tty --volume ${PWD}:/usr/code openruntimes/dart:v2-2.16 sh /usr/local/src/build.sh + ``` + As a result, a `code.tar.gz` file will be generated. + 3. Start the Open Runtime: + ``` + docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume ${PWD}/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/dart:v2-2.16 sh /usr/local/src/start.sh + ``` + Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Dart runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dart-2.16). + + ## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Dart 2.18. Other versions may work but are not guaranteed to work as they haven't been tested. Versions below Dart 2.14 will not work, because Apwrite SDK requires Dart 2.14. \ No newline at end of file diff --git a/dart/deepgram_audio_summary/lib/main.dart b/dart/deepgram_audio_summary/lib/main.dart new file mode 100644 index 00000000..02dd463e --- /dev/null +++ b/dart/deepgram_audio_summary/lib/main.dart @@ -0,0 +1,66 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; + +//custom success message +void returnSuccess(final res, final data) { + res.json({ + 'success': true, + 'deepgramData': data, + }); +} + +//custom failure message +void returnFailure(final res, final message) { + res.json({ + 'success': false, + 'message': message, + }); +} + +Future start(final req, final res) async { + var fileUrl; + var apiKey; + + //getting data from payload + try { + final data = jsonDecode(req.payload); + fileUrl = data["fileUrl"]; + apiKey = req.variables["DEEPGRAM_API_KEY"]; + } catch (err) { + returnFailure(res, err.toString()); + return; + } + + //checks + if (fileUrl == null) { + returnFailure(res, "Provide a valid file URL in payload"); + return; + } + + if (apiKey == null) { + returnFailure(res, "Provide the API key as an environment variable"); + return; + } + + //making the request + try { + final endPoint = Uri.parse( + "https://api.deepgram.com/v1/listen?summarize=true&punctuate=true"); + final headers = { + "Authorization": "Token $apiKey", + 'content-type': 'application/json', + }; + final body = {"url": fileUrl}; + final result = + await http.post(endPoint, headers: headers, body: jsonEncode(body)); + if (result.statusCode != 200) { + returnFailure(res, jsonDecode(result.body)); + return; + } + returnSuccess(res, jsonDecode(result.body)); + return; + } catch (err) { + returnFailure(res, err.toString()); + return; + } +} diff --git a/dart/deepgram_audio_summary/pubspec.yaml b/dart/deepgram_audio_summary/pubspec.yaml new file mode 100644 index 00000000..e3f150c2 --- /dev/null +++ b/dart/deepgram_audio_summary/pubspec.yaml @@ -0,0 +1,9 @@ +name: deepgram_audio_summary +description: "" +version: 1.0.0 + +environment: + sdk: '>=2.14.0 <3.0.0' + +dependencies: + http: ^0.13.4 \ No newline at end of file diff --git a/dart/deepgram_language_detection/README.md b/dart/deepgram_language_detection/README.md new file mode 100644 index 00000000..f3cd7c69 --- /dev/null +++ b/dart/deepgram_language_detection/README.md @@ -0,0 +1,77 @@ +# 🔎 Language Detection + +A Dart Cloud Function that detects a language from spoken audio using [Deepgram](https://developers.deepgram.com/). + + _Example input 1:_ + ```json + { + "payload": "{\"fileUrl\": \"https://static.deepgram.com/examples/interview_speech-analytics.wav\"}" + } + ``` + _Example output 1:_ + ```json + { + "success": true, + "deepgramData": { "A big": "Object" } + } + ``` + _Example input 2:_ + ```json + { + "payload": "{\"fileUrl\": \"Wrong\"}" + } + ``` + _Example output 2:_ + ```json + { + "success": false, + "message": "Failed to parse URL." + } + ``` + _Example input 3:_ + ```json + { + "payload": "{}" + } + ``` + _Example output 3:_ + ```json + { + "success": false, + "message": "Please provide a valid file URL in payload" + } + ``` + If the API Key is not provided, you would get: + ```json + { + "success": false, + "message": "Provide the API key in environment variables" + } + ``` + ## 📝 Variables + + List of variables used by this cloud function: + + * **DEEPGRAM_API_KEY** - API Key for Deepgram + + ## 🚀 Deployment + + 1. Clone this repository, and enter this function folder: + ``` + $ git clone https://github.com/open-runtimes/examples.git && cd examples + $ cd dart/deepgram_language_detection + ``` + 2. Enter this function folder and build the code: + ``` + docker run -e INTERNAL_RUNTIME_ENTRYPOINT=lib/main.dart --rm --interactive --tty --volume ${PWD}:/usr/code openruntimes/dart:v2-2.16 sh /usr/local/src/build.sh + ``` + As a result, a `code.tar.gz` file will be generated. + 3. Start the Open Runtime: + ``` + docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume ${PWD}/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/dart:v2-2.16 sh /usr/local/src/start.sh + ``` + Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Dart runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dart-2.16). + + ## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Dart 2.18. Other versions may work but are not guaranteed to work as they haven't been tested. Versions below Dart 2.14 will not work, because Apwrite SDK requires Dart 2.14. \ No newline at end of file diff --git a/dart/deepgram_language_detection/lib/main.dart b/dart/deepgram_language_detection/lib/main.dart new file mode 100644 index 00000000..aef7f703 --- /dev/null +++ b/dart/deepgram_language_detection/lib/main.dart @@ -0,0 +1,70 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; + +//custom success message + +void returnSuccess(final res, final data) { + res.json({ + 'success': true, + 'deepgramData': data, + }); +} + +//custom failure message + +void returnFailure(final res, final message) { + res.json({ + 'success': false, + 'message': message, + }); +} + +Future start(final req, final res) async { + var fileUrl; + var apiKey; + + //getting data from payload + + try { + final data = jsonDecode(req.payload); + fileUrl = data["fileUrl"]; + apiKey = req.variables["DEEPGRAM_API_KEY"]; + } catch (err) { + returnFailure(res, err.toString()); + return; + } + + //checks + + if (fileUrl == null) { + returnFailure(res, "Provide a valid file URL in payload"); + return; + } + + if (apiKey == null) { + returnFailure(res, "Provide the API key as an environment variable"); + } + + //making the request + + try { + final endPoint = Uri.parse( + "https://api.deepgram.com/v1/listen?detect_language=true&punctuate=true"); + final headers = { + "Authorization": "Token $apiKey", + 'content-type': 'application/json', + }; + final body = {"url": fileUrl}; + final result = + await http.post(endPoint, headers: headers, body: jsonEncode(body)); + if (result.statusCode != 200) { + returnFailure(res, jsonDecode(result.body)); + return; + } + returnSuccess(res, jsonDecode(result.body)); + return; + } catch (err) { + returnFailure(res, err.toString()); + return; + } +} diff --git a/dart/deepgram_language_detection/pubspec.yaml b/dart/deepgram_language_detection/pubspec.yaml new file mode 100644 index 00000000..e3c69594 --- /dev/null +++ b/dart/deepgram_language_detection/pubspec.yaml @@ -0,0 +1,9 @@ +name: language_detection +description: "" +version: 1.0.0 + +environment: + sdk: '>=2.14.0 <3.0.0' + +dependencies: + http: ^0.13.4 \ No newline at end of file diff --git a/dart/deepgram_transcribe_audio/README.md b/dart/deepgram_transcribe_audio/README.md new file mode 100644 index 00000000..a688bbbd --- /dev/null +++ b/dart/deepgram_transcribe_audio/README.md @@ -0,0 +1,99 @@ +# 📝 Transcribe audio using Deepgram + +A Dart Cloud Function that transcribes pre-recorded audio using [Deepgram](https://developers.deepgram.com/). + +_Example input 1:_ + +```json +{ + "payload": "{\"fileUrl\": \"https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav\"}" +} +``` + +_Example output 1:_ + +```json +{ + "success": true, + "deepgramData": { "A big": "Object" } +} +``` + +_Example input 2:_ + +```json +{ + "payload": "{\"fileUrl\": \"Wrong\"}" +} +``` + +_Example output 2:_ + +```json +{ + "success": false, + "message": "Failed to parse URL." +} +``` + +_Example input 3:_ + +```json +{ + "payload": "{}" +} +``` + +_Example output 3:_ + +```json +{ + "success": false, + "message": "Please provide a file url in payload" +} +``` + +If the API Key is not provided, you would get: + +```json +{ + "success": false, + "message": "Please provide the api key in environment variables" +} +``` + +## 📝 Variables + +List of variables used by this cloud function: + +- **DEEPGRAM_API_KEY** - API Key for Deepgram + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd dart/deepgram_transcribe_audio +``` + +2. Enter this function folder and build the code: + +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=lib/main.dart --rm --interactive --tty --volume ${PWD}:/usr/code openruntimes/dart:v2-2.16 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume ${PWD}/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/dart:v2-2.16 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Dart runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dart-2.16). + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Dart 2.18. Other versions may work but are not guaranteed to work as they haven't been tested. Versions below Dart 2.14 will not work, because Apwrite SDK requires Dart 2.14, diff --git a/dart/deepgram_transcribe_audio/lib/main.dart b/dart/deepgram_transcribe_audio/lib/main.dart new file mode 100644 index 00000000..0417d874 --- /dev/null +++ b/dart/deepgram_transcribe_audio/lib/main.dart @@ -0,0 +1,62 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; + +void returnSuccess(final res, final data) { + res.json({ + 'success': true, + 'deepgramData': data, + }); +} + +void returnFailure(final res, final message) { + res.json({ + 'success': false, + 'message': message, + }); +} + +Future start(final req, final res) async { + var fileUrl; + var deepgramApiKey; + + //getting data from payload + try { + final data = jsonDecode(req.payload); + fileUrl = data["fileUrl"]; + deepgramApiKey = req.variables["DEEPGRAM_API_KEY"]; + } catch (err) { + returnFailure(res, err.toString()); + return; + } + + //checks + if (fileUrl == null || deepgramApiKey == null) { + if (fileUrl == null) + returnFailure(res, "Please provide a file url in payload"); + else + returnFailure(res, "Please provide the api key in environment variables"); + return; + } + + //making the request + try { + final endPoint = + Uri.parse("https://api.deepgram.com/v1/listen?model=general"); + final headers = { + "Authorization": "Token $deepgramApiKey", + 'content-type': 'application/json', + }; + final body = {"url": fileUrl}; + final result = + await http.post(endPoint, headers: headers, body: jsonEncode(body)); + if (result.statusCode != 200) { + returnFailure(res, jsonDecode(result.body)); + return; + } + returnSuccess(res, jsonDecode(result.body)); + return; + } catch (err) { + returnFailure(res, err.toString()); + return; + } +} diff --git a/dart/deepgram_transcribe_audio/pubspec.yaml b/dart/deepgram_transcribe_audio/pubspec.yaml new file mode 100644 index 00000000..ccb3e9f1 --- /dev/null +++ b/dart/deepgram_transcribe_audio/pubspec.yaml @@ -0,0 +1,8 @@ +name: deepgram_transcribe_audio +description: "" +version: 1.0.0 + +environment: + sdk: '>=2.14.0 <3.0.0' +dependencies: + http: ^0.13.5 diff --git a/dart/deepgram_transcribe_video/README.md b/dart/deepgram_transcribe_video/README.md new file mode 100644 index 00000000..fa2e81a8 --- /dev/null +++ b/dart/deepgram_transcribe_video/README.md @@ -0,0 +1,92 @@ +# 📹 Transcribe Video + +A Dart Cloud Function that transcribes pre-recorded video using [Deepgram](https://developers.deepgram.com/). + +_Example input 1:_ + + ```json + { + "payload": "{\"fileUrl\": \"https://rawcdn.githack.com/deepgram-devs/transcribe-videos/62fc7769d6e2bf38e420ee5224060922af4546f7/deepgram.mp4\"}" + } + ``` + +_Example output 1:_ + + ```json + { + "success": true, + "deepgramData": { "A big": "Object" } + } + ``` + +_Example input 2:_ + + ```json + { + "payload": "{\"fileUrl\": \"Wrong\"}" + } + ``` + +_Example output 2:_ + + ```json + { + "success": false, + "message": "Failed to parse URL." + } + ``` + +_Example input 3:_ + + ```json + { + "payload": "{}" + } + ``` + +_Example output 3:_ + + ```json + { + "success": false, + "message": "Please provide a valid file URL in payload" + } + ``` + + If the API Key is not provided, you would get: + + ```json + { + "success": false, + "message": "Provide the API key in environment variables" + } + ``` + + ## 📝 Variables + + List of variables used by this cloud function: + + * **DEEPGRAM_API_KEY** - API Key for Deepgram + + ## 🚀 Deployment + + 1. Clone this repository, and enter this function folder: + ``` + $ git clone https://github.com/open-runtimes/examples.git && cd examples + $ cd dart/deepgram_transcribe_video + ``` + 2. Enter this function folder and build the code: + ``` + docker run -e INTERNAL_RUNTIME_ENTRYPOINT=lib/main.dart --rm --interactive --tty --volume ${PWD}:/usr/code openruntimes/dart:v2-2.16 sh /usr/local/src/build.sh + ``` + As a result, a `code.tar.gz` file will be generated. + + 3. Start the Open Runtime: + ``` + docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume ${PWD}/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/dart:v2-2.16 sh /usr/local/src/start.sh + ``` + Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Dart runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dart-2.16). + + ## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Dart 2.18. Other versions may work but are not guaranteed to work as they haven't been tested. Versions below Dart 2.14 will not work, because Apwrite SDK requires Dart 2.14. diff --git a/dart/deepgram_transcribe_video/lib/main.dart b/dart/deepgram_transcribe_video/lib/main.dart new file mode 100644 index 00000000..bedd2fdb --- /dev/null +++ b/dart/deepgram_transcribe_video/lib/main.dart @@ -0,0 +1,67 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; + +//custom success message +void returnSuccess(final res, final data) { + res.json({ + 'success': true, + 'deepgramData': data, + }); +} + +//custom failure message +void returnFailure(final res, final message) { + res.json({ + 'success': false, + 'message': message, + }); +} + +Future start(final req, final res) async { + var fileUrl; + var apiKey; + + //getting data from payload + try { + final data = jsonDecode(req.payload); + fileUrl = data["fileUrl"]; + apiKey = req.variables["DEEPGRAM_API_KEY"]; + } catch (err) { + returnFailure(res, err.toString()); + return; + } + + //checks + + if (fileUrl == null) { + returnFailure(res, "Provide a valid file URL in payload"); + return; + } + + if (apiKey == null) { + returnFailure(res, "Provide the API key as an environment variable"); + return; + } + + //making the request + try { + final endPoint = + Uri.parse("https://api.deepgram.com/v1/listen?model=video"); + final headers = { + "Authorization": "Token $apiKey", + 'content-type': 'application/json', + }; + final body = {"url": fileUrl}; + final result = + await http.post(endPoint, headers: headers, body: jsonEncode(body)); + if (result.statusCode != 200) { + returnFailure(res, jsonDecode(result.body)); + return; + } + returnSuccess(res, jsonDecode(result.body)); + return; + } catch (err) { + returnFailure(res, err.toString()); + return; + } +} diff --git a/dart/deepgram_transcribe_video/pubspec.yaml b/dart/deepgram_transcribe_video/pubspec.yaml new file mode 100644 index 00000000..3e3a428f --- /dev/null +++ b/dart/deepgram_transcribe_video/pubspec.yaml @@ -0,0 +1,9 @@ +name: transcribe_video +description: "" +version: 1.0.0 + +environment: + sdk: '>=2.14.0 <3.0.0' + +dependencies: + http: ^0.13.4 \ No newline at end of file diff --git a/dart/generate-website-screenshot/README.md b/dart/generate-website-screenshot/README.md new file mode 100644 index 00000000..1966f9dd --- /dev/null +++ b/dart/generate-website-screenshot/README.md @@ -0,0 +1,70 @@ +# 🖼️ Get Website Screenshot + +A Dart Cloud Function for getting website screenshot from the ScreeenlyAPI. + +_Example input:_ + +```json +{ + "url": "https://github.com/appwrite/appwrite" +} +``` + +_Example output:_ + +```json +{ + "success": "true", + "screenshot": "iVBORw0KGgoAAAANSUhEUgAAAaQAAALiCAYQoH9hbkTPQAAAABJRU5ErkJggg==" +} +``` + + +_Example input:_ + +```json +{ + "url": "Not A URL" +} +``` + +_Example output:_ + +```json +{ + "success": "false", + "message": "An internal error occured" +} +``` + +## 📝 Variables + +List of variables used by this cloud function: + +**SCREEENLY_API_KEY** - Your Screeenly API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd dart/generate-website-screenshot +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=lib/main.dart --rm --interactive --tty --volume $PWD:/usr/code openruntimes/dart:v2-2.16 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/dart:v2-2.16 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Dart runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dart-2.16). + +## 📝 Notes +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Dart 2.16. Other versions may work but are not guaranteed to work as they haven't been tested. Versions below Dart 2.14 will not work, because Apwrite SDK requires Dart 2.14 diff --git a/dart/generate-website-screenshot/lib/main.dart b/dart/generate-website-screenshot/lib/main.dart new file mode 100644 index 00000000..df472d02 --- /dev/null +++ b/dart/generate-website-screenshot/lib/main.dart @@ -0,0 +1,58 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; + +Future start(final req, final res) async { + // Validating payload + Map data; + try { + data = jsonDecode(req.payload); + } on FormatException { + res.json({ + "success": false, + "message": "Invalid Payload.", + }); + return; + } + + // Checking if url Parameter is present in the payload + if (!data.containsKey("url")) { + res.json({ + "success": false, + "message": "Missing parameter url.", + }); + return; + } + + final url = data["url"]; + + // Checking if SCREEENLY_API_KEY is provided in Variables. + if (req.variables['SCREEENLY_API_KEY'] == null) { + res.json({ + "success": false, + "message": "Missing Screeenly API Key in variables", + }); + return; + } + + final api_key = req.variables['SCREEENLY_API_KEY']; + + var parsedUrl = Uri.parse( + "http://screeenly.com/api/v1/fullsize?key=${api_key}&url=${url}"); + + // Sending Post request to Screenly to get the screenshot. + var response = await http.post(parsedUrl); + + // Response if the request was a success + if (response.statusCode == 200) { + Map parsedBody = jsonDecode(response.body); + res.json({"success": true, "screenshot": parsedBody["base64_raw"]}); + } + + // Response otherwise + else { + Map parsedBody = jsonDecode(response.body); + final title = parsedBody['title']; + final message = parsedBody['message']; + res.json({"success": false, "message": '$title: $message'}); + } +} diff --git a/dart/generate-website-screenshot/pubspec.yaml b/dart/generate-website-screenshot/pubspec.yaml new file mode 100644 index 00000000..12eb1d4c --- /dev/null +++ b/dart/generate-website-screenshot/pubspec.yaml @@ -0,0 +1,9 @@ +name: generate_website_screenshot +description: "" +version: 1.0.0 + +environment: + sdk: '>=2.14.0 <3.0.0' + +dependencies: + http: ^0.13.4 diff --git a/dart/generate_giphy_gif/README.md b/dart/generate_giphy_gif/README.md new file mode 100644 index 00000000..fcd20a82 --- /dev/null +++ b/dart/generate_giphy_gif/README.md @@ -0,0 +1,53 @@ +# 🖼️ Get Giphy GIF + +A Dart Cloud Function for generating Giphy GIF from the [Giphy API](https://developers.giphy.com/docs/api#quick-start-guide). + +_Example input:_ + +```json +{ + "search": "good morning" +} +``` + +_Example output:_ + + +```json +{ + "search": "good morning", + "gif": "https://giphy.com/gifs/text-gif-sticker-brittdoesdesign-MS9Yq6Y718CSiDTxR5" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +**GIPHY_API_KEY** - Your Giphy API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd dart/generate_giphy_gif +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=lib/main.dart --rm --interactive --tty --volume $PWD:/usr/code openruntimes/dart:v2-2.16 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/dart:v2-2.16 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Dart runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dart-2.16). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Dart 2.16. Other versions may work but are not guaranteed to work as they haven't been tested. Versions below Dart 2.14 will not work, because Apwrite SDK requires Dart 2.14, \ No newline at end of file diff --git a/dart/generate_giphy_gif/lib/main.dart b/dart/generate_giphy_gif/lib/main.dart new file mode 100644 index 00000000..290ca220 --- /dev/null +++ b/dart/generate_giphy_gif/lib/main.dart @@ -0,0 +1,37 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:http/http.dart' as http; + +Future start(final req, final res) async { + final APIKey = req.variables["GIPHY_API_KEY"]; + + Map data = jsonDecode(req.payload); + + if (!data.containsKey("search")) { + throw new Exception("Missing Search Query"); + } + + if (req.variables['GIPHY_API_KEY'] == null) { + throw new Exception("Missing Giphy API Key in environment variables"); + } + + final search = data["search"]; + + // Download image into buffer + var parsedUrl = Uri.parse("https://api.giphy.com/v1/gifs/search?api_key=${APIKey}&q=${search}&limit=1"); + var response = await http.get(parsedUrl); + + if (response.statusCode != 200) { + throw new Exception("Failed to get GIF"); + } + + // Parse response + Map parsedBody = jsonDecode(response.body); + + Map result = { + "search": search, + "url": parsedBody["data"][0]['url'] + }; + + res.json(result); +} \ No newline at end of file diff --git a/dart/generate_giphy_gif/pubspec.yaml b/dart/generate_giphy_gif/pubspec.yaml new file mode 100644 index 00000000..bdae38fd --- /dev/null +++ b/dart/generate_giphy_gif/pubspec.yaml @@ -0,0 +1,9 @@ +name: object_detection +description: "" +version: 1.0.0 + +environment: + sdk: '>=2.14.0 <3.0.0' + +dependencies: + http: ^0.13.4 \ No newline at end of file diff --git a/dart/generate_map/README.md b/dart/generate_map/README.md new file mode 100644 index 00000000..72efb023 --- /dev/null +++ b/dart/generate_map/README.md @@ -0,0 +1,72 @@ +# 🗺️ Generate Map + +A Dart Cloud Function that generates a static map base64 encoded image at given latitude and longitute. + +_Example input 1:_ + +```json +{ + "lat": "50", + "lng": "50" +} +``` + +_Example output 1:_ + + +```json +{ + "success": "true", + "image": "9j..longString.dasdsdasd/sadas/d/asd/asdasfasasfssdafad=" +} +``` +_Example input 2:_ + +```json +{ + "lat": "50", + "lng": "-270" +} +``` + +_Example output 2:_ + + +```json +{ + "success": "false", + "message": "The longitude must be between -180 and 180" +} +``` + +## 📝 Variables + +List of variables used by this cloud function: + +- **MAPQUEST_API_KEY** - Your MAP Quest API KEY + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd dart/generate_map +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=lib/main.dart --rm --interactive --tty --volume $PWD:/usr/code openruntimes/dart:v2-2.16 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/dart:v2-2.16 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Dart runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dart-2.16). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Dart 2.16. Other versions may work but are not guaranteed to work as they haven't been tested. Versions below Dart 2.14 will not work, because Apwrite SDK requires Dart 2.14, diff --git a/dart/generate_map/lib/main.dart b/dart/generate_map/lib/main.dart new file mode 100644 index 00000000..dea19fb4 --- /dev/null +++ b/dart/generate_map/lib/main.dart @@ -0,0 +1,82 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; + +void returnFailure(final res, final msg) { + res.json({ + "success": false, + "message": msg, + }); +} + +Future start(final req, final res) async { + Map data; + + try { + data = jsonDecode(req.payload); + } catch (err) { + returnFailure(res, err.toString()); + return; + } + + if (!data.containsKey("lat")) { + returnFailure(res, "The payload must contain latitude!"); + return; + } + + if (!data.containsKey("lng")) { + returnFailure(res, "The payload must contain longitude!"); + return; + } + + final lat = data["lat"].toString(); + final lng = data["lng"].toString(); + + final mapQuestAPIKey = req.variables["MAPQUEST_API_KEY"]; + if (mapQuestAPIKey == null) { + returnFailure( + res, "MAPQUEST_API_KEY is not provided in the environment variables"); + return; + } + + var doubleLat = double.tryParse(lat); + var doubleLng = double.tryParse(lng); + + //checks + if (doubleLat == null) { + returnFailure(res, "Latitude must be a number"); + return; + } + if (doubleLng == null) { + returnFailure(res, "Longitude must be a number"); + return; + } + if (doubleLng > 180 || doubleLng < -180) { + returnFailure(res, "The longitude must be between -180 and 180"); + return; + } + if (doubleLat > 90 || doubleLat < -90) { + returnFailure(res, "The latitude must be between -90 and 90"); + return; + } + + //make the http request + var parsedUrl = Uri.parse( + "https://www.mapquestapi.com/staticmap/v5/map?key=$mapQuestAPIKey¢er=$lat,$lng"); + var response = await http.get(parsedUrl); + + if (response.statusCode != 200) { + returnFailure(res, "Failed to get the map: ${response.body}"); + return; + } + + //Getting image + var imageBuffer = response.bodyBytes; + //converting to base64 + String base64Image = base64Encode(imageBuffer); + + Map result = { + "success": true, + "image": base64Image, + }; + res.json(result); +} diff --git a/dart/generate_map/pubspec.yaml b/dart/generate_map/pubspec.yaml new file mode 100644 index 00000000..69ce8db8 --- /dev/null +++ b/dart/generate_map/pubspec.yaml @@ -0,0 +1,9 @@ +name: generate_map +description: "" +version: 1.0.0 + +environment: + sdk: ">=2.14.0 <3.0.0" + +dependencies: + http: ^0.13.4 diff --git a/dart/generate_short_url/README.md b/dart/generate_short_url/README.md new file mode 100644 index 00000000..93d12a5f --- /dev/null +++ b/dart/generate_short_url/README.md @@ -0,0 +1,99 @@ +# 🌐 Shorten any URL using bitly and tinyurl. + +A Dart Cloud Function that shortens any given URL using bitly and tinyurl. + +_Example input 1:_ + +```json +{ + "provider": "bitly", + "url": "https://www.google.com" +} +``` + +_Example output 1:_ + +```json +{ + "success": true, + "url": "https://bit.ly/3SDv4VA" +} +``` + +_Example input 2:_ + +```json +{ + "provider": "tinyurl", + "url": "https://www.google.com" +} +``` + +_Example output 2:_ + +```json +{ + "success": true, + "url": "https://tinyurl.com/2p9hzpun" +} +``` + +_Example input 3:_ + +```json +{ + "provider": "tinyurl", + "url": "httpswwwgooglecom" +} +``` + +_Example output 3:_ + +```json +{ + "success": false, + "message": "Invalid URL" +} +``` + +If the API Key is not correct, you would get: + +```json +{ + "success": false, + "message": "Invalid API key" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +* **BITLY_API_KEY** - API Key for Bitly +* **TINYURL_API_KEY** - API Key for TinyUrl + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd dart/generate_short_url +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=lib/main.dart --rm --interactive --tty --volume ${PWD}:/usr/code openruntimes/dart:v2-2.16 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume ${PWD}/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/dart:v2-2.16 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Dart runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dart-2.16). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Dart 2.18. Other versions may work but are not guaranteed to work as they haven't been tested. Versions below Dart 2.14 will not work, because Apwrite SDK requires Dart 2.14, diff --git a/dart/generate_short_url/lib/main.dart b/dart/generate_short_url/lib/main.dart new file mode 100644 index 00000000..9fa20bb0 --- /dev/null +++ b/dart/generate_short_url/lib/main.dart @@ -0,0 +1,123 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; + +Future bitly(final res, String url, String token) async { + var reqUrl = Uri.parse("https://api-ssl.bitly.com/v4/shorten"); + + var body = { + "long_url": url, + }; + + var headers = { + "Content-Type": "application/json", + "Authorization": "Bearer $token", + }; + + var response = + await http.post(reqUrl, body: json.encode(body), headers: headers); + var resBody = json.decode(response.body); + + if (resBody["message"] == "INVALID_ARG_LONG_URL") { + markFailure(res, "Invalid URL"); + return; + } else if (resBody["message"] == "FORBIDDEN") { + markFailure(res, "Invalid API key"); + return; + } + + try { + if (resBody["link"] == null) { + markFailure(res, "Something went wrong"); + } else { + markSuccess(res, resBody["link"]); + } + } catch (err) { + markFailure(res, "Something went wrong"); + } +} + +Future tinyurl(final res, String url, String token) async { + var reqUrl = Uri.parse("https://api.tinyurl.com/create"); + + var body = { + "url": url, + }; + + var headers = { + "Content-Type": "application/json", + "Authorization": "Bearer $token", + }; + + var response = + await http.post(reqUrl, body: json.encode(body), headers: headers); + var resBody = json.decode(response.body); + + if (resBody["errors"].length != 0) { + var err = resBody["errors"][0]; + + if (err == "Unauthenticated.") { + markFailure(res, "Invalid API key"); + return; + } else if (err == "Invalid URL") { + markFailure(res, "Invalid URL"); + return; + } + + markFailure(res, "Something went wrong"); + return; + } + + markSuccess(res, resBody["data"]["tiny_url"]); +} + +void markSuccess(final res, final url) { + res.json({ + 'success': true, + 'url': url, + }); +} + +void markFailure(final res, final message) { + res.json({ + 'success': false, + 'message': message, + }); +} + +Future start(final req, final res) async { + var provider = ""; + var url = ""; + var apiKey = ""; + + try { + final payload = jsonDecode(req.payload); + provider = payload["provider"]; + url = payload["url"]; + } catch (err) { + markFailure(res, "Payload is invalid"); + return; + } + + provider = provider.toLowerCase(); + if (provider == "bitly") { + try { + apiKey = req.variables["BITLY_API_KEY"]; + } catch (err) { + markFailure(res, "BITLY_API_KEY is not provided"); + return; + } + + await bitly(res, url, apiKey); + } else if (provider == "tinyurl") { + try { + apiKey = req.variables["TINYURL_API_KEY"]; + } catch (err) { + markFailure(res, "TINYURL_API_KEY is not provided"); + return; + } + + await tinyurl(res, url, apiKey); + } else { + markFailure(res, "$provider provider is not supported"); + } +} diff --git a/dart/generate_short_url/pubspec.yaml b/dart/generate_short_url/pubspec.yaml new file mode 100644 index 00000000..f3f15e2a --- /dev/null +++ b/dart/generate_short_url/pubspec.yaml @@ -0,0 +1,8 @@ +name: generate_short_url +description: "" +version: 1.0.0 + +environment: + sdk: '>=2.14.0 <3.0.0' +dependencies: + http: ^0.13.5 diff --git a/dart/object_detection/README.md b/dart/object_detection/README.md new file mode 100644 index 00000000..6f46eded --- /dev/null +++ b/dart/object_detection/README.md @@ -0,0 +1,58 @@ +# 📷 Object Detection using Cloudmersive Vision API + +A Dart Cloud Function for object detection from an image URL. + +_Example input:_ + +```json +{ + "url": "https://picsum.photos/seed/open___runtimes/1000/1000" +} +``` + +_Example output:_ + + +```json +{ + "url": "https://picsum.photos/seed/open___runtimes/1000/1000", + "name": "cake", + "confidence": 0.7977721691131592, + "x": 21, + "y": 5, + "width": 494, + "height": 333 +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +**CLOUDMERSIVE_API_KEY** - Your Cloudmersive API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd dart/object_detection +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=lib/main.dart --rm --interactive --tty --volume $PWD:/usr/code openruntimes/dart:v2-2.16 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/dart:v2-2.16 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Dart runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dart-2.16). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Dart 2.16. Other versions may work but are not guaranteed to work as they haven't been tested. Versions below Dart 2.14 will not work, because Apwrite SDK requires Dart 2.14, \ No newline at end of file diff --git a/dart/object_detection/lib/main.dart b/dart/object_detection/lib/main.dart new file mode 100644 index 00000000..3e731cde --- /dev/null +++ b/dart/object_detection/lib/main.dart @@ -0,0 +1,46 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:http/http.dart' as http; + +Future start(final req, final res) async { + final APIKey = req.variables["CLOUDMERSIVE_API_KEY"]; + + Map data = jsonDecode(req.payload); + + if (!data.containsKey("url")) { + throw new Exception("Missing url"); + } + + if (req.variables['CLOUDMERSIVE_API_KEY'] == null) { + throw new Exception("Missing Cloudmersive API Key in environment variables"); + } + + final url = data["url"]; + + // Download image into buffer + var parsedUrl = Uri.parse(url); + var response = await http.get(parsedUrl); + + if (response.statusCode != 200) { + throw new Exception("Failed to download image"); + } + + var imageBuffer = response.bodyBytes; + + var request = new http.MultipartRequest('POST', Uri.parse("https://api.cloudmersive.com/image/recognize/detect-objects")) + ..files.add(new http.MultipartFile.fromBytes('imageFile', imageBuffer)) + ..headers['Apikey'] = APIKey; + + // Call Cloudmersive OCR API + var cloudmersiveResponse = await request.send(); + + // Parse response + var responseBody = await cloudmersiveResponse.stream.bytesToString(); + Map parsedBody = jsonDecode(responseBody); + + if (parsedBody["Objects"] == null) { + throw new Exception("No objects detected"); + } + + res.json(parsedBody["Objects"][0]); +} \ No newline at end of file diff --git a/dart/object_detection/pubspec.yaml b/dart/object_detection/pubspec.yaml new file mode 100644 index 00000000..bdae38fd --- /dev/null +++ b/dart/object_detection/pubspec.yaml @@ -0,0 +1,9 @@ +name: object_detection +description: "" +version: 1.0.0 + +environment: + sdk: '>=2.14.0 <3.0.0' + +dependencies: + http: ^0.13.4 \ No newline at end of file diff --git a/dart/send-email-with-mailgun/README.md b/dart/send-email-with-mailgun/README.md new file mode 100644 index 00000000..d6953422 --- /dev/null +++ b/dart/send-email-with-mailgun/README.md @@ -0,0 +1,56 @@ +# 📧 Sending Welcome Emails using Mailgun's Email API + + + +A sample Dart Cloud Function for sending emails using the Mailgun API. + + +_Example input:_ + +```json +{ + "name": "John Doe", + "email": "johndoe@gmail.com" +} +``` + + +_Example output:_ + + +``` +email sent successfully. +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +* **MAILGUN_API_KEY** - API Key for Mailgun +* **MAILGUN_DOMAIN** - Domain Name from Mailgun + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd dart/send-email-with-mailgun +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=lib/main.dart --rm --interactive --tty --volume $PWD:/usr/code openruntimes/dart:v2-2.15 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/dart:v2-2.15 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Dart runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dart-2.15). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Dart 2.13, 2.14 and 2.15. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/dart/send-email-with-mailgun/lib/main.dart b/dart/send-email-with-mailgun/lib/main.dart new file mode 100644 index 00000000..7a7ca174 --- /dev/null +++ b/dart/send-email-with-mailgun/lib/main.dart @@ -0,0 +1,127 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:http/http.dart' as http; + +Future start(final req, final res) async { + final domain = req.variables['MAILGUN_DOMAIN']; + final apiKey = req.variables['MAILGUN_API_KEY']; + + // Validate Domain + if ((RegExp(r"^((?!-))(xn--)?[a-z0-9][a-z0-9-_]{0,61}[a-z0-9]{0,1}\.(xn--)?([a-z0-9\-]{1,61}|[a-z0-9-]{1,30}\.[a-z]{2,})$")).hasMatch(domain) == false) { + return res.send('Invalid domain', status: 400); + } + + final mailgun = MailgunMailer( + apiKey: apiKey!, + domain: domain, + ); + + // Get the name and email of the newly created user from the payload + final payload = jsonDecode(req.payload!); + final name = payload['name']; + final email = payload['email']; + + // Validate Email + if ((RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+")).hasMatch(email) == false) { + return res.send('Invalid Email', status: 400); + } + + // Validate Name + if (name.length == 0) { + return res.send('Invalid Name', status: 400); + } + + // Create your email + final sent = await mailgun.send( + from: 'Welcome to My Awesome App ', + to: [email], + subject: 'Welcome on board ${name}!', + text: 'Hi ${name}\nGreat to have you with us. !'); + if (sent) { + res.send("email sent successfully."); + } else { + res.send("failed to send message", status: 400); + } +} + +class MailgunMailer { + final String domain; + final String apiKey; + + MailgunMailer({required this.domain, required this.apiKey}); + + Future send( + {String? from, + List to = const [], + List cc = const [], + List bcc = const [], + List attachments = const [], + String? subject, + String? html, + String? text, + String? template, + Map? options}) async { + var client = http.Client(); + try { + var request = http.MultipartRequest( + 'POST', + Uri( + userInfo: 'api:$apiKey', + scheme: 'https', + host: 'api.mailgun.net', + path: '/v3/$domain/messages')); + if (subject != null) { + request.fields['subject'] = subject; + } + if (html != null) { + request.fields['html'] = html; + } + if (text != null) { + request.fields['text'] = text; + } + if (from != null) { + request.fields['from'] = from; + } + if (to.length > 0) { + request.fields['to'] = to.join(", "); + } + if (cc.length > 0) { + request.fields['cc'] = cc.join(", "); + } + if (bcc.length > 0) { + request.fields['bcc'] = bcc.join(", "); + } + if (template != null) { + request.fields['template'] = template; + } + if (options != null) { + if (options.containsKey('template_variables')) { + request.fields['h:X-Mailgun-Variables'] = + jsonEncode(options['template_variables']); + } + } + if (attachments.length > 0) { + request.headers["Content-Type"] = "multipart/form-data"; + for (var i = 0; i < attachments.length; i++) { + var attachment = attachments[i]; + if (attachment is File) { + request.files.add(await http.MultipartFile.fromPath( + 'attachment', attachment.path)); + } + } + } + var response = await client.send(request); + if (response.statusCode != HttpStatus.ok) { + client.close(); + throw await response.stream.bytesToString(); + } + + return true; + } catch (e) { + client.close(); + throw e; + } finally { + client.close(); + } + } +} diff --git a/dart/send-email-with-mailgun/pubspec.yaml b/dart/send-email-with-mailgun/pubspec.yaml new file mode 100644 index 00000000..08b40e9f --- /dev/null +++ b/dart/send-email-with-mailgun/pubspec.yaml @@ -0,0 +1,9 @@ +name: send_email_with_mailgun +description: "" +version: 1.0.0 + +environment: + sdk: '>=2.12.0 <3.0.0' + +dependencies: + http: ^0.13.3 diff --git a/dart/send_push_notification/README.md b/dart/send_push_notification/README.md new file mode 100644 index 00000000..314ada6e --- /dev/null +++ b/dart/send_push_notification/README.md @@ -0,0 +1,93 @@ +# Send push notification + +A Dart Cloud Function that send push notification using FCM to particular user. + +* Make sure that you are integrated FCM into your app (Web/Android/Apple/Flutter) +* Generate needed `FMC_SERVER_KEY` env variable + +### Hot to get FCM Server Key + +* Visit your FCM console and enter your project +* Go to Project settings and switch to Cloud Messaging tab +* Enable Cloud Messaging API (Legacy) +* Copy server key or create a new one + +_Example input 1:_ + +```json +{ + "user_token": "d0MXntS8ur81...UEFGL" +} +``` + +_Example output 1:_ + +```json +{ + "success": true, + "message": "Push notification successfully sent" +} +``` + +_Example input 2:_ + +```json +{ + "user_token": "" +} +``` + +_Example output 2:_ + +```json +{ + "success": false, + "message": "Payload has incorrect data, user_token is empty" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +* **FMC_SERVER_KEY** - Server Key for FCM settings + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +```shell +git clone https://github.com/open-runtimes/examples.git && cd examples +cd dart/send_push_notification +``` + +2. Enter this function folder and build the code: + +```shell +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=lib/main.dart --rm --interactive --tty --volume $PWD:/usr/code openruntimes/dart:v2-2.17 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +```shell +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/dart:v2-2.17 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate +authorization headers. To learn more about runtime, you can visit Dart +runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dart-2.17). + +4. Execute function: + +```shell +curl http://localhost:3000/ -d '{"variables":{"FMC_SERVER_KEY":"YOUR_FMC_SERVER_KEY"},"payload":"{\"user_token\":\"USER_FCM_TOKEN\"}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +## 📝 Notes + +* This function is designed for use with Appwrite Cloud Functions. You can learn more about it + in [Appwrite docs](https://appwrite.io/docs/functions). +* This example is compatible with Dart 2.17. Other versions may work but are not guaranteed to work as they haven't been + tested. Versions below Dart 2.14 will not work, because Apwrite SDK requires Dart 2.14, diff --git a/dart/send_push_notification/lib/fcm_service.dart b/dart/send_push_notification/lib/fcm_service.dart new file mode 100644 index 00000000..3143b6ea --- /dev/null +++ b/dart/send_push_notification/lib/fcm_service.dart @@ -0,0 +1,28 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; + +class FCMService { + Future sendFCMToUser( + {required String serverKey, + required String userFCMToken, + required Map notificationData}) async { + try { + await http.post( + Uri.parse('https://fcm.googleapis.com/fcm/send'), + headers: { + 'Content-Type': 'application/json; charset=UTF-8', + 'Authorization': 'key=$serverKey' + }, + body: jsonEncode({ + 'to': userFCMToken, + 'notification': notificationData + }), + ); + } catch (e) { + print(e); + return false; + } + return true; + } +} diff --git a/dart/send_push_notification/lib/main.dart b/dart/send_push_notification/lib/main.dart new file mode 100644 index 00000000..75e318d6 --- /dev/null +++ b/dart/send_push_notification/lib/main.dart @@ -0,0 +1,66 @@ +import 'dart:convert'; +import 'fcm_service.dart'; + +void returnSuccess(final res, final message) { + res.json({ + 'success': true, + 'message': message, + }, status: 200); +} + +void returnFailure(final res, final String message) { + res.json({ + 'success': false, + 'message': message, + }, status: 500); +} + +bool checkEnvVariables(final req, final res) { + if (req.variables['FMC_SERVER_KEY'] == null) { + returnFailure(res, "Some Environment variables are not set"); + return false; + } + return true; +} + +bool checkPayload(Map payload, final res) { + if (payload['user_token'] == null) { + returnFailure(res, "Payload has incorrect data, user_token is empty"); + return false; + } + return true; +} + +FCMService? mockFCMService; + +Future start(final req, final res) async { + if (!checkEnvVariables(req, res)) { + return; + } + final String serverKey = req.variables['FMC_SERVER_KEY']; + + final payload = jsonDecode(req.payload == '' ? '{}' : req.payload); + if (!checkPayload(payload, res)) { + return; + } + + final String userToken = payload['user_token']; + + final fcmService = mockFCMService ?? FCMService(); + + final Map notificationData = { + 'title': "Awesome title!", + 'body': "Awesome body", + }; + + final isPushSent = await fcmService.sendFCMToUser( + serverKey: serverKey, + userFCMToken: userToken, + notificationData: notificationData); + + if (isPushSent) { + returnSuccess(res, "Push notification successfully sent"); + } else { + returnFailure(res, "Error while sending push notification"); + } +} diff --git a/dart/send_push_notification/pubspec.yaml b/dart/send_push_notification/pubspec.yaml new file mode 100644 index 00000000..44ad3a1d --- /dev/null +++ b/dart/send_push_notification/pubspec.yaml @@ -0,0 +1,13 @@ +name: send_push_notification +description: "" +version: 1.0.0 + +environment: + sdk: '>=2.17.0 <3.0.0' + +dependencies: + http: ^0.13.5 + +dev_dependencies: + test: ^1.21.4 + mocktail: ^0.3.0 diff --git a/dart/send_push_notification/test/send_push_notification_test.dart b/dart/send_push_notification/test/send_push_notification_test.dart new file mode 100644 index 00000000..cd7fcfee --- /dev/null +++ b/dart/send_push_notification/test/send_push_notification_test.dart @@ -0,0 +1,92 @@ +import 'dart:convert' as convert; + +import 'package:mocktail/mocktail.dart'; +import 'package:send_push_notification/fcm_service.dart'; +import 'package:send_push_notification/main.dart'; +import 'package:test/test.dart'; + + +const fakeFriendDeviceToken = 'fake_friend_device_token'; +const fakeServerKey = 'fake_server_key'; + +class Request { + Map headers = {}; + String payload = ''; + Map variables = { + 'FMC_SERVER_KEY': fakeServerKey + }; +} + +class Response { + String responseAsString = ''; + int statusCode = 0; + + void send(text, {int status = 200}) { + responseAsString = text; + statusCode = status; + } + + void json(obj, {int status = 200}) { + responseAsString = convert.json.encode(obj); + statusCode = status; + } +} + +class MockFCMService extends Mock implements FCMService {} + +void main() { + test('call remote function with incorrect ENV variables', () async { + final req = Request(); + req.variables['FMC_SERVER_KEY'] = null; + + final res = Response(); + await start(req, res); + expect(res.statusCode, 500); + expect(res.responseAsString, + '{"success":false,"message":"Some Environment variables are not set"}'); + }); + + test('call remote function with incorrect payload', () async { + final req = Request(); + req.payload = ''; + + final res = Response(); + await start(req, res); + expect(res.statusCode, 500); + expect(res.responseAsString, + '{"success":false,"message":"Payload has incorrect data, user_token is empty"}'); + }); + + test('mocked services: call remote function with users.create event', + () async { + final req = Request(); + req.payload = '{"user_token": "$fakeFriendDeviceToken"}'; + + final res = Response(); + mockFCMService = MockFCMService(); + + when(() => mockFCMService!.sendFCMToUser( + serverKey: fakeServerKey, + userFCMToken: fakeFriendDeviceToken, + notificationData: any(named: 'notificationData'), + )).thenAnswer((invocation) async => true); + + await start(req, res); + + final capturedFCMDataArgs = verify(() => mockFCMService!.sendFCMToUser( + serverKey: fakeServerKey, + userFCMToken: captureAny(named: 'userFCMToken'), + notificationData: captureAny(named: 'notificationData'), + )).captured; + + expect(capturedFCMDataArgs[0], fakeFriendDeviceToken); + + final pushData = capturedFCMDataArgs[1]; + expect(pushData['Title'], 'Awesome title!'); + expect(pushData['Body'], 'Awesome body'); + + expect(res.statusCode, 200); + expect(res.responseAsString, + '{"success":true,"message":"Push notification successfully sent"}'); + }); +} diff --git a/deno/.gitignore b/deno/.gitignore new file mode 100644 index 00000000..56979529 --- /dev/null +++ b/deno/.gitignore @@ -0,0 +1,35 @@ +*.orig +*.pyc +*.swp + +/.cargo_home/ +/.idea/ +/.vscode/ +gclient_config.py_entries +/gh-pages/ +/target/ +/std/hash/_wasm/target +/tools/wpt/manifest.json + +# Files that help ensure VSCode can work but we don't want checked into the +# repo +/node_modules +/tsconfig.json + +# compiled wasm files +std/wasi/testdata/snapshot_preview1/ + +# generated v8 coverage files +cli/tests/.test_coverage/ + +# MacOS generated files +.DS_Store +.DS_Store? + +# Flamegraphs +/flamebench*.svg +/flamegraph*.svg + +# WPT generated cert files +/tools/wpt/certs/index.txt* +/tools/wpt/certs/serial* \ No newline at end of file diff --git a/deno/compress_image/README.md b/deno/compress_image/README.md new file mode 100644 index 00000000..f1a1a586 --- /dev/null +++ b/deno/compress_image/README.md @@ -0,0 +1,58 @@ +# 🔗 Compressing an image + +A Deno Cloud Function for compressing an image with two providers: +- [Tinypng](https://tinypng.com/) +- [Kraken.io](https://kraken.io/) + +_Example input:_ + +```json +{ + "provider": "tinypng", + "image": "https://www.youtube.com/watch?v=Par3nEq739o" +} +``` + +_Example output:_ + +```json +{ + "success":true, + "image":"https:\/\/dl.kraken.io\/api\/3a\/4c\/93\/41fb5a7b65703c40965b7b727f\/9c75adab-2253-4d0f-ae31-09c94f265238.png" +} +``` + +## 📝 Variables + +For the provider Tinypng: +- TINIFY_API_KEY + +For the provider Kraken.io: +- KRAKEN_API_KEY +- KRAKEN_API_SECRET + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/compress_image +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.24 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.24 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.24). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Deno 1.24. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/deno/compress_image/src/deps.ts b/deno/compress_image/src/deps.ts new file mode 100644 index 00000000..23b23f1d --- /dev/null +++ b/deno/compress_image/src/deps.ts @@ -0,0 +1,6 @@ +import { + encode as base64Encode, + decode as base64Decode +} from "https://deno.land/std@0.82.0/encoding/base64.ts" + +export { base64Encode, base64Decode } \ No newline at end of file diff --git a/deno/compress_image/src/mod.ts b/deno/compress_image/src/mod.ts new file mode 100644 index 00000000..71304321 --- /dev/null +++ b/deno/compress_image/src/mod.ts @@ -0,0 +1,116 @@ +import { base64Encode, base64Decode } from "./deps.ts" + +export default async function (req: any, res: any) { + const { provider, image } = req.payload + if(!provider) { + return res.json({ + success: false, + message: "The provider is missing from the payload." + }) + } + + if(!image) { + return res.json({ + success: false, + message: "The image is missing from the payload." + }) + } + + switch (provider) { + case "tinypng": { + if(!req.variables.TINIFY_API_KEY) { + return res.json({ + success: false, + message: "The environment variables (TINIFY_API_KEY) are required." + }) + } + + const jsonResponse = await fetch("https://api.tinypng.com/shrink", { + method: "POST", + headers: { + "Accept": "*/*", + "Cache-Control": "no-cache", + "Authorization": `Basic ${base64Encode("api:" + req.variables.TINIFY_API_KEY)}` + }, + body: base64Decode(image) + }) + + const jsonData = await jsonResponse.json() + if(jsonData.error) { + return res.json({ + success: false, + message: jsonData.message + }) + } else { + const outputResponse = await fetch(jsonData.output.url) + const outputBuffer = await outputResponse.arrayBuffer() + const outputData = base64Encode(outputBuffer) + + return res.json({ + success: true, + image: outputData + }) + } + } + + case "krakenio": { + if(!req.variables.KRAKEN_API_KEY || !req.variables.KRAKEN_API_SECRET) { + return res.json({ + success: false, + message: "The environment variables (KRAKEN_API_KEY, KRAKEN_API_SECRET) are required." + }) + } + + const formData = new FormData() + formData.append("data", JSON.stringify({ + auth: { + api_key: req.variables.KRAKEN_API_KEY, + api_secret: req.variables.KRAKEN_API_SECRET + }, + wait: true + })) + + const file = new File([ + new Blob([base64Decode(image)]) + ], "Nameless") + formData.append("file", file) + + const jsonResponse = await fetch("https://api.kraken.io/v1/upload", { + method: "POST", + body: formData + }) + + try { + const jsonData = await jsonResponse.json() + if(!jsonData.success) { + return res.json({ + success: false, + message: jsonData.message + }) + } + + + const outputResponse = await fetch(jsonData.kraked_url) + const outputBuffer = await outputResponse.arrayBuffer() + const outputData = base64Encode(outputBuffer) + + return res.json({ + success: true, + image: outputData + }) + } catch(e) { + return res.json({ + success: false, + message: e.toString() + }) + } + } + + default: { + return res.json({ + success: false, + message: "The provider is invalid." + }) + } + } +} \ No newline at end of file diff --git a/deno/convert-phone-number-to-country-name/README.md b/deno/convert-phone-number-to-country-name/README.md new file mode 100644 index 00000000..acde9408 --- /dev/null +++ b/deno/convert-phone-number-to-country-name/README.md @@ -0,0 +1,60 @@ +# 📱 Validate phone number and get it's country information + +A Deno Cloud Function that figures out country in which a phone number is registered. + +_Example input:_ + +```json +{ + "phoneNumber": "+421957215740" +} +``` + +> Function can also accept phone numbers with spaces, for instance `+421 957 215 740`. + + +_Example output:_ + + +```json +{ + "phoneNumber": "+421957215740", + "phonePrefix": "+421", + "countryCode": "SK", + "countryName": "Slovakia" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of your Appwrite server +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key +- **APPWRITE_FUNCTION_PROJECT_ID** - Appwrite project ID. If running on Appwrite, this variable is provided automatically. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/convert_phone_number_to_country_name +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.14 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=mod.ts --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.14 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.14). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Deno 1.14. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/deno/convert-phone-number-to-country-name/deps.ts b/deno/convert-phone-number-to-country-name/deps.ts new file mode 100644 index 00000000..611a9e51 --- /dev/null +++ b/deno/convert-phone-number-to-country-name/deps.ts @@ -0,0 +1 @@ +export * as sdk from "https://deno.land/x/appwrite@3.0.0/mod.ts"; diff --git a/deno/convert-phone-number-to-country-name/mod.ts b/deno/convert-phone-number-to-country-name/mod.ts new file mode 100644 index 00000000..1c2b052e --- /dev/null +++ b/deno/convert-phone-number-to-country-name/mod.ts @@ -0,0 +1,74 @@ +import { sdk } from "./deps.ts"; + +/* +Globally scoped cache used by function. Example value: +[ + { + "code": "+1", + "countryCode": "US", + "countryName": "United States" + } +] +*/ +let phonePrefixList: { + code: string; + countryCode: string; + countryName: string; +}[] | null = null; + + +export default async function(req: any, res: any) { + // Input validation + let phoneNumber: string = ''; + try { + const payload = JSON.parse(req.payload); + phoneNumber = payload.phoneNumber.split(' ').join(''); + } catch(err) { + console.log(err); + throw new Error('Payload is invalid.'); + } + + if(!phoneNumber || !phoneNumber.startsWith('+')) { + throw new Error('Invalid phone number.'); + } + + // Make sure we have envirnment variables required to execute + if( + !req.variables.APPWRITE_FUNCTION_ENDPOINT || + !req.variables.APPWRITE_FUNCTION_PROJECT_ID || + !req.variables.APPWRITE_FUNCTION_API_KEY + ) { + throw new Error('Please provide all required environment variables.'); + } + + // If we don't have cached list of phone number prefixes (first execution only) + if(!phonePrefixList) { + // Init Appwrite SDK + const client = new sdk.Client(); + const locale = new sdk.Locale(client); + + client + .setEndpoint(req.variables.APPWRITE_FUNCTION_ENDPOINT) + .setProject(req.variables.APPWRITE_FUNCTION_PROJECT_ID) + .setKey(req.variables.APPWRITE_FUNCTION_API_KEY); + + // Fetch and store phone number prefixes + const serverResponse = await locale.getCountriesPhones(); + phonePrefixList = serverResponse.phones; + } + + // Get phone prefix + const phonePrefix = phonePrefixList.find((prefix) => phoneNumber.startsWith(prefix.code)); + + if(!phonePrefix) { + throw new Error('Invalid phone number.'); + } + + // Return phone number prefix + res.json({ + phoneNumber, + phonePrefix: phonePrefix.code, + countryCode: phonePrefix.countryCode, + countryName: phonePrefix.countryName + }); +}; \ No newline at end of file diff --git a/deno/deepgram-language-detection/README.md b/deno/deepgram-language-detection/README.md new file mode 100644 index 00000000..ba94d042 --- /dev/null +++ b/deno/deepgram-language-detection/README.md @@ -0,0 +1,65 @@ +# ⚡ deepgramLanguageDetection() + +A Deno Cloud Function for detecting language from audio using [Deepgram](https://deepgram.com/) + +_Example function payload:_ + +```json +{ + "fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Successful function response::_ + +```json +{ "deepgramData": {}, "success": true } +``` + +_Error function response:_ + +```json +{ "message": "error message", "success": false } +``` + +## 📝 Variables + +List of variables used by this cloud function: + +**DEEPGRAM_API_KEY** - Your Deepgram API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/deepgram-language-detection +``` + +2. Enter this function folder and build the code: + +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.21 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.21 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.21). + +4. Curl Command + +```bash +curl http://localhost:3000/ -d '{"variables": {"DEEPGRAM_API_KEY":""},"payload": "{\"fileUrl\":\"https://static.deepgram.com/examples/interview_speech-analytics.wav\"}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Deno 1.21. Other versions may work but are not guarenteed to work as they haven't been tested. diff --git a/deno/deepgram-language-detection/src/mod.ts b/deno/deepgram-language-detection/src/mod.ts new file mode 100644 index 00000000..df439de7 --- /dev/null +++ b/deno/deepgram-language-detection/src/mod.ts @@ -0,0 +1,60 @@ +export default async function (req: any, res: any) { + try { + const APIkey = req.variables["DEEPGRAM_API_KEY"]; + const fileUrl = JSON.parse(req.payload)["fileUrl"]; + + if (!APIkey) { + return res.json({ + success: false, + message: "DEEPGRAM_API_KEY is not set", + }); + } + + if (!fileUrl) { + return res.json({ + success: false, + message: "fileUrl is not provided", + }); + } + + const response = await fetch( + "https://api.deepgram.com/v1/listen?model=general&detect_language=true&punctuate=true", + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Token ${APIkey}`, + }, + body: JSON.stringify({ url: fileUrl }), + } + ); + + if (response.status !== 200) { + if (response.status === 401) { + return res.json({ + success: false, + message: `Status code: ${response.status}, Data: ${response.statusText} - Please check your Deepgram API key`, + }); + } + + const error = await response.json(); + return res.json({ + success: false, + message: error.reason, + }); + } + + const data = await response.json(); + + res.json({ + success: true, + deepgramData: data, + }); + } catch (err) { + console.log(err); + res.json({ + success: false, + message: err.message, + }); + } +} diff --git a/deno/deepgram-topic-detection/README.md b/deno/deepgram-topic-detection/README.md new file mode 100644 index 00000000..857ebe76 --- /dev/null +++ b/deno/deepgram-topic-detection/README.md @@ -0,0 +1,47 @@ +# 🔗 Topic detection with Deepgram + +A Deno Cloud Function for detecting topics with [Deepgram](https://deepgram.com/) + +_Example input:_ + +```json +{ + "fileUrl":"https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Example output:_ + +```json +{"success":true,"deepgramData":{"channels":[{"alternatives":[{"transcript":"another big problem in the speech analytics space. When customers first bring the software on. Is that they... They are blown away by the fact that an engine can monitor hundreds of Kpis. Right? Everything from my new compliance issues to, you know, human human interaction, empathy measurements to upsell aptitude to closing aptitude, They're hundreds literally of Kpis that one to look at. And the speech analytics companies have typically gone to the customer and really bang that trump. We'll get all of these things that we're gonna help you keep an eye on. The reality, however, is that a company even a contact center manager They can't keep track in their brain even if they have a report in front of them. Of that many Kpis. Mh. And frankly, it's overwhelming. So what successful companies do is they bite off no more than they can chew at any given time. The reality is is you can only train a call center agent on a maximum of three skills at any given day. Right? And by focusing on focusing on problem areas, for a week for a month depending on how bad things are. And then once you've mastered that skill to take a baseline of of your performance and move on to the next worst skill. Right? Is the way that company succeed using this product?","confidence":0.9926758,"words":[{"word":"another","start":0.33959904,"end":0.839599,"confidence":0.9995117,"punctuated_word":"another"},{"word":"big","start":0.89893866,"end":1.3989387,"confidence":0.99902344,"punctuated_word":"big"},{"word":"problem","start":1.6580424,"end":2.1580424,"confidence":0.99853516,"punctuated_word":"problem"},{"word":"in","start":2.257335,"end":2.4171462,"confidence":0.99902344,"punctuated_word":"in"},{"word":"the","start":2.4171462,"end":2.6568632,"confidence":0.81884766,"punctuated_word":"the"},{"word":"speech","start":2.6568632,"end":3.0963442,"confidence":1,"punctuated_word":"speech"},{"word":"analytics","start":3.0963442,"end":3.4559197,"confidence":0.9267578,"punctuated_word":"analytics"},{"word":"space","start":3.4559197,"end":3.7755425,"confidence":0.99853516,"punctuated_word":"space."},{"word":"when","start":4.614552,"end":4.9341745,"confidence":0.9814453,"punctuated_word":"When"},{"word":"customers","start":4.9341745,"end":5.4341745,"confidence":0.9921875,"punctuated_word":"customers"},{"word":"first","start":5.4535613,"end":5.6932783,"confidence":0.9296875,"punctuated_word":"first"},{"word":"bring","start":5.6932783,"end":5.8930426,"confidence":0.984375,"punctuated_word":"bring"},{"word":"the","start":5.8930426,"end":6.0528536,"confidence":0.98291016,"punctuated_word":"the"},{"word":"software","start":6.0528536,"end":6.5528536,"confidence":0.9946289,"punctuated_word":"software"},{"word":"on","start":6.5722404,"end":6.7720046,"confidence":0.9926758,"punctuated_word":"on."},{"word":"is","start":7.091627,"end":7.331344,"confidence":0.99658203,"punctuated_word":"Is"},{"word":"that","start":7.331344,"end":7.6509666,"confidence":0.99609375,"punctuated_word":"that"},{"word":"they","start":7.6509666,"end":8.150967,"confidence":0.97509766,"punctuated_word":"they..."},{"word":"they","start":8.824085,"end":9.302795,"confidence":0.9941406,"punctuated_word":"They"},{"word":"are","start":9.302795,"end":9.802795,"confidence":0.99560547,"punctuated_word":"are"},{"word":"blown","start":10.100645,"end":10.379892,"confidence":0.99902344,"punctuated_word":"blown"},{"word":"away","start":10.379892,"end":10.699032,"confidence":0.92089844,"punctuated_word":"away"},{"word":"by","start":10.699032,"end":10.858602,"confidence":0.99853516,"punctuated_word":"by"},{"word":"the","start":10.858602,"end":11.058064,"confidence":0.99853516,"punctuated_word":"the"},{"word":"fact","start":11.058064,"end":11.297419,"confidence":1,"punctuated_word":"fact"},{"word":"that","start":11.297419,"end":11.456989,"confidence":0.96972656,"punctuated_word":"that"},{"word":"an","start":11.456989,"end":11.776129,"confidence":0.99316406,"punctuated_word":"an"},{"word":"engine","start":11.776129,"end":12.276129,"confidence":0.9975586,"punctuated_word":"engine"},{"word":"can","start":12.494193,"end":12.733548,"confidence":0.9995117,"punctuated_word":"can"},{"word":"monitor","start":12.733548,"end":13.233548,"confidence":0.99853516,"punctuated_word":"monitor"},{"word":"hundreds","start":13.331935,"end":13.831935,"confidence":0.9980469,"punctuated_word":"hundreds"},{"word":"of","start":13.970215,"end":14.129785,"confidence":0.99658203,"punctuated_word":"of"},{"word":"kpis","start":14.20957,"end":14.608494,"confidence":0.9951172,"punctuated_word":"Kpis."},{"word":"right","start":15.446236,"end":15.526021,"confidence":0.9951172,"punctuated_word":"Right?"},{"word":"everything","start":16.26,"end":16.76,"confidence":0.99902344,"punctuated_word":"Everything"},{"word":"from","start":16.9,"end":17.3,"confidence":0.99902344,"punctuated_word":"from"},{"word":"my","start":17.3,"end":17.54,"confidence":0.83447266,"punctuated_word":"my"},{"word":"new","start":17.54,"end":18.04,"confidence":0.62890625,"punctuated_word":"new"},{"word":"compliance","start":18.14,"end":18.5,"confidence":0.9995117,"punctuated_word":"compliance"},{"word":"issues","start":18.5,"end":19,"confidence":0.99316406,"punctuated_word":"issues"},{"word":"to","start":19.22,"end":19.46,"confidence":0.99560547,"punctuated_word":"to,"},{"word":"you","start":19.54,"end":19.619999,"confidence":0.93359375,"punctuated_word":"you"},{"word":"know","start":19.619999,"end":19.7,"confidence":0.98535156,"punctuated_word":"know,"},{"word":"human","start":19.98,"end":20.48,"confidence":0.98876953,"punctuated_word":"human"},{"word":"human","start":20.86,"end":21.36,"confidence":0.99902344,"punctuated_word":"human"},{"word":"interaction","start":21.5,"end":21.86,"confidence":0.99560547,"punctuated_word":"interaction,"},{"word":"empathy","start":22.42,"end":22.74,"confidence":0.9926758,"punctuated_word":"empathy"},{"word":"measurements","start":22.74,"end":23.24,"confidence":0.9633789,"punctuated_word":"measurements"},{"word":"to","start":23.9,"end":24.4,"confidence":0.9975586,"punctuated_word":"to"},{"word":"upsell","start":24.46,"end":24.96,"confidence":0.9633789,"punctuated_word":"upsell"},{"word":"aptitude","start":25.63415,"end":26.13415,"confidence":0.9790039,"punctuated_word":"aptitude"},{"word":"to","start":26.552963,"end":27.032345,"confidence":0.9902344,"punctuated_word":"to"},{"word":"closing","start":27.032345,"end":27.511726,"confidence":0.99365234,"punctuated_word":"closing"},{"word":"aptitude","start":27.511726,"end":28.011726,"confidence":0.95410156,"punctuated_word":"aptitude,"},{"word":"they're","start":29.229511,"end":29.50915,"confidence":0.859375,"punctuated_word":"They're"},{"word":"hundreds","start":29.50915,"end":29.988531,"confidence":0.8339844,"punctuated_word":"hundreds"},{"word":"literally","start":29.988531,"end":30.388016,"confidence":0.9863281,"punctuated_word":"literally"},{"word":"of","start":30.388016,"end":30.467913,"confidence":0.77490234,"punctuated_word":"of"},{"word":"kpis","start":30.54781,"end":31.027191,"confidence":0.9926758,"punctuated_word":"Kpis"},{"word":"that","start":31.027191,"end":31.147036,"confidence":0.99609375,"punctuated_word":"that"},{"word":"one","start":31.147036,"end":31.346779,"confidence":0.4958496,"punctuated_word":"one"},{"word":"to","start":31.346779,"end":31.506573,"confidence":0.47265625,"punctuated_word":"to"},{"word":"look","start":31.506573,"end":31.666367,"confidence":0.99609375,"punctuated_word":"look"},{"word":"at","start":31.666367,"end":31.786211,"confidence":0.99902344,"punctuated_word":"at."},{"word":"and","start":33.15874,"end":33.31826,"confidence":0.99121094,"punctuated_word":"And"},{"word":"the","start":33.31826,"end":33.55754,"confidence":0.9868164,"punctuated_word":"the"},{"word":"speech","start":33.55754,"end":34.036102,"confidence":1,"punctuated_word":"speech"},{"word":"analytics","start":34.036102,"end":34.434902,"confidence":0.99316406,"punctuated_word":"analytics"},{"word":"companies","start":34.434902,"end":34.934902,"confidence":0.99365234,"punctuated_word":"companies"},{"word":"have","start":35.6313,"end":35.95034,"confidence":0.99560547,"punctuated_word":"have"},{"word":"typically","start":35.95034,"end":36.45034,"confidence":0.9975586,"punctuated_word":"typically"},{"word":"gone","start":36.46878,"end":36.628304,"confidence":0.9970703,"punctuated_word":"gone"},{"word":"to","start":36.628304,"end":36.74794,"confidence":0.99316406,"punctuated_word":"to"},{"word":"the","start":36.74794,"end":36.907463,"confidence":0.9873047,"punctuated_word":"the"},{"word":"customer","start":36.907463,"end":37.38602,"confidence":0.9975586,"punctuated_word":"customer"},{"word":"and","start":37.38602,"end":37.78482,"confidence":0.9169922,"punctuated_word":"and"},{"word":"really","start":37.78482,"end":38.223503,"confidence":0.99609375,"punctuated_word":"really"},{"word":"bang","start":38.223503,"end":38.502663,"confidence":0.8803711,"punctuated_word":"bang"},{"word":"that","start":38.502663,"end":38.781822,"confidence":0.9633789,"punctuated_word":"that"},{"word":"trump","start":38.781822,"end":39.021103,"confidence":0.6166992,"punctuated_word":"trump."},{"word":"we'll","start":39.260384,"end":39.45978,"confidence":0.6879883,"punctuated_word":"We'll"},{"word":"get","start":39.45978,"end":39.73894,"confidence":0.49804688,"punctuated_word":"get"},{"word":"all","start":39.73894,"end":39.97822,"confidence":0.99853516,"punctuated_word":"all"},{"word":"of","start":39.97822,"end":40.17762,"confidence":0.9873047,"punctuated_word":"of"},{"word":"these","start":40.17762,"end":40.456783,"confidence":0.99658203,"punctuated_word":"these"},{"word":"things","start":40.456783,"end":40.77582,"confidence":0.99902344,"punctuated_word":"things"},{"word":"that","start":40.77582,"end":40.895462,"confidence":0.99316406,"punctuated_word":"that"},{"word":"we're","start":40.895462,"end":41.015102,"confidence":0.9550781,"punctuated_word":"… +``` + +## 📝 Variables + +A single variable: `DEEPGRAM_API_KEY` + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/deepgram-topic-detection +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.24 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.24 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.24). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Deno 1.24. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/deno/deepgram-topic-detection/src/deps.ts b/deno/deepgram-topic-detection/src/deps.ts new file mode 100644 index 00000000..7578090b --- /dev/null +++ b/deno/deepgram-topic-detection/src/deps.ts @@ -0,0 +1 @@ +export * as sdk from "https://raw.githubusercontent.com/MoskalykA/deepgram-deno-sdk/main/mod.ts" \ No newline at end of file diff --git a/deno/deepgram-topic-detection/src/mod.ts b/deno/deepgram-topic-detection/src/mod.ts new file mode 100644 index 00000000..0c9b2f37 --- /dev/null +++ b/deno/deepgram-topic-detection/src/mod.ts @@ -0,0 +1,38 @@ +import { sdk } from "./deps.ts" + +export default async function (req: any, res: any) { + if (!req.variables.DEEPGRAM_API_KEY) { + return res.json({ + success: false, + message: "The environment variables (DEEPGRAM_API_KEY) are required." + }) + } + + const { fileUrl } = req.payload + if (!fileUrl) { + return res.json({ + success: false, + message: "The link to the audio file is missing." + }) + } + + try { + const deepgram = await sdk.default(req.variables.DEEPGRAM_API_KEY) + const transcription = await deepgram.transcription.preRecorded({ + url: fileUrl + }, { + punctuate: true, + detect_topics: true + }) + + res.json({ + success: true, + deepgramData: transcription.results + }) + } catch(e) { + res.json({ + success: false, + message: e.toString() + }) + } +} \ No newline at end of file diff --git a/deno/deepgram-transcribe-audio/README.md b/deno/deepgram-transcribe-audio/README.md new file mode 100644 index 00000000..98b843db --- /dev/null +++ b/deno/deepgram-transcribe-audio/README.md @@ -0,0 +1,47 @@ +# 🔗 Transcribe audio with Deepgram + +A Deno Cloud Function for transcribing the audio with [Deepgram](https://deepgram.com/) + +_Example input:_ + +```json +{ + "fileUrl":"https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Example output:_ + +```json +{"success":true,"deepgramData":{"channels":[{"alternatives":[{"transcript":"another big problem in the speech analytics space. When customers first bring the software on. Is that they they are blown away by the fact that an engine can monitor hundreds of Kpis. Right? Everything from my new compliance issues to, you know, human human interaction, empathy measurements to upsell aptitude to closing aptitude, They're hundreds literally of Kpis that one to look at. And the speech analytics companies have typically gone to the customer and really bang that trump. We'll get all of these things that we're gonna help you keep an eye on. The reality, however, is that a company even a contact center manager They can't keep track in their brain even if they have a report in front of them. Of that many Kpis. Mh. And frankly, it's overwhelming. So what successful companies do is they bite off no more than they chew at any given time. The reality is is you can only train a call center agent on a maximum of three skills at any given day. Right? And by focusing on focusing on problem areas, for a week for a month depending on how bad things are. And then once you've mastered that skill to take a baseline of of your performance and move on to the next worst skill. Right? Is the way that company succeed using this product?","confidence":0.9926758,"words":[{"word":"another","start":0.33959904,"end":0.839599,"confidence":0.9995117,"punctuated_word":"another"},{"word":"big","start":0.89893866,"end":1.3989387,"confidence":0.99902344,"punctuated_word":"big"},{"word":"problem","start":1.6580424,"end":2.1580424,"confidence":0.99853516,"punctuated_word":"problem"},{"word":"in","start":2.257335,"end":2.4171462,"confidence":0.99902344,"punctuated_word":"in"},{"word":"the","start":2.4171462,"end":2.6568632,"confidence":0.8208008,"punctuated_word":"the"},{"word":"speech","start":2.6568632,"end":3.0963442,"confidence":1,"punctuated_word":"speech"},{"word":"analytics","start":3.0963442,"end":3.4559197,"confidence":0.9296875,"punctuated_word":"analytics"},{"word":"space","start":3.4559197,"end":3.7755425,"confidence":0.99853516,"punctuated_word":"space."},{"word":"when","start":4.614552,"end":4.9341745,"confidence":0.9814453,"punctuated_word":"When"},{"word":"customers","start":4.9341745,"end":5.4341745,"confidence":0.9916992,"punctuated_word":"customers"},{"word":"first","start":5.4535613,"end":5.6932783,"confidence":0.921875,"punctuated_word":"first"},{"word":"bring","start":5.6932783,"end":5.8930426,"confidence":0.97998047,"punctuated_word":"bring"},{"word":"the","start":5.8930426,"end":6.0528536,"confidence":0.9819336,"punctuated_word":"the"},{"word":"software","start":6.0528536,"end":6.5528536,"confidence":0.9951172,"punctuated_word":"software"},{"word":"on","start":6.5722404,"end":6.7720046,"confidence":0.99121094,"punctuated_word":"on."},{"word":"is","start":7.091627,"end":7.331344,"confidence":0.99658203,"punctuated_word":"Is"},{"word":"that","start":7.331344,"end":7.6509666,"confidence":0.99560547,"punctuated_word":"that"},{"word":"they","start":7.6509666,"end":8.150967,"confidence":0.9838867,"punctuated_word":"they"},{"word":"they","start":8.824085,"end":9.302795,"confidence":0.99365234,"punctuated_word":"they"},{"word":"are","start":9.302795,"end":9.802795,"confidence":0.9946289,"punctuated_word":"are"},{"word":"blown","start":10.100645,"end":10.379892,"confidence":0.99902344,"punctuated_word":"blown"},{"word":"away","start":10.379892,"end":10.699032,"confidence":0.92822266,"punctuated_word":"away"},{"word":"by","start":10.699032,"end":10.858602,"confidence":0.99853516,"punctuated_word":"by"},{"word":"the","start":10.858602,"end":11.058064,"confidence":0.99853516,"punctuated_word":"the"},{"word":"fact","start":11.058064,"end":11.297419,"confidence":1,"punctuated_word":"fact"},{"word":"that","start":11.297419,"end":11.456989,"confidence":0.9975586,"punctuated_word":"that"},{"word":"an","start":11.456989,"end":11.776129,"confidence":0.99316406,"punctuated_word":"an"},{"word":"engine","start":11.776129,"end":12.276129,"confidence":0.9970703,"punctuated_word":"engine"},{"word":"can","start":12.494193,"end":12.733548,"confidence":0.9995117,"punctuated_word":"can"},{"word":"monitor","start":12.733548,"end":13.233548,"confidence":0.99853516,"punctuated_word":"monitor"},{"word":"hundreds","start":13.331935,"end":13.831935,"confidence":0.9980469,"punctuated_word":"hundreds"},{"word":"of","start":13.970215,"end":14.129785,"confidence":0.99609375,"punctuated_word":"of"},{"word":"kpis","start":14.20957,"end":14.608494,"confidence":0.99609375,"punctuated_word":"Kpis."},{"word":"right","start":15.446236,"end":15.526021,"confidence":0.99365234,"punctuated_word":"Right?"},{"word":"everything","start":16.26,"end":16.76,"confidence":0.99902344,"punctuated_word":"Everything"},{"word":"from","start":16.9,"end":17.3,"confidence":0.9995117,"punctuated_word":"from"},{"word":"my","start":17.3,"end":17.54,"confidence":0.84521484,"punctuated_word":"my"},{"word":"new","start":17.54,"end":18.04,"confidence":0.6513672,"punctuated_word":"new"},{"word":"compliance","start":18.14,"end":18.5,"confidence":0.9995117,"punctuated_word":"compliance"},{"word":"issues","start":18.5,"end":19,"confidence":0.99365234,"punctuated_word":"issues"},{"word":"to","start":19.22,"end":19.46,"confidence":0.99560547,"punctuated_word":"to,"},{"word":"you","start":19.54,"end":19.619999,"confidence":0.9501953,"punctuated_word":"you"},{"word":"know","start":19.619999,"end":19.7,"confidence":0.98535156,"punctuated_word":"know,"},{"word":"human","start":19.98,"end":20.48,"confidence":0.9892578,"punctuated_word":"human"},{"word":"human","start":20.86,"end":21.36,"confidence":0.9995117,"punctuated_word":"human"},{"word":"interaction","start":21.5,"end":21.86,"confidence":0.99560547,"punctuated_word":"interaction,"},{"word":"empathy","start":22.42,"end":22.74,"confidence":0.99316406,"punctuated_word":"empathy"},{"word":"measurements","start":22.74,"end":23.24,"confidence":0.9741211,"punctuated_word":"measurements"},{"word":"to","start":23.9,"end":24.4,"confidence":0.99658203,"punctuated_word":"to"},{"word":"upsell","start":24.46,"end":24.96,"confidence":0.96777344,"punctuated_word":"upsell"},{"word":"aptitude","start":25.63415,"end":26.13415,"confidence":0.9790039,"punctuated_word":"aptitude"},{"word":"to","start":26.552963,"end":27.032345,"confidence":0.9902344,"punctuated_word":"to"},{"word":"closing","start":27.032345,"end":27.511726,"confidence":0.99365234,"punctuated_word":"closing"},{"word":"aptitude","start":27.511726,"end":28.011726,"confidence":0.95410156,"punctuated_word":"aptitude,"},{"word":"they're","start":29.229511,"end":29.50915,"confidence":0.8588867,"punctuated_word":"They're"},{"word":"hundreds","start":29.50915,"end":29.988531,"confidence":0.8330078,"punctuated_word":"hundreds"},{"word":"literally","start":29.988531,"end":30.388016,"confidence":0.9863281,"punctuated_word":"literally"},{"word":"of","start":30.388016,"end":30.467913,"confidence":0.77441406,"punctuated_word":"of"},{"word":"kpis","start":30.54781,"end":31.027191,"confidence":0.9926758,"punctuated_word":"Kpis"},{"word":"that","start":31.027191,"end":31.147036,"confidence":0.99609375,"punctuated_word":"that"},{"word":"one","start":31.147036,"end":31.346779,"confidence":0.4975586,"punctuated_word":"one"},{"word":"to","start":31.346779,"end":31.506573,"confidence":0.46948242,"punctuated_word":"to"},{"word":"look","start":31.506573,"end":31.666367,"confidence":0.99609375,"punctuated_word":"look"},{"word":"at","start":31.666367,"end":31.786211,"confidence":0.99902344,"punctuated_word":"at."},{"word":"and","start":33.15874,"end":33.31826,"confidence":0.99121094,"punctuated_word":"And"},{"word":"the","start":33.31826,"end":33.55754,"confidence":0.9868164,"punctuated_word":"the"},{"word":"speech","start":33.55754,"end":34.036102,"confidence":1,"punctuated_word":"speech"},{"word":"analytics","start":34.036102,"end":34.434902,"confidence":0.99316406,"punctuated_word":"analytics"},{"word":"companies","start":34.434902,"end":34.934902,"confidence":0.99365234,"punctuated_word":"companies"},{"word":"have","start":35.6313,"end":35.95034,"confidence":0.99560547,"punctuated_word":"have"},{"word":"typically","start":35.95034,"end":36.45034,"confidence":0.9975586,"punctuated_word":"typically"},{"word":"gone","start":36.46878,"end":36.628304,"confidence":0.9970703,"punctuated_word":"gone"},{"word":"to","start":36.628304,"end":36.74794,"confidence":0.99316406,"punctuated_word":"to"},{"word":"the","start":36.74794,"end":36.907463,"confidence":0.9873047,"punctuated_word":"the"},{"word":"customer","start":36.907463,"end":37.38602,"confidence":0.9975586,"punctuated_word":"customer"},{"word":"and","start":37.38602,"end":37.78482,"confidence":0.9165039,"punctuated_word":"and"},{"word":"really","start":37.78482,"end":38.223503,"confidence":0.99609375,"punctuated_word":"really"},{"word":"bang","start":38.223503,"end":38.502663,"confidence":0.8803711,"punctuated_word":"bang"},{"word":"that","start":38.502663,"end":38.781822,"confidence":0.9633789,"punctuated_word":"that"},{"word":"trump","start":38.781822,"end":39.021103,"confidence":0.6171875,"punctuated_word":"trump."},{"word":"we'll","start":39.260384,"end":39.45978,"confidence":0.6879883,"punctuated_word":"We'll"},{"word":"get","start":39.45978,"end":39.73894,"confidence":0.49902344,"punctuated_word":"get"},{"word":"all","start":39.73894,"end":39.97822,"confidence":0.99853516,"punctuated_word":"all"},{"word":"of","start":39.97822,"end":40.17762,"confidence":0.9873047,"punctuated_word":"of"},{"word":"these","start":40.17762,"end":40.456783,"confidence":0.99658203,"punctuated_word":"these"},{"word":"things","start":40.456783,"end":40.77582,"confidence":0.99902344,"punctuated_word":"things"},{"word":"that","start":40.77582,"end":40.895462,"confidence":0.99316406,"punctuated_word":"that"},{"word":"we're","start":40.895462,"end":41.015102,"confidence":0.9550781,"punctuated_word":"we're"},{"w… +``` + +## 📝 Variables + +A single variable: `DEEPGRAM_API_KEY` + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/deepgram-transcribe-audio +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.24 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.24 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.24). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Deno 1.24. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/deno/deepgram-transcribe-audio/src/deps.ts b/deno/deepgram-transcribe-audio/src/deps.ts new file mode 100644 index 00000000..2b2bc0ac --- /dev/null +++ b/deno/deepgram-transcribe-audio/src/deps.ts @@ -0,0 +1 @@ +export * as sdk from "https://raw.githubusercontent.com/deepgram-devs/deepgram-deno-sdk/main/mod.ts" \ No newline at end of file diff --git a/deno/deepgram-transcribe-audio/src/mod.ts b/deno/deepgram-transcribe-audio/src/mod.ts new file mode 100644 index 00000000..76c46612 --- /dev/null +++ b/deno/deepgram-transcribe-audio/src/mod.ts @@ -0,0 +1,37 @@ +import { sdk } from "./deps.ts" + +export default async function (req: any, res: any) { + if (!req.variables.DEEPGRAM_API_KEY) { + return res.json({ + success: false, + message: "The environment variables (DEEPGRAM_API_KEY) are required." + }) + } + + const { fileUrl } = req.payload + if (!fileUrl) { + return res.json({ + success: false, + message: "The link to the audio file is missing." + }) + } + + try { + const deepgram = await sdk.default(req.variables.DEEPGRAM_API_KEY) + const transcription = await deepgram.transcription.preRecorded({ + url: fileUrl + }, { + punctuate: true + }) + + res.json({ + success: true, + deepgramData: transcription.results + }) + } catch(e) { + res.json({ + success: false, + message: e.toString() + }) + } +} \ No newline at end of file diff --git a/deno/deepgram-transcribe-video/README.md b/deno/deepgram-transcribe-video/README.md new file mode 100644 index 00000000..0fc4f2f0 --- /dev/null +++ b/deno/deepgram-transcribe-video/README.md @@ -0,0 +1,65 @@ +# ⚡ deepgramTranscribeVideo() + +A Deno Cloud Function for transcribing video using [Deepgram](https://deepgram.com/) + +_Example function payload:_ + +```json +{ + "fileUrl": "https://rawcdn.githack.com/deepgram-devs/transcribe-videos/62fc7769d6e2bf38e420ee5224060922af4546f7/deepgram.mp4" +} +``` + +_Successful function response::_ + +```json +{ "deepgramData": {}, "success": true } +``` + +_Error function response:_ + +```json +{ "message": "error message", "success": false } +``` + +## 📝 Variables + +List of variables used by this cloud function: + +**DEEPGRAM_API_KEY** - Your Deepgram API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/deepgram-transcribe-video +``` + +2. Enter this function folder and build the code: + +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.21 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.21 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.21). + +4. Curl Command + +```bash +curl http://localhost:3000/ -d '{"variables": {"DEEPGRAM_API_KEY":""},"payload": "{\"fileUrl\":\"https://static.deepgram.com/examples/interview_speech-analytics.wav\"}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Deno 1.21. Other versions may work but are not guarenteed to work as they haven't been tested. diff --git a/deno/deepgram-transcribe-video/src/mod.ts b/deno/deepgram-transcribe-video/src/mod.ts new file mode 100644 index 00000000..ed72991a --- /dev/null +++ b/deno/deepgram-transcribe-video/src/mod.ts @@ -0,0 +1,61 @@ +export default async function (req: any, res: any) { + // try catch everything + try { + const apikey = req.variables["DEEPGRAM_API_KEY"]; + const fileUrl = JSON.parse(req.payload)["fileUrl"]; + + // error handling + if (!apikey) { + return res.json({ + success: false, + message: "Missing Deepgram API key", + }); + } + + if (!fileUrl) { + return res.json({ + success: false, + message: "Missing fileUrl", + }); + } + + const response = await fetch( + "https://api.deepgram.com/v1/listen?model=video", + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Token ${apikey}`, + }, + body: JSON.stringify({ url: fileUrl }), + } + ); + + if (response.status !== 200) { + if (response.status === 401) { + return res.json({ + success: false, + message: `Status code: ${response.status}, Data: ${response.statusText} - Please check your Deepgram API key`, + }); + } + + const error = await response.json(); + return res.json({ + success: false, + message: error.reason, + }); + } + + const data = await response.json(); + + return res.json({ + success: true, + deepgramData: data, + }); + } catch (error) { + return res.json({ + success: false, + message: error.message, + }); + } +} diff --git a/deno/deepgram_audio_summary/README.md b/deno/deepgram_audio_summary/README.md new file mode 100644 index 00000000..ac80731b --- /dev/null +++ b/deno/deepgram_audio_summary/README.md @@ -0,0 +1,70 @@ +# ⚡ deepgramAudioSummary() + +A Deno Cloud Function for transcribing audio using [Deepgram](https://deepgram.com/) + +_Example function payload:_ + +```json +{ + "fileUrl":"https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Successful function response::_ + +```json +{"success":true,"deepgramData":{}} +``` + +_Error function response:_ + +```json +{"success":false,"message":"Please provide a valid file URL."} +``` + +## 📝 Variables + +List of variables used by this cloud function: + +**DEEPGRAM_API_KEY** - Your Deepgram API key.## 🚀 Deployment + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/deepgram_audio_summary +``` + +2. Enter this function folder and build the code: + +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.21 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.21 sh /usr/local/src/start.sh +``` + +4. In the new terminal execute the following function: +``` +curl -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" -X POST http://localhost:3000/ -d ' { + "payload": "{\"fileUrl\": \"https://static.deepgram.com/examples/interview_speech-analytics.wav\"}", + + "variables": { + "DEEPGRAM_API_KEY": "Your APIKey" + } +}' +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.24). + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Deno 1.21 and 1.24. Other versions may work but are not guarenteed to work as they haven't been tested. diff --git a/deno/deepgram_audio_summary/src/mod.ts b/deno/deepgram_audio_summary/src/mod.ts new file mode 100644 index 00000000..1b746c2b --- /dev/null +++ b/deno/deepgram_audio_summary/src/mod.ts @@ -0,0 +1,59 @@ +export default async function (req: any, res: any) { + try { + const apikey = req.variables["DEEPGRAM_API_KEY"]; + const fileUrl = JSON.parse(req.payload)["fileUrl"]; + + if (!apikey) { + return res.json({ + success: false, + message: "Missing Deepgram API key", + }); + } + + if (!fileUrl) { + return res.json({ + success: false, + message: "Missing fileUrl", + }); + } + + const response = await fetch( + "https://api.deepgram.com/v1/listen?", + { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Token ${apikey}`, + }, + body: JSON.stringify({ url: fileUrl }), + } + ); + + if (response.status !== 200) { + if (response.status === 401) { + return res.json({ + success: false, + message: `Encountered an error trying to make a request: ${response.statusText}`, + }); + } + + const error = await response.json(); + return res.json({ + success: false, + message: error.reason, + }); + } + + const data = await response.json(); + + return res.json({ + success: true, + deepgramData: data, + }); + } catch (error) { + return res.json({ + success: false, + message: error.message, + }); + } + } \ No newline at end of file diff --git a/deno/generate_giphy_gif/README.md b/deno/generate_giphy_gif/README.md new file mode 100644 index 00000000..956fbbe9 --- /dev/null +++ b/deno/generate_giphy_gif/README.md @@ -0,0 +1,53 @@ +# 🖼️ Get Giphy GIF + +A Deno Cloud Function for generating Giphy GIF from the [Giphy API](https://developers.giphy.com/docs/api#quick-start-guide). + +_Example input:_ + +```json +{ + "search": "good morning" +} +``` + +_Example output:_ + + +```json +{ + "search": "good morning", + "gif": "https://giphy.com/gifs/text-gif-sticker-brittdoesdesign-MS9Yq6Y718CSiDTxR5" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +**GIPHY_API_KEY** - Your Giphy API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/generate_giphy_gif +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.14 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.14 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.14). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Deno 1.13 and 1.14. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/deno/generate_giphy_gif/src/mod.ts b/deno/generate_giphy_gif/src/mod.ts new file mode 100644 index 00000000..ec1ea8d3 --- /dev/null +++ b/deno/generate_giphy_gif/src/mod.ts @@ -0,0 +1,32 @@ +export default async function(req: any, res: any) { + const APIkey = req.variables["GIPHY_API_KEY"] + + const { search } = JSON.parse(req.payload); + + if (!search) { + throw new Error("search is required"); + } + + if (!APIkey) { + throw new Error("API key is required"); + } + + // Fetch the gif + const response = await fetch(`https://api.giphy.com/v1/gifs/search?api_key=${APIkey}&q=${search}&limit=1`, + { + method: "GET", + headers: { + "Apikey": APIkey, + } + }); + + // Check status code + if (response.status !== 200) { + throw new Error(`Status code: ${response.status}, Data: ${await response.text()}`); + } + + // Parse the response + const dataJson = await response.json(); + + res.json(dataJson["data"][0]['url']); +} \ No newline at end of file diff --git a/deno/generate_short_url/README.md b/deno/generate_short_url/README.md new file mode 100644 index 00000000..321fbba9 --- /dev/null +++ b/deno/generate_short_url/README.md @@ -0,0 +1,78 @@ +# 🌐 Shorten URL + +A Deno Cloud Function for shortening URL from the [Bitly API](https://dev.bitly.com/) and [TinyURL API](https://tinyurl.com/app/dev). + +_Example input:_ + +```json +{ + "provider": "bitly", + "url": "https://google.com/" +} +``` + +```json +{ + "provider": "tinyurl", + "url": "https://google.com/" +} +``` + +_Example output:_ + +```json +{ + "success": true, + "url": "https://bit.ly/3y3HDkC" +} +``` + +```json +{ + "success": false, + "message": "provider is required" +} +``` + +## 📝 Variables + +List of variables used by this cloud function: + +**BITLY_TOKEN** - Your Bitly API token. +**TINYURL_TOKEN** - Your TInyURL API token. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/generate_short_url +``` + +2. Enter this function folder and build the code: + +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.24 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.24 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.24). + +4. Execute function: + +``` +curl http://localhost:3000/ -d '{"variables":{"BITLY_TOKEN":"[YOUR_API_KEY]"},"payload": "{\"url\":\"https://appwrite.io/\",\"provider\":\"bitly\"}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Deno 1.21 and 1.24. Other versions may work but are not guarenteed to work as they haven't been tested. diff --git a/deno/generate_short_url/src/mod.ts b/deno/generate_short_url/src/mod.ts new file mode 100644 index 00000000..d5793a4f --- /dev/null +++ b/deno/generate_short_url/src/mod.ts @@ -0,0 +1,67 @@ +export default async function (req: any, res: any) { + const { provider, url } = JSON.parse(req.payload); + + if (!provider) { + res.json({ success: false, message: "provider is required" }); + return; + } + + if (!url) { + res.json({ success: false, message: "url is required" }); + return; + } + + if (provider === "bitly") { + const BITLY_TOKEN = req.variables["BITLY_TOKEN"]; + + if (!BITLY_TOKEN) { + res.json({ success: false, message: "BITLY_TOKEN is required" }); + return; + } + + const response = await fetch(`https://api-ssl.bitly.com/v4/shorten`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${BITLY_TOKEN}`, + }, + body: JSON.stringify({ + long_url: url, + }), + }); + + if (response.status >= 400) { + res.json({ success: false, code: response.status, message: `${await response.text()}` }); + return; + } + + const data = await response.json(); + res.json({ success: true, url: data["link"] }); + } else if (provider === "tinyurl") { + const TINYURL_TOKEN = req.variables["TINYURL_TOKEN"]; + + if (!TINYURL_TOKEN) { + res.json({ success: false, message: "TINYURL_TOKEN is required" }); + return; + } + + const response = await fetch(`https://api.tinyurl.com/create`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${TINYURL_TOKEN}`, + }, + body: JSON.stringify({ + url: url, + }), + }); + + if (response.status !== 200) { + res.json({ success: false, message: `${await response.text()}` }); + return; + } + + const data = await response.json(); + res.json({ success: true, url: data.data.tiny_url }); + } +} diff --git a/deno/generate_website_screenshot/README.md b/deno/generate_website_screenshot/README.md new file mode 100644 index 00000000..aece4878 --- /dev/null +++ b/deno/generate_website_screenshot/README.md @@ -0,0 +1,60 @@ +# 🖼️ Get Website ScreenShot from url + +A Deno Cloud Function for generating screenshot of a website from the [screenshotapi.net](https://screenshot-api.gitbook.io/screenshot-api-docs/). + +_Example input:_ + +```json +{ + "url":"https://appwrite.io/" +} + +``` + +_Example output:_ + + +```json +{ + "sucess": true, + "screenshot": "iVBORw0KGgoAAAANSUh...XWkulRXfkcAAAAASUVORK5CYII=" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +**SCREEN_SHOT_API_KEY** - Your screenshotapi.net API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/generate_website_screenshot +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.24 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.24 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.24). + +4. Execute function: + +``` +curl http://localhost:3000/ -d '{"variables":{"SCREEN_SHOT_API_KEY":"25PVQ6R-R124R86-PKB2H0A-Z61P1JR"},"payload":"{\"url\":\"https://appwrite.io/\"}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +## 📝 Notes +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Deno 1.13 and 1.14. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/deno/generate_website_screenshot/src/deps.ts b/deno/generate_website_screenshot/src/deps.ts new file mode 100644 index 00000000..91b149eb --- /dev/null +++ b/deno/generate_website_screenshot/src/deps.ts @@ -0,0 +1,6 @@ +import { + decode as base64Decode, + encode as base64Encode, + } from 'https://deno.land/std@0.82.0/encoding/base64.ts'; + +export { base64Decode, base64Encode }; \ No newline at end of file diff --git a/deno/generate_website_screenshot/src/mod.ts b/deno/generate_website_screenshot/src/mod.ts new file mode 100644 index 00000000..9babf218 --- /dev/null +++ b/deno/generate_website_screenshot/src/mod.ts @@ -0,0 +1,44 @@ +import { base64Encode } from "./deps.ts"; + +const getBase64FromUrl = async (url: string) => { + const data = await fetch(url); + + if (data.ok) { + const blob = await data.blob(); + const arr = await blob.arrayBuffer(); + const base64String = base64Encode(arr); + return base64String; + } else { + throw new Error(await data.text()); + } +}; + +export default async function (req: any, res: any) { + let APIkey: any; + let url: any; + + try { + const payload = JSON.parse(req.payload ?? '{}'); + url = payload.url; + } catch(error) { + res.json({ success: false, message: "Please provide URL." }); + return; + } + try { + APIkey = req.variables["SCREEN_SHOT_API_KEY"]; + } catch(error) { + res.json({ success: false, message: "Please API key." }); + return; + } + + const fetchURL = `https://shot.screenshotapi.net/screenshot?token=${APIkey}&url=${url}&output=image&file_type=png&wait_for_event=load`; + + try { + const response = await getBase64FromUrl(fetchURL); + res.json({ success: true, screenshot: response }); + return; + } catch(error) { + res.json({ success: false, message: error }); + return; + } +} diff --git a/deno/get_price/README.md b/deno/get_price/README.md new file mode 100644 index 00000000..8534f1e4 --- /dev/null +++ b/deno/get_price/README.md @@ -0,0 +1,66 @@ +# Get Price! + +A Deno Appwrite Function to get the price of crypto, stocks, and commodities. Supported types include Bitcoin, Ethereum, Google, Amazon, gold, and silver. + +_Example input:_ + +```json +{ + "type": "gold" +} +``` + +> Other allowed types are: `google`, `amazon`, `ethereum`, `bitcoin`, `gold`, `silver`. + +_Example output:_ + + +```json +{ + "success":true, + "price":1666.81 +} +``` + +```json +{ + "success":false, + "message":"GOLDAPIkey key is required" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **COIN_API_KEY** - Your [Coin API key](https://docs.coinapi.io/#md-docs) +- **ALPHAVANTAGE_API_KEY** - Your [Alphavantage API key](https://www.alphavantage.co/) +- **GOLD_API_KEY** - Your [Gold API key](https://www.goldapi.io/) + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/get_price +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.21 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.21 sh /usr/local/src/start.sh +``` + +4. Execute function: + +``` +curl http://localhost:3000/ -d '{"variables":{"GOLD_API_KEY":"[YOUR_API_KEY]"},"payload": "{\"type\":\"gold\"}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.21). \ No newline at end of file diff --git a/deno/get_price/src/mod.ts b/deno/get_price/src/mod.ts new file mode 100644 index 00000000..a836f800 --- /dev/null +++ b/deno/get_price/src/mod.ts @@ -0,0 +1,100 @@ +export default async function (req: any, res: any) { + const CoinAPIkey = req.variables["COIN_API_KEY"]; + const AlphavantageAPIkey = req.variables["ALPHAVANTAGE_API_KEY"]; + const GOLDAPIkey = req.variables["GOLD_API_KEY"]; + + const payload = JSON.parse(req.payload); + + if (!payload.type) { + res.json({ success: false, message: 'type is required' }); + return; + } + + const type = payload.type.toLowerCase(); + + let price; + if (type === "google" || type === "amazon") { + if (!AlphavantageAPIkey || AlphavantageAPIkey === "") { + res.json({ success: false, message: 'AlphavantageAPI key is required' }); + return; + } + + let code = type === "google" ? "GOOGL" : "AMZN"; + const str = "Time Series (5min)"; + let response: { [str: string]: any } = await fetch( + `https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=${code}&interval=5min&apikey=${AlphavantageAPIkey}`, + { + method: "GET", + headers: { + "User-Agent": "request", + }, + }, + ); + + if (response.status >= 400) { + res.json({ success: false, message: `${await response.text()}` }); + return; + } + + const data = await response.json(); + let price = data[str][Object.keys(data[str])[0]]["1. open"]; + + res.send({ "success": true, "price": price }); + } else if ( + type === "bitcoin" || type === "ethereum" + ) { + if (!CoinAPIkey || CoinAPIkey === "") { + res.json({ success: false, message: 'CoinAPI key is required' }); + return; + } + + let code = type === "bitcoin" ? "BTC" : "ETH"; + let response: { [rate: string]: any } = await fetch( + `https://rest.coinapi.io/v1/exchangerate/${code}/USD`, + { + method: "GET", + headers: { + "X-CoinAPI-Key": CoinAPIkey, + }, + }, + ); + + if (response.status >= 400) { + res.json({ success: false, message: `${await response.text()}` }); + return; + } + + const data = await response.json(); + price = data["rate"]; + res.send({ "success": true, "price": price }); + } else if (type === "gold" || type === "silver") { + if (!GOLDAPIkey || GOLDAPIkey === "") { + res.json({ success: false, message: 'GOLDAPIkey key is required' }); + return; + } + + let code = type === "gold" ? "XAU" : "XAG"; + let response: { [index: string]: any } = await fetch( + `https://www.goldapi.io/api/${code}/USD/`, + { + method: "GET", + headers: { + "x-access-token": GOLDAPIkey, + }, + }, + ); + + if (response.status >= 400) { + res.json({ success: false, message: `${await response.text()}` }); + return; + } + + const data = await response.json(); + + let price = data["price"]; + + res.send({ "success": true, "price": price }); + } else { + res.send({ "success": false, "message": "Type is not supported." }); + } +} diff --git a/deno/object_detection/README.md b/deno/object_detection/README.md new file mode 100644 index 00000000..0dcdc44f --- /dev/null +++ b/deno/object_detection/README.md @@ -0,0 +1,56 @@ +# 📷 Object Detection using Cloudmersive Vision API + +A Deno Cloud Function for object detection from an image URL. + +_Example input:_ + +```json +{ + "url": "https://picsum.photos/id/237/200/300" +} +``` + +_Example output:_ + +```json +[{ + "ObjectClassName": "dog", + "Height": 293, + "Width": 198, + "Score": 0.9331955909729004, + "X": 1, + "Y": 9 +}] +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +**CLOUDMERSIVE_API_KEY** - Your Cloudmersive API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/object_detection +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.14 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.14 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.14). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Deno 1.13 and 1.14. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/deno/object_detection/src/mod.ts b/deno/object_detection/src/mod.ts new file mode 100644 index 00000000..15087a11 --- /dev/null +++ b/deno/object_detection/src/mod.ts @@ -0,0 +1,39 @@ +export default async function(req: any, res: any) { + const APIkey = req.variables["CLOUDMERSIVE_API_KEY"] + + const { url } = JSON.parse(req.payload); + + if (!url) { + throw new Error("URL is required"); + } + + if (!APIkey) { + throw new Error("API key is required"); + } + + // Download the image + const image = await fetch(url).then((response) => response.blob()); + + // Run the image through the Cloudmersive OCR API + var data = new FormData(); + data.append('imageFile', image, 'file'); + + const response = await fetch("https://api.cloudmersive.com/image/recognize/detect-objects", + { + method: "POST", + headers: { + "Apikey": APIkey, + }, + body: data, + }); + + // Check status code + if (response.status !== 200) { + throw new Error(`Status code: ${response.status}, Data: ${await response.text()}`); + } + + // Parse the response + const dataJson = await response.json(); + + res.json(dataJson["Objects"]); +} \ No newline at end of file diff --git a/deno/send_email_with_mailgun/README.md b/deno/send_email_with_mailgun/README.md new file mode 100644 index 00000000..55d9b132 --- /dev/null +++ b/deno/send_email_with_mailgun/README.md @@ -0,0 +1,53 @@ +# 📧 Sending Welcome Emails using Mailgun's Email API + +A sample Deno Cloud Function for sending emails using the Mailgun API. + +_Example input:_ + +```json +{ + "name": "John Doe", + "email": "johndoe@gmail.com" +} +``` + + +_Example output:_ + + +``` +email sent successfully. +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +* **MAILGUN_API_KEY** - API Key for Mailgun +* **MAILGUN_DOMAIN** - Domain Name from Mailgun + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/send_email_with_mailgun +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.14 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.14 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.14). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Deno 1.13 and 1.14. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/deno/send_email_with_mailgun/src/mod.ts b/deno/send_email_with_mailgun/src/mod.ts new file mode 100644 index 00000000..1d648225 --- /dev/null +++ b/deno/send_email_with_mailgun/src/mod.ts @@ -0,0 +1,28 @@ +export default async function(req: any, res: any) { + // Create a new MailGunClient and pass it your API key and API domain + const domain = req.variables["MAILGUN_DOMAIN"]; + const apiKey = req.variables["MAILGUN_API_KEY"]; + + // Get the name and email of the newly created user from Appwrite's environment variable + const payload = JSON.parse(req.payload); + const userName = payload["name"]; + const email = payload["email"]; + + // Create your email + const form = new FormData(); + form.append("from", "Welcome to My Awesome App "); + form.append("to", email); + form.append("subject", `Welcome on board ${userName}!`); + form.append("text", `Hi ${userName}\nGreat to have you with us. !`); + + // Send the email! + fetch(`https://api.mailgun.net/v3/${domain}/messages`, { + method: "POST", + headers: { + Authorization: `Basic ${btoa("api:" + apiKey)}`, + }, + body: form, + }); + + res.send("Success"); +} \ No newline at end of file diff --git a/deno/send_http_request/README.md b/deno/send_http_request/README.md new file mode 100644 index 00000000..b23989c0 --- /dev/null +++ b/deno/send_http_request/README.md @@ -0,0 +1,66 @@ +# 🌐 Send HTTP request + +A Deno Cloud Function for sending HTTP requests + +_Example input:_ + +```json +{ + "url":"https://demo.appwrite.io/v1/locale/countries/eu","method":"GET", + "headers": + { + "x-client-version":"1.0.0" + }, + "body":"{}" +} +``` + +_Example output:_ + +```json +{ + "success":true, + "response": + { + "headers":{}, + "code":200, + "body":"{\"total\":27,\"countries\":[]}" + } +} +``` + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/send_http_request +``` + +2. Enter this function folder and build the code: + +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.24 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.24 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.14). + +4. Execute function: + +```shell +curl http://localhost:3000/ -d '{"payload": "{\"url\":\"https://demo.appwrite.io/v1/locale/countries/eu\",\"method\":\"GET\",\"headers\":{\"x-client-version\":\"1.0.0\"}}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Deno 1.24. Other versions may work but are not guarenteed to work as they haven't been tested. diff --git a/deno/send_http_request/src/mod.ts b/deno/send_http_request/src/mod.ts new file mode 100644 index 00000000..ee293dbc --- /dev/null +++ b/deno/send_http_request/src/mod.ts @@ -0,0 +1,24 @@ +export default async function (req: any, res: any) { + const { url, headers, method, body } = JSON.parse(req.payload); + + if (!url) { + throw new Error("url is required"); + } + + if (!method) { + throw new Error("method is required"); + } + + const response = await fetch(url, { method, headers, body: body ? JSON.stringify(body) : undefined }); + + if (response.status !== 200) { + res.json({ success: false, message: "URL could not be reached." }); + } + + const data = await response.json(); + + res.json({ + success: true, + response: { code: response.status, headers: response.headers, body: JSON.stringify(data) }, + }); +} \ No newline at end of file diff --git a/deno/send_sms_with_twilio/README.md b/deno/send_sms_with_twilio/README.md new file mode 100644 index 00000000..552ed3d9 --- /dev/null +++ b/deno/send_sms_with_twilio/README.md @@ -0,0 +1,56 @@ +# 📱 Send SMS with Twilio + +A Deno Cloud Function for sending message to a phone number using [Twilio API](https://www.twilio.com/docs/usage/api). + +_Example input:_ + +```json +{ + "text": "Hello from Open Runtimes 👋", + "phoneNumber": "+421XXXXXXXXX" +} +``` + +_Example output:_ + +```json +{ + "messageId": "SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **TWILIO_ACCOUNT_SID** - Twilio account SID +- **TWILIO_AUTH_TOKEN** - Twilio auth token +- **TWILIO_SENDER** - Sender's phone number from Twilio + +ℹ️ _Find your Account SID and Auth Token at twilio.com/console._ + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/send_sms_with_twilio +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.14 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.14 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.14). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Deno 1.13 and 1.14. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/deno/send_sms_with_twilio/src/mod.ts b/deno/send_sms_with_twilio/src/mod.ts new file mode 100644 index 00000000..68f1f872 --- /dev/null +++ b/deno/send_sms_with_twilio/src/mod.ts @@ -0,0 +1,30 @@ +export default async function test(req: any, res: any) { + const accountSID = req.variables["TWILIO_ACCOUNT_SID"]; + const authToken = req.variables["TWILIO_AUTH_TOKEN"]; + const sender = req.variables["TWILIO_SENDER"]; + + const { + phoneNumber, + text, + } = JSON.parse(req.payload); + + let response = await fetch( + `https://api.twilio.com/2010-04-01/Accounts/${accountSID}/Messages.json`, + { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + "Authorization": `Basic ${btoa(`${accountSID}:${authToken}`)}`, + }, + body: new URLSearchParams({ + To: phoneNumber, + From: sender, + Body: text, + }), + }, + ).then((res) => res.json()).then((data) => { + return JSON.stringify(data); + }).catch(console.error); + + res.send(response); +} \ No newline at end of file diff --git a/deno/translate_text_with_google/README.md b/deno/translate_text_with_google/README.md new file mode 100644 index 00000000..08900459 --- /dev/null +++ b/deno/translate_text_with_google/README.md @@ -0,0 +1,52 @@ +# 🌐 Translate text from one language to another + +A Deno Cloud Function for translating text from one language to another using [Google Translate](https://translate.google.com/). + +_Example input:_ + +```json +{ + "text": "Hello from Open Runtimes 👋", + "source": "en", + "target": "es" +} +``` + +_Example output:_ + +```json +{ + "text": "Hello from Open Runtimes 👋", + "translation": "Saludos desde Open Runtime 👋" +} +``` + +## 📝 Environment Variables + +No environment variables needed. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd deno/translate_text_with_google +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts --rm --interactive --tty --volume $PWD:/usr/code openruntimes/deno:v2-1.14 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/mod.ts -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/deno:v2-1.14 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Deno runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/deno-1.14). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Deno 1.13 and 1.14. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/deno/translate_text_with_google/src/mod.ts b/deno/translate_text_with_google/src/mod.ts new file mode 100644 index 00000000..d1d7ac1b --- /dev/null +++ b/deno/translate_text_with_google/src/mod.ts @@ -0,0 +1,28 @@ +import { GTR } from "https://deno.land/x/gtr/mod.ts"; + +export default async function (req: any, res: any) { + const gtr = new GTR(); + + // Get the query parameters from Appwrite's environment variable + const payload = JSON.parse(req.payload); + const { text, source, target } = payload; + + // Send request + try { + const { trans } = await gtr.translate( + text, + { + sourceLang: source, + targetLang: target + }, + ); + + // Parse response + res.send({ + text: text, + translation: trans + }); + } catch (e) { + console.error(e); + } +} diff --git a/deno/wipe_appwrite_bucket/README.md b/deno/wipe_appwrite_bucket/README.md new file mode 100644 index 00000000..0f9b3f9d --- /dev/null +++ b/deno/wipe_appwrite_bucket/README.md @@ -0,0 +1,41 @@ +# 🗑 Wipe Appwrite Bucket + +A Deno cloud function to wipe a complete bucket in Appwrite by passing the bucket id as a payload. + +_Example input:_ + +```json +{ + "bucketId":"profilePictures" +} +``` + +_Example output:_ + +```json +{ + "success":true +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key +- **APPWRITE_FUNCTION_PROJECT_ID** - Appwrite project ID. If running on Appwrite, this variable is provided automatically. + +## 🚀 Deployment + +There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience. + +### Using CLI + +Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`. + +Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy. + +### Manual using tar.gz + +Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/mod.ts`, and upload the file we just generated. diff --git a/deno/wipe_appwrite_bucket/src/deps.ts b/deno/wipe_appwrite_bucket/src/deps.ts new file mode 100644 index 00000000..6be1e80b --- /dev/null +++ b/deno/wipe_appwrite_bucket/src/deps.ts @@ -0,0 +1 @@ +export * as sdk from "https://deno.land/x/appwrite@6.0.0/mod.ts"; diff --git a/deno/wipe_appwrite_bucket/src/mod.ts b/deno/wipe_appwrite_bucket/src/mod.ts new file mode 100644 index 00000000..5cfb48f2 --- /dev/null +++ b/deno/wipe_appwrite_bucket/src/mod.ts @@ -0,0 +1,50 @@ +import { sdk } from "./deps.ts"; + +export default async function (req: any, res: any) { + if ( + !req.variables["APPWRITE_FUNCTION_ENDPOINT"] || + !req.variables["APPWRITE_FUNCTION_PROJECT_ID"] || + !req.variables["APPWRITE_FUNCTION_API_KEY"] || + !req.payload + ) { + return res.json({ + success: false, + message: "Missing required environment variables or payload.", + }); + } + let bucketId = ""; + try { + const payload = JSON.parse(req.payload); + bucketId = payload.bucketId; + } catch (_err) { + return res.json({ + success: false, + message: "Payload is invalid.", + }); + } + const client = new sdk.Client(); + const storage = new sdk.Storage(client); + + client + .setEndpoint(req.variables["APPWRITE_FUNCTION_ENDPOINT"]) + .setProject(req.variables["APPWRITE_FUNCTION_PROJECT_ID"]) + .setKey(req.variables["APPWRITE_FUNCTION_API_KEY"]); + + try { + while (true) { + const listFiles = await storage.listFiles(bucketId); + if (listFiles.total === 0) { + return res.json({ + success: true, + }); + } + const promises = listFiles.files.map((file) => storage.deleteFile(bucketId, file.$id)); + await Promise.all(promises); + } + } catch (_err) { + return res.json({ + success: false, + message: "Bucket not found.", + }); + } +} diff --git a/dotnet/generateShortUrl/.gitignore b/dotnet/generateShortUrl/.gitignore new file mode 100644 index 00000000..8c11bb36 --- /dev/null +++ b/dotnet/generateShortUrl/.gitignore @@ -0,0 +1,158 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Folder config file +[Dd]esktop.ini + +# JetBrains Rider +.idea/ +*.sln.iml + +## +## Visual Studio Code +## +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json diff --git a/dotnet/generateShortUrl/Function.csproj b/dotnet/generateShortUrl/Function.csproj new file mode 100644 index 00000000..f9353a4c --- /dev/null +++ b/dotnet/generateShortUrl/Function.csproj @@ -0,0 +1,12 @@ + + + + net6.0 + Exe + + + + + + + diff --git a/dotnet/generateShortUrl/README.md b/dotnet/generateShortUrl/README.md new file mode 100644 index 00000000..2b1cdf2d --- /dev/null +++ b/dotnet/generateShortUrl/README.md @@ -0,0 +1,57 @@ +# generateShortUrl + +Welcome to the documentation of this function 👋 + +## 🤖 Documentation + +Generates a short URL using the `bitly` and `tinyurl` APIs. + +_Example payload:_ + +```json +{ + "provider":"bitly", + "url":"https://google.com/" +} +``` + +_Example successful response:_ + +```json +{ + "success":true, + "url":"https:\/\/bit.ly\/3DGAJF8" +} +``` + +_Example failure response:_ + +```json +{ + "success":false, + "message":"The value provided is invalid." +} +``` + +## 📝 Environment Variables + +This cloud function needs the following environment variables: + +- `BITLY_API_KEY`: Bitly API Access Token +- `TINYURL_API_KEY`: Tinyurl API Key + +ℹ️ *Note: Learn how to create the [Bitly](https://dev.bitly.com/) and [Tinyurl](https://tinyurl.com/app/dev) API Keys via their docs.* + +## 🚀 Deployment + +There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience. + +### Using CLI + +Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`. + +Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy. + +### Manual using tar.gz + +Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/Index.cs`, and upload the file we just generated. diff --git a/dotnet/generateShortUrl/src/Index.cs b/dotnet/generateShortUrl/src/Index.cs new file mode 100644 index 00000000..07f96da0 --- /dev/null +++ b/dotnet/generateShortUrl/src/Index.cs @@ -0,0 +1,156 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading.Tasks; + +public async Task Main(RuntimeRequest req, RuntimeResponse res) +{ + try + { + // Check if payload is present + + if(String.IsNullOrEmpty(req.Payload)) + { + return res.Json(new() + { + { "success", false }, + { "message", "Payload is missing" } + }); + } + + var payload = JsonConvert.DeserializeObject>(req.Payload); + + // Check if provider and URL to be shortened are present in the payload + + if(!(payload.ContainsKey("provider") && payload.ContainsKey("url"))) + { + return res.Json(new() + { + { "success", false }, + { "message", "Payload must contain a provider and a URL" } + }); + } + + string provider = payload["provider"]; + string url = payload["url"]; + + string apiKey = ""; + string uri = ""; + Dictionary body = new Dictionary(); + string json = ""; + + // Preparing API info based on chosen provider + + if(payload["provider"].Equals("bitly")) + { + if(!req.Variables.ContainsKey("BITLY_API_KEY")) + { + return res.Json(new() + { + { "success", false }, + { "message", "Bitly API Access Token is missing. Please add it as an environment variable \"BITLY_API_KEY\"" } + }); + } + apiKey = req.Variables["BITLY_API_KEY"]; + uri = "https://api-ssl.bitly.com/v4/shorten"; + body.Add("long_url", url); + json = JsonConvert.SerializeObject(body); + } + + else if(payload["provider"].Equals("tinyurl")) + { + if(!req.Variables.ContainsKey("TINYURL_API_KEY")) + { + return res.Json(new() + { + { "success", false }, + { "message", "Tinyurl API Key is missing. Please add it as an environment variable \"TINYURL_API_KEY\"" } + }); + } + apiKey = req.Variables["TINYURL_API_KEY"]; + uri = "https://api.tinyurl.com/create"; + body.Add("url", url); + json = JsonConvert.SerializeObject(body); + } + + else + { + return res.Json(new() + { + { "success", false }, + { "message", "Provider is invalid" } + }); + } + + // Sending Http Request to the chosen provider's API + + var client = new HttpClient(); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); + var data = new StringContent(json, Encoding.UTF8, "application/json"); + var httpResponse = await client.PostAsync(uri, data); + var responseContent = await httpResponse.Content.ReadAsStringAsync(); + var response = JsonConvert.DeserializeObject(responseContent); + + // Successful response + + if(httpResponse.StatusCode == HttpStatusCode.OK || httpResponse.StatusCode == HttpStatusCode.Created) + { + if(payload["provider"].Equals("bitly")) + { + return res.Json(new() + { + { "success", true }, + { "url", response?.link.ToString() } + }); + } + else if(payload["provider"].Equals("tinyurl")) + { + return res.Json(new() + { + { "success", true }, + { "url", response?.data.tiny_url.ToString() } + }); + } + } + + // Failed response + + else + { + if(payload["provider"].Equals("bitly")) + { + return res.Json(new() + { + { "success", false }, + { "message", response?.description.ToString() } + }); + } + else if(payload["provider"].Equals("tinyurl")) + { + return res.Json(new() + { + { "success", false }, + { "message", response?.errors[0].ToString() } + }); + } + } + } + catch(Exception ex) + { + return res.Json(new() + { + { "success", false }, + { "message", ex.Message } + }); + } + + return res.Json(new() + { + { "success", false }, + { "message", "Function failed for unknown reasons" } + }); +} \ No newline at end of file diff --git a/dotnet/wipe_appwrite_collection/AppwriteDatabaseClient.cs b/dotnet/wipe_appwrite_collection/AppwriteDatabaseClient.cs new file mode 100644 index 00000000..2ed5a0cd --- /dev/null +++ b/dotnet/wipe_appwrite_collection/AppwriteDatabaseClient.cs @@ -0,0 +1,33 @@ +using Newtonsoft.Json; +using wipeAppwriteCollection.Models; + +namespace wipeAppwriteCollection; + +public class AppwriteDatabaseClient +{ + private readonly HttpClient httpClient; + + public AppwriteDatabaseClient(string baseUrl, string apiKey, string projectId) + { + httpClient = new HttpClient + { + BaseAddress = new Uri(baseUrl), + }; + + httpClient.DefaultRequestHeaders.Add("X-Appwrite-Key", apiKey); + httpClient.DefaultRequestHeaders.Add("X-Appwrite-Project", projectId); + } + + public async Task ListDocuments(string databaseId, string collectionId, int? limit = 25) + { + var response = await httpClient.GetAsync($"/v1/databases/{databaseId}/collections/{collectionId}/documents?limit={limit}"); + var responseStr = await response.Content.ReadAsStringAsync(); + var parsedResponse = JsonConvert.DeserializeObject(responseStr); + return parsedResponse; + } + + public async Task DeleteDocument(string databaseId, string collectionId, string documentId) + { + await httpClient.DeleteAsync($"/v1/databases/{databaseId}/collections/{collectionId}/documents/{documentId}"); + } +} diff --git a/dotnet/wipe_appwrite_collection/Index.cs b/dotnet/wipe_appwrite_collection/Index.cs new file mode 100644 index 00000000..b1f7de4e --- /dev/null +++ b/dotnet/wipe_appwrite_collection/Index.cs @@ -0,0 +1,65 @@ +using Newtonsoft.Json; +using wipeAppwriteCollection; +using wipeAppwriteCollection.Models; + +public async Task Main(RuntimeRequest req, RuntimeResponse res) +{ + var baseUrl = Environment.GetEnvironmentVariable("APPWRITE_FUNCTION_ENDPOINT"); + var apiKey = Environment.GetEnvironmentVariable("APPWRITE_FUNCTION_API_KEY"); + var projectId = Environment.GetEnvironmentVariable("APPWRITE_FUNCTION_PROJECT_ID"); + + if (string.IsNullOrWhiteSpace(baseUrl) || + string.IsNullOrWhiteSpace(apiKey) || + string.IsNullOrWhiteSpace(projectId)) + { + res.Json(new() { + { "success", false }, + { "message", "Please provide all required environment variables." } + }); + return res; + } + + var reqBody = JsonConvert.DeserializeObject>(req.Payload); + var gotRequestVariables = + reqBody.TryGetValue("databaseId", out string databaseId) & + reqBody.TryGetValue("collectionId", out string collectionId); + if (!gotRequestVariables) + { + res.Json(new() { + { "success", false }, + { "message", "Payload is invalid." } + }); + return res; + } + + var databaseClient = new AppwriteDatabaseClient(baseUrl, apiKey, projectId); + ListDocumentsResponse documents; + var done = false; + while (!done) + { + documents = await databaseClient.ListDocuments(databaseId, collectionId); + if (documents?.Documents == null) + { + res.Json(new() { + { "success", false }, + { "message", "Failed to get documents from database." } + }); + return res; + } + + foreach (var document in documents.Documents) + { + await databaseClient.DeleteDocument(databaseId, collectionId, document.Id); + } + + if (documents.Total <= 0) + { + done = true; + } + } + + res.Json(new() { + { "success", true } + }); + return res; +} diff --git a/dotnet/wipe_appwrite_collection/Models/Document.cs b/dotnet/wipe_appwrite_collection/Models/Document.cs new file mode 100644 index 00000000..4cef9581 --- /dev/null +++ b/dotnet/wipe_appwrite_collection/Models/Document.cs @@ -0,0 +1,9 @@ +using Newtonsoft.Json; + +namespace wipeAppwriteCollection.Models; + +public class Document +{ + [JsonProperty("$id")] + public string Id { get; set; } +} diff --git a/dotnet/wipe_appwrite_collection/Models/ListDocumentsResponse.cs b/dotnet/wipe_appwrite_collection/Models/ListDocumentsResponse.cs new file mode 100644 index 00000000..761f8c0e --- /dev/null +++ b/dotnet/wipe_appwrite_collection/Models/ListDocumentsResponse.cs @@ -0,0 +1,12 @@ +using Newtonsoft.Json; + +namespace wipeAppwriteCollection.Models; + +public class ListDocumentsResponse +{ + [JsonProperty("total")] + public int Total { get; set; } + + [JsonProperty("documents")] + public Document[] Documents { get; set; } +} diff --git a/dotnet/wipe_appwrite_collection/README.md b/dotnet/wipe_appwrite_collection/README.md new file mode 100644 index 00000000..51bd779c --- /dev/null +++ b/dotnet/wipe_appwrite_collection/README.md @@ -0,0 +1,68 @@ +# 🧹 Wipe Appwrite Collection + +A .NET Cloud Function that wipes all documents from an Appwrite collection. + +_Example payload:_ + +```json +{ + "databaseId":"stage", + "collectionId":"profiles" +} +``` + +_Example output:_ + + +```json +{ + "success":true +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of your Appwrite server +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key +- **APPWRITE_FUNCTION_PROJECT_ID** - Appwrite project ID. If running on Appwrite, this variable is provided automatically. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd dotnet/wipe_appwrite_collection +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty \ + -e INTERNAL_RUNTIME_ENTRYPOINT=Index.cs \ + --volume $PWD:/usr/code \ + openruntimes/dotnet:v2-6.0 sh \ + /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run --rm --interactive --tty \ + -p 3000:3000 \ + -e INTERNAL_RUNTIME_KEY=secret-key \ + -e INTERNAL_RUNTIME_ENTRYPOINT=Index.cs \ + -e APPWRITE_FUNCTION_PROJECT_ID=project-id \ + -e APPWRITE_FUNCTION_ENDPOINT=appwrite-endpoint \ + -e APPWRITE_FUNCTION_API_KEY=secret-key \ + --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro \ + openruntimes/dotnet:v2-6.0 \ + sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit .NET runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/dotnet-6.0). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with .NET 6.0. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/dotnet/wipe_appwrite_collection/wipeAppwriteCollection.csproj b/dotnet/wipe_appwrite_collection/wipeAppwriteCollection.csproj new file mode 100644 index 00000000..02fb71a4 --- /dev/null +++ b/dotnet/wipe_appwrite_collection/wipeAppwriteCollection.csproj @@ -0,0 +1,12 @@ + + + + net6.0 + enable + + + + + + + diff --git a/java/deepgramLanguageDetection/Index.java b/java/deepgramLanguageDetection/Index.java new file mode 100644 index 00000000..4be00d21 --- /dev/null +++ b/java/deepgramLanguageDetection/Index.java @@ -0,0 +1,170 @@ +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.*; +import java.util.stream.*; +import java.net.HttpURLConnection; +import java.net.ProtocolException; +import java.net.URL; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; + +import com.google.gson.Gson; +import org.apache.commons.validator.routines.UrlValidator; +final Gson gson=new Gson(); + +public RuntimeResponse main(RuntimeRequest req,RuntimeResponse res)throws Exception{ + // Validate that values present in the request are not empty (payload, variables) + RuntimeResponse errorResponse=checkEmptyPayloadAndVariables(req,res); + if(errorResponse!=null){ + return errorResponse; + } + + // Validate the requested payload (URL) + String payloadString=req.getPayload().toString(); + Map payload=gson.fromJson(payloadString,Map.class); + + errorResponse=validatePayload(payload,res); + if(errorResponse!=null){ + return errorResponse; + } + + // Get file url from payload + String fileurl=payload.get("fileUrl").toString(); + + // Name API key is not empty + String apiKeyVariable="DEEPGRAM_SECRET_KEY"; + + errorResponse=checkEmptyAPIKey(req,res,apiKeyVariable); + if(errorResponse!=null){ + return errorResponse; + } + + String apiKey=req.getVariables().get(apiKeyVariable).toString(); + + String deepgramData=""; + Map responseData=new HashMap<>(); + + try{ + deepgramData=detectLanguage(fileurl,apiKey); + }catch(Exception e){ + responseData.put("success",false); + responseData.put("message","Something went wrong while generating the summary, please check with the developers. Error: "+e.getMessage());//TODO + return res.json(responseData); + } + responseData.put("success",true); + responseData.put("deepgramData",deepgramData); + + return res.json(responseData); +} + + +/** + * This method will send a POST request to the specified endpoint and return the Deepgram's response + * + * @param requestBody is the Request Body for the POST request containing the URL to the wav file to Summarize + * @param apiKey is the access token used by Deepgram to summarize + * @return the Deepgram's response to the POST request + * @throws Exception in case of malformed URL, I/O exception, etc. + */ +private String detectLanguage(String requestBody,String apiKey)throws Exception{ + + String endpointUrl="https://api.deepgram.com/v1/listen?detect_language=true&punctuate=true"; + URL url=new URL(endpointUrl); + HttpURLConnection con=(HttpURLConnection)url.openConnection(); + + con.setRequestMethod("POST"); + con.setRequestProperty("Content-Type","application/json"); + con.setRequestProperty("Authorization","Token "+apiKey); + + con.setDoOutput(true); + + //prepare request body + requestBody="{\"url\":\""+requestBody+"\"}"; + + OutputStream os=con.getOutputStream(); + byte[] input=requestBody.getBytes("utf-8"); + os.write(input,0,input.length); + + StringBuilder response=new StringBuilder(); + + BufferedReader br=new BufferedReader(new InputStreamReader(con.getInputStream(),"utf-8")); + String responseLine=null; + while((responseLine=br.readLine())!=null){ + response.append(responseLine.trim()); + } + + br.close(); + con.disconnect(); + + return response.toString(); +} + +/** + * This method validates that a non-empty API key is present in variables + * + * @param req is the received POST request + * @return null if non-empty API key is present, otherwise an error response + */ +private RuntimeResponse checkEmptyAPIKey(RuntimeRequest req,RuntimeResponse res,String apiKeyVariable){ + Map variables=req.getVariables(); + + if(!variables.containsKey(apiKeyVariable)){ + Map responseData=new HashMap<>(); + responseData.put("success",false); + responseData.put("message","Please pass a non-empty API Key "+apiKeyVariable+" for Deepgram"); + + return res.json(responseData); + } + + return null; +} +/** + * This method validates that non-empty URL is present in the payload + * + * @param payload is the object that contains the URL + * @return null if payload is valid, otherwise an error response + */ +private RuntimeResponse validatePayload(Map payload,RuntimeResponse res){ + Map responseData=new HashMap<>(); + + // Validate that payload has fileUrl + if(!payload.containsKey("fileUrl")){ + responseData.put("success",false); + responseData.put("message","Please provide a valid file URL"); + return res.json(responseData); + } + + String fileUrl=payload.get("fileUrl").toString(); + + // Validate the URL + UrlValidator urlValidator=new UrlValidator(); + if(!urlValidator.isValid(fileUrl)){ + responseData.put("success",false); + responseData.put("message","Provided URL: "+fileUrl+" is not valid, please provide a valid, correctly formed URL"); + return res.json(responseData); + } + + return null; +} +/** + * This function will validate that the payload and variables are non-empty in the request + * + * @param req is the received POST request + * @return null is nothing is empty, otherwise an error response + */ +private RuntimeResponse checkEmptyPayloadAndVariables(RuntimeRequest req,RuntimeResponse res){ + Map responseData=new HashMap<>(); + + if(req.getPayload().isEmpty()||req.getPayload().trim().equals("{}")){ + responseData.put("message","Payload is empty, expected a payload with provider and URL"); + return res.json(responseData); + } + + if(req.getVariables()==null){ + responseData.put("success",false); + responseData.put("message","Empty function variables found. You need to pass an API key for the provider"); + return res.json(responseData); + } + return null; +} \ No newline at end of file diff --git a/java/deepgramLanguageDetection/README.md b/java/deepgramLanguageDetection/README.md new file mode 100644 index 00000000..5bd9691b --- /dev/null +++ b/java/deepgramLanguageDetection/README.md @@ -0,0 +1,72 @@ +# 🧹Deepgram Language Detection + +A Cloud Function for Language detection using [Deepgram](https://deepgram.com/) + +_Example input:_ + +```json +{ + "fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Example output:_ + +```json +{ + "deepgramData": {}, + "success": true +} +``` + +_Example error output:_ + +```json +{ + "success": false, + "message": "Error" +} +``` + +## 📝 Environment Variables + +**DEEPGRAM_API_KEY** - Your Deepgram secret API key. +Details are under link: [Deepgram_getting_started](https://developers.deepgram.com/documentation/getting-started/) + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +```bash +git clone https://github.com/open-runtimes/examples.git && cd examples +cd java/deepgramLanguageDetection +``` + +2. Build the code: + +```bash +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=Index.java --rm --interactive --tty --volume $PWD:/usr/code openruntimes/java:v2-11.0 sh /usr/local/src/build.sh +``` + +3. Spin-up open-runtime: + +```bash +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/java:v2-11.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Java runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/java-11.0). + +4. Run the curl function to send request. + +```bash +curl --location --request POST 'http://localhost:3000/' \ +--header 'X-Internal-Challenge: secret-key' \ +--header 'Content-Type: application/json' \ +--data-raw '{"payload": "{\"fileUrl\": \"https://static.deepgram.com/examples/interview_speech-analytics.wav\"}", +"variables": {"DEEPGRAM_SECRET_KEY":""}} +' +``` + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). diff --git a/java/deepgramLanguageDetection/deps.gradle b/java/deepgramLanguageDetection/deps.gradle new file mode 100644 index 00000000..16206c71 --- /dev/null +++ b/java/deepgramLanguageDetection/deps.gradle @@ -0,0 +1,4 @@ +dependencies { + implementation 'com.google.code.gson:gson:2.9.0' + implementation 'commons-validator:commons-validator:1.7' +} \ No newline at end of file diff --git a/java/deepgram_audio_summary/Index.java b/java/deepgram_audio_summary/Index.java new file mode 100644 index 00000000..c2c15b4e --- /dev/null +++ b/java/deepgram_audio_summary/Index.java @@ -0,0 +1,182 @@ +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.*; +import java.util.stream.*; +import java.net.HttpURLConnection; +import java.net.ProtocolException; +import java.net.URL; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; + +import com.google.gson.Gson; +import org.apache.commons.validator.routines.UrlValidator; + +final Gson gson=new Gson(); + +public RuntimeResponse main(RuntimeRequest req,RuntimeResponse res)throws Exception{ + // Validate that values present in the request are not empty (payload, variables) + RuntimeResponse errorResponse=checkEmptyPayloadAndVariables(req,res); + if(errorResponse!=null){ + return errorResponse; + } + + // Validate the requested payload (URL) + String payloadString=req.getPayload().toString(); + + errorResponse=validatePayload(payloadString,res); + if(errorResponse!=null){ + return errorResponse; + } + + Map payload = gson.fromJson(payloadString,Map.class); + + // Get file url from payload + String fileurl=payload.get("fileUrl").toString(); + + // Name API key is not empty + String apiKeyVariable="DEEPGRAM_SECRET_KEY"; + + errorResponse=checkEmptyAPIKey(req,res,apiKeyVariable); + if(errorResponse!=null){ + return errorResponse; + } + + String apiKey=req.getVariables().get(apiKeyVariable).toString(); + + String deepgramData=""; + Map responseData=new HashMap<>(); + + try{ + deepgramData=generateSummary(fileurl,apiKey); + }catch(Exception e){ + responseData.put("success",false); + responseData.put("message","Something went wrong while generating the summary, please check with the developers. Error: "+e.getMessage());//TODO + return res.json(responseData); + } + responseData.put("success",true); + responseData.put("deepgramData",deepgramData); + + return res.json(responseData); +} + + +/** + * This method will send a POST request to the specified endpoint and return the Deepgram's response + * + * @param requestBody is the Request Body for the POST request containing the URL to the wav file to Summarize + * @param apiKey is the access token used by Deepgram to summarize + * @return the Deepgram's response to the POST request + * @throws Exception in case of malformed URL, I/O exception, etc. + */ +private String generateSummary(String requestBody,String apiKey)throws Exception{ + String endpointUrl="https://api.deepgram.com/v1/listen?summarize=true&punctuate=true"; + URL url=new URL(endpointUrl); + HttpURLConnection con=(HttpURLConnection)url.openConnection(); + + con.setRequestMethod("POST"); + con.setRequestProperty("Content-Type","application/json"); + con.setRequestProperty("Authorization","Token "+apiKey); + + con.setDoOutput(true); + + //prepare request body + requestBody="{\"url\":\""+requestBody+"\"}"; + + OutputStream os=con.getOutputStream(); + byte[] input=requestBody.getBytes("utf-8"); + os.write(input,0,input.length); + + StringBuilder response=new StringBuilder(); + + BufferedReader br=new BufferedReader(new InputStreamReader(con.getInputStream(),"utf-8")); + String responseLine=null; + while((responseLine=br.readLine())!=null){ + response.append(responseLine.trim()); + } + + br.close(); + con.disconnect(); + + return response.toString(); +} + +/** + * This method validates that a non-empty API key is present in variables + * + * @param req is the received POST request + * @return null if non-empty API key is present, otherwise an error response + */ +private RuntimeResponse checkEmptyAPIKey(RuntimeRequest req,RuntimeResponse res,String apiKeyVariable){ + Map variables=req.getVariables(); + + if(!variables.containsKey(apiKeyVariable) ||variables.get(apiKeyVariable)==null||variables.get(apiKeyVariable).trim().isEmpty()){ + Map responseData=new HashMap<>(); + responseData.put("success",false); + responseData.put("message","Please pass a non-empty API Key "+apiKeyVariable+" for Deepgram"); + + return res.json(responseData); + } + + return null; +} +/** + * This method validates that non-empty URL is present in the payload + * + * @param payload is the object that contains the URL + * @return null if payload is valid, otherwise an error response + */ +private RuntimeResponse validatePayload(String payloadString,RuntimeResponse res){ + Map responseData=new HashMap<>(); + Map payload=new HashMap<>();; + try{ + payload=gson.fromJson(payloadString,Map.class); + } catch (Exception e) { + responseData.put("success",false); + responseData.put("message","The payload is invalid. Example of valid payload:{\"fileUrl\": \"...\"}"); + return res.json(responseData); + } + + // Validate that payload has fileUrl + if(!payload.containsKey("fileUrl")){ + responseData.put("success",false); + responseData.put("message","Please provide a valid file URL"); + return res.json(responseData); + } + + String fileUrl=payload.get("fileUrl").toString(); + + // Validate the URL + UrlValidator urlValidator=new UrlValidator(); + if(!urlValidator.isValid(fileUrl)){ + responseData.put("success",false); + responseData.put("message","Provided URL: "+fileUrl+" is not valid, please provide a valid, correctly formed URL"); + return res.json(responseData); + } + + return null; +} +/** + * This function will validate that the payload and variables are non-empty in the request + * + * @param req is the received POST request + * @return null is nothing is empty, otherwise an error response + */ +private RuntimeResponse checkEmptyPayloadAndVariables(RuntimeRequest req,RuntimeResponse res){ + + Map responseData=new HashMap<>(); + + if(req.getPayload()==null||req.getPayload().trim().isEmpty()||req.getPayload().trim().equals("{}")){ + responseData.put("success",false); + responseData.put("message","Payload is empty, expected a payload with provider and URL"); + return res.json(responseData); + + } + if(req.getVariables()==null){ + responseData.put("success",false); + responseData.put("message","Empty function variables found. You need to pass an API key for the provider"); + return res.json(responseData); + } + + return null; +} \ No newline at end of file diff --git a/java/deepgram_audio_summary/README.md b/java/deepgram_audio_summary/README.md new file mode 100644 index 00000000..4ae2ec38 --- /dev/null +++ b/java/deepgram_audio_summary/README.md @@ -0,0 +1,59 @@ +# 💻 Deepgram Audio Summary + +A Java Cloud Function for generating a summary using [Deepgram](https://deepgram.com/) + +_Deepgram Example input:_ + +```json +{"fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav"} +``` +_Deepgram Example output:_ + +```json +{ + "success": true, + "deepgramData": {} +} +``` + +_Error Example output:_ + +```json +{ + "success": false, + "message":"Please provide a valid file URL." +} +``` + + +## 📝 Variables + +List of variables used by this cloud function. These must be passed within 'variables' section of the request: + +**DEEPGRAM_SECRET_KEY** - This API key would be the access token used by Deepgram for generating the Summary. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd java/deepgram_audio_summary +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=Index.java --rm --interactive --tty --volume $PWD:/usr/code openruntimes/java:v2-11.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/java:v2-11.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Java runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/java-11.0). + +## 📝 Notes +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Java 11.0. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/java/deepgram_audio_summary/deps.gradle b/java/deepgram_audio_summary/deps.gradle new file mode 100644 index 00000000..16206c71 --- /dev/null +++ b/java/deepgram_audio_summary/deps.gradle @@ -0,0 +1,4 @@ +dependencies { + implementation 'com.google.code.gson:gson:2.9.0' + implementation 'commons-validator:commons-validator:1.7' +} \ No newline at end of file diff --git a/java/generate_invoice/Index.java b/java/generate_invoice/Index.java new file mode 100644 index 00000000..9d8026ca --- /dev/null +++ b/java/generate_invoice/Index.java @@ -0,0 +1,116 @@ +import com.google.gson.Gson; +import com.itextpdf.text.*; +import com.itextpdf.text.pdf.PdfWriter; +import com.itextpdf.text.pdf.draw.VerticalPositionMark; + +import java.io.ByteArrayOutputStream; +import java.util.*; +import java.util.List; + +final Gson gson = new Gson(); + +public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) { + String payloadString = req.getPayload(); + Map payload = gson.fromJson(payloadString, Map.class); + Map responseData = new HashMap<>(); + + try { + String currency = Objects.toString(payload.get("currency"), ""); + List> items = (List>)(List) payload.get("items"); + String issuer = Objects.toString(payload.get("issuer"), ""); + String customer = Objects.toString(payload.get("customer"), ""); + Number vat = (Number) payload.get("vat"); + + List errorFields = validatePayload(currency, items, issuer, customer, vat); + if (!errorFields.isEmpty()) { + throw new NoSuchFieldException("Please provide " + String.join(", ", errorFields)); + } + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Document doc = new Document(); + PdfWriter writer = PdfWriter.getInstance(doc, baos); + + doc.open(); + Font font = new Font(Font.FontFamily.TIMES_ROMAN, 26, Font.BOLD | Font.UNDERLINE); + Paragraph invoice = new Paragraph("Invoice", font); + invoice.setAlignment(Element.ALIGN_CENTER); + doc.add(invoice); + + font.setSize(12); + font.setStyle(Font.NORMAL); + doc.add(new Paragraph(50)); + doc.add(new Paragraph("Issuer: " + issuer, font)); + doc.add(new Paragraph("Customer: " + customer, font)); + doc.add(new Paragraph("Currency: " + currency, font)); + doc.add(new Paragraph("VAT: " + vat, font)); + + Chunk glue = new Chunk(new VerticalPositionMark()); + Chunk rightChunk = new Chunk(glue); + + font.setStyle(Font.BOLD); + Paragraph itemHeader = new Paragraph(50, "Item", font); + itemHeader.add(rightChunk); + itemHeader.add("Price"); + doc.add(itemHeader); + + font.setStyle(Font.NORMAL); + double total = 0; + for (Map item : items) { + String name = item.get("name").toString(); + double price = (double) item.get("price"); + + total += price; + Paragraph itemParagraph = new Paragraph(name, font); + itemParagraph.add(rightChunk); + itemParagraph.add(String.valueOf(price)); + doc.add(itemParagraph); + } + + font.setStyle(Font.UNDERLINE | Font.BOLD); + font.setSize(15); + Paragraph totalParagraph = new Paragraph(20, "Total:", font); + totalParagraph.add(rightChunk); + totalParagraph.add(String.valueOf(total)); + doc.add(totalParagraph); + doc.close(); + writer.close(); + + String base64String = Base64.getEncoder().encodeToString(baos.toByteArray()); + + responseData.put("success", true); + responseData.put("invoice", base64String); + + return res.json(responseData); + } catch (DocumentException | NoSuchFieldException exception) { + responseData.put("success", false); + responseData.put("message", exception.getMessage()); + return res.json(responseData); + } +} + +private List validatePayload(String currency, List> items, String issuer, String customer, Number vat) { + + List errors = new ArrayList<>(); + + if (currency.isEmpty()) { + errors.add("currency"); + } + + if (items == null || items.isEmpty()) { + errors.add("items"); + } + + if (issuer.isEmpty()) { + errors.add("issuer"); + } + + if (customer.isEmpty()) { + errors.add("customer"); + } + + if (vat == null) { + errors.add("vat"); + } + + return errors; +} \ No newline at end of file diff --git a/java/generate_invoice/README.md b/java/generate_invoice/README.md new file mode 100644 index 00000000..b197d646 --- /dev/null +++ b/java/generate_invoice/README.md @@ -0,0 +1,69 @@ +# 💻 Generate invoice + +A Java Cloud Function for generating invoice. + +```json +{ + "currency":"EUR", + "items":[{"name":"Web development","price":15}], + "issuer":"Some\nIssuer", + "customer":"Some\nCustomer", + "vat":21 +} +``` + +_Example output:_ + + +```json +{ + "success":true, + "invoice":"iVBORw0KGgoAAAANSUhEUgAAAaQAAALiCAY...QoH9hbkTPQAAAABJRU5ErkJggg==" +} +``` + +_Error Example output:_ + +```json +{ + "success": false, + "message":"Please provide currency" +} +``` + + +## 📝 Environment Variables + +This function does not require any variables. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd java/generate_invoice +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=Index.java --rm --interactive --tty --volume $PWD:/usr/code openruntimes/java:v2-18.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/java:v2-18.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Java runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/java-18.0). + +4. Execute function: + +``` +curl http://localhost:3000/ -d '{"payload":"{\"currency\":\"EUR\",\"items\":[{\"name\":\"Web development\",\"price\":15}],\"issuer\":\"Some\nIssuer\",\"customer\":\"Some\nCustomer\",\"vat\":21}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Java 18.0. Other versions may work but are not guarenteed to work as they haven't been tested. diff --git a/java/generate_invoice/deps.gradle b/java/generate_invoice/deps.gradle new file mode 100644 index 00000000..21f72fbe --- /dev/null +++ b/java/generate_invoice/deps.gradle @@ -0,0 +1,4 @@ +dependencies { + implementation 'com.google.code.gson:gson:2.9.0' + implementation 'com.itextpdf:itextpdf:5.5.13.3' +} \ No newline at end of file diff --git a/java/get_price/Index.java b/java/get_price/Index.java new file mode 100644 index 00000000..a02bf6f8 --- /dev/null +++ b/java/get_price/Index.java @@ -0,0 +1,52 @@ +import com.google.gson.Gson; +import yahoofinance.Stock; +import yahoofinance.YahooFinance; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + +final Gson gson = new Gson(); + +final Map SYMBOLS = Map.of( + "amazon", "AMZN", + "bitcoin", "BTC-USD", + "ethereum", "ETH-USD", + "gold", "GC=F", + "google", "GOOG", + "silver", "SI=F" +); + +public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) { + String payloadString = req.getPayload(); + Map payload = gson.fromJson(payloadString, Map.class); + Map responseData = new HashMap<>(); + + String type = payload.get("type").toString(); + String symbol = SYMBOLS.get(type); + + if (symbol == null) { + responseData.put("success", false); + responseData.put("message", "Type is not supported."); + return res.json(responseData); + } + + try { + BigDecimal price = getPrice(symbol); + responseData.put("success", true); + responseData.put("price", price); + + return res.json(responseData); + } catch (IOException ex) { + responseData.put("success", false); + responseData.put("message", ex.getMessage()); + return res.json(responseData); + } +} + +private BigDecimal getPrice(String symbol) throws IOException { + Stock stock = YahooFinance.get(symbol); + BigDecimal price = stock.getQuote().getPrice(); + return price; +} \ No newline at end of file diff --git a/java/get_price/README.md b/java/get_price/README.md new file mode 100644 index 00000000..4222c170 --- /dev/null +++ b/java/get_price/README.md @@ -0,0 +1,61 @@ +# 💻 Get Short URL + +A Java Cloud Function to get price of crypto. + +```json +{ + "payload": { + "type": "gold" + } +} +``` + +_Example output:_ + + +```json +{ + "success":true, + "price":1643.1 +} +``` + +_Error Example output:_ + +```json +{ + "success": false, + "message":"Type is not supported." +} +``` + + +## 📝 Environment Variables + +List of environment variables used by this cloud function. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd java/get_price +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=Index.java --rm --interactive --tty --volume $PWD:/usr/code openruntimes/java:v2-18.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/java:v2-18.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Java runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/java-18.0). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Java 18.0. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/java/get_price/deps.gradle b/java/get_price/deps.gradle new file mode 100644 index 00000000..9afcb61f --- /dev/null +++ b/java/get_price/deps.gradle @@ -0,0 +1,4 @@ +dependencies { + implementation 'com.google.code.gson:gson:2.9.0' + implementation 'com.yahoofinance-api:YahooFinanceAPI:3.16.0' +} \ No newline at end of file diff --git a/java/short_url_generator/Index.java b/java/short_url_generator/Index.java new file mode 100644 index 00000000..ace28ef1 --- /dev/null +++ b/java/short_url_generator/Index.java @@ -0,0 +1,283 @@ +import java.util.Collections; +import java.util.stream.Collectors; +import java.util.*; +import java.util.stream.*; +import java.net.HttpURLConnection; +import java.net.ProtocolException; +import java.net.URL; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import com.google.gson.Gson; +import org.apache.commons.validator.routines.UrlValidator; + +// List of supported providers +private enum Provider { + + BITLY("bitly"), + TINY_URL("tinyurl"); + + private final String name; + + Provider(String name) { + this.name = name; + } + + static boolean validateProvider(String name) { + for(Provider providerName: Provider.values()) { + if(providerName.name.equals(name)) { + return true; + } + } + + return false; + } + + String getName() { + return name; + } +} + +final Gson gson = new Gson(); + +final Map endpointsMap = Map.of( + "bitly", "https://api-ssl.bitly.com/v4/shorten", + "tinyurl", "https://api.tinyurl.com/create" +); + +public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) throws Exception { + + // Validate that values present in the request are not empty (payload, variables) + RuntimeResponse errorResponse = checkEmptyPayloadAndVariables(req, res); + if(errorResponse != null) { + return errorResponse; + } + + // Validate the requested payload (provider and URL) + String payloadString = req.getPayload(); + Map payload = gson.fromJson(payloadString, Map.class); + + errorResponse = validatePayload(payload, res); + if(errorResponse != null) { + return errorResponse; + } + + // Generate short url + String provider = payload.get("provider").toString(); + String url = payload.get("url").toString(); + + // Validate that the API key is not empty + String apiKeyVariable = Provider.BITLY.getName().equals(provider) ? "BITLY_API_KEY" : "TINYURL_API_KEY"; + + errorResponse = checkEmptyAPIKey(req, res, apiKeyVariable); + if(errorResponse != null) { + return errorResponse; + } + + String apiKey = req.getVariables().get(apiKeyVariable); + + String shortUrl = ""; + + Map responseData = new HashMap<>(); + + try { + shortUrl = generateShortUrl(apiKey, provider, url); + } catch(Exception e) { + responseData.put("success", false); + responseData.put("message", "Something went wrong while generating the shortUrl, please check with the developers. Error: " + e.getMessage()); + return res.json(responseData); + } + + // Validate that the generated short URL is not empty + errorResponse = checkEmptyShortUrl(shortUrl, res); + if(errorResponse != null) { + return errorResponse; + } + + // Send response + responseData.put("success", true); + responseData.put("url", shortUrl); + + return res.json(responseData); +} + +/** + * This method validates that the generated short URL is not empty + * + * @param shortUrl is the URL to be validated + * @return null if shortURL is non-empty, otherwise an error response + */ +private RuntimeResponse checkEmptyShortUrl(String shortUrl, RuntimeResponse res) { + Map responseData = new HashMap<>(); + + if(shortUrl == null || shortUrl.trim().isEmpty()) { + responseData.put("success", false); + responseData.put("message", "Blank or null shortUrl value is returned, please try again or check with the developers"); + return res.json(responseData); + } + + return null; +} + +/** + * This method validates that non-empty provider and URL are present in the payload + * It also validates that the requested provider is one of the supported providers + * + * @param payload is the object that contains the provider and the URL + * @return null if payload is valid, otherwise an error response + */ +private RuntimeResponse validatePayload(Map payload, RuntimeResponse res) { + Map responseData = new HashMap<>(); + + // Validate that payload has both provider and url + if(!payload.containsKey("provider") || !payload.containsKey("url")) { + responseData.put("success", false); + responseData.put("message", "Payload must contain both provider and url data"); + return res.json(responseData); + } + + String provider = payload.get("provider").toString(); + String url = payload.get("url").toString(); + + // Validate the provider + if(!Provider.validateProvider(provider)) { + responseData.put("success", false); + String providerNames = Stream.of(Provider.values()) + .map(Provider::getName) + .collect(Collectors.joining(", ")); + responseData.put("message", "Provider " + provider + " is not supported currently. " + + "Only " + providerNames + " are supported"); + return res.json(responseData); + } + + // Validate the URL + UrlValidator urlValidator = new UrlValidator(); + if (!urlValidator.isValid(url)) { + responseData.put("success", false); + responseData.put("message", "Provided URL: " + url + " is not valid, please provide a valid, correctly formed URL"); + return res.json(responseData); + } + + return null; +} + +/** + * This function will validate that the payload and variables are non-empty in the request + * + * @param req is the received POST request + * @return null is nothing is empty, otherwise an error response + */ +private RuntimeResponse checkEmptyPayloadAndVariables(RuntimeRequest req, RuntimeResponse res) { + Map responseData = new HashMap<>(); + + if(req.getPayload() == null || req.getPayload().trim().isEmpty() || req.getPayload().trim().equals("{}")) { + responseData.put("success", false); + responseData.put("message", "Payload is empty, expected a payload with provider and URL"); + return res.json(responseData); + } + + if(req.getVariables() == null) { + responseData.put("success", false); + responseData.put("message", "Empty function variables found. You need to pass an API key for the provider"); + return res.json(responseData); + } + return null; +} + +/** + * This method validates that a non-empty API key is present in variables + * + * @param req is the received POST request + * @return null if non-empty API key is present, otherwise an error response + */ +private RuntimeResponse checkEmptyAPIKey(RuntimeRequest req, RuntimeResponse res, String apiKeyVariable) { + Map variables = req.getVariables(); + + if(!variables.containsKey(apiKeyVariable) + || variables.get(apiKeyVariable) == null + || variables.get(apiKeyVariable).trim().isEmpty()) { + Map responseData = new HashMap<>(); + responseData.put("success", false); + responseData.put("message", "Please pass a non-empty API Key " + apiKeyVariable + " for the provider"); + return res.json(responseData); + } + + return null; +} + +/** + * This method will generate a short URL for the given long URL and provider using the provider's API key + * It will generate the request body and parse the response according to the provider + * + * @param apiKey is the access token used by the provider to generate a short URL + * @param provider is the service that will generate the short URL. E.g. tinyurl, bitly + * @param url is the URL to be shortened + * @return the shortened URL + * @throws Exception in case of malformed URL, I/O exception, etc. + */ +private String generateShortUrl(String apiKey, String provider, String url) throws Exception { + if(apiKey == null || apiKey.trim().isEmpty()) { + return null; + } + + String requestBody = ""; + + if(Provider.BITLY.getName().equals(provider)) { + requestBody = "{\"long_url\": \"" + url + "\"}"; + } else if(Provider.TINY_URL.getName().equals(provider)) { + requestBody = "{\"url\": \"" + url + "\"}"; + } + + if(requestBody.isEmpty()) { + return null; + } + + String response = getShortUrlFromProvider(endpointsMap.get(provider), requestBody, apiKey); + Map parsedResponse = gson.fromJson(response, Map.class); + + if(Provider.BITLY.getName().equals(provider)) { + return parsedResponse.get("link").toString(); + } else if(Provider.TINY_URL.getName().equals(provider)) { + Map responseData = (Map) parsedResponse.get("data"); + return responseData.get("tiny_url").toString(); + } + + return null; +} + +/** + * This method will send a POST request to the specified endpoint and return the provider's response + * + * @param endpointUrl is the provider's POST endpoint to which the URL generation request is to be sent + * @param requestBody is the Request Body for the POST request containing the URL to be shortened + * @param apiKey is the access token used by the provider to generate a short URL + * @return the provider's response to the POST request + * @throws Exception in case of malformed URL, I/O exception, etc. + */ +private String getShortUrlFromProvider(String endpointUrl, String requestBody, String apiKey) throws Exception { + URL url = new URL(endpointUrl); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + + con.setRequestMethod("POST"); + con.setRequestProperty("Content-Type", "application/json"); + con.setRequestProperty("Authorization", "Bearer " + apiKey); + con.setRequestProperty("Accept", "application/json"); + con.setDoOutput(true); + + OutputStream os = con.getOutputStream(); + byte[] input = requestBody.getBytes("utf-8"); + os.write(input, 0, input.length); + + StringBuilder response = new StringBuilder(); + + BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8")); + String responseLine = null; + while ((responseLine = br.readLine()) != null) { + response.append(responseLine.trim()); + } + + br.close(); + con.disconnect(); + + return response.toString(); +} \ No newline at end of file diff --git a/java/short_url_generator/README.md b/java/short_url_generator/README.md new file mode 100644 index 00000000..ef6ec7cf --- /dev/null +++ b/java/short_url_generator/README.md @@ -0,0 +1,91 @@ +# 💻 Get Short URL + +A Java Cloud Function for generating a Short URL using [tinyurl](https://tinyurl.com/app) and [bitly](https://bitly.com/) + +Supported providers: tinyurl, bitly + +_Bitly Example input:_ + + + +```json +{ + "provider": "bitly", + "url": "https://google.com" +} +``` + +_Bitly Example output:_ + + +```json +{ + "success": true, + "url": "https://bit.ly/3CywbjA" +} +``` + +_Tinyurl Example input:_ + + + +```json +{ + "provider": "tinyurl", + "url": "https://google.com" +} +``` + +_Tinyurl Example output:_ + + +```json +{ + "success": true, + "url": "https://tinyurl.com/dck67zxk" +} +``` + +_Error Example output:_ + +```json +{ + "success": false, + "message":"Provided URL: https://xyz is not valid, please provide a valid, correctly formed URL" +} +``` + + +## 📝 Environment Variables + +List of environment variables used by this cloud function. These must be passed within 'variables' section of the request: + +**BITLY_API_KEY** - Pass this API key if the requested provider is bitly. This API key would be the access token used by bitly for generating a short URL. + +**TINYURL_API_KEY** - Pass this API key if the requested provider is tinyurl. This API key would be the access token used by tinyurl for generating a short URL. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd java/short_url_generator +``` + +2. Enter this function folder and build the code: +``` +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=Index.java --rm --interactive --tty --volume $PWD:/usr/code openruntimes/java:v2-11.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/java:v2-11.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Java runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/java-11.0). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Java 11.0. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/java/short_url_generator/deps.gradle b/java/short_url_generator/deps.gradle new file mode 100644 index 00000000..16206c71 --- /dev/null +++ b/java/short_url_generator/deps.gradle @@ -0,0 +1,4 @@ +dependencies { + implementation 'com.google.code.gson:gson:2.9.0' + implementation 'commons-validator:commons-validator:1.7' +} \ No newline at end of file diff --git a/kotlin/deepgram-transcribe-audio/README.md b/kotlin/deepgram-transcribe-audio/README.md new file mode 100644 index 00000000..d2874160 --- /dev/null +++ b/kotlin/deepgram-transcribe-audio/README.md @@ -0,0 +1,63 @@ +# 🧹 Deepgram Transcribe Audio + +A Cloud Function for transcribing audio using [Deepgram](https://deepgram.com/) + +_Example input:_ + +```json +{ + "fileUrl": "https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav" +} +``` + +_Example output:_ + + +```json +{ + "deepgramData": {}, + "success": true +} +``` + +_Example error output:_ + + +```json +{ + "success":false, + "message":"Error Message" +} +``` + +## 📝 Environment Variables + +**DEEPGRAM_API_KEY** - Your Deepgram secret API key. +Details are under link: [Deepgram_getting_started](https://developers.deepgram.com/documentation/getting-started/) + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd kotlin/deepgram-transcribe-audio +``` + +2. Build the code: + +```bash +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/Index.kt --rm --interactive --tty --volume $PWD:/usr/code openruntimes/kotlin:v2-1.6 sh /usr/local/src/build.sh +``` + +3. Spin-up open-runtime: + +```bash +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/kotlin:v2-1.6 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Kotlin runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/kotlin-1.6). + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). diff --git a/kotlin/deepgram-transcribe-audio/deps.gradle b/kotlin/deepgram-transcribe-audio/deps.gradle new file mode 100644 index 00000000..88d25ae1 --- /dev/null +++ b/kotlin/deepgram-transcribe-audio/deps.gradle @@ -0,0 +1,3 @@ +dependencies { + implementation 'com.google.code.gson:gson:2.9.0' +} diff --git a/kotlin/deepgram-transcribe-audio/src/Index.kt b/kotlin/deepgram-transcribe-audio/src/Index.kt new file mode 100644 index 00000000..ade48196 --- /dev/null +++ b/kotlin/deepgram-transcribe-audio/src/Index.kt @@ -0,0 +1,86 @@ +import com.google.gson.Gson +import com.google.gson.JsonSyntaxException +import io.openruntimes.kotlin.RuntimeRequest +import io.openruntimes.kotlin.RuntimeResponse +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStreamReader +import java.io.OutputStream +import java.net.HttpURLConnection +import java.net.URL + + +val HTTP_BAD_REQEST = 400 +val DEEPGRAM_TRANSCRIBE_AUDIO_API_END_POINT = "https://api.deepgram.com/v1/listen" +val gson = Gson() + +fun getErrorResponseWithMessage(res: RuntimeResponse, message: String? = "Some error occurred"): RuntimeResponse { + return res.json( + data = mapOf( + "success" to false, + "message" to message + ), + statusCode = HTTP_BAD_REQEST + ) +} + +@Throws(Exception::class) +suspend fun main(req: RuntimeRequest, res: RuntimeResponse): RuntimeResponse { + + val deepgramApiKey = req.variables["DEEPGRAM_API_KEY"] + if (deepgramApiKey == null || deepgramApiKey.trim().isEmpty()) { + return getErrorResponseWithMessage(res, "Deepgram API key must be set to use this function.") + } + + val payloadMap = Gson().fromJson>( + req.payload.ifBlank { "{}" }, + Map::class.java + ) + val fileUrl = payloadMap["fileUrl"] ?: "" + + if (fileUrl.isEmpty() || fileUrl.trim().isEmpty()) { + return getErrorResponseWithMessage(res, "Payload doesn't contain 'fileUrl'") + } + + val url = URL(DEEPGRAM_TRANSCRIBE_AUDIO_API_END_POINT) + val conn: HttpURLConnection = url.openConnection() as HttpURLConnection + + conn.requestMethod = "POST" + conn.addRequestProperty("Content-Type", "application/json") + conn.addRequestProperty("Authorization", "Token $deepgramApiKey") + + conn.doOutput = true + + //prepare request body + val requestBody ="{\"url\":\""+fileUrl+"\"}" + + val response = StringBuilder() + + try { + val os: OutputStream = conn.getOutputStream() + val input: ByteArray = requestBody.toByteArray(Charsets.UTF_8) + os.write(input, 0, input.size) + + val br = BufferedReader(InputStreamReader(conn.getInputStream(), "utf-8")) + var responseLine: String? = null + while (br.readLine().also { responseLine = it } != null) { + response.append(responseLine!!.trim { it <= ' ' }) + } + + br.close() + conn.disconnect() + } + catch (e: Exception){ + return getErrorResponseWithMessage(res, e.message) + } + + + val deepgramResponse = response.toString() + return res.json( + data = mapOf( + "success" to true, + "deepgramData" to deepgramResponse + ), + statusCode = 200 + ) +} diff --git a/kotlin/generate-short-url/README.md b/kotlin/generate-short-url/README.md new file mode 100644 index 00000000..cc4aac02 --- /dev/null +++ b/kotlin/generate-short-url/README.md @@ -0,0 +1,78 @@ +# 🔗 Shorten a url + +A Kotlin Cloud Function for shorten a url with two providers: + +- [Bitly](https://bitly.com/) +- [Tinyurl](https://tinyurl.com/) + +## Example input: + +```json +{ + "provider":"bitly", + "url":"https://google.com/", +} +``` + +## Example output: + +Successful response: + +```json +{ + "success":true, + "url":"https://bit.ly/3y3HDkC" +} +``` + +Error response: + +```json +{ + "success":false, + "message":"Payload does not contain 'provider'" +} +``` + +```json +{ + "success":false, + "message":"Payload does not contain 'url'" +} +``` + +## 📝 Variables + +- `PROVIDER_API_KEY`: Bitly or Tinyurl API key + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd kotlin/generate-short-url +``` + +2. Build the code: + +```bash +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=src/Index.kt --rm --interactive --tty --volume $PWD:/usr/code openruntimes/kotlin:v2-1.6 sh /usr/local/src/build.sh +``` + +3. Spin-up open-runtime: + +```bash +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/kotlin:v2-1.6 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Kotlin runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/kotlin-1.6). + +4. Execute command: +```bash +curl -X 'POST' 'http://localhost:3000/' -H 'Content-Type: application/json' -H 'X-Internal-Challenge: secret-key' -d '{"payload": "{\"url\":\"https://appwrite.io/\",\"provider\":\"bitly\"}","variables": {"PROVIDER_API_KEY":""}}' +``` + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). diff --git a/kotlin/generate-short-url/deps.gradle b/kotlin/generate-short-url/deps.gradle new file mode 100644 index 00000000..a2e7f58b --- /dev/null +++ b/kotlin/generate-short-url/deps.gradle @@ -0,0 +1,3 @@ +dependencies { + implementation 'com.google.code.gson:gson:2.9.0' +} \ No newline at end of file diff --git a/kotlin/generate-short-url/src/Index.kt b/kotlin/generate-short-url/src/Index.kt new file mode 100644 index 00000000..f4a7507f --- /dev/null +++ b/kotlin/generate-short-url/src/Index.kt @@ -0,0 +1,113 @@ +import com.google.gson.Gson +import com.google.gson.JsonParser +import com.google.gson.JsonSyntaxException +import io.openruntimes.kotlin.RuntimeRequest +import io.openruntimes.kotlin.RuntimeResponse +import java.io.BufferedReader +import java.io.IOException +import java.io.InputStreamReader +import java.io.OutputStream +import java.net.HttpURLConnection +import java.net.URL + + +val PROVIDER_API_MAP = mapOf("bitly" to "https://api-ssl.bitly.com/v4/shorten", + "tinyurl" to "https://api.tinyurl.com/create") + +val PROVIDER_API_URL_KEY = mapOf("bitly" to "long_url","tinyurl" to "url") + +val gson = Gson() + +fun getErrorResponseWithMessage(res: RuntimeResponse, message: String? = "Some error occurred"): RuntimeResponse { + return res.json( + data = mapOf( + "success" to false, + "message" to message + ), + statusCode = 400 + ) +} + +@Throws(Exception::class) +suspend fun main(req: RuntimeRequest, res: RuntimeResponse): RuntimeResponse { + + val payloadMap = Gson().fromJson>( + req.payload.ifBlank { "{}" }, + Map::class.java + ) + + val provider = payloadMap["provider"]?:"" + val longUrl = payloadMap["url"] ?: "" + val providerApiKey = req.variables["PROVIDER_API_KEY"]?:"" + var providerResponse="" + + try{ + + if (provider.isEmpty() || provider.trim().isEmpty()) { + return getErrorResponseWithMessage(res, "Payload doesn't contain 'provider'") + } + if (longUrl.isEmpty() || longUrl.trim().isEmpty()) { + return getErrorResponseWithMessage(res, "Payload doesn't contain 'url'") + } + + if(!PROVIDER_API_MAP.contains(provider)){ + return getErrorResponseWithMessage(res, "Payload doesn't contain valid provider - '$provider'.") + } + + val providerUrl = URL(PROVIDER_API_MAP.get(provider)) + + val connection = createConnection(providerUrl,providerApiKey) + + val requestBody ="{\"${PROVIDER_API_URL_KEY.get(provider)}\":\"$longUrl\"}" + + providerResponse= parseResponse(connection,requestBody,provider) + } + catch (e: Exception){ + return getErrorResponseWithMessage(res, e.message) + } + + return res.json( + data = mapOf( + "success" to true, + "url" to providerResponse + ), + statusCode = 200 + ) +} + +fun createConnection(providerUrl:URL,providerApiKey:String): HttpURLConnection { + val connection: HttpURLConnection = providerUrl.openConnection() as HttpURLConnection + connection.requestMethod = "POST" + connection.addRequestProperty("Content-Type", "application/json") + connection.addRequestProperty("Authorization", "Bearer $providerApiKey") + connection.setRequestProperty("accept", "application/json") + connection.doOutput = true + return connection +} + +fun parseResponse(connection:HttpURLConnection,requestBody:String,provider:String): String { + val response = StringBuilder() + val os: OutputStream = connection.getOutputStream() + val input: ByteArray = requestBody.toByteArray(Charsets.UTF_8) + os.write(input, 0, input.size) + + val br = BufferedReader(InputStreamReader(connection.getInputStream(), Charsets.UTF_8)) + + var responseLine: String? = null + + while (br.readLine().also { responseLine = it } != null) { + response.append(responseLine!!.trim { it <= ' ' }) + } + + br.close() + connection.disconnect() + + val jsonObject = JsonParser().parse(response.toString()).getAsJsonObject() + + return when { + provider == "bitly" -> jsonObject.get("link").getAsString() + else -> jsonObject.getAsJsonObject("data").get("tiny_url").getAsString() + } + +} + diff --git a/kotlin/wipeAppwriteBucket/README.md b/kotlin/wipeAppwriteBucket/README.md new file mode 100644 index 00000000..a4c13c63 --- /dev/null +++ b/kotlin/wipeAppwriteBucket/README.md @@ -0,0 +1,57 @@ +# wipeAppwriteBucket() - Kotlin + +## ⚡ Function Details + +Delete all files inside an Appwrite Storage bucket. +Bucket ID should be received as payload. + +Gets list of files in batches and continue until files returned equals files available. +Appwrite API will return at most 100 records at a time. + +Adds a 1 second delay after each batch of deletion to avoid overwhelming the server. + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key + +## Example input: + +```json +{ + "bucketId": "profilePictures" +} +``` + +## Example output: + +Successful response: + +```json +{ + "success": true +} +``` + +Error response: + +```json +{ + "success": false, + "message": "Error description" +} +``` + +## 🚀 Deployment + +There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. It is highly recommended to use CLI deployment to achieve the best experience. + +### Using CLI + +For instrunctions on using the Appwrite CLI check https://appwrite.io/docs/functions#deployFunction + +### Manual using tar.gz + +Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/Index.kt`, and upload the file just generated. diff --git a/kotlin/wipeAppwriteBucket/deps.gradle b/kotlin/wipeAppwriteBucket/deps.gradle new file mode 100644 index 00000000..c2b42c92 --- /dev/null +++ b/kotlin/wipeAppwriteBucket/deps.gradle @@ -0,0 +1,4 @@ +dependencies { + implementation 'io.appwrite:sdk-for-kotlin:1.1.0' + implementation 'com.google.code.gson:gson:2.9.0' +} \ No newline at end of file diff --git a/kotlin/wipeAppwriteBucket/src/Index.kt b/kotlin/wipeAppwriteBucket/src/Index.kt new file mode 100644 index 00000000..fad32df9 --- /dev/null +++ b/kotlin/wipeAppwriteBucket/src/Index.kt @@ -0,0 +1,82 @@ +import com.google.gson.Gson +import io.appwrite.Client +import io.appwrite.Query +import io.appwrite.services.Storage +import kotlinx.coroutines.delay + +/* + 'req' variable has: + 'headers' - object with request headers + 'payload' - request body data as a string + 'variables' - object with function variables + + 'res' variable has: + 'send(text, status)' - function to return text response. Status code defaults to 200 + 'json(obj, status)' - function to return JSON response. Status code defaults to 200 + + If an error is thrown, a response with code 500 will be returned. +*/ + +@Throws(Exception::class) +suspend fun main(req: RuntimeRequest, res: RuntimeResponse): RuntimeResponse { + val QUERY_LIMIT = 100 + val HTTP_BAD_REQEST = 400 + + // Check for API endpoint and key in the variables + if (req.variables["APPWRITE_FUNCTION_ENDPOINT"] == null + || req.variables["APPWRITE_FUNCTION_API_KEY"] == null) { + + return res.json( + data = mapOf( + "success" to false, + "message" to "Environment variables are not set, Function cannot use Appwrite SDK" + ), + statusCode = HTTP_BAD_REQEST + ) + } + + // Check for bucketId in the payload + val payloadMap = Gson().fromJson>( + req.payload.ifBlank { "{}" }, + Map::class.java) + val bucketId = payloadMap["bucketId"] ?: "" + + if (bucketId.isEmpty()) { + return res.json( + data = mapOf( + "success" to false, + "message" to "Payload doesn't contain 'bucketId'" + ), + statusCode = HTTP_BAD_REQEST + ) + } + + val client = Client() + .setEndpoint(req.variables["APPWRITE_FUNCTION_ENDPOINT"]!!) + .setProject(req.variables["APPWRITE_FUNCTION_PROJECT_ID"]!!) + .setKey(req.variables["APPWRITE_FUNCTION_API_KEY"]!!) + + val storage = Storage(client) + + // Get list of files in batches and continue until files returned equals files available + // Appwrite API will return at most 100 records at a time + do { + val fileList = storage.listFiles( + bucketId = bucketId, + queries = listOf(Query.limit(QUERY_LIMIT)) + ) + println("Fetched ${fileList.files.size} files out of total ${fileList.total}") + + // Delete the files returned in current batch + for (file in fileList.files) { + storage.deleteFile(bucketId, file.id) + println("\tDeleted file: ${file.id}") + } + + // A delay to avoid overwhelming the server + delay(1000) + + } while (fileList.files.size < fileList.total) + + return res.json(mapOf("success" to true)) +} diff --git a/node/.gitignore b/node/.gitignore new file mode 100644 index 00000000..66ba7e92 --- /dev/null +++ b/node/.gitignore @@ -0,0 +1,131 @@ +## Node Gitignore +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* \ No newline at end of file diff --git a/node/convert-phone-number-to-country-name/README.md b/node/convert-phone-number-to-country-name/README.md new file mode 100644 index 00000000..7978f89e --- /dev/null +++ b/node/convert-phone-number-to-country-name/README.md @@ -0,0 +1,60 @@ +# 📱 Validate phone number and get it's country information + +A Node Cloud Function that figures out country in which a phone number is registered. + +_Example input:_ + +```json +{ + "phoneNumber": "+421957215740" +} +``` + +> Function can also accept phone numbers with spaces, for instance `+421 957 215 740`. + + +_Example output:_ + + +```json +{ + "phoneNumber": "+421957215740", + "phonePrefix": "+421", + "countryCode": "SK", + "countryName": "Slovakia" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of your Appwrite server +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key +- **APPWRITE_FUNCTION_PROJECT_ID** - Appwrite project ID. If running on Appwrite, this variable is provided automatically. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/convert_phone_number_to_country_name +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-17.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.js --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-17.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Node runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-17.0). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Node 17.0. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/node/convert-phone-number-to-country-name/index.js b/node/convert-phone-number-to-country-name/index.js new file mode 100644 index 00000000..fa40b6bc --- /dev/null +++ b/node/convert-phone-number-to-country-name/index.js @@ -0,0 +1,69 @@ +const sdk = require('node-appwrite'); + +/* +Globally scoped cache used by function. Example value: +[ + { + "code": "+1", + "countryCode": "US", + "countryName": "United States" + } +] +*/ +let phonePrefixList; + +module.exports = async (req, res) => { + // Input validation + let phoneNumber; + try { + const payload = JSON.parse(req.payload); + phoneNumber = payload.phoneNumber.split(' ').join(''); + } catch(err) { + console.log(err); + throw new Error('Payload is invalid.'); + } + + if(!phoneNumber || !phoneNumber.startsWith('+')) { + throw new Error('Invalid phone number.'); + } + + // Make sure we have envirnment variables required to execute + if( + !req.variables.APPWRITE_FUNCTION_ENDPOINT || + !req.variables.APPWRITE_FUNCTION_PROJECT_ID || + !req.variables.APPWRITE_FUNCTION_API_KEY + ) { + throw new Error('Please provide all required environment variables.'); + } + + // If we don't have cached list of phone number prefixes (first execution only) + if(!phonePrefixList) { + // Init Appwrite SDK + const client = new sdk.Client(); + const locale = new sdk.Locale(client); + + client + .setEndpoint(req.variables.APPWRITE_FUNCTION_ENDPOINT) + .setProject(req.variables.APPWRITE_FUNCTION_PROJECT_ID) + .setKey(req.variables.APPWRITE_FUNCTION_API_KEY); + + // Fetch and store phone number prefixes + const serverResponse = await locale.getCountriesPhones(); + phonePrefixList = serverResponse.phones; + } + + // Get phone prefix + const phonePrefix = phonePrefixList.find((prefix) => phoneNumber.startsWith(prefix.code)); + + if(!phonePrefix) { + throw new Error('Invalid phone number.'); + } + + // Return phone number prefix + res.json({ + phoneNumber, + phonePrefix: phonePrefix.code, + countryCode: phonePrefix.countryCode, + countryName: phonePrefix.countryName + }); +}; \ No newline at end of file diff --git a/node/convert-phone-number-to-country-name/package-lock.json b/node/convert-phone-number-to-country-name/package-lock.json new file mode 100644 index 00000000..b91296d5 --- /dev/null +++ b/node/convert-phone-number-to-country-name/package-lock.json @@ -0,0 +1,175 @@ +{ + "name": "convert_phone_number_to_country_name", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "convert_phone_number_to_country_name", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "node-appwrite": "^5.0.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/axios": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", + "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", + "dependencies": { + "follow-redirects": "^1.14.7" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dependencies": { + "mime-db": "1.51.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-appwrite": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-5.0.0.tgz", + "integrity": "sha512-VJ9e5+ra+ycQS17C0aJMbVXK4Gcja6at+f2EzlRlsjxAzTMetb79QJBOO6ktMtmVrUkAieMnaMZcV1hPppERmg==", + "dependencies": { + "axios": "^0.25.0", + "form-data": "^4.0.0" + } + }, + "node_modules/node-appwrite/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + } + }, + "dependencies": { + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "axios": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", + "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", + "requires": { + "follow-redirects": "^1.14.7" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + }, + "mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + }, + "mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "requires": { + "mime-db": "1.51.0" + } + }, + "node-appwrite": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-5.0.0.tgz", + "integrity": "sha512-VJ9e5+ra+ycQS17C0aJMbVXK4Gcja6at+f2EzlRlsjxAzTMetb79QJBOO6ktMtmVrUkAieMnaMZcV1hPppERmg==", + "requires": { + "axios": "^0.25.0", + "form-data": "^4.0.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + } + } +} diff --git a/node/convert-phone-number-to-country-name/package.json b/node/convert-phone-number-to-country-name/package.json new file mode 100644 index 00000000..0bc553e7 --- /dev/null +++ b/node/convert-phone-number-to-country-name/package.json @@ -0,0 +1,15 @@ +{ + "name": "convert_phone_number_to_country_name", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "node-appwrite": "^5.0.0" + } +} diff --git a/node/deepgram-transcribe-video/README.md b/node/deepgram-transcribe-video/README.md new file mode 100644 index 00000000..730807de --- /dev/null +++ b/node/deepgram-transcribe-video/README.md @@ -0,0 +1,69 @@ +# 📝 Deepgram Transcribe Video + +A Node Cloud Function for transcribing a video using the [DEEPGRAM API](https://developers.deepgram.com/). + +_Example input 1:_ + +```json +{ + "payload": "{\"fileUrl\": \"https://rawcdn.githack.com/deepgram-devs/transcribe-videos/62fc7769d6e2bf38e420ee5224060922af4546f7/deepgram.mp4\"}" +} +``` + +_Example output 1:_ + +```json +{ + "success": true, + "deepgramData": {"A long": "Object"}, +} +``` + +_Example input 2:_ + +```json +{ + "payload": "{}" +} +``` + +_Example output 2:_ + +```json +{ + "success": false, + "message": "Please provide a file url in payload" +} +``` + +## 📝 Variables + +List of variables used by this cloud function: + +**DEEPGRAM_API_KEY** - Your Deepgram API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/deepgram-transcribe-video +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-18.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=index.js -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-18.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit NodeJS runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-18.0). + +## 📝 Notes +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with NodeJS 18.0. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/node/deepgram-transcribe-video/index.js b/node/deepgram-transcribe-video/index.js new file mode 100644 index 00000000..aa8ffbb6 --- /dev/null +++ b/node/deepgram-transcribe-video/index.js @@ -0,0 +1,66 @@ +const axios = require("axios").default; + +module.exports = async (req, res) => { + let fileUrl; + try { + const payload = JSON.parse(req.payload); + fileUrl = payload.fileUrl; + } catch (err) { + res.json({ + success: false, + message: "Payload does not have a proper structure.", + }); + return; + } + let deepgramApiKey = req.variables["DEEPGRAM_API_KEY"]; + + //checks + if (!deepgramApiKey) { + res.json({ + success: false, + message: "Please provide Deepgram Api Key as an environment variable.", + }); + return; + } + if (!fileUrl) { + res.json({ + success: false, + message: "Please provide a valid file URL.", + }); + return; + } + //setting headers + let headers = { + "content-type": "application/json", + Authorization: `Token ${deepgramApiKey}`, + }; + + //setting our file url + let data = JSON.stringify({ + url: fileUrl, + }); + + //making the request + try { + const response = await axios.post( + `https://api.deepgram.com/v1/listen?model=video`, + data, + { + headers: headers, + } + ); + if (response.status !== 200) { + res.json({ + success: false, + message: response.data, + }); + return; + } + res.json({ + success: true, + deepgramData: response.data, + }); + } catch (error) { + res.json({ success: false, message: error.toString() }); + } +}; diff --git a/node/deepgram-transcribe-video/package-lock.json b/node/deepgram-transcribe-video/package-lock.json new file mode 100644 index 00000000..685b938b --- /dev/null +++ b/node/deepgram-transcribe-video/package-lock.json @@ -0,0 +1,58 @@ +{ + "name": "deepgram-transcribe-video", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "deepgram-transcribe-video", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "axios": "0.26.1" + } + }, + "node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + } + }, + "dependencies": { + "axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "requires": { + "follow-redirects": "^1.14.8" + } + }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + } + } +} diff --git a/node/deepgram-transcribe-video/package.json b/node/deepgram-transcribe-video/package.json new file mode 100644 index 00000000..f4752468 --- /dev/null +++ b/node/deepgram-transcribe-video/package.json @@ -0,0 +1,15 @@ +{ + "name": "deepgram-transcribe-video", + "version": "1.0.0", + "description": "", + "type": "commonjs", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "axios": "0.26.1" + } +} diff --git a/node/deepgram_audio_summary/README.md b/node/deepgram_audio_summary/README.md new file mode 100644 index 00000000..9e250803 --- /dev/null +++ b/node/deepgram_audio_summary/README.md @@ -0,0 +1,70 @@ +# 🔉📃 Summarize Audio with Deepgram + +A NodeJS Cloud Function for summarizing audio number using [Deepgram API](https://deepgram.com/). + +_Example input:_ + +```json +{ + "fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Example output:_ + +```json +{ + "success": true, + "deepgramData": [ + { + "summary": "another big problem in the speech analytics space. When customers first bring the software on is that they they are blown away by the fact that an engine can monitor hundreds of Kpis.", + "start_word": 0, + "end_word": 228 + } + ] +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **DEEPGRAM_API_KEY** - Deepgram API Key + +ℹ️ _Create your Deepgram API key at console.deepgram.com_ + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +```bash +git clone https://github.com/open-runtimes/examples.git && cd examples +cd node/deepgram_audio_summary +``` + +2. Enter this function folder and build the code: + +```bash +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-18.0 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +```bash +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/index.js -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-18.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit NodeJS runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-18.0). + +4. Run the cURL function to send request. + +```bash +curl --location --request POST 'http://localhost:3000' --header 'Content-Type: application/json' --header 'X-Internal-Challenge: secret-key' --data-raw '{"variables": {"DEEPGRAM_API_KEY": "YOUR_DEEPGRAM_API_KEY"},"payload": {"fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav"}}' +``` + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with NodeJS 18.0. Other versions may work but are not guarenteed to work as they haven't been tested. diff --git a/node/deepgram_audio_summary/package-lock.json b/node/deepgram_audio_summary/package-lock.json new file mode 100644 index 00000000..c0036a2a --- /dev/null +++ b/node/deepgram_audio_summary/package-lock.json @@ -0,0 +1,169 @@ +{ + "name": "deepgram_audio_summary", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "deepgram_audio_summary", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "axios": "^1.2.1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz", + "integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + } + }, + "dependencies": { + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz", + "integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + } + } +} diff --git a/node/deepgram_audio_summary/package.json b/node/deepgram_audio_summary/package.json new file mode 100644 index 00000000..be9dece8 --- /dev/null +++ b/node/deepgram_audio_summary/package.json @@ -0,0 +1,15 @@ +{ + "name": "deepgram_audio_summary", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "axios": "^1.2.1" + } +} diff --git a/node/deepgram_audio_summary/src/index.js b/node/deepgram_audio_summary/src/index.js new file mode 100644 index 00000000..51c3b31f --- /dev/null +++ b/node/deepgram_audio_summary/src/index.js @@ -0,0 +1,36 @@ +const axios = require('axios').default; + +module.exports = async (req, res) => { + const APIkey = req.variables['DEEPGRAM_API_KEY']; + const { fileUrl } = req.payload; + + if (!APIkey) { + throw new Error('Deepgram API Key is required'); + } + + if (!fileUrl) { + throw new Error('fileUrl is required'); + } + + const resp = await axios.post( + 'https://api.deepgram.com/v1/listen?summarize=true&punctuate=true', + { + url: fileUrl, + }, + { + headers: { + 'content-type': 'application/json', + Authorization: `Token ${APIkey}`, + }, + }, + ); + + if (resp.status === 200) { + res.json({ + success: true, + deepgramData: resp.data.results, + }); + } else { + res.json({ success: false, message: 'Please provide a valid file URL.' }); + } +}; diff --git a/node/deepgram_topic_detection/README.md b/node/deepgram_topic_detection/README.md new file mode 100644 index 00000000..46957c20 --- /dev/null +++ b/node/deepgram_topic_detection/README.md @@ -0,0 +1,75 @@ +# 🕵️ Deepgram Topic Detection + +A Node Cloud Function that detect list of topic from spoken audio using [Deepgram API](https://developers.deepgram.com/documentation/). + +_Example input function payload:_ + +```json +{ "fileUrl": "url_of_the_wav_file" } +``` + +_Successful function response:_ + +```json +{ + "success": true, + "deepgramData": {} +} +``` + +_Error function response:_ + +```json +{ + "success": false, + "message": "Please provide a valid file URL and API key." +} +``` + +## 📝 Variables + +List of variables used by this cloud function: + +- **DEEPGRAM_API_KEY** - Your Deepgram API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/deepgram_topic_detection +``` + +2. Enter this function folder and build the code: + +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-18.0 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=src/index.js --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-18.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request to `http://localhost:3000` with appropriate authorization headers. To learn more about runtime, you can visit NodeJS runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-18.0). + +## 🧪 Test Function Execution + +In new terminal window, execute function to send request: + +```bash +curl -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" -X POST http://localhost:3000/ -d '{"payload": "{\"fileUrl\":\"url_of_the_wav_file\"}", "variables": {"DEEPGRAM_API_KEY": "your_deepgram_api_key"} }' +``` + +- Make sure to use bash terminal, if you are using other terminal then modify the `payload` accordingly +- Replace the `url_of_the_wav_file` and `your_deepgram_api_key` +- Make sure you have header `x-internal-challenge: secret-key`. + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with NodeJS 18.0. Other versions may work but are not guarenteed to work as they haven't been tested. diff --git a/node/deepgram_topic_detection/package-lock.json b/node/deepgram_topic_detection/package-lock.json new file mode 100644 index 00000000..4b97958e --- /dev/null +++ b/node/deepgram_topic_detection/package-lock.json @@ -0,0 +1,119 @@ +{ + "name": "deepgram_topic_detection", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "deepgram_topic_detection", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@deepgram/sdk": "^1.10.1" + } + }, + "node_modules/@deepgram/sdk": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@deepgram/sdk/-/sdk-1.10.1.tgz", + "integrity": "sha512-HZ7PPIZ1ejGKnfOVkb4gMPDTjKIs/1lTC2W3OPzTI56nGJGd3EVUp/wiQ9w3lru3Rdz+OxrcVo1WzcjWu4w/Lg==", + "dependencies": { + "bufferutil": "^4.0.6", + "utf-8-validate": "^5.0.9", + "ws": "^7.5.5" + } + }, + "node_modules/bufferutil": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", + "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/node-gyp-build": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", + "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/utf-8-validate": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", + "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + }, + "dependencies": { + "@deepgram/sdk": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@deepgram/sdk/-/sdk-1.10.1.tgz", + "integrity": "sha512-HZ7PPIZ1ejGKnfOVkb4gMPDTjKIs/1lTC2W3OPzTI56nGJGd3EVUp/wiQ9w3lru3Rdz+OxrcVo1WzcjWu4w/Lg==", + "requires": { + "bufferutil": "^4.0.6", + "utf-8-validate": "^5.0.9", + "ws": "^7.5.5" + } + }, + "bufferutil": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", + "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", + "requires": { + "node-gyp-build": "^4.3.0" + } + }, + "node-gyp-build": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", + "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==" + }, + "utf-8-validate": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", + "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", + "requires": { + "node-gyp-build": "^4.3.0" + } + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + } + } +} diff --git a/node/deepgram_topic_detection/package.json b/node/deepgram_topic_detection/package.json new file mode 100644 index 00000000..31d1de35 --- /dev/null +++ b/node/deepgram_topic_detection/package.json @@ -0,0 +1,15 @@ +{ + "name": "deepgram_topic_detection", + "version": "1.0.0", + "description": "A Node Cloud Function that detect list of topic from spoken audio using [Deepgram API](https://developers.deepgram.com/documentation/).", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@deepgram/sdk": "^1.10.1" + } +} diff --git a/node/deepgram_topic_detection/src/index.js b/node/deepgram_topic_detection/src/index.js new file mode 100644 index 00000000..bdaa2d20 --- /dev/null +++ b/node/deepgram_topic_detection/src/index.js @@ -0,0 +1,40 @@ +const { Deepgram } = require("@deepgram/sdk"); + +module.exports = async (req, res) => { + const { fileUrl } = JSON.parse(req.payload); + const apiKey = req.variables["DEEPGRAM_API_KEY"]; + + if (!apiKey) { + res.json({ + success: false, + message: "API key is required.", + }); + } + + if (!fileUrl) { + res.json({ + success: false, + message: "wav file url is required.", + }); + } + + const deepgram = new Deepgram(apiKey); + + try { + const response = await deepgram.transcription.preRecorded( + { url: fileUrl, mimetype: "audio/wav" }, + { detect_topics: true, punctuate: true } + ); + + res.json({ + success: true, + deepgramData: response, + }); + } catch (error) { + res.json({ + success: false, + message: "Please check file URL and API key.", + error: error, + }); + } +}; diff --git a/node/generate_giphy_gif/README.md b/node/generate_giphy_gif/README.md new file mode 100644 index 00000000..186382a9 --- /dev/null +++ b/node/generate_giphy_gif/README.md @@ -0,0 +1,53 @@ +# 🖼️ Get Giphy GIF + +A Node Cloud Function for generating Giphy GIF from the [Giphy API](https://developers.giphy.com/docs/api#quick-start-guide). + +_Example input:_ + +```json +{ + "search": "good morning" +} +``` + +_Example output:_ + + +```json +{ + "search": "good morning", + "gif": "https://giphy.com/gifs/text-gif-sticker-brittdoesdesign-MS9Yq6Y718CSiDTxR5" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +**GIPHY_API_KEY** - Your Giphy API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/generate_giphy_gif +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-17.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/index.js -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-17.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit NodeJS runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-17.0). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with NodeJS 17.0. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/node/generate_giphy_gif/package-lock.json b/node/generate_giphy_gif/package-lock.json new file mode 100644 index 00000000..8effdf32 --- /dev/null +++ b/node/generate_giphy_gif/package-lock.json @@ -0,0 +1,560 @@ +{ + "name": "object_detection", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "object_detection", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "axios": "^0.26.1", + "cloudmersive-image-api-client": "^1.3.1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cloudmersive-image-api-client": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/cloudmersive-image-api-client/-/cloudmersive-image-api-client-1.3.5.tgz", + "integrity": "sha512-73BS+8RQQmJbecpXc88gmy/398RXtjnwqNeO3ASq7mHX73BuR1Ng2Yn9oTvuOf1uSjEm6MfNH3xDvonEv1SLkA==", + "dependencies": { + "superagent": "3.7.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "node_modules/cookiejar": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", + "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/superagent": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.7.0.tgz", + "integrity": "sha512-/8trxO6NbLx4YXb7IeeFTSmsQ35pQBiTBsLNvobZx7qBzBeHYvKCyIIhW2gNcWbLzYxPAjdgFbiepd8ypwC0Gw==", + "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at .", + "dependencies": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.1.1", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + } + }, + "dependencies": { + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "requires": { + "follow-redirects": "^1.14.8" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "cloudmersive-image-api-client": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/cloudmersive-image-api-client/-/cloudmersive-image-api-client-1.3.5.tgz", + "integrity": "sha512-73BS+8RQQmJbecpXc88gmy/398RXtjnwqNeO3ASq7mHX73BuR1Ng2Yn9oTvuOf1uSjEm6MfNH3xDvonEv1SLkA==", + "requires": { + "superagent": "3.7.0" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "cookiejar": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", + "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + }, + "form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "superagent": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.7.0.tgz", + "integrity": "sha512-/8trxO6NbLx4YXb7IeeFTSmsQ35pQBiTBsLNvobZx7qBzBeHYvKCyIIhW2gNcWbLzYxPAjdgFbiepd8ypwC0Gw==", + "requires": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.1.1", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.0.5" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + } + } +} diff --git a/node/generate_giphy_gif/package.json b/node/generate_giphy_gif/package.json new file mode 100644 index 00000000..a751768e --- /dev/null +++ b/node/generate_giphy_gif/package.json @@ -0,0 +1,15 @@ +{ + "name": "generate_giphy_gif", + "version": "1.0.0", + "description": "", + "main": "src/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "axios": "^0.26.1" + } +} diff --git a/node/generate_giphy_gif/src/index.js b/node/generate_giphy_gif/src/index.js new file mode 100644 index 00000000..dfab29d2 --- /dev/null +++ b/node/generate_giphy_gif/src/index.js @@ -0,0 +1,32 @@ +const axios = require('axios').default; + +module.exports = async function (req, res) { + const APIkey = req.variables["GIPHY_API_KEY"] + + const { + search + } = JSON.parse(req.payload); + + if (!search) { + throw new Error("search is required"); + } + + if (!APIkey) { + throw new Error("API key is required"); + } + + const response = await axios.get(`https://api.giphy.com/v1/gifs/search?api_key=${APIkey}&q=${search}&limit=1`, { + headers: {'Apikey': APIkey} + }) + + if (response.status !== 200) { + throw new Error(`Status code: ${response.status}, Data: ${response.data}`); + } + + const dataJson = response.data; + + res.json({ + search: search, + gif: dataJson["data"][0]['url'] + }); +}; \ No newline at end of file diff --git a/node/generate_invoice/README.md b/node/generate_invoice/README.md new file mode 100644 index 00000000..053c78df --- /dev/null +++ b/node/generate_invoice/README.md @@ -0,0 +1,59 @@ +# 🧾 Generate Invoice + +A Node Cloud Function for generating invoice. + +_Example input:_ + +```json +{ + + "payload": { + "currency":"EUR", + "items":[{"name":"Web development","price":15}], + "issuer":"Some\nIssuer", + "customer":"Some\nCustomer", + "vat":21 + } +} +``` + +_Example output:_ + + +```json +{ + "success":true, + "invoice":"iVBORw0KGgoAAAANSUhEUgAAAaQAAALiCAY...QoH9hbkTPQAAAABJRU5ErkJggg==" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/generate_invoice +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-16.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/index.js -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-17.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit NodeJS runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-17.0). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with NodeJS 17.0. Other versions may work but are not guarenteed to work as they haven't been tested. diff --git a/node/generate_invoice/Screenshot from 2022-10-03 23-09-25.png b/node/generate_invoice/Screenshot from 2022-10-03 23-09-25.png new file mode 100644 index 0000000000000000000000000000000000000000..c3aec62489940a5dc4c61f9961c962c9ed2506c4 GIT binary patch literal 470857 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

h; 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

iRZ|k#*pT-+ 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

_Id9)-osBZO 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

(s(wG4Mp98?1d zyvR8B%@O^&FdE8DH^H+J$XQ3&T)vO9;by8%i%dW!`lU~cvNc_*GXm|fy@Yk7XMNew z`!3=*6sZdZHrU+*OaY}d4OnNvxcyB_MxI$)`v2biXnRrh~{ zk1K`6!<0jQ!ip1bOFAq^0Q?F~JnSMwN|_o4V68eyF(;Tsu@tI(8&AGCCA^9luYQ_< zpg6Pv^B5*RwR+j^1U{watqIg*RXT-g-e%8_`@YZ$8_uYho~m(CM2ZNC%{Ggj6QSQI zF8x)*L<_evRcMB5IHvc>P#7UyMn~b3ttpB)-xVHHoua<5;vbKV!nY%tr6G8nQO6$1 ze-BfkGOeG>l>IzKp7s@AEPe^y3aQMlOnyabuaR}6p%6qt_|17mW8|-%?W$J<_i}Q- zpeM$hqi(Wb`(ek4q`CNN16Bg@_Rn_|1K1d-rsSW*m|9+b4^^O&+XO%N-z&HTFg$lt3z z%?K#7Q|A;=%{YPc^}PJ`U2$*nQAP9~20A;PKS|lmb{F4qO396*r$uC*H=};2RSf`)3{@?WQD?e5;xW@fUs_VH9A?`cV$u6ZAfQ4e z(-+3TPM+TQkoxO?rsZe^Z#*X{l(cVpSbIo7!TdG56uh_6`#ZOtr=783O-ly zYZy4-ZKM5QAN~YduNijc|EPT1+;6`YtiZ*)PxE7~;qh1K$dU}edzHAm0TywUz`6GP zIwC5pQR}!UKQ8$_>CYoqvn^j+!luJ+U~5Eh z7g}6}w=YP!%Y`UiJNdA+u6sKM&sG`5i}RIlvt!O$&mz-7C6ut8DBdvQyl$?0kG64@ z!e#UCNo6d&1jCKtOS|+}8vLuD<%8WQ1a^88KA|Oi-;j%9tg<75aS26%)B^$U6o1xt zmfwu{w>UK`$iMceJ7d!Yd^5|7@Bf7pK32xFQ(XEvOs|%y*`!!$%*a+5>J)R8Z~n}% zI#RH|Cs3-9P~ei4fnpqTOX2GZGTR1RYj?Y5dw)nY0k7t=U?6IIkGqb`gU4st_SXq)6SU# zO_cdzE*2M@hK{4X>r#yey}|n(PLi|RUHrX!!Z`$&D+H#jw$(>VSsl9 zRAPb!(`_KD1C6kM>^RhZ`Ruyy#Zx2crvJ~VX0jpMGmvhX*lj_^AKPKTl9wO_k`Op@ z5sg5ITfA8NUf=p`b1?V3b9w2V!Y}~)-?YqpKeuYRLT7S4@RP%H31F6nb*z^0T=B;n z9~R?B!)I(X-j0v=pxXQqItaVpJ46izpAXl|kzsCzOgy}6=^&%W?`i;}xM7QwesRV| z@r^A-@LQhRo8&JG6w7N<=WJFagRWN*)A5{r0<_drDeX9ejR6&yRz~)>FWLCgyESs% z*zbt36XqB6H#?ffTh)sjT-;Iy&EOM$m4WRbOs7AOczE^PWXDPyreg7je#2 zbA?0nDF#MImacX?&rDN|fvCtk92``=LldnWE)VY#yuGmoh0H<5C)0dDUpysQJf$m<9UGw&XPUw%Keq-b?MLQu$}Fms4@77d#dw$+yJo z@cOMx*H#*A*t*n!#ifK&coX>r+U8WNJ{90_;L#zj^;atJQfU~FMmAD|xxhM_e6zOS&`_~W87K=W>VOq+jQ2KL^PfzMQO+Q{93;l?eG_yAGAX|}5XH!Qf z_LKz;1JrUTF)Icqk43?AN_^23Mz1>gJKvtJJCAQyOlSjxv>zSuDmLTd5_y~>xyIfT zd3($!Cv_hm-_=yajePKEuO}%MU5Za2c2DFg&J0gDetN6xZTxk_$;V3R>+Azb9v)tF z#F2gl&hxTjIX^!m+-Zi|CR}~sw`bQeSyI1PZ<+}5OGXIu`(!rkw> zf>2^DE?E>F(W9Ei9`FjK7vs(uH?^s>pP)b&-iyZ2DNxDIL<#YN_AxS%{4b+7`%Z0H zCOJVG_$^WTkp-nM_!1cfd?zlBt$_|^R215_idVl>PsDwg6U<0yjem8!)RWAYDZW<< z!sWeQ+B4g_Mf>rD*PMGm>AJ1adxKd9-|O?L0gT%IEk{sNm-z5Lx9z#H4&tvQK&kd~ z#Y?On9mrwh2+A8N|DRg@3>+;+)~d4Hf53VHw;LsYU)x>=5${_!-qMIBgr#FCK_OH< zd?e3zOv*8r{o&xznu>~Rf01rA&atvD<)*=a>Q?rathI`CmX2n(E6PDm){@|SME@+I zdgu^mD9c~u-SrcX!RRR2LwLXO8|;b+0m~Dz(}3U?*1%ILy{+Dlfqw(cOSRdq=Mw+M^)`b&t`mkaO&qSKbzE`mTHD z>^;Lte{h2Lr>z&ro!O7~70cA3S{3ejGOot*6%A#e8gU@tI{_V?5+YB2q))GgQ1tU3 zA=F2up5NtrPbe8pz8|umQQ90-#Q2u&tCag?xw&#&{ci~$#ZW?Y3xB@Q@D|$#@@;44 z!qhTxXlodfHVZ$04=Yd&z6!ZQa_7;W?>H*)ZaWUdttU6j3up&)@M*o*zjQU(jsW7l z=D6-3wY0A%R(zlhl4i&}&dBj$&0&Dbt9!fDm-m=&5|gtPk6omMsIu#MXjGQLbUac^ zIHwkB$_C?_so}>K2k`7~FlVNgqv1B@ z+oP0@fw#H00JAI&$T51poAR+=eYOHZKj7l$!68dI;M`>8o!mR@EMos> zJa!tg9!?s4_veRZwnB|BxEnf;9Hq$;RVwg!S1mQ!*yinfD`Fh(G{~ar|8>^j@XCYw z>ulY>>O?lR9Nmq8?fKyypVIpiF*mHSr(`O{^_MPWX&=d)--&oc_)arfNXC9%VvDAC zIR|-;85Q4+X}c0S<;VUTXq7X9Ls7K>ifbNaHEU?&)G_m|{bi%CDADLaAK6OlUak+9 z1LFU;r4}K}H0y1+&x>E@(_VS75IQAkqm5e13)ydN>cYi-UlK0PFq@1D znmc*lJYKn9)zB$|o1ViK28}MSh&UgAR!tLt(iK6R*gKM^9))d?^3AH&8LP}@Qfrnr z%ioI&`rTU?5O6Msk(`ss+reye7_rl?tiTQV|Iq@x6p;_e#3u3HNsbMhww*L+ssA= zE+hwSv`c?Cou!bQCwEA#@aO=503g#+t+b(|HhYW^+NKnh%zu3rxpyK@u($M$UfR82 z;JcRNeaXcC^)%4}Yg0V;1+yb*e#yW|V;YB|?s*A4y(~Z0*aO0o6Ot5cgxFx8stMsP zkD|BqCb;+l_#sF*d}Dk8iN1I5oMJe>P|JX+ZQNz4J{s<2P^Ozm)%X&xm;|+I-oOLg zarMZv5TEjd)jz5i06Nn+F6a-M7a2;+26BWZTf9lPFjDS&H(T?_stNnwe(a+2*&+-F zxu;54IC=MYZ}2gt4xeJQ*1dh$9Ck!1#%6+&B{3f&`rN4Ml*M5#s~2i}N~Lv4#RJ>q zk?kKMp#xOGOinN<{hPhO!&@X#*--WCgxR(!Y5Mv6RoX|?9oq-=p|2IV+V#O?kQo1W zr?$d+rF~6G)sxRDNsw`UCj`X}@aYK;oi6W)J_NCbTR%w0J9 z8dD_pkEEA5I?6Sp%MVy}l{N_vR=ZHpcR76^yHe;lM4o%sq*qnx#SfjJHhE`$nOn5Aodpjl2*eJ_2EyGN z8M6GSc~P^PX4Rg8qRAR@Jy*>gbZ3v-EsS`=rmXz^kpLM9kBv{R1?N9U3D$p$f+LQ2 zT)ElgRo!>qF&3YSsT|VVvp&gz(GXL22QC&mrYm#M*4m4YgxY z=n3GN$IovcqkZy*ORIVXi10H4{~y-gDj=?)Sr^3#9^BpC-2wzjaF+lB0fM_b1Pcxc z?(XjH?(P~~2c5w=lYj5C@5{OOyxb>X)|$1N>aObQs;|CEhmBirDid`fc|Qx1k;a&` zFYSFE7nnUiZLc3zjx#!O9Dq@-N2Z4-haMvaCH^+pY$q1Qe?{) zg+=yhaqSXrH%e}!BS@(r_8uYNgC_CQWc;#Ikb)=12=Tm{E`aq0pBJhG=Sj`^g^$vJ z9p~Wml7Mf&dAWzV51n$2JVx5ifdG3b@91e}J4wIoM_RBD=G-pGc9NcE9V0AuJwG|p zm1_JAUXGMp-SQpTIQ%=8>{RYUo!);kzNR5Fmm8nYd^3%*AHGHPz&oq&9@jM*`>wP! zp|fEZqoD`bnfPt1c2IsRUYc(C*K{Q?%5A9+V1_FeeD2^ zF?PAunAEC^@fc>}CdTnhd4lXq&0b%CUS2C2TK?8ugu z#^B>Z+I@5^T?+%5CQ&gAXXk_on~$&3)~*7jq>cfxq;n#96+I5KUnBA|takN!*BedX zL}QFQ+sz{+j8#Mpe@o1WgW?n)mR{#{F&PAS&}C(F*>-w;q-lM&+yJVdS}@h}0>Agr z+1MHmwuaGB{e?s2KbXBwb#;hIQT9qJ0|RTb7;3wq%8UJbk%x%ucI&J>b_gKe9mhpj zBAGLnk1>ZxN35QAiW5XNrF|>Un;C&e$vxl(y-=Re2(Qd@d4tL;JF=kP$*=|Wmi#50Rz~Ib9 zQeg5g8}!@E5FpF1%iqegLd^w}RUCHJNlXRvt6dR=mP%%fD1x)=>wmk;kfUwRzkS%q z7t-tqR4C5(i&7}(b)5(S2+TFDzV)`K7i?Sr@}2=8r(4_XxB_nI8oiB_kDZ;MmAQP4 zRet)lH7lNB*w<@HRL9(B&2oyEKco{TTbO9o9|?CXV4Mu1O!;|Wfd;S-7A@_OOU^K* zvNDGPUW%-_e6ykvWG2RRpNn>Ek}}iwaZ`QgQ$p82rITbv3z+XLz_jRMkXw)qc+Uqu z+-ySc<=Z&fq;QCD@R#}*t@{z%WM{?e*>47d=ywhR zyQdkz=(>w$mfWB#}YVnTVk#1O@F*hwI*RW(uo|E=&gxFWD?Hnu9G?1BuB z(q#wBlE*2Q>s=(jtb^hiQS##pUdJC+^gIBfyWo>Bss02%KXFZAnfkh7C+D~#zaNii6i{@kxN80tX-0kEqQ{W;{J zbQTV&87HSvM4 zEGg+yly*Y@>YztAK^8&7>Kqr>u8B*hpv?4-svVCn2+r2dI}oj)48AL;cFwIs z7)=5FaitMqE6!8Anx<@F5}3Vl*e5pRGkDZL792jSw|v*2*2mh|y^w8h4$@@*e7U7G z4k~;yp&9S&Vi9inF>)Ecak6$7D}m}G=U9i0#-)m9sy5ebu=6$hQ_KrYk}Smd%!(W~ zb;Ut~=@*Ey*WLc4KiUnyfUA{@pT*H@PPQ)P48EtgblQe)fCk)G+D@ggF0d(-&571i zf>P3$e|R^ZH{Gj$SKgy-TJ(@r8WF0B(KPha(+JC&@fW+j5|VL%baq z)9(xHIn#!LC#!9{bv2fW`MQRs|{BP!#klDyqDbA%-15)h&lbVJxd( zuY6i?nHyqe-oZxe3sn(c>)(vwBY?nr-Ok6SdLK?oZM=@ytbKhupsUbimvik=UnBVt zqiGk&m4&={oQ|XxAk8D))^!>Hy&`E{wy|CQik~+yVEzV10w0d9VX52LQKzo2YW_+1* zKG%1&?q9HOR<7^OOvHt5Vf}8~pVa(b8~yJ!=53}-6shGer@F{M&;ZmM^I0FFSiXsm z5t_oJg!IhLZdmn25XQ2UT~44lIU(76bL))Pj!}Ie`n1~73$wK#_1K{2T&wpnx$pKKfi!f==)Gq@O_UH|y9I&*10A`4ORHXyJ`ui1hYdns z^au_*$b>ustzf)>ET{^7!P5!{I={aR4E-kc#l!?fy{|xpXc>6D6t6oj3fpZF*Xg=u zX~F^4K9~3^Db&1CHywXsm72kEsPp*-J856?lTaLIzbD8bL7&{OTJ0bhl213=;*^4v z#FsARQ>}_o+A93f1@QCh`a3*ZvK?7M)q8||$R8?a+By5S_kMo%jrvm6`#`)BB^c|z z?^2PE_y)}|%GxT|A!N1bf^WaSzv6Mn&?&#bh)KW!<|5GUC0RSYn{^_@-mdU5y?#d2 zcxv%$U9AAfpa%Ja@G5CbPm=(ZP#6-BUs*wlu_#FR! zH6(Sg1|-ehgKVIC$A?^N^_*Q2LV_6 ztuJ=gce6@|PjQZuRu3}>UgB__6DjBc{q+IcB-Lk5wQR5OHXP*Z#Ez^1jm^z-pft_k zb1m~qt_v-18H#yW;@jF|D0S=#PvwH!ZMCyl`ahz2MOh|7)E_SBQx$(QGHADru|vJu z2N58K8TnFp{jjB+oWz&7t!Wi&&;7`m2O&m=dc|ftBL8vZL+GhZO+6t2 z7C=?#FCa&TnI>>bLlW6j?>zQLo}N#5`AS0Dji>Ay1xu))kmOB&4`|f`TDqHRZ+a1n+5ujioXGcnwo`-@9p-6I!=;2Uj z@n}bGf8!0%OV1AuG3tE2A|V;Lee68ezWBw#QB=?skYVRNa;-~bkL^}69RZw=JsL+G zIc<28SzMm0X2*Or&$RFt4CUpp#q*FimQOV@y6eBAS!;*T4rIqQ7@jHRu%t@>e)taN zF-n$#^L@?4X(!{mwJ(_U5f;far3ZWY6`FhiueeA=Y8u0Xn5aq`hV+vA$}O_B z@1&uAOk*YD804dJlw2BR26vV0Gim?vsb5?g?@i;odY2`5cndPyI#Me(CsOTp_Q9DG zx0C%n`VWwTWD2Zk1oryXUDGinNKWupPqG!Awi_Fg7)1KdSxpxY0c+m@)jU7gVdemW z>@#1-%YoLy4_@ap>KZ3(XkVKFJla5zeJa;tvr$d?7}neRmNNa!qf+_;u;hAR0jc89 z;Ue8{1A{WNoGKn5UgdP466^{^QBb6fdEGgnZfH29#$P&$)bTR@w-am7n~uW{+*)yZ z?I}MQH}YmvfE_g(o_nmS+oY1yp7ex6l+fO=v&S!9?TZfuh*5zP_mtxV$;M*qrDhIR zo)m-nIYO79| zVQAOHPRWG(Fq3sG;Xhn8!wxYESP-+I>NmMZc#-Zs*Wf$a&>JA4d;ED0RNa;OaP*lv zMv;RQ5=i}91F96Z>@Gxl*VUpda*gfJv^@s9q;H*5`tS%8*xuPN_L%Fs;C0@ ztV2bENvQMrIgi>X6vaipj_;sCT%#@`YgzEbL=W|_?me~h)wz#4Z&r?k*U)rZb~~{K zw1_iz4VBRX=2Ka*2#UH6jBq~jjnvWhIvRg4Vp0;b*6dx_-nnow0miP74zam5;C%^3 zBv{xgbEZ|9XMe{SJ#yA{2m{;sN6hJx;|jOT!QLwlFnr5cT@{cElpXF5y=!k9IYk$5 zH@65?$$V=~F3Og@oY1~+y!#hM&HbUbB?4z(-n-0jeu^e`v_kVzo7}i<-z?(KMTfnEtwN}%g zhl|Fa>5TajxOa?AA?w$BV*&Yh=w``j8`^keNpTBJqZ|j^ux~l3E=$MKXQh-Kj z#DKq~m)rE^#cf@Pqd%~`;?}S@d1$3Yo>98R!jT|v#xL_p94rbSzxH|gY+;@GzSh@x z<6J^G5)`MaFdvQ_SJVR7#nUZ3ii&qnBwCu&i^4M2wXUOVmVnl?9mHPMP zm@S0?BNja_1r+A@;@jNjO{5xpJm`JwM7vIFNGG^O(J=1y#@SSrM(X?nZMUv{UaY05 zH9<&>{{lj^x9CCVH9{?(S}1k=m?U|1UlviMN>hFYUyKrot%xK0ljiL58%&`js?KcJ z{Yi3P>`S-4T9jeq^OT|A1q5BGkSk)WJSiLSw=A`EYHbN*N&9ufOr$xmoA3(e}^xaV=%e-!;HWtc}Wm{^6EK9ptoB_fcV|a9l*BA zF455=O3<5-{5<#MX$0q7X+)p==1!@92FYh|%8NMQ2tsz3pFQ^e4+HiBDis&%=^@U} z2R|YBm?xX)Dh!4lU47Vajw)*Zex@j2D4wMNvWTlVS~&Wi_&5r_Z&>W68LOs%ggYzR zZv^%1ZGut8uRZ(5fn?h(=Om%ouAdik^W!W0FmBFg>+YU4jw=Lz#O#@E;l#wiZ*)a(J-JWEXR`;c)m*F?~BRnY+GO@|k%6@KMG-dQ2 zV4J1afEBmK4YOdv3vz-P=KgX=*0rbgYq9O~Z;K%4*18#`IuQFb#2KJ(6=HHV#@4rK z7z&*nZOtC0WM;lOU^Sy#I&?7gMX#7C5fYMC&4IQg;(5Q_2v}yF;R*nc9c5P6(uH9k zFrQ2VEQ^v-uT&TLvD=aqhL(lz7v5N@Yss>WCC+o6WTIh1LE|E8sQ?>{hgXin{33TDN~sDK zy{fXJ6aL}9S^PDP0b3EMOkPEdo2=VYMJg;fLov4#B~efcdygxIDL1OC{Ci`nLul%* zx((GxBTut}r!k80>uoL0N`#enC$14g^0dkc z(-NV`x4(%$PLC|f%b(0gPBJNrD!faAn@#!rh6DyHemx5LKjQO{>hh@DT$Mh3DgRhPu&{kC~lNyA6`HAbpe>rmVH z_nq=AXg&MuH5!#_>gcZ>Ep(>yi&;Ddr@NUjWRt+;MvCS#^Wu6!GAy7-< zG4)j#e8YBB5L}&vRSY^LUhd^Z3#9fF$zFq)N^g@lrCb$;ByPQ(?n7{O;2BYEf#j1q zy(0N$vqy+J0}gTs)g(dnbkS?>?S~7GS6$|KAD%D%`5XstwnSdXA zSdw1bvFN*sTwlxjK1atQOaF~J_H=oB%eV@R?Fay4g5zEDYg1lTPePDGzKb#VO8$E< zyONR{lYtFZFwTwpQXj8%KfooX1X>evDeq%K=4SCB_Z2PaQg|uQ$Kz5+a-J0tztjae z1oG7a{9ecU*GOWd;)E;J=l07%<^;)HIpG9fDlA^03ImROV!rvB+Mjkg&k_fjf1|m1 z;8_p67rc_YS^hThR&pm9BFRafAO?984l;ehAA_F{q8u{`veWly4t|MOlc>B*84Zy4 zd^WQ&K$qRp#;C4B(1MG33M3TCw#_{Oi$>}Q{Tm0v9AY=34FCR|?(c6e@RG#@E%V`tlE~$px`%)?ZQKe%0%q1{SO|BjUlivQKbfJjN4cdJwxk5V@MPC(ba}g@J$`_zq=+T z$`sK3$}kOSiMXMBJlyW;59?X?8x+~Jt|6BpYOaBx#F|sgiTIT(mj(8;E~gag)HYt> zN0G&gKO$ab24qGYRYBnoC7xlBn{PaBLom3%{%HLK5ghTNq00Zp0!T-!h{F-fPjuJU zophNCZ?Z}`n8LWl{C#zl9Z-f;Rx)*}Uxeb;dWb3GIWOJ+ij~L}JhJH9^IR}`Vl3a=^%`c;~dq6HoKjoZbU#k2^6ZS1f z;C&9ahr*><$JG9bPx@5n_3nc+aHV%3`s|u_HLrp{_H#zI-G9w<$-L^I|@87zW_L}8| z-^}L_L4oC-;YO?6!vPW$J*AEeqCk}L1tKf(f5~dh!*7xB$$QWQHd5zzVIUDXZp1>} zVX1M;ji5}&BZ)9C`B**0a(|k?jEv*g;r~*O-B3tP&cC%IXa8^aaa*=wG&MUY`djxO z_4{WS{;mH1(~pASMr&)T7*D)hlK=Oc{`;FONC|%++tB~{LI3k~RTU+-|LdbZO9-z1 zo8te^r(wb$m=^zE-i9oV^Z(zVj1Ru!f5IGsxVK_;crShrZp>Tnm-^>a(nda-Va!a% zMnq!UKf&yYrZi4yes^ zydF?sJn z+zNYQ34@>^EQA|-ULb8HI_EVA^ApaAV>`CZ%v4e=(G_6lp*+Yrs+S@81Vd5s8&M9S zA;|IlCZb|AFxvBKfdf@(@Ac0rUU3F6a@G6yweA&_C=RIBJaDzs)Gmm{lKL&+jBd%eX2L4H_2L zk~opk6^B@rxghxTm!E};2D*!T4v=PX@RgFhbr3z+vC z5R@EA^*92BiAB=A@|x*NY;(^V34=b;5P^$Q>Yt>3>&Zko+jl~*4)UtUBo75>4YkfVkF>{sXcQ`^5 z=eeU;x0tSyxY~*v?J`P_lf=-Z?9PKfD@Z+xr3I>iZ@zy zK(uV$Q*g=qQ2X?8D2dS0Q6PfC^R<}M&A4~G#`t1jC_tQ9x8;krVLu1!xZN@}yB38wSxANT6l%L8hG z=TBb~G@71Ghht!dfpxbTwlV##5V z)Ftv{*pmw7l`r^^T1L~6=f?-vkreT<%UE^IRFXF}Yz;FBM}%|YAZ+d(aL-BwBO*qI z(Zy~5zKg3S&ybH!B9boIae8RXmkxK@ zOM%vvrvbI^keqdzx*-3$A#I1X$xa)UJ`b=0ln^}Ky)w{iLz3k zRO~nO#?D-#t>!JKisxSRuT|UTf>j9caUqr!Z((*pB66!re0%qR$X*Vq2(IFHcr4h$&2`I!N7 z-Fd-!IOKB|@2XgO^nhp@%HFnCKW@2^dg_4(kbRwD+mqu7=mvmduAgwuJ}!C@_152Z zelTB$a-I`>4U&pOE{=o%$W3*wp1!L1q4`RMo%XFPyI7QyW^V_9Ra`vdY@T5}Z>%9u z*?&vQa2pC=>!YG3XBQtDKp+52b`&yKdoPGNE%-7(Asu=vEbg}_Bv1(xkXjrQWR$^G zRT}8b+)r;m9dfZ7YYR0jvx7+L@m|b)>Red1IbKp-xYUJ3N}eAd^_B>_*^*hlDE<^} zkTn?yu4e3RE+iS31|$YoILalx=sD*6f)hF#7Jz2d&ORCZVZ}z{B!@oIDMzp0 zL<<7{7_^N&@A{XA$ioa}?qcuES)TVi(q3I$wTnOX;$OWrDnGq&{&GBEdiYG8a3t&Z zsKsHI6+GRz<2&P-`!(t1w;q5k;~a}HY;IL7e#}u=_c^)Z$w?XpINMUPK&7qRAR@7q zdu&^{*J-`882IP`WGEOJWvkrxg`krb|Jj%KJ_Lb6mYZRF=)G-a6&C|;-f4mHJ^0FM z=^1C!X<@tu@vjuLPs>yz-g1F{**`#%a>|cp5`9F{EDa#X7dU=(&krX*q6Z188HS%7 ze8NQc+PqqR@a_vE_8mXpAWnSp6ymzb561KKBxL(ZVPh) zJjDUNl5|7Tg?I*{xI%}cbr4b?IcwiOnYNYui;)EI=#;hDB)J)QxF1;F+!XG7OEPWU zkHH#bv27*&KAf{BSeiyn3|N8EuBJOBT1j?!08)E&A5Immv{wdn#q#y6;_93#bsVB8 zUOg*yK(d71oh~!hte6OisjjaFg|_pf>zni zr6nimGG{Fn10L$GlHD_8w{TJH)5Y7_RFrDtYWrrsn&nCC?4V*alX{sqGtUS>0&YUWsS(9PKQ5_Rg(*RYh<_~ zn}gKA#M?5k9%w^ZTH|oeke{L)kN8Wsj~?panEUXtu?{~hw_XLJHNhLUM}N3Va=ddl zrzvo!=icUnASC)*R$jmho>TO=rYPb%0)+9WPhW#I8lF94W3h%Qf!l}<3EG0IF24TG z1G}$BIKAJ_AXI`2-(NUxNMsKwfo8|pYO4)ULWf@<3*APC>gluIYCdd%zdC8Fh}2o)5_)(j4sGt%*)e%EsZcu=J9K&f}@jj zbVJ3vBriTQX}{{Wk6ul-w=doaXh#a+6GJhm70rKT<|%1FH(Xnid}w^uV02-35*WguS3ZhHNB)+mDM$c13^XM2G>oKJiG<&K>9N^w zoz@pxUP1DzwEqc(r}V#Dj+5r#PB$dUOMOdBkgH#<|v#lj^BXd0+6% zm}R=Znl)sf5$Ey^72uj5F=AfCiaxNTg`!O6SbJ0QPPcrpeYZ0XJ0{-%4?j|B`_cAG zE^AZWSeNmkR5Gh|4cL~8iH9g%e3pEMDHyGW)HDyVH}w(b{RPUd^Ft}4_wS%;nD-_o zJ~#(CDFhKO^^%iP<$PAa3A~WLs%H?ct_x{vApSsH>7?FXjtgn~CWUUp*f;%E^5@#O zvE1#97;uKa%!Z^}d$JxtzQUK5TTBSDe>4{CcX~{3ah8nGmArv7)jkcPlscz0)|1?6 z(hm_krHu0sTS-I;ZyKHo(0uV@<+0n&UwBIydg|0Ljfv&*EWu}k)M6-yZ3b8}0}%(^ z4!10$W*TEV)?@I%b?Tzk;yKD4mov7d&kGG&I*I62>cdN{2k=1+2#Gd zR8@P>@Sqpg`cftCxy^ytb?*;;25;rF5e&z+#QpjE{YSzvkD8p6XEuaSp`(;YtU3Iu zM<@(rfpJb0go>fB8z|00KArO{ub80!=(8`1SJQL8h{e?xTI$%!JVThsU{*NPXcGYe5jJ3v`eI=T9p1Z$BGvL#m`D4bVH=<@ZGZrSmVT6kQWW~vj@iG1cuneY)FkzCN0l(PeK4gGW5Kwz>F z1877#qi@h}J2H23K2eeKtd=xKU9?G?VTWAsMs+uaX=0SvKoJ*(?NMTdTb-G(d9;!|^B7im=ADk; zz2(gz+tNqr&K=U!_)>6akoIcRfx-FW(a;4ymzDbR{+0Ubl^W^YZcE3Fdm`7~nf&{v zWa4I!PUO`c(92u}I)$!d524(M9Vcof2{3+bXHY%W(f)g6>hH~G&c#pFSW$Yd>_6*oat`=a8b?|o5SC_#ElROg7|9`pGj^7 zg_V(xV?ibyQdhd605vlAIZGcGR#ODrWI>`!3waRI_qvZa%&K_#T^nQ76)}u=@>KH% zI_swrcfh9h_S#?&yxbpv8AOhtK*h1*Rc9!h$H5Ml! z8_M8x5=pLX)pL(^*rQ|$qC2Z}+cEuCid*ta$>zeEb#Rx^3;8!$xk{#~fBRsEy;rYO z)}0%BeOHps^KU+}-z{&6Q#XdDHYVs9gl->ax*Q4K5zlhPI06-{iY;zfP<$5yL5Ne7 zG=NKyU*M*umhN~V^e?{wk%8%8hDLEV-d8c*e>%rF-QdF_SGX50Kc}^Y@#|tF4a}br~L)jodk}tcfhEE1lXm%^hdQ-+F z-7p7N@FFKiRZjQ*4RD(f^i8@xk?}CkcQ8eOnlVLY9G3{disGp{n|+l}SRi`dC`^=ifwzkvf!gt6K=Y=9JRf zsG!UH+p$VDvT#36Q`##yYJ z@RqREa@(e#ieRg9 zYOk#UtE(F2Pa%6H91Gp5B|8}+%bdNbwi_t#X32nI#VR6Q9IC0i{9_k+HNuY6t}K6u za*h0;&v$gf^6`Ka`tP03-)hGbkokX2BiR=9bPpU94x15Kj==eK5am|4`{SG@0%`73 z{x+$l4BFJzg^~JN@uA|MHN%WovU8vxQ?#&7bQYOu4gy609+_gbeG$fqH87(H#O|*; z7JRmY+SceVT2>)SfB0H6b;A>?cWF~OD(K>ZW140Mbyb?sK0WR#Ep)&0mK1kG-&bw+ zwA4)47fjx-*r7F1DsRAzy(d$(3( z^v|o5ar6Ivpk3d*0ukd674BZA zrSJ@r@Oo1Qz1=e>Ebr3SkLYW$*qVer#rS6!=jUkIM))~?p7cAoRovw%)XaX9Lyt~I zRbb@_w@y*w$1)Snu`-M5m1g)Hu_;!#z29ZmhTrusUY?we558kXviq+KP>{vFRvLU9 zms%#o<2>RJ0Mr%S-4leZj&&Dgvxh(Wj)CxtPVYa+5$6ArJ!9H)*JvC6K3E4%fFj3r zs+r}~(0@s~hq4cNDy_5-@E3L3+n^J)J3xKWIH0CRD%8{&4b*=ve+Tg zv3foJA$o^loH)$o9|NK5L-nxNJT^W6BEIn7(NSo1Bztw4ex(_1aF+6iyS03A6#H`E zBbo5^b(WDBxM?RY)JbMbmi%;(*|Qy@NyE)G+d0)BT2nAxlBxHBq+ag*pqw-b`yA@i z>xD#)I>V7{sJ(8*t4ktB?-b&JJF5!&icw}ZlnUTf_P&r<)qVF{iN5_g_m|Zh-mvp; z-^ZNKZJIMATYhI6eE%)X9T*iOAjAg0mZheyFFDK#b^d;0 zbzC1%tm>EPDhpOI;akHqhmEWcEJJ;FN@+z2$Ow5uqI@1w0lDCRm~5H(ML zVy=4~kMQ#SG)!8ce6v=kCV zw`j?Z`A)44>Je&GC$c%=i$;|3fKYu3f9RXHweYn2r|r9{(I8_!&^mfhNbas+^u`Zj zH09ctuZ9uJc8_&)R#qZxNgKTtoy`N=pP1!fm-h3{dtVtgEqr1jwN)kf_NebByl-5^ zFNMTi+_2F-p;yQo4mRR8FbPJ2X~AAcWP3nmR+tG~1ytH}NV7#NhtFCsLiundx7*=O z57}XHt6b<8ZA3f4R7NgD2jbRJ*L3d?&I;|r?eC22XdZ?5iWtoyommsN2R~k50$z(g z+m}w(F_rs#i3VVfw2@(lgDpw_s3?1}g3|8@#vP_g21x~_B~AYBP^hG0dzVj;{l?{x{P@QC3Py|Ht~a+OYnx_(Pcns)KI!TG!l3Lf>C4!MbykcIn_VJ3 zk2@vY`cFZ>Z+*4+0+X4cbV`|eE$@~Z_bB?colKplJ2}&Tw2T~j^jcm7vFIYEAyxxc z_UO5J;5?aNipc(W z{Ou|Fb=vtaX1+f!#H5_Rg=<`}D=a?1e;Olz?CY9@7GiBs4cJy6rYZDFPXk)CwfNjz-s z@be-GiAXnz#RT*m?#>R)l|Fx(;jcQ^ngS>GcE5zxcif_HzXS;bf&1Ue-d4K&O0t`> z6flz+t_{7!j3tEI;RMP)T8!KQ=9l5l`#P1a^j>aTz>O0;oxKJJZ~#*6+E4Nl~eN z^R=9vL_ngK6M>kL?)?GBg+DdMy)A~R2bBfCSfdqMbU zu059E^H5-q)3Pt_8x7p@!h`?2hj5KfhN`_1T}XSuz=cj%i-=3u?931})RX(FXG1OK z+>Xntye2~=Yb|lC?J#an&CRIw5>f`X+qm}UzodV*zL=7^ETv)#WpT>~M2@}6m*NN0 zf7jivH{4oMYf?G1nPSq;J_!ZAT0TgXBd$r~CVg1~x#L2cYliu0U9OV8ea{AO5vnlMT@z5+C+%Hi^){>nR#6fAJ#7YjC764gRmp}vZ=Y1R&e)x zCPQw_E>a1+kp77bI3=+EJ{F*?z0n#Epv zZH*3AUb#e!OZERE0^sT%cANi7K08+S?)>4}ui0x>v*+ zF|jrjkk<1_KDX8|-m^=Mb2{Eod@Ks^`#JS57VZ1jMGy9Ne=6K(6m>yA=s0c}%w81} z^fk6>gegY&n@TzYkAAY*uDXSm!B<;hTeK^^c+zf=p$htI`5usRT=0a?)Y*4XI^xLCAX<6;1+3w76?;?qEQJZ8&m#V)wO{mG zup9>|NHOfw#n-Yld_PJI8a_O%AyZIuLmC;vtQ{pmZEu7W0YZ|~HKw`?j3$IE$Lfr;#{tC4Kcafj>b zhxSLjGt#7Mn2!jo(}&{Ld9q07w8Z>9di{0p{OHCo7rR}qqys^bnVFQ`C+5=FRFKp{ zbI;lXJ(GowMvNsfVSh-yiwa9z9_Cw#Wp-&8Xlbjf= zW$rG|2j!t_ahGK$>a*A0uKI4QO}-$@N@PFo+)o}^$k?|%5&>}SJL5lup-=30U}YZ( zaC60VkQVLxJLFBxLe0AC(~8;MSAuulPbqsKul5qb6nLhp)zPd-f^&`nTsY^Xxe;UW zZNz}|K}kO$h!ip@{m4Dxs42p(&iA*eWf6LgL)CINo{ITDI$h}XSjP(SD<$6&Bd*1c zPl;Z)l~EM8V27X|a}Rd!3!j$lK8t8;^E?PE!O}5t&s^WSe&F3&PWt|A_GDn=Hj(VJ z_*=*QT)`m`mi|7j;DNSXp+(J}-b1v=#gCoy{kNVt%-r8)4_`V|@Vh1T3|l4Kr5?P$ zZXE;hGKhSktKaA^Fjn`ljUyIrKy4oZSjmtUl_WYE(r9?h;K*UgZ()i#XeIvJ zcg~TIKOBT^fHa2yu4#yAnvs6sck9bz|yXz_RNVjylj$T z_SY!WQWddQT;k9i=T!F_KR*jTz3quF#oDS_C_&B!u1Vpdj_DCLozmasoV1|Nbc4{J z+>92*Qmb(_gRWlfQoel~gwY?J5_4=l^tdeHRLv5ALRCEb*35g@Pqm6Zm$Rhl9X<$3AGBet9r`s7;4v&Za ze97DQhfQm!oEPewdw8fW7Yqk0K~(oa%|l&rUC9?BJu9M@4r9TD_pRtQdg0ldGwQ&; zPpuuUve2exwQ8smd!721z0OGdzHZIoyO@&wtm+_#~(;F-sSYCSF+v@D}mcQuSJ zQ2?&-VB&kXyk(OzNC)g&NV=bTf3W&cvj}~53u$Ld^9@Wu0RJ`zPeOvI#PSnJ<6C3* z;(O539hJ#pH&Fd~Joy~Rc|JAuGQ!MoSGwBsl@i0FPbSK3&d;a$iVS;C=dLN5wH==+ z-k+Y+Z&U;lh*%~$&;HfCm6Z11<{%VWk=U$JQiRP!Sj7qwxbPtN>V(@ntx`v!99m>4 z=Zn#8bFjfKTFjxzs@9lrhQc5JUyOZqSXwelzf@DzV)Sfv86NirTE(4we5W%-e+GkmZ9*%&qE zbj^=%iI*~U1MH-yZRI8lPzO6^1PP^SH}ys4;Y%%E*6p87f=m6yr?aP$yjmM40nO@$ z2dF}LsHwC_P2eka7x?Inb?i7UU5#}3TfjI@Wpu7{mM7Wx{bexqmY1uzzX(=a^tWtB zj$+WmgSI*_yM%G?Td=KY(c~=yTuIxe$P829i zL*{f+P`0p%x}QJVXjJt#NZmw1y6K=YC;P=J)N50nnZ0}y#G}@v6Fds|SU|eBzI$`Z zTzS$AxMuy_JF;FmopYV_IQLd1#}K)|e?Id1{c$Zj%w3y3mU+DnO@^*_vOT{cjIYQ) z+O>`T#E&V3x5Jk8DRl15@0@)_yLeZpX4y^KSIiE$2Op83;3|_i)!@JjvVEt_{34GK z-h|Qv%14m-e4sk1F=>Me(F=;!AO-r5gJ_KE6_F4(9eEh~L;)Ei!q7Gi0QSvCNNcaZ zdWv5*gy}$l!PSz`i?}X0#@;<_nE`7t`+_cx^vmwK+XKGa*v!1=uE2Su`yT!N{IwNm zHn89USIr7%U=#z*=Zd%zy_JHw)#d@`DBNg+cesu;zRzJi)m5EZ_N7Bk?j&px!;8rviodmOE!6dVlqYVK#KP~gsdB!xta_C-J;i}a0MEtHJ9zA zQhcS6$H%WZNrC>4Deii5?4=&*l3yF{4}QZVJX-H0uD*nUlH}lT$ZC#;0J?yDOOxd< zABfSDE2mW1(aRkkOX}PVmmk|x1y#73uG<4pr0;a?=~HpY=@hz>97845wC`Qp1vK=!hnG#%dzL76s7G@%O4m7MZ=2a?aoOoZ*~ ztSjFjjR?}Q@cm;%&NaG8zEGiZ3Vx(b4P6x10o3ZX-hu@UnqK*TBX^ZoK@%h#(c#z> z4Ol;A-tqoelGPWjd(iVP@(PeY6~hh#eeFMaGe!RDxFt)x`#Ayb*N{^)@gKB~3W!VN z8oIO?6zBMiMjFrX<9di<(TJFB40<2e6{eIr`~7;*?dxDF$#-i^OY1}D zP+Ywlic!dEWV;lEa;$zDl6oLY=mZ}8A`#8cBB-R8l6-b9OapA;Uj;T5ZKT*@_CMS3 z>Gc&`oh(M3eV4537HK=&K~sksefxN=&RJ8hHpWU7k$@8zO*p3`AVvK?1G~%e1v|mE z-Cz(yPoyRFpjmkgu%BGuPb~RCs{%OsJEm*eUTCq|%^$m_FdE5vW_e>_CgY>V{te-f zPM;ipLk7_47B@RrK#SkC?>jNHY0@^i8;c*`ZnSsPh>@=E~=M$P)Z=QR)LWmq@w#iZ17bA3K_#Nc%J4-vFBM5{@YUl@CE!oJ-$ z-+~@cJwE!SF}n^DatZC$S!2V&RC!~bRwocPy_iLflK+T`V!Wuq;myPrZ1n|;leLBg z(8JH3{apT5P^sKkd^KZ#cMY>@0h8VqWg?Vuf5=Yvq7T#D8`X*mjm1~m9K-i!b~Gp& zv!M{{`3obTDN1p?@W4J}|7F)wy!oZhfV9^rdoAGe;FGJpH2 z_F!1J$hf#7fIB&Cz(*>k9993lLcW3t?yq^z% z1adwEMnCePlF&X%f0A}?wHTh=nu|iEQovW+PZ?cF@(s2@dpWGbky7E=sSiYrP4NG& z-i!%2F!(GTwMbBSKe+myDsAFuH@v19sk}s%Cq-|?tg%T zNQUz3NhUlFw$>yqb#OD)E}VO8$&AT;K3Q8EiIzI7j}g7S1*pATPnvbg89li%QMmr$ zz!D9MA;HrwVocVg-*4CJa=<^@62n*1=*hN732l4 z>ip>T(Rk+U_Wh}=_r=u?ywApOvNVA+dqF&?Kp!Np3hp{_53}qtny}^ctyx}iv5ACPs`t`BJIFJTV>RCod z+5ET*wIs~0y1!-rR%2cMA!S;mPu1%?(QbX(!9xqK##+ld5`TPa!B)|4I;0M*oxW|A zw+Jw5sNeM=&<1vX)BFhM@qN_xI(=~lZ}8wmLC-Wq67)V$ohysBr`lGCp^Q^v(F@W< zwwOgz2CQVkzxFwI*HT&s1)N{j>BGk?>h=z1i|8_50k$!p78uZ$9AdG`%O+iWf=3%jzA%&wW9n{Y|-B4WR>LbzLA_NqUOd=FB zpHDY#(?f~1+*76ED$Z$cOhX*jn8d{gJ-**hi=FvRVL+oLa+QAY%H+0?P9&cz_OOM=B`uVx2pIfL;= z@mlN}2%#UuK*o066^&CshT28g*ikDwzF+0WAOtPYcBpY&u-IFaw_rq5}3 z&xkX>Pd5C$p&iqRT0)JeJV|x@Wa#$|YHYehPvH0|^M&`vsw{RE)&m6%!qt}ZTRtr$ z?k587BhN#kkSDd>Sng1VPu@D$9HQNd9|U@5&3}lWes*avC&hSwkbLLn6=FY}_z+RWQi4E~Wb-uc6Xh(cyESVoDr+ZX>?(dh~ew@d#w)y6# z)rsNd&28c+>$KEU=RkwAut(BWhG62i{)xav);?+)|HKy-B8C}wr9`*b4<)lMNTVPK z`E8jlZCk7KU6ErQR9;hWup2|#rR6vx58uu<*mJ)d+qtmfA$lYpIgju+fU%a5)cZLK+vw2&|I}eMJ0X2A*0}Hk~S|~^3S7AEfg=db|=2dNL8FHI1 z_e}SHsW<=Z#k@F_Odg2{^*#wHf>wCt(RI)*22T}6E3oB=76Tg8dN_#OA!@)?EL<*P&uilp(Rp89Ij-n=C~bGPYudmx>g)SdLcnGhus=Cio3KBE< zOK|HMa39Z@eqoXdE};_{|V~ zEcl)?X%#+tYPYNl7kDJD-TqM-fcwe6$89USQbHX0C^w?Z)cvO^dTa-wzFMhYQ3~1z z(knzTLpBzC7;74ZW*RzXUP`W8+!KOy~cJGZ|_Vae$EPuisl~C*>bTFRzbKmJ?(Yt_oz?>WDC@Yv_CiVVAVk zdRgJHX9vFrzH*)nl%1Jd2!n@m5Li1GbqW8h!*N4L&e?q;GbBirt!j0L8sDFABI(OW zjpgXhpk0CEMLlr~$M1(BjyjrmT3xP9WmsxhscGx4=K8-=mCm#(FCebqR#kaQBBfEs~R zPaC?UU1rc)41W(!+6YIG6#EqR#a5NJMLNdQ1~0qc&2VR?z9A?Qvpc*}=+SW;dH;_h zd*6+%Tv$bmqUmUxEdQ{1SnvPEML)t}c`kF)=1_!B33Z&!a^8{Uo^f^ld=dit{u%Mm zY1-(>>f1#T(jxEfiTlq()g3 zMK8sDXXjQR&AO<^Bxv@-aJQq)wCUcb|G{wkgAls=Tjp3^<=7n}j$sx!9%kf@;!%;O z!tlAL$(?J7vpX#p8Kn^xm;SEO4Iz<0T1nRde3dXbUfVP7V%B~t2^YZDekEx9P(DFA zZb0j$n)1QGpRH2j8g)7TwlzqK4Kx!dLsjDN)f#GmS&B8Be)Vz|DbCfXst0xLd&0x= zcB*z8OcOg#6{~Y{v7u(RFK)EVS-faXCj-MvtS*Iu)XBW5C!BKd?AU&f%Bn}lZW+&u-Aj99e$ z{usr&)sE~F;7Ppm9MS1duJG*A1NQer0r|?!j!kuVA*#PX^4pJhNnBFG*-GYv2@ab> z@cYSxW#O*AB_2aPzFLwOZUa5FK$@~8za|Lg?j)9Sx|=3`BMlVL%SMz;SX`fB7*qUh z30ZWB3^oZw!ayyyksgC4KD@uVwLL~@KRlXj?mrsYB2#DtzNR^w zbE}oMc;0;%`yiQ?5Jpo&*YhN5L1_aXSN~0@h_ruZ^DzvwKOE$c!7I>oVjF#~)>~dr zvjzGYR}sDsjxm7^tLoXi{4S3Kg1_4|*RKnfTVQX1rDH@R9OlCh#Zyp_adH|m(p&}g zHJR2rUj+W*{;3b7WMUi%>wO7lJM;e7l*Rtd^G;_dp5VxQI);4)BvQDlgU;8(=0Jk+ zT0A6s@t449M3`{y{`2HehO=-*xKMrZo8Sc(|4+|PmcRG%efKx#>9jwn6u5t%IJubY z2kGV<&xz3he5F>9&&MKN^^(2T_S76`>AW3_&-X5JbmMV)uvrVD!P6$GWqjY9;tBbN z%lTS`!eu{`@odabhQVp&S@y6X-#SLb1eH|@+kZ8@2LRmeFr-}?kM6;ZlfMSc@K0><+JqPdWVKJ%|3UBQ?d~8dz$R?x$ zn)N+$H*q7R-1@TkT3nyF(ai-+J-o+SGFjvB3c&Bblv;*<%YjVb+pn?TRtPhnuWNr`(%0BpQvr@Rz zOQMeBhhHjRq`@!p2h!Mp$|kiymN~jW;z%o{DPHs8h^$# zopj2qUFR;|Jxq#$Zn!JgVe5_&u;%I4dcA-)6&6S{@)46VLu`Y!Dd*c|M7^xfrLM91 z7^b zokbgHEg2SV3rSFbADHKh`EfViP)f#*fT*XZynte&qY<*BI;Eh?t2HA#YK(W- zxQFrQ$4mM&)0mN2_)r^X!IvAA{W>Wx~vto%=&) zqjrT&d&GJUdT>l(J~>h1*R=xS^owVD=iiPE9Xff*hEtgTZ=JLAk7@U+6G-LNkG!hd zbL~0de6`lX+~ZaAREPEa>)X>ydZpodUF%&DV`(2dYSFt+Zh-|!knx{zG*%Nrh?L@Y zq`ry3VvPT#Z^cM`OIg(sBj-ahbv$;{1-ss{DT z8n|lb-;~moy)FvvwnZir2Wp@1pQ8e>k^Y;S?t~}ri7y4q+k%@l6-BYwG^{f-+*Zu* zevco4=AxBKq>4q>S{QniYaXn5qJjO?0>l+P3(l(5d(kcNdevvV4@XQ}L=Kk<;zjkA zdEk$W|k{qbgjY`vl8=9{$cW8r&L+tq}GdtLtt{ek0pV<28 zdUWDE@O=8)QA4}|&Ybn;#y938eBU@H6v-{SG=_s11(e1%X~C%eJuZ$(bR6!XU}v8W ztF{kpnv!^R8?WV(pRx^kj6_6a^^r^2rwZRy_F4m17O=AJSsd}0VS;-m1?Pq*PezsnkM zf~;jMqodYA;uScn3-Q$Zk;Xo@Z=bn=mY<7O42pbFw3}X zS}~)?CH#XK5pG>558(s@I0+gg3hL(n<^n`!eV3+^ z5obZkN9!TY6(5@U^wyYGJ<4M*ZbaxYP+11Z*7bbw!$A6S^O1o6fF$?Aa#xeEauJb$pFP4^z$` zusBfU-A` zTBRCr4SgQ14dRBE?hn>*d=2+9H$3%O-%LX!UUDt4-$aHmUxHROx+OTJU3yIpN*bKf|o#OV@ z;Ro4fB4Ke|WNPWi#fi)gJyd%Om7+a+c4>9V;`QC;6KPzbQD1cjSaiFJ3oB|}YMn4w zw3FqGXOcDD#mlCFwGb-9w6?DnGs%fGJJ+*S{L6u&6O-Mqsc$FjzI-b4 zEn(LU^9aYRH*G9JC8rB=f#F@#ioJ)vMQAb{+lvKDRB4J9zpiM0V#@k9q43KaRW*8H zZPbr7v4i_A?yL~~jW^;gGsmt$8BP8=X&B203Ue03baL9_^XP1drZRtq|5UWn+J(AD zPS=8(29lU6yTxdW3nOLsw-5D>uy}Zdq)MHnx9%<7(zDgb!3A9|v8Juck8ezw-b$}- zaS}G2aK;-HQWCZ3o-h`O45XZ2o455{un8=txzVP^Ec#GJd9WXB%Pwpo->*3G zlw2hOI>JG7qv!4J7K^AcOG0*Wf%-J4_^^78g~AZeBdtakc6kc4iwa_`q%B{XBK2WnxQSw_!R8!?$W|Ix?vtucYe zxHhB;K;F4VbLnKm%hN$3X9E#X9255l0h8t*;1)?PufNk#L9UbEr(=reKwkq--fWUT zihkNZtRLr5x2>OqmTvSxOWtoxw~lj;)#xkFPY&P-NnKtg4RpA?+Vi<4-RH^tA3H@z zhPCB^{m#~#4;jP4VeM8#XgIK@_ldT}8-^xuD~2)e*LRa*ei2G~830)X%a=9p2m;pjoU7*r755|3auAK2 z_hBPf0J7JSeivzBFM!pZID&|81fF$=)x0 zn?Jcm?Jp&7d;sXIq_@k^!${aZsv+CcZn@6Bh<~ePXFfb&em2EmHC!I>FnyJ#z;CqOViiw93rN^G+SoCMM0B{`}R%9M{0s?3lNll#{jJ_Eyk{+bjFl%Zk27 zKZ4hMwX(iT79;a7IJjVJnu1B<@FhNGg;m5t%iGcNa@1J7dvAQ-Hs)o_!spFgRJv~o zy?>nk)Lz@;dU_~PEdaZDmLq$gCB$*)o#R_OGjliJIeBV6Lu!MehxC!MX1=6F&y$ap zm!cA{-IUIgD)e|aI@!Sp8#Zxq(<#l>(Ybd_waJ!l_QB9hWQJ% z)D8J~-nl|(8*y-TXiLx35 zQ$4HD>(hB91nsdtBUPBi=E@>_=FoQLvOat!x2B`ic!c z!Z0+>LNZyKoFTbN+L=VLRyXn9lKrK03x}W=Z)BQN41onk{>DGLc~eb^i=JX^;LFo` z9yW{%5}2~wH&T?X1$fBN4T2w@Ee{(Qk0f-pImyuaj zRqcfa{aHepX*&vfk#tiPTAZct)-n<2F1*FyNVZQ%m5qKvO_H9t{&}mQtY|k?&Z=Lv zAWG4_daY&f>;+dMyxu$8kfg`GFwk>V5@4#gFX%@X+Hsw?&nH_&^i11-rK|nMyW2!l z^SI?L+e3V+TEiF}ciy6V6Zqp?xmyXGeD&D7MxQ0ovS}IHpn}$}DffvAl)v0!>()}x z8Yo1E1{6bOd#tK`_3~zn_T4uJGxf#&&?7PURvrF3IfGf(QWmrvEp3zz6L!skl+NqP zk0;)iJw`7#ZHGK~>^}ly$S+ydoPa(*l}!UEzO0qsF23+;HTZ#Ot&bG!;oMe6=d5Z0Sm8e_%j37A$eVM;czm` z3QvvpU6rhOJq}VY@j~QIS1c@PW~x_HW^{=N!yT%OxtTz3Rl4QIr~0+s;Hun@ zs*X`-uYitIW^u5dGm;z;bp@yy5t1HPMdK+B1v=aYNW$45tK5RK>CZ6$Wt>swj#XVW zW|{t&R6Yd_09sEnsE(hw8+A z&xbHE_>z5)`qBKO3*H5S2Tt$RfR&M^@b(nNX-H+~C`!J>BB}&CPPg!82s|puE2~2O znR^4Za;2&(a@BnLXVv_QTs1Q`iIA)2zhIr%^ooKA7{lI0@U0TmS^A`5`=D*~O@rPa z@3sEa%Gq3qD>xT0=k}si$(SU7*RkFs@+BTD2B8Yhkv*0rA;>B*Xn5S98&lZt_&#od ztCOw%U;4Oko%91vuEZn=qA#jjOy5z+GlX2rZ5-@^Ot0Afk^p-Xh6VEx@M1>$4o9Ql-gtFd{(_7nWE32v1fiDX8Dm61Hl z#3&Gd4_oKjaMf^ajd(KVDUq@5&qGBvZQPetJR?Ja?jEKSrf_^&_f6lsmR4D@KAZS8S|CXt8}Axt-oz zTbA-cM{px@GTxH9gD=z70SAqy0p@K+2SKOX;Qab0Bro$C*6WagqOx6SW)|x^gqxnU ziqx?MK0l1*Ty@{N!r1BM%}dwoy)Pcs3^a2O)L~<{gU9?%JuYiBX!_nc5HnNYg+tD7 zk?-gk3S{Jl`b`bgbCOeSOBbh;#LPD_>#-uw<53P6yW1QN5^Bl4&1mk8RXiPn;n1>Z z=-wdVT0*yFyHvfsNof2KUJ0@=v9-mPfoCg{_5J9%9~GyGUK|PZcW|4U^F{6J4406m zxq{e9N zYH&Tf;CZ*yOd=}#R>M?{{O#<(J`NNu|Kz(Axfo|qJIgHAmbo2a(7?}otb2;CQ7J9V z1L3_<1hfZ@6@!Xc%E$t>zegBJtr=pPe%XjDv-{%)e*m(?`|By0G%q>3T3vqxW>lEV1ZH$sp=&&<&=n^gQWLkWLE7h#jGY!I5NM>`+rs{?8P2aQ+%=nJz zFrJvPss9RvKeU*wIUED5FJjmKu%0@JN3N{8tfk_@Z(0WL-m{EAJ5^ZEl2zgTJhF%(}aBJ&pX3O=qBD5DSq6bcjWmNyo7OaBcijVm<|6@7>u$$ z$YllnKxB9btS4`LlA;hQ=e1uC8cqIm4t_uNd|t(W8?=??D3 z8{hJf`x%up+zS|JW6iVU&>tdWG8s?31X8G`;G)8M<)SvCo@iBx9ur*2aX;^`KvGA8 zZzpi!UqC`=R!4X6S~HWe%(t(Z)_f|);i}>rGvgvMnfbN~`ux>e$^>6H!HPhJUWjao zt89fpjRf|bS`2`v1oJuC#%=w@mbRHmXYPW|g%RgH%mCxVJM06p5@#!e%!_;pz?=^< zU|}#svVsyWP0x&VS5$rib@yvpxc7W|QlNa5>d)BK5scfA29^Uzjqf-tzHs zV3v~&uN26tAHgsIz4jELh}qxSes0#=o<38XpVb0msgIDR<(nlwR+c#moFPrM7Kn0g4(qbsl3Uop{zpl0+j$Tkmja&J#)ZFQy zZlTwAU#jivox5L$C$l4KO!`^Pt`r6w{#Xs9?@eC?C-2_5AXgi_0j`Klk>~>zPA#cz zd*xuxk4AZl1Kg)wtVZY}%9k>p>XPuyyc9v(Xp>ZTgb|#KCS}#h#9U#Ioxt+44K$4n zXs5#T1=Sdux{w5q_kU);)s%D74BLHDol|)F$85PA1c+Bq`B}~W`ZrBGm^+4(70&B3 zz>OY&*otP&>b4fV6>xd6Ar0YcqlRx(Rl4D?8|dR!n7^rlD@hz7;N-XF>@sZ!U-|ca z3W&*R&@e0m;ss67r~#zNy|HdK)F1MX^fT&h(Pzf-xp48CxzHg{QW!)EbssxDt4mM1 z;H%ShcJmkwBr4YCXgK#NA6C_SZ=Lj1g!6;TiPEv^=Rj%9E9S|^Ng0R6MGsVv4^Bft zcVq4jjfiGOrP0%UMd^X3qrw|No!Z9dOr+yPMGxUa;`^XIOr9q!V%FP!_g3eZ(YGmK zJiWmW;-@)BCql&blfbP~BprE$8aCgrNGe&WIDhl8vBZ?=XMSDk|IUiF13vNoqA^Mg3akLg6 zP3tBk)F#*Mqq%v`fm*@QVk@@!8@eBk3!j<|oJ(IX=g$vFfY|?W`!hB{1k8MkJ{3fV zluaS$@Et&r8D0wS=8$0_DcS` zSaJfql4&YJ?Zr=w`1zyC&z5;q;EA&LClIalTcc--rHPYB_#w^fV_OdUm!IrC;7)N(yxPnh+*|9*^jJ z@2((@x*`xQt)KM2d#4IZysKwcJ_8J#>>ANFEQ0C{lfXT!jcu_UYJ)XX={xl2 zg1E$mHx)tqMpBqK@B$hy@zrgpk{}q#^VJ?kNw%v6VTxEgqMZ)wlvwMJom%-J<7Q3m zpw;+)Su*D-S_XT~j{l*HaWPy;gw(HbQOT zM4CS~t=WK49WjTp)R=@ANz1~WZz6>qW?+bQBR9@bPqdb(drO8gVEs@0t$UagZf!`)BfX6` z?)SN~JxTkyR$3~3kPL48we=gYK%_@5*DUwm;FqQyb=e!wTh1oIBPFzq<1EYOHLKE@^f?n9}u@$80GRMIjlH!)>bvWG_4zzh$1NY8nhcA!Uis2Hd3 zu`kTK@!*fZAq}_)?t#FpF|-LXz@E~lIaKoa>uBS|4{*F{4;W0X<Ews& z9uDN&#h+A6|Hi+_yG8#Jc))nv{F~wa05w};WQpw&VB97n^bLd~D&PCH#eKX1i%Hm( zkKh}wtk-4thTaI~VlYlzVg)5e#`Cbq=wmHdzf>c|SL)Ce-{j3(%v9}bSHvt^iE95J zBeO_*c7$r~>5b|(t*31Gv(5UB08l;0l0Dz>2+?F4t$|v~_B#e&immBR{j4pj z*O?ET+UN|Cb6?ZpK)&=rzJOAq)loO|a?$WwVPrNV8E3=t2@=d8$l^#y zJTq?yX=aPAGfy*q#a?n5d++^P32xPK1r?jFa|Gf{?G{- z28xx_=fTOt6888Ozm8u|(_W8Q26QD?X#!2-t_`*~h>qKTekaT1MRMjY)A(3t9&xvL z3nY5rrABk(>S{lx)_YRah2+!$Do4Go#VG!d1vs9t?4U~o;HWa>G5R)c%Dq68l8E0H z1W@fRm+>1mXBM+B9~tPLS60Py%<~5hXTZC^2OJ!ueokAp6~U)AZRS+*W4Qc1wkumU zQ{_tDkVCsT`Re(g6y|bjI{G37AoJj*X<}2xnR}E`pVwa1(Kv1^vdX!jFjTTOyCqS`2e6>?uo)(E^U+EFoZ7=R7bGj!4*{B*KpO?BaCZDi%M&a zD=t+(pmX=zuEV3+EDavr7s9#pa-g1Sg(yJ;pwz>5+$vQB-8&vRC&ja=>f-;Ix%-hE z!rEk4-cO34IPf6#F+4=0tTqK|)G*vP4}^m<=ak3ywu7=Vabg}kFfXQQD^x=<+ubTf z-CfdqZ^BtJuQ!VO1M>KdH8#zWM9b9_y=T*m^sI|M?|VKGWh9NPmUW*Uu|FM#7xeZO zY}JC7eT_Hj7rI9zt3|MB2U|z`1UAsREdnwXv%QFC_#;ns@N%3YekPG+B>U)XaZVy# zga2(j{Fi?#c?ROb*y)m`EGpij0VD+8wg$FdP+IkvyD4X%f2$umOUpxEimQpmS3UdW zSJ{j+6n{~G6DP(8qvsP@6yK#&pN@H)7JgqOsCqz-OBJG^Av0|nzHx=j3+r8&ZhKXq zPM+czu^i7%>3f7HK_r8l&lWo&BRm+x96`b=U)A63KU~=*YO!t%97xQqr3r?VTLY#Y z<%buqS#bfwu$Y&-*e%=eQT=U*7hf}L;xn%DLmG6j$J3}7-Dw?%EfA8q*^Bg1HV|R6 zMfGb#Pzy#7iD*A7!j#JW!y^6%tw%?ME75Sk$g#-rM`21@n<~46foM=M!SPvDT8}sQMY3Um!|6c zt4Ln=Ka5k+e;B6$fixZ4&6hOSkSf$go41k;K7a;)I?AkZ)2UPaI@6I1fz~Fa6@%>< z=hU>0k*M1aKXR{fY`KXped*; zER$EQcGP`|3T}a~HiZgrbktvW=9!S?-&Np5zT)G86j!{U$_ z&p5A%x9X&{=@)~@GW!&lXAh636OrLn7Vky4N9CI7i`EUTznpf_|&#&QlaXXEk=RYOLS6t7f$4V=&a=VQtkk8v7Uetu1_9e&W{vhJm&n%q{gDV zfuAez@bVoH%$!-V3v@KM8Q2GS^}Bz35JG#P{OY=Qr0^ynV5`evxu#W4ef*HP8komw zi?W=C9#RkxM1<(u*2mCzFyZBgwLAWfVs5b{+%i%!Q3>Vt-C3xL(&pGR!`61xjWnZf% ze2T?JpwiI`@A<|ntsXO97}J|%o10x$nmYGveFfte0M_)olms6Nr^micF~~xMOFR$L&MXr=Q+);gr9}# z&&}?Y=A#pyeENX@=YHTv6a8CYzZK(ua{&@)Sn+yJH{=mX`$ut_p^<#yvbLwAZ!_?e zuhp9@1vi&sCe2MaWM3l6XM`~$r!2F}Sco9=p94lh)7vPB>C&A9qg_N2eNwkLNxsX# z8`gr7tnRaBgn2K^hh#nUDEq}&HJWD^*M0s$|GpIsNxw13w!N8KCouXx3pXEyIkZ6Iwho>ah~IP1IoU{XL}We9@*5m^`-|O4G9#PXE(IW7vi*c=_seC}XnEvu^_;7O&-8 zN!F(4+Z5f+md^mP13$+ulgwLBBF;h0bDx`OimQTIHDX85&V@F!&o;YS*-6?R3)I~b zl55s-*NyI36A+FV$#T(+ZbsYA}6TB2Oi>1 zH}fFhGe`&>X4aF|5L1uGn6Lmuc}e?8or@;|lvRxSrrntjM8W{l;4T**oUs`7gx^l3&y3$k#{%6wO=pqP|NSAz+%Uw_-uP#nN7L)q8yLsnMw>`j^q$5 zbHc{1T^>rQ$(Zri$Oy((KAnL7i0U5!{So4P=jjV%pZOgG1Cq!`MJ@2}-kF*@W{(8{ zSvxNuMl#zpmiv%9ZCW0c(vimL^|cDhqv)pS&`HoRwjPO(U9TnU0fm$Z|34m1-oGEt zJ@Oqnp+7INvP~b8f5q@F3>f~izJ8{{RKM9Ys*Z_fV`_0E%xr@CtcDf3=m9BXEkR`Mb3SI(C8|z*WW1@5Qj>kz`S6sq|d?qwT|;j=c)# z=V`+mk81p=FMl0ONLq*pjek2|!y%Cl6>Zb*Zp6uOciDA28RS#u;UW_a#ot}^bsw0l zC1%E9R7_)MO=D(_ka_za#FaSpOarqz85#eQ$+KC~#3XHh$yrRkLN+P8#Tp|22Uvua z?VfbPFC1*LTQc<0l9KMXYLXEvD{)M8On>*-RZ{t!cc0IJjH*z@(RSv%Zu4P<*S}|Z z86f31UYoO|^NvTRr>&fc=06Cguk*l!Xu`D!f7B!DmA|9^DPG85Quva;%G88T2?5V zM>QbW<$*We_wSZ+Ohl}+qVL`se8%RLU_C!W!@uYE!j%2HVfiwXcqmWPsSKC0{$s%Q z;ci<3)L*RcKg=b$YGi?|Y)Oo|?88*ufzoQ+-_tNoU!-rC;nmo~!l-&$GaAF+4{Vx? zjk65lU5#(T)8DJqgT+dV_DVxt_gz4OnkZhL>DtUsAJBiCPSk8%gV;XGNcA{lUeVqB ze75LMD)sT^k-837N8o4dZ1m*%H1e!gGAVynL$8}CCOU?{Wjs4Ms!noAULT>-I_{64 zDsNns_q`nlbwLe%h@`Uck)NHNotY(X`q|L`aQ|5EzwV=bEm0M{@bp~`DRJ)PAVHq7 zNWpu1cU$G}FMfM>SLF}Vuf~u2dlnFOD!SvP`wdex+-2&^!aC||XF31ViW$o)be|$DGBNrbX{P(TQcPqL(i%q~B zuNy1rc@-68{+?6F62T^sTEY7Et+UTy9(H!s)v^CDSJIGk<M*eG;>vp@bnP4{&c z)oNFINp8t=#~200|2W~&NLlUxni(eFWIf=8QjzC4e(?r6I#*nDe~XD=h*Y&YVr4w5 zku)_m_1N2TG{3wxPN4!1?qK&3X9RdRvQ9(&_i2qbE3ENeLUe;8CMU>7v3vpHvqcjAbi6LGV%JO zwwS|*M^g_zrvGuqe8?9p?zxHgds_VCM**q=jT^d>QaGQaWDsN#Y`0W}>Em(q<}&B+ z;l`Qa;%XVkI5Rh~&B4S*7pLO(JLvy<(78+}Om~34hxsV@vP$i{8iPvy!jN>q47dYcGr8QaoY2=j|`{y%|F-t zZ)d09_c~SmUzhuDetTQl$aQ0hZ*|t39PRO^Ll%g9%W}|uQ%C$`Iq$n z+X!&b*sBwK_oxjh)$%GZQ`2mYMdnTngtvl^Ww-O>o>e(pAZF*Qj&;5&*L~D+#Gh_) zpY?zh9WnfTyScox(UHm6RAeiDi98`+ZtjO1KmR(l*iGz6bR6RW0=5!rQc~O(2B4Pu za86VISJ$sYqLHG7yeO@bqQ2k$c#Ms{{M>*E1ZM`P*><^vA*g-5q&lxr97bnxG1FG^ z_+3Ek*Ld%xJTYKBW077Pny-&B=d(*NpL|<6V_Zj^wR$WFhMB!P&7%;W6V60goV%gi zP%&RJ2>S59*m?`ExB_2mlp=-VPVoXQF2x;+Q;NG&+;wm-HaNxI-J!TUgF6iF?rwv; zx%XRlz4zVU`v+#u$~oCdc6O4>v0xT#Jj}piAkEoYWdc`1O^dVOh4;;Z+giQvryGo& z;hT2}T?Y~vrp(G!$ky3u)$%K8)9LPxNv&F#Nj>Gk)Nr7;>t|p+1ZNauSiR1P?eenT z2SH6!@tL$q@_&DO(jgN+>HeXhqJH`M^|OHixqyH`jW%9uYpaEwU2bhHR>Z)w9=B3n zUysh<;($3I49TePD`%R7ebWBu3EHRm$WqiidW!4f#M|&u<7%*-s?6 zRh#UN4hmtI>z(fg88YXk45(eYp#JYNW`jTC$eY_l^tiX$tiqmeL$|_xNP*YiNzeAnci6#Q1pGswhNV=wWJ9b z*?D6N=^@S!XGPT6IP;pX*1X)EcllW0i)MNJ7FJ_vq-f9vyT86QhMb<9>RfVdxf4x8 zC8t=~MchvfsO=%kzH1da&3Bn6Xx29vA2b@5$>ZaT;)pY)QvBfcsaew6hig0MxfW81GPTUYyx0 zXmF9{ws*o0l*$6ksl1}kSt}}O7&hE=q9T#aM-o02n12Nf7asiPvtv*xmjBTsYASK( zwkrDn`Q-nPw-E}^Bn~lu|L(uLEB^B0?GpVFlaNrpdZ2fD#Hy^UObJ(_IK$+7iv8H1 zVXWxLa91b4He-`S>SyblIG1afLkX||z?jt_mKCZ`K`V{PPdInIM4s9QN&N2gL2Ze- z;M`?P{IzY->P9IZY#BYThv4F8_3eBi3cfm#m?dudr?xnsc{H!VkeAuc#)p(FfpmWS zb=%4JR+F0?3D<+j7XJup1H0tK2DhfV)1_c4yNlXJZKHrZ&L>{h7G0q|8U3~U>(Jxu zB!NKk$@bu}p)udlGscYx27Y}LucZZ%d19Q;`NI)t;j?r{X*VDPSv%EEJz?Eh<#Azd zA&@JPUqMnnVeOYBfmo(k+(p*K zO&t{zWuU}Tgx23qaZK|+ju)tnC#W_LhHuaz(J?8Y+WSZ#L%|Tbv5gA{HWuFCq_3-B zab_c?8;0BX)rNorB21g>`Ch7D`_KYYTjv?I%>RNx?BTz>mg26gtkYkq2lJm}+dpEs zxnbk%AR(g{l+*-eWo6kH|JmSXp7ak@l=Ad?3N7b2tCUJj`)YP>JIAuR`cXuL$IIzo z-FJM+(jhx(ACgMddXY5YR%2mdd{oS(RPs#p(SOe@yQDw%>WVkrwvYuB8d(!wzBGHB zpSid4bD?$d{)?Xn+UPU*2y_Jh(_5$#0jJ}oGL3a^8%t1GnUixesfi;>exM$&bC&77 z#R@xRPID*Z9`Cg6Hs|Q>?;n zBD}wS&f^s0dp9W-)^VZc=8M^2_DLz}9`ZdwxkuZ*M{vW!`8-}n?AM&tE?@9pwhx5b ze!B1BYRPe6uAGN+$61+bMmLG|IP=3t^9ReVSCmLdeo3Rl;(>4W_g-}=Vx?)U_R9-U zSVT<20bRJ!gVDiQP?)j%el}DF>DM)Z9K}viex*3v?=f$|_an3BSqm3Tq!_T0PcXvS!`bk_(!`2ts0CPwCSo@ zi2os$KIWKE=y{(4>uQDnR^GERn~}t1-b70N25tAgB4DTj_Jm77iPHC!AsK==a&MJU=S?eVfMhPi7vi zs>b}~ayj}%lX`h#NXSRr^1k2rELo7sCYApT6eA@MCIp{9OMACd>4wjjDJm)bl#^pp zFIQ9J^50GP`r>W7{ZZI}Tv<7emY)8JE8Tl$HkBMUltNG7p8K=1+e8b)(J=bp@mci4 zxo7eorH01x+xrWW8Gt^3tbW!=T1Or?@NCE8n~g0V%oan;Zy^Q*hwGtv!+AmTnv{1g z9BLXQkD_~g_k5)AG>T<{y=9wAG-uot{0MQjlhS#eoES2EXb)L*CBZ+n+FqBiFV5K zFY!5=@1+B7C~Aa;mjf?;7%hIdQR_XqnvCR@^W6O%Kdv|a%ITpfXMgJNaxzg?baHX= zUky!ezK+~1q>um9{E^;~e49?OdhGBJ_}cgvwL8N`ikt$xMN_hUkv|Ci>1_eac4Uo9 zoG9obO44nFKwlqXU@Fveh98cWSm_+;skv9u@@aE&ejn9tZqdE*8m#_~bg->)-I!k+ zXf>Md+gP1@3V_j4`Ym=vH0LLQyO6oMz8q=twULiV%YDQKav`*EkXOG6`4e_^^bzuaM+h_43}H zK!p1G`oko9OUr@wcbKK6RCxGDIB4l4X=|G~3izrWek0215r!Cv0zUGnu{6O;Xd;^Z zi!&4o;jvP*1*)O?onmBW!~SB+aKe>6kr{6B%~Y&%lRy9p3*i8#W&_u6e+VG&kt9W; zSEc(>IsQSvGB@^uQYJFD=i8;%Cg3GO9tBt99gyYqJ;@qxr24%=wHj)n{+cfDY3tyi z9QF((`g|*?sd_eHG;(OWtQ5?~ZcAo==9}mv1*9fpEN389hp6QLNr2&4QMr)yJ`$b$2tr`N+}?fq4pr*UT{?%K_^{-_9e8HyV3)f8xr6C@8lahYfq`6+(Y#iZ*Sk5icIWz% z=WWkUR(38_!gZhAln)zuw-c%$?0R~^O(BJ272;AbSg{`VSr*7Uxhp_aP9>1>D&Y=t z7pWnjBTw9JtIG;e*(pi;{2}bE(Kw5mXGUa*0I$D_C(jnbx%8bK`$aIPEIuXX*C#!n zIp21G4efvmB?-+cr@o5RRmSHOtiqLr+sX#_GeGF&*n2X%aqpKIf)~Nue1c;>L${9a zc7Z+E7eMN=D+*8pdUm?(#fxU>^&fQxLir0v#rXgkV#uNBTSC!G;tMQIw$Cm1_zbcvyklyr|uWUzaPow~A8L zup6X)ir7~2Qa(ky#KkYi;U%}0SIDt5;}D04*3fX=b-#UN6JqWIz~pW;b;zS8$KEQ9 zI~@FFaJpt|Ii0ytthqiezi>M2KD_3^Cr{`O#$l-|#@l=vSFjv;at{R*uN+^RxJj-r z1wDp9bHd5>GC>MPqUPQm)CKiA$~vvTj^Tfssy(^geB9fLPNxT{UM|wXEoRSA z0m*soDXalQ=VLE*tfbr~2#-@oZ+A-?&GzunpGzr!xLT-sM{hOw{!%N<{!UUXWlO+- zQBgzQ=6wAgOOzCyolGv3UaqN8leQ++HC+jkZUY;ukB|%wD12QN&VZ@@q1~oK%ctJm z+RLfRk@(tVW-K=!17j+wB$0dk4!2DjPPmxi?G1)+J(6Y6bMtukrH!v1K86~>Z)bbQ` z9Km0*zc8w!M3JH;a3|E3y1)9rsv6IEJDb%2ETmmRzW&9}5~*?f4h4UBcZ8a%O9u1> zGRzS|UZA8lcr0P5ACYGJY%40c7^5s(A*Y-W*iC#U& z_C9;zYtE~lu#gonwD6c-TIs>DCO5O4COTfR$@*vhb#eyjgI=Xh-~dvaLbNo&j6@)= zA#tswf?Sros|lG%=O6fI_^k`VZhN7p!cpsqpVO1`Qgyx#(CwG&Hyy8e9VT zs*8(($7Mv@JGNcj80hG|={m;TZMgGj>BF1A~~OzW3+}->?gjR zZL?gh^FMws-zPWki*x^sgZ^j{oi4;se0>X_MrKeV=t0Sm6)UlW@NHM$8plRc1&-&j zOTy?-F2~A}TJ7SL=0RWQuzQ<#ABr{@pJ8c69qY3Rm~eksCc}f!_5OK61R| z7>;Nchps`!9WHNr?jDO|U6Z!nX=ps+u1~c)L1;ImcskB2SMf_tj*@R4j~>?9cre0g zuB7DW9?4Q&&++@3@~UKZcH52KTeYx8fkqyOW1ydCzwn|n<643uXkN)5yxkEIt?p4k zbGc$4+B;DZX#W#cG>SJ$)IzC zt5M%zY$`%8^Qx>X-Ec zoU``0*V|&-r`hqMD$P3y21{qnZN=#r4;@mH?$j8J(5q*;VZANICQSQzR~ilvpe7{_ z|Ib!mjiEy=Lz%@qqSI=e8gY*5<2Y{B7@}v(ROsTA)OgDxBUoJ9_;|LGm@agw*(2|Ln1+R6W{K zTCUi&iaA~Z=a9~(GQgmIHvv%nx^40t?h7+dwA7?$+9D=v0YuAqVrN{h`s%i|>u7-; z8VEELx)0Mccni{H%c)*6S;qQ+*T3Bq_f1J@1n=ICv7KP zX24-oa)N^DSUaO5LFFI*%4h<&`l5tu@j+%!?+(aH$Lfr-?eQMldyP)>;ZBW)MsnQ1l;oGae!G9DGlI(VH1W)Ie z4{qM6>x+v)d9;B-O}RZ3&rSgLt)2YU4+8c7qXnR%C;Tdrc3CQ@iTz6F3y4+cG43i6 zhWaXD&H2QYVTwTpaLKz=ZitJTOz;mW?W2vLr1%lc7N2>c!=~s8!6Kr8RteVP5-&^4 zy(Opvd=vyEMP`M}!{)yAM`m4?6FSRA9TrCh4(i&jv|IDjdfup3c2~trVWPjf6rJZT z9ATwAWFcxq5!dq|6~bMdS^X(?^r;w9yUSk*|2CanR(wE(behrP%~&~$sL}QGY%@kY zS#Voe$i-@E^0`&TFQS=MBdM5l<1!9k=B*CXhc)AqFGp7NFke7y_HM+ti;XRdjqKuH zL3Z7_PrnB$7Y!e1jD*rQv{0MmB{aPEOW>J@`k)-+T0V_a=66`CXC&y0Wl|}U@1LAh zGXL=#My2@BE7DQI%!Jy5)%cm|CViG{H=Cei3_!5*#x%)qt>`i-oi@B$k8od~*S!IL zlW3|)ZsVEA6l`>;&GpT7_vE=f8_$e3S8F!lDK)h0^&tKwel^e>6xQx@2h!y@VoOfX z_Q~MA*R@OWiJ%td6wr&;m{lGS8zl#{h!7tWjMyu@=TmppsxV-7*z_j8Hjd&Y>4Q(o zvYRl34IEfJSf7|jZ)5SZcz>t9(UyS;;6Ah7!+6vhdz?s-JI>FYd}OLAw=O-{obK`J zBnhvakjY{x07Fj**blYlM@End;Q`b^HL-x9&{iV8li;1stmvm1YsU%%YHpyLl%K+MJYM(ohu%00 zaHlWrB)Z_-mWD4j_7E_q)p$JilepkUF5j{%%$z0AU%oeo`PVT)m`RGi)xb)FKxkce` z?&fjp$UkwN$LShOuq~WSGU@xgueL+iUOgD_1`ag;!`E)2(RBvLEyGOWP6abX=*0l6 zopT zZVmiKS1rb@ll#tQby2W0rPo(z&2}viqJs|#{FD8<&ggk*B&0PmVne@>oY{OkkXzXg zf7-HiP>)uz%=9EyyEnb`=ICnr>}0Ik^18ZWs`U&D!l{@4{71=$!xi1KR6sdO&C%wE zcBMLfj4Imksu#g)QX+TdLCY`wts|880RnFO{YmrJ#5spEfz(vCO>?3>a0vHm={rMN>FOOB0R4poglIe9-4L&rnQ@Tn8y+s;yluYS2A->_poN9wP+48lra@F zsE~9$*1+qxT$56NlbxQMCLhm~qaC?=JG>njAMcMlEreT$$4v{*TkQW(b;w`!240$% z@aW*mNK-N*ChrxDxM)I&OxSryuCbavXP6pCp6zBVauy}R#$S~J-GEgalu~oOe3M>7iJ+N)VK_?(AU`TzM+B$qQs!?Et!)U_I^$0Y22*&&&FC@e6kWL^8#;sIbZ$S zkLH%J=N<~4p4q$|xu{6mA3bx^u;nqL#Rz)=xIb1^t+MgZ$df*KRL)Y-zJmowbHgiR zsXZ0v$i~n)mZ15ST6Zj0$yq=GOaekF67x^9uYHlUIViIuY&;85POg-XrR|o5OTJn;+SyQyrH|t~+6GR%y_f~PQ9!G&NB|0Q-FZ%a}J-0t8WNeGae`%8g)78${?1a+% z;!u{Xu2Ka>btt33u(3g1>W?=W}qx|f=M@&6jniubPvQB$ndxKNKhr7de zPQ9vI8E5jjMpQ3U?wj?(+h=?3T$*^n|DM?v2z*3LZ?L>qJG9c=xKfq0?%A@)vSj7c zM(+PrpLx(>xG z)IkWcNYMwiP**DSK)|T-`~eUY?5tXpb+adsBjsW-jE^(_OPt7%5QY>=RFkEbxN@2e z0?AX(8R(AkwY4qjHh$;;YDZ1%x5gU#4ev5=tXH&pdM+B=p+S3!94?&Gvnx^Q>HPZV z>+tSRSciE1$70!Nix)y6M&%yU+F0G|BZ6@HVuHZd=m_Z^>P=;KAz$q9JjHpZ1i3=u zqgv-$S^(YFo1sxlb65ocJBi5ZfxcEr{0DplK>k452SG;$Y}hkGms)HI|M3&WGo?lT z>09roWHzmDV<%7){Ppxv<|I7qGR8z?5Zk-G|Dm_AWpv4J&arxia^`0YHl+FZvbYs2 zi;Oh@8bCugoY;>;n`|c`| zvSPWm!gH%0e0D+6dw*u%4n@VS3+tLxsDx%wVr~8lT$mfoS;#R!5Z9)8ie?wUy~#nP zj}()Ty8Hiti>SlDzhq%FZClG7X>;ElN%`3Pfn!3E+WFRLcNf8A@i@gs%03{68W~)8 zq6W!8$42CQKRuu8u!B@~FXYsvqZCm`K6_5|KzSd=0; zyr2#>@wsrS#>?7?CeSI8ToT|YSu}HBtp~FjnHM}I2d#A-sx1(64jTG!z1_J2YK|X^ zL?>bvc#d27aL&^xR1DDoa|IRR-gKq$MzZet+`RJeZ`N1mQF1wj%bK4 zH*~Eh`CjBmJ21v^!s+nUq_e(leno-XrRw`4wTd_M>}?|JZyY$@3n3O8Pd>Y9aeaK1%-CG^5;$OnU+q z=)u+6zilHT`;3mO?7}r+!&YR@__)yUHUCk0gK5AUkmdd+qNXVXcR(dfN>g-1xi`Xc z^}1}RQ+X3k>*tEq+mVSG@-cte#T0$}`Mav;2jI}eln@aQQ1`0eAbTgQONjgMx{0M( zhpGlJINKLUF4q<SP8@8_eug^VT>NrG0^1d|?FCrR@b30`0wTPlHQMSi2{h7+zkC0&Pzh?F}bgy}aq8T-VT( zzR03N<|6PvWKz_f4b^bh*YAiFs{MMi9wxGyo-Xh%wziIH<`u~+^#oeB>}6%s%xerbSA4~soGqrrXi$L;;`fT7OPUwe)!Kt%Ob<9F}-ML>&B z4@>Y)a+edci!ErbxTSxnHaqpJP_dP^)zc9_Sb44DuAQAE#H!rtgS^}?G?z0tpsV`q z_U=5B8mJRjV(WFy{zjv?CXoEhBgW6*o{#Jt9TI*|Adx8pFc8Rv_eY*Z6*!h%Y$x5%*=F-;do7)sxUNbcS-`4v`jj!xiC}j@ z(C~}llCfy0gv6iqb+QG#YQwu+g(b!IXguz!9`MnVqG~ms1eB4BEGbuNpysI_p4c*4 z%M^FLqF2%tYdh1Muz&=R57vpr%w2M{3rZMj^wjnR+GVr%HFycms2a6wi!=_GaJCky zosiBX(zJbYj1O{b(#C64v%wpIW*bld@cdU%F5L2zEbz8?F+`qD^#bFxe@b_{A$*CU z`@g%(VI~}GWqkvUjeK0TVxj?8wEP6)I*R`&Ar7ZI8Q>g9fQs*zHmHC0fY^jy(|XQkGL!9P)_}K zDD>K}M0plmtR`lW%UeUf*39N}_h2-DIqta*lU$1Uxj$E;t5V#&s0DPR=YU5^IeQT3 zF)TXi|0EU@s~NiliTC|(_JRNM!`2}DOAXxR@~r>a8?RC^-c_ofppw*YaPU#?`0m(i zO2z^Dw*DL}Kw^@BWU7wkt|%-Ii{RN?B}Q&;ub)+_jSmE*T=cTWAq!?oVUY>`0Wym| zD)cGn^ja+&3#+ilU3!-3%v*Si9Q?`(fa z756SZE#1i#Hc5z>BkGbqSxP9?XjZ0S0-)4SMqG#Hj)aX$Dpx{Y+KKsEWLH!EMd4jx zd&^DNYsLp5yS&iCIxrUtG};?65ZP?)T^kKz5*}Xa&#bTY5Fl!Nz$74<>~)sn;Xrsi zz(3ok>F$ST-L1&`VH$rZLEUTMH7T?N$%2}p#I`cGQw0~7$1BBUfB9X1A|%g6vjTs- z_RGc(yL3MS1-(buu%0kJ^AjAr&y`o-0nMHku&@nMnS=NH6k%T@$sj{8(|w7+;lPSe zl1QVHMk3PBGzAPqBf1IBe{ti2(tqkETkDWe_M~iTj`L=dKZ;{QCltApEZc=Wn)$Py zBx8JJ|1N5j=OJyQ`3D#y)VoBS0E~qLfU(Q3*DrO!kV2T4%BT1*>oAM@wNZTyd0!}| zq;yBk3d3M0%8K$yN?5I{QpsX-eRXncChppmH>~}Iy?v|oU=SKzDk{s-BId2$!Hagp zO@Kjzpkm-oCq43u?HX09D5k%ysZPt*c)4@%7s-_%vOcYgc+vQ$vl$@5pG-BSMdj8% zpRB{*jg@`9wqv8hO> zTlY7Bhd8xkww8~F|5YuJTkn=J*zfINNMHplIOAvYb&IC~P1V<3?+E6vE9s<19&(cXZH!B(x}tAdLa>2SDdy%zD>33Kk5s z7whLgJnfn%rt~K_Z-P=EaIHlLV5?7i@|)Gt{mMsle(bS|m{{Z^vVJXMVTxhwev!sF zEelbT8hXsbR_J&}g!g1TgQB`uNlHj4!qiw@FGK_d~`?L_sLD33yyiI>t*)K&dUYaIgUifKZdgKy$l~MoH zJGl3p$8wrYP>>zo2JAB%As*pK-(Zh7ujO&0Lt#%sdJ1j;(z+s(bJHoIdVFk*I_>hl zqgnGU;SQTOgv)HXh|jL0g*aDby24HO)HauX6cVP+?#hHPa(4lkq+EJiN}=WZue#K> z7MoZ91K#+u>k<`ZVUFD3SYwQ-^)<;Fps{QptmxD0HPG_n*aRGF>#f%r%T$$LWDL&gH0YC)>FhTU<@*r+df0)+$>Do=UO<)r}0*PKJ%( z9m764RCfY-?cE&ZN=d%VZAqW{>OaF$=*?>mCj&K(^oxtmXtj6*1hp#iy7kTkt;DXh z*F33d!VF8>yu9d2S*Dp#{+1vQSTxY%9wK>=y&q4eWZ0QoMpaHc9Tg+*p)aI7S!_U< zs}UV48YHutZO zV~?XMml~9U3Qb*IB{={AzajewDi)GI`xM+4f}r{l))cNJZgj@D1>=~2?+_gCGEI(SR^Fko}OibwzZn2 ze0(q8ZA^KW6|*Xs9DM>}MrLOn9pj$@aHa9Z=2O-ei?J3zeAj!m_F`CPZqK_j`Iy%d zbwM`8lz!8N{mR83pZh%j+7labs+ouVJU6$c&vq%<$*I79uQf@IJ0n>70r$liJ%|_O z8n>5hsgf6bD?&G-rDY*7vGoZD`?n}8f-vI9$>yHeZYLYOJ!ao&e%9abM}87%?N#l+ z=Zv^85-;sFf!k?eldZ6oV?|M`hjvB@Q zX7Cq<8Iaq%9`w9CMSD$hs|u#Rp6k5m1bB;uV#t2s<3YzrbWl;sDXdGC>hx9|((pR? z@VIf#?F{*gADesE%F%6hTo#!9?|8F#mF)q2f($@LcAgb5#LDu#uez{_ z`GJ`C-ZFOCwURH#RzpUUh>UETU+t>)4+4B&1LPEmRp2?viJ;e}dqwV6W_e)`vwl)G zwUVwYU-W&QWf)s*GMPK6x!p`zIu3IgcQaG4`Xouu=Mf;M?=3B$ROZ#*x~Y;3CPvCX z$WPlE%Y}Aa;>ma1@#&D;Yj=c+{*W&A%TC;CGNy6P5Am9)>NQj@|IJ+oWjl6+_eJF2 zESigl<_f!!F6EXQ7u@fKU+h4WOOE+hCcDr2C5u~~2Zyo5nKVeH-39u{Q^l38|tiMS?@FqoNL6`z3P zzpHLh{kB-Z%a1htVLB=KISUyzOD7tlu3E&hu-->>ysKt zNvB`Oqy2&>D%~_zN8vdDX-C^kN+d(3|LN9FV2p1ax^lvkVnj89hZ7dW+ed7y}x0PozCBp;xUI zIlE@GpeX*mDc92T+nt=Z2Vn8JAfyOo>(_%?MBd&^2=@8&CKtYG=3uJv#5YzBJc(N6 z8O44Yi149?4UB{O8}BZk2k+7G`Tnq+AF1j}yBcMikb>)*el+j&qGdY6j?rN3=i|$L z6;+L)&U~-aqXI>sLwk$_Z?W|??!f+^!7|OKA|rkUJNJxjzAKNvMaVlJFP|HeT_81I zy-ElBMjFE_TTSN$TFzP14=vV7cR`U@T$kp>jPM`vm!dR0)*#zcG6diB^3gGL`9d8^ zCO-4t!zfhv;3{A!>=!aocCTQ>56e+C!wp4DP_gjEARHAtff0p?Ycl&9)L7hzGT(_q->}Bo4EmKAtn-!xOpVxj%8@o z%vFDSfQZPlFOB?jdKXU>gR$9BE4$}rI(2Iz7iCb7zF?GS)ZKMQrPb8Dc${EnPj2~c z27$`Ggjl1b)DSrs%_ zL6;2Yr=-QULwyaOdVLo9*wGxQB+mU>8KuDM$)c`!m(X)}3=Php&V3lT_ zIl*cde<_~ARtJX9GGl7z9d7ZN;^$R9@L>)u9$ZsZLjm`{P{UBny@Nk4pqRv=6l5= zbgkv}fcJf4O=BO5pLG&wdV zhUBA3GHo)=$uA1t`9pNCqEQC4e%;Rp)4 z^W0Mi0*$UkG#ELk(QkZkhF$|ZHOpdR@048LNAAwlPUfo#V#Lrt=nc%6%wLf?y`A@p zCENSc_XPl#2j|X~4|!(6fgl3f-`*|I-lM%|xq1y>nIEPDubXQzd4Vv4Jr_3w( z=DKp^W6I4}E#50&s?WV+^P>V$c8+!^qWy{+0_Q@VW#w}rX?(UfK0n_Gdxtu1q7Jo~ z=cMXcRwRq>n&H(%lyd5t;;EwcPRmw%(gNmB-LTSFDh@(<2}0JAdBWoIs|q(OGHOs zmb98$7-~k5K!nI%w-p4Q2eLI28iI~~)}^HIBr0ww%7O&jcvgDrcT;uQZ$9cT-r97z zpo7)D7&9OF!m{SGD&|ZiP2)*Zsdg(Fo=4tzIYsNMtFp+F^*xxgyb~|a)#o+oLVuw( zcqJ~D)QCXOGgM*cx;{8RSQmSuE}RE?2XY=XI=8+Vis}9i_$%Z*w$;ExEsZ*<2`=jL zWf>I|!x5@q9Dtsgl?>fkSeqTqweqna_JsGahAh%Blc7V~&-bhuytrhT@^+DrvhNNt zzM-SROA%q01P2;n@|vnt2Y+K-=G_*;DEV2^Lxm~C@A|&{R_?`ReeoD3TC%4sw z66T*1e*z&LZ9nIFVUP`bMU&BOS&FvS8#+)j=7SH9@uw&HUIx1Q>@&Uip=9~Jvw{Lf zwf%dH;^6kBeC zB0ZtuOh<48BRL1fTeCWmY9oiji&m8!L zTm-aDSDDA@Rg6%W;cCXDUlr6(H$Oj!xM55jI!cK?_$M+$w3R=MGX05=7k7DXi~eZ9 z>;22hVLo;sDM3IgV-D-uy&0@;M_|9gM;g0Pk2d&q<_|fpzNjt{+lD`3WfcEvUe>#R z{_%w)PiVjF^w;DK$&W^veznTwT_u#SBZE*#0eMDaYn@}eye#szoo`k zDEs32lzn;cwD?y|N!RlSQK%ZC5MI9|j9t;2fiN4DL`=G1hhV~-wV3*YR7&;2tl6)J zsh}On=#Dfsppf}Ig$`2x&z~wOSsW3B!#C3CI1&tixPu3Vf5c&xT#ekwq5%ntmBnJ_ zRcWr3pA*`flGT8uunQdXPu9qHXD78cSzo!PC@__9A0NPzp9&*MAoWwS6nYg@cCgYB zmxg69K7toB^|)`84n}sKbz0&5f|sn7&LgUaXch@~6{^)heC)G)r!)>)T#? zVkl);QQlb>{gs4F!$-hd8d=Ur^aZyfoYH+aBb7~|)~K8{*Q0`tKy4K zO%3^kb7p%+BB(r|)ZKo8X*{^(tDE>2bHfkeKa_cF;XHKWt}uFfYboQv&`4AodOl$&{gQou_i1SPT^eGlfX=*#I*Vwvp3_|h; z>#9`Z&3#=c;NdN=>5gfH?4rEX{ky_NPd5@QzW#7!x0dmSbp`XqJm5a_|Es z&YM0}i9T>DM^KU|wAk_eIjnSJc#Hhy>ei*)GF5a7meutc$DBArDQCO$v@Iqn{Pw> zuK5m6zVV3nmK6=bJuJV`cgTocwi0<2iR&eO;NznWM<6V|R{O&>cH^iPmB&*`ZH7alE*M zpDTw?ZWNDKLxi)QkisZFrTyC*-^LJ&%n*~D1cj(yfr#I--gG(7_*U1}o>tofzVZHI zP5mP5iuzO=?G_%$X_l;CEoo)o`J$LbT3S|9VXJ3*-{Af|BlLk}Y8|>9$&}Cdln9NJ zX_-8{K*D76U=LIY@MYfB;8MGsj8d=~A#Ra8Vb#?UBwSGABqSXE9S{(J?WO-KLaf=U z0hOdo|9?jjX-SmjY|$8_3U!A0`G(V_j+nK!2ggSTtbqYjT>PXOzjqPWvsE!i$5IMd zet%E7Q29{$Mi0z#AttgLb^z`323w^=QCn1n4j13d`ttZhU@@O>t)80<<33ALZvnh> zS3UaW6dDlaM~#fG+Tv;JDa@mrCWi+nw-vX^N^y{Jr_b1C)lTtoTRM600Wa4rKPbfL z?M78juaM7}+*3fe!b^>x1dkgslAR8E8=ci_9QOXn$8=*{V`3$C3Uj-QVC-u`M6_n9 z)#e*Kfm#<6bz{t_HgMrWVRobTiIa03P0cnGJD5W-RfNRzMD>RhM=ACo={zB1u7kN< zw6&azbpGrZk6R9xg?lx+{=(l&OWKo||-% zbu<;Vtv8rx5{v@@Di{0*=4Yl!{l~a3haXBTtM+0T{Hl4uCAHZJJQDF54zdO*SbH=f z28_xcAK7Nkt#z!FRI9y5ohG*HPfhPVZ;U}#FW=rNsD~)_m2utO9!`2aZ1wVLgg6;9 zCA5B>-a+Rk(VHeZP$JX}hBlAa=$NH%nN`{Q~591rNab_Yh+H>*@GW;>!|Z)#&=$DqXZ8UOrkztBZ+qtNTkc5+H88$tQA8Qcf5 zH&NlJ|Mu!<`71#OnHdgzGsfJ){9xfKPydl3Di~d!EhmV!6_lS`++Kz|mOlFx^WUt8 zvl{K@_45oxROa*ruTP0s44Gxg=Ndi9s%f9YUP9Q3@B4lvfb zo~*B7KHgAIEk4%pCQnyU(Z*iv?K2RwqrSpO`tCo;eYfGCJHzsF=H>*MnPOL;xty&4 z4cn<{H1bf%D=8;u^Rey;Ip@Z`lfY+r zEFY05OpCQUd0Xx5i+DHZ^y{X;7=|l(HE7{sFa~I0n(ef ze2nriVf5a??$7Mr;J>;^L(*^^z6=|u@{Vq zw48I-KE+0*Jlpx*<+EBLqO83B&S1aM8$_1YI`|YbCDWojzY42&pf+le$u6VO@^n3X zlC1Kv+SHE2%0AH1O2KGIlxfkcZ4_B-=kdNh1?-gW*2 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 literal 0 HcmV?d00001 diff --git a/node/generate_invoice/Screenshot from 2022-10-03 23-10-49.png b/node/generate_invoice/Screenshot from 2022-10-03 23-10-49.png new file mode 100644 index 0000000000000000000000000000000000000000..a085300c35585a79ba28633f6a7bf4de2f3dc888 GIT binary patch literal 250853 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 QM>h% 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%0AevdXV%Q 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

r>%9p_)03XQhNfO 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 A2mk;8 literal 0 HcmV?d00001 diff --git a/node/generate_invoice/package-lock.json b/node/generate_invoice/package-lock.json new file mode 100644 index 00000000..51a58a22 --- /dev/null +++ b/node/generate_invoice/package-lock.json @@ -0,0 +1,1395 @@ +{ + "name": "invoice", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "invoice", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "pdfkit": "^0.13.0" + } + }, + "node_modules/@swc/helpers": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.3.17.tgz", + "integrity": "sha512-tb7Iu+oZ+zWJZ3HJqwx8oNwSDIU440hmVMDPhpACWQWnrZHK99Bxs70gT1L2dnr5Hg50ZRWEFkQCAnOVVV0z1Q==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "dependencies": { + "base64-js": "^1.1.2" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, + "node_modules/deep-equal": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.5.tgz", + "integrity": "sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw==", + "dependencies": { + "call-bind": "^1.0.0", + "es-get-iterator": "^1.1.1", + "get-intrinsic": "^1.0.1", + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.2", + "is-regex": "^1.1.1", + "isarray": "^2.0.5", + "object-is": "^1.1.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.3", + "which-boxed-primitive": "^1.0.1", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" + }, + "node_modules/es-abstract": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.3.tgz", + "integrity": "sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw==", + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.3", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.6", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.2", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz", + "integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.0", + "has-symbols": "^1.0.1", + "is-arguments": "^1.1.0", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fontkit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.9.0.tgz", + "integrity": "sha512-HkW/8Lrk8jl18kzQHvAw9aTHe1cqsyx5sDnxncx652+CIfhawokEPkeM3BoIC+z/Xv7a0yMr0f3pRRwhGH455g==", + "dependencies": { + "@swc/helpers": "^0.3.13", + "brotli": "^1.3.2", + "clone": "^2.1.2", + "deep-equal": "^2.0.5", + "dfa": "^1.2.0", + "restructure": "^2.0.1", + "tiny-inflate": "^1.0.3", + "unicode-properties": "^1.3.1", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", + "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/linebreak": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz", + "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==", + "dependencies": { + "base64-js": "0.0.8", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/linebreak/node_modules/base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, + "node_modules/pdfkit": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.13.0.tgz", + "integrity": "sha512-AW79eHU5eLd2vgRDS9z3bSoi0FA+gYm+100LLosrQQMLUzOBGVOhG7ABcMFpJu7Bpg+MT74XYHi4k9EuU/9EZw==", + "dependencies": { + "crypto-js": "^4.0.0", + "fontkit": "^1.8.1", + "linebreak": "^1.0.2", + "png-js": "^1.0.0" + } + }, + "node_modules/png-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", + "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/restructure": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-2.0.1.tgz", + "integrity": "sha512-e0dOpjm5DseomnXx2M5lpdZ5zoHqF1+bqdMJUohoYVVQa7cBdnk7fdmeI6byNWP/kiME72EeTiSypTCVnpLiDg==" + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" + }, + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", + "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + } + }, + "dependencies": { + "@swc/helpers": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.3.17.tgz", + "integrity": "sha512-tb7Iu+oZ+zWJZ3HJqwx8oNwSDIU440hmVMDPhpACWQWnrZHK99Bxs70gT1L2dnr5Hg50ZRWEFkQCAnOVVV0z1Q==", + "requires": { + "tslib": "^2.4.0" + } + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "requires": { + "base64-js": "^1.1.2" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" + }, + "crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, + "deep-equal": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.5.tgz", + "integrity": "sha512-nPiRgmbAtm1a3JsnLCf6/SLfXcjyN5v8L1TXzdCmHrXJ4hx+gW/w1YCcn7z8gJtSiDArZCgYtbao3QqLm/N1Sw==", + "requires": { + "call-bind": "^1.0.0", + "es-get-iterator": "^1.1.1", + "get-intrinsic": "^1.0.1", + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.2", + "is-regex": "^1.1.1", + "isarray": "^2.0.5", + "object-is": "^1.1.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.3", + "which-boxed-primitive": "^1.0.1", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.2" + } + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" + }, + "es-abstract": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.3.tgz", + "integrity": "sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw==", + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.3", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.6", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.2", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + } + }, + "es-get-iterator": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz", + "integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.0", + "has-symbols": "^1.0.1", + "is-arguments": "^1.1.0", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "fontkit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.9.0.tgz", + "integrity": "sha512-HkW/8Lrk8jl18kzQHvAw9aTHe1cqsyx5sDnxncx652+CIfhawokEPkeM3BoIC+z/Xv7a0yMr0f3pRRwhGH455g==", + "requires": { + "@swc/helpers": "^0.3.13", + "brotli": "^1.3.2", + "clone": "^2.1.2", + "deep-equal": "^2.0.5", + "dfa": "^1.2.0", + "restructure": "^2.0.1", + "tiny-inflate": "^1.0.3", + "unicode-properties": "^1.3.1", + "unicode-trie": "^2.0.0" + } + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + }, + "get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==" + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==" + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", + "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0" + } + }, + "is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==" + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "linebreak": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz", + "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==", + "requires": { + "base64-js": "0.0.8", + "unicode-trie": "^2.0.0" + }, + "dependencies": { + "base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==" + } + } + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + }, + "object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, + "pdfkit": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.13.0.tgz", + "integrity": "sha512-AW79eHU5eLd2vgRDS9z3bSoi0FA+gYm+100LLosrQQMLUzOBGVOhG7ABcMFpJu7Bpg+MT74XYHi4k9EuU/9EZw==", + "requires": { + "crypto-js": "^4.0.0", + "fontkit": "^1.8.1", + "linebreak": "^1.0.2", + "png-js": "^1.0.0" + } + }, + "png-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", + "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==" + }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, + "restructure": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-2.0.1.tgz", + "integrity": "sha512-e0dOpjm5DseomnXx2M5lpdZ5zoHqF1+bqdMJUohoYVVQa7cBdnk7fdmeI6byNWP/kiME72EeTiSypTCVnpLiDg==" + }, + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "requires": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "requires": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, + "which-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", + "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.9" + } + } + } +} diff --git a/node/generate_invoice/package.json b/node/generate_invoice/package.json new file mode 100644 index 00000000..1e1597a4 --- /dev/null +++ b/node/generate_invoice/package.json @@ -0,0 +1,15 @@ +{ + "name": "invoice", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "pdfkit": "^0.13.0" + } +} diff --git a/node/generate_invoice/src/index.js b/node/generate_invoice/src/index.js new file mode 100644 index 00000000..7d57f41b --- /dev/null +++ b/node/generate_invoice/src/index.js @@ -0,0 +1,49 @@ +const PDFDOC = require("pdfkit") +const doc = new PDFDOC(); +module.exports =(req,res)=>{ + const {currency,items,issuer,customer,vat} = req.payload; + console.log(issuer); + if(!issuer || issuer ==="") return {status:false,message:"Please provide Issuer"} + if(!customer || customer ==="") return {status:false,message:"Please provide Customer"} + if(!vat) return {status:false,message:"Please provide Vat"} + if(!currency || currency ==="") return {status:false,message:"Please provide Currency"} + if(!items) return {status:false,message:"Please provide Items"} + doc + .fontSize(26).text("Invoice",{ + align:"center", + underline:true, + lineGap:10, + + } ,100, 100); + + doc.moveDown(); + doc.fontSize(15).text(`Issuer: ${issuer}`,{align:"left"}); + doc.moveDown(); + doc.text(`Customer: ${customer}`,{align:"left"}); + doc.moveDown(); + doc.text(`Currency: ${currency}`,{align:"left"}); + doc.moveDown(); + doc.text(`VAT: ${vat}%`,{align:"left"}); + let totalPrice=0; + doc.moveDown(); + for (let index = 0; index < items.length; index++) { + doc.text( + `Items:${items[index].name} Price:${items[index].price}`, + { + x: 50, + }, + ); + totalPrice += items[index].price; + if (index === items.length - 1) { + doc.moveDown(); + doc.fontSize(20).text(`Total:${totalPrice}`, { + x: 50, + }); + } + doc.moveDown(); + } + doc.end(); + const output = doc.read(); + const string = output.toString("base64"); + res.send({status:true,invoice:string}) +} \ No newline at end of file diff --git a/node/generate_map/README.md b/node/generate_map/README.md new file mode 100644 index 00000000..ba47224b --- /dev/null +++ b/node/generate_map/README.md @@ -0,0 +1,48 @@ +# 📱 Generate Map + +A Node Generate Map Function for generate a screenshot of map location using [OpenStreetMap](https://www.openstreetmap.org/). + +_Example input:_ + +```json +{ + "provider": "openstreets", + "lat": 41.909986, + "lng": 12.3959136 +} +``` + +_Example output:_ + +```json +{ + "success": "true", + "image":"iVBORw0KGgoAAAANSUhEUgAAAaQAAALiCAY...QoH9hbkTPQAAAABJRU5ErkJggg==" +} +``` + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/generate_map +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-17.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/index.js -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-17.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit NodeJS runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-17.0). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with NodeJS 17.0. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/node/generate_map/package.json b/node/generate_map/package.json new file mode 100644 index 00000000..638de8e7 --- /dev/null +++ b/node/generate_map/package.json @@ -0,0 +1,17 @@ +{ + "name": "generate_map", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "ajv": "^8.11.0", + "ajv-errors": "^3.0.0", + "undici": "^5.11.0" + } +} diff --git a/node/generate_map/src/index.js b/node/generate_map/src/index.js new file mode 100644 index 00000000..7037fce6 --- /dev/null +++ b/node/generate_map/src/index.js @@ -0,0 +1,80 @@ +const { fetch } = require("undici"); +const Ajv = require("ajv"); + +const ajv = new Ajv({ allErrors: true }); +require("ajv-errors")(ajv); + +ajv.addFormat("provider", { + type: "string", + validate: (x) => x === "openstreets", +}); + +const schema = { + type: "object", + properties: { + provider: { type: "string", format: "provider" }, + lat: { type: "number", minimum: -90, maximum: 90 }, + lng: { type: "number", minimum: -180, maximum: 180 }, + }, + required: ["provider", "lat", "lng"], + errorMessage: { + properties: { + provider: "Provider must be an openstreets", + lat: "Latitude must be a valid number between -90 and 90.", + lng: "Longitude must be a valid number between -180 and 180.", + }, + }, +}; + +module.exports = async function (req, res) { + const validate = ajv.compile(schema); + + const payload = JSON.parse(req.payload); + const valid = validate(payload); + + if (!valid) { + return res.json({ + success: false, + message: validate.errors.map((error) => error.message).join(", "), + }); + } + + const { lat, lng, provider } = payload; + + const z = 16; // zoom level + const x = Math.floor(((lng + 180) / 360) * Math.pow(2, z)); + const y = Math.floor( + ((1 - + Math.log( + Math.tan((lat * Math.PI) / 180) + 1 / Math.cos((lat * Math.PI) / 180) + ) / + Math.PI) / + 2) * + Math.pow(2, z) + ); + + switch (provider) { + case "openstreets": { + const result = await fetch( + `https://tile.openstreetmap.org/${z}/${x}/${y}.png` + ); + + if (result.status != 200) { + return res.json({ + success: false, + message: "Openstreetmap server error", + }); + } + + const image = await result.arrayBuffer(); + + res.json({ + success: true, + image: Buffer.from(image).toString("base64"), + }); + } + + default: + return; + } +}; diff --git a/node/get_covid_stats/README.md b/node/get_covid_stats/README.md new file mode 100644 index 00000000..cfbe28f5 --- /dev/null +++ b/node/get_covid_stats/README.md @@ -0,0 +1,53 @@ +# 🦠 Get COVID-19 stats from an API + +A Node Cloud Function for fetching COVID information using [Covid19Api](https://covid19api.com/). + +_Example input:_ + +```json +{ + "country": "NZ" +} +``` + +_Example output:_ + + +```json +{ + "country": "New Zealand", + "confirmedCasesToday": 2, + "recoveredToday": 4, + "deathsToday": 0 +} +``` + +## 📝 Environment Variables + +No environment variables needed. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/get_covid_stats +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-17.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/index.js -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-17.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit NodeJS runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-17.0). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with NodeJS 17.0. Other versions may work but are not guarenteed to work as they haven't been tested. diff --git a/node/get_covid_stats/package-lock.json b/node/get_covid_stats/package-lock.json new file mode 100644 index 00000000..2da3ad30 --- /dev/null +++ b/node/get_covid_stats/package-lock.json @@ -0,0 +1,58 @@ +{ + "name": "get_covid_stats", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "get_covid_stats", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "axios": "^0.26.1" + } + }, + "node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, + "node_modules/follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + } + }, + "dependencies": { + "axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "requires": { + "follow-redirects": "^1.14.8" + } + }, + "follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + } + } +} diff --git a/node/get_covid_stats/package.json b/node/get_covid_stats/package.json new file mode 100644 index 00000000..9b33efc8 --- /dev/null +++ b/node/get_covid_stats/package.json @@ -0,0 +1,15 @@ +{ + "name": "get_covid_stats", + "version": "1.0.0", + "description": "", + "main": "src/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "axios": "^0.26.1" + } +} diff --git a/node/get_covid_stats/src/index.js b/node/get_covid_stats/src/index.js new file mode 100644 index 00000000..842998dc --- /dev/null +++ b/node/get_covid_stats/src/index.js @@ -0,0 +1,35 @@ +const axios = require('axios').default; + +module.exports = async function (req, res) { + let countryId = ''; + if (req.payload) { + countryId = JSON.parse(req.payload).country; + } + + const response = await axios.get(`https://api.covid19api.com/summary`); + + if (response.status !== 200) { + throw new Error(`Status code: ${response.status}, Data: ${response.data}`); + } + + const dataJson = response.data; + + if (countryId) { + dataJson.Countries = dataJson.Countries.filter(country => + country['Country'] === countryId || + country['CountryCode'] === countryId || + country['Slug'] === countryId); + } + + let country = dataJson.Countries[0]['Country'] ?? 'The World'; + let confirmedCasesToday = dataJson.Countries[0]['NewConfirmed'] ?? dataJson.Global.NewConfirmed; + let deathsToday = dataJson.Countries[0]['NewDeaths'] ?? dataJson.Global.NewDeaths; + let recoveredCasesToday = dataJson.Countries[0]['NewRecovered'] ?? dataJson.Global.NewRecovered; + + res.json({ + country: country, + confirmedCasesToday: confirmedCasesToday, + deathsToday: deathsToday, + recoveredCasesToday: recoveredCasesToday + }); +}; \ No newline at end of file diff --git a/node/object_detection/README.md b/node/object_detection/README.md new file mode 100644 index 00000000..bf540018 --- /dev/null +++ b/node/object_detection/README.md @@ -0,0 +1,58 @@ +# 📷 Object Detection using Cloudmersive Vision API + +A Node Cloud Function for object detection from an image URL. + +_Example input:_ + +```json +{ + "url": "https://picsum.photos/seed/open___runtimes/1000/1000" +} +``` + +_Example output:_ + + +```json +{ + "url": "https://picsum.photos/seed/open___runtimes/1000/1000", + "name": "cake", + "confidence": 0.7977721691131592, + "x": 21, + "y": 5, + "width": 494, + "height": 333 +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +**CLOUDMERSIVE_API_KEY** - Your Cloudmersive API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/object_detection +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-17.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/index.js -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-17.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit NodeJS runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-17.0). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with NodeJS 17.0. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/node/object_detection/package-lock.json b/node/object_detection/package-lock.json new file mode 100644 index 00000000..8effdf32 --- /dev/null +++ b/node/object_detection/package-lock.json @@ -0,0 +1,560 @@ +{ + "name": "object_detection", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "object_detection", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "axios": "^0.26.1", + "cloudmersive-image-api-client": "^1.3.1" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/cloudmersive-image-api-client": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/cloudmersive-image-api-client/-/cloudmersive-image-api-client-1.3.5.tgz", + "integrity": "sha512-73BS+8RQQmJbecpXc88gmy/398RXtjnwqNeO3ASq7mHX73BuR1Ng2Yn9oTvuOf1uSjEm6MfNH3xDvonEv1SLkA==", + "dependencies": { + "superagent": "3.7.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "node_modules/cookiejar": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", + "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", + "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau", + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/superagent": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.7.0.tgz", + "integrity": "sha512-/8trxO6NbLx4YXb7IeeFTSmsQ35pQBiTBsLNvobZx7qBzBeHYvKCyIIhW2gNcWbLzYxPAjdgFbiepd8ypwC0Gw==", + "deprecated": "Please upgrade to v7.0.2+ of superagent. We have fixed numerous issues with streams, form-data, attach(), filesystem errors not bubbling up (ENOENT on attach()), and all tests are now passing. See the releases tab for more information at .", + "dependencies": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.1.1", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + } + }, + "dependencies": { + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "requires": { + "follow-redirects": "^1.14.8" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "cloudmersive-image-api-client": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/cloudmersive-image-api-client/-/cloudmersive-image-api-client-1.3.5.tgz", + "integrity": "sha512-73BS+8RQQmJbecpXc88gmy/398RXtjnwqNeO3ASq7mHX73BuR1Ng2Yn9oTvuOf1uSjEm6MfNH3xDvonEv1SLkA==", + "requires": { + "superagent": "3.7.0" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "cookiejar": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz", + "integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + }, + "form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "formidable": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "superagent": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.7.0.tgz", + "integrity": "sha512-/8trxO6NbLx4YXb7IeeFTSmsQ35pQBiTBsLNvobZx7qBzBeHYvKCyIIhW2gNcWbLzYxPAjdgFbiepd8ypwC0Gw==", + "requires": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.1.1", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.0.5" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + } + } +} diff --git a/node/object_detection/package.json b/node/object_detection/package.json new file mode 100644 index 00000000..91908d23 --- /dev/null +++ b/node/object_detection/package.json @@ -0,0 +1,16 @@ +{ + "name": "object_detection", + "version": "1.0.0", + "description": "", + "main": "src/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "axios": "^0.26.1", + "cloudmersive-image-api-client": "^1.3.1" + } +} diff --git a/node/object_detection/src/index.js b/node/object_detection/src/index.js new file mode 100644 index 00000000..9b3e9a6d --- /dev/null +++ b/node/object_detection/src/index.js @@ -0,0 +1,26 @@ +const CloudmersiveImageApiClient = require('cloudmersive-image-api-client'); +const axios = require('axios').default; + +module.exports = async function(req, res) { + let defaultClient = CloudmersiveImageApiClient.ApiClient.instance; + let Apikey = defaultClient.authentications['Apikey']; + Apikey.apiKey = req.variables["CLOUDMERSIVE_API_KEY"]; + let payload = JSON.parse(req.payload); + + let apiInstance = new CloudmersiveImageApiClient.RecognizeApi(); + + let imageBlob = await axios.get(payload.url, { responseType: 'arraybuffer' }); + + let recognizeDetectObjectsPromise = (imageBlob) => { + return new Promise ((resolve, reject) => { + apiInstance.recognizeDetectObjects(imageBlob, (error, data, response) => { + if (error) return reject(error); + resolve(data); + }); + }) + } + + let result = await recognizeDetectObjectsPromise(imageBlob.data); + + res.json(result.Objects); +}; \ No newline at end of file diff --git a/node/send_email_with_mailgun/README.md b/node/send_email_with_mailgun/README.md new file mode 100644 index 00000000..7f6fb330 --- /dev/null +++ b/node/send_email_with_mailgun/README.md @@ -0,0 +1,54 @@ +# 📧 Sending Welcome Emails using Mailgun's Email API + +A sample NodeJS Cloud Function for sending emails using the Mailgun API. + + +_Example input:_ + +```json +{ + "name": "John Doe", + "email": "johndoe@gmail.com" +} +``` + + +_Example output:_ + + +``` +{"id":"","message":"Queued. Thank you."} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +* **MAILGUN_API_KEY** - API Key for Mailgun +* **MAILGUN_DOMAIN** - Domain Name from Mailgun + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/send_email_with_mailgun +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-17.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/index.js -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-17.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit NodeJS runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-17.0). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with NodeJS 17.0. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/node/send_email_with_mailgun/package.json b/node/send_email_with_mailgun/package.json new file mode 100644 index 00000000..563d3c6c --- /dev/null +++ b/node/send_email_with_mailgun/package.json @@ -0,0 +1,16 @@ +{ + "name": "send_email_with_mailgun", + "version": "1.0.0", + "description": "", + "main": "src/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "mailgun-js": "^0.22.0" + } + } + \ No newline at end of file diff --git a/node/send_email_with_mailgun/src/index.js b/node/send_email_with_mailgun/src/index.js new file mode 100644 index 00000000..f5304bdd --- /dev/null +++ b/node/send_email_with_mailgun/src/index.js @@ -0,0 +1,27 @@ +const mailgun = require("mailgun-js"); + +module.exports = async function (req, res) { + const emailConfig = { + apiKey: req.variables.MAILGUN_API_KEY, + domain: req.variables.MAILGUN_DOMAIN + }; + const mg = mailgun(emailConfig); + + // Get the name and email of the newly created user from Appwrite's environment variable + const payload = JSON.parse(req.payload) + const name = payload['name'] + const email = payload['email'] + + // Create your email + const data = { + from: 'Welcome to My Awesome App ', + to: email, + subject: `Welcome on board ${name}!`, + text: `Hi ${name}\nGreat to have you with us. !` + }; + + // Send the email! + mg.messages().send(data, function (error, body) { + res.send(body); + }); +}; \ No newline at end of file diff --git a/node/send_http_request/README.md b/node/send_http_request/README.md new file mode 100644 index 00000000..be2a6be4 --- /dev/null +++ b/node/send_http_request/README.md @@ -0,0 +1,63 @@ +# 📱 Send Http Request + +A Node Cloud Function that send http request. + +_Example input function payload:_ + +```json +{ + "url": "https://demo.appwrite.io/v1/locale/countries/eu", + "method": "GET", + "headers": { "x-client-version": "1.0.0" }, + "body": "" +} +``` + +_Successful function response:_ + +```json +{ + "success":true, + "response":{"headers":{},"code":200,"body":"{\"total\":27,\"countries\":[]}"} +} +``` + +_Error function response:_ + +```json +{ + "success":false, + "message":"URL could not be reached." +} + +``` + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +```bash +git clone https://github.com/open-runtimes/examples.git && cd examples +cd node/send_http_request +``` + +2. Enter this function folder and build the code: + +```bash +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-16.0 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +1. Start the Open Runtime: + +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.js --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-18.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Node runtime [README](https://github.com/open-runtimes/open-runtimes/tree/6d07f73a5984a0014a3bd297499ecb4dcc0e38f4/runtimes/node-18.0). + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Node 16.0. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/node/send_http_request/index.js b/node/send_http_request/index.js new file mode 100644 index 00000000..ae4c7545 --- /dev/null +++ b/node/send_http_request/index.js @@ -0,0 +1,37 @@ +const axios = require("axios"); +module.exports = async (req, res) => { + let url, method, body, headers; + + try { + const payload = JSON.parse(req.payload); + url = payload.url; + method = payload.method || undefined; + headers = payload.headers || undefined; + body = payload.body || undefined; + } catch (err) { + + res.json({ success: false, message: "Payload does not have a proper structure." }); + } + + const config = { + method, + url, + data: body, + headers, + }; + + try { + const response = await axios(config); // Request to Server + + res.json({ + success: true, + response: { + headers: response.headers, + code: response.status, + body: response.data, + }, + }); + } catch (error) { + res.json({ success: false, message: "URL could not be reached." }); + } +}; diff --git a/node/send_http_request/package-lock.json b/node/send_http_request/package-lock.json new file mode 100644 index 00000000..920c95cb --- /dev/null +++ b/node/send_http_request/package-lock.json @@ -0,0 +1,69 @@ +{ + "name": "send_http_request", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.0.0.tgz", + "integrity": "sha512-SsHsGFN1qNPFT5QhSoSD37SHDfGyLSW5AESmyLk2JeCMHv5g0I9g0Hz/zQHx2KNe0jGXh2q2hAm7OdkXm360CA==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + } + } +} diff --git a/node/send_http_request/package.json b/node/send_http_request/package.json new file mode 100644 index 00000000..63c32255 --- /dev/null +++ b/node/send_http_request/package.json @@ -0,0 +1,15 @@ +{ + "name": "send_http_request", + "version": "1.0.0", + "description": "", + "type": "commonjs", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "axios": "^1.0.0" + } +} diff --git a/node/send_sms_with_twilio/README.md b/node/send_sms_with_twilio/README.md new file mode 100644 index 00000000..6638802d --- /dev/null +++ b/node/send_sms_with_twilio/README.md @@ -0,0 +1,56 @@ +# 📱 Send SMS with Twilio + +A Node Cloud Function for sending message to a phone number using [Twilio API](https://www.twilio.com/docs/usage/api). + +_Example input:_ + +```json +{ + "text": "Hello from Open Runtimes 👋", + "phoneNumber": "+421XXXXXXXXX" +} +``` + +_Example output:_ + +```json +{ + "messageId": "SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **TWILIO_ACCOUNT_SID** - Twilio account SID +- **TWILIO_AUTH_TOKEN** - Twilio auth token +- **TWILIO_SENDER** - Sender's phone number from Twilio + +ℹ️ _Find your Account SID and Auth Token at twilio.com/console._ + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/send_sms_with_twilio +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-17.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/index.js -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-17.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit NodeJS runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-17.0). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with NodeJS 17.0. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/node/send_sms_with_twilio/package-lock.json b/node/send_sms_with_twilio/package-lock.json new file mode 100644 index 00000000..48750752 --- /dev/null +++ b/node/send_sms_with_twilio/package-lock.json @@ -0,0 +1,58 @@ +{ + "name": "send_sms_with_twilio", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "send_sms_with_twilio", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "axios": "^0.26.1" + } + }, + "node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, + "node_modules/follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + } + }, + "dependencies": { + "axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "requires": { + "follow-redirects": "^1.14.8" + } + }, + "follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + } + } +} diff --git a/node/send_sms_with_twilio/package.json b/node/send_sms_with_twilio/package.json new file mode 100644 index 00000000..9d12424b --- /dev/null +++ b/node/send_sms_with_twilio/package.json @@ -0,0 +1,15 @@ +{ + "name": "send_sms_with_twilio", + "version": "1.0.0", + "description": "", + "main": "src/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "axios": "^0.26.1" + } + } \ No newline at end of file diff --git a/node/send_sms_with_twilio/src/index.js b/node/send_sms_with_twilio/src/index.js new file mode 100644 index 00000000..7e5fef0c --- /dev/null +++ b/node/send_sms_with_twilio/src/index.js @@ -0,0 +1,30 @@ +const axios = require('axios').default; + +module.exports = async function test(req, res) { + const accountSID = req.variables["TWILIO_ACCOUNT_SID"]; + const authToken = req.variables["TWILIO_AUTH_TOKEN"]; + const sender = req.variables["TWILIO_SENDER"]; + + const { + phoneNumber, + text, + } = JSON.parse(req.payload); + + let response = await axios({ + method: 'POST', + url: `https://api.twilio.com/2010-04-01/Accounts/${accountSID}/Messages.json`, + auth: { + username: accountSID, + password: authToken + }, + data: new URLSearchParams({ + From: sender, + To: phoneNumber, + Body: text + }), + }).then((data) => { + return data; + }).catch((e) => console.error(e)); + + res.json(response.data); +}; \ No newline at end of file diff --git a/node/translate_text/README.md b/node/translate_text/README.md new file mode 100644 index 00000000..834824c1 --- /dev/null +++ b/node/translate_text/README.md @@ -0,0 +1,73 @@ +# 🌐 Translate text from one language to another + +A NodeJS Cloud Function for translating text from one language to another. Includes support for [Google](https://translate.google.com/), [AWS](https://aws.amazon.com/translate/), and [Azure](https://azure.microsoft.com/en-us/products/cognitive-services/translator/) + +_Example input:_ + +```json +{ + "provider": "google", + "text": "Hello from Open Runtimes", + "from": "en", + "to": "es" +} +``` + +_Example output:_ + +```json +{ + "response": { + "message": "Hola desde Open Runtimes", + "success": true, + "from": "en" + }, + "stdout": "", + "stderr": "" +} +``` + +## 📝 Variables + +#### Translating with `google` + +No variables required + +#### Translate with `aws` + +- **AWS_ACCESS_KEY** - Access key for AWS +- **AWS_SECRET_KEY** - Secret Key for AWS + +#### Translating with `azure` + +- **TRANSLATOR_KEY** - Translator Key for Azure + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/translate_text +``` + +2. Enter this function folder and build the code: + +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-18.0 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/index.js -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-18.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit NodeJS runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-18.0). + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with NodeJS 18.0. Other versions may work but are not guarenteed to work as they haven't been tested. diff --git a/node/translate_text/package-lock.json b/node/translate_text/package-lock.json new file mode 100644 index 00000000..f8af4023 --- /dev/null +++ b/node/translate_text/package-lock.json @@ -0,0 +1,2057 @@ +{ + "name": "translate_text", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "translate_text", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@vitalets/google-translate-api": "^8.0.0", + "aws-sdk": "^2.1229.0", + "axios": "^1.0.0" + } + }, + "node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@vitalets/google-translate-api": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@vitalets/google-translate-api/-/google-translate-api-8.0.0.tgz", + "integrity": "sha512-CHOi8DRgDAoLlFQy9pm1KHUauIk5ZXys3+Eh0aSYxzJSuxAE7Z2UL8+5MgNdl1oX7t/O7u+SwGhkhu6+U1bNcg==", + "dependencies": { + "configstore": "^5.0.1", + "got": "^9.6.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sdk": { + "version": "2.1229.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1229.0.tgz", + "integrity": "sha512-oe84BuQW2WTxinZAXqcCsWh2uS7ek2C7eaw+tYhni+LBJcpeiqB5gSqOE/OaFlTXIkJlsmWlI23ZkjXcBijNKw==", + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "util": "^0.12.4", + "uuid": "8.0.0", + "xml2js": "0.4.19" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/axios": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.0.0.tgz", + "integrity": "sha512-SsHsGFN1qNPFT5QhSoSD37SHDfGyLSW5AESmyLk2JeCMHv5g0I9g0Hz/zQHx2KNe0jGXh2q2hAm7OdkXm360CA==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/es-abstract": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.3.tgz", + "integrity": "sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw==", + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.3", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.6", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.2", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", + "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==" + }, + "node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", + "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "node_modules/xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==", + "engines": { + "node": ">=4.0" + } + } + }, + "dependencies": { + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@vitalets/google-translate-api": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@vitalets/google-translate-api/-/google-translate-api-8.0.0.tgz", + "integrity": "sha512-CHOi8DRgDAoLlFQy9pm1KHUauIk5ZXys3+Eh0aSYxzJSuxAE7Z2UL8+5MgNdl1oX7t/O7u+SwGhkhu6+U1bNcg==", + "requires": { + "configstore": "^5.0.1", + "got": "^9.6.0" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" + }, + "aws-sdk": { + "version": "2.1229.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1229.0.tgz", + "integrity": "sha512-oe84BuQW2WTxinZAXqcCsWh2uS7ek2C7eaw+tYhni+LBJcpeiqB5gSqOE/OaFlTXIkJlsmWlI23ZkjXcBijNKw==", + "requires": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "util": "^0.12.4", + "uuid": "8.0.0", + "xml2js": "0.4.19" + } + }, + "axios": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.0.0.tgz", + "integrity": "sha512-SsHsGFN1qNPFT5QhSoSD37SHDfGyLSW5AESmyLk2JeCMHv5g0I9g0Hz/zQHx2KNe0jGXh2q2hAm7OdkXm360CA==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + } + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "requires": { + "is-obj": "^2.0.0" + } + }, + "duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "es-abstract": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.3.tgz", + "integrity": "sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw==", + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.3", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.6", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.2", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==" + }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + }, + "get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", + "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==" + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==" + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "requires": { + "json-buffer": "3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==" + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==" + }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, + "sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "requires": { + "prepend-http": "^2.0.0" + } + }, + "util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==" + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", + "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.9" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" + }, + "xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==" + } + } +} diff --git a/node/translate_text/package.json b/node/translate_text/package.json new file mode 100644 index 00000000..2c7298c8 --- /dev/null +++ b/node/translate_text/package.json @@ -0,0 +1,16 @@ +{ + "name": "translate_text", + "version": "1.0.0", + "description": "", + "main": "src/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@vitalets/google-translate-api": "^8.0.0", + "aws-sdk": "^2.1229.0", + "axios": "^0.27.2" + } +} diff --git a/node/translate_text/src/aws_provider.js b/node/translate_text/src/aws_provider.js new file mode 100644 index 00000000..8ebb8f8b --- /dev/null +++ b/node/translate_text/src/aws_provider.js @@ -0,0 +1,31 @@ +const aws = require('aws-sdk') + + +module.exports = async function(payload,variables){ + const { + text, + from, + to + } = JSON.parse(payload); + + + const { + AWS_ACCESS_KEY, + AWS_SECRET_KEY + } = JSON.parse(variables); + + aws.config.region = 'us-east-1' + aws.config.credentials = new aws.Credentials(AWS_ACCESS_KEY, AWS_SECRET_KEY) + const params = { + SourceLanguageCode: from, + TargetLanguageCode: to, + Text: text + }; + const translateService = new aws.Translate() + + const response = await translateService.translateText(params, (err, data) => { + return data; +}).promise().then(data => {return {success :true , message: data.TranslatedText, from: from};}).catch(e =>{return {success :false , message: e.message};} ) + + return response; +} \ No newline at end of file diff --git a/node/translate_text/src/azure_provider.js b/node/translate_text/src/azure_provider.js new file mode 100644 index 00000000..e24d5b1f --- /dev/null +++ b/node/translate_text/src/azure_provider.js @@ -0,0 +1,43 @@ +const axios = require('axios').default; + +module.exports = async function(payload, variables){ + + const { + text, + from, + to + } = JSON.parse(payload); + + const { + TRANSLATOR_KEY, + LOCATION + } = JSON.parse(variables); + + + + let key = TRANSLATOR_KEY; + let endpoint = "https://api.cognitive.microsofttranslator.com"; + + let location = LOCATION; + const response = await axios({ + baseURL: endpoint, + url: '/translate', + method: 'post', + headers: { + 'Ocp-Apim-Subscription-Key': key, + 'Ocp-Apim-Subscription-Region': location, + 'Content-type': 'application/json' + }, + params: { + 'api-version': '3.0', + 'from': from, + 'to': [to] + }, + data: [{ + 'text': text + }], + responseType: 'json' + }).then((response) => {return {success: true, message: response.data[0]['translations'][0]['text'], from:from}}).catch(e => {console.error(e); return {success: false, message:e.message}}) + + return response; +} \ No newline at end of file diff --git a/node/translate_text/src/google_provider.js b/node/translate_text/src/google_provider.js new file mode 100644 index 00000000..3bcb95c5 --- /dev/null +++ b/node/translate_text/src/google_provider.js @@ -0,0 +1,14 @@ +const translate = require('@vitalets/google-translate-api'); + +module.exports = async function(payload){ + const { + text, + from, + to + } = JSON.parse(payload); + + let response = await translate(text, {to: to, from: from}).then((data) => { + return {message: data.text, success: true, from: from}; + }).catch((e) => {console.error(e); return {message: e.message, success: false}}); + return response; +} \ No newline at end of file diff --git a/node/translate_text/src/index.js b/node/translate_text/src/index.js new file mode 100644 index 00000000..8a669612 --- /dev/null +++ b/node/translate_text/src/index.js @@ -0,0 +1,33 @@ +const googleProvider = require('./google_provider') +const azureProvider = require('./azure_provider') +const awsProvider = require('./aws_provider'); + +module.exports = async function(req, res) { + const { + provider, + text + } = JSON.parse(req.payload); + + let response ={}; + + if(provider==='google'){ + response = await googleProvider(req.payload).catch((e)=>console.log(e)); + } + + else if(provider==='azure'){ + response = await azureProvider(req.payload, req.variables).catch((e)=>console.log(e)); + } + + else if(provider==='aws'){ + response = await awsProvider(req.payload, req.variables).catch((e)=>console.log(e)); + } + + else{ + response = { + success : false, + message : "The provider does not match the available providers" + } + } + // console.log(response); + res.json(response); +}; \ No newline at end of file diff --git a/node/translate_text_with_google/README.md b/node/translate_text_with_google/README.md new file mode 100644 index 00000000..57c5f0e6 --- /dev/null +++ b/node/translate_text_with_google/README.md @@ -0,0 +1,52 @@ +# 🌐 Translate text from one language to another + +A NodeJS Cloud Function for translating text from one language to another using [Google Translate](https://translate.google.com/). + +_Example input:_ + +```json +{ + "text": "Hello from Open Runtimes 👋", + "source": "en", + "target": "es" +} +``` + +_Example output:_ + +```json +{ + "text": "Hello from Open Runtimes 👋", + "translation": "Saludos desde Open Runtime 👋" +} +``` + +## 📝 Environment Variables + +No environment variables needed. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/translate_text_with_google +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-17.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_ENTRYPOINT=src/index.js -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-17.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit NodeJS runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-17.0). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with NodeJS 17.0. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/node/translate_text_with_google/package-lock.json b/node/translate_text_with_google/package-lock.json new file mode 100644 index 00000000..3520718b --- /dev/null +++ b/node/translate_text_with_google/package-lock.json @@ -0,0 +1,721 @@ +{ + "name": "translate_text_with_google", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "translate_text_with_google", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@vitalets/google-translate-api": "^8.0.0", + "axios": "^0.26.1" + } + }, + "node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@vitalets/google-translate-api": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@vitalets/google-translate-api/-/google-translate-api-8.0.0.tgz", + "integrity": "sha512-CHOi8DRgDAoLlFQy9pm1KHUauIk5ZXys3+Eh0aSYxzJSuxAE7Z2UL8+5MgNdl1oX7t/O7u+SwGhkhu6+U1bNcg==", + "dependencies": { + "configstore": "^5.0.1", + "got": "^9.6.0" + } + }, + "node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, + "node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, + "node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "engines": { + "node": ">=4" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "engines": { + "node": ">=8" + } + } + }, + "dependencies": { + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@vitalets/google-translate-api": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@vitalets/google-translate-api/-/google-translate-api-8.0.0.tgz", + "integrity": "sha512-CHOi8DRgDAoLlFQy9pm1KHUauIk5ZXys3+Eh0aSYxzJSuxAE7Z2UL8+5MgNdl1oX7t/O7u+SwGhkhu6+U1bNcg==", + "requires": { + "configstore": "^5.0.1", + "got": "^9.6.0" + } + }, + "axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "requires": { + "follow-redirects": "^1.14.8" + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + } + } + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "requires": { + "is-obj": "^2.0.0" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "requires": { + "json-buffer": "3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "requires": { + "prepend-http": "^2.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" + } + } +} diff --git a/node/translate_text_with_google/package.json b/node/translate_text_with_google/package.json new file mode 100644 index 00000000..ef1dd88a --- /dev/null +++ b/node/translate_text_with_google/package.json @@ -0,0 +1,15 @@ +{ + "name": "translate_text_with_google", + "version": "1.0.0", + "description": "", + "main": "src/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@vitalets/google-translate-api": "^8.0.0" + } +} diff --git a/node/translate_text_with_google/src/index.js b/node/translate_text_with_google/src/index.js new file mode 100644 index 00000000..fac2759d --- /dev/null +++ b/node/translate_text_with_google/src/index.js @@ -0,0 +1,18 @@ +const translate = require('@vitalets/google-translate-api'); + +module.exports = async function(req, res) { + const { + text, + source, + target + } = JSON.parse(req.payload); + + let translation = await translate(text, {to: target, from: source}).then((data) => { + return data; + }).catch((e) => console.error(e)); + + res.json({ + text: text, + translation: translation.text + }); +}; \ No newline at end of file diff --git a/node/url-shortener/README.md b/node/url-shortener/README.md new file mode 100644 index 00000000..e2247a79 --- /dev/null +++ b/node/url-shortener/README.md @@ -0,0 +1,69 @@ +# 🔗 Shorten a url + +A NodeJS Cloud Function for shorten a url with two providers: + +- [Bitly](https://bitly.com/) +- [Tinyurl](https://tinyurl.com/) + +_Example input:_ + +```json +{ + "provider": "bitly", + "url": "https://www.youtube.com/watch?v=Par3nEq739o" +} +``` + +_Example output:_ + +```json +{ + "success": true, + "url": "https://bit.ly/3dYizF2" +} +``` + +## 📝 Variables + +A single variable: `BITLY_API_KEY` + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/url-shortener +``` + +2. Enter this function folder and build the code: + +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-18.0 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.js --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-18.0 sh /usr/local/src/start.sh +``` + +4. Run the curl function to send request. + +```bash +curl --location --request POST 'http://localhost:3000/' \ +--header 'X-Internal-Challenge: secret-key' \ +--header 'Content-Type: application/json' \ +--data-raw '{"payload": "{\"provider\": \"bitly\", \"url\": \"https://www.youtube.com/watch?v=Par3nEq739o\"}", +"variables": {"BITLY_API_KEY":""}} +' +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit NodeJS runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-17.0). + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with NodeJS 18.0. Other versions may work but are not guarenteed to work as they haven't been tested. diff --git a/node/url-shortener/index.js b/node/url-shortener/index.js new file mode 100644 index 00000000..7098d7da --- /dev/null +++ b/node/url-shortener/index.js @@ -0,0 +1,65 @@ +const bitly = require("bitly") +const tinyurl = require("turl") + +module.exports = async function(req, res) { + const { provider, url } = req.payload + if (!provider) { + return res.json({ + success: false, + message: "The provider is missing." + }) + } + + if (!url) { + return res.json({ + success: false, + message: "The link is missing." + }) + } + + switch (provider) { + case "bitly": { + const bitlyClient = new bitly.BitlyClient(req.variables.BITLY_API_KEY, {}) + bitlyClient.shorten(url) + .then((url) => { + return res.json({ + success: true, + url: url.link + }) + }) + .catch((e) => { + return res.json({ + success: false, + message: e.toString() + }) + }) + + break + } + + case "tinyurl": { + tinyurl.shorten(url) + .then((url) => { + return res.json({ + success: true, + url + }) + }) + .catch((e) => { + return res.json({ + success: false, + message: e.toString() + }) + }) + + break + } + + default: { + res.json({ + success: false, + message: "The provider is invalid." + }) + } + } +} \ No newline at end of file diff --git a/node/url-shortener/package.json b/node/url-shortener/package.json new file mode 100644 index 00000000..d5029597 --- /dev/null +++ b/node/url-shortener/package.json @@ -0,0 +1,10 @@ +{ + "name": "url-shortener", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "bitly": "^7.1.2", + "turl": "^1.1.2" + } +} diff --git a/node/wipe_appwrite_bucket/.gitignore b/node/wipe_appwrite_bucket/.gitignore new file mode 100644 index 00000000..2551987d --- /dev/null +++ b/node/wipe_appwrite_bucket/.gitignore @@ -0,0 +1,149 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/node +# Edit at https://www.toptal.com/developers/gitignore?templates=node + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +### Node Patch ### +# Serverless Webpack directories +.webpack/ + +# Optional stylelint cache + +# SvelteKit build / generate output +.svelte-kit + +# End of https://www.toptal.com/developers/gitignore/api/node + +# OS +## Mac +.DS_Store diff --git a/node/wipe_appwrite_bucket/README.md b/node/wipe_appwrite_bucket/README.md new file mode 100644 index 00000000..b7dfc1ce --- /dev/null +++ b/node/wipe_appwrite_bucket/README.md @@ -0,0 +1,38 @@ +# 🚮 Wipe Appwrite Bucket + +This function deletes every file from a specified Appwrite Storage Bucket. + +## 🤖 Documentation + +_Example input:_ + +```JSON +{"bucketId":"profilePictures"} +``` + +_Example output:_ + +```json +{"success":true} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key + +## 🚀 Deployment + +There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience. + +### Using CLI + +Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`. + +Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy. + +### Manual using tar.gz + +Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `src/index.js`, and upload the file we just generated. diff --git a/node/wipe_appwrite_bucket/package-lock.json b/node/wipe_appwrite_bucket/package-lock.json new file mode 100644 index 00000000..e82c00aa --- /dev/null +++ b/node/wipe_appwrite_bucket/package-lock.json @@ -0,0 +1,175 @@ +{ + "name": "wipe_appwrite_bucket", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "wipe_appwrite_bucket", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "node-appwrite": "^8.0.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-appwrite": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-8.1.0.tgz", + "integrity": "sha512-PWT1rsxI54Vq6y+GDrbNNCO2eQiSkK0Rc/SOLNAFJvLsNmo4FF47ls7+RcEc9fDYYtXPwGt4Wa0vB7udwv92iQ==", + "dependencies": { + "axios": "^0.27.2", + "form-data": "^4.0.0" + } + } + }, + "dependencies": { + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "requires": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "node-appwrite": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-8.1.0.tgz", + "integrity": "sha512-PWT1rsxI54Vq6y+GDrbNNCO2eQiSkK0Rc/SOLNAFJvLsNmo4FF47ls7+RcEc9fDYYtXPwGt4Wa0vB7udwv92iQ==", + "requires": { + "axios": "^0.27.2", + "form-data": "^4.0.0" + } + } + } +} diff --git a/node/wipe_appwrite_bucket/package.json b/node/wipe_appwrite_bucket/package.json new file mode 100644 index 00000000..da7f30f8 --- /dev/null +++ b/node/wipe_appwrite_bucket/package.json @@ -0,0 +1,15 @@ +{ + "name": "wipe_appwrite_bucket", + "version": "1.0.0", + "description": "", + "main": "src/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "node-appwrite": "^8.0.0" + } +} diff --git a/node/wipe_appwrite_bucket/src/index.js b/node/wipe_appwrite_bucket/src/index.js new file mode 100644 index 00000000..7683f48e --- /dev/null +++ b/node/wipe_appwrite_bucket/src/index.js @@ -0,0 +1,103 @@ +const sdk = require("node-appwrite"); + +/* + 'req' variable has: + 'headers' - object with request headers + 'payload' - request body data as a string + 'variables' - object with function variables + + 'res' variable has: + 'send(text, status)' - function to return text response. Status code defaults to 200 + 'json(obj, status)' - function to return JSON response. Status code defaults to 200 + + If an error is thrown, a response with code 500 will be returned. +*/ + +module.exports = async function (req, res) { + const client = new sdk.Client(); + + const storage = new sdk.Storage(client); + + console.log("Starting function"); + + // initialize appwrite client + if ( + !req.variables["APPWRITE_FUNCTION_ENDPOINT"] || + !req.variables["APPWRITE_FUNCTION_API_KEY"] + ) { + console.warn( + "Environment variables are not set. Function cannot use Appwrite SDK." + ); + res.json({ success: false, message: "Environment variables are not set." }); + return; + } else { + client + .setEndpoint(req.variables["APPWRITE_FUNCTION_ENDPOINT"]) + .setProject(req.variables["APPWRITE_FUNCTION_PROJECT_ID"]) + .setKey(req.variables["APPWRITE_FUNCTION_API_KEY"]); + } + + // parse payload + const payload = req.payload; + const { bucketId } = JSON.parse(payload); + if (!bucketId) { + console.warn("Bucket ID is not set."); + res.json({ success: false, message: "Bucket ID is not set." }); + return; + } + + // get files + let filesFound = true; + let offset = 0; + let files = []; + + console.log("Getting files from bucket: " + bucketId); + while (filesFound) { + try { + // fetch files from appwrite + const sto = await storage.listFiles(bucketId, [ + sdk.Query.limit(50), + sdk.Query.offset(offset), + ]); + if (sto.files.length && sto.files.length > 0) { + // some files were found, save them for deletion + files = files.concat(sto.files); + + offset += sto.files.length; + } else { + // no more files were found + filesFound = false; + } + } catch (err) { + console.warn(err); + res.json({ success: false, message: "Bucket not found." }); + return; + } + } + + console.log(`Found ${files.length} files.`); + if (files.length === 0) { + console.log("No files found."); + res.json({ success: false, message: "No files found." }); + return; + } + + // add all deleteFile() requests to a list so we can run them all at once later + const deleteStack = []; + for (const file of files) { + deleteStack.push(storage.deleteFile(bucketId, file.$id)); + } + + const results = await Promise.allSettled(deleteStack); + for (const result of results) { + if (result.status === "rejected") { + console.warn(result.reason); + res.json({ success: false, message: "Failed to delete files." }); + return; + } + } + + res.json({ + success: true, + }); +}; diff --git a/node/wipe_appwrite_collection/README.md b/node/wipe_appwrite_collection/README.md new file mode 100644 index 00000000..0d67d258 --- /dev/null +++ b/node/wipe_appwrite_collection/README.md @@ -0,0 +1,89 @@ +# Wipe an Appwrite collection + +A Node Cloud Function that wipes out all the documents inside a collection. + +_Example input:_ + +```json +{ + "databaseId": "stage", + "collectionId": "profiles" +} +``` + +_Example output (success):_ + +```json +{ + "success": true, + "sum": 2 +} +``` + +_Example output (failure):_ + +```json +{ + "success": false, + "message": "Collection not found." +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of your Appwrite server +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key +- **APPWRITE_FUNCTION_PROJECT_ID** - Appwrite project ID. If running on Appwrite, this variable is provided automatically. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/wipe_appwrite_collection +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:v2-18.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.js --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/node:v2-18.0 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Node runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/node-18.0). + +4. Execute function: + +``` +curl http://localhost:3000/ -d '{"variables":{"APPWRITE_FUNCTION_ENDPOINT":"YOUR_ENDPOINT","APPWRITE_FUNCTION_PROJECT_ID":"YOUR_PROJECT_ID","APPWRITE_FUNCTION_API_KEY":"YOUR_API_KEY"},"payload":"{\"databaseId\":\"stage\",\"collectionId\":\"profiles\"}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +## 🚀 Deployment using Appwrite + +1. Clone this repository, and enter this function folder: +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd node/wipe_appwrite_collection +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/node:18.0 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Add a new function to appwrite server. Upload the code.tar.gz file manually. Set index.js as entrypoint. + +4. Execute the function. Pass collection ID and database ID as shown in example input and execute the function. + + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Node 18.0. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/node/wipe_appwrite_collection/index.js b/node/wipe_appwrite_collection/index.js new file mode 100644 index 00000000..6509aa40 --- /dev/null +++ b/node/wipe_appwrite_collection/index.js @@ -0,0 +1,46 @@ +const sdk = require('node-appwrite'); + +module.exports = async function (req, res) { + const client = new sdk.Client(); + const databases = new sdk.Databases(client); + + if(!req.variables["APPWRITE_FUNCTION_ENDPOINT"] || !req.variables["APPWRITE_FUNCTION_API_KEY"] || !req.variables["APPWRITE_FUNCTION_PROJECT_ID"]) { + res.json({success: false, message: "Variables missing."}); + return; + } + + client + .setEndpoint(req.variables["APPWRITE_FUNCTION_ENDPOINT"]) + .setProject(req.variables["APPWRITE_FUNCTION_PROJECT_ID"]) + .setKey(req.variables["APPWRITE_FUNCTION_API_KEY"]); + + try{ + const payload = JSON.parse(req.payload ?? '{}'); + if(!payload.databaseId || !payload.collectionId) { + res.json({success: false, message: "Invalid payload."}); + return; + } + + let sum = 0; + let done = false; + + while(!done) { + const response = await databases.listDocuments(payload.databaseId, payload.collectionId); + const documents = response.documents; + + for(const document of documents) { + await databases.deleteDocument(payload.databaseId, payload.collectionId, document.$id); + sum++; + } + + if(documents.length === 0) { + done = true; + } + } + + res.send({success: true, sum: sum}); + } catch(e) { + res.json({success: false, message: "Unexpected error: " + e}); + } + +}; diff --git a/node/wipe_appwrite_collection/package-lock.json b/node/wipe_appwrite_collection/package-lock.json new file mode 100644 index 00000000..64f92249 --- /dev/null +++ b/node/wipe_appwrite_collection/package-lock.json @@ -0,0 +1,72 @@ +{ + "name": "wipe_appwrite_collection", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "requires": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "node-appwrite": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-8.1.0.tgz", + "integrity": "sha512-PWT1rsxI54Vq6y+GDrbNNCO2eQiSkK0Rc/SOLNAFJvLsNmo4FF47ls7+RcEc9fDYYtXPwGt4Wa0vB7udwv92iQ==", + "requires": { + "axios": "^0.27.2", + "form-data": "^4.0.0" + } + } + } +} diff --git a/node/wipe_appwrite_collection/package.json b/node/wipe_appwrite_collection/package.json new file mode 100644 index 00000000..74deeeb6 --- /dev/null +++ b/node/wipe_appwrite_collection/package.json @@ -0,0 +1,14 @@ +{ + "name": "wipe_appwrite_collection", + "version": "1.0.0", + "description": "Delete all documents from a collection", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Kritika Sharma", + "license": "ISC", + "dependencies": { + "node-appwrite": "^8.1.0" + } +} diff --git a/php/.gitignore b/php/.gitignore new file mode 100644 index 00000000..ae18c01d --- /dev/null +++ b/php/.gitignore @@ -0,0 +1,477 @@ +# PHP Gitignore from: https://gist.githubusercontent.com/Yousha/a5514afd6cda8afba800f5af9f7115b4/raw/a27554246db50778257d079a89705e79f8488151/.gitignore + +##### Windows +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +##### Linux +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +##### MacOS +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +##### Backup +*.bak +*.gho +*.ori +*.orig +*.tmp + +##### GPG +secring.* + +##### Dropbox +# Dropbox settings and caches +.dropbox +.dropbox.attr +.dropbox.cache + +##### SynopsysVCS +# Waveform formats +*.vcd +*.vpd +*.evcd +*.fsdb + +# Default name of the simulation executable. A different name can be +# specified with this switch (the associated daidir database name is +# also taken from here): -o / +simv + +# Generated for Verilog and VHDL top configs +simv.daidir/ +simv.db.dir/ + +# Infrastructure necessary to co-simulate SystemC models with +# Verilog/VHDL models. An alternate directory may be specified with this +# switch: -Mdir= +csrc/ + +# Log file - the following switch allows to specify the file that will be +# used to write all messages from simulation: -l +*.log + +# Coverage results (generated with urg) and database location. The +# following switch can also be used: urg -dir .vdb +simv.vdb/ +urgReport/ + +# DVE and UCLI related files. +DVEfiles/ +ucli.key + +# When the design is elaborated for DirectC, the following file is created +# with declarations for C/C++ functions. +vc_hdrs.h + +##### SVN +.svn/ + +##### Mercurial +.hg/ +.hgignore +.hgsigs +.hgsub +.hgsubstate +.hgtags + +##### Bazaar +.bzr/ +.bzrignore + +##### CVS +/CVS/* +**/CVS/* +.cvsignore +*/.cvsignore + +##### TortoiseGit +# Project-level settings +/.tgitconfig + +##### PuTTY +# Private key +*.ppk + +##### Vim +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +##### Emacs +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +# directory configuration +.dir-locals.el + +# network security +/network-security.data + +##### SublimeText +# Cache files for Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# Workspace files are user-specific +*.sublime-workspace + +# Project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using Sublime Text +# *.sublime-project + +# SFTP configuration file +sftp-config.json +sftp-config-alt*.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + +##### Notepad++ +# Notepad++ backups # +*.bak + +##### TextMate +*.tmproj +*.tmproject +tmtags + +##### VisualStudioCode +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +##### NetBeans +**/nbproject/private/ +**/nbproject/Makefile-*.mk +**/nbproject/Package-*.bash +build/ +nbbuild/ +dist/ +nbdist/ +.nb-gradle/ + +##### JetBrains +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +##### Eclipse +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ +.apt_generated_test/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +# Uncomment this line if you wish to ignore the project description file. +# Typically, this file would be tracked if it contains build/dependency configurations: +#.project + +##### Dreamweaver +# DW Dreamweaver added files +_notes +_compareTemp +configs/ +dwsync.xml +dw_php_codehinting.config +*.mno + +##### CodeKit +# General CodeKit files to ignore +config.codekit +config.codekit3 +/min + +##### Gradle +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties + +##### Composer +composer.phar +/vendor/ +vendor + +# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control +# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file +composer.lock + +##### PHP CodeSniffer +# gitignore for the PHP Codesniffer framework +# website: https://github.com/squizlabs/PHP_CodeSniffer +# +# Recommended template: PHP.gitignore + +/wpcs/* + +##### SASS +.sass-cache/ +*.css.map +*.sass.map +*.scss.map diff --git a/php/convert-phone-number-to-country-name/README.md b/php/convert-phone-number-to-country-name/README.md new file mode 100644 index 00000000..eaefdd63 --- /dev/null +++ b/php/convert-phone-number-to-country-name/README.md @@ -0,0 +1,60 @@ +# 📱 Validate phone number and get it's country information + +A PHP Cloud Function that figures out country in which a phone number is registered. + +_Example input:_ + +```json +{ + "phoneNumber": "+421957215740" +} +``` + +> Function can also accept phone numbers with spaces, for instance `+421 957 215 740`. + + +_Example output:_ + + +```json +{ + "phoneNumber": "+421957215740", + "phonePrefix": "+421", + "countryCode": "SK", + "countryName": "Slovakia" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of your Appwrite server +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key +- **APPWRITE_FUNCTION_PROJECT_ID** - Appwrite project ID. If running on Appwrite, this variable is provided automatically. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd php/convert_phone_number_to_country_name +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/php:v2-8.1 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.php --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/php:v2-8.1 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit PHP runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/php-8.1). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with PHP 8.1. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/php/convert-phone-number-to-country-name/composer.json b/php/convert-phone-number-to-country-name/composer.json new file mode 100644 index 00000000..002e86f1 --- /dev/null +++ b/php/convert-phone-number-to-country-name/composer.json @@ -0,0 +1,11 @@ +{ + "name": "opr/convert_phone_number_to_country_name", + "description": "", + "type": "library", + "license": "ISC", + "authors": [], + "require": { + "php": ">=8.0.0", + "appwrite/appwrite": "4.0.*" + } +} \ No newline at end of file diff --git a/php/convert-phone-number-to-country-name/index.php b/php/convert-phone-number-to-country-name/index.php new file mode 100644 index 00000000..3a4c1373 --- /dev/null +++ b/php/convert-phone-number-to-country-name/index.php @@ -0,0 +1,75 @@ +setEndpoint($req['variables']['APPWRITE_FUNCTION_ENDPOINT']) + ->setProject($req['variables']['APPWRITE_FUNCTION_PROJECT_ID']) + ->setKey($req['variables']['APPWRITE_FUNCTION_API_KEY']); + + // Fetch and store phone number prefixes + $serverResponse = $locale->getCountriesPhones(); + $phonePrefixList = $serverResponse['phones']; + } + + // Get phone prefix + $phonePrefix = \current(\array_filter($phonePrefixList, fn($prefix) => \str_starts_with($phoneNumber, $prefix['code']))); + + if(empty($phonePrefix)) { + throw new \Exception('Invalid phone number.'); + } + + // Return phone number prefix + $res->json([ + 'phoneNumber' => $phoneNumber, + 'phonePrefix' => $phonePrefix['code'], + 'countryCode' => $phonePrefix['countryCode'], + 'countryName' => $phonePrefix['countryName'] + ]); +}; \ No newline at end of file diff --git a/php/deepgram-audio-summary/README.md b/php/deepgram-audio-summary/README.md new file mode 100644 index 00000000..960b1efb --- /dev/null +++ b/php/deepgram-audio-summary/README.md @@ -0,0 +1,62 @@ + +# ⚡ deepgramAudioSummary() + +A Php Cloud Function for audio summary using [Deepgram](https://deepgram.com/) + +_Example function payload:_ + +```json +{ + "fileUrl":"https://rawcdn.githack.com/deepgram-devs/summary-audio/62fc7769d6e2bf38e420ee5224060922af4546f7/deepgram.mp3" +} +``` + +_Successful function response::_ + +```json +{ "deepgramData": {}, "success": true } +``` + +_Error function response:_ + +```json +{ "message": "error message", "success": false } +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +**DEEPGRAM_API_KEY** - Your Deepgram API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd php/deepgram-audio-summary +``` + +2. Enter this function folder and build the code: + +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/php:v2-8.1 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.php --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/php:v2-8.1 sh /usr/local/src/start.sh +``` + +> Make sure to replace `YOUR_API_KEY` without your key. + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit PHP runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/php-8.1). + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with PHP 2.8.1. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/php/deepgram-audio-summary/index.php b/php/deepgram-audio-summary/index.php new file mode 100644 index 00000000..70b79bf3 --- /dev/null +++ b/php/deepgram-audio-summary/index.php @@ -0,0 +1,55 @@ +json([ + 'success' => false, + 'message' => 'Cannot read payload.' + ]); + return; + } + + $secretKey = $req['variables']['DEEPGRAM_API_KEY']; + $request = "https://api.deepgram.com/v1/listen?summarize=true&punctuate=true"; + $ch = curl_init($request); + + $payload = json_encode( array( "url" => $fileUrl ) ); + curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); + curl_setopt($ch, CURLOPT_HTTPHEADER, array( + "Content-Type: application/json", + "Authorization: Token " . $secretKey + )); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + + $response = curl_exec($ch); + + if (curl_errno($ch)) { + $res->json([ + 'success' => false, + 'message' => 'Unexpected request error.' + ]); + return; + } else { + $resultStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); + if ($resultStatus != 200) { + $res->json([ + 'success' => false, + 'message' => 'HTTP ' . $resultStatus . ' error.' + ]); + return; + } + } + + curl_close($ch); + + $res->json([ + 'success' => true, + 'deepgramData' => \json_decode($response) + ]); +} + +?> diff --git a/php/deepgram_language_detection/README.md b/php/deepgram_language_detection/README.md new file mode 100644 index 00000000..25d548a2 --- /dev/null +++ b/php/deepgram_language_detection/README.md @@ -0,0 +1,61 @@ +# deepgramLanguageDetection() + +A PHP Cloud Function for detecting language from audio using [Deepgram](https://deepgram.com/) + +_Example function payload:_ + +```json +{ + "fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Example successful function response:_ + +```json +{ + "success": true, + "deepgramData": {} +} +``` + +_Example error function response:_ + +```json +{ + "success": false, + "message": "Please provide a valid file URL." +} +``` + +## 📝 Variables + +List of variables used by this cloud function: + +**DEEPGRAM_API_KEY** - Your Deepgram API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd php/deepgram_language_detection +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/php:v2-8.1 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.php --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/php:v2-8.1 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit PHP runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/php-8.1). + +## 📝 Notes +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with PHP 8.1. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/php/deepgram_language_detection/composer.json b/php/deepgram_language_detection/composer.json new file mode 100644 index 00000000..ef164e86 --- /dev/null +++ b/php/deepgram_language_detection/composer.json @@ -0,0 +1,10 @@ +{ + "name": "opr/deepgram_language_detection", + "description": "", + "type": "library", + "license": "ISC", + "authors": [], + "require": { + "php": ">=8.0.0" + } +} \ No newline at end of file diff --git a/php/deepgram_language_detection/index.php b/php/deepgram_language_detection/index.php new file mode 100644 index 00000000..5f41deca --- /dev/null +++ b/php/deepgram_language_detection/index.php @@ -0,0 +1,56 @@ +json([ + 'success' => false, + 'message' => 'Please provide all required environment variables.', + ]); + } + + // Make sure the payload is populated + try { + $payload = \json_decode($req['payload'], true); + $file_url = \trim($payload['fileUrl']); + } catch(\Exception $err) { + $res->json([ + 'success' => false, + 'message' => 'Payload is invalid with error ' . $err->getMessage(), + ]); + } + + if(empty($file_url)) { + $res->json([ + 'success' => false, + 'message' => 'Invalid url. ' . $file_url, + ]); + } + + $ch = \curl_init("https://api.deepgram.com/v1/listen?detect_language=true&punctuate=true"); + // Authorization: Token + \curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: Token " . $req['variables']['DEEPGRAM_API_KEY'], "Content-Type: application/json")); + \curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + \curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(array("url" => $file_url))); + + $response = \curl_exec($ch); + $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + + if ($response !== false && $httpcode === 200) { + $return = [ + 'success' => true, + 'deepgramData' => \json_decode($response, true), + ]; + } else { + $return = [ + 'success' => false, + 'message' => 'HTTP code: ' . $httpcode . ' Body: ' . $response, + ]; + } + \curl_close($ch); + + $res->json($return); +}; \ No newline at end of file diff --git a/php/deepgram_transcribe_audio/README.md b/php/deepgram_transcribe_audio/README.md new file mode 100644 index 00000000..d24cfa8d --- /dev/null +++ b/php/deepgram_transcribe_audio/README.md @@ -0,0 +1,59 @@ +# 📷 Transcribe audio into written text using Deepgram API + +A PHP Function to transform audio into written text from an URL. + +_Example input:_ + +```json +{ + "payload": { + "fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav" + }, + "variables": { + "DEEPGRAM_API_SECRET_KEY": "YOUR_PERSONAL_DEEPGRAM_API_SECRET_KEY" + } +} +``` + +_Example output:_ + +```json +{ + "success": true, + "deepgramData": "DEEPGRAM_DATA" +} +``` + +## 📝 Variables + +List of variables used by this cloud function: + +**DEEPGRAM_API_SECRET_KEY** - Your Deepgram secret API key. +Details are under link: [Deepgram_getting_started](https://developers.deepgram.com/documentation/getting-started/) + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd php/deepgram_transcribe_audio +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/php:v2-8.1 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.php --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/php:v2-8.1 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit PHP runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/php-8.1). + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with PHP 8.1. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/php/deepgram_transcribe_audio/composer.json b/php/deepgram_transcribe_audio/composer.json new file mode 100644 index 00000000..7d57ef19 --- /dev/null +++ b/php/deepgram_transcribe_audio/composer.json @@ -0,0 +1,11 @@ +{ + "name": "opr/deepgram_transcribe_audio", + "description": "", + "type": "library", + "license": "ISC", + "authors": [], + "require": { + "php": ">=8.0.0", + "guzzlehttp/guzzle": "^7.0" + } +} diff --git a/php/deepgram_transcribe_audio/index.php b/php/deepgram_transcribe_audio/index.php new file mode 100644 index 00000000..d9fb3a21 --- /dev/null +++ b/php/deepgram_transcribe_audio/index.php @@ -0,0 +1,73 @@ +json([ + 'success' => false, + 'message' => 'Please provide a valid file URL.' + ]); + } + if ( + !isset($req['variables']['DEEPGRAM_API_SECRET_KEY']) || + empty($deepgramSecretApiKey = \trim($req['variables']['DEEPGRAM_API_SECRET_KEY'])) + ) { + return $res->json([ + 'success' => false, + 'message' => 'Please provide valid deepgram api secret key under variables.' + ]); + } + + $extension = pathinfo($fileUrl, PATHINFO_EXTENSION); + + if ($extension !== 'wav') { + return $res->json([ + 'success' => false, + 'message' => 'Please provide valid file url extension. This should be wav.' + ]); + } + + $client = new Client(); + $headers = [ + 'Authorization' => 'Token ' . $deepgramSecretApiKey, + 'Content-Type' => 'application/json' + ]; + $body = json_encode([ + 'url' => $fileUrl + ]); + try { + $response = $client->request('POST', 'https://api.deepgram.com/v1/listen', [ + 'body' => $body, + 'headers' => $headers + ]); + } catch(\Exception $err) { + return $res->json([ + 'success' => false, + 'message' => $err->getMessage() + ]); + } + + if ($response->getStatusCode() === 200) { + $deepgramData = $response->getBody()->getContents(); + $res->json([ + 'success' => true, + 'deepgramData' => \json_decode($deepgramData) + ]); + } else { + $res->json([ + 'success' => false, + 'message' => $response->getBody()->getContents() + ]); + } +} +?> \ No newline at end of file diff --git a/php/generate-short-url/README.md b/php/generate-short-url/README.md new file mode 100644 index 00000000..8cb8a462 --- /dev/null +++ b/php/generate-short-url/README.md @@ -0,0 +1,94 @@ +# Generate short URL + +A PHP Cloud Function that for URL shortener service name and URL returns shorten link. + +Available services: + +* [Bitly](https://bitly.com) +* [Tinyurl](https://tinyurl.com/) + +_Example input:_ + +```json +{ + "provider": "bitly", + "url": "https://appwrite.io/" +} +``` + +```json +{ + "provider": "tinyurl", + "url": "https://facebook.com/" +} +``` + +_Example output:_ + +```json +{ + "success": true, + "url": "https://bit.ly/3SDBqnK" +} +``` + +```json +{ + "success": true, + "url": "https://tinyurl.com/47ksc2ud" +} +``` + +```json +{ + "success": false, + "message": "Provided unsupported provider name. [bitly, tinyurl]" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **API_BITLY_AUTHORIZATION_TOKEN** - Bitly authorization token +- **API_TINYURL_AUTHORIZATION_TOKEN** - Tinyurl authorization token + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd php/generate-short-url +``` + +2. Enter this function folder and build the code: + +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/php:v2-8.1 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.php --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/php:v2-8.1 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate +authorization headers. To learn more about runtime, you can visit PHP +runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/php-8.1). + +4. Execute function: + +``` +curl http://localhost:3000/ -d '{"variables":{"API_BITLY_AUTHORIZATION_TOKEN":"[YOUR_API_KEY]"},"payload": "{\"url\":\"https://appwrite.io/\",\"provider\":\"bitly\"}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it + in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with PHP 8.1. Other versions may work but are not guaranteed to work as they haven't been + tested. diff --git a/php/generate-short-url/index.php b/php/generate-short-url/index.php new file mode 100644 index 00000000..edcfdc76 --- /dev/null +++ b/php/generate-short-url/index.php @@ -0,0 +1,77 @@ +json(['success' => false, 'message' => 'Provider param is required. [bitly, tinyurl]'], 400); + return; + } + + if (false === in_array($chosenProvider, ['bitly', 'tinyurl'])) { + $res->json(['success' => false, 'message' => 'Provided unsupported provider name. [bitly, tinyurl]'], 400); + return; + } + + // Prepare request data + switch ($chosenProvider) { + case 'bitly': + $apiUrl = 'https://api-ssl.bitly.com/v4/shorten'; + $authorizationToken = $req['variables']['API_BITLY_AUTHORIZATION_TOKEN'] ?? null; + $data = json_encode(['long_url' => $longUrl]); + break; + case 'tinyurl': + $apiUrl = 'https://api.tinyurl.com/create'; + $authorizationToken = $req['variables']['API_TINYURL_AUTHORIZATION_TOKEN'] ?? null; + $data = json_encode(['url' => $longUrl]); + break; + default: + $apiUrl = null; + $authorizationToken = null; + $data = null; + } + + if (null === $authorizationToken) { + $res->json(['success' => false, 'message' => 'Authorization token not set in variables'], 401); + return; + } + + // Make request + $curl = curl_init(); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_URL, $apiUrl); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_HTTPHEADER, [ + 'Content-Type: application/json', + sprintf('Authorization: Bearer %s', $authorizationToken) + ]); + + $apiResponse = json_decode(curl_exec($curl), true); + curl_close($curl); + + // Extract request result + switch ($chosenProvider) { + case 'bitly': + $shortenUrl = $apiResponse['link'] ?? null; + $errorMessage = $apiResponse['message'] ?? null; + break; + case 'tinyurl': + $shortenUrl = $apiResponse['data']['tiny_url'] ?? null; + $errorMessage = $apiResponse['errors'][0] ?? null; + break; + default: + $shortenUrl = null; + $errorMessage = 'Error.'; + } + + if (null === $shortenUrl) { + $res->json(['success' => false, 'message' => $errorMessage], 401); + return; + } + + $res->json(['success' => true, 'url' => $shortenUrl]); +}; diff --git a/php/generate_giphy_gif/README.md b/php/generate_giphy_gif/README.md new file mode 100644 index 00000000..e6e82fe9 --- /dev/null +++ b/php/generate_giphy_gif/README.md @@ -0,0 +1,53 @@ +# 🖼️ Get Giphy GIF + +A PHP Cloud Function for generating Giphy GIF from the [Giphy API](https://developers.giphy.com/docs/api#quick-start-guide). + +_Example input:_ + +```json +{ + "search": "good morning" +} +``` + +_Example output:_ + + +```json +{ + "search": "good morning", + "gif": "https://giphy.com/gifs/text-gif-sticker-brittdoesdesign-MS9Yq6Y718CSiDTxR5" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +**GIPHY_API_KEY** - Your Giphy API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd php/generate_giphy_gif +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/php:v2-8.1 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.php --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/php:v2-8.1 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit PHP runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/php-8.1). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with PHP 8.1. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/php/generate_giphy_gif/composer.json b/php/generate_giphy_gif/composer.json new file mode 100644 index 00000000..5bf275dc --- /dev/null +++ b/php/generate_giphy_gif/composer.json @@ -0,0 +1,10 @@ +{ + "name": "opr/generate_giphy_gif", + "description": "", + "type": "library", + "license": "ISC", + "authors": [], + "require": { + "php": ">=8.0.0" + } +} \ No newline at end of file diff --git a/php/generate_giphy_gif/index.php b/php/generate_giphy_gif/index.php new file mode 100644 index 00000000..39dc0ffc --- /dev/null +++ b/php/generate_giphy_gif/index.php @@ -0,0 +1,37 @@ +json([ + 'search' => $search, + 'gif' => $response["data"][0]['url'], + ]); +}; diff --git a/php/object_detection/README.md b/php/object_detection/README.md new file mode 100644 index 00000000..04927bd1 --- /dev/null +++ b/php/object_detection/README.md @@ -0,0 +1,59 @@ +# 📷 Object Detection using Cloudmersive Vision API + +A PHP Cloud Function for object detection from an image URL. + +_Example input:_ + +```json +{ + "url": "https://picsum.photos/seed/open___runtimes/1000/1000" +} +``` + +_Example output:_ + + +```json +{ + "ObjectClassName": "cake", + "Score": 0.7977721691131592, + "X": 21, + "Y": 5, + "Width": 494, + "Height": 333 +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +**CLOUDMERSIVE_API_KEY** - Your Cloudmersive API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd php/object_detection +``` + +2. Enter this function folder and build the code: + +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/php:v2-8.1 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.php --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/php:v2-8.1 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit PHP runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/php-8.1). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with PHP 8.1. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/php/object_detection/composer.json b/php/object_detection/composer.json new file mode 100644 index 00000000..7322fd08 --- /dev/null +++ b/php/object_detection/composer.json @@ -0,0 +1,10 @@ +{ + "name": "opr/object_detection", + "description": "", + "type": "library", + "license": "ISC", + "authors": [], + "require": { + "php": ">=8.0.0" + } +} \ No newline at end of file diff --git a/php/object_detection/index.php b/php/object_detection/index.php new file mode 100644 index 00000000..90bf4400 --- /dev/null +++ b/php/object_detection/index.php @@ -0,0 +1,52 @@ + $image, + ]); + \curl_setopt($ch, CURLOPT_HTTPHEADER, [ + 'Apikey: ' . $req['variables']['CLOUDMERSIVE_API_KEY'], + ]); + + $response = \json_decode(\curl_exec($ch), true); + \curl_close($ch); + + // Return phone number prefix + $res->json($response['Objects']); +}; diff --git a/php/send-http-request/README.md b/php/send-http-request/README.md new file mode 100644 index 00000000..172d13ad --- /dev/null +++ b/php/send-http-request/README.md @@ -0,0 +1,54 @@ +# Function to send request and get response + +A PHP Cloud Function for getting the response from request. + +_Example input:_ + +```json +{ + "url": "https://demo.appwrite.io/v1/locale/countries/eu", + "method": "GET", + "headers": { + "x-client-version": "1.0.0" + }, + "body": "" +} +``` + +_Example output:_ + + +```json +{ + "success": true, + "response": { + "headers": "{headers_content}", + "code": 200, + "body": "{body_content}" + } +} +``` + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd php/send-http-request +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/php:v2-8.1 sh /usr/local/src/build.sh +``` + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.php --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/php:v2-8.1 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `GET` request with appropriate authorization headers. To learn more about runtime, you can visit PHP runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/php-8.1). + +## 📝 Notes +- This example is compatible with PHP 8.1. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/php/send-http-request/composer.json b/php/send-http-request/composer.json new file mode 100644 index 00000000..c865dced --- /dev/null +++ b/php/send-http-request/composer.json @@ -0,0 +1,11 @@ +{ + "name": "opr/send-http-request", + "description": "", + "type": "library", + "license": "ISC", + "authors": [], + "require": { + "php": ">=8.0.0", + "guzzlehttp/guzzle": "^7.0" + } +} diff --git a/php/send-http-request/index.php b/php/send-http-request/index.php new file mode 100644 index 00000000..d2e3f72d --- /dev/null +++ b/php/send-http-request/index.php @@ -0,0 +1,51 @@ +json([ + 'success' => false, + 'message' => 'Payload is invalid: ' . $err->getMessage() + ]); + return; + } + + $client = new Client(); + $response = $client->request($method, $url, [ + 'body' => $body, + 'headers' => $headers + ]); + + if ($response->getStatusCode() >= 200 && $response->getStatusCode() < 300) { + $res->json([ + 'success' => true, + 'response' => [ + 'headers' => $response->getHeaders(), + 'code' => $response->getStatusCode(), + 'body' => $response->getBody()->getContents() + ] + ]); + return; + } + + $res->json([ + 'success' => false, + 'message' => $response->getBody()->getContents() + ]); +} +?> \ No newline at end of file diff --git a/php/send_message/README.md b/php/send_message/README.md new file mode 100644 index 00000000..281229ac --- /dev/null +++ b/php/send_message/README.md @@ -0,0 +1,113 @@ +# 📬 Send Message using a specific channel. + +An PHP Cloud Function sending a message using a specific channel. + +This example includes the following channels, `SMS`, `Email`, `Twitter`, and `Discord`. + +*Example input: (SMS)* + +```json +{ + "type": "SMS", + "receiver": "+123456789", + "message": "Programming is fun!" +} +``` + +*Example input: (Email)* + +```json +{ + "type": "Email", + "receiver": "user@example.app", + "subject": "Welcome to the work of Cloud Functions", + "message": "Email sent from a PHP Cloud Function. 👀" +} +``` + +*Example input: (Twitter)* + +```json +{ + "type": "Twitter", + "message": "Tweet sent from a PHP Cloud Function. 🐦" +} +``` + +*Example input: (Discord)* + +```json +{ + "type": "Discord", + "message": "Message sent from a PHP Cloud Function. 😏" +} +``` + +*Example output: (Success)* + +```json +{ + "success": true +} +``` + +*Example output: (Failure)* + +```json +{ + "success": false, + "message": "Receiver is not a valid email." +} +``` + +## 📝 Variables + +List of variables used by this cloud function: + +#### Mailgun + +- **MAILGUN_API_KEY** - API Key for Mailgun +- **MAILGUN_DOMAIN** - Domain Name from Mailgun + +#### Discord + +- **DISCORD_WEBHOOK_URL** - Webhook URL for Discord + +#### Twilio + +- **TWILIO_ACCOUNT_SID** - Acount SID from Twilio +- **TWILIO_AUTH_TOKEN** - Auth Token from Twilio +- **TWILIO_SENDER** - Sender Phone Number from Twilio + +#### Twitter + +- **TWITTER_API_KEY** - API Key for Twitter +- **TWITTER_API_KEY_SECRET** - API Key Secret for Twitter +- **TWITTER_ACCESS_TOKEN** - Access Token from Twitter +- **TWITTER_ACCESS_KEY_SECRET** - Access Token Secret from Twitter + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd php/send_message +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/php:v2-8.1 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.php --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/php:v2-8.1 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit PHP runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/php-8.1). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with PHP 8.1. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/php/send_message/composer.json b/php/send_message/composer.json new file mode 100644 index 00000000..34a7f63c --- /dev/null +++ b/php/send_message/composer.json @@ -0,0 +1,11 @@ +{ + "name": "opr/send-message", + "description": "An example PHP Cloud Function sending a message using a specific channel to a receiver", + "type": "project", + "require": { + "guzzlehttp/guzzle": "^7.5", + "guzzlehttp/oauth-subscriber": "^0.6.0" + }, + "license": "ISC", + "minimum-stability": "stable" +} diff --git a/php/send_message/index.php b/php/send_message/index.php new file mode 100644 index 00000000..222d51a1 --- /dev/null +++ b/php/send_message/index.php @@ -0,0 +1,41 @@ +json([ + 'status' => false, + 'message' => $e->getMessage(), + ]); + }; + + if (!array_key_exists('type', $payload)) { + return $res->json([ + 'status' => false, + 'message' => "Invalid payload, object 'type' is required." + ]); + } + + $notificator = match (strtolower($payload['type'])) { + 'sms' => new SMSChannel($req['variables']), + 'email' => new EmailChannel($req['variables']), + 'twitter' => new TwitterChannel($req['variables']), + 'discord' => new DiscordChannel($req['variables']), + default => new NullChannel, + }; + + $res->json( + json: $notificator->send( + payload: $payload, + ), + ); +}; diff --git a/php/send_message/src/Contracts/Channel.php b/php/send_message/src/Contracts/Channel.php new file mode 100644 index 00000000..443cdffd --- /dev/null +++ b/php/send_message/src/Contracts/Channel.php @@ -0,0 +1,6 @@ +client = new Client( + config: [ + 'headers' => [ + 'content-type' => 'application/json', + ] + ] + ); + } + + public function hasEnvironmentVariables(): string + { + return array_key_exists('DISCORD_WEBHOOK_URL', $this->environment); + } + + public function getEndpoint(): string + { + return $this->environment['DISCORD_WEBHOOK_URL']; + } + + public function send(array $payload): array + { + if (! $this->hasEnvironmentVariables()) { + return [ + 'success' => false, + 'message' => 'Environment variables are not set.', + ]; + } + + try { + $response = $this->client->send( + request: new Request( + method: 'POST', + uri: $this->getEndpoint(), + ), + options: [ + RequestOptions::JSON => [ + 'content' => $payload['message'], + ], + ], + ); + } catch (\Exception $e) { + return [ + 'success' => false, + 'message' => $e->getMessage(), + ]; + } + + return [ + 'success' => (200 <= $response->getStatusCode() && $response->getStatusCode() < 300), + ]; + } +} diff --git a/php/send_message/src/EmailChannel.php b/php/send_message/src/EmailChannel.php new file mode 100644 index 00000000..849d7580 --- /dev/null +++ b/php/send_message/src/EmailChannel.php @@ -0,0 +1,87 @@ +client = new Client; + } + + public function hasEnvironmentVariables(): string + { + return array_key_exists('MAILGUN_API_KEY', $this->environment) + && array_key_exists('MAILGUN_DOMAIN', $this->environment); + } + + public function getApiKey(): string + { + return $this->environment['MAILGUN_API_KEY']; + } + + public function getDomain(): string + { + return $this->environment['MAILGUN_DOMAIN']; + } + + public function send(array $payload): array + { + if (! $this->hasEnvironmentVariables()) { + return [ + 'success' => false, + 'message' => 'Environment variables are not set.', + ]; + } + + if (! $this->validate( + validator: new EmailValidator, + receiver: $payload['receiver'], + )) { + return [ + 'success' => false, + 'message' => 'Receiver is not a valid email.', + ]; + } + + try { + $response = $this->client->send( + request: new Request( + method: 'POST', + uri: sprintf('https://api.mailgun.net/v3/%s/messages', $this->getDomain()), + headers: [ + 'authorization' => sprintf('Basic %s', base64_encode(sprintf('api:%s', $this->getApiKey()))), + ] + ), + options: [ + RequestOptions::FORM_PARAMS => [ + 'from' => sprintf('SendMessage ', $this->getDomain()), + 'to' => $payload['receiver'], + 'subject' => $payload['subject'], + 'text' => $payload['message'], + ], + ], + ); + } catch (\Exception $e) { + return [ + 'success' => false, + 'message' => $e->getMessage(), + ]; + } + + return [ + 'success' => (200 <= $response->getStatusCode() && $response->getStatusCode() < 300), + ]; + } +} diff --git a/php/send_message/src/NullChannel.php b/php/send_message/src/NullChannel.php new file mode 100644 index 00000000..f888ed1a --- /dev/null +++ b/php/send_message/src/NullChannel.php @@ -0,0 +1,14 @@ + false, + 'message' => 'No channel type found.', + ]; + } +} diff --git a/php/send_message/src/SMSChannel.php b/php/send_message/src/SMSChannel.php new file mode 100644 index 00000000..809d8ad9 --- /dev/null +++ b/php/send_message/src/SMSChannel.php @@ -0,0 +1,104 @@ +client = new Client; + } + + public function hasEnvironmentVariables(): string + { + return array_key_exists('TWILIO_ACCOUNT_SID', $this->environment) + && array_key_exists('TWILIO_AUTH_TOKEN', $this->environment) + && array_key_exists('TWILIO_SENDER', $this->environment); + } + + public function getAccountSID(): string + { + return $this->environment['TWILIO_ACCOUNT_SID']; + } + + public function getToken(): string + { + return $this->environment['TWILIO_AUTH_TOKEN']; + } + + public function getPhoneNumber(): string + { + return $this->environment['TWILIO_SENDER']; + } + + public function send(array $payload): array + { + if (! $this->hasEnvironmentVariables()) { + return [ + 'success' => false, + 'message' => 'Environment variables are not set.', + ]; + } + + if (! $this->validate( + validator: new PhoneNumberValidator( + client: $this->client, + SID: $this->getAccountSID(), + token: $this->getToken(), + ), + receiver: $payload['receiver'], + )) { + return [ + 'success' => false, + 'message' => 'Receiver is not a valid phone number.', + ]; + } + + try { + $response = $this->client->send( + request: new Request( + method: 'POST', + uri: sprintf('https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json', rawurlencode($this->getAccountSID())), + headers: [ + 'content-type' => 'application/x-www-form-urlencoded', + ], + ), + options: [ + RequestOptions::BODY => Query::build( + params: [ + 'To' => $payload['receiver'], + 'From' => $this->getPhoneNumber(), + 'Body' => $payload['message'], + ], + encoding: PHP_QUERY_RFC1738, + ), + RequestOptions::AUTH => [ + $this->getAccountSID(), $this->getToken(), + ], + RequestOptions::ALLOW_REDIRECTS => false, + ], + ); + } catch (\Exception $e) { + return [ + 'success' => false, + 'message' => $e->getMessage(), + ]; + } + + return [ + 'success' => (200 <= $response->getStatusCode() && $response->getStatusCode() < 300), + ]; + } +} diff --git a/php/send_message/src/Traits/HasReceiver.php b/php/send_message/src/Traits/HasReceiver.php new file mode 100644 index 00000000..503bc529 --- /dev/null +++ b/php/send_message/src/Traits/HasReceiver.php @@ -0,0 +1,11 @@ +validate($receiver); + } +} diff --git a/php/send_message/src/TwitterChannel.php b/php/send_message/src/TwitterChannel.php new file mode 100644 index 00000000..60192810 --- /dev/null +++ b/php/send_message/src/TwitterChannel.php @@ -0,0 +1,101 @@ +environment) + && array_key_exists('TWITTER_API_KEY_SECRET', $this->environment) + && array_key_exists('TWITTER_ACCESS_TOKEN', $this->environment) + && array_key_exists('TWITTER_ACCESS_KEY_SECRET', $this->environment); + } + + public function getConsumerKey(): string + { + return $this->environment['TWITTER_API_KEY']; + } + + public function getConsumerSecret(): string + { + return $this->environment['TWITTER_API_KEY_SECRET']; + } + + public function getTokenKey(): string + { + return $this->environment['TWITTER_ACCESS_TOKEN']; + } + + public function getTokenSecret(): string + { + return $this->environment['TWITTER_ACCESS_KEY_SECRET']; + } + + public function client(): Client + { + $stack = HandlerStack::create(); + + $stack->push( + middleware: new Oauth1( + config: [ + 'consumer_key' => $this->getConsumerKey(), + 'consumer_secret' => $this->getConsumerSecret(), + 'token' => $this->getTokenKey(), + 'token_secret' => $this->getTokenSecret(), + ] + ), + ); + + return new Client( + config: [ + 'handler' => $stack, + ], + ); + } + + public function send(array $payload): array + { + if (! $this->hasEnvironmentVariables()) { + return [ + 'success' => false, + 'message' => 'Environment variables are not set.', + ]; + } + + try { + $response = $this->client()->send( + request: new Request( + method: 'POST', + uri: 'https://api.twitter.com/1.1/statuses/update.json' + ), + options: [ + RequestOptions::QUERY => [ + 'status' => $payload['message'], + ], + RequestOptions::AUTH => 'oauth', + ], + ); + } catch (\Exception $e) { + return [ + 'success' => false, + 'message' => $e->getMessage(), + ]; + } + + return [ + 'success' => (200 <= $response->getStatusCode() && $response->getStatusCode() < 300), + ]; + } +} diff --git a/php/send_message/src/Validators/EmailValidator.php b/php/send_message/src/Validators/EmailValidator.php new file mode 100644 index 00000000..42a48e4d --- /dev/null +++ b/php/send_message/src/Validators/EmailValidator.php @@ -0,0 +1,11 @@ +client->send( + request: new Request( + method: 'GET', + uri: sprintf('https://lookups.twilio.com/v1/PhoneNumbers/%s', rawurlencode($receiver)), + ), + options: [ + RequestOptions::AUTH => [ + $this->SID, $this->token, + ], + RequestOptions::ALLOW_REDIRECTS => false, + ], + ); + } catch (\Exception) { + return false; + } + + return $response->getStatusCode() === 200; + } +} diff --git a/php/wipe_appwrite_bucket/README.md b/php/wipe_appwrite_bucket/README.md new file mode 100644 index 00000000..9b5e18b9 --- /dev/null +++ b/php/wipe_appwrite_bucket/README.md @@ -0,0 +1,67 @@ +# 🗑 Wipe Appwrite Bucket + +A PHP cloud function to wipe a complete bucket in Appwrite by passing the bucket id as a payload. + +_Example input:_ + +```json +{ + "bucketId":"profilePictures" +} +``` + +_Example output:_ + +```json +{ + "success":true, + "sum": 3 +} +``` + +```json +{ + "success":false, + "message": "Could not connect to Appwrite server." +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key +- **APPWRITE_FUNCTION_PROJECT_ID** - Appwrite project ID. If running on Appwrite, this variable is provided automatically. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd php/wipe_appwrite_bucket +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/php:v2-8.1 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.php --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/php:v2-8.1 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit PHP runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/php-8.1). + +4. Execute function: + +``` +curl http://localhost:3000/ -d '{"variables":{"APPWRITE_FUNCTION_ENDPOINT":"YOUR_ENDPOINT","APPWRITE_FUNCTION_PROJECT_ID":"YOUR_PROJECT_ID","APPWRITE_FUNCTION_API_KEY":"YOUR_API_KEY"},"payload":"{\"bucketId\":\"profilePictures\"}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with PHP 8.1. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/php/wipe_appwrite_bucket/composer.json b/php/wipe_appwrite_bucket/composer.json new file mode 100644 index 00000000..d304dbf0 --- /dev/null +++ b/php/wipe_appwrite_bucket/composer.json @@ -0,0 +1,11 @@ +{ + "name": "user/function", + "description": "", + "type": "library", + "license": "ISC", + "authors": [], + "require": { + "php": ">=8.0.0", + "appwrite/appwrite": "7.0.*" + } +} diff --git a/php/wipe_appwrite_bucket/index.php b/php/wipe_appwrite_bucket/index.php new file mode 100644 index 00000000..47ead6f7 --- /dev/null +++ b/php/wipe_appwrite_bucket/index.php @@ -0,0 +1,77 @@ +json([ + 'success' => false, + 'message' => 'Payload is invalid.' + ]); + return; + } + + if(empty($bucketId)) { + $res->json([ + 'success' => false, + 'message' => 'Invalid bucket id.' + ]); + return; + } + + // Make sure we have envirnment variables required to execute + if(!$req['variables']['APPWRITE_FUNCTION_ENDPOINT'] || + !$req['variables']['APPWRITE_FUNCTION_PROJECT_ID'] || + !$req['variables']['APPWRITE_FUNCTION_API_KEY']) { + $res->json([ + 'success' => false, + 'message' => 'Please provide all required variables.' + ]); + return; + } + + $client = new Client(); + $storage = new Storage($client); + + $client + ->setEndpoint($req['variables']['APPWRITE_FUNCTION_ENDPOINT']) + ->setProject($req['variables']['APPWRITE_FUNCTION_PROJECT_ID']) + ->setKey($req['variables']['APPWRITE_FUNCTION_API_KEY']); + + $done = false; + $sum = 0; + try { + while (!$done) { + $files = $storage->listFiles($bucketId)['files']; + foreach ($files as $file) { + $storage->deleteFile($bucketId, $file['$id']); + $sum++; + } + + if (count($files) == 0) { + $done = true; + } + } + } catch(\Exception $err) { + $res->json([ + 'success' => false, + 'message' => $err->getMessage() + ]); + return; + } + + // Return success result + $res->json([ + 'success' => true, + 'sum' => $sum + ]); +}; diff --git a/python/.DS_Store b/python/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..50853ab1f1f3cda04b7104f8e316b6cbc80b3d6e GIT binary patch literal 8196 zcmeHMU2GLa6rOKeV0WSI@ZUu)UaV9K1q=Owioop;QvQ)!+ENPT{w#Fky}Q@DdvAeS zt$%O+#TYdb)Tobu!9*X_2Yf?#($pv~7=17?Xkubw;**}8*;_0>lK3J?cbb_qbIzQZ zd(M1kCTGhSLwg~;hOuhKm`c^Bd?q!wD8AgUHx(t|loJK%GnQv2bLnptvu>IlGC~i8 z9tb@UdLZ;b=z+Vz1N3J5MZL|tFQs7{dLZ<`l=OgqKSZheG#1b?NyXJcjYt8A`YC`Y z)TcZ^=tKh=3+R}nLY3B(*#iPq1StljI?1E{bfU3iv-9Vauu_u@VcBM0C|hZh zrVR92cG?+kcM5je73;*MKx{O~jggTx%`L6<(WdoHqxI2|buG>H(Z-gB(NRrZxNObF zZAY>vPL4b=`s7>EPz09+tGdDPQ+KjD;}$!l)n)TbR)05PwLa76>Fv`8`J5sdvnS_S zj_vlCd6(!QuX4!&+ft6bH*fm#-jtImWNmkl&rT&WsX`{ugC|o|6xR`-G5NcF`ip(}_#utEyTPTOp4}IJPF%AV(TKZ3bIS z4_Ox*pbum@c7naYPP4b!S@sG0f?Z}`u`BE<`=0&4eq`6!@9a;Mp&ZjO0~`hx;T}Y= z0*z=wGup5nJFpYG5yt=y;V_QCgbfEdotJEqFD9e>PWv#MKiOHX?lme(Ny7OCx+5MS>jOuh&NSbczBwtc$FSaD{?T4p&DS zbY4cGCF0m@TROL^YP67RynGdaObV)}s|0@G!PuE4l=ByU~MQ96&!(gxsSTf +ℹ️ _Create your KrakenIO API key at https://kraken.io/docs/getting-started_.
+ + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +```bash +git clone https://github.com/open-runtimes/examples.git +cd examples/python/compress-image +``` + +2. Enter this function folder and build the code: +```bash +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/python:v2-3.10 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +```bash +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=main.py --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/python:v2-3.10 sh /usr/local/src/start.sh +``` + +> Make sure to replace `YOUR_API_KEY` with your key. +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/openruntimes/python:v2-3.10). +4. Run the cURL function to send request. +>TinyPNG Curl Example (Supports only API_KEY in Environment Variables) +```bash +curl http://localhost:3000/ -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" -d '{"payload": {"provider": "tinypng", "image": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAA1JREFUGFdj+L+U4T8ABu8CpCYJ1DQAAAAASUVORK5CYII="}, "variables": {"API_KEY": ""}}' +``` +>KrakenIO Curl Example (Supports API_KEY and SECRET_API_KEY in Environment Variables) +```bash +curl http://localhost:3000/ -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" -d '{"payload": {"provider": "krakenio", "image": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAA1JREFUGFdj+L+U4T8ABu8CpCYJ1DQAAAAASUVORK5CYII="}, "variables": {"API_KEY": "", "SECRET_API_KEY": ""}}' +``` +## 📝 Notes +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Python 3.10. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/python/compress-image/main.py b/python/compress-image/main.py new file mode 100644 index 00000000..d87c0ae2 --- /dev/null +++ b/python/compress-image/main.py @@ -0,0 +1,148 @@ +""" Compress image function using Tinypng and Krakenio API.""" +import base64 +import json +import tinify +import requests + +KRAKEN_API_ENDPOINT = "https://api.kraken.io/v1/upload" +KRAKEN_USER_AGENT = ( + "Mozilla/5.0 (Windows NT 6.1; Win64; x64)AppleWebKit/" + "537.36(KHTML, like Gecko)Chrome/40.0.2214.85 Safari/537.36" +) + + +def krakenio_impl(variables): + """ + Implements image optimization using the Kraken.io API. + + Input: + variables (dict): A dictionary containing the + required variables for optimization. + Returns: + optimized_image (bytes): decoded optimized image. + Raises: + raise_for_status (method): raise an HTTPError if the HTTP request + returned an unsuccessful status code. + """ + # Headers for post request + headers = {"User-Agent": KRAKEN_USER_AGENT} + # Image that we will pass in + files = {"file": variables["decoded_image"]} + # Parameters for post request + params = { + "auth": { + "api_key": variables["api_key"], + "api_secret": variables["api_secret_key"] + }, + "wait": True, # Optional: Wait for the optimization to complete + "dev": False, # Optional: Set to false to enter user mode. + } + response = requests.post( + url=KRAKEN_API_ENDPOINT, + headers=headers, + files=files, + data={"data": json.dumps(params)}, + timeout=10, + ) + # Check status code of response + response.raise_for_status() + data = response.json() + # Response unsuccessful, raise error + if not data["success"]: + raise ValueError("KrakenIO was not able to compress image.") + # Response successful, parse the response + optimized_url = data["kraked_url"] + optimized_image = requests.get(optimized_url, timeout=10).content + return optimized_image + + +def tinypng_impl(variables): + """ + Implements image optimization using the Tinypng API. + + Input: + variables (dict): A dictionary containing the required variables + for optimization. Includes api_key and decoded_image. + Returns: + tinify.from_buffer().tobuffer() (bytes): decoded optimized image. + Raises: + tinify.error (method): raised if tinify fails to compress image. + """ + tinify.key = variables["api_key"] + return tinify.from_buffer(variables["decoded_image"]).to_buffer() + + +def validate_request(req): + """ + Validates the request and extracts the necessary information. + + Input: + req (json): The request object containing the payload and variables. + Returns: + result (dict): Contains the validated request information. + Raises: + ValueError: If any required value is missing or invalid. + """ + # Check if payload is empty + if not req.payload: + raise ValueError("Missing payload") + # Accessing provider from payload + if not req.payload.get("provider"): + raise ValueError("Missing provider") + # Check if payload is not empty + if not req.variables: + raise ValueError("Missing variables.") + # Accessing api_key from variables + if not req.variables.get("API_KEY"): + raise ValueError("Missing API_KEY") + # Accessing encoded image from payload + if not req.payload.get("image"): + raise ValueError("Missing encoding image") + result = { + "provider": req.payload.get("provider").lower(), + "api_key": req.variables.get("API_KEY"), + "decoded_image": base64.b64decode(req.payload.get("image")), + } + # Get secret key + if req.payload.get("provider") == "krakenio": + if not req.variables.get("SECRET_API_KEY"): + raise ValueError("Missing api secret key.") + result["api_secret_key"] = req.variables.get("SECRET_API_KEY") + return result + + +IMPLEMENTATIONS = { + "krakenio": krakenio_impl, + "tinypng": tinypng_impl, + } + + +def main(req, res): + """ + The main function that runs validate_request and calls IMPLEMENTATIONS. + + Input: + req (json): The request object. + res (json): The response object. + + Returns: + res (json): A JSON response containing the optimization results. + """ + try: + variables = validate_request(req) + except (ValueError) as value_error: + return res.json({ + "success": False, + "error": f"{value_error}", + }) + try: + optimized_image = IMPLEMENTATIONS[variables["provider"]](variables) + except Exception as error: + return res.json({ + "success": False, + "error": f"{type(error).__name__}: {error}", + }) + return res.json({ + "success": True, + "image": base64.b64encode(optimized_image).decode(), + }) diff --git a/python/compress-image/requirements.txt b/python/compress-image/requirements.txt new file mode 100644 index 00000000..c65c821b --- /dev/null +++ b/python/compress-image/requirements.txt @@ -0,0 +1 @@ +tinify==1.6.0 \ No newline at end of file diff --git a/python/compress-image/secret.py b/python/compress-image/secret.py new file mode 100644 index 00000000..7952e6bb --- /dev/null +++ b/python/compress-image/secret.py @@ -0,0 +1,8 @@ +''' +API Key for tinyPNG and KrakenIO are stored here + +You should be in python/compress-image directory to run test_main.py +''' +API_KEY_TINYPNG = None +API_KEY_KRAKENIO = None +SECRET_API_KEY_KRAKENIO = None diff --git a/python/compress-image/test/1kb.png b/python/compress-image/test/1kb.png new file mode 100644 index 0000000000000000000000000000000000000000..5c9c29ba75a6713292f62959c089bc1191757c7b GIT binary patch literal 739 zcmV<90v!E`P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGmbN~PnbOGLGA9w%&0(eP8K~y+T&6Lki z6G0TmzdKuYS-UN^*eVF&M?*kkAYy`zF%m8&7(+PeNk}|sykg?P6W*G5>fMBJ(0HkT zfLi1F5}v{7H0nm3$!sc1!HLmPPq)wxI~gb zA`!&XXJik9>O&4=%JKn{gmkRv=W1v{!6I54q@!x=2s9Lh2odc=j&y=kKLb(^4`Cj#kRx zfs$b3b=<=2kcf}P5{%puY`R3la-mxsT@r_7g&@(mf<$lwr1>OBxWjA62HH1anpNS} zRm_aHVdi`gUthU};!KtjnF1%oRzq5JTH|miPR%8d8GJ(U-2x$S;e#EEMBg?MTw@ZzEi-x--cBv!O~Q;9ky|EB!t1_2palt zfRFaEd3CRmZM}>&x{ Function can also accept phone numbers with spaces, for instance `+421 957 215 740`. + + +_Example output:_ + + +```json +{ + "phoneNumber": "+421957215740", + "phonePrefix": "+421", + "countryCode": "SK", + "countryName": "Slovakia" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of your Appwrite server +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key +- **APPWRITE_FUNCTION_PROJECT_ID** - Appwrite project ID. If running on Appwrite, this variable is provided automatically. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd python/convert-phone-number-to-country-name +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/python:v2-3.10 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=main.py --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/python:v2-3.10 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/python-3.10). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Python 3.10. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/python/convert-phone-number-to-country-name/main.py b/python/convert-phone-number-to-country-name/main.py new file mode 100644 index 00000000..6671398b --- /dev/null +++ b/python/convert-phone-number-to-country-name/main.py @@ -0,0 +1,65 @@ + +import json +from appwrite.client import Client +from appwrite.services.locale import Locale + +""" +Globally scoped cache used by function. Example value: +[ + { + "code": "+1", + "countryCode": "US", + "countryName": "United States" + } +] +""" + +def main(req, res): + global phone_prefix_list + phone_prefix_list = None + + # Input validation + phone_number = None + try: + payload = json.loads(req.payload) + phone_number = payload['phoneNumber'].replace(" ", "") + except Exception as err: + print(err) + raise Exception('Payload is invalid.') + + if not phone_number or not phone_number.startswith('+'): + raise Exception('Invalid phone number.') + + # Make sure we have envirnment variables required to execute + if not req.variables.get('APPWRITE_FUNCTION_ENDPOINT', None) or not req.variables.get('APPWRITE_FUNCTION_PROJECT_ID', None) or not req.variables.get('APPWRITE_FUNCTION_API_KEY', None): + raise Exception('Please provide all required environment variables.') + + # If we don't have cached list of phone number prefixes (first execution only) + if phone_prefix_list is None: + # Init Appwrite SDK + client = Client() + locale = Locale(client) + + (client + .set_endpoint(req.variables.get('APPWRITE_FUNCTION_ENDPOINT', None)) + .set_project(req.variables.get('APPWRITE_FUNCTION_PROJECT_ID', None)) + .set_key(req.variables.get('APPWRITE_FUNCTION_API_KEY', None)) + ) + + # Fetch and store phone number prefixes + server_response = locale.get_countries_phones() + phone_prefix_list = server_response['phones'] + + # Get phone prefix + phonePrefix = list(filter(lambda prefix: phone_number.startswith(prefix['code']), phone_prefix_list)) + + if len(phonePrefix) < 1: + raise Exception('Invalid phone number.') + + # Return phone number prefix + return res.json({ + 'phoneNumber': phone_number, + 'phonePrefix': phonePrefix[0]['code'], + 'countryCode': phonePrefix[0]['countryCode'], + 'countryName': phonePrefix[0]['countryName'] + }) \ No newline at end of file diff --git a/python/convert-phone-number-to-country-name/requirements.txt b/python/convert-phone-number-to-country-name/requirements.txt new file mode 100644 index 00000000..0733474c --- /dev/null +++ b/python/convert-phone-number-to-country-name/requirements.txt @@ -0,0 +1 @@ +appwrite==0.7.0 \ No newline at end of file diff --git a/python/deepgram-audio-summary/README.md b/python/deepgram-audio-summary/README.md new file mode 100644 index 00000000..67a6658e --- /dev/null +++ b/python/deepgram-audio-summary/README.md @@ -0,0 +1,66 @@ +# 🔉📃 Summarize Audio with Deepgram + +A Python Cloud Function for summarizing audio number using [Deepgram API](https://deepgram.com/). + +_Example input:_ + +```json +{ + "fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Example output:_ + + +```json +{ + "success": true, + "deepgramData": [ + { + "summary": "another big problem in the speech analytics space. When customers first bring the software on is that they they are blown away by the fact that an engine can monitor hundreds of Kpis.", + "start_word": 0, + "end_word": 228 + } + ] +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **DEEPGRAM_API_KEY** - Deepgram API Key + +ℹ️ _Create your Deepgram API key at console.deepgram.com_ + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +```bash +git clone https://github.com/open-runtimes/examples.git && cd examples +cd python/deepgram-audio-summary +``` + +2. Enter this function folder and build the code: +```bash +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/python:v2-3.10 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +```bash +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=main.py --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/python:v2-3.10 sh /usr/local/src/start.sh +``` + +> Make sure to replace `YOUR_API_KEY` without your key. +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/openruntimes/python:v2-3.10). +4. Run the cURL function to send request. +```bash +curl http://localhost:3000/ -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" -d '{"payload": {"fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav"}, "variables": {"DEEPGRAM_API_KEY": ""}}' +``` + +## 📝 Notes +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Python 3.10. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/python/deepgram-audio-summary/main.py b/python/deepgram-audio-summary/main.py new file mode 100644 index 00000000..72c0cdd8 --- /dev/null +++ b/python/deepgram-audio-summary/main.py @@ -0,0 +1,39 @@ +import requests +import json + + +def errorMessage(res, message): + return res.json({ + "success": False, + "message": message, + }) + + +def main(req,res): + try: + #fileUrl and DEEPGRAM_API_KEY is required + file_url = req.payload['fileUrl'] + api_key = req.variables.get('DEEPGRAM_API_KEY') + + except Exception: + return errorMessage(res, 'Payload must contain fileUrl and DEEPGRAM_API_KEY.') + + # Setting up headers and body data for the requst + headers = { + 'content-type': "application/json", + 'Authorization': f"Token {api_key}" + } + data = {"url": file_url } + try: + r = requests.post("https://api.deepgram.com/v1/listen?summarize=true&punctuate=true", headers=headers, json=data) + except Exception as ex: + return errorMessage(res, str(ex)) + + status = r.status_code + if status == requests.codes.ok: + return res.json({ + "success": True, + "deepgramData": r.json()["results"] + }) + else: + return errorMessage(res, f"{status} status error.") diff --git a/python/deepgram-audio-summary/requirements.txt b/python/deepgram-audio-summary/requirements.txt new file mode 100644 index 00000000..9cdfca0c --- /dev/null +++ b/python/deepgram-audio-summary/requirements.txt @@ -0,0 +1 @@ +requests==2.27.1 \ No newline at end of file diff --git a/python/deepgram-language-detection/README.md b/python/deepgram-language-detection/README.md new file mode 100644 index 00000000..c05cd3fe --- /dev/null +++ b/python/deepgram-language-detection/README.md @@ -0,0 +1,59 @@ +# 🔉📃 Summarize Audio with Deepgram + +A Python Cloud Function for summarizing audio number using [Deepgram API](https://deepgram.com/). + +_Example input:_ + +```json +{ + "fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Example output:_ + + +```json +{ + "success": true, + "deepgramData": {} +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **DEEPGRAM_API_KEY** - Deepgram API Key + +ℹ️ _Create your Deepgram API key at console.deepgram.com_ + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +```bash +git clone https://github.com/open-runtimes/examples.git && cd examples +cd python/deepgram-language-detection +``` + +2. Enter this function folder and build the code: +```bash +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/python:v2-3.10 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +```bash +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=main.py --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/python:v2-3.10 sh /usr/local/src/start.sh +``` + +> Make sure to replace `YOUR_API_KEY` without your key. +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/openruntimes/python:v2-3.10). +4. Run the cURL function to send request. +```bash +curl http://localhost:3000/ -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" -d '{"payload": {"fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav"}, "variables": {"DEEPGRAM_API_KEY": ""}}' +``` +## 📝 Notes +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Python 3.10. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/python/deepgram-language-detection/main.py b/python/deepgram-language-detection/main.py new file mode 100644 index 00000000..f7da3499 --- /dev/null +++ b/python/deepgram-language-detection/main.py @@ -0,0 +1,39 @@ +import requests +import json + + +def errorMessage(res, message): + return res.json({ + "success": False, + "message": message, + }) + + +def main(req,res): + try: + #fileUrl and DEEPGRAM_API_KEY is required + file_url = req.payload['fileUrl'] + api_key = req.variables.get('DEEPGRAM_API_KEY') + + except Exception: + return errorMessage(res, 'Request must contain the File URL in the payload and the Deepgram API Key as a variable.') + + # Setting up headers and body data for the requst + headers = { + 'content-type': "application/json", + 'Authorization': f"Token {api_key}" + } + data = {"url": file_url } + try: + r = requests.post("https://api.deepgram.com/v1/listen?detect_language=true&punctuate=true", headers=headers, json=data) + except Exception as ex: + return errorMessage(res, str(ex)) + + status = r.status_code + if status == requests.codes.ok: + return res.json({ + "success": True, + "deepgramData": r.json()["results"] + }) + else: + return errorMessage(res, f"{status} status error.") \ No newline at end of file diff --git a/python/deepgram-language-detection/requirements.txt b/python/deepgram-language-detection/requirements.txt new file mode 100644 index 00000000..a743bbe3 --- /dev/null +++ b/python/deepgram-language-detection/requirements.txt @@ -0,0 +1 @@ +requests==2.27.1 diff --git a/python/deepgram-topic-detection/README.md b/python/deepgram-topic-detection/README.md new file mode 100644 index 00000000..028d0ab5 --- /dev/null +++ b/python/deepgram-topic-detection/README.md @@ -0,0 +1,61 @@ +# 🧹Deepgram Topic Detection + +A Cloud Function for topic detection using [Deepgram](https://deepgram.com/) + +_Example input:_ + +```json +{ + "fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Example output:_ + +```json +{ + "deepgramData": {}, + "success": true +} +``` + +_Example error output:_ + +```json +{ + "success": false, + "message": "Error" +} +``` + +## 📝 Environment Variables + +**DEEPGRAM_API_KEY** - Your Deepgram secret API key. +Details are under link: [Deepgram_getting_started](https://developers.deepgram.com/documentation/getting-started/) + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +```bash +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd python/deepgram-topic-detection +``` + +2. Build the code: + +```bash +docker run -e INTERNAL_RUNTIME_ENTRYPOINT=main.py --rm --interactive --tty --volume $PWD:/usr/code openruntimes/python:v2-3.10 sh /usr/local/src/build.sh +``` + +3. Spin-up open-runtime: + +```bash +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/python:v2-3.10 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/python-3.10). + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). \ No newline at end of file diff --git a/python/deepgram-topic-detection/main.py b/python/deepgram-topic-detection/main.py new file mode 100644 index 00000000..4453c10a --- /dev/null +++ b/python/deepgram-topic-detection/main.py @@ -0,0 +1,37 @@ +import requests +import validators + + +def main(req, res): + # validate the request url/payload is not empty + file_url = None + try: + file_url = req.payload['fileUrl'] + api_key = req.variables.get('DEEPGRAM_API_KEY') + except Exception: + return res.json({'success': "false", 'message': "Invalid/Empty Payload"}) + + if not file_url: + return res.json({'success': "false", 'message': "Empty URL"}) + + # validate if the file url is in correct format + if not validators.url(file_url): + return res.json({'success': "false", 'message': "Invalid URL please provide URL in correct format"}) + + # Make sure we have environment variables required to execute + if not api_key: + return res.json({'success': "false", 'message': "You need to pass an API key for the provider"}) + + # Fetch the DEEPGRAM Data + base_url = "https://api.deepgram.com/v1/listen?detect_topics=true&punctuate=true" + response = requests.post(base_url, json={"url": file_url}, + headers={"Content-Type": "application/json", "Authorization": "Token " + api_key}) + + # Make sure we get the deepgram data + if response.status_code != 200: + return res.json({"success": "false", 'message': "Can't fetch the data/API key is not valid"}) + + print(response.json()) + + # Return DEEPGRAM DATA + return res.json({"success": "true", "deepgramData": response.json()["results"]}) diff --git a/python/deepgram-topic-detection/requirements.txt b/python/deepgram-topic-detection/requirements.txt new file mode 100644 index 00000000..d2cf2a32 --- /dev/null +++ b/python/deepgram-topic-detection/requirements.txt @@ -0,0 +1,2 @@ +requests==2.28.1 +validators==0.20.0 \ No newline at end of file diff --git a/python/deepgram-transcribe-audio/README.md b/python/deepgram-transcribe-audio/README.md new file mode 100644 index 00000000..d4921471 --- /dev/null +++ b/python/deepgram-transcribe-audio/README.md @@ -0,0 +1,96 @@ +# Transcribe Audio Files + +A Python Cloud Function that transcribes an Audio file with the help of Deepgram. + +_Example input 1:_ + +```json +{ + "fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Example output 1:_ + +```json +{ + "deepgramData": { + "confidence": 0.9926758, + "transcript": "another big problem in the ... company succeed using this product", + "words": [ + { + "confidence": 0.9995117, + "end": 0.839599, + "start": 0.33959904, + "word": "another" + }, + { + "confidence": 0.99365234, + "end": 95.770004, + "start": 95.41, + "word": "product" + } + ] + } + "success": true +} +``` + +_Example input 2:_ + +```json +{ + + "fileUrl": "WRONG_URL" +} +``` + +_Example output 2:_ + +```json +{ + "message": "Please provide a valid audio URL", + "success": false +} +``` + +## 📝 Variables + +List of variables used by this cloud function: + +- **DEEPGRAM_API_KEY** - Deepgram API Key + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + + ```shell + git clone https://github.com/open-runtimes/examples.git && cd examples + cd python/deepgram-transcribe-audio + ``` + +2. Enter this function folder and build the code: + + ```shell + docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/python:v2-3.10 sh /usr/local/src/build.sh + ``` + + As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + + ```shell + docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=main.py --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/python:v2-3.10 sh /usr/local/src/start.sh + ``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/python-3.10). + +4. Run the cURL function to send request. +```bash +curl -g -X POST http://localhost:3000/ -H "X-Internal-Challenge: secret-key" -H "Content-type: application/json" -d '{"payload":"{\"fileUrl\":\"https://static.deepgram.com/examples/interview_speech-analytics.wav\"}","variables":{"DEEPGRAM_API_KEY":""}}' +``` + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Python 3.10. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/python/deepgram-transcribe-audio/main.py b/python/deepgram-transcribe-audio/main.py new file mode 100644 index 00000000..37c048b1 --- /dev/null +++ b/python/deepgram-transcribe-audio/main.py @@ -0,0 +1,75 @@ +import json +import requests +from json import JSONDecodeError + + +def main(req, res): + url = None + + # Extracting URL from the payload + try: + payload = json.loads(req.payload) + url = payload['fileUrl'] + + except KeyError: + err = 'Please provide all the required parameters.' + return res.json({ + "success": False, + "message": err + }) + + # Checking if DEEPGRAM_API_KEY is provided + if not req.variables.get('DEEPGRAM_API_KEY', None): + return res.json({ + "success": False, + "message": "Please provide DEEPGRAM_API_KEY in variables" + }) + + api_key = req.variables.get('DEEPGRAM_API_KEY') + + # Setting up headers and body data for the requst + headers = { + 'content-type': "application/json", + 'Authorization': f"Token {api_key}" + } + + data = "{\"url\": \"" + url + "\"}" + + # Post requst to the Deepgram API + response = requests.post( + "https://api.deepgram.com/v1/listen", data=data, headers=headers + ) + + # Responses for different status codes + if response.status_code == 200: + response = response.json() + return res.json({ + "success": True, + "deepgramData": response + }) + + elif response.status_code == 401: + return res.json({ + "success": False, + "message": "Please provide a valid DEEPGRAM_API_KEY" + }) + + elif response.status_code == 400: + return res.json({ + "success": False, + "message": "Please provide a valid audio URL" + }) + + else: + try: + response = response.json() + return res.json({ + "success": False, + "message": f"{response['error']}, {response['reason']}" + }) + + except JSONDecodeError: + return res.json({ + "success": False, + "message": response.text + }) diff --git a/python/deepgram-transcribe-audio/requirements.txt b/python/deepgram-transcribe-audio/requirements.txt new file mode 100644 index 00000000..a743bbe3 --- /dev/null +++ b/python/deepgram-transcribe-audio/requirements.txt @@ -0,0 +1 @@ +requests==2.27.1 diff --git a/python/deepgram-transcribe-video/README.md b/python/deepgram-transcribe-video/README.md new file mode 100644 index 00000000..601084ad --- /dev/null +++ b/python/deepgram-transcribe-video/README.md @@ -0,0 +1,66 @@ +# ⚡ deepgramTranscribeVideo() + +A Python Cloud Function for transcribing video using [Deepgram](https://deepgram.com/) + +_Example function payload:_ + +```json +{ + "fileUrl": "https://rawcdn.githack.com/deepgram-devs/transcribe-videos/62fc7769d6e2bf38e420ee5224060922af4546f7/deepgram.mp4" +} +``` + +_Successful function response::_ + +```json +{ "deepgramData": {}, "success": true } +``` + +_Error function response:_ + +```json +{ "message": "error message", "success": false } +``` + +## 📝 Variables + +List of variables used by this cloud function: + +**DEEPGRAM_API_KEY** - Your Deepgram API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd python/deepgram-transcribe-video +``` + +2. Enter this function folder and build the code: + +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/python:v2-3.10 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=main.py --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/python:v2-3.10 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/python-3.10). + +4. Curl Command + +```bash +curl http://localhost:3000/ -d '{"variables": {"DEEPGRAM_API_KEY":""},"payload": "{\"fileUrl\":\"https://rawcdn.githack.com/deepgram-devs/transcribe-videos/62fc7769d6e2bf38e420ee5224060922af4546f7/deepgram.mp4\" }" +}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Python 3.10. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/python/deepgram-transcribe-video/main.py b/python/deepgram-transcribe-video/main.py new file mode 100644 index 00000000..f221cd22 --- /dev/null +++ b/python/deepgram-transcribe-video/main.py @@ -0,0 +1,25 @@ +from deepgram import Deepgram +import asyncio +import json + + +async def transribeVideo(api_key, payload): + + dg_client = Deepgram(api_key) + source = {'url': payload['fileUrl']} + + try: + response = await dg_client.transcription.prerecorded(source, {'punctuate': True, "model": 'video'}) + except Exception as e: + return {'success': False, 'message': str(e)} + return {'success': True, 'deepgramData': response} + + +def main(req, res): + try: + payload = json.loads(req.payload) + api_key = req.variables['DEEPGRAM_API_KEY'] + rs = asyncio.run(transribeVideo(api_key, payload)) + return res.json(rs) + except Exception as e: + return res.json({'success': False, 'message': str(e)}) diff --git a/python/deepgram-transcribe-video/requirements.txt b/python/deepgram-transcribe-video/requirements.txt new file mode 100644 index 00000000..ab2dce9c --- /dev/null +++ b/python/deepgram-transcribe-video/requirements.txt @@ -0,0 +1,11 @@ +aiohttp==3.8.3 +aiosignal==1.2.0 +async-timeout==4.0.2 +attrs==22.1.0 +charset-normalizer==2.1.1 +deepgram-sdk==1.0.0 +frozenlist==1.3.1 +idna==3.4 +multidict==6.0.2 +websockets==10.3 +yarl==1.8.1 diff --git a/python/generate-giphy-gif/README.md b/python/generate-giphy-gif/README.md new file mode 100644 index 00000000..28a5f82f --- /dev/null +++ b/python/generate-giphy-gif/README.md @@ -0,0 +1,55 @@ +# 🖼️ Get Giphy GIF + +A Python Cloud Function for generating Giphy GIF from the [Giphy API](https://developers.giphy.com/docs/api#quick-start-guide). + +_Example input:_ + +```json +{ + "search": "good morning" +} +``` + +_Example output:_ + + +```json +{ + "search": "good morning", + "gif": "https://giphy.com/gifs/text-gif-sticker-brittdoesdesign-MS9Yq6Y718CSiDTxR5" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +**GIPHY_API_KEY** - Your Giphy API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd python/generate-giphy-gif +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/python:v2-3.10 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=main.py --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/python:v2-3.10 sh /usr/local/src/start.sh +``` + +> Make sure to replace `YOUR_API_KEY` without your key. + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/python-3.10). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Python 3.10. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/python/generate-giphy-gif/main.py b/python/generate-giphy-gif/main.py new file mode 100644 index 00000000..584fcd66 --- /dev/null +++ b/python/generate-giphy-gif/main.py @@ -0,0 +1,29 @@ +import json +import requests + +def main(req, res): + # Input validation + search = None + try: + payload = json.loads(req.payload) + search = payload['search'] + except Exception as err: + print(err) + raise Exception('Payload is invalid.') + + if not search: + raise Exception('Invalid search.') + + # Make sure we have envirnment variables required to execute + if not req.variables.get('GIPHY_API_KEY', None): + raise Exception('Please provide all required environment variables.') + + api_key = req.variables.get('GIPHY_API_KEY', None) + + # Fetch the Giphy URL + response = requests.get(f"https://api.giphy.com/v1/gifs/search?api_key={api_key}&q={search}&limit=1") + response.raise_for_status() + url = response.json()["data"][0]['url'] + + # Return Giphy URL + return res.json({'search': search, 'gif': url}) \ No newline at end of file diff --git a/python/generate-giphy-gif/requirements.txt b/python/generate-giphy-gif/requirements.txt new file mode 100644 index 00000000..a743bbe3 --- /dev/null +++ b/python/generate-giphy-gif/requirements.txt @@ -0,0 +1 @@ +requests==2.27.1 diff --git a/python/generate-map/README.md b/python/generate-map/README.md new file mode 100644 index 00000000..f71345de --- /dev/null +++ b/python/generate-map/README.md @@ -0,0 +1,54 @@ +# 🗺️ Generate Map Image +A Python Cloud Function that generate static map image from longitude and latitude. +_Example input:_ +```json +{ + "lng": 12.561767, + "lat": 41.857177 +} +``` +_Example output:_ + +```json +{ + "success":true, + "image":"iVBORw0KGgoAAAANSUhEUgAAAaQAAALiCAY...QoH9hbkTPQAAAABJRU5ErkJggg==" +} +``` +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +**MAPBOX_ACCESS_TOKEN** - Your Mapbox API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd python/generate-map +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/python:v2-3.10 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=main.py --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/python:v2-3.10 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/python-3.10). + +4. Execute function: + +``` +curl http://localhost:3000/ -d '{"variables":{"MAPBOX_ACCESS_TOKEN":"YOUR_API_KEY"},"payload": "{\"lng\":50,\"lat\":60}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" + +``` + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Python 3.10. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/python/generate-map/main.py b/python/generate-map/main.py new file mode 100644 index 00000000..12aab8ff --- /dev/null +++ b/python/generate-map/main.py @@ -0,0 +1,32 @@ +import json +import requests +import base64 + +def error(res,message): + return res.json({"success":False,"message":message}) + +def main(req,res): + try: + payload = json.loads('{}' if not req.payload else req.payload) + lng = payload.get('lng', None) + lat = payload.get('lat', None) + access_token = req.variables["MAPBOX_ACCESS_TOKEN"] + except Exception: + return error(res,"The payload must contain lng and lat or access token is not present") + if lng == None or lat == None: + return error(res,"The payload must contain lng and lat") + elif((type(lng)!=float or type(lat)!=float) and (type(lng)!=int or type(lat)!=int)): + return error(res,"The longitude and latitude must be a number") + elif lng >180 or lng < -180: + return error(res,"The longitude must be between -180 and 180") + elif lat >90 or lat < -90: + return error(res,"The latitude must be between -90 and 90") + + url ="https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/{0},{1},15,0,0/1000x1000?access_token={2}".format(lng,lat,access_token) + response = requests.get(url,timeout=30) + + if response.status_code ==requests.codes.ok: + image = base64.b64encode(response.content) + return res.json({"success":True,"image":image.decode("utf-8")}) + else: + return error(res,"Error " + str(response.status_code) + ": " + str(response.content)) diff --git a/python/generate-map/requirements.txt b/python/generate-map/requirements.txt new file mode 100644 index 00000000..9cdfca0c --- /dev/null +++ b/python/generate-map/requirements.txt @@ -0,0 +1 @@ +requests==2.27.1 \ No newline at end of file diff --git a/python/generate-short-url/README.md b/python/generate-short-url/README.md new file mode 100644 index 00000000..51ceb7e3 --- /dev/null +++ b/python/generate-short-url/README.md @@ -0,0 +1,93 @@ +# Generates Short URL with Bitly and Tinyurl + +A Python Cloud Function that generates short URLs with help of Bitly or Tinyurl. + +_Example input:_ + +```json +{ + "provider": "tinyurl", + "url": "https://github.com/appwrite/appwrite" +} +``` + + +_Example output:_ + +```json +{ + "success": true, + "url": "https://tinyurl.com/abc3df" +} +``` + + +_Example input:_ + +```json +{ + "provider": "bitly", + "url": "https://github.com/appwrite/appwrite" +} +``` + +_Example output:_ + +```json +{ + "success": true, + "url": "https://bit.ly/asd57dd" +} +``` + + +_Example input:_ + +```json +{ + "provider": "owly", + "url": "https://github.com/appwrite/appwrite" +} +``` + +_Example output:_ + +```json +{ + "success": false, + "message": "owly is not a valid provider" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **TINYURL_API_KEY** - Tinyurl API Key +- **BITLY_API_KEY** - Bitly API Key + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd python/generate-short-url +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/python:v2-3.10 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=main.py --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/python:v2-3.10 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/python-3.10). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Python 3.10. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/python/generate-short-url/main.py b/python/generate-short-url/main.py new file mode 100644 index 00000000..419b6952 --- /dev/null +++ b/python/generate-short-url/main.py @@ -0,0 +1,104 @@ +import json +import requests + + +def main(req, res): + # Required parameters + provider = None + url = None + + try: + payload = json.loads(req.payload) + provider = payload['provider'] + url = payload['url'] + + except Exception: + err = 'Please provide all the required parameters.' + return res.json({ + "success": False, + "message": err, + }) + + # Logic if the provider is tinyurl + if provider == "tinyurl": + + if not req.variables.get('TINYURL_API_KEY', None): + return res.json({ + "success": False, + "message": "Please provide all required environment variables." + }) + + api_key = req.variables.get('TINYURL_API_KEY', None) + + response = requests.post(f'https://api.tinyurl.com/create?api_token={api_key}&url={url}') + response = response.json() + + if response['code'] == 0: + return res.json({ + "success": True, + "url": response['data']['tiny_url'] + }) + + elif response['code'] == 1: + return res.json({ + "success": False, + "message": "Please provide a valid API Key" + }) + + elif response['code'] == 5: + return res.json({ + "success": False, + "message": "Please provide a valid URL" + }) + + else: + return res.json({ + "success": False, + "message": response['errors'] + }) + + # Logic if provider is bitly + elif provider == "bitly": + if not req.variables.get('BITLY_API_KEY', None): + return res.json({ + "success": False, + "message": "Please provide all required environment variables." + }) + + api_key = req.variables.get('BITLY_API_KEY', None) + + headers = { + 'Authorization': f'Bearer {api_key}', + 'Content-Type': 'application/json', + } + data = '{"long_url": "' + url + '"}' + + response = requests.post('https://api-ssl.bitly.com/v4/shorten', headers=headers, data=data) + + if response.status_code == 200: + response = response.json() + return res.json({ + "success": True, + "url": response['link'] + }) + elif response.status_code == 403: + response = response.json() + return res.json({ + "success": False, + "message": "Please provide a valid API Key" + }) + + else: + response = response.json() + return res.json({ + "success": False, + "message": str(response['message']) + }) + + # Logic if the Provider is not valid. + else: + err = f'{provider} is not a valid provider.' + return res.json({ + "success": False, + "message": err + }) diff --git a/python/generate-short-url/requirements.txt b/python/generate-short-url/requirements.txt new file mode 100644 index 00000000..a743bbe3 --- /dev/null +++ b/python/generate-short-url/requirements.txt @@ -0,0 +1 @@ +requests==2.27.1 diff --git a/python/object-detection/README.md b/python/object-detection/README.md new file mode 100644 index 00000000..238c64d9 --- /dev/null +++ b/python/object-detection/README.md @@ -0,0 +1,60 @@ +# 📷 Object Detection using Cloudmersive Vision API + +A Python Cloud Function for object detection from an image URL. + +_Example input:_ + +```json +{ + "url": "https://picsum.photos/seed/open___runtimes/1000/1000" +} +``` + +_Example output:_ + + +```json +{ + "url": "https://picsum.photos/seed/open___runtimes/1000/1000", + "name": "cake", + "confidence": 0.7977721691131592, + "x": 21, + "y": 5, + "width": 494, + "height": 333 +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +**CLOUDMERSIVE_API_KEY** - Your Cloudmersive API key. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd python/object-detection +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/python:v2-3.10 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=main.py --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/python:v2-3.10 sh /usr/local/src/start.sh +``` + +> Make sure to replace `YOUR_API_KEY` without your key. + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/python-3.10). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Python 3.10. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/python/object-detection/main.py b/python/object-detection/main.py new file mode 100644 index 00000000..4e59b804 --- /dev/null +++ b/python/object-detection/main.py @@ -0,0 +1,57 @@ +import json +import requests + +from cloudmersive_image_api_client import Configuration, RecognizeApi, ApiClient +from cloudmersive_image_api_client.rest import ApiException + +def main(req, res): + # Input validation + file_url = None + try: + payload = json.loads(req.payload) + file_url = payload['url'] + except Exception as err: + print(err) + raise Exception('Payload is invalid.') + + if not file_url: + raise Exception('Invalid search.') + + # Make sure we have envirnment variables required to execute + if not req.variables.get('CLOUDMERSIVE_API_KEY', None): + raise Exception('Please provide all required environment variables.') + + api_key = req.variables.get('CLOUDMERSIVE_API_KEY', None) + + # Download the file + response = requests.get(file_url, stream=True) + with open("temp.jpg", 'wb') as newFile: + for chunk in response.iter_content(chunk_size=1024): + if chunk: + newFile.write(chunk) + newFile.flush() + + # Configure the detection client + configuration = Configuration() + configuration.api_key['Apikey'] = api_key + + # Create an instance of the API class + api_client = RecognizeApi(ApiClient(configuration)) + + # Detect objects including types and locations in an image + api_response = api_client.recognize_detect_objects("temp.jpg") + + # Return object detection results + results = list(map(lambda x: { + "name": x.object_class_name, + "confidence": x.score, + "x": x.x, + "y": x.y, + "width": x.width, + "height": x.height + }, api_response.objects)) + + if len(results) < 1: + raise Exception('No objects found in the image.') + + return res.json(results[0]) diff --git a/python/object-detection/requirements.txt b/python/object-detection/requirements.txt new file mode 100644 index 00000000..8ff86d0b --- /dev/null +++ b/python/object-detection/requirements.txt @@ -0,0 +1,2 @@ +requests==2.27.1 +cloudmersive-image-api-client==3.0.1 \ No newline at end of file diff --git a/python/send-http-request/README.md b/python/send-http-request/README.md new file mode 100644 index 00000000..fdcaf5f0 --- /dev/null +++ b/python/send-http-request/README.md @@ -0,0 +1,72 @@ +# 🌐 Send HTTP request + +A Python Cloud Function for sending an HTTP request. Supported options are method, url, body, and headers. Status code, response body, and response headers are returned. + +_Example input:_ + +```json +{ + "url":"https://demo.appwrite.io/v1/locale/countries/eu", + "method":"GET", + "headers": + { + "x-client-version":"1.0.0" + }, + "body":"" +} +``` + +_Example success output:_ + + +```json +{ + "success":true, + "response": + { + "headers":{}, + "code":200, + "body":"{\"total\":27,\"countries\":[]}" + } +} +``` + +_Example failure output:_ + + +```json +{ + "success":false, + "message":"URL could not be reached" +} +``` + +## 📝 Environment Variables + +No environment variables are required to run this function. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd python/send-http-request +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/python:3.10 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=main.py --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/python:3.10 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/python-3.10). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Python 3.10. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/python/send-http-request/main.py b/python/send-http-request/main.py new file mode 100644 index 00000000..815bf584 --- /dev/null +++ b/python/send-http-request/main.py @@ -0,0 +1,54 @@ +import requests +import json + + +def errorMessage(res, message): + return res.json({ + "success": False, + "message": message, + }) + + +def main(req,res): + + headers = None + body = None + try: + payload = json.loads(req.payload) + + #url and method are required + url = payload['url'] + method = payload['method'] + + # headers and body are optional + if 'headers' in payload.keys(): + headers = payload['headers'] + if 'body' in payload.keys(): + body = payload['body'] + + except Exception: + return errorMessage(res, 'Payload must contain url and method.') + if url.strip() == "": + return errorMessage(res, 'Payload url cannot be empty.') + if method.strip() == "": + return errorMessage(res, 'Payload method cannot be empty.') + + r = None + try: + r = requests.request(method, url, headers=headers, json=body, timeout=30) + except Exception: + return errorMessage(res, 'URL could not be reached.') + + status = r.status_code + if status == requests.codes.ok: + return res.json({ + "success": True, + "response": + { + "headers": json.dumps(dict(r.headers)), + "code": status, + "body": r.json() + } + }) + else: + return errorMessage(res, f"{status} status error. Nothing to retrieve. Check that URL path is correct.") \ No newline at end of file diff --git a/python/send-http-request/requirements.txt b/python/send-http-request/requirements.txt new file mode 100644 index 00000000..9cdfca0c --- /dev/null +++ b/python/send-http-request/requirements.txt @@ -0,0 +1 @@ +requests==2.27.1 \ No newline at end of file diff --git a/python/send_message/README.md b/python/send_message/README.md new file mode 100644 index 00000000..91b6cc0f --- /dev/null +++ b/python/send_message/README.md @@ -0,0 +1,119 @@ +# SendMessage() + +A Python Cloud Function for sending a message using a specific channel to a receiver + +Supported channels are `SMS`, `Email` ,`Disocrd` and `Twitter`. + +_SMS Example payload_ + +```json +{ "type": "SMS", "receiver": "+123456789", "message": "Programming is fun!" } +``` + +_Email Example payload_ + +```json +{ + "type": "Email", + "receiver": "hello@example.com", + "message": "Programming is fun!", + "subject": "Programming is funny!" +} +``` + +_Discord Example payload_ + +```json +{ + "type": "Discord", + "message": "Hi" +} +``` + +_Twitter Example payload_ + +```json +{ + "type": "Twitter", + "receiver": "", + "message": "Programming is fun!" +} +``` + +_Successful function response:_ + +```json +{ + "success": true +} +``` + +_Error function response:_ + +```json +{ + "success": false, + "message": "Failed to send message,check webhook URL" +} +``` + +## 📝 Variables + +List of variables used by this cloud function: + +Mailgun + +- **MAILGUN_API_KEY** - API Key for Mailgun +- **MAILGUN_DOMAIN** - Domain Name from Mailgun + +Discord + +- **DISCORD_WEBHOOK_URL** - Webhook URL for Discord + +Twilio + +- **TWILIO_ACCOUNT_SID** - Acount SID from Twilio +- **TWILIO_AUTH_TOKEN** - Auth Token from Twilio +- **TWILIO_SENDER** - Sender Phone Number from Twilio + +Twitter + +- **TWITTER_API_KEY** - API Key for Twitter +- **TWITTER_API_KEY_SECRET** - API Key Secret for Twitter +- **TWITTER_ACCESS_TOKEN** - Access Token from Twitter +- **TWITTER_ACCESS_TOKEN_SECRET** - Access Token Secret from Twitter + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd python/send_message +``` + +2. Enter this function folder and build the code: + +```bash +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/python:v2-3.10 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +```bash +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=main.py --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/python:v2-3.10 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/python-3.10/example). + +4. Curl Command ( Email ) + +```bash +curl -X POST http://localhost:3000/ -d '{"variables": {"MAILGUN_API_KEY":"YOUR_MAILGUN_API_KEY","MAILGUN_DOMAIN":"YOUR_MAILGUN_DOMAIN"},"payload": "{\"type\": \"Email\",\"receiver\": \"hello@example.com\",\"message\": \"Programming is fun!\",\"subject\": \"Programming is funny!\"}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). diff --git a/python/send_message/functions/send_email_mailgun.py b/python/send_message/functions/send_email_mailgun.py new file mode 100644 index 00000000..523440ed --- /dev/null +++ b/python/send_message/functions/send_email_mailgun.py @@ -0,0 +1,38 @@ +import requests +import os + + +def send_email_mailgun(variables, email, message, subject): + """Send email using Mailgun""" + + if not email or not message or not subject: + raise Exception("Missing email, message or subject") + + domain = variables.get("MAILGUN_DOMAIN", None) + api_key = variables.get("MAILGUN_API_KEY", None) + + if not domain: + raise Exception("Missing Mailgun domain") + if not api_key: + raise Exception("Missing Mailgun API key") + + try: + response = requests.post( + f"https://api.mailgun.net/v3/{domain}/messages", + auth=("api", api_key), + data={ + "from": "", + "to": email, + "subject": subject, + "text": message, + }, + ) + response.raise_for_status() + + except Exception as e: + print(e) + return {"success": False, "message": str(e)} + + return { + "success": True, + } diff --git a/python/send_message/functions/send_message_discord_webhook.py b/python/send_message/functions/send_message_discord_webhook.py new file mode 100644 index 00000000..187904a6 --- /dev/null +++ b/python/send_message/functions/send_message_discord_webhook.py @@ -0,0 +1,27 @@ +import json +import requests + + +def send_message_discord_webhook(variables, message): + """Send message to Discord webhook""" + + if not message: + raise Exception("No message provided") + + webhook = variables.get("DISCORD_WEBHOOK_URL", None) + + if not webhook: + raise Exception("No Discord webhook URL provided") + + try: + response = requests.post( + webhook, + data=json.dumps({"content": message}), + headers={"Content-Type": "application/json"}, + ) + response.raise_for_status() + except Exception as e: + print(e) + return {"success": False, "message": str(e)} + + return {"success": True} diff --git a/python/send_message/functions/send_sms_twilio.py b/python/send_message/functions/send_sms_twilio.py new file mode 100644 index 00000000..02742587 --- /dev/null +++ b/python/send_message/functions/send_sms_twilio.py @@ -0,0 +1,39 @@ +import requests + + +def send_sms_twilio(variables, phoneNumber, message): + """Send SMS using Twilio""" + + if not phoneNumber: + raise Exception("No phone number provided") + + if not message: + raise Exception("No message provided") + + accountSID = variables.get("TWILIO_ACCOUNT_SID", None) + authToken = variables.get("TWILIO_AUTH_TOKEN", None) + sender = variables.get("TWILIO_SENDER", None) + + if not accountSID: + raise Exception("Missing Twilio account SID") + if not authToken: + raise Exception("Missing Twilio auth token") + if not sender: + raise Exception("Missing Twilio sender") + + try: + response = requests.post( + f"https://api.twilio.com/2010-04-01/Accounts/{accountSID}/Messages.json", + auth=(accountSID, authToken), + data={ + "From": sender, + "To": phoneNumber, + "Body": message, + }, + ) + response.raise_for_status() + except Exception as e: + print(e) + return {"success": False, "message": str(e)} + + return {"success": True} diff --git a/python/send_message/functions/send_tweet.py b/python/send_message/functions/send_tweet.py new file mode 100644 index 00000000..4152c02d --- /dev/null +++ b/python/send_message/functions/send_tweet.py @@ -0,0 +1,41 @@ +import tweepy + + +def send_tweet(variables, message): + """Send tweet to Twitter""" + + if not message: + raise Exception("Missing message") + + consumer_key = variables.get("TWITTER_API_KEY", None) + consumer_secret = variables.get("TWITTER_API_KEY_SECRET", None) + access_token = variables.get("TWITTER_ACCESS_TOKEN", None) + access_token_secret = variables.get("TWITTER_ACCESS_TOKEN_SECRET", None) + + if not consumer_key: + raise Exception("Missing Twitter consumer key") + if not consumer_secret: + raise Exception("Missing Twitter consumer secret") + if not access_token: + raise Exception("Missing Twitter access token") + if not access_token_secret: + raise Exception("Missing Twitter access token secret") + + try: + auth = tweepy.OAuthHandler(consumer_key, consumer_secret) + auth.set_access_token( + access_token, + access_token_secret, + ) + + api = tweepy.API(auth) + + api.update_status(message) + + except Exception as e: + print(e) + return {"success": False, "message": str(e)} + + return { + "success": True, + } diff --git a/python/send_message/main.py b/python/send_message/main.py new file mode 100644 index 00000000..dce1a953 --- /dev/null +++ b/python/send_message/main.py @@ -0,0 +1,38 @@ +from .functions.send_sms_twilio import send_sms_twilio +from .functions.send_email_mailgun import send_email_mailgun +from .functions.send_tweet import send_tweet +from .functions.send_message_discord_webhook import send_message_discord_webhook +import json + + +def main(req, res): + """Main Function""" + + result = {} + + try: + payload = json.loads(req.payload) + + payload_type = payload["type"] + message = payload["message"] + + if payload_type == "SMS": + reciever = payload["receiver"] + result = send_sms_twilio(req.variables, reciever, message) + elif payload_type == "Email": + reciever = payload["receiver"] + subject = payload["subject"] + result = send_email_mailgun( + req.variables, reciever, message, subject) + elif payload_type == "Twitter": + result = send_tweet(req.variables, message) + elif payload_type == "Discord": + result = send_message_discord_webhook(req.variables, message) + else: + result = {"success": False, "message": "Invalid Type"} + + except Exception as e: + + return res.json({"success": False, "message": str(e)}) + + return res.json(result) diff --git a/python/send_message/requirements.txt b/python/send_message/requirements.txt new file mode 100644 index 00000000..724d281b --- /dev/null +++ b/python/send_message/requirements.txt @@ -0,0 +1,9 @@ +certifi==2022.9.24 +charset-normalizer==2.0.12 +idna==3.4 +oauthlib==3.2.1 +python-dotenv==0.21.0 +requests==2.27.1 +requests-oauthlib==1.3.1 +tweepy==4.10.1 +urllib3==1.26.12 diff --git a/ruby/.gitignore b/ruby/.gitignore new file mode 100644 index 00000000..81bee80d --- /dev/null +++ b/ruby/.gitignore @@ -0,0 +1,58 @@ +# Ruby gitignore from: https://github.com/github/gitignore/blob/main/Ruby.gitignore + +*.gem +*.rbc +/.config +/coverage/ +/InstalledFiles +/pkg/ +/spec/reports/ +/spec/examples.txt +/test/tmp/ +/test/version_tmp/ +/tmp/ + +# Used by dotenv library to load environment variables. +# .env + +# Ignore Byebug command history file. +.byebug_history + +## Specific to RubyMotion: +.dat* +.repl_history +build/ +*.bridgesupport +build-iPhoneOS/ +build-iPhoneSimulator/ + +## Specific to RubyMotion (use of CocoaPods): +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# vendor/Pods/ + +## Documentation cache and generated files: +/.yardoc/ +/_yardoc/ +/doc/ +/rdoc/ + +## Environment normalization: +/.bundle/ +/vendor/bundle +/lib/bundler/man/ + +# for a library or gem, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# Gemfile.lock +# .ruby-version +# .ruby-gemset + +# unless supporting rvm < 1.11.0 or doing something fancy, ignore this: +.rvmrc + +# Used by RuboCop. Remote config files pulled in from inherit_from directive. +# .rubocop-https?--* diff --git a/ruby/compress-image/Gemfile b/ruby/compress-image/Gemfile new file mode 100644 index 00000000..d9b295cf --- /dev/null +++ b/ruby/compress-image/Gemfile @@ -0,0 +1,4 @@ +source "https://rubygems.org" +gem "base64" +gem "tinify" +gem "kraken-io" \ No newline at end of file diff --git a/ruby/compress-image/README.md b/ruby/compress-image/README.md new file mode 100644 index 00000000..f4560f3f --- /dev/null +++ b/ruby/compress-image/README.md @@ -0,0 +1,65 @@ +# Compress .png Images + +A Ruby Cloud Function that compresses png images. + + +`image` and `provider` are recieved from the payload, where `image` is a base64 encoded string and `provider` is either [`tinypng`](https://tinypng.com) or [`krakenio`](https://kraken.io) + +_Example input:_ + +```json +{ + "image": "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAf0lEQVR4nO2Wuw2AMAxEbw1gpMwDDMBcGQpooDKydGVAoXCK6J7k6qyc83MCCFGP/Yz+CkDF4KHmjgowbQF0CKFrCDUiwztqxabHCL0/xwcNhoI2UdsjC8g0mQvaSs1zwkg0uQAsAEaGm9/UPCeU7eMj6loTEpf6ZOQWMxd98gAhZnS6XEZcNQAAAABJRU5ErkJggg==", + "provider": "tinypng", +} +``` + +> `krakenio` is also a supported provider + +_Example output:_ + +```json +{ + "success": true, + "image": "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAAG1BMVEUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUUeIgAAAACHRSTlMA8712Sxr5g97cFtUAAAA9SURBVCjPY6Aa6AADfAIcDSA8KoBTgLGVgSFCAEmAqZmBwUIBSYClzTQ4wwE52Cs6OtpR4oFFUciBerEKAP58HnyLtZsYAAAAAElFTkSuQmCC" +} +``` + +## 📝 Variables + +> only selected provider's api keys are neccessary, ie. kraken's api keys are not neccessary when choosing tinypng as the provider. + +- **TINYPNG_API** - API key for tinypng service +- **KRAKENIO_KEY** - API key for kraken-io service +- **KRAKENIO_SECRET** - API Secret for kraken-io service + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd ruby/compress-image +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/ruby:v2-3.1 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.rb --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/ruby:v2-3.1 sh /usr/local/src/start.sh +``` + +4. Execute function: + +```shell +curl http://localhost:3000/ -d '{"variables":{"TINYPNG_API":"[YOUR_API_KEY]"},"payload":"{\"provider\":\"tinypng\",\"image\":\"iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAf0lEQVR4nO2Wuw2AMAxEbw1gpMwDDMBcGQpooDKydGVAoXCK6J7k6qyc83MCCFGP/Yz+CkDF4KHmjgowbQF0CKFrCDUiwztqxabHCL0/xwcNhoI2UdsjC8g0mQvaSs1zwkg0uQAsAEaGm9/UPCeU7eMj6loTEpf6ZOQWMxd98gAhZnS6XEZcNQAAAABJRU5ErkJggg==\"}"}' -H "X-Internal-Challenge: secret-key" -H "Content-Type: application/json" +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/ruby-3.1). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Ruby 3.1. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/ruby/compress-image/index.rb b/ruby/compress-image/index.rb new file mode 100644 index 00000000..59eea9f6 --- /dev/null +++ b/ruby/compress-image/index.rb @@ -0,0 +1,119 @@ +require "json" +require "base64" +require "tinify" +require "kraken-io" + +class NotImageException < StandardError; end +class ApiError < StandardError; end +class NoApiError < StandardError; end + +$invalidPayload = { + success: false, message: "Invalid Payload" +} +$notImage = { + success: false, message: "Input file is not an image." +} +$invalidApi = { + success: false, message: "Invalid API." +} +$noApi = { + success: false, message: "no API key was provided." +} + +def tinypng(req, image) + # Get api key + if !req.variables['TINYPNG_API'] + raise NoApiError + end + + Tinify.key = req.variables['TINYPNG_API'] + buffer = Base64.decode64(image) + result = Tinify.from_buffer(buffer).to_buffer + + Base64.encode64(result) +end + +def krakenio(req, image) + if !req.variables['KRAKENIO_KEY'] or !req.variables['KRAKENIO_SECRET'] + raise NoApiError + end + + buffer = Base64.decode64(image) + dir = Dir.mktmpdir("kraken_temp") + + File.open("#{dir}/file.png", 'wb') do |f| + f.write(buffer) + end + + kraken = Kraken::API.new( + :api_key => req.variables['KRAKENIO_KEY'], + :api_secret => req.variables['KRAKENIO_SECRET'] + ) + + data = kraken.upload("#{dir}/file.png") + + File.delete("#{dir}/file.png") if File.exist?("#{dir}/file.png") + + if data.success + img = URI.open(data.kraked_url) + Base64.encode64(img.read) + else + if data.message.include? 'Unknown API Key' + raise ApiError + end + raise NotImageException + end +end + +def main(req, res) + # Input validation + provider = nil + image = nil + begin + payload = JSON.parse(req.payload) + provider = payload["provider"] + image = payload["image"] + rescue Exception => err + return res.json($invalidPayload) + end + + if provider.nil? or provider.empty? or image.nil? or image.empty? + return res.json($invalidPayload) + end + + if provider == 'tinypng' + begin + base64 = tinypng(req, image) + return res.json({ + success: true, + image: base64.gsub("\n",'') + }) + rescue Tinify::ClientError + return res.json($notImage) + rescue Tinify::AccountError + return res.json($invalidApi) + rescue NoApiError + return res.json($noApi) + end + end + + if provider == 'krakenio' + begin + base64 = krakenio(req, image) + return res.json({ + success: true, + image: base64.gsub("\n",'') + }) + rescue ApiError + return res.json($invalidApi) + rescue NotImageException + return res.json($notImage) + rescue NoApiError + return res.json($noApi) + end + end + + res.json({ + success: false, message: "Unsupported Providers." + }) +end \ No newline at end of file diff --git a/ruby/convert-phone-number-to-country-name/Gemfile b/ruby/convert-phone-number-to-country-name/Gemfile new file mode 100644 index 00000000..b4ff0dc7 --- /dev/null +++ b/ruby/convert-phone-number-to-country-name/Gemfile @@ -0,0 +1,2 @@ +source "https://rubygems.org" +gem "appwrite" \ No newline at end of file diff --git a/ruby/convert-phone-number-to-country-name/README.md b/ruby/convert-phone-number-to-country-name/README.md new file mode 100644 index 00000000..cce61f07 --- /dev/null +++ b/ruby/convert-phone-number-to-country-name/README.md @@ -0,0 +1,60 @@ +# 📱 Validate phone number and get it's country information + +A Ruby Cloud Function that figures out country in which a phone number is registered. + +_Example input:_ + +```json +{ + "phoneNumber": "+421957215740" +} +``` + +> Function can also accept phone numbers with spaces, for instance `+421 957 215 740`. + + +_Example output:_ + + +```json +{ + "phoneNumber": "+421957215740", + "phonePrefix": "+421", + "countryCode": "SK", + "countryName": "Slovakia" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of your Appwrite server +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key +- **APPWRITE_FUNCTION_PROJECT_ID** - Appwrite project ID. If running on Appwrite, this variable is provided automatically. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd ruby/convert_phone_number_to_country_name +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/ruby:v2-3.1 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.rb --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/ruby:v2-3.1 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Ruby runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/ruby-3.1). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Ruby 3.1. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/ruby/convert-phone-number-to-country-name/index.rb b/ruby/convert-phone-number-to-country-name/index.rb new file mode 100644 index 00000000..0d580d4e --- /dev/null +++ b/ruby/convert-phone-number-to-country-name/index.rb @@ -0,0 +1,66 @@ +require 'appwrite' +require 'json' + +=begin +Globally scoped cache used by function. Example value: +[ + { + "code": "+1", + "countryCode": "US", + "countryName": "United States" + } +] +=end +$phone_prefix_list = nil + +def main(req, res) + # Input validation + phone_number = nil + begin + payload = JSON.parse(req.payload) + phone_number = (payload['phoneNumber'] || '').delete(' ') + rescue Exception => err + puts err + raise 'Payload is invalid.' + end + + if phone_number.nil? or phone_number.empty? or !phone_number.start_with?('+') + raise 'Invalid phone number.' + end + + # Make sure we have envirnment variables required to execute + if !req.variables['APPWRITE_FUNCTION_ENDPOINT'] or !req.variables['APPWRITE_FUNCTION_PROJECT_ID'] or !req.variables['APPWRITE_FUNCTION_API_KEY'] + raise 'Please provide all required environment variables.' + end + + # If we don't have cached list of phone number prefixes (first execution only) + if $phone_prefix_list.nil? + # Init Appwrite SDK + client = Appwrite::Client.new + locale = Appwrite::Locale.new(client) + + client + .set_endpoint(req.variables['APPWRITE_FUNCTION_ENDPOINT']) + .set_project(req.variables['APPWRITE_FUNCTION_PROJECT_ID']) + .set_key(req.variables['APPWRITE_FUNCTION_API_KEY']) + + # Fetch and store phone number prefixes + server_response = locale.get_countries_phones() + $phone_prefix_list = server_response.phones + end + + # Get phone prefix + phone_prefix = $phone_prefix_list.filter_map { |prefix| prefix if phone_number.start_with?(prefix.code) } + + if phone_prefix.empty? + raise 'Invalid phone number.' + end + + # Return phone number prefix + return res.json({ + :phone_number => phone_number, + :phonePrefix => phone_prefix[0].code, + :countryCode => phone_prefix[0].country_code, + :countryName => phone_prefix[0].country_name, + }) +end \ No newline at end of file diff --git a/ruby/deepgram-audio-summary/Gemfile b/ruby/deepgram-audio-summary/Gemfile new file mode 100644 index 00000000..de42b591 --- /dev/null +++ b/ruby/deepgram-audio-summary/Gemfile @@ -0,0 +1,3 @@ +source "https://rubygems.org" + +gem "uri" diff --git a/ruby/deepgram-audio-summary/README.md b/ruby/deepgram-audio-summary/README.md new file mode 100644 index 00000000..cfba9cc8 --- /dev/null +++ b/ruby/deepgram-audio-summary/README.md @@ -0,0 +1,67 @@ +# 🔉📃 Summarize Audio with Deepgram + +A Ruby Cloud Function for summarizing audio number using [Deepgram API](https://deepgram.com/). + +_Example input:_ + +```json +{ + "fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Example output:_ + + +```json +{ + "success": true, + "deepgramData": [ + { + "summary": "another big problem in the speech analytics space. When customers first bring the software on is that they they are blown away by the fact that an engine can monitor hundreds of Kpis.", + "start_word": 0, + "end_word": 228 + } + ] +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **DEEPGRAM_API_KEY** - Deepgram API Key + +ℹ️ _Create your Deepgram API key at console.deepgram.com_ + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +```bash +git clone https://github.com/open-runtimes/examples.git && cd examples +cd ruby/deepgram-audio-summary +``` + +2. Enter this function folder and build the code: +```bash +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/ruby:v2-3.1 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +```bash +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.rb --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/ruby:v2-3.1 sh /usr/local/src/start.sh +``` + +> Make sure to replace `YOUR_API_KEY` without your key. +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/ruby-3.1). + +4. Run the cURL function to send request. +```bash +curl http://localhost:3000/ -d '{"payload": {"fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav"}, "variables": {"DEEPGRAM_API_KEY": ""}}' -H "X-Internal-Challenge: secret-key" +``` + +## 📝 Notes +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Ruby 3.1. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/ruby/deepgram-audio-summary/index.rb b/ruby/deepgram-audio-summary/index.rb new file mode 100644 index 00000000..ff4c0c03 --- /dev/null +++ b/ruby/deepgram-audio-summary/index.rb @@ -0,0 +1,54 @@ +require "uri" +require "net/http" +require "openssl" +require "json" + + +def main(req, res) + fileUrl = req.payload["fileUrl"] + deepgramApiKey = req.variables["DEEPGRAM_API_KEY"] + + url = URI("https://api.deepgram.com/v1/listen?summarize=true&punctuate=true") + http = Net::HTTP.new(url.host, url.port) + http.use_ssl = true + + request = Net::HTTP::Post.new(url) + request["content-type"] = "application/json" + request["Authorization"] = "Token #{deepgramApiKey}" + request.body = JSON.generate({url: fileUrl}) + + begin + response = http.request(request) + rescue Exception => err + return res.json({ + success: false, + message: err + }) + end + + response_body = response.read_body + if response.code=="200" + parsed_response = JSON.parse(response_body) + res.json({ + success: true, + deepgramData: parsed_response["results"] + }) + elsif valid_json?(response_body) + res.json({ + success: false, + message: JSON.parse(response_body) + }) + else + res.json({ + success: false, + message: response_body + }) + end +end + +def valid_json?(json) + JSON.parse(json) + true +rescue JSON::ParserError, TypeError => e + false +end diff --git a/ruby/deepgram-transcribe-video/Gemfile b/ruby/deepgram-transcribe-video/Gemfile new file mode 100644 index 00000000..7d5fe40a --- /dev/null +++ b/ruby/deepgram-transcribe-video/Gemfile @@ -0,0 +1,3 @@ +source "https://rubygems.org" + +gem "uri" \ No newline at end of file diff --git a/ruby/deepgram-transcribe-video/README.md b/ruby/deepgram-transcribe-video/README.md new file mode 100644 index 00000000..e55f40ed --- /dev/null +++ b/ruby/deepgram-transcribe-video/README.md @@ -0,0 +1,67 @@ +# 🔉📃 Transcribe Video with Deepgram + +A Ruby Cloud Function for transcribing video using [Deepgram API](https://deepgram.com/). + +_Example input:_ + +```json +{ + "fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav" +} +``` + +_Example output:_ + + +```json +{ + "success": "true", + "deepgramData": "another big problem in the speech analytics space. When customers first bring the software on. Is that they they are blown away by the fact that an engine can monitor hundreds of Kpis. Right? Everything from my..." +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **DEEPGRAM_API_KEY** - Deepgram API Key + +ℹ️ _Create your Deepgram API key at console.deepgram.com_ + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +git clone https://github.com/open-runtimes/examples.git && cd examples +cd ruby/deepgram-transcribe-video +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/ruby:v2-3.1 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.rb --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/ruby:v2-3.1 sh /usr/local/src/start.sh +``` + + + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/ruby-3.1). + +> Make sure to replace `YOUR_API_KEY` without your key. +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Python runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/ruby-3.1). + +4. Run the curl function to send request. +``` +curl http://localhost:3000/ -d '{"payload": {"fileUrl": "https://static.deepgram.com/examples/interview_speech-analytics.wav"}, "variables": {"DEEPGRAM_API_KEY": ""}}' -H "X-Internal-Challenge: secret-key" +``` + + + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Ruby 3.1. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/ruby/deepgram-transcribe-video/index.rb b/ruby/deepgram-transcribe-video/index.rb new file mode 100644 index 00000000..fab5e5b8 --- /dev/null +++ b/ruby/deepgram-transcribe-video/index.rb @@ -0,0 +1,54 @@ +require "uri" +require "net/http" +require "openssl" +require "json" + + +def main(req, res) + fileUrl = req.payload["fileUrl"] + deepgramApiKey = req.variables["DEEPGRAM_API_KEY"] + + url = URI("https://api.deepgram.com/v1/listen?model=video") + http = Net::HTTP.new(url.host, url.port) + http.use_ssl = true + + request = Net::HTTP::Post.new(url) + request["content-type"] = "application/json" + request["Authorization"] = "Token #{deepgramApiKey}" + request.body = JSON.generate({url: fileUrl}) + + begin + response = http.request(request) + rescue Exception => err + return res.json({ + success: false, + message: err + }) + end + + response_body = response.read_body + if response.code=="200" + parsed_response = JSON.parse(response_body) + res.json({ + success: true, + deepgramData: parsed_response["results"] + }) + elsif valid_json?(response_body) + res.json({ + success: false, + message: JSON.parse(response_body) + }) + else + res.json({ + success: false, + message: response_body + }) + end +end + +def valid_json?(json) + JSON.parse(json) + true +rescue JSON::ParserError, TypeError => e + false +end \ No newline at end of file diff --git a/ruby/send-http-request/Gemfile b/ruby/send-http-request/Gemfile new file mode 100644 index 00000000..a2fceb50 --- /dev/null +++ b/ruby/send-http-request/Gemfile @@ -0,0 +1,2 @@ +source "https://rubygems.org" +gem "httparty" diff --git a/ruby/send-http-request/README.md b/ruby/send-http-request/README.md new file mode 100644 index 00000000..a49acdef --- /dev/null +++ b/ruby/send-http-request/README.md @@ -0,0 +1,99 @@ +# 🌐 Send a HTTP Request + +A Ruby Cloud Function for sending HTTP requests that supports custom headers and body. + +_Example input:_ + +```json +{ + "headers": {}, + "variables": {}, + "payload": "{\"url\":\"https:\/\/demo.appwrite.io\/v1\/locale\/countries\/eu\",\"method\":\"GET\",\"headers\":{\"x-client-version\":\"1.0.0\"},\"body\":\"\"}" +} +``` + +_Example output:_ + +```json +{ + "success": true, + "response": { + "headers": { + "access-control-allow-credentials": [ + "true" + ], + "access-control-allow-headers": [ + "Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-Appwrite-ID, Content-Range, Range, Cache-Control, Expires, Pragma" + ], + "access-control-allow-methods": [ + "GET, POST, PUT, PATCH, DELETE" + ], + "access-control-allow-origin": [ + "https://localhost" + ], + "access-control-expose-headers": [ + "X-Fallback-Cookies" + ], + "content-length": [ + "302" + ], + "content-type": [ + "application/json; charset=UTF-8" + ], + "date": [ + "Tue, 04 Oct 2022 08:02:27 GMT" + ], + "server": [ + "Appwrite" + ], + "strict-transport-security": [ + "max-age=10886400" + ], + "x-content-type-options": [ + "nosniff" + ], + "x-debug-fallback": [ + "true" + ], + "x-debug-speed": [ + "0.0030789375305176" + ], + "connection": [ + "close" + ] + }, + "code": 200, + "body": "{\"total\":27,\"countries\":[{\"name\":\"Austria\",\"code\":\"AT\"},{\"name\":\"Belgium\",\"code\":\"BE\"},{\"name\":\"Bulgaria\",\"code\":\"BG\"},{\"name\":\"Croatia\",\"code\":\"HR\"},{\"name\":\"Cyprus\",\"code\":\"CY\"},{\"name\":\"Czechia\",\"code\":\"CZ\"},{\"name\":\"Denmark\",\"code\":\"DK\"},{\"name\":\"Estonia\",\"code\":\"EE\"},{\"name\":\"Finland\",\"code\":\"FI\"},{\"name\":\"France\",\"code\":\"FR\"},{\"name\":\"Germany\",\"code\":\"DE\"},{\"name\":\"Greece\",\"code\":\"GR\"},{\"name\":\"Hungary\",\"code\":\"HU\"},{\"name\":\"Ireland\",\"code\":\"IE\"},{\"name\":\"Italy\",\"code\":\"IT\"},{\"name\":\"Latvia\",\"code\":\"LV\"},{\"name\":\"Lithuania\",\"code\":\"LT\"},{\"name\":\"Luxembourg\",\"code\":\"LU\"},{\"name\":\"Malta\",\"code\":\"MT\"},{\"name\":\"Netherlands\",\"code\":\"NL\"},{\"name\":\"Poland\",\"code\":\"PL\"},{\"name\":\"Portugal\",\"code\":\"PT\"},{\"name\":\"Romania\",\"code\":\"RO\"},{\"name\":\"Slovakia\",\"code\":\"SK\"},{\"name\":\"Slovenia\",\"code\":\"SI\"},{\"name\":\"Spain\",\"code\":\"ES\"},{\"name\":\"Sweden\",\"code\":\"SE\"}]}" + } +} +``` + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +```bash +git clone https://github.com/open-runtimes/examples.git && cd examples +cd ruby/send-http-request +``` + +2. Enter this function folder and build the code: + +```bash +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/ruby:v2-3.1 sh /usr/local/src/build.sh +``` + +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: + +```bash +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.rb --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/ruby:v2-3.1 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit the Ruby runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/ruby-3.1). + +## 📝 Notes + +- This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). +- This example is compatible with Ruby 3.1. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/ruby/send-http-request/index.rb b/ruby/send-http-request/index.rb new file mode 100644 index 00000000..93fcf8e0 --- /dev/null +++ b/ruby/send-http-request/index.rb @@ -0,0 +1,45 @@ +require "httparty" +require "json" + +def main(req, res) + begin + payload = JSON.parse(req.payload) + url = payload["url"] + method = payload["method"] + headers = payload["headers"] + body = payload["body"] + rescue Exception => err + puts err + raise 'Payload is invalid.' + end + + if url.nil? or url.empty? or method.nil? or method.empty? + raise 'Payload is invalid.' + end + + begin + response = HTTParty.send(method.downcase, url, headers: headers, body: body) + + if response.success? + res.json({ + "success": response.success?, + "response": { + "headers": response.headers, + "code": response.code, + "body": response.body + } + }) + else + res.json({ + "success": false, + "message": { + "code": response.code, + "body": response.message + } + }) + end + rescue Exception => err + puts err + raise 'Request could not be made.' + end +end diff --git a/ruby/send-sms-with-twilio/Gemfile b/ruby/send-sms-with-twilio/Gemfile new file mode 100644 index 00000000..b75b2110 --- /dev/null +++ b/ruby/send-sms-with-twilio/Gemfile @@ -0,0 +1,2 @@ +source "https://rubygems.org" +gem "twilio-ruby" \ No newline at end of file diff --git a/ruby/send-sms-with-twilio/README.md b/ruby/send-sms-with-twilio/README.md new file mode 100644 index 00000000..7d3a8c9b --- /dev/null +++ b/ruby/send-sms-with-twilio/README.md @@ -0,0 +1,59 @@ +# 📱 Send SMS with Twilio + +A Ruby Cloud Function for sending a message to a phone number using [Twilio API](https://www.twilio.com/docs/usage/api). + +_Example input:_ + +```json +{ + "message": "Hello from Open Runtimes 👋", + "receiver": "+421XXXXXXXXX" +} +``` + +_Example output:_ + + +```json +{ + "messageId": "SMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **TWILIO_ACCOUNT_SID** - Twilio account SID +- **TWILIO_AUTH_TOKEN** - Twilio auth token +- **TWILIO_SENDER** - Sender's phone number from Twilio + +ℹ️ _Find your Account SID and Auth Token at twilio.com/console._ + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd ruby/send-sms-with-twilio +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/ruby:v2-3.1 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.rb --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/ruby:v2-3.1 sh /usr/local/src/start.sh +``` + +> Make sure to replace `secret-key` with your key. + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Ruby runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/ruby-3.1). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Ruby 3.1. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/ruby/send-sms-with-twilio/index.rb b/ruby/send-sms-with-twilio/index.rb new file mode 100644 index 00000000..17c4252b --- /dev/null +++ b/ruby/send-sms-with-twilio/index.rb @@ -0,0 +1,45 @@ +require "twilio-ruby" +require "json" + +def main(req, res) + # Input validation + message = nil + receiver = nil + begin + payload = JSON.parse(req.payload) + message = payload["message"] + receiver = payload["receiver"] + rescue Exception => err + puts err + raise 'Payload is invalid.' + end + + if message.nil? or message.empty? or receiver.nil? or receiver.empty? + raise 'Payload is invalid.' + end + + # Make sure we have envirnment variables required to execute + if !req.variables['TWILIO_ACCOUNT_SID'] or !req.variables['TWILIO_AUTH_TOKEN'] or !req.variables['TWILIO_SENDER'] + raise 'Please provide all required environment variables.' + end + + # Parse the environment variables to get account keys and the sender's mobile number. + account_sid = req.variables["TWILIO_ACCOUNT_SID"] + auth_token = req.variables["TWILIO_AUTH_TOKEN"] + sender = req.variables["TWILIO_SENDER"] + + # Create the Twilio client. + client = Twilio::REST::Client.new(account_sid, auth_token) + + # Send the message. + message = client.messages.create( + body: message, + from: sender, + to: receiver + ) + + # Return a response + res.json({ + messageId: message.sid, + }) +end \ No newline at end of file diff --git a/ruby/translate-text-with-google/Gemfile b/ruby/translate-text-with-google/Gemfile new file mode 100644 index 00000000..5737f07d --- /dev/null +++ b/ruby/translate-text-with-google/Gemfile @@ -0,0 +1,2 @@ +source "https://rubygems.org" +gem "free_google_translate" \ No newline at end of file diff --git a/ruby/translate-text-with-google/README.md b/ruby/translate-text-with-google/README.md new file mode 100644 index 00000000..c37774a0 --- /dev/null +++ b/ruby/translate-text-with-google/README.md @@ -0,0 +1,54 @@ +# 🌐 Translate text from one language to another + +A Ruby Cloud Function for translating text from one language to another using [Google Translate](https://translate.google.com/). + +_Example input:_ + +```json +{ + "text": "Hello from Open Runtimes 👋", + "source": "en", + "target": "es" +} +``` + +_Example output:_ + +```json +{ + "text": "Hello from Open Runtimes 👋", + "translation": "Saludos desde Open Runtime 👋" +} +``` + +## 📝 Environment Variables + +No environment variables needed. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd ruby/translate-text-with-google +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/ruby:v2-3.1 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key -e INTERNAL_RUNTIME_ENTRYPOINT=index.rb --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/ruby:v2-3.1 sh /usr/local/src/start.sh +``` + +> Make sure to replace `secret-key` with your key. + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Ruby runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/ruby-3.1). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Ruby 3.1. Other versions may work but are not guaranteed to work as they haven't been tested. diff --git a/ruby/translate-text-with-google/index.rb b/ruby/translate-text-with-google/index.rb new file mode 100644 index 00000000..04498916 --- /dev/null +++ b/ruby/translate-text-with-google/index.rb @@ -0,0 +1,35 @@ +require "free_google_translate" +require "json" + +def main(req, res) + # Input validation + text = nil + source = nil + target = nil + begin + payload = JSON.parse(req.payload) + text = payload["text"] + source = payload["source"] + target = payload["target"] + rescue Exception => err + puts err + raise 'Payload is invalid.' + end + + if text.nil? or text.empty? or source.nil? or source.empty? or target.nil? or target.empty? + raise 'Payload is invalid.' + end + + # Translate your text + translation = GoogleTranslate.translate( + from: source, + to: target, + text: text + ) + + # Return the translation + res.json({ + "text": text, + "translation": translation + }) +end diff --git a/ruby/wipe-appwrite-bucket/Gemfile b/ruby/wipe-appwrite-bucket/Gemfile new file mode 100644 index 00000000..a25455c8 --- /dev/null +++ b/ruby/wipe-appwrite-bucket/Gemfile @@ -0,0 +1,3 @@ +source "https://rubygems.org" + +gem 'appwrite' \ No newline at end of file diff --git a/ruby/wipe-appwrite-bucket/README.md b/ruby/wipe-appwrite-bucket/README.md new file mode 100644 index 00000000..561ca052 --- /dev/null +++ b/ruby/wipe-appwrite-bucket/README.md @@ -0,0 +1,50 @@ +# 🗑 Wipe Appwrite Bucket + +A Ruby cloud function to wipe a complete bucket in Appwrite by passing the bucket id as a payload. + +_Example input:_ + +```json +{ + "bucketId":"profilePictures" +} +``` + +_Example output:_ + +```json +{ + "success":true +} +``` + +_Example error output:_ + +```json +{ + "success":false, + "message":"bucketId was not provided." +} +``` + +## 📝 Variables + +List of variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key +- **APPWRITE_FUNCTION_PROJECT_ID** - Appwrite project ID. If running on Appwrite, this variable is provided automatically. + +## 🚀 Deployment + +There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience. + +### Using CLI + +Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`. + +Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy. + +### Manual using tar.gz + +Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `index.rb`, and upload the file we just generated. diff --git a/ruby/wipe-appwrite-bucket/index.rb b/ruby/wipe-appwrite-bucket/index.rb new file mode 100644 index 00000000..71b757bc --- /dev/null +++ b/ruby/wipe-appwrite-bucket/index.rb @@ -0,0 +1,62 @@ +require 'appwrite' + +def main(req, res) + client = Appwrite::Client.new + storage = Appwrite::Storage.new(client) + + if !req.variables['APPWRITE_FUNCTION_ENDPOINT'] or !req.variables['APPWRITE_FUNCTION_API_KEY'] or !req.variables['APPWRITE_FUNCTION_PROJECT_ID'] + return res.json({ + :success => false, + :message => 'Environment variables are not set. Function cannot use Appwrite SDK.', + }) + end + + bucket_id = nil + begin + payload = JSON.parse(req.payload) + bucket_id = (payload['bucketId'] || '').delete(' ') + rescue Exception => err + return res.json({ + :success => false, + :message => 'Payload is invalid.', + }) + end + + if !bucket_id || bucket_id == '' + return res.json({ + :success => false, + :message => 'bucketId was not provided.', + }) + end + + client + .set_endpoint(req.variables['APPWRITE_FUNCTION_ENDPOINT']) + .set_project(req.variables['APPWRITE_FUNCTION_PROJECT_ID']) + .set_key(req.variables['APPWRITE_FUNCTION_API_KEY']) + .set_self_signed(true) + + done = false + while !done do + file_list = nil + begin + file_list = storage.list_files(bucket_id: bucket_id) + rescue Exception => err + return res.json({ + :success => false, + :message => 'Failed to get file list.', + }) + end + + file_list.files.each do |file| + storage.delete_file(bucket_id: bucket_id, file_id: file.id) + end + + if file_list.files.count <= 0 + done = true + end + end + + return res.json({ + :success => true, + }) +end diff --git a/ruby/wipe-appwrite-collection/Gemfile b/ruby/wipe-appwrite-collection/Gemfile new file mode 100644 index 00000000..a25455c8 --- /dev/null +++ b/ruby/wipe-appwrite-collection/Gemfile @@ -0,0 +1,3 @@ +source "https://rubygems.org" + +gem 'appwrite' \ No newline at end of file diff --git a/ruby/wipe-appwrite-collection/README.md b/ruby/wipe-appwrite-collection/README.md new file mode 100644 index 00000000..cae39494 --- /dev/null +++ b/ruby/wipe-appwrite-collection/README.md @@ -0,0 +1,53 @@ +# 🧹 Wipe Appwrite Collection + +A Ruby Cloud Function that wipes all documents from an Appwrite collection. + +_Example input:_ + +```json +{ + "databaseId":"stage", + "collectionId":"profiles" +} +``` + +_Example output:_ + + +```json +{ + "success":true +} +``` + +_Example error output:_ + + +```json +{ + "success":false, + "message":"databaseId was not provided." +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of Appwrite project +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key +- **APPWRITE_FUNCTION_PROJECT_ID** - Appwrite project ID. If running on Appwrite, this variable is provided automatically. + +## 🚀 Deployment + +There are two ways of deploying the Appwrite function, both having the same results, but each using a different process. We highly recommend using CLI deployment to achieve the best experience. + +### Using CLI + +Make sure you have [Appwrite CLI](https://appwrite.io/docs/command-line#installation) installed, and you have successfully logged into your Appwrite server. To make sure Appwrite CLI is ready, you can use the command `appwrite client --debug` and it should respond with green text `✓ Success`. + +Make sure you are in the same folder as your `appwrite.json` file and run `appwrite deploy function` to deploy your function. You will be prompted to select which functions you want to deploy. + +### Manual using tar.gz + +Manual deployment has no requirements and uses Appwrite Console to deploy the tag. First, enter the folder of your function. Then, create a tarball of the whole folder and gzip it. After creating `.tar.gz` file, visit Appwrite Console, click on the `Deploy Tag` button and switch to the `Manual` tab. There, set the `entrypoint` to `index.rb`, and upload the file we just generated. diff --git a/ruby/wipe-appwrite-collection/index.rb b/ruby/wipe-appwrite-collection/index.rb new file mode 100644 index 00000000..13171834 --- /dev/null +++ b/ruby/wipe-appwrite-collection/index.rb @@ -0,0 +1,71 @@ +require 'appwrite' + +def main(req, res) + client = Appwrite::Client.new + database = Appwrite::Databases.new(client) + + if !req.variables['APPWRITE_FUNCTION_ENDPOINT'] or !req.variables['APPWRITE_FUNCTION_API_KEY'] + return res.json({ + :success => false, + :message => 'Environment variables are not set. Function cannot use Appwrite SDK.', + }) + end + + database_id = nil + collection_id = nil + begin + payload = JSON.parse(req.payload) + database_id = (payload['databaseId'] || '').delete(' ') + collection_id = (payload['collectionId'] || '').delete(' ') + rescue Exception => err + return res.json({ + :success => false, + :message => 'Payload is invalid.', + }) + end + + if !database_id || database_id == '' + return res.json({ + :success => false, + :message => 'databaseId was not provided.', + }) + end + + if !collection_id || collection_id == '' + return res.json({ + :success => false, + :message => 'collectionId was not provided.', + }) + end + + client + .set_endpoint(req.variables['APPWRITE_FUNCTION_ENDPOINT']) + .set_project(req.variables['APPWRITE_FUNCTION_PROJECTID']) + .set_key(req.variables['APPWRITE_FUNCTION_API_KEY']) + .set_self_signed(true) + + done = false + while !done do + document_list = nil + begin + document_list = database.list_documents(database_id: database_id, collection_id: collection_id) + rescue Exception => err + return res.json({ + :success => false, + :message => 'Failed to get documents list.', + }) + end + + document_list.documents.each do |document| + database.delete_document(database_id: database_id, collection_id: collection_id, document_id: document.id) + end + + if document_list.documents.count <= 0 + done = true + end + end + + return res.json({ + :success => true, + }) +end diff --git a/swift/.gitignore b/swift/.gitignore new file mode 100644 index 00000000..cbcb4d2a --- /dev/null +++ b/swift/.gitignore @@ -0,0 +1,91 @@ +# Swift Gitignore from https://github.com/github/gitignore/blob/main/Swift.gitignore +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +## Obj-C/Swift specific +*.hmap + +## App packaging +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +# *.xcodeproj +# +# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata +# hence it is not needed unless you have added a package configuration file to your project +# .swiftpm + +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ +# +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build/ + +# Accio dependency management +Dependencies/ +.accio/ + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. +# Instead, use fastlane to re-generate the screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ diff --git a/swift/convert-phone-number-to-country-name/Package.swift b/swift/convert-phone-number-to-country-name/Package.swift new file mode 100644 index 00000000..c0c7602e --- /dev/null +++ b/swift/convert-phone-number-to-country-name/Package.swift @@ -0,0 +1,22 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "swift-5.5", + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + .package(url: "https://github.com/appwrite/sdk-for-swift", .upToNextMajor(from: "0.3.0")), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .executableTarget( + name: "swift-5.5", + dependencies: [ + .product(name: "Appwrite", package: "sdk-for-swift") + ]), + ] +) \ No newline at end of file diff --git a/swift/convert-phone-number-to-country-name/README.md b/swift/convert-phone-number-to-country-name/README.md new file mode 100644 index 00000000..e9d81af9 --- /dev/null +++ b/swift/convert-phone-number-to-country-name/README.md @@ -0,0 +1,60 @@ +# 📱 Validate phone number and get it's country information + +A Swift Cloud Function that figures out country in which a phone number is registered. + +_Example input:_ + +```json +{ + "phoneNumber": "+421957215740" +} +``` + +> Function can also accept phone numbers with spaces, for instance `+421 957 215 740`. + + +_Example output:_ + + +```json +{ + "phoneNumber": "+421957215740", + "phonePrefix": "+421", + "countryCode": "SK", + "countryName": "Slovakia" +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +- **APPWRITE_FUNCTION_ENDPOINT** - Endpoint of your Appwrite server +- **APPWRITE_FUNCTION_API_KEY** - Appwrite API Key +- **APPWRITE_FUNCTION_PROJECT_ID** - Appwrite project ID. If running on Appwrite, this variable is provided automatically. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd swift/convert_phone_number_to_country_name +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/swift:v2-5.5 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/swift:v2-5.5 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Swift runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/swift-5.5). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Swift 5.5. Other versions may work but are not guaranteed to work as they haven't been tested. \ No newline at end of file diff --git a/swift/convert-phone-number-to-country-name/Sources/index.swift b/swift/convert-phone-number-to-country-name/Sources/index.swift new file mode 100644 index 00000000..9f941886 --- /dev/null +++ b/swift/convert-phone-number-to-country-name/Sources/index.swift @@ -0,0 +1,97 @@ +// +// File.swift +// +// +// +// + +import Foundation +import Appwrite +import AppwriteModels + +enum ExampleError : Error { + case missing(String) + case invalid(String) +} + +/* +Globally scoped cache used by function. Example value: +[ + { + "code": "+1", + "countryCode": "US", + "countryName": "United States" + } +] +*/ + +struct PhonePrefix { + let code: String + let countryCode: String + let countryName: String +} + +var phonePrefixList:PhoneList?; + +func main(req: RequestValue, res: RequestResponse) async throws -> RequestResponse { + var phoneNumber = "" + + guard let data = (req.payload.isEmpty ? "{}" : req.payload).data(using: .utf8), + let payload = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { + return res.json(data: ["error": "Invalid payload."]) + } + + phoneNumber = payload["phoneNumber"] as? String ?? "" + + guard phoneNumber.hasPrefix("+") else { + throw ExampleError.invalid("Invalid phone number") + } + + guard let endpoint = req.variables["APPWRITE_FUNCTION_ENDPOINT"], + let projectId = req.variables["APPWRITE_FUNCTION_PROJECT_ID"], + let apiKey = req.variables["APPWRITE_FUNCTION_API_KEY"] else { + throw ExampleError.missing("Please provide all required environment variables") + } + + if phonePrefixList == nil { + let group = DispatchGroup() + + let client = Client() + .setEndpoint(endpoint) + .setProject(projectId) + .setKey(apiKey) + + let locale = Locale(client) + + group.enter() + locale.getCountriesPhones() { result in + defer { group.leave() } + + switch result { + case .failure: + break + case .success(let list): + phonePrefixList = list + } + } + + group.wait() + } + + if phonePrefixList == nil { + throw ExampleError.invalid("Unable to fetch phone prefix list") + } + + guard let phonePrefix = phonePrefixList!.phones.first(where: { prefix -> Bool in + return phoneNumber.hasPrefix(prefix.code) + }) else { + throw ExampleError.invalid("Invalid phone number") + } + + return res.json(data: [ + "phoneNumber": phoneNumber, + "phonePrefix": phonePrefix.code, + "countryCode": phonePrefix.countryCode, + "countryName": phonePrefix.countryName, + ]) +} \ No newline at end of file diff --git a/swift/get-covid-stats/CovidData.swift b/swift/get-covid-stats/CovidData.swift new file mode 100644 index 00000000..8e95730a --- /dev/null +++ b/swift/get-covid-stats/CovidData.swift @@ -0,0 +1,39 @@ +struct CovidData : Codable { + let global: Global + let countries: [Country] + + enum CodingKeys : String, CodingKey { + case global = "Global" + case countries = "Countries" + } +} + +struct Global : Codable { + let newConfirmed: Int + let newDeaths: Int + let newRecovered: Int + + enum CodingKeys: String, CodingKey { + case newConfirmed = "NewConfirmed" + case newDeaths = "NewDeaths" + case newRecovered = "NewRecovered" + } +} + +struct Country : Codable { + let country: String + let countryCode: String + let slug: String + let newConfirmed: Int + let newDeaths: Int + let newRecovered: Int + + enum CodingKeys: String, CodingKey { + case country = "Country" + case countryCode = "CountryCode" + case slug = "Slug" + case newConfirmed = "NewConfirmed" + case newDeaths = "NewDeaths" + case newRecovered = "NewRecovered" + } +} diff --git a/swift/get-covid-stats/Index.swift b/swift/get-covid-stats/Index.swift new file mode 100644 index 00000000..e788a716 --- /dev/null +++ b/swift/get-covid-stats/Index.swift @@ -0,0 +1,46 @@ +import AsyncHTTPClient +import Foundation +import NIOCore +import NIOFoundationCompat + +func main(req: RequestValue, res: RequestResponse) async throws -> RequestResponse { + let httpClient = HTTPClient(eventLoopGroupProvider: .createNew) + + guard !req.payload.isEmpty, + let data = req.payload.data(using: .utf8), + let payload: [String: Any?] = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], + let countryId = payload["country"] as? String else { + return res.json(data: ["error": "Invalid payload."]) + } + + let request = HTTPClientRequest(url: "https://api.covid19api.com/summary") + let response = try await httpClient.execute(request, timeout: .seconds(30)) + let body = try await response.body.collect(upTo: 1024*1024) // 1MB + + if (response.status != .ok) { + return res.json(data: ["error": "Failed to fetch data: \(body)"]) + } + + let covidData = try! JSONDecoder().decode(CovidData.self, from: body) + + let resultCountry = covidData.countries.filter { + [ + $0.countryCode.lowercased(), + $0.country.lowercased(), + $0.slug.lowercased() + ].contains(countryId.lowercased()) + }.first + + // Variables that will be shown in output + let country = resultCountry?.country ?? "The World" + let confirmedCasesToday = resultCountry?.newConfirmed ?? covidData.global.newConfirmed + let deathsToday = resultCountry?.newDeaths ?? covidData.global.newDeaths + let recoveredToday = resultCountry?.newRecovered ?? covidData.global.newRecovered + + return res.json(data: [ + "country": country, + "confirmedCasesToday": confirmedCasesToday, + "deathsToday": deathsToday, + "recoveredToday": recoveredToday + ]) +} \ No newline at end of file diff --git a/swift/get-covid-stats/Package.swift b/swift/get-covid-stats/Package.swift new file mode 100644 index 00000000..f2163574 --- /dev/null +++ b/swift/get-covid-stats/Package.swift @@ -0,0 +1,22 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "GetCovidStats", + dependencies: [ + // Dependencies declare other packages that this package depends on. + .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.9.0") + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .executableTarget( + name: "GetCovidStats", + dependencies: [ + .product(name: "AsyncHTTPClient", package: "async-http-client") + ] + ), + ] +) diff --git a/swift/get-covid-stats/README.md b/swift/get-covid-stats/README.md new file mode 100644 index 00000000..eb47b3ad --- /dev/null +++ b/swift/get-covid-stats/README.md @@ -0,0 +1,53 @@ +# 🦠 Get COVID-19 stats from an API + +A Swift Cloud Function for fetching COVID information using [Covid19Api](https://covid19api.com/). + +_Example input:_ + +```json +{ + "country": "NZ" +} +``` + +_Example output:_ + + +```json +{ + "country": "New Zealand", + "confirmedCasesToday": 2, + "recoveredToday": 4, + "deathsToday": 0 +} +``` + +## 📝 Environment Variables + +No environment variables needed. + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd swift/convert_phone_number_to_country_name +``` + +2. Enter this function folder and build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/swift:v2-5.5 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/swift:v2-5.5 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Swift runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/swift-5.5). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with Swift 5.5. Other versions may work but are not guarenteed to work as they haven't been tested. \ No newline at end of file diff --git a/swift/send-email-with-mailgun/.gitignore b/swift/send-email-with-mailgun/.gitignore new file mode 100644 index 00000000..d6311f2f --- /dev/null +++ b/swift/send-email-with-mailgun/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +/.Package.resolved +/*.xcodeproj +xcuserdata/ +DerivedData/ +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata diff --git a/swift/send-email-with-mailgun/Index.swift b/swift/send-email-with-mailgun/Index.swift new file mode 100644 index 00000000..d3e5948e --- /dev/null +++ b/swift/send-email-with-mailgun/Index.swift @@ -0,0 +1,49 @@ +import AsyncHTTPClient +import Foundation + +func main(req: RequestValue, res: RequestResponse) async throws -> RequestResponse { + + guard !req.payload.isEmpty, + let data = req.payload.data(using: .utf8), + let payload: [String: Any?] = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], + let name = payload["name"] as? String, + let email = payload["email"] as? String else { + return res.json(data: ["error": "Invalid payload."]) + } + + guard let mailgunDomain = req.variables["MAILGUN_DOMAIN"], + let mailgunAPIKey = req.variables["MAILGUN_API_KEY"] else { + return res.json(data: ["error": "Missing environment variables."]) + } + + let message = "Welcome \(name)!" + let targetURL = "https://api.mailgun.net/v3/\(mailgunDomain)/messages" + let auth = "api:\(mailgunAPIKey)".data(using: .utf8)!.base64EncodedString() + let params = [ + "from" : "Excited User ", + "to" : email, + "subject" : "Hello", + "text" : message + ] + + let httpClient = HTTPClient(eventLoopGroupProvider: .createNew) + var request = HTTPClientRequest(url: targetURL) + request.method = .POST + request.headers.add(name: "Content-Type", value: "multipart/form-data") + request.headers.add(name: "Authorization", value: "Basic \(auth)") + + buildMultipart(&request, with: params) + + let response = try await httpClient.execute(request, timeout: .seconds(30)) + var body = try await response.body.collect(upTo: 1024*1024) //1MB + let string = body.readString(length: body.readableBytes) + + if response.status == .ok { + return res.send(data: string ?? "OK") + } else { + return res.json(data: [ + "code": 500, + "message": string ?? "Unknown error" + ]) + } +} \ No newline at end of file diff --git a/swift/send-email-with-mailgun/MultipartUtils.swift b/swift/send-email-with-mailgun/MultipartUtils.swift new file mode 100644 index 00000000..f0d4cd2d --- /dev/null +++ b/swift/send-email-with-mailgun/MultipartUtils.swift @@ -0,0 +1,81 @@ +import AsyncHTTPClient +import NIO + +let DASHDASH = "--" +let CRLF = "\r\n" +let boundaryChars = "abcdefghijklmnopqrstuvwxyz1234567890" + +open class File { + public let name: String + public var buffer: ByteBuffer + + public init(name: String, buffer: ByteBuffer) { + self.name = name + self.buffer = buffer + } +} + +func randomBoundary() -> String { + var string = "" + for _ in 0..<16 { + string.append(boundaryChars.randomElement()!) + } + return string +} + +func buildMultipart( + _ request: inout HTTPClientRequest, + with params: [String: Any?] = [:] +) { + func addPart(name: String, value: Any) { + bodyBuffer.writeString(DASHDASH) + bodyBuffer.writeString(boundary) + bodyBuffer.writeString(CRLF) + bodyBuffer.writeString("Content-Disposition: form-data; name=\"\(name)\"") + + if let file = value as? File { + bodyBuffer.writeString("; filename=\"\(file.name)\"") + bodyBuffer.writeString(CRLF) + bodyBuffer.writeString("Content-Length: \(bodyBuffer.readableBytes)") + bodyBuffer.writeString(CRLF+CRLF) + bodyBuffer.writeBuffer(&file.buffer) + bodyBuffer.writeString(CRLF) + return + } + + let string = String(describing: value) + bodyBuffer.writeString(CRLF) + bodyBuffer.writeString("Content-Length: \(string.count)") + bodyBuffer.writeString(CRLF+CRLF) + bodyBuffer.writeString(string) + bodyBuffer.writeString(CRLF) + } + + let boundary = randomBoundary() + var bodyBuffer = ByteBuffer() + + for (key, value) in params { + switch key { + case "file": + addPart(name: key, value: value!) + default: + if let list = value as? [Any] { + for listValue in list { + addPart(name: "\(key)[]", value: listValue) + } + continue + } + addPart(name: key, value: value!) + } + } + + bodyBuffer.writeString(DASHDASH) + bodyBuffer.writeString(boundary) + bodyBuffer.writeString(DASHDASH) + bodyBuffer.writeString(CRLF) + + request.headers.remove(name: "content-type") + request.headers.add(name: "Content-Length", value: bodyBuffer.readableBytes.description) + request.headers.add(name: "Content-Type", value: "multipart/form-data;boundary=\"\(boundary)\"") + request.body = .bytes(bodyBuffer) +} diff --git a/swift/send-email-with-mailgun/Package.swift b/swift/send-email-with-mailgun/Package.swift new file mode 100644 index 00000000..1acaa88b --- /dev/null +++ b/swift/send-email-with-mailgun/Package.swift @@ -0,0 +1,18 @@ +// swift-tools-version:5.3 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "WelcomeEmail", + dependencies: [ + .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.9.0"), + ], + targets: [ + .target( + name: "WelcomeEmail", + dependencies: [ + .product(name: "AsyncHTTPClient", package: "async-http-client"), + ]) + ] +) diff --git a/swift/send-email-with-mailgun/README.md b/swift/send-email-with-mailgun/README.md new file mode 100644 index 00000000..41adbc55 --- /dev/null +++ b/swift/send-email-with-mailgun/README.md @@ -0,0 +1,57 @@ +# 📧 Sending Welcome Emails using Mailgun's Email API + +A sample Swift Cloud Function for sending emails using the Mailgun API. + + +_Example input:_ + +```json +{ + "name": "John Doe", + "email": "johndoe@gmail.com" +} +``` + + +_Example output:_ + + +```json +{ + "id":"", + "message":"Queued. Thank you." +} +``` + +## 📝 Environment Variables + +List of environment variables used by this cloud function: + +* **MAILGUN_API_KEY** - API Key for Mailgun +* **MAILGUN_DOMAIN** - Domain Name from Mailgun + +## 🚀 Deployment + +1. Clone this repository, and enter this function folder: + +``` +$ git clone https://github.com/open-runtimes/examples.git && cd examples +$ cd swift/send-email-with-mailgun +``` + +2. Build the code: +``` +docker run --rm --interactive --tty --volume $PWD:/usr/code openruntimes/swift:v2-5.5 sh /usr/local/src/build.sh +``` +As a result, a `code.tar.gz` file will be generated. + +3. Start the Open Runtime: +``` +docker run -p 3000:3000 -e INTERNAL_RUNTIME_KEY=secret-key --rm --interactive --tty --volume $PWD/code.tar.gz:/tmp/code.tar.gz:ro openruntimes/swift:v2-5.5 sh /usr/local/src/start.sh +``` + +Your function is now listening on port `3000`, and you can execute it by sending `POST` request with appropriate authorization headers. To learn more about runtime, you can visit Swift runtime [README](https://github.com/open-runtimes/open-runtimes/tree/main/runtimes/swift-5.5). + +## 📝 Notes + - This function is designed for use with Appwrite Cloud Functions. You can learn more about it in [Appwrite docs](https://appwrite.io/docs/functions). + - This example is compatible with NodeJS 5.5. \ No newline at end of file From 5982fc0341f89b359e71f8cf2b8e4925c1e921ff Mon Sep 17 00:00:00 2001 From: rubynguyen1510 <50710444+rubynguyen1510@users.noreply.github.com> Date: Tue, 18 Jul 2023 18:34:03 +0000 Subject: [PATCH 2/6] deleted .DS_Store file --- python/.DS_Store | Bin 8196 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 python/.DS_Store diff --git a/python/.DS_Store b/python/.DS_Store deleted file mode 100644 index 50853ab1f1f3cda04b7104f8e316b6cbc80b3d6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8196 zcmeHMU2GLa6rOKeV0WSI@ZUu)UaV9K1q=Owioop;QvQ)!+ENPT{w#Fky}Q@DdvAeS zt$%O+#TYdb)Tobu!9*X_2Yf?#($pv~7=17?Xkubw;**}8*;_0>lK3J?cbb_qbIzQZ zd(M1kCTGhSLwg~;hOuhKm`c^Bd?q!wD8AgUHx(t|loJK%GnQv2bLnptvu>IlGC~i8 z9tb@UdLZ;b=z+Vz1N3J5MZL|tFQs7{dLZ<`l=OgqKSZheG#1b?NyXJcjYt8A`YC`Y z)TcZ^=tKh=3+R}nLY3B(*#iPq1StljI?1E{bfU3iv-9Vauu_u@VcBM0C|hZh zrVR92cG?+kcM5je73;*MKx{O~jggTx%`L6<(WdoHqxI2|buG>H(Z-gB(NRrZxNObF zZAY>vPL4b=`s7>EPz09+tGdDPQ+KjD;}$!l)n)TbR)05PwLa76>Fv`8`J5sdvnS_S zj_vlCd6(!QuX4!&+ft6bH*fm#-jtImWNmkl&rT&WsX`{ugC|o|6xR`-G5NcF`ip(}_#utEyTPTOp4}IJPF%AV(TKZ3bIS z4_Ox*pbum@c7naYPP4b!S@sG0f?Z}`u`BE<`=0&4eq`6!@9a;Mp&ZjO0~`hx;T}Y= z0*z=wGup5nJFpYG5yt=y;V_QCgbfEdotJEqFD9e>PWv#MKiOHX?lme(Ny7OCx+5MS>jOuh&NSbczBwtc$FSaD{?T4p&DS zbY4cGCF0m@TROL^YP67RynGdaObV)}s|0@G!PuE4l=ByU~MQ96&!(gxsSTf Date: Tue, 18 Jul 2023 15:15:19 -0700 Subject: [PATCH 3/6] modified main --- python/compress-image/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/compress-image/main.py b/python/compress-image/main.py index d87c0ae2..0a04057e 100644 --- a/python/compress-image/main.py +++ b/python/compress-image/main.py @@ -34,7 +34,7 @@ def krakenio_impl(variables): "api_key": variables["api_key"], "api_secret": variables["api_secret_key"] }, - "wait": True, # Optional: Wait for the optimization to complete + "wait": True, # Optional: Wait for the optimization to complete. "dev": False, # Optional: Set to false to enter user mode. } response = requests.post( From 57173ec02976ad80e14851ea138016a63626e040 Mon Sep 17 00:00:00 2001 From: Noah Jacinto Date: Tue, 18 Jul 2023 16:23:09 -0700 Subject: [PATCH 4/6] added request and parameterized to requirements --- python/compress-image/requirements.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/compress-image/requirements.txt b/python/compress-image/requirements.txt index c65c821b..1fad875b 100644 --- a/python/compress-image/requirements.txt +++ b/python/compress-image/requirements.txt @@ -1 +1,3 @@ -tinify==1.6.0 \ No newline at end of file +tinify==1.6.0 +requests==2.31.0 +parameterized==0.9.0 \ No newline at end of file From 1507bcf2e9aec630e37b38a15223c81023733b94 Mon Sep 17 00:00:00 2001 From: Noah Jacinto <95050103+Mushmou@users.noreply.github.com> Date: Thu, 27 Jul 2023 10:17:05 -0700 Subject: [PATCH 5/6] Update README.md Addressed stnguyen90 regarding 3 different variables for TinyPNG and KrakenIO. --- python/compress-image/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/compress-image/README.md b/python/compress-image/README.md index 5cd636fb..24267bd0 100644 --- a/python/compress-image/README.md +++ b/python/compress-image/README.md @@ -36,9 +36,9 @@ Example error output: ## 📝 Environment Variables List of environment variables used by this cloud function: - -- **API_KEY** - Tinypng API Key or KrakenIO API Key -- **SECRET_API_KEY** - KrakenIO Secret API Key +- **TINYPNG_KEY** - Tinypng API Key +- **KRAKENIO_KEY** - KrakenIO API Key +- **KRAKENIO_SECRET_KEY** - KrakenIO Secret API Key ℹ️ _Create your TinyPNG API key at https://tinypng.com/developers_.
From 2387de04f4cc8377552abfbe7d026376639c4989 Mon Sep 17 00:00:00 2001 From: rubynguyen1510 <50710444+rubynguyen1510@users.noreply.github.com> Date: Fri, 28 Jul 2023 23:46:57 +0000 Subject: [PATCH 6/6] fixed functions' names and added object-oriented approach --- python/compress-image/main.py | 25 ++++++------ python/compress-image/test_main.py | 62 +++++++++++++++--------------- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/python/compress-image/main.py b/python/compress-image/main.py index 0a04057e..d9b40555 100644 --- a/python/compress-image/main.py +++ b/python/compress-image/main.py @@ -11,7 +11,7 @@ ) -def krakenio_impl(variables): +def implement_krakenio(variables): """ Implements image optimization using the Kraken.io API. @@ -56,7 +56,7 @@ def krakenio_impl(variables): return optimized_image -def tinypng_impl(variables): +def implement_tinypng(variables): """ Implements image optimization using the Tinypng API. @@ -85,19 +85,19 @@ def validate_request(req): """ # Check if payload is empty if not req.payload: - raise ValueError("Missing payload") + raise ValueError("Missing payload.") # Accessing provider from payload if not req.payload.get("provider"): - raise ValueError("Missing provider") + raise ValueError("Missing provider.") # Check if payload is not empty if not req.variables: raise ValueError("Missing variables.") # Accessing api_key from variables if not req.variables.get("API_KEY"): - raise ValueError("Missing API_KEY") + raise ValueError("Missing API_KEY.") # Accessing encoded image from payload if not req.payload.get("image"): - raise ValueError("Missing encoding image") + raise ValueError("Missing encoding image.") result = { "provider": req.payload.get("provider").lower(), "api_key": req.variables.get("API_KEY"), @@ -111,12 +111,6 @@ def validate_request(req): return result -IMPLEMENTATIONS = { - "krakenio": krakenio_impl, - "tinypng": tinypng_impl, - } - - def main(req, res): """ The main function that runs validate_request and calls IMPLEMENTATIONS. @@ -136,7 +130,12 @@ def main(req, res): "error": f"{value_error}", }) try: - optimized_image = IMPLEMENTATIONS[variables["provider"]](variables) + if variables["provider"] == "tinypng": + optimized_image = implement_tinypng(variables) + elif variables["provider"] == "krakenio": + optimized_image = implement_krakenio(variables) + else: + raise ValueError("Invalid provider.") except Exception as error: return res.json({ "success": False, diff --git a/python/compress-image/test_main.py b/python/compress-image/test_main.py index 102e4c5d..0f25a284 100644 --- a/python/compress-image/test_main.py +++ b/python/compress-image/test_main.py @@ -1,4 +1,4 @@ -""" Unittests for Compress Image implementation in main.py""" +""" Unittests for Compress Image implementation in main.py.""" # Standard library import base64 import pathlib @@ -29,12 +29,12 @@ class TestTinypng(unittest.TestCase): - """Class for testing the functionality of the "tinypng_impl" function.""" - @unittest.skipUnless(secret.API_KEY_TINYPNG, "No Tinypng API Key set") + """Class for testing the functionality of the "implement_tinypng" function.""" + @unittest.skipUnless(secret.API_KEY_TINYPNG, "No Tinypng API Key set.") def test_tinypng_happy_path(self): - """Test case optimizing 1kb image using "tinypng_impl" function.""" + """Test case optimizing 1kb image using "implement_tinypng" function.""" want = RESULT_TINYPNG - got = main.tinypng_impl( + got = main.implement_tinypng( { "api_key": secret.API_KEY_TINYPNG, "decoded_image": IMAGE, @@ -43,11 +43,11 @@ def test_tinypng_happy_path(self): self.assertEqual(base64.b64encode(got).decode(), want) def test_tinypng_credential(self): - """Test case handling Account errors in the "tinypng_impl" function.""" + """Test case handling Account errors in the "implement_tinypng" function.""" # Incorrect Credential self.assertRaises( tinify.errors.AccountError, - main.tinypng_impl, + main.implement_tinypng, { "api_key": "1NCORRECT4CREDENT1ALS", "decoded_image": IMAGE, @@ -60,13 +60,13 @@ def test_tinypng_credential(self): (b"ORw0KGgoAAAANSUhEUgAAABEAAAAOCAMAAAD+M",), ]) def test_tinypng_client(self, image): - """Test case for Client errors in the "tinypng_impl" function.""" + """Test case for Client errors in the "implement_tinypng" function.""" # Image is empty data = { "api_key": secret.API_KEY_TINYPNG, "decoded_image": image, } - self.assertRaises(tinify.errors.ClientError, main.tinypng_impl, data) + self.assertRaises(tinify.errors.ClientError, main.implement_tinypng, data) @unittest.skipUnless(secret.API_KEY_TINYPNG, "No Tinypng API Key set.") @parameterized.expand([ @@ -84,41 +84,41 @@ def test_tinypng_client(self, image): ), ]) def test_tinypng_keys(self, data): - """Test case for handling KeyError in the "tinypng_impl" function.""" + """Test case for handling KeyError in the "implement_tinypng" function.""" # Accessing wrong key self.assertRaises( KeyError, - main.tinypng_impl, + main.implement_tinypng, data, ) @unittest.skipUnless(secret.API_KEY_TINYPNG, "No Tinypng API Key set.") def test_tinypng_variables(self): - """Test case handling variables in the "tinypng_impl" function.""" + """Test case handling variables in the "implement_tinypng" function.""" # Empty variables self.assertRaises( KeyError, - main.tinypng_impl, + main.implement_tinypng, {}, ) # One key in variable self.assertRaises( KeyError, - main.tinypng_impl, + main.implement_tinypng, { "api_key": secret.API_KEY_TINYPNG }, ) @unittest.skipUnless(secret.API_KEY_TINYPNG, "No Tinypng API Key set.") - def test_tinypng_impl_basic_functionality_1kb(self): - """Basic functionality of "tinypng_impl" with a 1kb image.""" + def test_implement_tinypng_basic_functionality_1kb(self): + """Basic functionality of "implement_tinypng" with a 1kb image.""" with patch.object(tinify, "from_buffer") as mock_from_buffer: # Set up the mock return value as decoded result mock_from_buffer.return_value.to_buffer.return_value = ( base64.b64decode(RESULT_TINYPNG)) # Assert the expected result - optimized_image = main.tinypng_impl( + optimized_image = main.implement_tinypng( { "api_key": secret.API_KEY_TINYPNG, "decoded_image": IMAGE, @@ -132,8 +132,8 @@ def test_tinypng_impl_basic_functionality_1kb(self): mock_from_buffer.return_value.to_buffer.return_value) @unittest.skipUnless(secret.API_KEY_TINYPNG, "No Tinypng API Key set.") - def test_tinypng_impl_unexpected_exception_account_error(self): - """Test case handling unexpected "AccountError" in tinypng_impl.""" + def test_implement_tinypng_unexpected_exception_account_error(self): + """Test case handling unexpected "AccountError" in implement_tinypng.""" with patch.object(tinify, "from_buffer") as mock_from_buffer: # Set up the mock return value as account exception mock_from_buffer.side_effect = ( @@ -141,24 +141,24 @@ def test_tinypng_impl_unexpected_exception_account_error(self): # Check the raise for Account error self.assertRaises( tinify.errors.AccountError, - main.tinypng_impl, + main.implement_tinypng, { "api_key": secret.API_KEY_TINYPNG, "decoded_image": IMAGE, }, ) - @unittest.skipUnless(secret.API_KEY_TINYPNG, "No Tinypng API Key set") - def test_tinypng_impl_unexpected_exception_client_error(self): - """Test case handling unexpected "ClientError" in tinypng_impl.""" + @unittest.skipUnless(secret.API_KEY_TINYPNG, "No Tinypng API Key set.") + def test_implement_tinypng_unexpected_exception_client_error(self): + """Test case handling unexpected "ClientError" in implement_tinypng.""" with patch.object(tinify, "from_buffer") as mock_from_buffer: # Set up the mock return value as client exception mock_from_buffer.side_effect = ( - tinify.errors.ClientError("Image is incorrect")) + tinify.errors.ClientError("Image is incorrect.")) # Check the raise for Client error self.assertRaises( tinify.errors.ClientError, - main.tinypng_impl, + main.implement_tinypng, { "api_key": secret.API_KEY_TINYPNG, "decoded_image": IMAGE @@ -167,14 +167,14 @@ def test_tinypng_impl_unexpected_exception_client_error(self): class TestKrakenIO(unittest.TestCase): - """Class for testing the functionality of the "krakenio_impl" function.""" + """Class for testing the functionality of the "implement_krakenio" function.""" @unittest.skipUnless( secret.API_KEY_KRAKENIO and secret.SECRET_API_KEY_KRAKENIO, "No KrakenIO API Key or Secret Key.") def test_krakenio_happy_path(self): - """Test case optimizing 1kb image using "krakenio_impl" function.""" + """Test case optimizing 1kb image using "implement_krakenio" function.""" want = RESULT_KRAKENIO - got = main.krakenio_impl( + got = main.implement_krakenio( { "api_key": secret.API_KEY_KRAKENIO, "api_secret_key": secret.SECRET_API_KEY_KRAKENIO, @@ -192,7 +192,7 @@ def test_krakenio_time_out(self): mock_post.side_effect = requests.exceptions.ReadTimeout self.assertRaises( requests.exceptions.ReadTimeout, - main.krakenio_impl, + main.implement_krakenio, { "api_key": secret.API_KEY_KRAKENIO, "api_secret_key": secret.SECRET_API_KEY_KRAKENIO, @@ -347,7 +347,7 @@ def test_validate_request_value_error(self, got): class TestMain(unittest.TestCase): """Class test for main function.""" - @unittest.skipUnless(secret.API_KEY_TINYPNG, "No Tinypng API Key set") + @unittest.skipUnless(secret.API_KEY_TINYPNG, "No Tinypng API Key set.") def test_main_success(self): """Unittest for main function success json response.""" want = { @@ -373,7 +373,7 @@ def test_main_success(self): def test_main_value_error(self): """Unittest for main function when a value error is raised.""" - want = {"success": False, "error": "Missing payload"} + want = {"success": False, "error": "Missing payload."} # Create a request req = MyRequest({"payload": {}, "variables": {}}) # Create a response object