lastfm test
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
package bruhcollective.itaysonlab.libvkx.client;
|
||||
|
||||
import static ru.vtosters.lite.music.Scrobbler.scrobbleTrack;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getGlobalContext;
|
||||
import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.os.RemoteException;
|
||||
|
||||
@@ -14,22 +16,23 @@ import java.util.List;
|
||||
|
||||
import bruhcollective.itaysonlab.libvkx.ILibVkxService;
|
||||
|
||||
public class LibVKXClient {
|
||||
public class LibVKXClient{
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private static LibVKXClientImpl impl;
|
||||
|
||||
public static LibVKXClientImpl getInstance(Context context) {
|
||||
public static LibVKXClientImpl getInstance(Context context){
|
||||
if (impl == null) {
|
||||
impl = new LibVKXClientImpl(context);
|
||||
}
|
||||
return impl;
|
||||
}
|
||||
|
||||
public static LibVKXClientImpl getInstance() {
|
||||
public static LibVKXClientImpl getInstance(){
|
||||
LibVKXClientImpl libVKXClientImpl = impl;
|
||||
return libVKXClientImpl == null ? getInstance(getGlobalContext()) : libVKXClientImpl;
|
||||
}
|
||||
|
||||
public static boolean isVkxInstalled() {
|
||||
public static boolean isVkxInstalled(){
|
||||
try {
|
||||
getGlobalContext().getPackageManager().getPackageInfo("ua.itaysonlab.vkx", 0);
|
||||
return true;
|
||||
@@ -38,11 +41,13 @@ public class LibVKXClient {
|
||||
}
|
||||
} // VKX check
|
||||
|
||||
public static boolean isIntegrationEnabled() {
|
||||
public static boolean isIntegrationEnabled(){
|
||||
return getBoolValue("libvkx_integration", false) && isVkxInstalled();
|
||||
}
|
||||
|
||||
public static boolean play(MusicTrack musicTrack, List<MusicTrack> list, MusicPlaybackLaunchContext playerRefer) {
|
||||
public static boolean play(MusicTrack musicTrack, List<MusicTrack> list, MusicPlaybackLaunchContext playerRefer){
|
||||
scrobbleTrack(musicTrack.h, musicTrack.C, musicTrack.f, musicTrack.y1());
|
||||
|
||||
if (!isIntegrationEnabled()) {
|
||||
return false;
|
||||
}
|
||||
@@ -52,7 +57,7 @@ public class LibVKXClient {
|
||||
return getInstance().runOnService(action);
|
||||
}
|
||||
|
||||
public static void lambdaplay(List<MusicTrack> list, MusicTrack musicTrack, ILibVkxService iLibVkxService) {
|
||||
public static void lambdaplay(List<MusicTrack> list, MusicTrack musicTrack, ILibVkxService iLibVkxService){
|
||||
int indexOf = list.indexOf(musicTrack);
|
||||
var ids = new ArrayList<String>();
|
||||
for (var track : list) {
|
||||
@@ -69,7 +74,7 @@ public class LibVKXClient {
|
||||
}
|
||||
}
|
||||
|
||||
private static String asId(MusicTrack musicTrack) {
|
||||
private static String asId(MusicTrack musicTrack){
|
||||
String str = musicTrack.e + "_" + musicTrack.d;
|
||||
if (musicTrack.O == null || musicTrack.O.equals("")) {
|
||||
return str;
|
||||
|
||||
@@ -6,7 +6,7 @@ import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
import static ru.vtosters.lite.utils.Preferences.milkshake;
|
||||
import static ru.vtosters.lite.utils.Preferences.superapp;
|
||||
import static ru.vtosters.lite.utils.Preferences.useNewSettings;
|
||||
import static ru.vtosters.lite.utils.Preferences.videoewcatalog;
|
||||
import static ru.vtosters.lite.utils.Preferences.videonewcatalog;
|
||||
import static ru.vtosters.lite.utils.Preferences.vkme;
|
||||
|
||||
import com.vk.apps.AppsFragment;
|
||||
@@ -53,7 +53,7 @@ public class StartFragmentHook {
|
||||
case "photos":
|
||||
return PhotosFragment.class;
|
||||
case "videos":
|
||||
return videoewcatalog() ? VideoCatalogFragment.class : VideosFragment.class;
|
||||
return videonewcatalog() ? VideoCatalogFragment.class : VideosFragment.class;
|
||||
case "settings":
|
||||
return useNewSettings();
|
||||
case "apps":
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package ru.vtosters.lite.music;
|
||||
import static java.lang.String.valueOf;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.MD5;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getDefaultPrefs;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.sendToast;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import ru.vtosters.lite.net.NetCall;
|
||||
import ru.vtosters.lite.net.NetCallback;
|
||||
import ru.vtosters.lite.net.NetClient;
|
||||
import ru.vtosters.lite.net.NetRequest;
|
||||
import ru.vtosters.lite.net.NetResponse;
|
||||
import ru.vtosters.lite.utils.Preferences;
|
||||
|
||||
public class Scrobbler{
|
||||
public static final String key = "5965d63402414776c54c266db0211746";
|
||||
public static final String keysecret = "d982180eed13275bb948e41cf225f88f";
|
||||
public static final String url = "https://ws.audioscrobbler.com/2.0/";
|
||||
private static final NetClient client = new NetClient.Builder().build();
|
||||
public static ArrayList<String> scrobbled = new ArrayList<>();
|
||||
|
||||
public static void scrobbleTrack(long duration, String artist, String title, String uid){
|
||||
var string = getDefaultPrefs().getString("sessionKey", null);
|
||||
var timestamp = System.currentTimeMillis() / 1000;
|
||||
|
||||
Log.d("Scrobbler", "scrobbleTrack: " + title + " - " + artist + " - " + duration + " - " + uid);
|
||||
|
||||
if (string == null || !scrobbled.contains(uid) && !getPreferences().getBoolean("lastfm_enabled", false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
scrobbled.add(uid);
|
||||
|
||||
TreeMap<String, String> treeMap = new TreeMap<>();
|
||||
treeMap.put("method", "track.scrobble");
|
||||
treeMap.put("sk", string);
|
||||
treeMap.put("artist[0]", artist);
|
||||
treeMap.put("track[0]", title);
|
||||
treeMap.put("timestamp[0]", valueOf(timestamp));
|
||||
treeMap.put("api_key", key);
|
||||
treeMap.put("duration[0]", String.valueOf(duration));
|
||||
treeMap.put("api_sig", signMD5(treeMap));
|
||||
treeMap.put("format", "json");
|
||||
|
||||
client.newCall(new NetRequest.Builder().url(url).post().params(treeMap).build()).enqueue(new NetCallback(){
|
||||
@Override
|
||||
public void onFailure(NetCall call, IOException e){
|
||||
Log.d("Scrobbler", "Error: " + e.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(NetCall call, NetResponse response){
|
||||
Log.d("Scrobbler", "Scrobbled: " + artist + " - " + title);
|
||||
if (Preferences.dev()) Log.d("Scrobbler", "Response scrobble: " + response.getDataString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static String signMD5(Map<String, String> map){
|
||||
var sb = new StringBuilder();
|
||||
|
||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
||||
sb.append(entry.getKey());
|
||||
sb.append(entry.getValue());
|
||||
}
|
||||
sb.append(keysecret);
|
||||
|
||||
return MD5(sb.toString());
|
||||
}
|
||||
|
||||
public static void auth(String login, String pass){
|
||||
TreeMap<String, String> treeMap = new TreeMap<>();
|
||||
treeMap.put("method", "auth.getMobileSession");
|
||||
treeMap.put("api_key", key);
|
||||
treeMap.put("username", login);
|
||||
treeMap.put("password", pass);
|
||||
treeMap.put("api_sig", signMD5(treeMap));
|
||||
treeMap.put("format", "json");
|
||||
|
||||
client.newCall(new NetRequest.Builder().url(url).post().params(treeMap).build()).enqueue(new NetCallback(){
|
||||
@Override
|
||||
public void onFailure(NetCall call, IOException e){
|
||||
Log.d("Scrobbler", "Auth failed", e);
|
||||
sendToast("Ошибка входа");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(NetCall call, NetResponse response){
|
||||
try {
|
||||
Log.d("Scrobbler", "Auth " + response.getDataString());
|
||||
JSONObject jSONObject = new JSONObject(response.getDataString()).getJSONObject("session");
|
||||
String string = jSONObject.getString("name");
|
||||
getDefaultPrefs().edit().putString("username", string).putString("sessionKey", jSONObject.getString("key")).apply();
|
||||
sendToast("Успешно вошли как " + string);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void reset(){
|
||||
edit().remove("username").apply();
|
||||
edit().remove("sessionKey").apply();
|
||||
sendToast("Вы успешно вышли из учетной записи");
|
||||
}
|
||||
|
||||
private static String getSessionKey(){
|
||||
return getDefaultPrefs().getString("sessionKey", null);
|
||||
}
|
||||
|
||||
public static String getUserName(){
|
||||
return !getSessionKey().isEmpty() ? getDefaultPrefs().getString("username", null) : null;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import static ru.vtosters.lite.utils.Preferences.getBoolValue;
|
||||
import static ru.vtosters.lite.utils.Preferences.milkshake;
|
||||
import static ru.vtosters.lite.utils.Preferences.superapp;
|
||||
import static ru.vtosters.lite.utils.Preferences.useNewSettings;
|
||||
import static ru.vtosters.lite.utils.Preferences.videoewcatalog;
|
||||
import static ru.vtosters.lite.utils.Preferences.videonewcatalog;
|
||||
import static ru.vtosters.lite.utils.Preferences.vkme;
|
||||
import static ru.vtosters.lite.utils.Preferences.vkme_notifs;
|
||||
|
||||
@@ -197,7 +197,7 @@ public class DockBarEditorManager {
|
||||
R.drawable.ic_video_outline_28,
|
||||
R.string.videos,
|
||||
R.id.menu_videos,
|
||||
videoewcatalog() ? VideoCatalogFragment.class : VideosFragment.class);
|
||||
videonewcatalog() ? VideoCatalogFragment.class : VideosFragment.class);
|
||||
case "tab_lives":
|
||||
return DockBarTab.valuesOf(
|
||||
"tab_lives",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package ru.vtosters.lite.ui.fragments;
|
||||
|
||||
import static ru.vtosters.lite.ui.PreferencesUtil.getSTextColor;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.dp2px;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.edit;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getIdentifier;
|
||||
import static ru.vtosters.lite.utils.AndroidUtils.getPreferences;
|
||||
@@ -13,6 +15,7 @@ import android.content.DialogInterface;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
@@ -26,6 +29,7 @@ import com.vtosters.lite.general.fragments.MaterialPreferenceToolbarFragment;
|
||||
import java.util.Arrays;
|
||||
|
||||
import ru.vtosters.lite.downloaders.VideoDownloader;
|
||||
import ru.vtosters.lite.music.Scrobbler;
|
||||
import ru.vtosters.lite.ui.adapters.ImagineArrayAdapter;
|
||||
|
||||
public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
||||
@@ -37,21 +41,52 @@ public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
||||
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.MATCH_PARENT);
|
||||
|
||||
input.setLayoutParams(lp);
|
||||
|
||||
input.setTextColor(getTextAttr());
|
||||
|
||||
input.setBackgroundTintList(ColorStateList.valueOf(getAccentColor()));
|
||||
|
||||
alertDialog.setView(input);
|
||||
|
||||
alertDialog.setPositiveButton("Скачать", (dialog, which) -> VideoDownloader.parseVideoLink(input.getText().toString(), ctx));
|
||||
|
||||
var alert = alertDialog.create();
|
||||
|
||||
alert.show();
|
||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
||||
}
|
||||
|
||||
public static void lastfmAuth(Context ctx) {
|
||||
LinearLayout linearLayout = new LinearLayout(ctx);
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
final EditText fn = new EditText(ctx);
|
||||
fn.setHint("Логин");
|
||||
fn.setTextColor(getTextAttr());
|
||||
fn.setHintTextColor(getSTextColor(ctx));
|
||||
fn.setBackgroundTintList(ColorStateList.valueOf(getAccentColor()));
|
||||
linearLayout.addView(fn);
|
||||
fn.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
ViewGroup.MarginLayoutParams margin = ((ViewGroup.MarginLayoutParams) fn.getLayoutParams());
|
||||
margin.setMargins(dp2px(20f), 0, dp2px(20f), 0);
|
||||
fn.setLayoutParams(margin);
|
||||
|
||||
final EditText ln = new EditText(ctx);
|
||||
ln.setHint("Пароль");
|
||||
ln.setTextColor(getTextAttr());
|
||||
ln.setHintTextColor(getSTextColor(ctx));
|
||||
ln.setBackgroundTintList(ColorStateList.valueOf(getAccentColor()));
|
||||
linearLayout.addView(ln);
|
||||
ln.getLayoutParams().width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
ln.setLayoutParams(margin);
|
||||
|
||||
AlertDialog.Builder alertDialog = new AlertDialog.Builder(ctx, getAlertStyle());
|
||||
alertDialog.setTitle("Введите логин и пароль");
|
||||
|
||||
alertDialog.setView(linearLayout);
|
||||
alertDialog.setPositiveButton("Войти", (dialog, which) -> {
|
||||
String login = fn.getText().toString();
|
||||
String pass = ln.getText().toString();
|
||||
|
||||
Scrobbler.auth(login, pass);
|
||||
});
|
||||
var alert = alertDialog.create();
|
||||
alert.show();
|
||||
alert.getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(getAccentColor());
|
||||
}
|
||||
|
||||
@@ -65,6 +100,14 @@ public class MediaFragment extends MaterialPreferenceToolbarFragment {
|
||||
private void prefs() {
|
||||
findPreference("download_video").setOnPreferenceClickListener(new MediaFragment.download());
|
||||
findPreference("dateformat").setOnPreferenceChangeListener(new MediaFragment.restart());
|
||||
findPreference("lastfm_auth").setOnPreferenceClickListener(preference -> {
|
||||
lastfmAuth(getContext());
|
||||
return true;
|
||||
});
|
||||
findPreference("lastfm_reset").setOnPreferenceClickListener(preference -> {
|
||||
Scrobbler.reset();
|
||||
return true;
|
||||
});
|
||||
findPreference("select_photo_search_engine").setOnPreferenceClickListener(preference -> {
|
||||
var items = Arrays.asList(
|
||||
new ImagineArrayAdapter.ImagineArrayAdapterItem(getIdentifier("yandex", "drawable"), "Yandex"),
|
||||
|
||||
@@ -15,6 +15,8 @@ import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Locale;
|
||||
|
||||
public class AndroidUtils {
|
||||
@@ -115,4 +117,24 @@ public class AndroidUtils {
|
||||
public static void sendToast(String text) {
|
||||
Toast.makeText(getGlobalContext(), text, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
public static String MD5(String s){
|
||||
try {
|
||||
var messageDigest = MessageDigest.getInstance("MD5");
|
||||
var sb = new StringBuilder();
|
||||
messageDigest.update(s.getBytes());
|
||||
byte[] digest = messageDigest.digest();
|
||||
for (byte b : digest) {
|
||||
String hexString = Integer.toHexString(b & 255);
|
||||
while(hexString.length() < 2) {
|
||||
hexString = "0" + hexString;
|
||||
}
|
||||
sb.append(hexString);
|
||||
}
|
||||
return sb.toString();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,8 +211,8 @@ public class Preferences {
|
||||
return getBoolValue("musicnewcatalog", true);
|
||||
}
|
||||
|
||||
public static boolean videoewcatalog() {
|
||||
return getBoolValue("videoewcatalog", true);
|
||||
public static boolean videonewcatalog() {
|
||||
return getBoolValue("videonewcatalog", true);
|
||||
}
|
||||
|
||||
public static boolean postsredesign() {
|
||||
|
||||
@@ -36,6 +36,18 @@
|
||||
android:summary="Отключение значительно улучшит качество загружаемых видео"
|
||||
android:title="@string/sett_compress_videos" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="Last.fm">
|
||||
<Preference
|
||||
android:key="lastfm_auth"
|
||||
android:title="Войти в аккаунт" />
|
||||
<Preference
|
||||
android:key="lastfm_reset"
|
||||
android:title="Сбросить настройки аккаунта" />
|
||||
<com.vtosters.lite.ui.MaterialSwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:key="lastfm_enabled"
|
||||
android:title="Включить скробблинг" />
|
||||
</PreferenceCategory>
|
||||
<PreferenceCategory android:title="Музыка">
|
||||
<com.vtosters.lite.ui.MaterialSwitchPreference
|
||||
android:defaultValue="true"
|
||||
@@ -56,7 +68,7 @@
|
||||
android:title="Скачать видео" />
|
||||
<com.vtosters.lite.ui.MaterialSwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:key="videoewcatalog"
|
||||
android:key="videonewcatalog"
|
||||
android:summary="Новый каталог видео раздела с динамическим контентом"
|
||||
android:title="Новый раздел видео" />
|
||||
<com.vtosters.lite.ui.MaterialSwitchPreference
|
||||
|
||||
@@ -356,7 +356,7 @@
|
||||
.line 1
|
||||
invoke-super {p0, p1}, Lcom/vk/navigation/NavigationDelegateActivity;->onCreate(Landroid/os/Bundle;)V
|
||||
|
||||
invoke-static {p0}, Lru/vtosters/lite/ui/components/Crashreporter;->init(Landroid/app/Activity;)V
|
||||
invoke-static {p0}, Lru/vtosters/lite/ui/components/CrashReporter;->init(Landroid/app/Activity;)V
|
||||
|
||||
invoke-static {p0}, Lru/vtosters/lite/utils/VTVerifications;->load(Landroid/content/Context;)V
|
||||
|
||||
|
||||
Reference in New Issue
Block a user