Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Brink conversion method #170

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 197 additions & 0 deletions java/compress_image/Index.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import java.util.Map;
import java.util.HashMap;
import java.net.HttpURLConnection;
import java.net.URL;
import java.io.BufferedReader;
import java.util.stream.Collectors;
import java.util.stream.*;
import java.util.Base64;
import com.google.gson.Gson;

/**
* Enum for provider names
* @param name is provider name
* TINY_PNG is TinyPNG provider
* KRAKENIO is Kraken.io provider
* getName() is getter for provider name
*/

private enum Provider {
TINY_PNG("tinypng"), KRAKENIO("krakenio");

private final String name;

Provider(String name) {
this.name = name;
}

String getName() {
return name;
}

// check if provider is valid
static boolean validateProvider(String name) {
for (Provider providerName : Provider.values()) {
if (providerName.name.equals(name)) {
return true;
}
}
return false;
}
}

final Gson gson = new Gson();

public RuntimeResponse main(RuntimeRequest req, RuntimeResponse res) throws Exception {

// payload string
String payloadString = req.getPayload() == null || req.getPayload().isEmpty() ? "{}" : req.getPayload();

// convert payload to map
Map<String, Object> payload = gson.fromJson(payloadString, Map.class);

// check if requested payload and variables are present
RuntimeResponse errorResponse = checkPayloadAndVariables(req, res);
if (errorResponse != null) {
return errorResponse;
}

// check if payload contains provider and image
errorResponse = validatePayload(payload, res);
if (errorResponse != null) {
return errorResponse;
}

// get provider from payload and image from payload
String provider = payload.get("provider").toString();
String image = payload.get("image").toString();

// check API key is present in variables
String apiKeyVariable = Provider.TINY_PNG.getName().equals(provider) ? "TINYPNG_API_KEY" : "KRAKENIO_API_KEY";

errorResponse = checkEmptyApiKey(req, res, apiKeyVariable);
if (errorResponse != null) {
return errorResponse;
}
String apiKey = req.getVariables().get(apiKeyVariable);

// compressed image in Base64 string
String compressedImage = "compressed image is under implementation";

// response data to return
Map<String, Object> responseData = new HashMap<>();

// TODO: compress image using provider API and store the result in compressedImage variable

// TODO: check if compressedImage is valid

// If input valid then return success true and compressed image
responseData.put("success", true);
responseData.put("image", compressedImage);

return res.json(responseData);
}

/**
* Check if requested payload and variables are present
* @param req is request object from function call
* @param res is response object from function call
* @return null if payload and variables are present, otherwise return error response
*/
private RuntimeResponse checkPayloadAndVariables(RuntimeRequest req, RuntimeResponse res) {
Map<String, Object> responseData = new HashMap<>();

// check if requested payload and variables are present
if (req.getPayload() == null || req.getPayload().trim().isEmpty() || req.getPayload().trim().equals("{}")) {
responseData.put("success", false);
responseData.put("message", "Payload is empty, please provide provider and image");
return res.json(responseData);
}

if (req.getVariables() == null) {
responseData.put("success", false);
responseData.put("message", "Variables are empty, please provide an API key for provider");
return res.json(responseData);
}
return null;
}

/**
* Validate payload whether it contains provider and image
* @param payload is an object from request payload which contains provider and image
* @param res is response object from function call
* @return null if payload is valid, otherwise return error response
*/

private RuntimeResponse validatePayload(Map<String, Object> payload, RuntimeResponse res) {
Map<String, Object> responseData = new HashMap<>();

// check if payload contains provider and image
if (!payload.containsKey("provider") || !payload.containsKey("image")) {
responseData.put("success", false);
responseData.put("message", "Payload is invalid, please provide provider and image");
return res.json(responseData);
}

// get provider from payload and image from payload
String provider = payload.get("provider").toString();
String image = payload.get("image").toString();

// check if provider is valid
if (!Provider.validateProvider(provider)) {
responseData.put("success", false);
String providerNames = Stream.of(Provider.values()).map(Provider::getName).collect(Collectors.joining(", ")); // get all provider names
responseData.put("message", "Provider " + provider + "is invalid, please provide one of providers: " + providerNames);
return res.json(responseData);
}

// check if image is valid in Base64 with regex pattern matching
if (!image.matches("^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$") || image.trim().isEmpty()) {
responseData.put("success", false);
responseData.put("message", "Image is invalid, please provide a valid Base64 image");
return res.json(responseData);
}
return null;
}

/**
* Check if API key is present in variables for provider
* @param req is request object from function call
* @param res is response object from function call
* @param apiKeyVariable is API key variable name for provider
* @return null if API key is present, otherwise return error response
*/

// check API key is present in variables
private RuntimeResponse checkEmptyApiKey(RuntimeRequest req, RuntimeResponse res, String apiKeyVariable) {
Map<String, String> variables = req.getVariables();

if (!variables.containsKey(apiKeyVariable) || variables.get(apiKeyVariable) == null || variables.get(apiKeyVariable).trim().isEmpty()) {
Map<String, Object> responseData = new HashMap<>();
responseData.put("success", false);
responseData.put("message", "API key is not present in variables, please provide " + apiKeyVariable + " for the provider");
return res.json(responseData);
}
return null;
}


/**
* Converts Base64 input of payload to byte array
* @param String baseInput is base64 string variable from payload
* @return byte [] baseInput decoded as byte array
*/

private byte [] convertToByte(String baseInput) {
return Base64.getDecoder().decode(baseInput);
}

/**
* Converts byte array input returned by compression method to Base64
* @param byte [] byteInput is byte array variable returned from compression method
* @return String byteInput encoded as Base64 String
*/

private String convertToBase64(byte [] byteInput) {
return Base64.getEncoder().encodeToString(byteInput);
}
45 changes: 45 additions & 0 deletions java/compress_image/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# compress_image

Welcome to the documentation of this function 👋 We strongly recommend keeping this file in sync with your function's logic to make sure anyone can easily understand your function in the future. If you don't need documentation, you can remove this file.

## 🤖 Documentation

Simple function similar to typical "hello world" example, but instead, we return a simple JSON that tells everyone how awesome developers are.

<!-- Update with your description, for example 'Create Stripe payment and return payment URL' -->

_Example input:_

This function expects no input

<!-- If input is expected, add example -->

_Example output:_

<!-- Update with your expected output -->

```json
{
"areDevelopersAwesome": true
}
```

## 📝 Environment Variables

List of environment variables used by this cloud function:

- No special environment variables are required for the cloud function.

## 🚀 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.java`, and upload the file we just generated.
3 changes: 3 additions & 0 deletions java/compress_image/deps.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dependencies {
implementation 'com.google.code.gson:gson:2.9.0'
}