Skip to content

Commit

Permalink
Add audience lookup function
Browse files Browse the repository at this point in the history
  • Loading branch information
aashikam committed Dec 19, 2024
1 parent efa6a24 commit 6014640
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
public class Constants {

public static final String PROPERTY_ACCESS_TOKEN = "_FB_ACCESS_TOKEN_";
public static final String HASHED_PAYLOAD = "HASHED_PAYLOAD";
public static final String ACCESS_TOKEN = "access_token";
public static final String PROPERTY_ERROR_CODE = "ERROR_CODE";
public static final String PROPERTY_ERROR_MESSAGE = "ERROR_MESSAGE";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
/*
* Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.carbon.facebook.ads.connector;

import org.apache.synapse.MessageContext;
Expand All @@ -14,11 +32,9 @@ public boolean mediate(MessageContext synCtx) {
if (jsonString == null || jsonString.isEmpty()) {
return true;
}

JSONArray inputArray = new JSONArray(jsonString);

JSONObject finalObj = FacebookDataProcessor.processData(inputArray);
synCtx.setProperty("HASHED_PAYLOAD", finalObj.toString());
synCtx.setProperty(Constants.HASHED_PAYLOAD, finalObj.toString());
return true;
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
/*
* Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.carbon.facebook.ads.connector;

import java.security.MessageDigest;
Expand All @@ -7,6 +25,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.synapse.SynapseException;
import org.json.JSONArray;
import org.json.JSONObject;
import org.apache.commons.logging.Log;
Expand Down Expand Up @@ -96,6 +115,7 @@ class FacebookDataProcessor {
US_STATE_MAP.put("wyoming", "wy");
US_STATE_MAP.put("district of columbia", "dc");

// If the country is not present here, default to lowercase
COUNTRY_MAP.put("unitedstates", "us");
COUNTRY_MAP.put("us", "us");
COUNTRY_MAP.put("unitedkingdom", "gb");
Expand Down Expand Up @@ -161,7 +181,6 @@ static JSONObject processData(JSONArray inputArray) {
String finalValue = normalized.isEmpty() ? "" : (requiresHashing(field) ? hashIfNotAlreadyHashed(normalized) : normalized);
dataRow.put(finalValue);
}

dataArray.put(dataRow);
}

Expand Down Expand Up @@ -200,7 +219,7 @@ private static String getOccurrenceValue(JSONObject entry, String originalField,
externIdFields.add(key);
}
}
// Sort them to ensure deterministic order (by base key and numeric index)
// Sort them
externIdFields.sort((a, b) -> {
String baseA = a.replaceAll("\\.\\d+", "");
String baseB = b.replaceAll("\\.\\d+", "");
Expand Down Expand Up @@ -251,7 +270,8 @@ private static int getSuffixIndex(String key) {
try {
return Integer.parseInt(m.group(1));
} catch (NumberFormatException e) {
// ignore
log.error("Error occurred while getting suffix index: ", e);
throw new SynapseException("Error occurred while getting suffix index: " + e.getMessage(), e);
}
}
return 0;
Expand All @@ -276,12 +296,6 @@ private static boolean requiresHashing(String fieldName) {
!fieldName.equalsIgnoreCase("PAGE_SCOPED_USER_ID");
}

private static void printNormalization(String fieldName, String originalValue, String normalizedValue) {
System.out.println("Normalizing field: " + fieldName);
System.out.println("original = " + originalValue);
System.out.println("normalized = " + normalizedValue);
}

private static Map<String, String> parsePhoneMeta(String val) {
Map<String, String> meta = new HashMap<>();
Pattern p = Pattern.compile("(alreadyHasPhoneCode|countryCode|phoneCode|phoneNumber)\\s*:\\s*([^;]+)");
Expand All @@ -299,6 +313,7 @@ private static Map<String, String> parsePhoneMeta(String val) {
return meta;
}

// Normalize phone numbers
private static String normalizePhone(String val, String country) {
Map<String, String> meta = parsePhoneMeta(val);
if (meta.isEmpty()) {
Expand Down Expand Up @@ -341,15 +356,16 @@ private static String normalizePhone(String val, String country) {
}
}
}

return phoneNumber;
}
}

// Normalize the cities
private static String normalizeCity(String val) {
return val.replaceAll("[^a-z]", "");
}

// Normalize the states
private static String normalizeState(String val, String country) {
String clean = val.replaceAll("[^a-z]", "");
if ("us".equalsIgnoreCase(country)) {
Expand All @@ -364,6 +380,7 @@ private static String normalizeState(String val, String country) {
return clean;
}

// Normalize the gender
private static String normalizeGender(String val) {
Set<String> maleSynonyms = new HashSet<>(Arrays.asList("m", "male", "man", "boy"));
Set<String> femaleSynonyms = new HashSet<>(Arrays.asList("f", "female", "woman", "girl"));
Expand All @@ -376,6 +393,7 @@ private static String normalizeGender(String val) {
return "m";
}

// Normalize the countries
private static String normalizeCountry(String val) {
val = val.replaceAll("[^a-z]", "");
String countryCode = COUNTRY_MAP.get(val);
Expand All @@ -385,6 +403,7 @@ private static String normalizeCountry(String val) {
return val;
}

// Normalize the dob
private static String parseDOBToYYYYMMDD(String val) {
String[] parts = val.split("[/\\-–]+");
if (parts.length < 3) {
Expand Down Expand Up @@ -481,27 +500,21 @@ private static String normalizeDOBD(String val) {

private static String normalizeField(String fieldName, String value, String country) {
if (value == null) {
printNormalization(fieldName, "null", "");
return "";
}

String originalValue = value;
String val = value.trim().toLowerCase();

switch (fieldName) {
case "EMAIL":
printNormalization(fieldName, originalValue, val);
return val;

case "PHONE":
val = normalizePhone(val, country);
printNormalization(fieldName, originalValue, val);
return val;

case "FN":
case "LN":
val = val.replaceAll("[^\\p{L}]", "");
printNormalization(fieldName, originalValue, val);
return val;

case "ZIP":
Expand All @@ -512,51 +525,41 @@ private static String normalizeField(String fieldName, String value, String coun
val = val.substring(0, 5);
}
}
printNormalization(fieldName, originalValue, val);
return val;

case "CT":
val = normalizeCity(val);
printNormalization(fieldName, originalValue, val);
return val;

case "ST":
val = normalizeState(val, country);
printNormalization(fieldName, originalValue, val);
return val;

case "COUNTRY":
val = normalizeCountry(val);
printNormalization(fieldName, originalValue, val);
return val;

case "DOB":
val = normalizeDOB(val);
printNormalization(fieldName, originalValue, val);
return val;

case "DOBY":
val = normalizeDOBY(val);
printNormalization(fieldName, originalValue, val);
return val;

case "DOBM":
val = normalizeDOBM(val);
printNormalization(fieldName, originalValue, val);
return val;

case "DOBD":
val = normalizeDOBD(val);
printNormalization(fieldName, originalValue, val);
return val;

case "GEN":
val = normalizeGender(val);
printNormalization(fieldName, originalValue, val);
return val;

default:
printNormalization(fieldName, originalValue, val);
return val;
}
}
Expand All @@ -568,7 +571,7 @@ private static String hashString(String input) {
byte[] encodedhash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
return bytesToHex(encodedhash);
} catch (NoSuchAlgorithmException e) {
log.error("Error hashing string", e);
log.error("Error hashing string: " + input, e);
return "";
}
}
Expand All @@ -589,8 +592,4 @@ private static String hashIfNotAlreadyHashed(String input) {
}
return hashString(input);
}

static void unhashAndPrintFinalPayload(JSONObject finalObj) {
System.out.println(finalObj.toString(4));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2024, WSO2 LLC. (https://www.wso2.com).
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.wso2.carbon.facebook.ads.connector;

import org.apache.synapse.MessageContext;
import org.apache.synapse.mediators.AbstractMediator;
import org.wso2.carbon.connector.core.util.ConnectorUtils;


public class FilterResponseByNameMediator extends AbstractMediator {

@Override
public boolean mediate(MessageContext synCtx) {
String filterByName = (String) ConnectorUtils.lookupTemplateParamater(synCtx, "filterByName");
// todo
return true;
}
}
12 changes: 0 additions & 12 deletions src/main/resources/functions/addUsersToAudience.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,6 @@
<property name="operationPath" value="/{custom_audience_id}/users"/>
<property name="pathParameters" value="customAudienceId,"/>
</class>

<!-- Log the hashed payload right after hashing is done -->
<log level="full">
<property name="hashed-payload" expression="get-property('HASHED_PAYLOAD')"/>
</log>

<!-- Construct the final payload using the payload factory -->
<payloadFactory media-type="json" template-type="freemarker">
<format><![CDATA[
${args.arg1}
Expand All @@ -44,11 +37,6 @@ ${args.arg1}
</args>
</payloadFactory>

<!-- Log again after the payload factory to confirm the final message body -->
<log level="full">
<property name="final-payload" expression="json-eval($.)"/>
</log>

<property name="DISABLE_CHUNKING" scope="axis2" type="STRING" value="true"/>
<property name="messageType" value="application/json" scope="axis2"/>
<property name="ContentType" value="application/json" scope="axis2"/>
Expand Down
9 changes: 5 additions & 4 deletions src/main/resources/functions/getCustomAudiences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,21 @@
<template xmlns="http://ws.apache.org/ns/synapse" name="getCustomAudiences">
<!-- Path Parameter List -->
<parameter name="adAccountId" description="ID of the ad account."/>
<parameter name="fields" description="Fields of the audience"/>
<parameter name="filterByName" description="Name of the audience to filter by name."/>
<sequence>
<class name="org.wso2.carbon.facebook.ads.connector.RestURLBuilder">
<property name="operationPath" value="/act_{ad_account_id}/customaudiences"/>
<property name="pathParameters" value="adAccountId,"/>
<property name="queryParameters" value="fields,"/>
</class>
<header name="Accept" value="application/json" scope="transport" action="set"/>
<call>
<endpoint>
<http method="GET" uri-template="{uri.var.base}{+uri.var.urlPath}{+uri.var.urlQuery}"/>
<http method="GET" uri-template="{uri.var.base}{+uri.var.urlPath}{+uri.var.urlQuery}&amp;fields=id,name,description,account_id,subtype,size,usage,delivery_status,lookalike_spec,rule,pixel_id,data_source,creation_time,update_time,is_restricted,can_create_lookalike,customer_file_source,retention_days,origin,country,ratio,targeting"/>
</endpoint>
</call>
<!-- Remove custom header information -->

<class name="org.wso2.carbon.facebook.ads.connector.FilterResponseByNameMediator"/>

<header name="x-business-use-case-usage" scope="transport" action="remove"/>
<header name="facebook-api-version" scope="transport" action="remove"/>
<header name="Strict-Transport-Security" scope="transport" action="remove"/>
Expand Down
13 changes: 0 additions & 13 deletions src/main/resources/functions/removeUsersFromAudience.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@
<!-- Generated on 16-Wed, 10, 2024 19:59:26+0530 -->

<template xmlns="http://ws.apache.org/ns/synapse" name="removeUsersFromAudience">
<!-- Path Parameter List -->
<parameter name="customAudienceId" description="The ID of the custom audience."/>
<!-- Request Body Parameter List -->
<parameter name="properties" description="Custom audience users properties."/>
<sequence>
<class name="org.wso2.carbon.facebook.ads.connector.FacebookDataClassMediator"/>
Expand All @@ -31,12 +29,6 @@
<property name="pathParameters" value="customAudienceId,"/>
</class>

<!-- Log the hashed payload right after hashing is done -->
<log level="full">
<property name="hashed-payload" expression="get-property('HASHED_PAYLOAD')"/>
</log>

<!-- Construct the final payload using the payload factory -->
<payloadFactory media-type="json" template-type="freemarker">
<format><![CDATA[
${args.arg1}
Expand All @@ -46,11 +38,6 @@ ${args.arg1}
</args>
</payloadFactory>

<!-- Log again after the payload factory to confirm the final message body -->
<log level="full">
<property name="final-payload" expression="json-eval($.)"/>
</log>

<property name="DISABLE_CHUNKING" scope="axis2" type="STRING" value="true"/>
<property name="messageType" value="application/json" scope="axis2"/>
<property name="ContentType" value="application/json" scope="axis2"/>
Expand Down
Loading

0 comments on commit 6014640

Please sign in to comment.