Compare commits

..
Author SHA1 Message Date
gdlbo e5928babef Update preferences_media.xml 2024-03-25 23:45:28 +03:00
gdlbo f5482321ce Update Metrics.java 2024-03-25 19:24:42 +03:00
gdlbo d17bdef23a added list of events to send them later 2024-03-25 18:04:15 +03:00
gdlbo 4a3e13939f Update VideoTracker.java 2024-03-25 16:58:18 +03:00
gdlbo 779029b7cc restart app after changing music download dir 2024-03-25 16:41:05 +03:00
gdlbo 024a7bc356 init 2024-03-25 16:36:55 +03:00
gdlbo 43d859d240 wip 2024-03-25 15:01:25 +03:00
46 changed files with 1299 additions and 2954 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
uses: nttld/setup-ndk@v1
with:
ndk-version: r25c
add-to-path: true
add-to-path: false
- name: Set up JDK
uses: actions/setup-java@v3
+2 -2
View File
@@ -4,7 +4,7 @@ import java.util.zip.ZipFile
plugins {
id 'com.android.application'
id 'net.nemerosa.versioning' version '3.1.0'
id 'net.nemerosa.versioning' version '2.15.1'
id 'org.mozilla.rust-android-gradle.rust-android'
}
@@ -95,7 +95,7 @@ dependencies {
implementation 'com.microsoft.appcenter:appcenter-crashes:5.0.4'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
implementation 'net.sourceforge.streamsupport:streamsupport-minifuture:1.7.4'
implementation 'com.google.guava:guava:33.2.1-android'
implementation 'com.google.guava:guava:32.0.0-android'
implementation 'com.mpatric:mp3agic:0.9.1'
@@ -2,6 +2,7 @@ package com.vk.libvideo;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
@@ -10,6 +11,7 @@ import com.vk.dto.common.VideoFile;
import com.vk.media.player.PlayerTypes;
import com.vk.navigation.NavigatorKeys;
import com.vk.statistic.Statistic;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import ru.vtosters.hooks.other.Preferences;
@@ -331,6 +333,6 @@ public class VideoTracker {
jsonObject.put("position_sec", 0);
jsonObject.put("cur_quality", "auto");
Metrics.trackEvents(jsonObject, false);
Metrics.trackEvents(jsonObject);
}
}
@@ -11,6 +11,7 @@ import com.vk.music.stats.i.MusicPlaybackParams;
import com.vk.navigation.NavigatorKeys;
import com.vtosters.lite.data.Analytics;
import kotlin.jvm.b.Functions2;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import ru.vtosters.hooks.other.Preferences;
@@ -184,7 +185,7 @@ public final class VKMusicStatsTracker implements MusicStatsTracker {
}
}
Metrics.trackEvents(event, true);
Metrics.trackEvents(event);
}
private Analytics.l a(MusicPlaybackParams musicPlaybackParams, String str) {
@@ -11,37 +11,37 @@ import com.vtosters.lite.R;
import ru.vtosters.lite.utils.AndroidUtils;
public class GmsHook {
private static final String[] spoofPackages = {"com.mgoogle", "app.revanced"};
private static final String currentGms;
private static final boolean needToSpoof = !isGmsInstalled() && (isFakeGmsInstalled() || isFakeGms2Installed());
static {
currentGms = getSpoofPackagePrefix();
}
private static boolean isPackageInstalled(String packageName) {
public static boolean isGmsInstalled() {
try {
AndroidUtils.getGlobalContext().getPackageManager().getPackageInfo(packageName, 0);
AndroidUtils.getGlobalContext().getPackageManager().getPackageInfo("com.google.android.gms", 0);
return true;
} catch (Exception unused) {
return false;
}
}
} // Google Market Services check
public static boolean isGmsInstalled() {
return isPackageInstalled("com.google.android.gms");
}
public static boolean isFakeGmsInstalled() {
try {
AndroidUtils.getGlobalContext().getPackageManager().getPackageInfo("com.mgoogle.android.gms", 0);
return true;
} catch (Exception unused) {
return false;
}
} // Microg Google Market Services check
public static boolean isSpoofPackageInstalled(String packageName) {
return isPackageInstalled(packageName + ".android.gms");
}
public static boolean isFakeGms2Installed() {
try {
AndroidUtils.getGlobalContext().getPackageManager().getPackageInfo("app.revanced.android.gms", 0);
return true;
} catch (Exception unused) {
return false;
}
} // Microg Google Market Services check
public static boolean isAnyServicesInstalled() {
for (String packageName : spoofPackages) {
if (isSpoofPackageInstalled(packageName)) {
return true;
}
}
return false;
return isGmsInstalled() || isFakeGmsInstalled() || isFakeGms2Installed();
}
public static void fixGapps() {
@@ -52,10 +52,10 @@ public class GmsHook {
notificationManager.createNotificationChannel(new NotificationChannel("audio_playback_channel", AndroidUtils.getResources().getString(R.string.audio_message_play_error), NotificationManager.IMPORTANCE_LOW));
}
}
}
} // Music channels fix
public static String replaceGMSPackage(String str) {
return shouldSpoof() ? str.replaceAll("com.google", currentGms) : str;
return needToSpoof ? str.replaceAll("com.google", (isFakeGms2Installed() ? "app.revanced" : "com.mgoogle")) : str;
}
public static String getFirebaseInstanceIdReceiver() {
@@ -63,37 +63,6 @@ public class GmsHook {
}
public static Class getFirebaseInstanceIdReceiverClass() {
return getSpoofFirebaseInstanceIdReceiverClass();
return needToSpoof ? (isFakeGms2Installed() ? FirebaseInstanceIdReceiver3.class : FirebaseInstanceIdReceiver2.class) : FirebaseInstanceIdReceiver.class;
}
public static String getCurrentGms() {
return currentGms;
}
private static boolean shouldSpoof() {
return !isGmsInstalled() && (isSpoofPackageInstalled("com.mgoogle") || isSpoofPackageInstalled("app.revanced"));
}
private static String getSpoofPackagePrefix() {
for (String packageName : spoofPackages) {
if (isSpoofPackageInstalled(packageName)) {
return packageName;
}
}
return "com.google";
}
private static Class getSpoofFirebaseInstanceIdReceiverClass() {
switch (currentGms) {
case "com.mgoogle" -> {
return FirebaseInstanceIdReceiver2.class;
}
case "app.revanced" -> {
return FirebaseInstanceIdReceiver3.class;
}
default -> {
return FirebaseInstanceIdReceiver.class;
}
}
}
}
}
@@ -1,16 +0,0 @@
package ru.vtosters.hooks;
import com.vtosters.lite.api.execute.GetWallInfo;
import java.util.ArrayList;
/**
* Since June 12, 2024, there are troubles with API method "execute.getUserInfo" in the old versions of VK Client (<6.16),
* to fix that issue we need to upgrade "execute.getUserInfo" for new API versions
* and implement the new API method "newsfeed.getPostTopics" (TODO)*/
@SuppressWarnings("unused")
public class PostTopicsHook {
public static void hook(final GetWallInfo.a model) throws Exception {
model.f = new ArrayList<>();
}
}
@@ -1,40 +1,29 @@
package ru.vtosters.hooks;
import androidx.core.util.Pair;
import org.json.JSONException;
import org.json.JSONObject;
import ru.vtosters.hooks.other.Preferences;
import ru.vtosters.lite.utils.RenameTool;
public class RenameHook {
public static void injectIntoJson(JSONObject obj) throws JSONException {
if (isEnabled()) {
int i = obj.getInt("id");
if (RenameTool.updateRequested) {
RenameTool.reloadDB();
}
Pair<String, String> user = RenameTool.renamedUsers.get(i);
if (user == null) return;
obj.put(RenameTool.COLUMN_FIRSTNAME, user.first).put(RenameTool.COLUMN_LASTNAME, user.second);
}
}
public static boolean isEnabled() {
return Preferences.getBoolValue("unstableNameChanger", true);
// int i = obj.getInt("id");
// if (RenameTool.updateRequested) {
// RenameTool.reloadDB();
// }
//
// Pair<String, String> user = RenameTool.renamedUsers.get(i);
// if (user == null) return;
// obj.put(RenameTool.COLUMN_FIRSTNAME, user.first).put(RenameTool.COLUMN_LASTNAME, user.second);
}
public static void injectIntoJsonGroup(JSONObject obj) throws JSONException {
if (isEnabled()) {
int i = obj.getInt("id");
if (RenameTool.updateRequested) {
RenameTool.reloadDB();
}
String user = RenameTool.renamedGroups.get(i);
if (user == null) return;
obj.put("name", user);
}
// int i = obj.getInt("id");
//
// if (RenameTool.updateRequested) {
// RenameTool.reloadDB();
// }
//
// String user = RenameTool.renamedGroups.get(i);
// if (user == null) return;
// obj.put("name", user);
}
}
@@ -4,6 +4,7 @@ import android.util.Log;
import bruhcollective.itaysonlab.libvkx.client.LibVKXClient;
import com.vk.core.network.Network;
import com.vk.core.util.DeviceIdProvider;
import okhttp3.Headers;
import okhttp3.Request;
import okhttp3.Response;
import org.json.JSONArray;
@@ -41,13 +42,11 @@ public class CatalogJsonInjector {
removeUnsupportedLayouts(blocks);
if (Preferences.getBoolValue("playlistsCatalogs", true)) {
fetchCatalogId("https://vk.com/audio?section=my_playlists", oldItems);
fetchCatalogId("https://vk.com/audio?section=my_playlists", oldItems);
fetchCatalogId("https://vk.com/audio?section=albums", oldItems);
}
fetchCatalogId("https://vk.com/audio?section=albums", oldItems);
if (Preferences.sendMusicMetrics() && Preferences.getBoolValue("playStatCatalog", false)) {
if (Preferences.sendMusicMetrics()) {
fetchCatalogId("https://vk.com/audio?section=recent", oldItems);
}
@@ -57,11 +56,7 @@ public class CatalogJsonInjector {
if (!MusicCacheImpl.isEmpty() && !LibVKXClient.isIntegrationEnabled()) { // inj in playlist list
var noPlaylists = !json.has("playlists");
if (noPlaylists) {
PlaylistHelper.addCachedPlaylists(new JSONArray());
} else {
PlaylistHelper.addCachedPlaylists(json.optJSONArray("playlists"));
}
PlaylistHelper.addCachedPlaylists(json.optJSONArray("playlists"), noPlaylists);
if (!useOldAppVer || noPlaylists) {
var newBlocks = new JSONArray();
@@ -102,11 +97,7 @@ public class CatalogJsonInjector {
var noPlaylists = !json.has("playlists");
if (noPlaylists) {
PlaylistHelper.addCachedPlaylists(new JSONArray());
} else {
PlaylistHelper.addCachedPlaylists(json.optJSONArray("playlists"));
}
PlaylistHelper.addCachedPlaylists(json.optJSONArray("playlists"), noPlaylists);
if (!useOldAppVer && !noPlaylists) {
var newBlocks = new JSONArray();
@@ -220,14 +211,10 @@ public class CatalogJsonInjector {
}
}
private static void removeUnsupportedLayouts(JSONArray blocks) {
private static void removeUnsupportedLayouts(JSONArray blocks) throws JSONException {
for (int i = blocks.length() - 1; i >= 0; i--) {
JSONObject block = blocks.optJSONObject(i);
if (block == null) continue;
JSONObject layout = block.optJSONObject("layout");
if (layout == null) continue;
String data_type = block.optString("data_type");
if (Objects.equals(data_type, "music_recommended_playlists") || Objects.equals(data_type, "radiostations")) {
@@ -237,6 +224,8 @@ public class CatalogJsonInjector {
continue; // Skip to the next iteration after removing
}
if (layout == null) continue; // Skip to the next iteration if layout is null
String name = layout.optString("name");
if (!name.equals("header_extended")) {
continue; // Skip to the next iteration if not header_extended
@@ -245,14 +234,11 @@ public class CatalogJsonInjector {
if (layout.has("top_title")) {
blocks.remove(i);
}
try {
layout.put("name", "header");
} catch (JSONException e) {
e.fillInStackTrace();
}
layout.put("name", "header");
}
}
private static void setDefaultAudioPage(JSONArray jsonArray, JSONObject catalog) throws JSONException {
for (int i = 0; i < jsonArray.length(); i++) {
var item = jsonArray.optJSONObject(i);
@@ -15,7 +15,6 @@ import ru.vtosters.lite.downloaders.AudioDownloader;
import ru.vtosters.lite.music.cache.MusicCacheImpl;
import ru.vtosters.lite.music.cache.helpers.PlaylistHelper;
import ru.vtosters.lite.music.cache.helpers.TracklistHelper;
import ru.vtosters.lite.utils.AccountManagerUtils;
import java.util.ArrayList;
import java.util.List;
@@ -37,10 +36,8 @@ public class PlaylistInjector {
public static Observable<AudioGetPlaylist.c> injectGetPlaylist(AudioGetPlaylist audioGetPlaylist) {
try {
if (MusicCacheImpl.isEmpty()) {
if (MusicCacheImpl.isEmpty())
return null;
}
var requestArgs = audioGetPlaylist.b();
var id = requestArgs.get("id");
@@ -48,11 +45,9 @@ public class PlaylistInjector {
var accessKey = requestArgs.get("access_key");
boolean isVirtualPlaylist = accessKey != null && (accessKey.equals("cache"));
boolean isAlbumVirtualPlaylist = accessKey != null && (accessKey.equals("cacheAlbum"));
boolean isOwnCachePlaylist = Objects.equals(ownerId, String.valueOf(AccountManagerUtils.getUserId())) && Objects.equals(id, "-1");
if (TextUtils.isEmpty(id) || (!isVirtualPlaylist && !isAlbumVirtualPlaylist)) {
if (TextUtils.isEmpty(id) || (!isVirtualPlaylist && !isAlbumVirtualPlaylist))
return null;
}
return Observable.a((ObservableOnSubscribe<AudioGetPlaylist.c>) observableEmitter -> {
AudioGetPlaylist.c response = new AudioGetPlaylist.c();
@@ -86,11 +81,13 @@ public class PlaylistInjector {
return;
}
if (isOwnCachePlaylist) {
response.c = (ArrayList<MusicTrack>) TracklistHelper.getMyCachedMusicTracks();
response.c = (ArrayList<MusicTrack>) MusicCacheImpl.getPlaylistSongs(ownerId, id);
Log.d("Playlist", "Open playlist " + ownerId + "_" + id);
if (Objects.equals(id, "-1")) {
response.b = PlaylistHelper.createCachedPlaylistMetadata();
} else {
response.c = (ArrayList<MusicTrack>) MusicCacheImpl.getPlaylistSongs(ownerId, id);
response.b = MusicCacheImpl.getPlaylist(id, ownerId);
}
@@ -42,7 +42,7 @@ public class TracklistInjector {
Log.d("TracklistInjector", "Using vkx cache catalog");
observableEmitter.b(parser.c(new JSONObject(service.getCacheCatalog())));
} catch (Exception e) {
e.fillInStackTrace();
e.printStackTrace();
List<MusicTrack> tracks = new ArrayList<>();
List<String> cache = service.getCache();
@@ -55,14 +55,16 @@ public class TracklistInjector {
observableEmitter.b(parser.c(createVirtualCatalog(tracks)));
}
} catch (Exception e) {
e.fillInStackTrace();
e.printStackTrace();
}
});
} else {
if (MusicCacheImpl.isEmpty()) {
observableEmitter.b(parser.c(getEmptyCatalog()));
} else {
observableEmitter.b(parser.c(createVirtualCatalog(TracklistHelper.getMyCachedMusicTracks())));
observableEmitter.b(parser.c(createVirtualCatalog(
PlaylistCacheDbDelegate.getTracksInPlaylist(AndroidUtils.getGlobalContext(),
AccountManagerUtils.getUserId() + "_-1"))));
}
}
});
@@ -165,12 +167,12 @@ public class TracklistInjector {
boolean noPlaylists = hasNoPlaylists(blocks);
if (noPlaylists) {
PlaylistHelper.addCachedPlaylists(new JSONArray());
PlaylistHelper.addCachedPlaylists(catalogNode.optJSONArray("playlists"), true);
firstSection.put("blocks", createNewBlocks(blocks));
} else {
try {
PlaylistHelper.addCachedPlaylists(catalogNode.optJSONArray("playlists"));
PlaylistHelper.addCachedPlaylists(catalogNode.optJSONArray("playlists"), false);
updatePlaylistsIds(blocks);
} catch (Exception e) {
@@ -246,7 +248,7 @@ public class TracklistInjector {
.put(getCatalogPlaylist());
}
if (!PlaylistCacheDbDelegate.isPlaylistEmpty(AndroidUtils.getGlobalContext(), AccountManagerUtils.getUserId() + "_-1")) {
if (!MusicCacheImpl.getAllOwnTracks().isEmpty()) {
if (MusicCacheImpl.hasPlaylist()) blocks.put(getCatalogSeparator());
blocks.put(getCatalogHeader(AndroidUtils.getString(R.string.cached_tracks_title)))
.put(getShuffleButton())
@@ -270,7 +272,7 @@ public class TracklistInjector {
return new JSONObject()
.put("catalog", catalog)
.put("playlists", addCachedPlaylists(new JSONArray()))
.put("playlists", addCachedPlaylists(new JSONArray(), false))
.put("audios", TracklistHelper.tracksToJsons(tracks));
}
@@ -100,8 +100,8 @@ public class Preferences {
return getBoolValue("vkme", false);
}
public static int autocache() {
return Preferences.getPreferences().getInt("autocaching", 0);
public static boolean autocache() {
return getBoolValue("autocache", false);
}
public static boolean adsstories() {
@@ -115,7 +115,7 @@ public class Device {
+ "- Manufacturer: " + this.manufacturerName + "\n"
+ "- Brand: " + this.brandName + "\n"
+ "- Model: " + this.modelName + "\n"
+ (isMIUI() || isHyperOs() ? "- Miui/HyperOS Version Code: " + this.MiuiUiVersionCode + "\n" + "- Miui/HyperOS Version Name: " + this.MiuiUiVersionName + "\n" : "")
+ (isMIUI() ? "- Miui Version Code: " + this.MiuiUiVersionCode + "\n" + "- Miui Version Name: " + this.MiuiUiVersionName + "\n" : "")
+ (isSamsung() ? "- OneUi Major Version: " + this.OneUiMajorVersion + "\n" + "- OneUi Minor Version: " + this.OneUiMinorVersion + "\n" : "")
+ (hasMiuiIncrCode() ? "- Miui Version Incremental Code: " + this.MiuiIncrementalCode + "\n" : "")
+ (isEMUI() ? "- Emui Version: " + this.EmuiVersion : "");
@@ -56,7 +56,7 @@ public class OEMDetector {
}
public static boolean isOEM() {
return isMIUI() || isEMUI() || isFlyme() || isZenUI() || isSamsung() || isVivo() || isOneUi() || isHyperOs();
return isMIUI() || isEMUI() || isFlyme() || isZenUI() || isSamsung() || isVivo() || isOneUi();
}
public static boolean isMIUI() {
@@ -68,15 +68,6 @@ public class OEMDetector {
}
}
public static boolean isHyperOs() {
try {
int miuiVer = Integer.parseInt(getMiuiUiVersionCode()); // cuz hyperos gives 816 and etc
return miuiVer > 14 && isMIUI();
} catch (Exception unused) {
return false;
}
}
public static boolean isIntentResolved(Context ctx, Intent intent) {
return (intent != null && ctx.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null);
}
@@ -133,6 +124,7 @@ public class OEMDetector {
try {
return (String) getPropMtd.invoke(null, prop);
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
@@ -30,7 +30,6 @@ import ru.vtosters.hooks.other.Preferences;
import ru.vtosters.lite.di.singleton.VtOkHttpClient;
import ru.vtosters.lite.downloaders.AudioDownloader;
import ru.vtosters.lite.music.cache.MusicCacheImpl;
import ru.vtosters.lite.utils.AccountManagerUtils;
import ru.vtosters.lite.utils.AndroidUtils;
import ru.vtosters.lite.utils.music.MusicTrackUtils;
@@ -51,14 +50,13 @@ public class LastFMScrobbler {
var access_key = !TextUtils.isEmpty(musictrack.J) ? musictrack.J : "";
var album_id = musictrack.I;
var album = album_id != null ? album_id.getTitle() : null;
var isOwnTrack = musictrack.e == AccountManagerUtils.getUserId();
if (TextUtils.isEmpty(uid) || TextUtils.isEmpty(artist) || TextUtils.isEmpty(title) || duration == 0) {
Log.d("Scrobbler", "grabTrackInfo: " + "Empty track, info: " + artist + " - " + title + " - " + duration + " - " + uid);
return;
}
if (needToCache(isOwnTrack) && !MusicCacheImpl.isCachedTrack(uid)) {
if (Preferences.autocache() && !MusicCacheImpl.isCachedTrack(uid)) {
if (LibVKXClient.isIntegrationEnabled()) {
LibVKXClient.getInstance().runOnService(service -> {
try {
@@ -75,12 +73,6 @@ public class LastFMScrobbler {
scrobbleTrack(duration, artist, title, uid, album);
}
private static boolean needToCache(boolean isOwnTrack) {
int autocache = Preferences.autocache();
return autocache == 2 || (autocache == 1 && isOwnTrack);
}
public static void scrobbleTrack(
long duration,
String artist,
@@ -59,12 +59,12 @@ public class MusicCacheImpl {
}
public static boolean hasPlaylist() {
return !PlaylistCacheDbDelegate.isPlaylistsDbEmpty(AndroidUtils.getGlobalContext()); // has playlists or not
return PlaylistCacheDbDelegate.getPlaylistsCount(AndroidUtils.getGlobalContext()) != 0; // has playlists or not
}
public static long getTracksCount() {
return !LibVKXClient.isIntegrationEnabled()
? PlaylistCacheDbDelegate.getTracksCountInPlaylist(AndroidUtils.getGlobalContext(),AccountManagerUtils.getUserId() + "_-1")
? MusicCacheDbDelegate.getTracksCount(AndroidUtils.getGlobalContext())
: LibVKXClient.getInstance().runOnServiceSync(
new LibVKXClientImpl.LibVKXActionGeneric<Long>() {
@Override
@@ -89,7 +89,7 @@ public class MusicCacheImpl {
}
public static boolean isEmpty() {
return !LibVKXClient.isIntegrationEnabled() && MusicCacheDbDelegate.isEmpty(AndroidUtils.getGlobalContext());
return !LibVKXClient.isIntegrationEnabled() && getTracksCount() == 0L;
}
public static void clear() {
@@ -174,15 +174,6 @@ public class MusicCacheDb extends SQLiteOpenHelper implements AutoCloseable { //
return DatabaseUtils.queryNumEntries(getReadableDatabase(), Constants.TABLE_NAME);
}
public boolean isDatabaseEmpty() {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT EXISTS(SELECT 1 FROM " + Constants.TABLE_NAME + " LIMIT 1)", null);
cursor.moveToFirst();
boolean isEmpty = cursor.getInt(0) == 0;
cursor.close();
return isEmpty;
}
public MusicTrack getTrackById(String trackId) {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(Constants.TABLE_NAME, null, Constants.COLUMN_TRACK_ID + " = ?", new String[]{trackId}, null, null, null);
@@ -53,7 +53,8 @@ public class PlaylistCacheDb extends SQLiteOpenHelper implements AutoCloseable {
Boolean.parseBoolean(cur.getString(cur.getColumnIndex(Constants.COLUMN_IS_EXPLICIT))),
cur.getString(cur.getColumnIndex(Constants.COLUMN_TITLE)),
cur.getString(cur.getColumnIndex(Constants.COLUMN_DESCRIPTION)),
photo);
photo,
0);
Log.d("Playlist", "generated " + Playlist.U.a(playlist).v1());
@@ -169,50 +170,6 @@ public class PlaylistCacheDb extends SQLiteOpenHelper implements AutoCloseable {
return playlists;
}
public long getTracksCountInPlaylist(String playlistId) {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(
Constants.TABLE_PLAYLIST_TRACKS,
new String[]{Constants.COLUMN_TRACK_ID},
Constants.COLUMN_PLAYLIST_ID + " = ?",
new String[]{playlistId},
null, null, null
);
long count = cursor.getCount();
cursor.close();
return count;
}
public List<String> getAllPlaylistIds() {
SQLiteDatabase db = getReadableDatabase();
List<String> playlistIds = new ArrayList<>();
Cursor cursor = db.query(
Constants.TABLE_NAME,
new String[]{Constants.COLUMN_ID, Constants.COLUMN_OWNER_ID},
null, null, null, null, null
);
if (cursor.moveToFirst()) {
do {
String playlistId = cursor.getString(cursor.getColumnIndexOrThrow(Constants.COLUMN_OWNER_ID)) + "_" + cursor.getString(cursor.getColumnIndexOrThrow(Constants.COLUMN_ID));
playlistIds.add(playlistId);
} while (cursor.moveToNext());
}
cursor.close();
return playlistIds;
}
public boolean isPlaylistsDbEmpty() {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT EXISTS(SELECT 1 FROM " + Constants.TABLE_NAME + " LIMIT 1)", null);
cursor.moveToFirst();
boolean isEmpty = cursor.getInt(0) == 0;
cursor.close();
return isEmpty;
}
public void addTrackToPlaylist(String playlistId, String trackId) {
ContentValues values = new ContentValues();
values.put(Constants.COLUMN_PLAYLIST_ID, playlistId);
@@ -224,15 +181,6 @@ public class PlaylistCacheDb extends SQLiteOpenHelper implements AutoCloseable {
getWritableDatabase().delete(Constants.TABLE_PLAYLIST_TRACKS, Constants.COLUMN_PLAYLIST_ID + " = ? AND " + Constants.COLUMN_TRACK_ID + " = ?", new String[]{playlistId, trackId});
}
public boolean isPlaylistEmpty(String playlistId) {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT EXISTS(SELECT 1 FROM " + Constants.TABLE_PLAYLIST_TRACKS + " WHERE " + Constants.COLUMN_PLAYLIST_ID + " = ? LIMIT 1)", new String[]{playlistId});
cursor.moveToFirst();
boolean isEmpty = cursor.getInt(0) == 0;
cursor.close();
return isEmpty;
}
public List<MusicTrack> getTracksInPlaylist(String playlistId) {
SQLiteDatabase db = getReadableDatabase();
Cursor cursor = db.query(
@@ -55,12 +55,6 @@ public class MusicCacheDbDelegate {
}
}
public static boolean isEmpty(Context context) {
try (var db = connectToDb(context)) {
return db.isDatabaseEmpty();
}
}
public static boolean isCachedTrack(Context context, String trackId) {
try (var db = connectToDb(context)) {
return db.isCachedTrack(trackId);
@@ -62,31 +62,6 @@ public class PlaylistCacheDbDelegate {
}
}
public static long getTracksCountInPlaylist(Context context, String playlistId) {
try (var db = connectToDb(context)) {
return db.getTracksCountInPlaylist(playlistId);
}
}
public static boolean isPlaylistsDbEmpty(Context context) {
try (var db = connectToDb(context)) {
return db.isPlaylistsDbEmpty();
}
}
public static void removeAllPlaylists(Context context) {
List<String> playlistIds = getAllPlaylistIds(context);
for (String playlistId : playlistIds) {
deletePlaylist(context, playlistId);
}
}
public static List<String> getAllPlaylistIds(Context context) {
try (var db = connectToDb(context)) {
return db.getAllPlaylistIds();
}
}
public static boolean isCachedPlaylist(Context context, String id) {
try (var db = connectToDb(context)) {
String[] parts = id.split("_");
@@ -137,12 +112,6 @@ public class PlaylistCacheDbDelegate {
}
}
public static boolean isPlaylistEmpty(Context context, String playlistId) {
try (var db = connectToDb(context)) {
return db.isPlaylistEmpty(playlistId);
}
}
public static void drop(Context context) {
context.deleteDatabase(PlaylistCacheDb.Constants.DB_NAME);
}
@@ -7,7 +7,6 @@ import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import ru.vtosters.lite.music.cache.MusicCacheImpl;
import ru.vtosters.lite.music.cache.delegate.PlaylistCacheDbDelegate;
import ru.vtosters.lite.utils.AccountManagerUtils;
import ru.vtosters.lite.utils.AndroidUtils;
import ru.vtosters.lite.utils.NetworkUtils;
@@ -23,18 +22,22 @@ public class PlaylistHelper {
}
}
public static JSONArray addCachedPlaylists(JSONArray jsonArray) {
public static JSONArray addCachedPlaylists(JSONArray jsonArray, Boolean noPlaylists) {
try {
if (!PlaylistCacheDbDelegate.isPlaylistEmpty(AndroidUtils.getGlobalContext(), AccountManagerUtils.getUserId() + "_-1")) {
if (noPlaylists) {
jsonArray.put(new JSONArray().put(getCachedSongsPlaylist()));
} else {
jsonArray.put(getCachedSongsPlaylist());
}
if (MusicCacheImpl.hasPlaylist()) {
for (Playlist playlist : MusicCacheImpl.getPlaylists()) {
jsonArray.put(generatePlaylist(playlist.a, playlist.b, playlist.C, playlist.g, playlist.B, PlaylistUtils.getThumb(playlist)));
Log.d("PlaylistHelper", "Playlist cache added: " + playlist.a + " " + playlist.b + " " + playlist.C + " " + playlist.g + " " + playlist.B);
for (Playlist playlist : MusicCacheImpl.getPlaylists()) {
if (noPlaylists) {
jsonArray.put(new JSONArray().put(generatePlaylist(playlist.a, playlist.b, playlist.C, playlist.g, playlist.B, PlaylistUtils.getThumb(playlist), playlist.O)));
} else {
jsonArray.put(generatePlaylist(playlist.a, playlist.b, playlist.C, playlist.g, playlist.B, PlaylistUtils.getThumb(playlist), playlist.O));
}
Log.d("PlaylistHelper", "Playlist cache added: " + playlist.a + " " + playlist.b + " " + playlist.C + " " + playlist.g + " " + playlist.B);
}
} catch (JSONException e) {
e.fillInStackTrace();
@@ -42,7 +45,7 @@ public class PlaylistHelper {
return jsonArray;
}
public static JSONObject generatePlaylist(int id, int owner_id, boolean is_explicit, String title, String description, JSONObject photo) throws JSONException {
public static JSONObject generatePlaylist(int id, int owner_id, boolean is_explicit, String title, String description, JSONObject photo, int count) throws JSONException {
JSONObject playlist = new JSONObject()
.put("id", id)
.put("owner_id", owner_id)
@@ -61,7 +64,7 @@ public class PlaylistHelper {
.put("subtitle", "")
.put("meta", new JSONObject()
.put("view", "compact"))
.put("count", 0);
.put("count", count);
if (photo != null) {
playlist.put("photo", photo);
@@ -98,18 +101,18 @@ public class PlaylistHelper {
.put("height", 600))
.put("meta", new JSONObject()
.put("view", "compact"))
.put("count", 0);
.put("count", MusicCacheImpl.getAllOwnTracks().size());
}
public static JSONArray getCachedPlaylistsIds() {
JSONArray arr = new JSONArray();
if (NetworkUtils.isNetworkConnected() && !PlaylistCacheDbDelegate.isPlaylistEmpty(AndroidUtils.getGlobalContext(), AccountManagerUtils.getUserId() + "_-1")) {
if (NetworkUtils.isNetworkConnected() && !MusicCacheImpl.getAllOwnTracks().isEmpty()) {
arr.put(AccountManagerUtils.getUserId() + "_-1");
}
for (String playlist : PlaylistCacheDbDelegate.getAllPlaylistIds(AndroidUtils.getGlobalContext())) {
arr.put(playlist);
for (var playlist : MusicCacheImpl.getPlaylists()) {
arr.put(playlist.v1());
}
return arr;
@@ -28,7 +28,7 @@ public class TracklistHelper {
boolean doNotinvertOrder = Preferences.getBoolValue("invertCachedTracks", false);
if (doNotinvertOrder) {
if (!doNotinvertOrder) {
Collections.reverse(tracks);
}
@@ -8,11 +8,9 @@ import com.google.android.exoplayer2.source.hls.playlist.e;
import com.google.android.exoplayer2.source.hls.playlist.f;
import com.google.android.exoplayer2.source.hls.playlist.f.a;
import com.vk.dto.music.MusicTrack;
import com.vk.dto.music.Playlist;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;
@@ -22,6 +20,7 @@ import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import com.vk.dto.music.Playlist;
import ru.vtosters.hooks.other.Preferences;
import ru.vtosters.lite.music.converter.ts.MpegDemuxer;
import ru.vtosters.lite.music.interfaces.Callback;
@@ -38,29 +37,17 @@ public final class Mp3Downloader implements ITrackDownloader {
@Override
public void download(MusicTrack track, Callback callback, Playlist playlist) {
String uri = track.D;
if (Objects.requireNonNull(uri).isEmpty()) {
String msg = "link error: " + track.y1() + ", title: " + Mp3Downloader.getTitle(track);
Log.d("Mp3Downloader", msg);
throw new RuntimeException(msg);
}
if (Objects.requireNonNull(uri).contains("master.m3u8?siren=1")) {
try {
String content = IOUtils.readAllLines(new URL(uri).openStream());
String replacement = content.split("\n")[2].trim();
uri = uri.replace("master.m3u8?siren=1", replacement);
} catch (IOException e) {
callback.onFailure(e);
return;
}
}
var tsParser = new com.google.android.exoplayer2.source.hls.playlist.h(e.a(uri));
var baseUri = uri.substring(0, uri.lastIndexOf("/") + 1);
var tsParser = new com.google.android.exoplayer2.source.hls.playlist.h(e.a(track.D));
var baseUri = track.D.substring(0, track.D.lastIndexOf("/") + 1);
try {
var segments = ((f) tsParser.a(Uri.parse(baseUri), IOUtils.openStream(uri))).o;
var segments = ((f) tsParser.a(Uri.parse(baseUri), IOUtils.openStream(track.D))).o;
byte[] buff = getMergedTs(baseUri, segments, callback);
MpegDemuxer.convert(buff, outputFile.getAbsolutePath());
@@ -10,7 +10,7 @@ import ru.vtosters.lite.utils.NavigatorUtils;
public class InstallGMS {
public static void alert(final Activity activity) {
if (!GmsHook.isAnyServicesInstalled() && !GmsHook.isGmsInstalled() && Preferences.getBoolValue("showAlertGms", true)) {
if (!GmsHook.isAnyServicesInstalled() && Preferences.getBoolValue("showAlertGms", true)) {
new VkAlertDialog.Builder(activity)
.setTitle(activity.getString(R.string.warning))
.setMessage(activity.getString(R.string.gmsissuesumm))
@@ -3,12 +3,9 @@ package ru.vtosters.lite.ui.fragments;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import bruhcollective.itaysonlab.libvkx.client.LibVKXClient;
import com.vk.core.dialogs.alert.VkAlertDialog;
import com.vk.dto.music.Playlist;
@@ -20,18 +17,13 @@ import ru.vtosters.lite.music.LastFMScrobbler;
import ru.vtosters.lite.music.cache.MusicCacheImpl;
import ru.vtosters.lite.music.cache.delegate.PlaylistCacheDbDelegate;
import ru.vtosters.lite.ui.PreferenceFragmentUtils;
import ru.vtosters.lite.utils.AccountManagerUtils;
import ru.vtosters.lite.utils.AndroidUtils;
import ru.vtosters.lite.utils.LifecycleUtils;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static ru.vtosters.hooks.other.Preferences.getBoolValue;
import static ru.vtosters.hooks.other.ThemesUtils.getTextAttr;
public class MusicFragment extends TrackedMaterialPreferenceToolbarFragment {
private static final ExecutorService executor = Executors.newCachedThreadPool();
@@ -56,7 +48,7 @@ public class MusicFragment extends TrackedMaterialPreferenceToolbarFragment {
if (MusicCacheImpl.isEmpty()) {
AndroidUtils.sendToast(requireContext().getString(com.vtosters.lite.R.string.no_cache_error));
} else {
delcache(requireContext(), false);
delcache(requireContext());
}
return true;
}
@@ -74,18 +66,6 @@ public class MusicFragment extends TrackedMaterialPreferenceToolbarFragment {
return true;
}
);
PreferenceFragmentUtils.addPreference(
getPreferenceScreen(),
"cached_playlists",
"Удалить все скачанные плейлисты",
null,
null,
preference -> {
delcache(requireContext(), true);
return true;
}
);
}
PreferenceFragmentUtils.addPreference(
@@ -113,38 +93,15 @@ public class MusicFragment extends TrackedMaterialPreferenceToolbarFragment {
}
).setEnabled(!MusicCacheImpl.isEmpty());
PreferenceFragmentUtils.addPreference(
PreferenceFragmentUtils.addMaterialSwitchPreference(
getPreferenceScreen(),
"autocache_params",
"autocache",
getString(com.vtosters.lite.R.string.autocache_title),
getAutocacheSumm(),
getString(com.vtosters.lite.R.string.autocache_summ),
null,
preference -> {
List<String> items = Arrays.asList("Не кешировать", "Только свои", "Все");
ArrayAdapter<String> adapter = new ArrayAdapter<>(requireContext(), android.R.layout.simple_list_item_1, items) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView textView = (TextView) super.getView(position, convertView, parent);
textView.setTextColor(getTextAttr());
return textView;
}
};
int selectedItem = Preferences.getPreferences().getInt("autocaching", 0);
if (selectedItem >= 0 && selectedItem < items.size()) {
adapter.getItem(selectedItem);
}
new VkAlertDialog.Builder(getActivity())
.setAdapter(adapter, (dialog, which) -> {
adapter.getItem(which);
Preferences.getPreferences().edit().putInt("autocaching", which).apply();
findPreference("autocache_params").setSummary(getAutocacheSumm());
dialog.cancel();
})
.show();
false,
(preference, o) -> {
Preferences.getPreferences().edit().putBoolean("autocache", (boolean) o).apply();
return true;
}
);
@@ -209,7 +166,6 @@ public class MusicFragment extends TrackedMaterialPreferenceToolbarFragment {
return;
}
Preferences.setMetadataSeparator(separator.getText().toString());
findPreference("metadataSeparator").setSummary(separator.getText().toString());
})
.setNegativeButton("Отмена", (dialog, which) -> dialog.cancel())
.show();
@@ -232,19 +188,6 @@ public class MusicFragment extends TrackedMaterialPreferenceToolbarFragment {
}
);
PreferenceFragmentUtils.addMaterialSwitchPreference(
getPreferenceScreen(),
"playStatCatalog",
"Список истории прослушиваний",
"Показывать вкладку истории прослушиваний в музыкальном разделе\n\nОтключение ускорит открытие музыкального раздела при медленном интернете",
null,
false,
(preference, o) -> {
Preferences.getPreferences().edit().putBoolean("playStatCatalog", (boolean) o).apply();
return true;
}
).setVisible(Preferences.sendMusicMetrics() && !getBoolValue("useOldAppVer", false));
if (!Preferences.serverFeaturesDisable()) {
PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), "Интеграция Genius");
PreferenceFragmentUtils.addMaterialSwitchPreference(
@@ -352,19 +295,6 @@ public class MusicFragment extends TrackedMaterialPreferenceToolbarFragment {
list.setVisible(!Preferences.getBoolValue("useOldAppVer", false));
getPreferenceScreen().addPreference(list);
PreferenceFragmentUtils.addMaterialSwitchPreference(
getPreferenceScreen(),
"playlistsCatalogs",
"Списки плейлистов",
"Показывать вкладку плейлистов и альбомов прослушиваний в музыкальном разделе\n\nОтключение ускорит открытие музыкального раздела при медленном интернете",
null,
true,
(preference, o) -> {
Preferences.getPreferences().edit().putBoolean("playlistsCatalogs", (boolean) o).apply();
return true;
}
).setVisible(!getBoolValue("useOldAppVer", false));
}
private void lastfmAuth(Context ctx) {
@@ -404,15 +334,6 @@ public class MusicFragment extends TrackedMaterialPreferenceToolbarFragment {
.show();
}
private static String getAutocacheSumm() {
int autocache = Preferences.autocache();
return switch (autocache) {
case 1 -> "Только для своих";
case 2 -> "Кешировать всё";
default -> "Отключено";
};
}
public void updateLastFmPref() {
if (LastFMScrobbler.isLoggedIn()) {
findPreference("lastfm_auth").setSummary(getString(com.vtosters.lite.R.string.lastfm_authorized_as) + " " + LastFMScrobbler.getUserName());
@@ -434,8 +355,7 @@ public class MusicFragment extends TrackedMaterialPreferenceToolbarFragment {
.show();
}
@SuppressLint("DefaultLocale")
private void cachedPlaylistsDialog(Context ctx) {
private static void cachedPlaylistsDialog(Context ctx) {
List<Playlist> playlists = PlaylistCacheDbDelegate.getAllPlaylists(ctx);
String[] playlistNames = new String[playlists.size()];
@@ -450,27 +370,19 @@ public class MusicFragment extends TrackedMaterialPreferenceToolbarFragment {
String playlistId = selectedPlaylist.v1();
PlaylistCacheDbDelegate.deletePlaylist(ctx, playlistId);
AndroidUtils.sendToast("Плейлист удален");
findPreference("cached_playlists").setSummary(String.format("Скачано плейлистов: %d", MusicCacheImpl.getPlaylists().size()));
});
builder.show();
}
private void delcache(Context ctx, boolean isPlaylists) {
private void delcache(Context ctx) {
new VkAlertDialog.Builder(ctx)
.setTitle(com.vtosters.lite.R.string.warning)
.setMessage(com.vtosters.lite.R.string.cached_tracks_remove_confirm)
.setPositiveButton(com.vtosters.lite.R.string.yes, (dialog, which) -> {
executor.submit(() -> {
if (isPlaylists) {
PlaylistCacheDbDelegate.removeAllPlaylists(ctx);
} else {
PlaylistCacheDbDelegate.deletePlaylist(ctx, AccountManagerUtils.getUserId() + "_-1");
}
});
findPreference("cached_tracks").setSummary(String.format(requireContext().getString(com.vtosters.lite.R.string.cached_tracks_counter), MusicCacheImpl.getTracksCount()));
})
.setNeutralButton(com.vtosters.lite.R.string.no, (dialog, which) -> dialog.cancel())
.setPositiveButton(com.vtosters.lite.R.string.yes,
(dialog, which) -> executor.submit(MusicCacheImpl::clear))
.setNeutralButton(com.vtosters.lite.R.string.no,
(dialog, which) -> dialog.cancel())
.show();
}
@@ -60,12 +60,12 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment {
return true;
});
findPreference("microgsettings").setVisible(GmsHook.isAnyServicesInstalled() && !GmsHook.isGmsInstalled());
findPreference("microgsettings").setVisible(GmsHook.isFakeGmsInstalled() && !GmsHook.isGmsInstalled());
findPreference("microgsettings").setOnPreferenceClickListener(preference -> {
try {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName(GmsHook.getCurrentGms() + ".android.gms", "org.microg.gms.ui.SettingsActivity"));
intent.setComponent(new ComponentName((GmsHook.isFakeGms2Installed() ? "app.revanced.android.gms" : "com.mgoogle.android.gms"), "org.microg.gms.ui.SettingsActivity"));
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
@@ -81,17 +81,6 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment {
return true;
});
findPreference("unstableNameChangerDrop").setOnPreferenceClickListener(preference -> {
RenameTool.clearDatabase();
LifecycleUtils.restartApplicationWithTimer();
return true;
});
findPreference("unstableNameChanger").setOnPreferenceChangeListener((preference, o) -> {
LifecycleUtils.restartApplicationWithTimer();
return true;
});
findPreference("copydebuginfo").setOnPreferenceClickListener(preference -> {
copyText(new DeviceInfoCollector().collect().forLogging());
Toast.makeText(requireContext(), AndroidUtils.getString("device_info_copied"), Toast.LENGTH_SHORT).show();
@@ -227,23 +227,6 @@ public class SponsorPostFragment extends TrackedMaterialPreferenceToolbarFragmen
}
);
if (NetworkUtils.isNetworkConnected()) {
PreferenceFragmentUtils.addPreference(
getPreferenceScreen(),
"",
"Обновить списки фильтров",
null,
null,
preference -> {
this.requireActivity().runOnUiThread(() -> {
FiltersPreferences.forceUpdateFilters();
AndroidUtils.sendToast("Обновлено");
});
return false;
}
);
}
PreferenceFragmentUtils.addPreference(
getPreferenceScreen(),
"",
@@ -13,8 +13,6 @@ import ru.vtosters.lite.ui.PreferenceFragmentUtils;
import ru.vtosters.lite.utils.AndroidUtils;
import ru.vtosters.lite.utils.VersionReader;
import static ru.vtosters.hooks.GmsHook.isSpoofPackageInstalled;
public class SystemInfo extends TrackedMaterialPreferenceToolbarFragment {
@Override
@@ -48,11 +46,11 @@ public class SystemInfo extends TrackedMaterialPreferenceToolbarFragment {
boolean isZenUI = OEMDetector.isZenUI();
boolean isEMUI = OEMDetector.isEMUI();
boolean hasMiuiIncrCode = OEMDetector.hasMiuiIncrCode();
boolean isHyperOS = OEMDetector.isHyperOs();
boolean hasGMS = GmsHook.isGmsInstalled();
boolean hasVancedMicroG = GmsHook.isAnyServicesInstalled();
String GMSPackageName = hasGMS ? "com.google.android.gms" : hasVancedMicroG ? GmsHook.getCurrentGms() + ".android.gms" : "no gms or microg";
boolean hasVancedMicroG = GmsHook.isFakeGmsInstalled();
boolean hasReVancedMicroG = GmsHook.isFakeGms2Installed();
String GMSPackageName = hasGMS ? "com.google.android.gms" : hasVancedMicroG ? "com.mgoogle.android.gms" : hasReVancedMicroG ? "app.revanced.android.gms" : "no gms or microg";
boolean isValidSignature = Preferences.isValidSignature();
boolean isTablet = AndroidUtils.isTablet();
@@ -106,7 +104,9 @@ public class SystemInfo extends TrackedMaterialPreferenceToolbarFragment {
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", "isInstalledGoogleGMS", "Value: " + hasGMS, 0, null);
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", "isInstalledMicroG", "Value: " + hasVancedMicroG, 0, null);
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", "isInstalledVancedMicroG", "Value: " + hasVancedMicroG, 0, null);
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", "isInstalledReVancedMicroG", "Value: " + hasReVancedMicroG, 0, null);
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", "Product Name", productName, 0, preference -> {
((ClipboardManager) requireActivity().getSystemService(Context.CLIPBOARD_SERVICE)).setPrimaryClip(ClipData.newPlainText("MBH-ST", productName));
@@ -194,8 +194,6 @@ public class SystemInfo extends TrackedMaterialPreferenceToolbarFragment {
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", "isMiui", "Value: " + isMiui, 0, null);
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", "isHyperOS", "Value: " + isHyperOS, 0, null);
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", "isEMUI", "Value: " + isEMUI, 0, null);
PreferenceFragmentUtils.addPreference(getPreferenceScreen(), "", "isFlyme", "Value: " + isFlyme, 0, null);
@@ -108,7 +108,7 @@ public class VTSettings extends TrackedMaterialPreferenceToolbarFragment {
boolean isLinksUnverified = AndroidUtils.isLinksUnverified(requireActivity());
boolean isDozingAvailable = Build.VERSION.SDK_INT >= 23 && !manager.isIgnoringBatteryOptimizations(AndroidUtils.getPackageName());
boolean areNotificationsDisabled = !AndroidUtils.areNotificationsEnabled() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
boolean isGMSNotInstalled = !GmsHook.isAnyServicesInstalled() && !GmsHook.isGmsInstalled();
boolean isGMSNotInstalled = !GmsHook.isAnyServicesInstalled();
if (AccountManagerUtils.isLogin()) {
Preference accountSwitcher = PreferenceFragmentUtils.addPreference(
@@ -584,7 +584,7 @@ public class VTSettings extends TrackedMaterialPreferenceToolbarFragment {
}
);
if (Build.VERSION.SDK_INT >= 33 && (!OEMDetector.isMIUI() || OEMDetector.isHyperOs())) {
if (Build.VERSION.SDK_INT >= 33 && !OEMDetector.isMIUI()) {
PreferenceFragmentUtils.addPreference(
getPreferenceScreen(),
"",
@@ -14,12 +14,10 @@ import com.vtosters.lite.api.ExtendedCommunityProfile;
import com.vtosters.lite.api.ExtendedUserProfile;
import kotlin.Unit;
import kotlin.jvm.b.Functions;
import ru.vtosters.hooks.RenameHook;
import ru.vtosters.hooks.other.Preferences;
import ru.vtosters.lite.foaf.FoafBase;
import ru.vtosters.lite.utils.AccountManagerUtils;
import ru.vtosters.lite.utils.AndroidUtils;
import ru.vtosters.lite.utils.RenameTool;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
@@ -68,12 +66,10 @@ public class MenuBuilder {
return Unit.a;
});
if (RenameHook.isEnabled()) {
addItem(builder, AndroidUtils.getString(R.string.menu_change_name), () -> {
RenameTool.createDialog(eup, ctx);
return Unit.a;
});
}
// addItem(builder, AndroidUtils.getString(R.string.menu_change_name), () -> {
// RenameTool.createDialog(eup, ctx);
// return Unit.a;
// });
addItem(builder, AndroidUtils.getString(isPageWhitelistedFilter ? R.string.remove_from_filter_whitelist : R.string.add_to_filter_whitelist), () -> {
setWhitelistedFilter(eup, !isPageWhitelistedFilter);
@@ -87,7 +83,7 @@ public class MenuBuilder {
return Unit.a;
});
} catch (IllegalAccessException | InvocationTargetException e) {
e.fillInStackTrace();
e.printStackTrace();
}
}
@@ -104,12 +100,10 @@ public class MenuBuilder {
return Unit.a;
});
if (RenameHook.isEnabled()) {
addItem(builder, AndroidUtils.getString(R.string.menu_change_name), () -> {
RenameTool.createDialogGroup(ecp, ctx);
return Unit.a;
});
}
// addItem(builder, AndroidUtils.getString(R.string.menu_change_name), () -> {
// RenameTool.createDialogGroup(ecp, ctx);
// return Unit.a;
// });
addItem(builder, AndroidUtils.getString(isPageWhitelistedFilter ? R.string.remove_from_filter_whitelist : R.string.add_to_filter_whitelist), () -> {
setWhitelistedFilter(ecp, !isPageWhitelistedFilter);
@@ -129,7 +123,7 @@ public class MenuBuilder {
return Unit.a;
});
} catch (IllegalAccessException | InvocationTargetException e) {
e.fillInStackTrace();
e.printStackTrace();
}
}
@@ -24,25 +24,13 @@ import static ru.vtosters.lite.utils.AccountManagerUtils.getUserToken;
public class Metrics {
private static JSONArray events = new JSONArray();
public static void trackEvents(JSONObject object, boolean isMusic) {
if (NetworkUtils.isNetworkConnected()) {
handleNetworkConnected(object, isMusic);
} else {
handleNetworkDisconnected(object, isMusic);
}
}
private static void handleNetworkConnected(JSONObject object, boolean isMusic) {
if (isMusic || shouldSaveUserTraffic() || events.length() > 0) {
trackEventsImmediately(object);
} else {
trackEventList(object);
}
}
private static void handleNetworkDisconnected(JSONObject object, boolean isMusic) {
if (!isMusic) {
public static void trackEvents(JSONObject object) {
if (!NetworkUtils.isNetworkConnected()) {
events.put(object);
} else if (shouldSaveUserTraffic() || events.length() > 0) {
trackEventList(object);
} else {
trackEventsImmediately(object);
}
}
@@ -1,6 +1,5 @@
package ru.vtosters.lite.utils;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
@@ -13,15 +12,15 @@ import android.widget.LinearLayout;
import androidx.core.util.Pair;
import com.vk.core.dialogs.alert.VkAlertDialog;
import com.vk.dto.user.UserProfile;
import com.vk.im.engine.models.users.User;
import com.vtosters.lite.R;
import com.vtosters.lite.api.ExtendedCommunityProfile;
import com.vtosters.lite.api.ExtendedUserProfile;
import ru.vtosters.hooks.other.ThemesUtils;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.function.BiConsumer;
import static ru.vtosters.hooks.other.ThemesUtils.getSTextAttr;
import static ru.vtosters.hooks.other.ThemesUtils.getTextAttr;
@@ -48,40 +47,69 @@ public class RenameTool {
return helperInstance;
}
public static String getCurrentModifiedUser() {
Cursor rawQuery = getHelper().getReadableDatabase().rawQuery(String.format("SELECT * FROM %s WHERE %s=%s", TABLE_NAME, COLUMN_VKID, AccountManagerUtils.getUserId()), new String[0]);
if (rawQuery.moveToFirst()) {
try {
String decode = URLDecoder.decode(rawQuery.getString(rawQuery.getColumnIndexOrThrow(COLUMN_FIRSTNAME)), "UTF-8");
return decode + " " + URLDecoder.decode(rawQuery.getString(rawQuery.getColumnIndexOrThrow(COLUMN_LASTNAME)), "UTF-8");
} catch (java.io.UnsupportedEncodingException | java.lang.IllegalArgumentException e) {
e.printStackTrace();
} finally {
rawQuery.close();
}
} else rawQuery.close();
return null;
}
// Reload all values from DB
public static void reloadDB() {
renamedGroups.clear();
renamedUsers.clear();
updateRequested = false;
loadData(TABLE_NAME, (cursor, vkID) -> {
String firstName = decode(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_FIRSTNAME)));
String lastName = decode(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_LASTNAME)));
renamedUsers.put(vkID, new Pair<>(firstName, lastName));
});
loadData(TABLE_NAME_GROUP, (cursor, vkID) -> {
String name = decode(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_NAME)));
renamedGroups.put(vkID, name);
});
}
// Generic method to load data from the database
private static void loadData(String tableName, BiConsumer<Cursor, Integer> consumer) {
try (Cursor cursor = getHelper().getReadableDatabase().rawQuery("SELECT * FROM " + tableName, null)) {
try (Cursor cursor = getHelper().getReadableDatabase().rawQuery(String.format("SELECT * FROM %s", TABLE_NAME), new String[0])) {
while (cursor.moveToNext()) {
String firstName = URLDecoder.decode(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_FIRSTNAME)), "UTF-8");
String lastName = URLDecoder.decode(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_LASTNAME)), "UTF-8");
int vkID = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_VKID));
consumer.accept(cursor, vkID);
renamedUsers.put(vkID, new Pair<>(firstName, lastName));
}
} catch (Exception e) {
throw new RuntimeException("Failed to load data from " + tableName, e);
e.printStackTrace();
}
try (Cursor cursor = getHelper().getReadableDatabase().rawQuery(String.format("SELECT * FROM %s", TABLE_NAME_GROUP), new String[0])) {
while (cursor.moveToNext()) {
String name = URLDecoder.decode(cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_NAME)), "UTF-8");
int vkID = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_VKID));
renamedGroups.put(vkID, name);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static String decode(String value) {
public static void injectIntoChat(User u) {
int id = u.getId();
if (updateRequested) {
reloadDB();
}
Pair<String, String> user = renamedUsers.get(id);
if (user == null) return;
setObject(u, "I", user.first);
setObject(u, "J", user.second);
}
public static void setObject(User instance, String name, Object obj) {
try {
return URLDecoder.decode(value, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 encoding not supported", e);
Field f = User.class.getDeclaredField(name);
f.setAccessible(true);
f.set(instance, obj);
} catch (Exception e) {
e.printStackTrace();
}
}
@@ -89,7 +117,7 @@ public class RenameTool {
LinearLayout linearLayout = new LinearLayout(ctx);
linearLayout.setOrientation(LinearLayout.VERTICAL);
EditText fn = new EditText(ctx);
final EditText fn = new EditText(ctx);
fn.setHint(R.string.vk_auth_sign_up_first_name);
fn.setTextColor(getTextAttr());
fn.setHintTextColor(getSTextAttr());
@@ -100,7 +128,7 @@ public class RenameTool {
margin.setMargins(dp2px(20f), 0, dp2px(20f), 0);
fn.setLayoutParams(margin);
EditText ln = new EditText(ctx);
final EditText ln = new EditText(ctx);
ln.setHint(R.string.vk_auth_sign_up_last_name);
ln.setTextColor(getTextAttr());
ln.setHintTextColor(getSTextAttr());
@@ -109,93 +137,69 @@ public class RenameTool {
ln.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
ln.setLayoutParams(margin);
UserProfile profile = AccountManagerUtils.fromEup(eup);
final UserProfile profile = AccountManagerUtils.fromEup(eup);
fn.setText(AccountManagerUtils.getUserFirstName(profile));
ln.setText(AccountManagerUtils.getUserLastName(profile));
int id = AccountManagerUtils.getUserID(profile);
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(ctx)
var builder = new VkAlertDialog.Builder(ctx)
.setTitle(R.string.rename_title)
.setMessage(R.string.rename_message)
.setView(linearLayout)
.setPositiveButton("OK", (dialog, which) -> updateName(ctx, fn.getText().toString(), ln.getText().toString(), id));
if (isChangedName(id)) {
builder.setNeutralButton(R.string.rename_reset, (dialog, which) -> deleteUser(ctx, id));
}
.setPositiveButton("OK", (dialog, which) -> {
String firstName = fn.getText().toString();
String lastName = ln.getText().toString();
SQLiteDatabase writableDatabase = getHelper().getWritableDatabase();
try {
if (isChangedName(id)) {
writableDatabase.execSQL(
String.format("UPDATE %s SET %s='%s', %s='%s' WHERE %s='%s'",
TABLE_NAME,
COLUMN_FIRSTNAME, URLEncoder.encode(firstName, "UTF-8"),
COLUMN_LASTNAME, URLEncoder.encode(lastName, "UTF-8"),
COLUMN_VKID, id));
} else {
writableDatabase.execSQL(
String.format("INSERT INTO %s (%s, %s, %s) VALUES (%s, '%s', '%s')",
TABLE_NAME,
COLUMN_VKID, COLUMN_FIRSTNAME, COLUMN_LASTNAME,
id, URLEncoder.encode(firstName, "UTF-8"), URLEncoder.encode(lastName, "UTF-8")));
}
updateRequested = true;
if (id == AccountManagerUtils.getUserId()) {
ctx.sendBroadcast(new Intent("com.vkontakte.android.USER_NAME_CHANGED"));
}
ctx.sendBroadcast(new Intent("com.vkontakte.android.ACTION_PROFILE_UPDATED").putExtra("uid", id));
sendToast(ctx.getString(R.string.rename_success));
} catch (Exception e) {
e.printStackTrace();
sendToast(ctx.getString(R.string.rename_error));
}
});
if (isChangedName(id))
builder.setNeutralButton(R.string.rename_reset, (dialog, which) -> {
getHelper().getWritableDatabase().execSQL(
String.format(
"DELETE FROM %s WHERE %s='%s'",
TABLE_NAME,
COLUMN_VKID, id));
if (id == AccountManagerUtils.getUserId()) {
ctx.sendBroadcast(new Intent("com.vkontakte.android.USER_NAME_CHANGED"));
}
updateRequested = true;
ctx.sendBroadcast(new Intent("com.vkontakte.android.ACTION_PROFILE_UPDATED").putExtra("uid", id));
sendToast(ctx.getString(R.string.rename_remove_from_bd_success));
});
builder.show();
}
public static void deleteUser(Context ctx, int id) {
SQLiteDatabase writableDatabase = getHelper().getWritableDatabase();
writableDatabase.delete(TABLE_NAME, COLUMN_VKID + "=?", new String[]{String.valueOf(id)});
updateRequested = true;
notifyUser(ctx, id);
sendToast(ctx.getString(R.string.rename_remove_from_bd_success));
}
public static void clearDatabase() {
SQLiteDatabase writableDatabase = getHelper().getWritableDatabase();
writableDatabase.delete(TABLE_NAME, null, null);
writableDatabase.delete(TABLE_NAME_GROUP, null, null);
renamedGroups.clear();
renamedUsers.clear();
updateRequested = true;
}
public static void updateName(Context ctx, String firstName, String lastName, int id) {
SQLiteDatabase writableDatabase = getHelper().getWritableDatabase();
try {
ContentValues values = new ContentValues();
values.put(COLUMN_FIRSTNAME, encode(firstName));
values.put(COLUMN_LASTNAME, encode(lastName));
if (isChangedName(id)) {
// Update existing record
writableDatabase.update(TABLE_NAME, values, COLUMN_VKID + "=?", new String[]{String.valueOf(id)});
} else {
// Insert new record
values.put(COLUMN_VKID, id);
writableDatabase.insert(TABLE_NAME, null, values);
}
updateRequested = true;
notifyUser(ctx, id);
sendToast(ctx.getString(R.string.rename_success));
} catch (Exception e) {
throw new RuntimeException("Database operation failed", e);
}
}
private static String encode(String value) {
try {
return URLEncoder.encode(value, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("UTF-8 encoding not supported", e);
}
}
private static void notifyUser(Context ctx, int id) {
if (id == AccountManagerUtils.getUserId()) {
ctx.sendBroadcast(new Intent("com.vkontakte.android.USER_NAME_CHANGED"));
}
ctx.sendBroadcast(new Intent("com.vkontakte.android.ACTION_PROFILE_UPDATED").putExtra("uid", id));
}
public static void createDialogGroup(ExtendedCommunityProfile eup, final Context ctx) {
LinearLayout linearLayout = new LinearLayout(ctx);
linearLayout.setOrientation(LinearLayout.VERTICAL);
EditText fn = new EditText(ctx);
final EditText fn = new EditText(ctx);
fn.setHint(R.string.vk_auth_sign_up_first_name);
fn.setHintTextColor(getSTextAttr());
fn.setTextColor(getTextAttr());
@@ -206,61 +210,52 @@ public class RenameTool {
margin.setMargins(dp2px(20f), 0, dp2px(20f), 0);
fn.setLayoutParams(margin);
UserProfile profile = AccountManagerUtils.fromEup(eup);
final UserProfile profile = AccountManagerUtils.fromEup(eup);
fn.setText(AccountManagerUtils.getGroupName(profile));
int fid = AccountManagerUtils.getUserID(profile);
if (fid < 0) fid = -fid;
int id = fid;
final int id = fid;
VkAlertDialog.Builder builder = new VkAlertDialog.Builder(ctx)
var builder = new VkAlertDialog.Builder(ctx)
.setTitle(R.string.rename_title)
.setMessage(R.string.rename_message)
.setView(linearLayout)
.setPositiveButton("OK", (dialog, which) -> updateGroupName(ctx, fn.getText().toString(), id));
if (isChangedNameGroup(id)) {
builder.setNeutralButton(R.string.rename_reset, (dialog, which) -> deleteGroupName(ctx, id));
}
.setPositiveButton("OK", (dialog, which) -> {
String firstName = fn.getText().toString();
SQLiteDatabase writableDatabase = getHelper().getWritableDatabase();
try {
if (isChangedNameGroup(id)) {
writableDatabase.execSQL(
String.format(
"UPDATE %s SET %s='%s' WHERE %s='%s'",
TABLE_NAME_GROUP,
COLUMN_NAME, URLEncoder.encode(firstName, "UTF-8"),
COLUMN_VKID, id));
} else {
writableDatabase.execSQL(
String.format(
"INSERT INTO %s (%s, %s) VALUES (%s, '%s')",
TABLE_NAME_GROUP,
COLUMN_VKID, COLUMN_NAME,
id, URLEncoder.encode(firstName, "UTF-8")));
}
updateRequested = true;
sendToast(AndroidUtils.getString(R.string.rename_group_success));
} catch (Exception e) {
e.printStackTrace();
}
});
if (isChangedNameGroup(id))
builder.setNeutralButton(R.string.rename_reset, (dialog, which) -> {
getHelper().getWritableDatabase().execSQL(String.format("DELETE FROM %s WHERE %s='%s'", TABLE_NAME_GROUP, COLUMN_VKID, id));
updateRequested = true;
sendToast(ctx.getString(R.string.rename_remove_group_from_bd_success));
});
builder.show();
}
public static void deleteGroupName(Context ctx, int id) {
SQLiteDatabase writableDatabase = getHelper().getWritableDatabase();
writableDatabase.delete(TABLE_NAME_GROUP, COLUMN_VKID + "=?", new String[]{String.valueOf(id)});
updateRequested = true;
sendToast(ctx.getString(R.string.rename_remove_group_from_bd_success));
}
public static void updateGroupName(Context ctx, String groupName, int id) {
SQLiteDatabase writableDatabase = getHelper().getWritableDatabase();
try {
ContentValues values = new ContentValues();
values.put(COLUMN_NAME, encode(groupName));
if (isChangedNameGroup(id)) {
// Update existing record
writableDatabase.update(TABLE_NAME_GROUP, values, COLUMN_VKID + "=?", new String[]{String.valueOf(id)});
} else {
// Insert new record
values.put(COLUMN_VKID, id);
writableDatabase.insert(TABLE_NAME_GROUP, null, values);
}
updateRequested = true;
sendToast(AndroidUtils.getString(R.string.rename_group_success));
} catch (Exception e) {
throw new RuntimeException("Database operation failed", e);
}
}
public static boolean isChangedName(int uid) {
return renamedUsers.get(uid) != null;
}
@@ -269,6 +264,10 @@ public class RenameTool {
return renamedGroups.get(uid) != null;
}
public static boolean isIdInList(UserProfile profile) {
return true;
}
private static class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
@@ -61,18 +61,6 @@ public class FiltersPreferences {
editor.apply();
}
public static void forceUpdateFilters() {
SharedPreferences.Editor editor = preferences.edit();
preferences.getAll().keySet().stream()
.filter(key -> key.endsWith(":" + PREF_KEY_VERSION))
.forEach(key -> editor.putString(key, "0"));
editor.apply();
Updates.updateFilters();
}
public static boolean getSavedKeyValue(int id) {
return getFilter(id) != null;
}
@@ -1,6 +1,5 @@
package ru.vtosters.sponsorpost.utils;
import android.util.Log;
import ru.vtosters.lite.utils.NetworkUtils;
import ru.vtosters.lite.utils.newsfeed.NewsFeedFiltersUtils;
import ru.vtosters.sponsorpost.data.Filter;
@@ -32,17 +31,14 @@ public class Updates {
for (Filter filter : filters) {
Filter localFilter = findLocalFilterById(localFilters, filter.getId());
if (localFilter == null) {
Log.d("Updates", "local filter is not exist, adding new: " + filter.getId());
FiltersPreferences.saveFilter(filter);
} else {
String remoteVersion = filter.getVersion();
String localVersion = localFilter.getVersion();
if (Objects.equals(remoteVersion, localVersion)) {
Log.d("Updates", "saved local filter: " + localFilter.getId());
FiltersPreferences.saveFilter(localFilter);
} else {
Log.d("Updates", "saved remote filter: " + filter.getId());
FiltersPreferences.saveFilter(filter);
} else {
FiltersPreferences.saveFilter(localFilter);
}
}
}
View File
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -6437,7 +6437,7 @@
<string name="update_latest">У вас установлена последняя версия приложения</string>
<string name="update_err">Ошибка проверки обновления</string>
<string name="serverFeaturesDisable">Отключить все внешние подключения</string>
<string name="serverFeaturesDisable_summ">Отключает галочки и все дополнительные функции связанные с получением данных с сервера ВТостерс.\n\nАктуально для тех у кого безлимитный интернет на ВКонтакте</string>
<string name="serverFeaturesDisable_summ">Отключает галочки и все дополнительные функции связанные с получением данных с сервера ВТостерс.\n\nАктульно для тех у кого безлимитный интернет на ВКонтакте</string>
<string name="tgs_token_missing">Токен отсутствует</string>
<string name="tgs_token_reset_dialog">Сбросить токен бота?</string>
-10
View File
@@ -8,21 +8,11 @@
<Preference
android:key="microgsettings"
android:title="@string/microgsett"/>
</PreferenceCategory>
<PreferenceCategory android:title="Экспериментальные функции">
<com.vtosters.lite.ui.MaterialSwitchPreference
android:defaultValue="false"
android:key="batchmessages"
android:summary="Поможет исправить скорость загрузки сообщений, но работает нестабильно"
android:title="Альтернативная загрузка сообщений"/>
<com.vtosters.lite.ui.MaterialSwitchPreference
android:defaultValue="true"
android:key="unstableNameChanger"
android:title="Редактор имен"
android:summary="Редактор имен групп и профилей людей\n\nПри проблемах с работой сообщений лучше отключить данную функцию"/>
<Preference
android:key="unstableNameChangerDrop"
android:title="Сбросить информацию о переименованиях"/>
</PreferenceCategory>
<PreferenceCategory android:title="@string/vtverify">
<Preference
@@ -474,7 +474,7 @@
invoke-virtual {p1, v1, v0}, Ljava/net/HttpURLConnection;->setRequestProperty(Ljava/lang/String;Ljava/lang/String;)V
.line 15
const-string v0, "48761EEF50EE53AFC4CC9C5F10E6BDE7F8F5B82F"
const-string v0, "C8EAB7342DA62B4A229E1BFDEB27B029DD6788A1"
const-string v1, "X-Android-Cert"
@@ -390,8 +390,6 @@
.method public static final b(Lorg/json/JSONObject;)Lcom/vk/dto/newsfeed/Owner;
.locals 1
invoke-static {p0}, Lru/vtosters/hooks/RenameHook;->injectIntoJsonGroup(Lorg/json/JSONObject;)V
sget-object v0, Lcom/vk/dto/newsfeed/Owner;->h:Lcom/vk/dto/newsfeed/Owner$b;
invoke-virtual {v0, p0}, Lcom/vk/dto/newsfeed/Owner$b;->b(Lorg/json/JSONObject;)Lcom/vk/dto/newsfeed/Owner;
@@ -404,8 +402,6 @@
.method public static final c(Lorg/json/JSONObject;)Lcom/vk/dto/newsfeed/Owner;
.locals 1
invoke-static {p0}, Lru/vtosters/hooks/RenameHook;->injectIntoJson(Lorg/json/JSONObject;)V
sget-object v0, Lcom/vk/dto/newsfeed/Owner;->h:Lcom/vk/dto/newsfeed/Owner$b;
invoke-virtual {v0, p0}, Lcom/vk/dto/newsfeed/Owner$b;->c(Lorg/json/JSONObject;)Lcom/vk/dto/newsfeed/Owner;
@@ -194,8 +194,6 @@
move-result v0
const v0, 0x0
if-eqz v0, :cond_2
const/4 v0, 0x1
@@ -35,7 +35,7 @@
const-string v0, "func_v"
const/16 v1, 0x25
const/16 v1, 0x1b
.line 3
invoke-virtual {p0, v0, v1}, Lcom/vk/api/base/ApiRequest;->b(Ljava/lang/String;I)Lcom/vk/api/base/ApiRequest;
@@ -39,7 +39,7 @@
.line 3
invoke-virtual {p0, v0, p1}, Lcom/vk/api/base/ApiRequest;->b(Ljava/lang/String;I)Lcom/vk/api/base/ApiRequest;
const/16 v0, 0x17
const/16 v0, 0xb
const-string v1, "func_v"
@@ -476,89 +476,89 @@
invoke-direct {v2}, Landroid/util/SparseArray;-><init>()V
# const-string v4, "cities"
const-string v4, "cities"
# .line 20
# invoke-virtual {v1, v4}, Lorg/json/JSONObject;->getJSONArray(Ljava/lang/String;)Lorg/json/JSONArray;
.line 20
invoke-virtual {v1, v4}, Lorg/json/JSONObject;->getJSONArray(Ljava/lang/String;)Lorg/json/JSONArray;
# move-result-object v4
move-result-object v4
# const/4 v9, 0x0
const/4 v9, 0x0
# .line 21
# :goto_3
# invoke-virtual {v4}, Lorg/json/JSONArray;->length()I
.line 21
:goto_3
invoke-virtual {v4}, Lorg/json/JSONArray;->length()I
# move-result v10
move-result v10
const-string v11, "title"
# if-ge v9, v10, :cond_4
if-ge v9, v10, :cond_4
# .line 22
# invoke-virtual {v4, v9}, Lorg/json/JSONArray;->getJSONObject(I)Lorg/json/JSONObject;
.line 22
invoke-virtual {v4, v9}, Lorg/json/JSONArray;->getJSONObject(I)Lorg/json/JSONObject;
# move-result-object v10
move-result-object v10
# .line 23
# invoke-virtual {v10, v3}, Lorg/json/JSONObject;->getInt(Ljava/lang/String;)I
.line 23
invoke-virtual {v10, v3}, Lorg/json/JSONObject;->getInt(Ljava/lang/String;)I
# move-result v12
move-result v12
# invoke-virtual {v10, v11}, Lorg/json/JSONObject;->getString(Ljava/lang/String;)Ljava/lang/String;
invoke-virtual {v10, v11}, Lorg/json/JSONObject;->getString(Ljava/lang/String;)Ljava/lang/String;
# move-result-object v10
move-result-object v10
# invoke-virtual {v2, v12, v10}, Landroid/util/SparseArray;->put(ILjava/lang/Object;)V
invoke-virtual {v2, v12, v10}, Landroid/util/SparseArray;->put(ILjava/lang/Object;)V
# add-int/lit8 v9, v9, 0x1
add-int/lit8 v9, v9, 0x1
# goto :goto_3
goto :goto_3
# .line 24
# :cond_4
# new-instance v4, Landroid/util/SparseArray;
.line 24
:cond_4
new-instance v4, Landroid/util/SparseArray;
# invoke-direct {v4}, Landroid/util/SparseArray;-><init>()V
invoke-direct {v4}, Landroid/util/SparseArray;-><init>()V
# const-string v9, "cities"
const-string v9, "cities"
# .line 25
# invoke-virtual {v1, v9}, Lorg/json/JSONObject;->getJSONArray(Ljava/lang/String;)Lorg/json/JSONArray;
.line 25
invoke-virtual {v1, v9}, Lorg/json/JSONObject;->getJSONArray(Ljava/lang/String;)Lorg/json/JSONArray;
# move-result-object v9
move-result-object v9
# const/4 v10, 0x0
const/4 v10, 0x0
# .line 26
# :goto_4
# invoke-virtual {v9}, Lorg/json/JSONArray;->length()I
.line 26
:goto_4
invoke-virtual {v9}, Lorg/json/JSONArray;->length()I
# move-result v12
move-result v12
# if-ge v10, v12, :cond_5
if-ge v10, v12, :cond_5
# .line 27
# invoke-virtual {v9, v10}, Lorg/json/JSONArray;->getJSONObject(I)Lorg/json/JSONObject;
.line 27
invoke-virtual {v9, v10}, Lorg/json/JSONArray;->getJSONObject(I)Lorg/json/JSONObject;
# move-result-object v12
move-result-object v12
# .line 28
# invoke-virtual {v12, v3}, Lorg/json/JSONObject;->getInt(Ljava/lang/String;)I
.line 28
invoke-virtual {v12, v3}, Lorg/json/JSONObject;->getInt(Ljava/lang/String;)I
# move-result v13
move-result v13
# invoke-virtual {v12, v11}, Lorg/json/JSONObject;->getString(Ljava/lang/String;)Ljava/lang/String;
invoke-virtual {v12, v11}, Lorg/json/JSONObject;->getString(Ljava/lang/String;)Ljava/lang/String;
# move-result-object v12
move-result-object v12
# invoke-virtual {v4, v13, v12}, Landroid/util/SparseArray;->put(ILjava/lang/Object;)V
invoke-virtual {v4, v13, v12}, Landroid/util/SparseArray;->put(ILjava/lang/Object;)V
# add-int/lit8 v10, v10, 0x1
add-int/lit8 v10, v10, 0x1
# goto :goto_4
goto :goto_4
# :cond_5
:cond_5
const-string v4, "can_write_private_message"
.line 29
@@ -285,8 +285,7 @@
const-string p1, "func_v"
#upgrade func_v to 0x16 to fix issue related with outdated gettings of post topics
const/16 v0, 0x16
const/16 v0, 0x15
.line 9
invoke-virtual {p0, p1, v0}, Lcom/vk/api/base/ApiRequest;->b(Ljava/lang/String;I)Lcom/vk/api/base/ApiRequest;
@@ -386,7 +385,6 @@
.end annotation
.end param
const/4 v0, 0x0
:try_start_0
@@ -505,22 +503,18 @@
iput-object v1, v3, Lcom/vtosters/lite/api/execute/GetWallInfo$a;->e:Lcom/vk/auth/api/AccountPhoneVerify;
invoke-static {v3}, Lru/vtosters/hooks/PostTopicsHook;->hook(Lcom/vtosters/lite/api/execute/GetWallInfo$a;)V
const-string v1, "post_topics"
# const-string v1, "post_topics"
.line 17
invoke-virtual {p1, v1}, Lorg/json/JSONObject;->optJSONArray(Ljava/lang/String;)Lorg/json/JSONArray;
# .line 17
# invoke-virtual {p1, v1}, Lorg/json/JSONObject;->optJSONArray(Ljava/lang/String;)Lorg/json/JSONArray;
move-result-object v1
# move-result-object v1
# invoke-static {v1}, Lcom/vk/dto/newsfeed/PostTopic;->a(Lorg/json/JSONArray;)Ljava/util/List;
# move-result-object v1
# iput-object v1, v3, Lcom/vtosters/lite/api/execute/GetWallInfo$a;->f:Ljava/util/List;
invoke-static {v1}, Lcom/vk/dto/newsfeed/PostTopic;->a(Lorg/json/JSONArray;)Ljava/util/List;
move-result-object v1
iput-object v1, v3, Lcom/vtosters/lite/api/execute/GetWallInfo$a;->f:Ljava/util/List;
const-string v1, "special_events"