Compare commits
35
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5c407ed13 | ||
|
|
f185668e7e | ||
|
|
f0246b722f | ||
|
|
803c2ffa40 | ||
|
|
51bbcb5305 | ||
|
|
60277d0d19 | ||
|
|
36f4a348ca | ||
|
|
999f1ccd06 | ||
|
|
1f5efdb41e | ||
|
|
18c73d4e48 | ||
|
|
4341804732 | ||
|
|
d7c1ce4b78 | ||
|
|
7a30e2aae6 | ||
|
|
0194f5ede1 | ||
|
|
e5b5467b27 | ||
|
|
982b2bb059 | ||
|
|
bf6c72f2a8 | ||
|
|
5214964e0f | ||
|
|
ade17dd2cf | ||
|
|
a14043c4f3 | ||
|
|
678774c44e | ||
|
|
58f80a5f54 | ||
|
|
f6a2412014 | ||
|
|
cf99b8a838 | ||
|
|
baa3afc378 | ||
|
|
dbdf5469f5 | ||
|
|
7fc51708f9 | ||
|
|
25cc4720f7 | ||
|
|
00b1fa3cad | ||
|
|
71edb4db24 | ||
|
|
cd6ed0f51f | ||
|
|
c18ea2846f | ||
|
|
de9382cb50 | ||
|
|
9aa8a3d45c | ||
|
|
9efccb37ad |
Vendored
+1
-1
@@ -35,7 +35,7 @@
|
||||
-optimizationpasses 5
|
||||
-keepattributes SourceFile, LineNumberTable
|
||||
|
||||
-keep,allowoptimization class ru.vtosters.hooks.**, ru.vtosters.lite.utils.AndroidUtils, ru.vtosters.lite.utils.NetworkUtils, ru.vtosters.lite.utils.CrashReporter, ru.vtosters.lite.ui.activities.**, ru.vtosters.lite.services.**, ru.vtosters.lite.ui.fragments.**, ru.vtosters.lite.themes.**, ru.vtosters.lite.music.hook.**, ru.vtosters.lite.music.cache.injectors.**, ru.vtosters.lite.ui.wallpapers.NativeEffects, com.aefyr.tsg.g2.TelegramStickersService {
|
||||
-keep,allowoptimization class ru.vtosters.hooks.**, ru.vtosters.sponsorpost.internal.Native, ru.vtosters.lite.utils.AndroidUtils, ru.vtosters.lite.utils.NetworkUtils, ru.vtosters.lite.utils.CrashReporter, ru.vtosters.lite.ui.activities.**, ru.vtosters.lite.services.**, ru.vtosters.lite.ui.fragments.**, ru.vtosters.lite.themes.**, ru.vtosters.lite.music.hook.**, ru.vtosters.lite.music.cache.injectors.**, ru.vtosters.lite.ui.wallpapers.NativeEffects, com.aefyr.tsg.g2.TelegramStickersService {
|
||||
public <fields>;
|
||||
public <methods>;
|
||||
public <init>(...);
|
||||
|
||||
@@ -10,6 +10,7 @@ import android.util.Log;
|
||||
import androidx.annotation.Keep;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import ru.vtosters.sponsorpost.internal.Native;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -274,6 +275,7 @@ public final class MediaNative {
|
||||
SoLoader.init(context2, false);
|
||||
NativeLibLoader.loadLibrary("gnustl_shared");
|
||||
NativeLibLoader.loadLibrary("vkchronicle");
|
||||
Native.canVote = NativeLibLoader.loadLibrary("sponsorpost");
|
||||
loadVKMediaLibs();
|
||||
f17443d.notifyAll();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.vk.newsfeed.holders;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.vk.core.dialogs.alert.VkAlertDialog;
|
||||
import com.vk.core.ui.themes.VKThemeHelper;
|
||||
import com.vk.dto.newsfeed.entries.NewsEntry;
|
||||
import com.vk.dto.newsfeed.entries.Post;
|
||||
import com.vk.dto.newsfeed.entries.PromoPost;
|
||||
import com.vk.extensions.ViewExtKt;
|
||||
import com.vtosters.lite.R;
|
||||
import ru.vtosters.hooks.other.Preferences;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.newsfeed.NewsFeedFiltersUtils;
|
||||
import ru.vtosters.sponsorpost.internal.Native;
|
||||
import ru.vtosters.sponsorpost.internal.VotesPreferences;
|
||||
import ru.vtosters.sponsorpost.internal.VotesService;
|
||||
import ru.vtosters.sponsorpost.utils.PostsPreferences;
|
||||
|
||||
public final class AdMarkHolder extends BaseNewsEntryHolder<NewsEntry> {
|
||||
private final TextView F;
|
||||
|
||||
@SuppressLint("ResourceType")
|
||||
public AdMarkHolder(ViewGroup viewGroup) {
|
||||
super(R.layout.marked_as_ads, viewGroup);
|
||||
View view = ((RecyclerView.ViewHolder) this).itemView;
|
||||
this.F = ViewExtKt.a(view, R.id.text, (View.OnClickListener) null);
|
||||
}
|
||||
|
||||
@SuppressLint("ResourceType")
|
||||
public void b(NewsEntry newsEntry) { // onBind
|
||||
String disclamer = null;
|
||||
Drawable drawable = null;
|
||||
int height = 0;
|
||||
|
||||
if (newsEntry instanceof Post) {
|
||||
Post post = ((Post) newsEntry);
|
||||
if (post.L1()) {
|
||||
drawable = VKThemeHelper.a(R.drawable.marked_as_ads, R.attr.icon_tertiary);
|
||||
int ownerId = post.b();
|
||||
int postId = post.P1();
|
||||
int date = post.K();
|
||||
String text = post.getText();
|
||||
|
||||
if (PostsPreferences.isPostAd(ownerId, postId)) {
|
||||
disclamer = "SponsorPost: Реклама";
|
||||
if (Preferences.isValidSignature() && Native.canVote()) {
|
||||
this.F.setOnClickListener(listener -> voteDialog(ownerId, postId, date, this.F.getContext()));
|
||||
}
|
||||
} else if (VotesPreferences.isPostAd(ownerId, postId)) {
|
||||
disclamer = "SponsorPost: Возможно реклама";
|
||||
if (Preferences.isValidSignature() && Native.canVote()) {
|
||||
this.F.setOnClickListener(listener -> voteDialog(ownerId, postId, date, this.F.getContext()));
|
||||
}
|
||||
} else if (NewsFeedFiltersUtils.sponsorFilters(text)) {
|
||||
disclamer = "SponsorPost: Заблокировано фильтрами";
|
||||
this.F.setOnClickListener(listener -> AndroidUtils.sendToast("Заблокировано по выражению: " + NewsFeedFiltersUtils.sponsorFiltersBanWord(text)));
|
||||
} else {
|
||||
disclamer = m(R.string.sponsored_post_in_group);
|
||||
}
|
||||
|
||||
height = e0().getDimensionPixelSize(R.dimen.newsfeed_ad_mark_post_height);
|
||||
}
|
||||
} else if (newsEntry instanceof PromoPost) {
|
||||
PromoPost promoPost = (PromoPost) newsEntry;
|
||||
if (!promoPost.E1().isEmpty()) {
|
||||
height = e0().getDimensionPixelSize(R.dimen.newsfeed_ad_mark_promo_post_height);
|
||||
disclamer = promoPost.E1();
|
||||
}
|
||||
}
|
||||
|
||||
this.F.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null);
|
||||
this.F.setMinHeight(height);
|
||||
this.F.setText(disclamer);
|
||||
}
|
||||
|
||||
public static void voteDialog(int ownerId, int postId, int date, Context ctx) {
|
||||
new VkAlertDialog.Builder(ctx)
|
||||
.setTitle("SponsorPost")
|
||||
.setMessage("Этот пост является рекламным?")
|
||||
.setPositiveButton("Да", ((dialog, which) -> {
|
||||
int resp = VotesService.ratePost(ownerId, postId, date, true).optInt("code");
|
||||
|
||||
if (resp == 201 || resp == 100) {
|
||||
AndroidUtils.sendToast("Спасибо за голос!");
|
||||
} else {
|
||||
AndroidUtils.sendToast("Ваш голос уже учтен");
|
||||
}
|
||||
}))
|
||||
.setNeutralButton("Нет", ((dialog, which) -> {
|
||||
int resp = VotesService.ratePost(ownerId, postId, date, false).optInt("code");
|
||||
|
||||
if (resp == 201 || resp == 100) {
|
||||
AndroidUtils.sendToast("Спасибо за голос!");
|
||||
} else {
|
||||
AndroidUtils.sendToast("Ваш голос уже учтен");
|
||||
}
|
||||
}))
|
||||
.show();
|
||||
}
|
||||
}
|
||||
@@ -11,13 +11,12 @@ import com.vk.discover.DiscoverItemDecorator;
|
||||
import ru.vtosters.hooks.other.Preferences;
|
||||
import ru.vtosters.lite.concurrent.VTExecutors;
|
||||
import ru.vtosters.lite.utils.NetworkUtils;
|
||||
import ru.vtosters.sponsorpost.internal.VotesPreferences;
|
||||
import ru.vtosters.sponsorpost.internal.VotesService;
|
||||
import ru.vtosters.sponsorpost.services.PostService;
|
||||
import ru.vtosters.sponsorpost.utils.PostsPreferences;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import static java.lang.Long.MAX_VALUE;
|
||||
import static ru.vtosters.hooks.other.Preferences.*;
|
||||
@@ -102,8 +101,16 @@ public class NewsfeedHook {
|
||||
public static void takeOwnerIdSponsorPost(int ownerid) {
|
||||
if (NetworkUtils.isNetworkConnected() && PostsPreferences.isEnabled() && !Preferences.serverFeaturesDisable()) {
|
||||
VTExecutors.getIoScheduler().a(() -> {
|
||||
List<Long> postIds = PostService.getPostIdsByOwnerId((long) ownerid, 0L);
|
||||
PostsPreferences.saveGroupSpecifiedPosts(postIds, (long) ownerid);
|
||||
if (PostsPreferences.isGroupAd(ownerid) || VotesPreferences.isGroupAd(ownerid)) {
|
||||
if (VotesPreferences.isEnabled()) {
|
||||
Map<String, List<String>> postIds = VotesService.getPostIdsByOwnerId((long) ownerid, 0L);
|
||||
VotesPreferences.saveGroupSpecifiedPosts(postIds.get("vote"), (long) ownerid);
|
||||
PostsPreferences.saveGroupSpecifiedPosts(postIds.get("prod"), (long) ownerid);
|
||||
} else {
|
||||
List<Long> postIds = PostService.getPostIdsByOwnerId((long) ownerid, 0L);
|
||||
PostsPreferences.saveGroupSpecifiedPosts(postIds, (long) ownerid);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -112,17 +119,28 @@ public class NewsfeedHook {
|
||||
long ownerid = Long.parseLong(strArr[0].split("_")[0]);
|
||||
long postId = Long.parseLong(strArr[0].split("_")[1]);
|
||||
|
||||
if (PostsPreferences.isPostAd(ownerid, postId)) {
|
||||
if (PostsPreferences.isPostAd(ownerid, postId) || VotesPreferences.isPostAd(ownerid, postId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (NetworkUtils.isNetworkConnected() && PostsPreferences.isEnabled() && !Preferences.serverFeaturesDisable() && PostsPreferences.isGroupAd(ownerid)) {
|
||||
if (NetworkUtils.isNetworkConnected() && PostsPreferences.isEnabled() && !Preferences.serverFeaturesDisable()) {
|
||||
VTExecutors.getIoScheduler().a(() -> {
|
||||
boolean postIds = PostService.isPostAd(ownerid, postId);
|
||||
if (VotesPreferences.isEnabled()) {
|
||||
boolean postIds = VotesService.isPostAd(ownerid, postId);
|
||||
|
||||
if (postIds) {
|
||||
PostsPreferences.saveAdPostInfo(ownerid, postId);
|
||||
sendToast("Этот пост помечен как рекламный");
|
||||
if (postIds) {
|
||||
VotesPreferences.saveAdPostInfo(ownerid, postId);
|
||||
}
|
||||
} else {
|
||||
boolean postIds = PostService.isPostAd(ownerid, postId);
|
||||
|
||||
if (postIds) {
|
||||
PostsPreferences.saveAdPostInfo(ownerid, postId);
|
||||
|
||||
if (!PostsPreferences.isEnabledMarking()) {
|
||||
sendToast("Этот пост помечен как рекламный");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package ru.vtosters.hooks;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import com.vk.dto.newsfeed.entries.NewsEntry;
|
||||
import com.vk.dto.newsfeed.entries.Post;
|
||||
import com.vk.newsfeed.NewsEntryActionsAdapter;
|
||||
import com.vk.newsfeed.holders.AdMarkHolder;
|
||||
import ru.vtosters.hooks.other.Preferences;
|
||||
import ru.vtosters.lite.utils.AccountManagerUtils;
|
||||
import ru.vtosters.sponsorpost.internal.Native;
|
||||
import ru.vtosters.sponsorpost.utils.PostsPreferences;
|
||||
|
||||
public class PostsMenuHook {
|
||||
private static final int id = 200;
|
||||
|
||||
public static void injectList(NewsEntryActionsAdapter actionsAdapter, NewsEntry newsEntry) {
|
||||
if (newsEntry instanceof Post && Preferences.isValidSignature() && Native.canVote()) {
|
||||
int ownerId = ((Post) newsEntry).b();
|
||||
|
||||
if (ownerId != AccountManagerUtils.getUserId() && PostsPreferences.isEnabled()) {
|
||||
actionsAdapter.a(id, "SponsorPost");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void injectButtons(int i, NewsEntry newsEntry, Context context) {
|
||||
if (newsEntry instanceof Post) {
|
||||
Post post = (Post) newsEntry;
|
||||
int ownerId = post.b();
|
||||
int postId = post.P1();
|
||||
int date = post.K();
|
||||
|
||||
AdMarkHolder.voteDialog(ownerId, postId, date, context);
|
||||
} else {
|
||||
Log.d("PostsMenuHook", "unsupported instance");
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isCustomButton(int i) {
|
||||
return i == id;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ 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;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@@ -13,6 +14,7 @@ import ru.vtosters.hooks.other.Preferences;
|
||||
import ru.vtosters.lite.music.cache.MusicCacheImpl;
|
||||
import ru.vtosters.lite.utils.AccountManagerUtils;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.sponsorpost.utils.GzipDecompressor;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -260,9 +262,10 @@ public class CatalogJsonInjector {
|
||||
+ sectionUrl
|
||||
+ "&access_token="
|
||||
+ AccountManagerUtils.getUserToken())
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.a(Headers.a("User-Agent", Network.l.c().a(), "Content-Type", "application/x-www-form-urlencoded; charset=utf-8")).a();
|
||||
try {
|
||||
var json = new JSONObject(Network.b(CLIENT_API).a(request).execute().a().g()).getJSONObject("response");
|
||||
try (Response resp = Network.b(CLIENT_API).a(request).execute()) {
|
||||
var json = new JSONObject(GzipDecompressor.decompressResponse(resp)).getJSONObject("response");
|
||||
var catalogarr = json.optJSONObject("catalog").optJSONArray("sections").optJSONObject(0);
|
||||
|
||||
var title = catalogarr.optString("title");
|
||||
@@ -276,4 +279,4 @@ public class CatalogJsonInjector {
|
||||
Log.d("VTLMusic", "Error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -311,6 +311,10 @@ public class Preferences {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String getId() {
|
||||
return String.valueOf(AccountManagerUtils.getUserId());
|
||||
}
|
||||
|
||||
public static void updateBuildNumber() {
|
||||
try {
|
||||
getPreferences().edit().putLong("setupTime", AndroidUtils.getGlobalContext().getPackageManager().getPackageInfo(AndroidUtils.getPackageName(), 0).lastUpdateTime).apply();
|
||||
|
||||
@@ -18,6 +18,7 @@ import ru.vtosters.lite.downloaders.messages.items.MiniUser;
|
||||
import ru.vtosters.lite.proxy.ProxyUtils;
|
||||
import ru.vtosters.lite.utils.AccountManagerUtils;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.sponsorpost.utils.GzipDecompressor;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -106,6 +107,7 @@ public class MessagesDownloader {
|
||||
AccountManagerUtils.getUserToken());
|
||||
var req = new Request.a()
|
||||
.b(url)
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.a();
|
||||
Network.b(CLIENT_API).a(req).a(new Callback() {
|
||||
@Override
|
||||
@@ -116,7 +118,7 @@ public class MessagesDownloader {
|
||||
@Override
|
||||
public void a(Call call, Response response) {
|
||||
try {
|
||||
JSONObject obj = new JSONObject(response.a().g()).getJSONObject("response");
|
||||
JSONObject obj = new JSONObject(GzipDecompressor.decompressResponse(response)).getJSONObject("response");
|
||||
|
||||
SparseArray<MiniUser> users = new SparseArray<>();
|
||||
parseUsers(users, obj.optJSONArray("profiles"), false);
|
||||
|
||||
@@ -15,6 +15,7 @@ import ru.vtosters.lite.proxy.ProxyUtils;
|
||||
import ru.vtosters.lite.proxy.api.VikaMobile;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.LifecycleUtils;
|
||||
import ru.vtosters.sponsorpost.utils.GzipDecompressor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
@@ -35,13 +36,14 @@ public class FoafBase {
|
||||
public static JSONObject getBypassedOnlineInfo(int id) throws JSONException {
|
||||
Request request = new Request.a()
|
||||
.b(API_VKNEXT + id)
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.a();
|
||||
|
||||
JSONObject dummy = new JSONObject();
|
||||
dummy.put("last_seen", 0);
|
||||
|
||||
try (Response response = client.a(request).execute()) {
|
||||
JSONObject online_info = new JSONObject(response.a().g()).getJSONObject("response").optJSONObject(Integer.toString(id));
|
||||
JSONObject online_info = new JSONObject(GzipDecompressor.decompressResponse(response)).getJSONObject("response").optJSONObject(Integer.toString(id));
|
||||
return online_info == null ? dummy : online_info;
|
||||
} catch (Exception e) {
|
||||
Log.e("GetBypassedOnlineInfo", e.getMessage());
|
||||
@@ -52,12 +54,13 @@ public class FoafBase {
|
||||
public static JSONObject getBypassedOnlineInfo(String ids) {
|
||||
Request request = new Request.a()
|
||||
.b(API_VKNEXT + ids)
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.a();
|
||||
|
||||
JSONObject dummy = new JSONObject();
|
||||
|
||||
try (Response response = client.a(request).execute()) {
|
||||
JSONObject online_info = new JSONObject(response.a().g()).getJSONObject("response").optJSONObject("response");
|
||||
JSONObject online_info = new JSONObject(GzipDecompressor.decompressResponse(response)).getJSONObject("response").optJSONObject("response");
|
||||
return online_info == null ? dummy : online_info;
|
||||
} catch (Exception e) {
|
||||
Log.e("GetBypassedOnlineInfo1", e.getMessage());
|
||||
|
||||
@@ -11,7 +11,9 @@ import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import ru.vtosters.lite.di.singleton.VtOkHttpClient;
|
||||
import ru.vtosters.lite.music.downloader.M3UDownloader;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.sponsorpost.utils.GzipDecompressor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
@@ -22,10 +24,10 @@ public class Genius {
|
||||
private static final OkHttpClient client = VtOkHttpClient.getInstance();
|
||||
|
||||
public static String getTextMusic(MusicTrack musictrack) {
|
||||
var uid = musictrack.y1();
|
||||
var artist = removeExtras(musictrack.C);
|
||||
var title = removeExtras(musictrack.f);
|
||||
var duration = musictrack.h;
|
||||
String uid = musictrack.y1();
|
||||
String artist = removeExtras(M3UDownloader.getArtists(musictrack));
|
||||
String title = removeExtras(musictrack.f);
|
||||
int duration = musictrack.h;
|
||||
|
||||
if (TextUtils.isEmpty(uid) || TextUtils.isEmpty(artist) || TextUtils.isEmpty(title) || duration == 0) {
|
||||
Log.d("Genius", "grabTrackInfo: " + "Empty track, info: " + artist + " - " + title + " - " + duration + " - " + uid);
|
||||
@@ -42,17 +44,18 @@ public class Genius {
|
||||
}
|
||||
|
||||
Request request = new Request.a()
|
||||
.b(URL + "/search/songs?q=" + URLEncoder.encode(artist + " " + track) + "&from_background=0" + "&page=1")
|
||||
.a("User-Agent", "Genius/5.14.0 (Android; Android 13; Google Pixel 4 XL)")
|
||||
.b(String.format("%s/search/songs?q=%s&from_background=0&page=1", URL, URLEncoder.encode(artist + " " + track)))
|
||||
.a("User-Agent", "Genius/5.21.3 (Android; Android 13; Google Pixel 4 XL)")
|
||||
.a("Authorization", KEY)
|
||||
.a("x-genius-app-background-request", "0")
|
||||
.a("x-genius-logged-out", "true")
|
||||
.a("host", "api.genius.com")
|
||||
.a("Content-Type", "application/x-www-form-urlencoded")
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.b()
|
||||
.a();
|
||||
try (Response resp = client.a(request).execute()) {
|
||||
String payload = resp.a().g();
|
||||
String payload = GzipDecompressor.decompressResponse(resp);
|
||||
JSONArray sections = new JSONObject(payload).getJSONObject("response").getJSONArray("sections");
|
||||
|
||||
for (int i = 0; i < sections.length(); i++) {
|
||||
@@ -86,17 +89,18 @@ public class Genius {
|
||||
|
||||
private static String getText(String track) {
|
||||
Request request = new Request.a()
|
||||
.b(URL + track + "?text_format=plain")
|
||||
.a("User-Agent", "Genius/5.14.0 (Android; Android 13; Google Pixel 4 XL)")
|
||||
.b(String.format("%s%s?text_format=plain", URL, track))
|
||||
.a("User-Agent", "Genius/5.21.3 (Android; Android 13; Google Pixel 4 XL)")
|
||||
.a("Authorization", KEY)
|
||||
.a("x-genius-app-background-request", "0")
|
||||
.a("x-genius-logged-out", "true")
|
||||
.a("host", "api.genius.com")
|
||||
.a("Content-Type", "application/x-www-form-urlencoded")
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.b()
|
||||
.a();
|
||||
try {
|
||||
JSONObject payload = new JSONObject(client.a(request).execute().a().g());
|
||||
try (Response resp = client.a(request).execute()) {
|
||||
JSONObject payload = new JSONObject(GzipDecompressor.decompressResponse(resp));
|
||||
|
||||
if (!payload.has("response")) {
|
||||
return AndroidUtils.getString("error_no_text");
|
||||
@@ -107,4 +111,4 @@ public class Genius {
|
||||
return AndroidUtils.getString("error_no_text") + "\n\n" + AndroidUtils.getString(R.string.error) + ": \n" + e.getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ 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.music.downloader.M3UDownloader;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -32,7 +33,7 @@ public class LastFMScrobbler {
|
||||
|
||||
public static void grabMusicTrack(MusicTrack musictrack) {
|
||||
var uid = musictrack.y1();
|
||||
var artist = musictrack.C;
|
||||
var artist = M3UDownloader.getArtists(musictrack);
|
||||
var title = musictrack.f;
|
||||
var duration = musictrack.h;
|
||||
var track_id = musictrack.d;
|
||||
|
||||
@@ -6,6 +6,7 @@ import bruhcollective.itaysonlab.libvkx.ILibVkxService;
|
||||
import bruhcollective.itaysonlab.libvkx.client.LibVKXClient;
|
||||
import bruhcollective.itaysonlab.libvkx.client.LibVKXClientImpl;
|
||||
import com.vk.dto.music.MusicTrack;
|
||||
import ru.vtosters.lite.music.downloader.M3UDownloader;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.music.MusicCacheStorageUtils;
|
||||
|
||||
@@ -19,7 +20,7 @@ public class MusicCacheImpl {
|
||||
track.I != null ? track.I.getId() + "" : "-1",
|
||||
track.f,
|
||||
!TextUtils.isEmpty(track.g) ? track.g : "",
|
||||
track.C,
|
||||
M3UDownloader.getArtists(track),
|
||||
track.I != null ? track.I.getTitle() : "",
|
||||
track.K,
|
||||
track.h,
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.vk.dto.music.AlbumLink;
|
||||
import com.vk.dto.music.MusicTrack;
|
||||
import com.vk.dto.music.Thumb;
|
||||
import org.json.JSONObject;
|
||||
import ru.vtosters.lite.music.downloader.M3UDownloader;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.music.MusicCacheStorageUtils;
|
||||
|
||||
@@ -116,7 +117,7 @@ public class MusicCacheDb extends SQLiteOpenHelper implements AutoCloseable { //
|
||||
vals.put(Constants.COLUMN_ALBUM_ID, track.I != null ? track.I.getId() + "" : "-1");
|
||||
vals.put(Constants.COLUMN_TITLE, track.f);
|
||||
vals.put(Constants.COLUMN_SUBTITLE, track.g);
|
||||
vals.put(Constants.COLUMN_ARTIST, track.C);
|
||||
vals.put(Constants.COLUMN_ARTIST, M3UDownloader.getArtists(track));
|
||||
vals.put(Constants.COLUMN_ALBUM_TITLE, track.I != null ? track.I.getTitle() : "");
|
||||
vals.put(Constants.COLUMN_EXPLICIT, Boolean.compare(track.K, true));
|
||||
vals.put(Constants.COLUMN_DURATION, track.h);
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import ru.vtosters.lite.music.cache.MusicCacheImpl;
|
||||
import ru.vtosters.lite.music.downloader.M3UDownloader;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.music.MusicCacheStorageUtils;
|
||||
|
||||
@@ -33,7 +34,7 @@ public class PlaylistHelper {
|
||||
return createAlbum(
|
||||
thumb != null ? thumb.h(600) : "",
|
||||
albumLink.getTitle(),
|
||||
track.C,
|
||||
M3UDownloader.getArtists(track),
|
||||
track.y1(),
|
||||
albumLink.getId()
|
||||
);
|
||||
@@ -75,7 +76,7 @@ public class PlaylistHelper {
|
||||
list.add(createAlbum(
|
||||
thumb != null ? thumb.h(600) : "",
|
||||
albumLink.getTitle(),
|
||||
track.C,
|
||||
M3UDownloader.getArtists(track),
|
||||
track.y1(),
|
||||
albumLink.getId()
|
||||
));
|
||||
|
||||
@@ -7,10 +7,12 @@ import com.vk.dto.music.Playlist;
|
||||
import java8.util.concurrent.CompletableFuture;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import ru.vtosters.lite.utils.AccountManagerUtils;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.sponsorpost.utils.GzipDecompressor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -50,17 +52,17 @@ public class PlaylistConverter {
|
||||
|
||||
var request = new Request.a()
|
||||
.b(requestUrl)
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.a(Headers.a("User-Agent", Network.l.c().a(), "Content-Type", "application/x-www-form-urlencoded; charset=utf-8")).a();
|
||||
|
||||
try {
|
||||
var response = CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
return Network.b(CLIENT_API).a(request).execute().a().g();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
).get();
|
||||
try (Response resp = Network.b(CLIENT_API).a(request).execute()) {
|
||||
return GzipDecompressor.decompressResponse(resp);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}).get();
|
||||
var jsonObj = new JSONObject(response);
|
||||
if (!jsonObj.has("response"))
|
||||
return null;
|
||||
|
||||
@@ -7,9 +7,11 @@ import com.vk.dto.music.MusicTrack;
|
||||
import java8.util.concurrent.CompletableFuture;
|
||||
import okhttp3.Headers;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.sponsorpost.utils.GzipDecompressor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -44,12 +46,13 @@ public class AudioGet {
|
||||
|
||||
var request = new Request.a()
|
||||
.b(requestUrl)
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.a(Headers.a("User-Agent", Network.l.c().a(), "Content-Type", "application/x-www-form-urlencoded; charset=utf-8")).a();
|
||||
|
||||
try {
|
||||
var response = CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
return Network.b(CLIENT_API).a(request).execute().a().g();
|
||||
try (Response resp = Network.b(CLIENT_API).a(request).execute()) {
|
||||
return GzipDecompressor.decompressResponse(resp);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.util.Log;
|
||||
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.Artist;
|
||||
import com.vk.dto.music.MusicTrack;
|
||||
import java8.util.concurrent.CompletableFuture;
|
||||
import java8.util.concurrent.CompletionException;
|
||||
@@ -26,6 +27,7 @@ import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class M3UDownloader
|
||||
implements ITrackDownloader {
|
||||
@@ -151,7 +153,7 @@ public class M3UDownloader
|
||||
}
|
||||
|
||||
static File getResultMp3File(File outDir, boolean cache, MusicTrack track) {
|
||||
return new File(outDir, IOUtils.getValidFileName((cache ? "track" : track.C + " - " + getTitle(track)) + ".mp3"));
|
||||
return new File(outDir, IOUtils.getValidFileName((cache ? "track" : getArtists(track) + " - " + getTitle(track)) + ".mp3"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,4 +180,14 @@ public class M3UDownloader
|
||||
private static class Holder {
|
||||
private static final M3UDownloader INSTANCE = new M3UDownloader();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getArtists(MusicTrack track) {
|
||||
return (track.L == null || track.I == null
|
||||
? normalizeMetadata(track.C)
|
||||
: normalizeMetadata(track.L.stream().map(Artist::w1).collect(Collectors.joining(", "))));
|
||||
}
|
||||
|
||||
private static String normalizeMetadata(String in) {
|
||||
return in.replaceAll("[\\\\/:*?\"<>|]", "");
|
||||
}
|
||||
}
|
||||
@@ -105,6 +105,7 @@ public class OtherFragment extends TrackedMaterialPreferenceToolbarFragment {
|
||||
|
||||
findPreference("updateverifdata").setOnPreferenceClickListener(preference -> {
|
||||
UsersList.getUsersList();
|
||||
VTVerifications.isLoaded = false;
|
||||
VTVerifications.load(requireContext());
|
||||
AndroidUtils.sendToast(AndroidUtils.getString("data_updated"));
|
||||
return true;
|
||||
|
||||
@@ -6,8 +6,10 @@ import android.os.Bundle;
|
||||
import ru.vtosters.hooks.other.Preferences;
|
||||
import ru.vtosters.hooks.other.ThemesUtils;
|
||||
import ru.vtosters.lite.ui.PreferenceFragmentUtils;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
import ru.vtosters.lite.utils.NetworkUtils;
|
||||
import ru.vtosters.sponsorpost.data.Filter;
|
||||
import ru.vtosters.sponsorpost.internal.VotesPreferences;
|
||||
import ru.vtosters.sponsorpost.services.FilterService;
|
||||
import ru.vtosters.sponsorpost.utils.FiltersPreferences;
|
||||
import ru.vtosters.sponsorpost.utils.PostsPreferences;
|
||||
@@ -35,6 +37,40 @@ public class SponsorPostFragment extends TrackedMaterialPreferenceToolbarFragmen
|
||||
null
|
||||
);
|
||||
|
||||
PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), "Статистика блокировок");
|
||||
|
||||
PreferenceFragmentUtils.addPreference(
|
||||
getPreferenceScreen(),
|
||||
"",
|
||||
"SponsorPost",
|
||||
"Заблокировано постов: " + PostsPreferences.getNumBlockedPosts(),
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
PreferenceFragmentUtils.addPreference(
|
||||
getPreferenceScreen(),
|
||||
"",
|
||||
"SponsorPost фильтры",
|
||||
"Заблокировано постов: " + FiltersPreferences.getNumBlockedPosts(),
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
PreferenceFragmentUtils.addPreference(
|
||||
getPreferenceScreen(),
|
||||
"",
|
||||
"Сброс статистики",
|
||||
null,
|
||||
null,
|
||||
preference -> {
|
||||
FiltersPreferences.dropNumBlockedPosts();
|
||||
PostsPreferences.dropNumBlockedPosts();
|
||||
AndroidUtils.sendToast("Статистика сброшена");
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
PreferenceFragmentUtils.addPreferenceCategory(getPreferenceScreen(), "Sponsor Post");
|
||||
|
||||
if (Preferences.serverFeaturesDisable()) {
|
||||
@@ -49,9 +85,9 @@ public class SponsorPostFragment extends TrackedMaterialPreferenceToolbarFragmen
|
||||
} else {
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(
|
||||
getPreferenceScreen(),
|
||||
"sponsorpost",
|
||||
"",
|
||||
"Фильтр постов",
|
||||
"Получать списки рекламных постов в группах и ленте, которые не блокируются рекламными фильтрами",
|
||||
"Получать списки рекламных постов в группах и ленте, которые не блокируются рекламными фильтрами\n\nРекомендуется использовать совместно со Стандартным фильтром",
|
||||
null,
|
||||
PostsPreferences.isEnabled(),
|
||||
(preference, o) -> {
|
||||
@@ -59,6 +95,61 @@ public class SponsorPostFragment extends TrackedMaterialPreferenceToolbarFragmen
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(
|
||||
getPreferenceScreen(),
|
||||
"",
|
||||
"Не скрывать посты",
|
||||
"Помечать посты рекламной пометкой, но не скрывать их полностью",
|
||||
null,
|
||||
PostsPreferences.isEnabledMarking(),
|
||||
(preference, o) -> {
|
||||
PostsPreferences.setEnabledMarking((boolean) o);
|
||||
return true;
|
||||
}
|
||||
).setEnabled(PostsPreferences.isEnabled());
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(
|
||||
getPreferenceScreen(),
|
||||
"",
|
||||
"Предварительные списки",
|
||||
"Получать дополнительно более свежие списки которые ещё не попали в основной список. Нужно для активного голосования для блокировки постов. Возможно много ошибок!",
|
||||
null,
|
||||
VotesPreferences.isEnabled(),
|
||||
(preference, o) -> {
|
||||
VotesPreferences.setEnabled((boolean) o);
|
||||
return true;
|
||||
}
|
||||
).setEnabled(PostsPreferences.isEnabled());
|
||||
|
||||
if (NetworkUtils.isNetworkConnected()) {
|
||||
PreferenceFragmentUtils.addPreference(
|
||||
getPreferenceScreen(),
|
||||
"",
|
||||
"Обновить списки постов",
|
||||
null,
|
||||
null,
|
||||
preference -> {
|
||||
this.requireActivity().runOnUiThread(() -> {
|
||||
Updates.updatePosts();
|
||||
AndroidUtils.sendToast("Обновлено");
|
||||
});
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
PreferenceFragmentUtils.addPreference(
|
||||
getPreferenceScreen(),
|
||||
"",
|
||||
"Телеграм чат",
|
||||
"Помогите улучшить качество блокировки постов в нашем телеграм чате\n\nДля перехода в чат вам необходима последняя версия Telegram",
|
||||
null,
|
||||
preference -> {
|
||||
requireContext().startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse("https://t.me/vtosterschat/3559729")));
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
requireActivity().runOnUiThread(() -> {
|
||||
@@ -123,6 +214,31 @@ public class SponsorPostFragment extends TrackedMaterialPreferenceToolbarFragmen
|
||||
);
|
||||
}
|
||||
|
||||
PreferenceFragmentUtils.addMaterialSwitchPreference(
|
||||
getPreferenceScreen(),
|
||||
"",
|
||||
"Не блокировать посты",
|
||||
"Помечать посты заблокированные фильтрами",
|
||||
null,
|
||||
FiltersPreferences.isEnabledMarking(),
|
||||
(preference, o) -> {
|
||||
FiltersPreferences.setEnabledMarking((boolean) o);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
PreferenceFragmentUtils.addPreference(
|
||||
getPreferenceScreen(),
|
||||
"",
|
||||
"Телеграм чат",
|
||||
"Помогите улучшить качество фильтров обсудив работу в нашем телеграм чате\n\nДля перехода в чат вам необходима последняя версия Telegram",
|
||||
null,
|
||||
preference -> {
|
||||
requireContext().startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse("https://t.me/vtosterschat/3559732")));
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
PreferenceFragmentUtils.addPreference(
|
||||
getPreferenceScreen(),
|
||||
"",
|
||||
@@ -139,6 +255,20 @@ public class SponsorPostFragment extends TrackedMaterialPreferenceToolbarFragmen
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (Preferences.dev()) {
|
||||
PreferenceFragmentUtils.addPreference(
|
||||
getPreferenceScreen(),
|
||||
"",
|
||||
"Сбросить токен пользователя",
|
||||
null,
|
||||
null,
|
||||
preference -> {
|
||||
VotesPreferences.remUserToken();
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,7 @@ import okhttp3.*;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import ru.vtosters.lite.di.singleton.VtOkHttpClient;
|
||||
import ru.vtosters.sponsorpost.utils.GzipDecompressor;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -25,6 +26,7 @@ public class OTAUtils {
|
||||
public void loadData(boolean isManualCheck) {
|
||||
Request release = new Request.a()
|
||||
.b(LATEST_RELEASE_URL)
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.a();
|
||||
|
||||
mClient.a(release).a(new Callback() {
|
||||
@@ -46,12 +48,13 @@ public class OTAUtils {
|
||||
});
|
||||
}
|
||||
|
||||
void setData(Response response, boolean isManualCheck) throws IOException, JSONException {
|
||||
mReleaseJson = new JSONObject(response.a().g());
|
||||
void setData(Response response, boolean isManualCheck) throws JSONException, IOException {
|
||||
mReleaseJson = new JSONObject(GzipDecompressor.decompressResponse(response));
|
||||
|
||||
String tag = mReleaseJson.getString("tag_name");
|
||||
Request commit = new Request.a()
|
||||
.b(String.format(LATEST_RELEASE_COMMIT_URL, tag))
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.a();
|
||||
|
||||
mClient.a(commit).a(new Callback() {
|
||||
@@ -62,15 +65,15 @@ public class OTAUtils {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void a(Call call, Response response) throws IOException {
|
||||
public void a(Call call, Response response) {
|
||||
try {
|
||||
mCommitJson = new JSONObject(response.a().g());
|
||||
mCommitJson = new JSONObject(GzipDecompressor.decompressResponse(response));
|
||||
mCommitSHA = mCommitJson.getJSONObject("object").getString("sha");
|
||||
if (isNewVersion())
|
||||
mListener.onUpdateApplied(isManualCheck);
|
||||
else
|
||||
mListener.onUpdateLatest(isManualCheck);
|
||||
} catch (NullPointerException | JSONException e) {
|
||||
} catch (NullPointerException | JSONException | IOException e) {
|
||||
e.printStackTrace();
|
||||
mListener.onUpdateError();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package ru.vtosters.lite.utils;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
import com.vk.core.network.Network;
|
||||
import com.vk.navigation.NavigatorKeys;
|
||||
import okhttp3.*;
|
||||
import org.json.JSONArray;
|
||||
@@ -10,12 +11,11 @@ import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import ru.vtosters.hooks.other.Preferences;
|
||||
import ru.vtosters.lite.di.singleton.VtOkHttpClient;
|
||||
import ru.vtosters.sponsorpost.utils.GzipDecompressor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static ru.vtosters.hooks.other.Preferences.getBoolValue;
|
||||
|
||||
@@ -44,13 +44,14 @@ public class VTVerifications {
|
||||
Request request = new Request.a()
|
||||
.b("https://vtosters.app/vktoaster/getGalo4kiBatch")
|
||||
.a(RequestBody.a(MediaType.b("application/json; charset=UTF-8"), "{\"types\":[0,228,404]}"))
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.a();
|
||||
|
||||
sClient.a(request).a(new Callback() {
|
||||
@Override
|
||||
public void a(Call call, Response response) {
|
||||
try {
|
||||
String payload = response.a().g();
|
||||
String payload = GzipDecompressor.decompressResponse(response);
|
||||
parseJson(payload);
|
||||
prefs.edit()
|
||||
.putString("ids", payload)
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import ru.vtosters.lite.utils.AccountManagerUtils;
|
||||
import ru.vtosters.sponsorpost.internal.VotesPreferences;
|
||||
import ru.vtosters.sponsorpost.utils.FiltersPreferences;
|
||||
import ru.vtosters.sponsorpost.utils.PostsPreferences;
|
||||
|
||||
@@ -185,7 +186,7 @@ public class NewsFeedFiltersUtils {
|
||||
return json;
|
||||
}
|
||||
|
||||
private static boolean needToSave(JSONObject post, String source, boolean needToShowToast) throws JSONException {
|
||||
private static boolean needToSave(JSONObject post, String source, boolean needToNotifyBlock) throws JSONException {
|
||||
String type = post.optString("type");
|
||||
|
||||
if (isAds(post, type)) {
|
||||
@@ -198,58 +199,84 @@ public class NewsFeedFiltersUtils {
|
||||
|| type.endsWith("playlists")
|
||||
|| type.endsWith("groups")))) {
|
||||
|
||||
logRemovedPost(post, source, "authors", needToShowToast);
|
||||
logRemovedPost(post, source, "authors", needToNotifyBlock);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (postsrecomm() && (type.equals("inline_user_rec") || type.equals("live_recommended"))) {
|
||||
logRemovedPost(post, source, "postsrecomm", needToShowToast);
|
||||
logRemovedPost(post, source, "postsrecomm", needToNotifyBlock);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (friendsrecomm() && (type.equals("user_rec") || type.equals("friends_recomm"))) {
|
||||
logRemovedPost(post, source, "friendsrecomm", needToShowToast);
|
||||
logRemovedPost(post, source, "friendsrecomm", needToNotifyBlock);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (adsgroup() && post.optInt("marked_as_ads") == 1 && !isWhitelistedAd(post)) {
|
||||
logRemovedPost(post, source, "marked_as_ads", needToShowToast);
|
||||
return false;
|
||||
if (adsgroup() && post.optInt("marked_as_ads") == 1 && !post.optBoolean("sponsorpost") && !isWhitelistedAd(post)) {
|
||||
logRemovedPost(post, source, "marked_as_ads", needToNotifyBlock);
|
||||
return needToNotifyBlock;
|
||||
}
|
||||
|
||||
if (PostsPreferences.isPostAd(getOwnerId(post), getPostId(post)) && !isWhitelistedAd(post)) {
|
||||
logRemovedPost(post, source, "sponsorpost", needToShowToast);
|
||||
return false;
|
||||
if (PostsPreferences.isPostAd(getOwnerId(post), getPostId(post)) && !post.optBoolean("sponsorpost") && !isWhitelistedAd(post)) {
|
||||
logRemovedPost(post, source, "sponsorpost", needToNotifyBlock);
|
||||
PostsPreferences.incrementNumBlockedPosts();
|
||||
|
||||
if (PostsPreferences.isEnabledMarking() || needToNotifyBlock) {
|
||||
addSponsorPostMark(post);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (sponsorFilters(post.optString("text")) && !isWhitelistedFilters(post)) {
|
||||
logRemovedPost(post, source, "sponsorpost filter", needToShowToast);
|
||||
return false;
|
||||
if (VotesPreferences.isPostAd(getOwnerId(post), getPostId(post)) && !post.optBoolean("sponsorpost") && !isWhitelistedAd(post)) {
|
||||
logRemovedPost(post, source, "sponsorpost vote base", needToNotifyBlock);
|
||||
addSponsorPostMark(post);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sponsorFilters(post.optString("text")) && !post.optBoolean("sponsorpost") && !isWhitelistedFilters(post)) {
|
||||
logRemovedPost(post, source, "sponsorpost filter", needToNotifyBlock);
|
||||
FiltersPreferences.incrementNumBlockedPosts();
|
||||
|
||||
if (FiltersPreferences.isEnabledMarking() || needToNotifyBlock) {
|
||||
addSponsorPostMark(post);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkCopyright(post)) {
|
||||
logRemovedPost(post, source, "copyright filters", needToShowToast);
|
||||
return false;
|
||||
logRemovedPost(post, source, "copyright filters", needToNotifyBlock);
|
||||
FiltersPreferences.incrementNumBlockedPosts();
|
||||
return needToNotifyBlock;
|
||||
}
|
||||
|
||||
if (checkCaption(post)) {
|
||||
logRemovedPost(post, source, "caption filters", needToShowToast);
|
||||
return false;
|
||||
logRemovedPost(post, source, "caption filters", needToNotifyBlock);
|
||||
return needToNotifyBlock;
|
||||
}
|
||||
|
||||
if (hasMiniAppAds(post) && !isWhitelistedFilters(post)) {
|
||||
logRemovedPost(post, source, "miniapps ban", needToShowToast);
|
||||
return false;
|
||||
logRemovedPost(post, source, "miniapps ban", needToNotifyBlock);
|
||||
return needToNotifyBlock;
|
||||
}
|
||||
|
||||
if (NewsFeedFiltersUtils.injectFiltersReposts(post) && !isWhitelistedFilters(post)) {
|
||||
logRemovedPost(post, source, "repost ad", needToShowToast);
|
||||
return false;
|
||||
logRemovedPost(post, source, "repost ad", needToNotifyBlock);
|
||||
return needToNotifyBlock;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void addSponsorPostMark(JSONObject post) throws JSONException {
|
||||
post.putOpt("marked_as_ads", 1);
|
||||
post.putOpt("sponsorpost", true);
|
||||
}
|
||||
|
||||
public static JSONArray feedInject(JSONArray items, boolean needToShowToast) {
|
||||
if (items.length() == 0) return items;
|
||||
|
||||
@@ -276,24 +303,26 @@ public class NewsFeedFiltersUtils {
|
||||
|
||||
public static boolean sponsorFilters(String text) {
|
||||
String textInLowerCase = text.toLowerCase();
|
||||
Set<String> list = filters.stream()
|
||||
.filter(adword -> !adword.isEmpty())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (!list.isEmpty()) {
|
||||
return list.stream().anyMatch(adword -> {
|
||||
if (textInLowerCase.contains(adword.toLowerCase())) {
|
||||
return filters.stream()
|
||||
.map(String::toLowerCase)
|
||||
.filter(adword -> !adword.isEmpty() && textInLowerCase.contains(adword))
|
||||
.peek(adword -> {
|
||||
if (dev()) {
|
||||
Log.d("NewsfeedAdBlockV2", text);
|
||||
Log.d("NewsfeedAdBlockV2", "Block word: " + adword);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
})
|
||||
.findAny()
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
return false;
|
||||
public static String sponsorFiltersBanWord(String text) {
|
||||
String textInLowerCase = text.toLowerCase();
|
||||
return filters.stream()
|
||||
.map(String::toLowerCase)
|
||||
.filter(adword -> !adword.isEmpty() && textInLowerCase.contains(adword))
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package ru.vtosters.sponsorpost.internal;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class Native {
|
||||
public static boolean canVote;
|
||||
|
||||
public static boolean canVote() {
|
||||
return canVote;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static native String sig();
|
||||
|
||||
@Nullable
|
||||
public static native String time();
|
||||
|
||||
@Nullable
|
||||
public static native String pkey();
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package ru.vtosters.sponsorpost.internal;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.util.Log;
|
||||
import ru.vtosters.lite.utils.AndroidUtils;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class VotesPreferences {
|
||||
private static final SharedPreferences preferences;
|
||||
|
||||
static {
|
||||
preferences = getPreferences();
|
||||
}
|
||||
|
||||
private static SharedPreferences getPreferences() {
|
||||
return AndroidUtils.getGlobalContext().getSharedPreferences("ru.vtosters.sponsorpost.votes.prefs", Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
public static boolean isEnabled() {
|
||||
return preferences.getBoolean("sponsortesting", false);
|
||||
}
|
||||
|
||||
public static void setEnabled(boolean status) {
|
||||
preferences.edit().putBoolean("sponsortesting", status).apply();
|
||||
}
|
||||
|
||||
public static void setUserToken(String token) {
|
||||
preferences.edit()
|
||||
.putString("token", token)
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static void remUserToken() {
|
||||
preferences.edit()
|
||||
.remove("token")
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static String getUserToken() {
|
||||
return preferences.getString("token", "");
|
||||
}
|
||||
|
||||
public static void savePosts(List<String> posts) {
|
||||
preferences.edit()
|
||||
.putStringSet("posts", new HashSet<>(posts))
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static void saveGroupsIds(List<String> ids) {
|
||||
preferences.edit()
|
||||
.putStringSet("groupIds", new HashSet<>(ids))
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static void saveGroupSpecifiedPosts(List<String> postsIds, Long ownerId) {
|
||||
Set<String> stringSet = postsIds.stream()
|
||||
.map(post -> ownerId + "_" + post)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
preferences.edit()
|
||||
.putStringSet(ownerId + "_posts", stringSet)
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static void saveAdPostInfo(long ownerId, long postId) {
|
||||
Set<String> currentStringSet = preferences.getStringSet("posts", new HashSet<>());
|
||||
Set<String> newStringSet = new HashSet<>(currentStringSet);
|
||||
|
||||
newStringSet.add(ownerId + "_" + postId);
|
||||
|
||||
Log.d("SponsorPost", ownerId + "_" + postId);
|
||||
|
||||
preferences.edit()
|
||||
.putStringSet("posts", newStringSet)
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static boolean isGroupAd(long ownerId) {
|
||||
Set<String> isGroupAd = preferences.getStringSet("groupIds", new HashSet<>());
|
||||
|
||||
if (!isGroupAd.isEmpty() && isEnabled()) {
|
||||
return isGroupAd.contains(Long.toString(ownerId));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPostAd(long ownerId, long postId) {
|
||||
if (isEnabled() && isGroupAd(ownerId)) {
|
||||
Set<String> hasSpecifiedGroupPosts = preferences.getStringSet(ownerId + "_posts", new HashSet<>());
|
||||
Set<String> hasPost = preferences.getStringSet("posts", new HashSet<>());
|
||||
|
||||
return hasPost.contains(ownerId + "_" + postId) || hasSpecifiedGroupPosts.contains(ownerId + "_" + postId);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package ru.vtosters.sponsorpost.internal;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import ru.vtosters.sponsorpost.utils.ApiUtils;
|
||||
import ru.vtosters.sponsorpost.utils.GzipDecompressor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class VotesService {
|
||||
private static final OkHttpClient client = new OkHttpClient();
|
||||
private static final String apiPath = ApiUtils.getURL() + "/votes";
|
||||
private static final String userPath = ApiUtils.getURL() + "/users";
|
||||
|
||||
public static Map<String, List<String>> getPosts(Long date) {
|
||||
String getFromDate = date > 0 ? ("&date=" + date) : "";
|
||||
Request request = new Request.a()
|
||||
.b(apiPath + "/getAllPostIds" + "?needProd=true" + getFromDate)
|
||||
.a("Content-Type", "application/json")
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.a();
|
||||
try (Response response = client.a(request).execute()) {
|
||||
if (response.h()) {
|
||||
return parseJSON(new JSONObject(GzipDecompressor.decompressResponse(response)));
|
||||
} else {
|
||||
throw new RuntimeException("Failed to get posts: " + response.l());
|
||||
}
|
||||
} catch (IOException | JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, List<String>> parseJSON(JSONObject object) throws JSONException {
|
||||
String PROD_KEY = "prod";
|
||||
String VOTE_KEY = "vote";
|
||||
|
||||
JSONArray prodBase = object.getJSONArray(PROD_KEY);
|
||||
JSONArray testBase = object.getJSONArray(VOTE_KEY);
|
||||
|
||||
if (prodBase.length() == 0 && testBase.length() == 0) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
List<String> prodList = IntStream.range(0, prodBase.length())
|
||||
.mapToObj(prodBase::optString)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<String> voteList = IntStream.range(0, testBase.length())
|
||||
.mapToObj(testBase::optString)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return Map.of(PROD_KEY, prodList, VOTE_KEY, voteList);
|
||||
}
|
||||
|
||||
public static Map<String, List<String>> getPostIdsByOwnerId(Long ownerId, Long date) {
|
||||
String getFromDate = date > 0 ? ("&date=" + date) : "";
|
||||
String requestUrl = apiPath + "/getPostIdsByOwnerId" + "?ownerId=" + ownerId + getFromDate + "&needProd=true";
|
||||
Request request = new Request.a()
|
||||
.b(requestUrl)
|
||||
.a("Content-Type", "application/json")
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.a();
|
||||
try (Response response = client.a(request).execute()) {
|
||||
if (response.h()) {
|
||||
return parseJSON(new JSONObject(GzipDecompressor.decompressResponse(response)));
|
||||
} else {
|
||||
throw new RuntimeException("Failed to get postIdsByOwnerId: " + response.l());
|
||||
}
|
||||
} catch (IOException | JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, List<String>> getOwnerIds() {
|
||||
String requestUrl = apiPath + "/getOwnerIds" + "?needProd=true";
|
||||
Request request = new Request.a()
|
||||
.b(requestUrl)
|
||||
.a("Content-Type", "application/json")
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.a();
|
||||
try (Response response = client.a(request).execute()) {
|
||||
if (response.h()) {
|
||||
return parseJSON(new JSONObject(GzipDecompressor.decompressResponse(response)));
|
||||
} else {
|
||||
throw new RuntimeException("Failed to get ownersIds: " + response.l());
|
||||
}
|
||||
} catch (IOException | JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static JSONObject ratePost(int ownerId, int postId, int date, boolean isAd) {
|
||||
String token = VotesPreferences.getUserToken() == null || VotesPreferences.getUserToken().isEmpty() ? getVoteToken() : VotesPreferences.getUserToken();
|
||||
String requestUrl = apiPath + (isAd ? "/dislike" : "/like") + "?ownerId=" + ownerId + "&postId=" + postId+ "&postDate=" + date + "&token=" + Uri.encode(token);
|
||||
Request request = new Request.a()
|
||||
.b(requestUrl)
|
||||
.a("Content-Type", "application/json")
|
||||
.a();
|
||||
try (Response response = client.a(request).execute()) {
|
||||
return new JSONObject(GzipDecompressor.decompressResponse(response));
|
||||
} catch (IOException | JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getVoteToken() {
|
||||
String requestUrl = userPath + "/getUserToken" + "?private_key=" + Uri.encode(Native.pkey());
|
||||
Request request = new Request.a()
|
||||
.b(requestUrl)
|
||||
.a("Content-Type", "application/json")
|
||||
.a("Timestamp", Native.time())
|
||||
.a("Signature", Native.sig())
|
||||
.a();
|
||||
try (Response response = client.a(request).execute()) {
|
||||
String userToken = new JSONObject(GzipDecompressor.decompressResponse(response)).getString("token");
|
||||
VotesPreferences.setUserToken(userToken);
|
||||
return userToken;
|
||||
} catch (IOException | JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPostAd(long ownerId, long postId) {
|
||||
String requestUrl = apiPath + "/isPostAdvert?post=" + ownerId + "_" + postId + "&needProd=true";
|
||||
Request request = new Request.a()
|
||||
.b(requestUrl)
|
||||
.a("Content-Type", "application/json")
|
||||
.a();
|
||||
try (Response response = client.a(request).execute()) {
|
||||
if (response.h()) {
|
||||
return Boolean.parseBoolean(GzipDecompressor.decompressResponse(response));
|
||||
} else {
|
||||
throw new RuntimeException("Failed to check post for ad status: " + response.l());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,20 +42,7 @@ public class FilterService {
|
||||
try (Response response = client.a(request).execute()) {
|
||||
// Check if the response is successful
|
||||
if (response.h()) {
|
||||
// Determine the response encoding
|
||||
String encoding = response.a("Content-Encoding");
|
||||
String resp;
|
||||
|
||||
if (encoding != null && encoding.equals("gzip")) {
|
||||
// Decompress the response body
|
||||
resp = GzipDecompressor.decompress(response.a().b());
|
||||
} else {
|
||||
// Retrieve the response body directly
|
||||
resp = response.a().g();
|
||||
}
|
||||
|
||||
// Parse the response body as a JSONArray and extract filter objects
|
||||
return parseJSON(new JSONArray(resp));
|
||||
return parseJSON(new JSONArray(GzipDecompressor.decompressResponse(response)));
|
||||
} else {
|
||||
if (!FiltersPreferences.getAllFilterIds().isEmpty()) {
|
||||
return FiltersPreferences.getAllDownloadedFilters(); // check for offline server to get local filters
|
||||
@@ -75,11 +62,12 @@ public class FilterService {
|
||||
public static Set<String> downloadFilter(String link) {
|
||||
Request request = new Request.a()
|
||||
.b(link)
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.a();
|
||||
|
||||
try (Response response = client.a(request).execute()) {
|
||||
if (response.h()) {
|
||||
return stringToSet(response.a().g());
|
||||
return stringToSet(GzipDecompressor.decompressResponse(response));
|
||||
} else {
|
||||
throw new RuntimeException("Failed to download filter: " + response.l());
|
||||
}
|
||||
|
||||
@@ -39,17 +39,7 @@ public class PostService {
|
||||
try (Response response = client.a(request).execute()) {
|
||||
// Check if the response is successful
|
||||
if (response.h()) {
|
||||
// Determine the response encoding
|
||||
String encoding = response.a("Content-Encoding");
|
||||
|
||||
// Handle GZIP-compressed responses
|
||||
if (encoding != null && encoding.equals("gzip")) {
|
||||
// Decompress the response body and parse JSON data
|
||||
return parseJSONPosts(new JSONArray(GzipDecompressor.decompress(response.a().b())));
|
||||
} else {
|
||||
// Parse JSON data from the response body
|
||||
return parseJSONPosts(new JSONArray(response.a().g()));
|
||||
}
|
||||
return parseJSONPosts(new JSONArray(GzipDecompressor.decompressResponse(response)));
|
||||
} else {
|
||||
// Handle error response
|
||||
throw new RuntimeException("Failed to get posts: " + response.l());
|
||||
@@ -78,20 +68,7 @@ public class PostService {
|
||||
try (Response response = client.a(request).execute()) {
|
||||
// Check if the response is successful
|
||||
if (response.h()) {
|
||||
// Determine the response encoding
|
||||
String encoding = response.a("Content-Encoding");
|
||||
String resp;
|
||||
|
||||
if (encoding != null && encoding.equals("gzip")) {
|
||||
// Decompress the response body
|
||||
resp = GzipDecompressor.decompress(response.a().b());
|
||||
} else {
|
||||
// Retrieve the response body directly
|
||||
resp = response.a().g();
|
||||
}
|
||||
|
||||
// Extract the boolean value indicating whether the post is an ad
|
||||
return Boolean.parseBoolean(resp);
|
||||
return Boolean.parseBoolean(GzipDecompressor.decompressResponse(response));
|
||||
} else {
|
||||
// Handle error response
|
||||
throw new RuntimeException("Failed to check post for ad status: " + response.l());
|
||||
@@ -101,10 +78,19 @@ public class PostService {
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getAllPostsIds() {
|
||||
public static List<String> getAllPostsIds(Long date) {
|
||||
String getFromDate;
|
||||
// Get posts older than the specified date (if positive) or all posts (if zero or negative or empty)
|
||||
if (date > 0) {
|
||||
getFromDate = ("?date=" + date);
|
||||
} else {
|
||||
// No date parameter for retrieving all posts
|
||||
getFromDate = "";
|
||||
}
|
||||
|
||||
// Create a GET request for retrieving all post IDs
|
||||
Request request = new Request.a()
|
||||
.b(apiPath + "/getAllPostIds")
|
||||
.b(apiPath + "/getAllPostIds" + getFromDate)
|
||||
.a("Content-Type", "application/json")
|
||||
.a("Accept-Encoding", "gzip")
|
||||
.a();
|
||||
@@ -112,17 +98,7 @@ public class PostService {
|
||||
try (Response response = client.a(request).execute()) {
|
||||
// Check if the response is successful
|
||||
if (response.h()) {
|
||||
// Determine the response encoding
|
||||
String encoding = response.a("Content-Encoding");
|
||||
|
||||
// Handle GZIP-compressed responses
|
||||
if (encoding != null && encoding.equals("gzip")) {
|
||||
// Decompress the response body and extract the first element as a list of post IDs
|
||||
return new ArrayList<>(Collections.singleton(GzipDecompressor.decompress(response.a().b())));
|
||||
} else {
|
||||
// Extract the first element as a list of post IDs
|
||||
return new ArrayList<>(Collections.singleton(response.a().g()));
|
||||
}
|
||||
return new ArrayList<>(Collections.singleton(GzipDecompressor.decompressResponse(response)));
|
||||
} else {
|
||||
// Handle error response
|
||||
throw new RuntimeException("Failed to get posts IDs: " + response.l());
|
||||
@@ -137,7 +113,7 @@ public class PostService {
|
||||
// Retrieve post IDs for a specific owner and date
|
||||
// If date is positive, get posts older than the specified date
|
||||
// Otherwise, get all posts for the owner
|
||||
String getFromDate = date > 0 ? ("?date=" + date) : "";
|
||||
String getFromDate = date > 0 ? ("&date=" + date) : "";
|
||||
|
||||
// Construct the API request URL
|
||||
String requestUrl = apiPath + "/getPostIdsByOwnerId" + "?ownerId=" + ownerId + getFromDate;
|
||||
@@ -152,20 +128,7 @@ public class PostService {
|
||||
try (Response response = client.a(request).execute()) {
|
||||
// Check if the response is successful
|
||||
if (response.h()) {
|
||||
// Determine the response encoding
|
||||
String encoding = response.a("Content-Encoding");
|
||||
String resp;
|
||||
|
||||
if (encoding != null && encoding.equals("gzip")) {
|
||||
// Decompress the response body
|
||||
resp = GzipDecompressor.decompress(response.a().b());
|
||||
} else {
|
||||
// Retrieve the response body directly
|
||||
resp = response.a().g();
|
||||
}
|
||||
|
||||
// Parse the response body as a JSONArray and extract post IDs
|
||||
return parseJSONIds(new JSONArray(resp));
|
||||
return parseJSONIds(new JSONArray(GzipDecompressor.decompressResponse(response)));
|
||||
} else {
|
||||
// Handle error response
|
||||
throw new RuntimeException("Failed to get postIdsByOwnerId: " + response.l());
|
||||
@@ -192,20 +155,7 @@ public class PostService {
|
||||
try (Response response = client.a(request).execute()) {
|
||||
// Check if the response is successful
|
||||
if (response.h()) {
|
||||
// Determine the response encoding
|
||||
String encoding = response.a("Content-Encoding");
|
||||
String resp;
|
||||
|
||||
if (encoding != null && encoding.equals("gzip")) {
|
||||
// Decompress the response body
|
||||
resp = GzipDecompressor.decompress(response.a().b());
|
||||
} else {
|
||||
// Retrieve the response body directly
|
||||
resp = response.a().g();
|
||||
}
|
||||
|
||||
// Parse the response body as a JSONArray and extract owner IDs
|
||||
return parseJSONIds(new JSONArray(resp));
|
||||
return parseJSONIds(new JSONArray(GzipDecompressor.decompressResponse(response)));
|
||||
} else {
|
||||
// Handle error response
|
||||
throw new RuntimeException("Failed to get ownersIds: " + response.l());
|
||||
|
||||
@@ -31,6 +31,26 @@ public class FiltersPreferences {
|
||||
return AndroidUtils.getGlobalContext().getSharedPreferences("ru.vtosters.sponsorpost.filters.prefs", Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
public static boolean isEnabledMarking() {
|
||||
return preferences.getBoolean("sponsorpost_filters_marking", false);
|
||||
}
|
||||
|
||||
public static void setEnabledMarking(boolean status) {
|
||||
preferences.edit().putBoolean("sponsorpost_filters_marking", status).apply();
|
||||
}
|
||||
|
||||
public static int getNumBlockedPosts() {
|
||||
return preferences.getInt("numBlockedPosts", 0);
|
||||
}
|
||||
|
||||
public static void incrementNumBlockedPosts() {
|
||||
preferences.edit().putInt("numBlockedPosts", getNumBlockedPosts() + 1).apply();
|
||||
}
|
||||
|
||||
public static void dropNumBlockedPosts() {
|
||||
preferences.edit().putInt("numBlockedPosts", 0).apply();
|
||||
}
|
||||
|
||||
public static void clearAllCachedLists() {
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package ru.vtosters.sponsorpost.utils;
|
||||
|
||||
import android.util.Log;
|
||||
import okhttp3.Response;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -26,4 +29,17 @@ public class GzipDecompressor {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String decompressResponse(Response response) throws IOException {
|
||||
String encoding = response.a("Content-Encoding");
|
||||
if (encoding != null && encoding.equals("gzip")) {
|
||||
// Decompress the response body
|
||||
Log.d("GZIP", "true, link " + response.o().g());
|
||||
return GzipDecompressor.decompress(response.a().b());
|
||||
} else {
|
||||
// Retrieve the response body directly
|
||||
Log.d("GZIP", "false, link " + response.o().g());
|
||||
return response.a().g();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,14 @@ public class PostsPreferences {
|
||||
preferences.edit().putBoolean("sponsorpost", status).apply();
|
||||
}
|
||||
|
||||
public static boolean isEnabledMarking() {
|
||||
return preferences.getBoolean("sponsorpost_marking", false);
|
||||
}
|
||||
|
||||
public static void setEnabledMarking(boolean status) {
|
||||
preferences.edit().putBoolean("sponsorpost_marking", status).apply();
|
||||
}
|
||||
|
||||
public static void savePosts(List<Post> posts) {
|
||||
Set<String> stringSet = posts.stream()
|
||||
.map(post -> post.getOwnerId() + "_" + post.getPostId())
|
||||
@@ -40,7 +48,13 @@ public class PostsPreferences {
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static void saveGroupSpecifiedPosts(List<Long> postsIds, Long ownerId) {
|
||||
public static void savePostsStr(List<String> posts) {
|
||||
preferences.edit()
|
||||
.putStringSet("posts", new HashSet<>(posts))
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static void saveGroupSpecifiedPosts(List<?> postsIds, Long ownerId) {
|
||||
Set<String> stringSet = postsIds.stream()
|
||||
.map(post -> ownerId + "_" + post)
|
||||
.collect(Collectors.toSet());
|
||||
@@ -50,7 +64,7 @@ public class PostsPreferences {
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static void saveGroupsIds(List<Long> ids) {
|
||||
public static void saveGroupsIds(List<?> ids) {
|
||||
Set<String> stringSet = ids.stream().map(String::valueOf).collect(Collectors.toSet());
|
||||
|
||||
preferences.edit()
|
||||
@@ -81,6 +95,18 @@ public class PostsPreferences {
|
||||
}
|
||||
}
|
||||
|
||||
public static int getNumBlockedPosts() {
|
||||
return preferences.getInt("numBlockedPosts", 0);
|
||||
}
|
||||
|
||||
public static void incrementNumBlockedPosts() {
|
||||
preferences.edit().putInt("numBlockedPosts", getNumBlockedPosts() + 1).apply();
|
||||
}
|
||||
|
||||
public static void dropNumBlockedPosts() {
|
||||
preferences.edit().putInt("numBlockedPosts", 0).apply();
|
||||
}
|
||||
|
||||
public static boolean isPostAd(long ownerId, long postId) {
|
||||
if (isEnabled() && isGroupAd(ownerId)) {
|
||||
Set<String> hasSpecifiedGroupPosts = preferences.getStringSet(ownerId + "_posts", new HashSet<>());
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
package ru.vtosters.sponsorpost.utils;
|
||||
|
||||
import ru.vtosters.hooks.other.Preferences;
|
||||
import ru.vtosters.lite.utils.NetworkUtils;
|
||||
import ru.vtosters.lite.utils.newsfeed.NewsFeedFiltersUtils;
|
||||
import ru.vtosters.sponsorpost.data.Filter;
|
||||
import ru.vtosters.sponsorpost.data.Post;
|
||||
import ru.vtosters.sponsorpost.internal.VotesPreferences;
|
||||
import ru.vtosters.sponsorpost.internal.VotesService;
|
||||
import ru.vtosters.sponsorpost.services.FilterService;
|
||||
import ru.vtosters.sponsorpost.services.PostService;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -59,16 +61,31 @@ public class Updates {
|
||||
long weekAgo = currentTime - TimeUnit.DAYS.toMillis(7);
|
||||
|
||||
if (PostsPreferences.isEnabled() && NetworkUtils.isNetworkConnected()) {
|
||||
List<Post> posts = PostService.getPosts(weekAgo);
|
||||
List<Long> groupIds = PostService.getOwnerIds();
|
||||
if (VotesPreferences.isEnabled()) {
|
||||
Map<String, List<String>> posts = VotesService.getPosts(weekAgo / 1000);
|
||||
Map<String, List<String>> groupIds = VotesService.getOwnerIds();
|
||||
|
||||
if (!posts.isEmpty()) {
|
||||
PostsPreferences.savePosts(posts);
|
||||
}
|
||||
if (!posts.isEmpty()) {
|
||||
PostsPreferences.savePostsStr(posts.get("prod"));
|
||||
VotesPreferences.savePosts(posts.get("vote"));
|
||||
}
|
||||
|
||||
if (!groupIds.isEmpty()) {
|
||||
PostsPreferences.saveGroupsIds(groupIds);
|
||||
if (!groupIds.isEmpty()) {
|
||||
PostsPreferences.saveGroupsIds(groupIds.get("prod"));
|
||||
VotesPreferences.saveGroupsIds(groupIds.get("vote"));
|
||||
}
|
||||
} else {
|
||||
List<String> posts = PostService.getAllPostsIds(weekAgo / 1000);
|
||||
List<Long> groupIds = PostService.getOwnerIds();
|
||||
|
||||
if (!posts.isEmpty()) {
|
||||
PostsPreferences.savePostsStr(posts);
|
||||
}
|
||||
|
||||
if (!groupIds.isEmpty()) {
|
||||
PostsPreferences.saveGroupsIds(groupIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -891,6 +891,17 @@
|
||||
|
||||
if-eqz v0, :cond_a
|
||||
|
||||
invoke-static {p1}, Lru/vtosters/hooks/PostsMenuHook;->isCustomButton(I)Z
|
||||
|
||||
move-result v2
|
||||
|
||||
if-eqz v2, :cond_99
|
||||
|
||||
invoke-static {p1, p2, v0}, Lru/vtosters/hooks/PostsMenuHook;->injectButtons(ILcom/vk/dto/newsfeed/entries/NewsEntry;Landroid/content/Context;)V
|
||||
|
||||
return-void
|
||||
|
||||
:cond_99
|
||||
invoke-static {v0}, Lcom/vk/core/util/ContextExtKt;->e(Landroid/content/Context;)Landroid/app/Activity;
|
||||
|
||||
move-result-object v2
|
||||
|
||||
@@ -1536,6 +1536,10 @@
|
||||
invoke-virtual {v0, v1, v2}, Lcom/vk/newsfeed/NewsEntryActionsAdapter;->a(ILjava/lang/CharSequence;)V
|
||||
|
||||
:cond_26
|
||||
iget-object v1, p0, Lcom/vk/newsfeed/NewsEntryActionsMenuBuilder;->e:Lcom/vk/dto/newsfeed/entries/NewsEntry;
|
||||
|
||||
invoke-static {v0, v1}, Lru/vtosters/hooks/PostsMenuHook;->injectList(Lcom/vk/newsfeed/NewsEntryActionsAdapter;Lcom/vk/dto/newsfeed/entries/NewsEntry;)V
|
||||
|
||||
return-object p1
|
||||
.end method
|
||||
|
||||
|
||||
@@ -1367,6 +1367,10 @@
|
||||
invoke-virtual {v1, v2, v3, v4}, Lcom/vk/newsfeed/NewsEntryActionsAdapter;->b(III)V
|
||||
|
||||
:cond_35
|
||||
iget-object v2, v0, Lcom/vk/newsfeed/PostViewActionsMenuBuilder;->b:Lcom/vk/dto/newsfeed/entries/NewsEntry;
|
||||
|
||||
invoke-static {v1, v2}, Lru/vtosters/hooks/PostsMenuHook;->injectList(Lcom/vk/newsfeed/NewsEntryActionsAdapter;Lcom/vk/dto/newsfeed/entries/NewsEntry;)V
|
||||
|
||||
return-object v17
|
||||
.end method
|
||||
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
.class public final Lcom/vk/newsfeed/holders/AdMarkHolder;
|
||||
.super Lcom/vk/newsfeed/holders/BaseNewsEntryHolder;
|
||||
.source "AdMarkHolder.kt"
|
||||
|
||||
|
||||
# annotations
|
||||
.annotation system Ldalvik/annotation/Signature;
|
||||
value = {
|
||||
"Lcom/vk/newsfeed/holders/BaseNewsEntryHolder<",
|
||||
"Lcom/vk/dto/newsfeed/entries/NewsEntry;",
|
||||
">;"
|
||||
}
|
||||
.end annotation
|
||||
|
||||
|
||||
# instance fields
|
||||
.field private final F:Landroid/widget/TextView;
|
||||
|
||||
|
||||
# direct methods
|
||||
.method public constructor <init>(Landroid/view/ViewGroup;)V
|
||||
.locals 3
|
||||
|
||||
const v0, 0x7f0d0307
|
||||
|
||||
.line 1
|
||||
invoke-direct {p0, v0, p1}, Lcom/vk/newsfeed/holders/BaseNewsEntryHolder;-><init>(ILandroid/view/ViewGroup;)V
|
||||
|
||||
.line 2
|
||||
iget-object p1, p0, Landroidx/recyclerview/widget/RecyclerView$ViewHolder;->itemView:Landroid/view/View;
|
||||
|
||||
const-string v0, "itemView"
|
||||
|
||||
invoke-static {p1, v0}, Lkotlin/jvm/internal/Intrinsics;->a(Ljava/lang/Object;Ljava/lang/String;)V
|
||||
|
||||
const/4 v0, 0x0
|
||||
|
||||
const v1, 0x7f0a0d4e
|
||||
|
||||
const/4 v2, 0x2
|
||||
|
||||
invoke-static {p1, v1, v0, v2, v0}, Lcom/vk/extensions/ViewExtKt;->a(Landroid/view/View;ILkotlin/jvm/b/Functions2;ILjava/lang/Object;)Landroid/view/View;
|
||||
|
||||
move-result-object p1
|
||||
|
||||
check-cast p1, Landroid/widget/TextView;
|
||||
|
||||
iput-object p1, p0, Lcom/vk/newsfeed/holders/AdMarkHolder;->F:Landroid/widget/TextView;
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
|
||||
# virtual methods
|
||||
.method public b(Lcom/vk/dto/newsfeed/entries/NewsEntry;)V
|
||||
.locals 4
|
||||
|
||||
.line 2
|
||||
instance-of v0, p1, Lcom/vk/dto/newsfeed/entries/Post;
|
||||
|
||||
const/4 v1, 0x0
|
||||
|
||||
const/4 v2, 0x0
|
||||
|
||||
if-eqz v0, :cond_0
|
||||
|
||||
check-cast p1, Lcom/vk/dto/newsfeed/entries/Post;
|
||||
|
||||
invoke-virtual {p1}, Lcom/vk/dto/newsfeed/entries/Post;->L1()Z
|
||||
|
||||
move-result p1
|
||||
|
||||
if-eqz p1, :cond_2
|
||||
|
||||
const p1, 0x7f0808cf
|
||||
|
||||
const v0, 0x7f040256
|
||||
|
||||
.line 3
|
||||
invoke-static {p1, v0}, Lcom/vk/core/ui/themes/VKThemeHelper;->a(II)Lcom/vk/core/drawable/RecoloredDrawable;
|
||||
|
||||
move-result-object p1
|
||||
|
||||
const v0, 0x7f120def
|
||||
|
||||
.line 4
|
||||
invoke-virtual {p0, v0}, Lcom/vtosters/lite/ui/holder/RecyclerHolder;->m(I)Ljava/lang/String;
|
||||
|
||||
move-result-object v0
|
||||
|
||||
.line 5
|
||||
invoke-virtual {p0}, Lcom/vtosters/lite/ui/holder/RecyclerHolder;->e0()Landroid/content/res/Resources;
|
||||
|
||||
move-result-object v1
|
||||
|
||||
const v3, 0x7f0701b8
|
||||
|
||||
invoke-virtual {v1, v3}, Landroid/content/res/Resources;->getDimensionPixelSize(I)I
|
||||
|
||||
move-result v1
|
||||
|
||||
goto :goto_1
|
||||
|
||||
.line 6
|
||||
:cond_0
|
||||
instance-of v0, p1, Lcom/vk/dto/newsfeed/entries/PromoPost;
|
||||
|
||||
if-eqz v0, :cond_2
|
||||
|
||||
check-cast p1, Lcom/vk/dto/newsfeed/entries/PromoPost;
|
||||
|
||||
invoke-virtual {p1}, Lcom/vk/dto/newsfeed/entries/PromoPost;->E1()Ljava/lang/String;
|
||||
|
||||
move-result-object v0
|
||||
|
||||
invoke-interface {v0}, Ljava/lang/CharSequence;->length()I
|
||||
|
||||
move-result v0
|
||||
|
||||
if-lez v0, :cond_1
|
||||
|
||||
const/4 v0, 0x1
|
||||
|
||||
goto :goto_0
|
||||
|
||||
:cond_1
|
||||
const/4 v0, 0x0
|
||||
|
||||
:goto_0
|
||||
if-eqz v0, :cond_2
|
||||
|
||||
.line 7
|
||||
invoke-virtual {p1}, Lcom/vk/dto/newsfeed/entries/PromoPost;->E1()Ljava/lang/String;
|
||||
|
||||
move-result-object p1
|
||||
|
||||
.line 8
|
||||
invoke-virtual {p0}, Lcom/vtosters/lite/ui/holder/RecyclerHolder;->e0()Landroid/content/res/Resources;
|
||||
|
||||
move-result-object v0
|
||||
|
||||
const v1, 0x7f0701b9
|
||||
|
||||
invoke-virtual {v0, v1}, Landroid/content/res/Resources;->getDimensionPixelSize(I)I
|
||||
|
||||
move-result v1
|
||||
|
||||
move-object v0, p1
|
||||
|
||||
move-object p1, v2
|
||||
|
||||
goto :goto_1
|
||||
|
||||
:cond_2
|
||||
move-object p1, v2
|
||||
|
||||
move-object v0, p1
|
||||
|
||||
.line 9
|
||||
:goto_1
|
||||
iget-object v3, p0, Lcom/vk/newsfeed/holders/AdMarkHolder;->F:Landroid/widget/TextView;
|
||||
|
||||
invoke-virtual {v3, p1, v2, v2, v2}, Landroid/widget/TextView;->setCompoundDrawablesRelativeWithIntrinsicBounds(Landroid/graphics/drawable/Drawable;Landroid/graphics/drawable/Drawable;Landroid/graphics/drawable/Drawable;Landroid/graphics/drawable/Drawable;)V
|
||||
|
||||
.line 10
|
||||
iget-object p1, p0, Lcom/vk/newsfeed/holders/AdMarkHolder;->F:Landroid/widget/TextView;
|
||||
|
||||
invoke-virtual {p1, v1}, Landroid/widget/TextView;->setMinHeight(I)V
|
||||
|
||||
.line 11
|
||||
iget-object p1, p0, Lcom/vk/newsfeed/holders/AdMarkHolder;->F:Landroid/widget/TextView;
|
||||
|
||||
invoke-virtual {p1, v0}, Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public bridge synthetic b(Ljava/lang/Object;)V
|
||||
.locals 0
|
||||
|
||||
.line 1
|
||||
check-cast p1, Lcom/vk/dto/newsfeed/entries/NewsEntry;
|
||||
|
||||
invoke-virtual {p0, p1}, Lcom/vk/newsfeed/holders/AdMarkHolder;->b(Lcom/vk/dto/newsfeed/entries/NewsEntry;)V
|
||||
|
||||
return-void
|
||||
.end method
|
||||
@@ -2860,7 +2860,17 @@
|
||||
|
||||
invoke-static {v2, v0}, Lkotlin/jvm/internal/Intrinsics;->a(Ljava/lang/Object;Ljava/lang/String;)V
|
||||
|
||||
.line 76
|
||||
invoke-static {p2}, Lru/vtosters/hooks/PostsMenuHook;->isCustomButton(I)Z
|
||||
|
||||
move-result v3
|
||||
|
||||
if-eqz v3, :cond_20
|
||||
|
||||
invoke-static {p2, p3, v2}, Lru/vtosters/hooks/PostsMenuHook;->injectButtons(ILcom/vk/dto/newsfeed/entries/NewsEntry;Landroid/content/Context;)V
|
||||
|
||||
goto/16 :goto_1
|
||||
|
||||
:cond_20
|
||||
invoke-interface {p0}, Lcom/vk/newsfeed/contracts/EntriesListContract;->v0()Ljava/lang/String;
|
||||
|
||||
move-result-object v3
|
||||
|
||||
@@ -3797,6 +3797,17 @@
|
||||
|
||||
if-eqz v4, :cond_6
|
||||
|
||||
invoke-static {p1}, Lru/vtosters/hooks/PostsMenuHook;->isCustomButton(I)Z
|
||||
|
||||
move-result v3
|
||||
|
||||
if-eqz v3, :cond_20
|
||||
|
||||
invoke-static {p1, v4, v0}, Lru/vtosters/hooks/PostsMenuHook;->injectButtons(ILcom/vk/dto/newsfeed/entries/NewsEntry;Landroid/content/Context;)V
|
||||
|
||||
goto/16 :goto_5
|
||||
|
||||
:cond_20
|
||||
const/4 v1, 0x1
|
||||
|
||||
const/4 v2, 0x0
|
||||
|
||||
Reference in New Issue
Block a user