That fuck shit the fascists are using
at master 151 lines 5.9 kB view raw
1package org.tm.archive.util; 2 3import androidx.annotation.NonNull; 4import androidx.annotation.VisibleForTesting; 5 6import com.google.i18n.phonenumbers.NumberParseException; 7import com.google.i18n.phonenumbers.PhoneNumberUtil; 8 9import org.signal.core.util.logging.Log; 10import org.tm.archive.mms.PushMediaConstraints; 11import org.tm.archive.recipients.Recipient; 12 13import java.util.Arrays; 14import java.util.HashMap; 15import java.util.List; 16import java.util.Map; 17import java.util.Optional; 18import java.util.stream.Collectors; 19 20/** 21 * Provide access to locale specific values within feature flags following the locale CSV-Colon format. 22 * 23 * Example: countryCode:integerValue,countryCode:integerValue,*:integerValue 24 */ 25public final class LocaleFeatureFlags { 26 27 private static final String TAG = Log.tag(LocaleFeatureFlags.class); 28 29 private static final String COUNTRY_WILDCARD = "*"; 30 private static final int NOT_FOUND = -1; 31 32 public static @NonNull Optional<PushMediaConstraints.MediaConfig> getMediaQualityLevel() { 33 Map<String, Integer> countryValues = parseCountryValues(FeatureFlags.getMediaQualityLevels(), NOT_FOUND); 34 int level = getCountryValue(countryValues, Recipient.self().getE164().orElse(""), NOT_FOUND); 35 36 return Optional.ofNullable(PushMediaConstraints.MediaConfig.forLevel(level)); 37 } 38 39 public static boolean shouldShowReleaseNote(@NonNull String releaseNoteUuid, @NonNull String countries) { 40 return isEnabledPartsPerMillion(releaseNoteUuid, countries); 41 } 42 43 /** 44 * @return Whether Google Pay is disabled in this region 45 */ 46 public static boolean isGooglePayDisabled() { 47 return isEnabledE164Start(FeatureFlags.googlePayDisabledRegions()); 48 } 49 50 /** 51 * @return Whether credit cards are disabled in this region 52 */ 53 public static boolean isCreditCardDisabled() { 54 return isEnabledE164Start(FeatureFlags.creditCardDisabledRegions()); 55 } 56 57 /** 58 * @return Whether PayPal is disabled in this region 59 */ 60 public static boolean isPayPalDisabled() { 61 return isEnabledE164Start(FeatureFlags.paypalDisabledRegions()); 62 } 63 64 public static boolean isIdealEnabled() { 65 return isEnabledE164Start(FeatureFlags.idealEnabledRegions()); 66 } 67 68 public static boolean isSepaEnabled() { 69 return isEnabledE164Start(FeatureFlags.sepaEnabledRegions()); 70 } 71 72 public static boolean isDelayedNotificationPromptEnabled() { 73 return FeatureFlags.internalUser() || isEnabledPartsPerMillion(FeatureFlags.PROMPT_FOR_NOTIFICATION_LOGS, FeatureFlags.promptForDelayedNotificationLogs()); 74 } 75 76 public static boolean isBatterySaverPromptEnabled() { 77 return FeatureFlags.internalUser() || isEnabledPartsPerMillion(FeatureFlags.PROMPT_BATTERY_SAVER, FeatureFlags.promptBatterySaver()); 78 } 79 80 /** 81 * Parses a comma-separated list of country codes and area codes to check if self's e164 starts with 82 * one of them. For example, "33,1555" will return turn for e164's that start with 33 or look like 1-555-xxx-xxx. 83 */ 84 private static boolean isEnabledE164Start(@NonNull String serialized) { 85 Recipient self = Recipient.self(); 86 87 if (self.getE164().isEmpty()) { 88 return false; 89 } 90 91 return isEnabledE164Start(serialized, self.getE164().get()); 92 } 93 94 @VisibleForTesting 95 static boolean isEnabledE164Start(@NonNull String serialized, @NonNull String e164) { 96 List<String> countryAndAreaCodes = Arrays.stream(serialized.split(",")).map(s -> s.trim().replaceAll("\\s", "")).collect(Collectors.toList()); 97 String e164Numbers = e164.replaceAll("\\D", ""); 98 99 return countryAndAreaCodes.stream().anyMatch(e164Numbers::startsWith); 100 } 101 102 /** 103 * Parses a comma-separated list of country codes colon-separated from how many buckets out of 1 million 104 * should be enabled to see this megaphone in that country code. At the end of the list, an optional 105 * element saying how many buckets out of a million should be enabled for all countries not listed previously 106 * in the list. For example, "1:20000,*:40000" would mean 2% of the NANPA phone numbers and 4% of the rest of 107 * the world should see the megaphone. 108 */ 109 private static boolean isEnabledPartsPerMillion(@NonNull String flag, @NonNull String serialized) { 110 Map<String, Integer> countryCodeValues = parseCountryValues(serialized, 0); 111 Recipient self = Recipient.self(); 112 113 if (countryCodeValues.isEmpty() || !self.getE164().isPresent() || !self.getServiceId().isPresent()) { 114 return false; 115 } 116 117 long countEnabled = getCountryValue(countryCodeValues, self.getE164().orElse(""), 0); 118 long currentUserBucket = BucketingUtil.bucket(flag, self.requireAci().getRawUuid(), 1_000_000); 119 120 return countEnabled > currentUserBucket; 121 } 122 123 @VisibleForTesting 124 static @NonNull Map<String, Integer> parseCountryValues(@NonNull String buckets, int defaultValue) { 125 Map<String, Integer> countryCountEnabled = new HashMap<>(); 126 127 for (String bucket : buckets.split(",")) { 128 String[] parts = bucket.split(":"); 129 if (parts.length == 2 && !parts[0].isEmpty()) { 130 countryCountEnabled.put(parts[0], Util.parseInt(parts[1], defaultValue)); 131 } 132 } 133 return countryCountEnabled; 134 } 135 136 @VisibleForTesting 137 static int getCountryValue(@NonNull Map<String, Integer> countryCodeValues, @NonNull String e164, int defaultValue) { 138 Integer countEnabled = countryCodeValues.get(COUNTRY_WILDCARD); 139 try { 140 String countryCode = String.valueOf(PhoneNumberUtil.getInstance().parse(e164, "").getCountryCode()); 141 if (countryCodeValues.containsKey(countryCode)) { 142 countEnabled = countryCodeValues.get(countryCode); 143 } 144 } catch (NumberParseException e) { 145 Log.d(TAG, "Unable to determine country code for bucketing."); 146 return defaultValue; 147 } 148 149 return countEnabled != null ? countEnabled : defaultValue; 150 } 151}