1
0
Fork 0
mirror of https://github.com/KokaKiwi/BarInsta synced 2026-03-15 00:41:35 +00:00

Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Ammar Githam 2021-05-23 06:31:04 +09:00
commit 505d5acef3
69 changed files with 1767 additions and 1040 deletions

View file

@ -702,7 +702,7 @@ public class MainActivity extends BaseLanguageActivity implements FragmentManage
Log.e(TAG, "showPostView: ", e);
}
}
Toast.makeText(getApplicationContext(), R.string.post_not_found, Toast.LENGTH_SHORT).show();
else Toast.makeText(getApplicationContext(), R.string.post_not_found, Toast.LENGTH_SHORT).show();
alertDialog.dismiss();
}

View file

@ -917,6 +917,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
private void setupButtons(final long profileId) {
profileDetailsBinding.btnTagged.setVisibility(isReallyPrivate() ? View.GONE : View.VISIBLE);
profileDetailsBinding.favChip.setVisibility(View.VISIBLE);
if (isLoggedIn) {
if (Objects.equals(profileId, myId)) {
profileDetailsBinding.btnTagged.setVisibility(View.VISIBLE);
@ -932,7 +933,6 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
profileDetailsBinding.btnLiked.setVisibility(View.GONE);
profileDetailsBinding.btnDM.setVisibility(disableDm ? View.GONE : View.VISIBLE);
profileDetailsBinding.btnFollow.setVisibility(View.VISIBLE);
profileDetailsBinding.favChip.setVisibility(View.VISIBLE);
final Context context = getContext();
if (context == null) return;
if (profileModel.getFriendshipStatus().isFollowing() || profileModel.getFriendshipStatus().isFollowedBy()) {

View file

@ -1,40 +0,0 @@
package awais.instagrabber.fragments.settings;
public final class PreferenceKeys {
// new boolean prefs
public static final String PREF_ENABLE_DM_NOTIFICATIONS = "enable_dm_notifications";
public static final String PREF_ENABLE_DM_AUTO_REFRESH = "enable_dm_auto_refresh";
public static final String PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT = "enable_dm_auto_refresh_freq_unit";
public static final String PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER = "enable_dm_auto_refresh_freq_number";
public static final String PREF_ENABLE_SENTRY = "enable_sentry";
public static final String PREF_TAB_ORDER = "tab_order";
public static final String PREF_SHOWN_COUNT_TOOLTIP = "shown_count_tooltip";
public static final String PREF_SEARCH_FOCUS_KEYBOARD = "search_focus_keyboard";
// string prefs
public static final String FOLDER_PATH = "custom_path";
public static final String DATE_TIME_FORMAT = "date_time_format";
public static final String DATE_TIME_SELECTION = "date_time_selection";
public static final String CUSTOM_DATE_TIME_FORMAT = "date_time_custom_format";
public static final String APP_THEME = "app_theme_v19";
public static final String APP_LANGUAGE = "app_language_v19";
public static final String STORY_SORT = "story_sort";
// set string prefs
public static final String KEYWORD_FILTERS = "keyword_filters";
// old boolean prefs
public static final String DOWNLOAD_USER_FOLDER = "download_user_folder";
public static final String TOGGLE_KEYWORD_FILTER = "toggle_keyword_filter";
public static final String DOWNLOAD_PREPEND_USER_NAME = "download_user_name";
public static final String PLAY_IN_BACKGROUND = "play_in_background";
public static final String FOLDER_SAVE_TO = "saved_to";
public static final String AUTOPLAY_VIDEOS = "autoplay_videos";
public static final String MUTED_VIDEOS = "muted_videos";
public static final String SHOW_CAPTIONS = "show_captions";
public static final String CUSTOM_DATE_TIME_FORMAT_ENABLED = "data_time_custom_enabled";
public static final String SWAP_DATE_TIME_FORMAT_ENABLED = "swap_date_time_enabled";
public static final String MARK_AS_SEEN = "mark_as_seen";
public static final String HIDE_MUTED_REELS = "hide_muted_reels";
public static final String DM_MARK_AS_SEEN = "dm_mark_as_seen";
public static final String CHECK_ACTIVITY = "check_activity";
public static final String CHECK_UPDATES = "check_updates";
public static final String FLAG_SECURE = "flag_secure";
}

View file

@ -0,0 +1,43 @@
package awais.instagrabber.fragments.settings
object PreferenceKeys {
// new boolean prefs
const val PREF_ENABLE_DM_NOTIFICATIONS = "enable_dm_notifications"
const val PREF_ENABLE_DM_AUTO_REFRESH = "enable_dm_auto_refresh"
const val PREF_ENABLE_DM_AUTO_REFRESH_FREQ_UNIT = "enable_dm_auto_refresh_freq_unit"
const val PREF_ENABLE_DM_AUTO_REFRESH_FREQ_NUMBER = "enable_dm_auto_refresh_freq_number"
const val PREF_ENABLE_SENTRY = "enable_sentry"
const val PREF_TAB_ORDER = "tab_order"
const val PREF_SHOWN_COUNT_TOOLTIP = "shown_count_tooltip"
const val PREF_SEARCH_FOCUS_KEYBOARD = "search_focus_keyboard"
// string prefs
const val FOLDER_PATH = "custom_path"
const val DATE_TIME_FORMAT = "date_time_format"
const val DATE_TIME_SELECTION = "date_time_selection"
const val CUSTOM_DATE_TIME_FORMAT = "date_time_custom_format"
const val APP_THEME = "app_theme_v19"
const val APP_LANGUAGE = "app_language_v19"
const val STORY_SORT = "story_sort"
// set string prefs
const val KEYWORD_FILTERS = "keyword_filters"
// old boolean prefs
const val DOWNLOAD_USER_FOLDER = "download_user_folder"
const val TOGGLE_KEYWORD_FILTER = "toggle_keyword_filter"
const val DOWNLOAD_PREPEND_USER_NAME = "download_user_name"
const val PLAY_IN_BACKGROUND = "play_in_background"
const val FOLDER_SAVE_TO = "saved_to"
const val AUTOPLAY_VIDEOS = "autoplay_videos"
const val MUTED_VIDEOS = "muted_videos"
const val SHOW_CAPTIONS = "show_captions"
const val CUSTOM_DATE_TIME_FORMAT_ENABLED = "data_time_custom_enabled"
const val SWAP_DATE_TIME_FORMAT_ENABLED = "swap_date_time_enabled"
const val MARK_AS_SEEN = "mark_as_seen"
const val HIDE_MUTED_REELS = "hide_muted_reels"
const val DM_MARK_AS_SEEN = "dm_mark_as_seen"
const val CHECK_ACTIVITY = "check_activity"
const val CHECK_UPDATES = "check_updates"
const val FLAG_SECURE = "flag_secure"
}

View file

@ -1,95 +0,0 @@
package awais.instagrabber.utils;
public final class Constants {
public static final String CRASH_REPORT_EMAIL = "barinsta@austinhuang.me";
// int prefs, do not export
public static final String PREV_INSTALL_VERSION = "prevVersion";
public static final String BROWSER_UA_CODE = "browser_ua_code";
public static final String APP_UA_CODE = "app_ua_code";
// never Export
public static final String COOKIE = "cookie";
// deprecated: public static final String SHOW_QUICK_ACCESS_DIALOG = "show_quick_dlg";
public static final String DEVICE_UUID = "device_uuid";
public static final String BROWSER_UA = "browser_ua";
public static final String APP_UA = "app_ua";
//////////////////////// EXTRAS ////////////////////////
public static final String EXTRAS_USER = "user";
public static final String EXTRAS_HASHTAG = "hashtag";
public static final String EXTRAS_LOCATION = "location";
public static final String EXTRAS_USERNAME = "username";
public static final String EXTRAS_ID = "id";
public static final String EXTRAS_POST = "post";
public static final String EXTRAS_PROFILE = "profile";
public static final String EXTRAS_TYPE = "type";
public static final String EXTRAS_NAME = "name";
public static final String EXTRAS_STORIES = "stories";
public static final String EXTRAS_HIGHLIGHT = "highlight";
public static final String EXTRAS_INDEX = "index";
public static final String EXTRAS_THREAD_MODEL = "threadModel";
public static final String EXTRAS_FOLLOWERS = "followers";
public static final String EXTRAS_SHORTCODE = "shortcode";
public static final String EXTRAS_END_CURSOR = "endCursor";
public static final String FEED = "feed";
public static final String FEED_ORDER = "feedOrder";
// Notification ids
public static final int ACTIVITY_NOTIFICATION_ID = 10;
public static final int DM_UNREAD_PARENT_NOTIFICATION_ID = 20;
public static final int DM_CHECK_NOTIFICATION_ID = 11;
// see https://github.com/dilame/instagram-private-api/blob/master/src/core/constants.ts
// public static final String SUPPORTED_CAPABILITIES = "[ { \"name\": \"SUPPORTED_SDK_VERSIONS\", \"value\":" +
// " \"13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0,21.0,22.0,23.0,24.0,25.0,26.0,27.0,28.0,29.0,30.0,31.0," +
// "32.0,33.0,34.0,35.0,36.0,37.0,38.0,39.0,40.0,41.0,42.0,43.0,44.0,45.0,46.0,47.0,48.0,49.0,50.0,51.0," +
// "52.0,53.0,54.0,55.0,56.0,57.0,58.0,59.0,60.0,61.0,62.0,63.0,64.0,65.0,66.0\" }, { \"name\": \"FACE_TRACKER_VERSION\", " +
// "\"value\": 12 }, { \"name\": \"segmentation\", \"value\": \"segmentation_enabled\" }, { \"name\": \"COMPRESSION\", " +
// "\"value\": \"ETC2_COMPRESSION\" }, { \"name\": \"world_tracker\", \"value\": \"world_tracker_enabled\" }, { \"name\": " +
// "\"gyroscope\", \"value\": \"gyroscope_enabled\" } ]";
// public static final String SIGNATURE_VERSION = "4";
// public static final String SIGNATURE_KEY = "9193488027538fd3450b83b7d05286d4ca9599a0f7eeed90d8c85925698a05dc";
public static final String BREADCRUMB_KEY = "iN4$aGr0m";
public static final int LOGIN_RESULT_CODE = 5000;
public static final String SKIPPED_VERSION = "skipped_version";
public static final String DEFAULT_TAB = "default_tab";
public static final String PREF_DARK_THEME = "dark_theme";
public static final String PREF_LIGHT_THEME = "light_theme";
public static final String DEFAULT_HASH_TAG_PIC = "https://www.instagram.com/static/images/hashtag/search-hashtag-default-avatar.png/1d8417c9a4f5.png";
public static final String SHARED_PREFERENCES_NAME = "settings";
public static final String PREF_POSTS_LAYOUT = "posts_layout";
public static final String PREF_PROFILE_POSTS_LAYOUT = "profile_posts_layout";
public static final String PREF_TOPIC_POSTS_LAYOUT = "topic_posts_layout";
public static final String PREF_HASHTAG_POSTS_LAYOUT = "hashtag_posts_layout";
public static final String PREF_LOCATION_POSTS_LAYOUT = "location_posts_layout";
public static final String PREF_LIKED_POSTS_LAYOUT = "liked_posts_layout";
public static final String PREF_TAGGED_POSTS_LAYOUT = "tagged_posts_layout";
public static final String PREF_SAVED_POSTS_LAYOUT = "saved_posts_layout";
public static final String PREF_EMOJI_VARIANTS = "emoji_variants";
public static final String PREF_REACTIONS = "reactions";
public static final String ACTIVITY_CHANNEL_ID = "activity";
public static final String ACTIVITY_CHANNEL_NAME = "Activity";
public static final String DOWNLOAD_CHANNEL_ID = "download";
public static final String DOWNLOAD_CHANNEL_NAME = "Downloads";
public static final String DM_UNREAD_CHANNEL_ID = "dmUnread";
public static final String DM_UNREAD_CHANNEL_NAME = "Messages";
public static final String SILENT_NOTIFICATIONS_CHANNEL_ID = "silentNotifications";
public static final String SILENT_NOTIFICATIONS_CHANNEL_NAME = "Silent notifications";
public static final String NOTIF_GROUP_NAME = "awais.instagrabber.InstaNotif";
public static final String GROUP_KEY_DM = "awais.instagrabber.MESSAGES";
public static final String GROUP_KEY_SILENT_NOTIFICATIONS = "awais.instagrabber.SILENT_NOTIFICATIONS";
public static final int SHOW_ACTIVITY_REQUEST_CODE = 1738;
public static final int SHOW_DM_THREAD = 2000;
public static final int DM_SYNC_SERVICE_REQUEST_CODE = 3000;
public static final int GLOBAL_NETWORK_ERROR_DIALOG_REQUEST_CODE = 7777;
public static final String ACTION_SHOW_ACTIVITY = "show_activity";
public static final String ACTION_SHOW_DM_THREAD = "show_dm_thread";
public static final String DM_THREAD_ACTION_EXTRA_THREAD_ID = "thread_id";
public static final String DM_THREAD_ACTION_EXTRA_THREAD_TITLE = "thread_title";
public static final String X_IG_APP_ID = "936619743392459";
}

View file

@ -0,0 +1,92 @@
package awais.instagrabber.utils
object Constants {
const val CRASH_REPORT_EMAIL = "barinsta@austinhuang.me"
// int prefs, do not export
const val PREV_INSTALL_VERSION = "prevVersion"
const val BROWSER_UA_CODE = "browser_ua_code"
const val APP_UA_CODE = "app_ua_code"
// never Export
const val COOKIE = "cookie"
// deprecated: public static final String SHOW_QUICK_ACCESS_DIALOG = "show_quick_dlg";
const val DEVICE_UUID = "device_uuid"
const val BROWSER_UA = "browser_ua"
const val APP_UA = "app_ua"
//////////////////////// EXTRAS ////////////////////////
const val EXTRAS_USER = "user"
const val EXTRAS_HASHTAG = "hashtag"
const val EXTRAS_LOCATION = "location"
const val EXTRAS_USERNAME = "username"
const val EXTRAS_ID = "id"
const val EXTRAS_POST = "post"
const val EXTRAS_PROFILE = "profile"
const val EXTRAS_TYPE = "type"
const val EXTRAS_NAME = "name"
const val EXTRAS_STORIES = "stories"
const val EXTRAS_HIGHLIGHT = "highlight"
const val EXTRAS_INDEX = "index"
const val EXTRAS_THREAD_MODEL = "threadModel"
const val EXTRAS_FOLLOWERS = "followers"
const val EXTRAS_SHORTCODE = "shortcode"
const val EXTRAS_END_CURSOR = "endCursor"
const val FEED = "feed"
const val FEED_ORDER = "feedOrder"
// Notification ids
const val ACTIVITY_NOTIFICATION_ID = 10
const val DM_UNREAD_PARENT_NOTIFICATION_ID = 20
const val DM_CHECK_NOTIFICATION_ID = 11
// see https://github.com/dilame/instagram-private-api/blob/master/src/core/constants.ts
// public static final String SUPPORTED_CAPABILITIES = "[ { \"name\": \"SUPPORTED_SDK_VERSIONS\", \"value\":" +
// " \"13.0,14.0,15.0,16.0,17.0,18.0,19.0,20.0,21.0,22.0,23.0,24.0,25.0,26.0,27.0,28.0,29.0,30.0,31.0," +
// "32.0,33.0,34.0,35.0,36.0,37.0,38.0,39.0,40.0,41.0,42.0,43.0,44.0,45.0,46.0,47.0,48.0,49.0,50.0,51.0," +
// "52.0,53.0,54.0,55.0,56.0,57.0,58.0,59.0,60.0,61.0,62.0,63.0,64.0,65.0,66.0\" }, { \"name\": \"FACE_TRACKER_VERSION\", " +
// "\"value\": 12 }, { \"name\": \"segmentation\", \"value\": \"segmentation_enabled\" }, { \"name\": \"COMPRESSION\", " +
// "\"value\": \"ETC2_COMPRESSION\" }, { \"name\": \"world_tracker\", \"value\": \"world_tracker_enabled\" }, { \"name\": " +
// "\"gyroscope\", \"value\": \"gyroscope_enabled\" } ]";
// public static final String SIGNATURE_VERSION = "4";
// public static final String SIGNATURE_KEY = "9193488027538fd3450b83b7d05286d4ca9599a0f7eeed90d8c85925698a05dc";
const val BREADCRUMB_KEY = "iN4\$aGr0m"
const val LOGIN_RESULT_CODE = 5000
const val SKIPPED_VERSION = "skipped_version"
const val DEFAULT_TAB = "default_tab"
const val PREF_DARK_THEME = "dark_theme"
const val PREF_LIGHT_THEME = "light_theme"
const val DEFAULT_HASH_TAG_PIC = "https://www.instagram.com/static/images/hashtag/search-hashtag-default-avatar.png/1d8417c9a4f5.png"
const val SHARED_PREFERENCES_NAME = "settings"
const val PREF_POSTS_LAYOUT = "posts_layout"
const val PREF_PROFILE_POSTS_LAYOUT = "profile_posts_layout"
const val PREF_TOPIC_POSTS_LAYOUT = "topic_posts_layout"
const val PREF_HASHTAG_POSTS_LAYOUT = "hashtag_posts_layout"
const val PREF_LOCATION_POSTS_LAYOUT = "location_posts_layout"
const val PREF_LIKED_POSTS_LAYOUT = "liked_posts_layout"
const val PREF_TAGGED_POSTS_LAYOUT = "tagged_posts_layout"
const val PREF_SAVED_POSTS_LAYOUT = "saved_posts_layout"
const val PREF_EMOJI_VARIANTS = "emoji_variants"
const val PREF_REACTIONS = "reactions"
const val ACTIVITY_CHANNEL_ID = "activity"
const val ACTIVITY_CHANNEL_NAME = "Activity"
const val DOWNLOAD_CHANNEL_ID = "download"
const val DOWNLOAD_CHANNEL_NAME = "Downloads"
const val DM_UNREAD_CHANNEL_ID = "dmUnread"
const val DM_UNREAD_CHANNEL_NAME = "Messages"
const val SILENT_NOTIFICATIONS_CHANNEL_ID = "silentNotifications"
const val SILENT_NOTIFICATIONS_CHANNEL_NAME = "Silent notifications"
const val NOTIF_GROUP_NAME = "awais.instagrabber.InstaNotif"
const val GROUP_KEY_DM = "awais.instagrabber.MESSAGES"
const val GROUP_KEY_SILENT_NOTIFICATIONS = "awais.instagrabber.SILENT_NOTIFICATIONS"
const val SHOW_ACTIVITY_REQUEST_CODE = 1738
const val SHOW_DM_THREAD = 2000
const val DM_SYNC_SERVICE_REQUEST_CODE = 3000
const val GLOBAL_NETWORK_ERROR_DIALOG_REQUEST_CODE = 7777
const val ACTION_SHOW_ACTIVITY = "show_activity"
const val ACTION_SHOW_DM_THREAD = "show_dm_thread"
const val DM_THREAD_ACTION_EXTRA_THREAD_ID = "thread_id"
const val DM_THREAD_ACTION_EXTRA_THREAD_TITLE = "thread_title"
const val X_IG_APP_ID = "936619743392459"
}

View file

@ -1,26 +0,0 @@
package awais.instagrabber.utils;
import android.content.Context;
import androidx.annotation.NonNull;
import com.google.android.exoplayer2.database.ExoDatabaseProvider;
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor;
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
public final class ExoplayerUtils {
private static final long MAX_CACHE_BYTES = 1048576;
private static final LeastRecentlyUsedCacheEvictor cacheEvictor = new LeastRecentlyUsedCacheEvictor(MAX_CACHE_BYTES);
public static DefaultMediaSourceFactory getCachedMediaSourceFactory(@NonNull final Context context) {
final ExoDatabaseProvider exoDatabaseProvider = new ExoDatabaseProvider(context);
final SimpleCache simpleCache = new SimpleCache(context.getCacheDir(), cacheEvictor, exoDatabaseProvider);
final CacheDataSource.Factory cacheDataSourceFactory = new CacheDataSource.Factory()
.setCache(simpleCache)
.setUpstreamDataSourceFactory(new DefaultHttpDataSourceFactory());
return new DefaultMediaSourceFactory(cacheDataSourceFactory);
}
}

View file

@ -0,0 +1,22 @@
package awais.instagrabber.utils
import android.content.Context
import com.google.android.exoplayer2.database.ExoDatabaseProvider
import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory
import com.google.android.exoplayer2.upstream.cache.CacheDataSource
import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor
import com.google.android.exoplayer2.upstream.cache.SimpleCache
object ExoplayerUtils {
private const val MAX_CACHE_BYTES: Long = 1048576
private val cacheEvictor = LeastRecentlyUsedCacheEvictor(MAX_CACHE_BYTES)
fun getCachedMediaSourceFactory(context: Context): DefaultMediaSourceFactory {
val exoDatabaseProvider = ExoDatabaseProvider(context)
val simpleCache = SimpleCache(context.cacheDir, cacheEvictor, exoDatabaseProvider)
val cacheDataSourceFactory = CacheDataSource.Factory()
.setCache(simpleCache)
.setUpstreamDataSourceFactory(DefaultHttpDataSourceFactory())
return DefaultMediaSourceFactory(cacheDataSourceFactory)
}
}

View file

@ -1,47 +0,0 @@
package awais.instagrabber.utils;
import android.util.Base64;
import androidx.annotation.NonNull;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public final class PasswordUtils {
private static final String cipherAlgo = "AES";
private static final String cipherTran = "AES/CBC/PKCS5Padding";
public static byte[] dec(final String encrypted, final byte[] keyValue) throws Exception {
try {
final Cipher cipher = Cipher.getInstance(cipherTran);
final SecretKeySpec secretKey = new SecretKeySpec(keyValue, cipherAlgo);
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(new byte[16]));
return cipher.doFinal(Base64.decode(encrypted, Base64.DEFAULT | Base64.NO_PADDING | Base64.NO_WRAP));
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
throw new IncorrectPasswordException(e);
}
}
public static byte[] enc(@NonNull final String str, final byte[] keyValue) throws Exception {
final Cipher cipher = Cipher.getInstance(cipherTran);
final SecretKeySpec secretKey = new SecretKeySpec(keyValue, cipherAlgo);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(new byte[16]));
final byte[] bytes = cipher.doFinal(str.getBytes());
return Base64.encode(bytes, Base64.DEFAULT | Base64.NO_PADDING | Base64.NO_WRAP);
}
public static class IncorrectPasswordException extends Exception {
public IncorrectPasswordException(final GeneralSecurityException e) {
super(e);
}
}
}

View file

@ -0,0 +1,52 @@
package awais.instagrabber.utils
import android.util.Base64
import java.security.GeneralSecurityException
import java.security.InvalidAlgorithmParameterException
import java.security.InvalidKeyException
import java.security.NoSuchAlgorithmException
import javax.crypto.BadPaddingException
import javax.crypto.Cipher
import javax.crypto.IllegalBlockSizeException
import javax.crypto.NoSuchPaddingException
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
object PasswordUtils {
private const val cipherAlgo = "AES"
private const val cipherTran = "AES/CBC/PKCS5Padding"
@JvmStatic
@Throws(Exception::class)
fun dec(encrypted: String?, keyValue: ByteArray?): ByteArray {
return try {
val cipher = Cipher.getInstance(cipherTran)
val secretKey = SecretKeySpec(keyValue, cipherAlgo)
cipher.init(Cipher.DECRYPT_MODE, secretKey, IvParameterSpec(ByteArray(16)))
cipher.doFinal(Base64.decode(encrypted, Base64.DEFAULT or Base64.NO_PADDING or Base64.NO_WRAP))
} catch (e: NoSuchAlgorithmException) {
throw IncorrectPasswordException(e)
} catch (e: NoSuchPaddingException) {
throw IncorrectPasswordException(e)
} catch (e: InvalidAlgorithmParameterException) {
throw IncorrectPasswordException(e)
} catch (e: InvalidKeyException) {
throw IncorrectPasswordException(e)
} catch (e: BadPaddingException) {
throw IncorrectPasswordException(e)
} catch (e: IllegalBlockSizeException) {
throw IncorrectPasswordException(e)
}
}
@JvmStatic
@Throws(Exception::class)
fun enc(str: String, keyValue: ByteArray?): ByteArray {
val cipher = Cipher.getInstance(cipherTran)
val secretKey = SecretKeySpec(keyValue, cipherAlgo)
cipher.init(Cipher.ENCRYPT_MODE, secretKey, IvParameterSpec(ByteArray(16)))
val bytes = cipher.doFinal(str.toByteArray())
return Base64.encode(bytes, Base64.DEFAULT or Base64.NO_PADDING or Base64.NO_WRAP)
}
class IncorrectPasswordException(e: GeneralSecurityException?) : Exception(e)
}

View file

@ -1,122 +0,0 @@
package awais.instagrabber.utils;
import android.content.Context;
import android.text.SpannableString;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.text.style.URLSpan;
import android.util.Patterns;
import androidx.annotation.NonNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.stream.Collectors;
public final class TextUtils {
// extracted from String class
public static int indexOfChar(@NonNull final CharSequence sequence, final int ch, final int startIndex) {
final int max = sequence.length();
if (startIndex < max) {
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
for (int i = startIndex; i < max; i++) if (sequence.charAt(i) == ch) return i;
} else if (Character.isValidCodePoint(ch)) {
final char hi = (char) ((ch >>> 10) + (Character.MIN_HIGH_SURROGATE - (Character.MIN_SUPPLEMENTARY_CODE_POINT >>> 10)));
final char lo = (char) ((ch & 0x3ff) + Character.MIN_LOW_SURROGATE);
for (int i = startIndex; i < max; i++)
if (sequence.charAt(i) == hi && sequence.charAt(i + 1) == lo) return i;
}
}
return -1;
}
public static CharSequence getSpannableUrl(final String url) {
if (isEmpty(url)) return url;
final int httpIndex = url.indexOf("http:");
final int httpsIndex = url.indexOf("https:");
if (httpIndex == -1 && httpsIndex == -1) return url;
final int length = url.length();
final int startIndex = httpIndex != -1 ? httpIndex : httpsIndex;
final int spaceIndex = url.indexOf(' ', startIndex + 1);
final int endIndex = (spaceIndex != -1 ? spaceIndex : length);
final String extractUrl = url.substring(startIndex, Math.min(length, endIndex));
final SpannableString spannableString = new SpannableString(url);
spannableString.setSpan(new URLSpan(extractUrl), startIndex, endIndex, 0);
return spannableString;
}
public static boolean isEmpty(final CharSequence charSequence) {
if (charSequence == null || charSequence.length() < 1) return true;
if (charSequence instanceof String) {
String str = (String) charSequence;
if ("".equals(str) || "null".equals(str) || str.isEmpty()) return true;
str = str.trim();
return "".equals(str) || "null".equals(str) || str.isEmpty();
}
return "null".contentEquals(charSequence) || "".contentEquals(charSequence);
}
public static String millisToTimeString(final long millis) {
return millisToTimeString(millis, false);
}
public static String millisToTimeString(final long millis, final boolean includeHoursAlways) {
final int sec = (int) (millis / 1000) % 60;
int min = (int) (millis / (1000 * 60));
if (min >= 60) {
min = (int) ((millis / (1000 * 60)) % 60);
final int hr = (int) ((millis / (1000 * 60 * 60)) % 24);
return String.format(Locale.ENGLISH, "%02d:%02d:%02d", hr, min, sec);
}
if (includeHoursAlways) {
return String.format(Locale.ENGLISH, "%02d:%02d:%02d", 0, min, sec);
}
return String.format(Locale.ENGLISH, "%02d:%02d", min, sec);
}
public static String getRelativeDateTimeString(final Context context, final long from) {
final Date now = new Date();
final Date then = new Date(from);
int days = daysBetween(from, now.getTime());
if (days == 0) {
return DateFormat.getTimeFormat(context).format(then);
}
return DateFormat.getDateFormat(context).format(then);
}
private static int daysBetween(long d1, long d2) {
return (int) ((d2 - d1) / DateUtils.DAY_IN_MILLIS);
}
public static List<String> extractUrls(final String text) {
if (isEmpty(text)) return Collections.emptyList();
final Matcher matcher = Patterns.WEB_URL.matcher(text);
final List<String> urls = new ArrayList<>();
while (matcher.find()) {
urls.add(matcher.group());
}
return urls;
}
// https://github.com/notslang/instagram-id-to-url-segment
public static long shortcodeToId(final String shortcode) {
long result = 0L;
for (int i = 0; i < shortcode.length() && i < 11; i++){
final char c = shortcode.charAt(i);
final int k = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".indexOf(c);
result = result * 64 + k;
}
return result;
}
}

View file

@ -0,0 +1,75 @@
package awais.instagrabber.utils
import android.content.Context
import android.text.format.DateFormat
import android.text.format.DateUtils
import android.util.Patterns
import java.util.*
object TextUtils {
@JvmStatic
fun isEmpty(charSequence: CharSequence?): Boolean {
if (charSequence == null || charSequence.length < 1) return true
if (charSequence is String) {
var str = charSequence
if ("" == str || "null" == str || str.isEmpty()) return true
str = str.trim { it <= ' ' }
return "" == str || "null" == str || str.isEmpty()
}
return "null".contentEquals(charSequence) || "".contentEquals(charSequence)
}
@JvmStatic
@JvmOverloads
fun millisToTimeString(millis: Long, includeHoursAlways: Boolean = false): String {
val sec = (millis / 1000).toInt() % 60
var min = (millis / (1000 * 60)).toInt()
if (min >= 60) {
min = (millis / (1000 * 60) % 60).toInt()
val hr = (millis / (1000 * 60 * 60) % 24).toInt()
return String.format(Locale.ENGLISH, "%02d:%02d:%02d", hr, min, sec)
}
return if (includeHoursAlways) {
String.format(Locale.ENGLISH, "%02d:%02d:%02d", 0, min, sec)
} else String.format(Locale.ENGLISH, "%02d:%02d", min, sec)
}
@JvmStatic
fun getRelativeDateTimeString(context: Context?, from: Long): String {
val now = Date()
val then = Date(from)
val days = daysBetween(from, now.time)
return if (days == 0) {
DateFormat.getTimeFormat(context).format(then)
} else DateFormat.getDateFormat(context).format(then)
}
private fun daysBetween(d1: Long, d2: Long): Int {
return ((d2 - d1) / DateUtils.DAY_IN_MILLIS).toInt()
}
@JvmStatic
fun extractUrls(text: String?): List<String> {
if (isEmpty(text)) return emptyList()
val matcher = Patterns.WEB_URL.matcher(text)
val urls: MutableList<String> = ArrayList()
while (matcher.find()) {
urls.add(matcher.group())
}
return urls
}
// https://github.com/notslang/instagram-id-to-url-segment
@JvmStatic
fun shortcodeToId(shortcode: String): Long {
var result = 0L
var i = 0
while (i < shortcode.length && i < 11) {
val c = shortcode[i]
val k = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".indexOf(c)
result = result * 64 + k
i++
}
return result
}
}

View file

@ -1,74 +0,0 @@
package awais.instagrabber.utils;
import androidx.annotation.NonNull;
import java.io.CharArrayWriter;
import java.util.BitSet;
// same as java.net.URLEncoder
public final class UrlEncoder {
private static final BitSet dontNeedEncoding = new BitSet(256);
private static final int caseDiff = ('a' - 'A');
static {
int i;
for (i = 'a'; i <= 'z'; i++) dontNeedEncoding.set(i);
for (i = 'A'; i <= 'Z'; i++) dontNeedEncoding.set(i);
for (i = '0'; i <= '9'; i++) dontNeedEncoding.set(i);
dontNeedEncoding.set(' ');
dontNeedEncoding.set('-');
dontNeedEncoding.set('_');
dontNeedEncoding.set('.');
dontNeedEncoding.set('*');
}
@NonNull
public static String encodeUrl(@NonNull final String s) {
final StringBuilder out = new StringBuilder(s.length());
final CharArrayWriter charArrayWriter = new CharArrayWriter();
boolean needToChange = false;
for (int i = 0; i < s.length(); ) {
int c = s.charAt(i);
if (dontNeedEncoding.get(c)) {
if (c == ' ') {
c = '+';
needToChange = true;
}
out.append((char) c);
i++;
} else {
do {
charArrayWriter.write(c);
if (c >= 0xD800 && c <= 0xDBFF && i + 1 < s.length()) {
final int d = s.charAt(i + 1);
if (d >= 0xDC00 && d <= 0xDFFF) {
charArrayWriter.write(d);
i++;
}
}
i++;
} while (i < s.length() && !dontNeedEncoding.get(c = s.charAt(i)));
charArrayWriter.flush();
final byte[] ba = charArrayWriter.toString().getBytes();
for (final byte b : ba) {
out.append('%');
char ch = Character.forDigit((b >> 4) & 0xF, 16);
if (Character.isLetter(ch)) ch -= caseDiff;
out.append(ch);
ch = Character.forDigit(b & 0xF, 16);
if (Character.isLetter(ch)) ch -= caseDiff;
out.append(ch);
}
charArrayWriter.reset();
needToChange = true;
}
}
return (needToChange ? out.toString() : s);
}
}