From bbfa278d6b5787ede79600481ccc4375de0e7f89 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 30 Dec 2020 15:37:09 +0100 Subject: [PATCH] Implement logic --- app/build.gradle | 7 +- .../fedilab/fedilabtube/LoginActivity.java | 169 +++++++++++----- .../fedilabtube/client/MastodonService.java | 47 +++++ .../client/RetrofitMastodonAPI.java | 189 ++++++++++++++++++ .../client/RetrofitPeertubeAPI.java | 6 +- .../fedilab/fedilabtube/helper/Helper.java | 2 + .../fedilabtube/sqlite/AccountDAO.java | 5 +- .../fedilab/fedilabtube/sqlite/Sqlite.java | 45 ++++- 8 files changed, 417 insertions(+), 53 deletions(-) create mode 100644 app/src/main/java/app/fedilab/fedilabtube/client/MastodonService.java create mode 100644 app/src/main/java/app/fedilab/fedilabtube/client/RetrofitMastodonAPI.java diff --git a/app/build.gradle b/app/build.gradle index 79b3770..e95e354 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -50,6 +50,7 @@ android { buildConfigField "boolean", "surfing_mode", "false" buildConfigField "boolean", "sepia_search", "false" buildConfigField "boolean", "instance_switcher", "true" + buildConfigField "boolean", "allow_remote_connections", "false" } google_peertube_apps_educ { applicationId "app.fedilab.fedilabtube" @@ -61,6 +62,7 @@ android { buildConfigField "boolean", "surfing_mode", "false" buildConfigField "boolean", "sepia_search", "false" buildConfigField "boolean", "instance_switcher", "true" + buildConfigField "boolean", "allow_remote_connections", "false" } fdroid_full { applicationId "app.fedilab.tubelab" @@ -72,6 +74,7 @@ android { buildConfigField "boolean", "surfing_mode", "true" buildConfigField "boolean", "sepia_search", "true" buildConfigField "boolean", "instance_switcher", "true" + buildConfigField "boolean", "allow_remote_connections", "true" } google_full { applicationId "app.fedilab.tubelab" @@ -83,6 +86,7 @@ android { buildConfigField "boolean", "surfing_mode", "true" buildConfigField "boolean", "sepia_search", "true" buildConfigField "boolean", "instance_switcher", "true" + buildConfigField "boolean", "allow_remote_connections", "true" } queermotion { applicationId "org.queermotion.peertube" @@ -94,6 +98,7 @@ android { buildConfigField "boolean", "surfing_mode", "false" buildConfigField "boolean", "sepia_search", "false" buildConfigField "boolean", "instance_switcher", "false" + buildConfigField "boolean", "allow_remote_connections", "false" } bittube { applicationId "app.fedilab.bittube" @@ -105,7 +110,7 @@ android { buildConfigField "boolean", "surfing_mode", "false" buildConfigField "boolean", "sepia_search", "false" buildConfigField "boolean", "instance_switcher", "true" - + buildConfigField "boolean", "allow_remote_connections", "false" } } diff --git a/app/src/main/java/app/fedilab/fedilabtube/LoginActivity.java b/app/src/main/java/app/fedilab/fedilabtube/LoginActivity.java index 39fb7fe..cdc24f4 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/LoginActivity.java +++ b/app/src/main/java/app/fedilab/fedilabtube/LoginActivity.java @@ -41,11 +41,13 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import app.fedilab.fedilabtube.client.RetrofitMastodonAPI; import app.fedilab.fedilabtube.client.RetrofitPeertubeAPI; import app.fedilab.fedilabtube.client.entities.Error; import app.fedilab.fedilabtube.client.entities.Oauth; import app.fedilab.fedilabtube.client.entities.OauthParams; import app.fedilab.fedilabtube.client.entities.Token; +import app.fedilab.fedilabtube.client.entities.WellKnownNodeinfo; import app.fedilab.fedilabtube.databinding.ActivityLoginBinding; import app.fedilab.fedilabtube.helper.Helper; import app.fedilab.fedilabtube.helper.HelperAcadInstance; @@ -76,6 +78,7 @@ public class LoginActivity extends AppCompatActivity { SpannableString content_create; + //noinspection ConstantConditions if (BuildConfig.FLAVOR.compareTo("queermotion") == 0) { content_create = new SpannableString(getString(R.string.register_account)); } else { @@ -98,6 +101,7 @@ public class LoginActivity extends AppCompatActivity { if (BuildConfig.full_instances && BuildConfig.instance_switcher) { binding.loginInstanceContainer.setVisibility(View.VISIBLE); } + //noinspection ConstantConditions if (BuildConfig.FLAVOR.compareTo("queermotion") == 0) { binding.loginInstance.setText("queermotion.org"); } @@ -211,7 +215,7 @@ public class LoginActivity extends AppCompatActivity { return; } binding.loginButton.setEnabled(false); - String instance, host; + String instance; if (!BuildConfig.full_instances) { String[] emailArray = binding.loginUid.getText().toString().split("@"); if (emailArray.length > 1 && !Arrays.asList(HelperAcadInstance.valideEmails).contains(emailArray[1])) { @@ -221,21 +225,19 @@ public class LoginActivity extends AppCompatActivity { } instance = HelperInstance.getLiveInstance(LoginActivity.this); - host = instance; } else { if (binding.loginInstance.getText() == null || binding.loginInstance.getText().toString().trim().length() == 0) { Toasty.error(LoginActivity.this, getString(R.string.not_valide_instance)).show(); binding.loginButton.setEnabled(true); return; } - instance = host = binding.loginInstance.getText().toString().trim().toLowerCase(); + instance = binding.loginInstance.getText().toString().trim().toLowerCase(); } if (instance.startsWith("http")) { try { URL url = new URL(instance); instance = url.getHost(); - host = instance; } catch (MalformedURLException e) { e.printStackTrace(); } @@ -243,7 +245,6 @@ public class LoginActivity extends AppCompatActivity { try { URL url = new URL("https://" + instance); instance = url.getHost(); - host = instance; } catch (MalformedURLException e) { e.printStackTrace(); } @@ -254,57 +255,133 @@ public class LoginActivity extends AppCompatActivity { return; } String finalInstance = instance; - String finalHost = host; if (BuildConfig.full_instances) { new Thread(() -> { - Oauth oauth = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).oauthClient(Helper.CLIENT_NAME_VALUE, Helper.WEBSITE_VALUE, Helper.OAUTH_SCOPES_PEERTUBE, Helper.WEBSITE_VALUE); - if (oauth == null) { - runOnUiThread(() -> { - binding.loginButton.setEnabled(true); - Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show(); - }); - return; - } - - client_id = oauth.getClient_id(); - client_secret = oauth.getClient_secret(); - - SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); - SharedPreferences.Editor editor = sharedpreferences.edit(); - editor.putString(Helper.CLIENT_ID, client_id); - editor.putString(Helper.CLIENT_SECRET, client_secret); - editor.apply(); - OauthParams oauthParams = new OauthParams(); - oauthParams.setClient_id(client_id); - oauthParams.setClient_secret(client_secret); - oauthParams.setGrant_type("password"); - oauthParams.setScope("user"); - oauthParams.setUsername(binding.loginUid.getText().toString().trim()); - if (binding.loginPasswd.getText() != null) { - oauthParams.setPassword(binding.loginPasswd.getText().toString()); - } - try { - Token token = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).manageToken(oauthParams); - proceedLogin(token, finalHost); - } catch (final Exception | Error e) { - oauthParams.setUsername(binding.loginUid.getText().toString().toLowerCase().trim()); - try { - Token token = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).manageToken(oauthParams); - proceedLogin(token, finalHost); - } catch (Error error) { - Error.displayError(LoginActivity.this, error); - error.printStackTrace(); - runOnUiThread(() -> binding.loginButton.setEnabled(true)); + boolean connectAPeertubeAccount = true; + WellKnownNodeinfo.NodeInfo instanceNodeInfo = null; + if (BuildConfig.allow_remote_connections) { + instanceNodeInfo = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).getNodeInfo(); + if (instanceNodeInfo != null && instanceNodeInfo.getSoftware().getName().toUpperCase().trim().compareTo("PEERTUBE") != 0) { + connectAPeertubeAccount = false; } } + if (connectAPeertubeAccount) { + connectToPeertube(finalInstance); + } else { + connectToFediverse(finalInstance, instanceNodeInfo); + } }).start(); } } }); } + private void connectToFediverse(String finalInstance, WellKnownNodeinfo.NodeInfo instanceNodeInfo) { + switch (instanceNodeInfo.getSoftware().getName().toUpperCase().trim()) { + case "MASTODON": + case "PLEROMA": + Oauth oauth = new RetrofitMastodonAPI(LoginActivity.this, finalInstance, null).oauthClient(Helper.CLIENT_NAME_VALUE, Helper.REDIRECT_CONTENT, Helper.OAUTH_SCOPES_MASTODON, Helper.WEBSITE_VALUE); + if (oauth == null) { + runOnUiThread(() -> { + binding.loginButton.setEnabled(true); + Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show(); + }); + return; + } + client_id = oauth.getClient_id(); + client_secret = oauth.getClient_secret(); + + SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); + SharedPreferences.Editor editor = sharedpreferences.edit(); + editor.putString(Helper.CLIENT_ID, client_id); + editor.putString(Helper.CLIENT_SECRET, client_secret); + editor.apply(); + OauthParams oauthParams = new OauthParams(); + oauthParams.setClient_id(client_id); + oauthParams.setClient_secret(client_secret); + oauthParams.setGrant_type("password"); + oauthParams.setScope("user"); + if (binding.loginUid.getText() != null) { + oauthParams.setUsername(binding.loginUid.getText().toString().trim()); + } + if (binding.loginPasswd.getText() != null) { + oauthParams.setPassword(binding.loginPasswd.getText().toString()); + } + try { + Token token = new RetrofitMastodonAPI(LoginActivity.this, finalInstance, null).manageToken(oauthParams); + proceedLogin(token, finalInstance, instanceNodeInfo.getSoftware().getName().toUpperCase().trim()); + } catch (final Exception | Error e) { + oauthParams.setUsername(binding.loginUid.getText().toString().toLowerCase().trim()); + try { + Token token = new RetrofitMastodonAPI(LoginActivity.this, finalInstance, null).manageToken(oauthParams); + proceedLogin(token, finalInstance, instanceNodeInfo.getSoftware().getName().toUpperCase().trim()); + } catch (Error error) { + Error.displayError(LoginActivity.this, error); + error.printStackTrace(); + runOnUiThread(() -> binding.loginButton.setEnabled(true)); + } + } + break; + + case "FRIENDICA": + + break; + } + + } + + /** + * Oauth process for Peertube + * + * @param finalInstance String + */ + private void connectToPeertube(String finalInstance) { + Oauth oauth = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).oauthClient(Helper.CLIENT_NAME_VALUE, Helper.WEBSITE_VALUE, Helper.OAUTH_SCOPES_PEERTUBE, Helper.WEBSITE_VALUE); + if (oauth == null) { + runOnUiThread(() -> { + binding.loginButton.setEnabled(true); + Toasty.error(LoginActivity.this, getString(R.string.client_error), Toast.LENGTH_LONG).show(); + }); + return; + } + + client_id = oauth.getClient_id(); + client_secret = oauth.getClient_secret(); + + SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); + SharedPreferences.Editor editor = sharedpreferences.edit(); + editor.putString(Helper.CLIENT_ID, client_id); + editor.putString(Helper.CLIENT_SECRET, client_secret); + editor.apply(); + OauthParams oauthParams = new OauthParams(); + oauthParams.setClient_id(client_id); + oauthParams.setClient_secret(client_secret); + oauthParams.setGrant_type("password"); + oauthParams.setScope("user"); + if (binding.loginUid.getText() != null) { + oauthParams.setUsername(binding.loginUid.getText().toString().trim()); + } + if (binding.loginPasswd.getText() != null) { + oauthParams.setPassword(binding.loginPasswd.getText().toString()); + } + try { + Token token = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).manageToken(oauthParams); + proceedLogin(token, finalInstance, null); + } catch (final Exception | Error e) { + oauthParams.setUsername(binding.loginUid.getText().toString().toLowerCase().trim()); + try { + Token token = new RetrofitPeertubeAPI(LoginActivity.this, finalInstance, null).manageToken(oauthParams); + proceedLogin(token, finalInstance, null); + } catch (Error error) { + Error.displayError(LoginActivity.this, error); + error.printStackTrace(); + runOnUiThread(() -> binding.loginButton.setEnabled(true)); + } + } + } + @SuppressLint("ApplySharedPref") - private void proceedLogin(Token token, String host) { + private void proceedLogin(Token token, String host, String software) { runOnUiThread(() -> { if (token != null) { SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); @@ -313,7 +390,7 @@ public class LoginActivity extends AppCompatActivity { editor.putString(Helper.PREF_INSTANCE, host); editor.commit(); //Update the account with the token; - updateCredential(LoginActivity.this, token.getAccess_token(), client_id, client_secret, token.getRefresh_token(), host); + updateCredential(LoginActivity.this, token.getAccess_token(), client_id, client_secret, token.getRefresh_token(), host, software); } else { binding.loginButton.setEnabled(true); } diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/MastodonService.java b/app/src/main/java/app/fedilab/fedilabtube/client/MastodonService.java new file mode 100644 index 0000000..ff8f822 --- /dev/null +++ b/app/src/main/java/app/fedilab/fedilabtube/client/MastodonService.java @@ -0,0 +1,47 @@ +package app.fedilab.fedilabtube.client; +/* Copyright 2020 Thomas Schneider + * + * This file is a part of TubeLab + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * TubeLab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with TubeLab; if not, + * see . */ + + +import app.fedilab.fedilabtube.client.data.AccountData; +import app.fedilab.fedilabtube.client.entities.Oauth; +import app.fedilab.fedilabtube.client.entities.Token; +import retrofit2.Call; +import retrofit2.http.Field; +import retrofit2.http.FormUrlEncoded; +import retrofit2.http.GET; +import retrofit2.http.Header; +import retrofit2.http.POST; +import retrofit2.http.Query; + +interface MastodonService { + + @GET("apps") + Call getOauth(@Query("client_name") String client_name, @Query("redirect_uris") String redirect_uris, @Query("scopes") String scopes, @Query("website") String website); + + @FormUrlEncoded + @POST("/oauth/token") + Call createToken( + @Field("client_id") String client_id, + @Field("client_secret") String client_secret, + @Field("grant_type") String grant_type, + @Field("scrope") String scope, + @Field("username") String username, + @Field("password") String password); + + @GET("/accounts/verify_credentials") + Call verifyCredentials(@Header("Authorization") String credentials); + +} diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/RetrofitMastodonAPI.java b/app/src/main/java/app/fedilab/fedilabtube/client/RetrofitMastodonAPI.java new file mode 100644 index 0000000..b4ed5ca --- /dev/null +++ b/app/src/main/java/app/fedilab/fedilabtube/client/RetrofitMastodonAPI.java @@ -0,0 +1,189 @@ +package app.fedilab.fedilabtube.client; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.database.sqlite.SQLiteDatabase; +import android.os.Handler; +import android.os.Looper; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; + +import app.fedilab.fedilabtube.BuildConfig; +import app.fedilab.fedilabtube.MainActivity; +import app.fedilab.fedilabtube.R; +import app.fedilab.fedilabtube.client.data.AccountData; +import app.fedilab.fedilabtube.client.entities.Error; +import app.fedilab.fedilabtube.client.entities.Oauth; +import app.fedilab.fedilabtube.client.entities.OauthParams; +import app.fedilab.fedilabtube.client.entities.Token; +import app.fedilab.fedilabtube.client.entities.UserMe; +import app.fedilab.fedilabtube.helper.Helper; +import app.fedilab.fedilabtube.helper.HelperInstance; +import app.fedilab.fedilabtube.sqlite.AccountDAO; +import app.fedilab.fedilabtube.sqlite.Sqlite; +import retrofit2.Call; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +public class RetrofitMastodonAPI { + + private final String finalUrl; + private final Context _context; + private final String instance; + private String token; + + public RetrofitMastodonAPI(Context context) { + _context = context; + instance = HelperInstance.getLiveInstance(context); + finalUrl = "https://" + HelperInstance.getLiveInstance(context) + "/api/v1/"; + } + + public RetrofitMastodonAPI(Context context, String instance, String token) { + _context = context; + this.instance = instance; + this.token = token; + finalUrl = "https://" + instance + "/api/v1/"; + } + + public static void updateCredential(Activity activity, String token, String client_id, String client_secret, String refresh_token, String host, String software) { + new Thread(() -> { + AccountData.Account account; + String instance = host; + try { + account = new RetrofitMastodonAPI(activity, instance, token).verifyCredentials(); + } catch (Error error) { + Error.displayError(activity, error); + error.printStackTrace(); + return; + } + try { + //At the state the instance can be encoded + instance = URLDecoder.decode(instance, "utf-8"); + } catch (UnsupportedEncodingException ignored) { + } + SharedPreferences sharedpreferences = activity.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + account.setToken(token); + account.setClient_id(client_id); + account.setClient_secret(client_secret); + account.setRefresh_token(refresh_token); + account.setHost(instance); + SQLiteDatabase db = Sqlite.getInstance(activity.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + boolean userExists = new AccountDAO(activity, db).userExist(account); + SharedPreferences.Editor editor = sharedpreferences.edit(); + editor.putString(Helper.PREF_KEY_ID, account.getId()); + editor.putString(Helper.PREF_KEY_NAME, account.getUsername()); + editor.apply(); + if (userExists) + new AccountDAO(activity, db).updateAccountCredential(account); + else { + if (account.getUsername() != null && account.getCreatedAt() != null) + new AccountDAO(activity, db).insertAccount(account, software); + } + Handler mainHandler = new Handler(Looper.getMainLooper()); + Runnable myRunnable = () -> { + Intent mainActivity = new Intent(activity, MainActivity.class); + mainActivity.putExtra(Helper.INTENT_ACTION, Helper.ADD_USER_INTENT); + activity.startActivity(mainActivity); + activity.finish(); + }; + mainHandler.post(myRunnable); + }).start(); + } + + private MastodonService init() { + Retrofit retrofit = new Retrofit.Builder() + .baseUrl(finalUrl) + .addConverterFactory(GsonConverterFactory.create()) + .build(); + SharedPreferences sharedpreferences = _context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); + if (token == null) { + token = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null); + } + return retrofit.create(MastodonService.class); + } + + /** + * Get Oauth + * + * @return APIResponse + */ + public Oauth oauthClient(String client_name, String redirect_uris, String scopes, String website) { + MastodonService mastodonService = init(); + try { + Call oauth; + oauth = mastodonService.getOauth(client_name, redirect_uris, scopes, website); + Response response = oauth.execute(); + if (response.isSuccessful() && response.body() != null) { + return response.body(); + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + + /*** + * Verifiy credential of the authenticated user *synchronously* + * @return Account + */ + public AccountData.Account verifyCredentials() throws Error { + MastodonService mastodonService = init(); + Call accountCall = mastodonService.verifyCredentials("Bearer " + token); + APIResponse apiResponse = new APIResponse(); + try { + Response response = accountCall.execute(); + if (response.isSuccessful() && response.body() != null) { + return response.body(); + } else { + Error error = new Error(); + error.setStatusCode(response.code()); + if (response.errorBody() != null) { + error.setError(response.errorBody().string()); + } else { + error.setError(_context.getString(R.string.toast_error)); + } + throw error; + } + } catch (IOException e) { + Error error = new Error(); + error.setError(_context.getString(R.string.toast_error)); + apiResponse.setError(error); + e.printStackTrace(); + } + return null; + } + + /*** + * Verifiy credential of the authenticated user *synchronously* + * @return Account + */ + public Token manageToken(OauthParams oauthParams) throws Error { + MastodonService mastodonService = init(); + Call createToken = mastodonService.createToken(oauthParams.getClient_id(), oauthParams.getClient_secret(), oauthParams.getGrant_type(), oauthParams.getScope(), oauthParams.getUsername(), oauthParams.getPassword()); + if (createToken != null) { + try { + Response response = createToken.execute(); + if (response.isSuccessful()) { + return response.body(); + } else { + Error error = new Error(); + error.setStatusCode(response.code()); + if (response.errorBody() != null) { + error.setError(response.errorBody().string()); + } else { + error.setError(_context.getString(R.string.toast_error)); + } + throw error; + } + } catch (IOException e) { + e.printStackTrace(); + } + } + return null; + } +} diff --git a/app/src/main/java/app/fedilab/fedilabtube/client/RetrofitPeertubeAPI.java b/app/src/main/java/app/fedilab/fedilabtube/client/RetrofitPeertubeAPI.java index 209cb3e..92963e9 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/client/RetrofitPeertubeAPI.java +++ b/app/src/main/java/app/fedilab/fedilabtube/client/RetrofitPeertubeAPI.java @@ -101,7 +101,7 @@ public class RetrofitPeertubeAPI { private final String count; private String token; private Set selection; - private String showNSFWVideos = "both"; + private final String showNSFWVideos; public RetrofitPeertubeAPI(Context context) { _context = context; @@ -137,7 +137,7 @@ public class RetrofitPeertubeAPI { } - public static void updateCredential(Activity activity, String token, String client_id, String client_secret, String refresh_token, String host) { + public static void updateCredential(Activity activity, String token, String client_id, String client_secret, String refresh_token, String host, String software) { new Thread(() -> { AccountData.Account account; String instance = host; @@ -173,7 +173,7 @@ public class RetrofitPeertubeAPI { new AccountDAO(activity, db).updateAccountCredential(account); else { if (account.getUsername() != null && account.getCreatedAt() != null) - new AccountDAO(activity, db).insertAccount(account); + new AccountDAO(activity, db).insertAccount(account, software); } Handler mainHandler = new Handler(Looper.getMainLooper()); Runnable myRunnable = () -> { diff --git a/app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java b/app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java index 1dddc73..ea6f73e 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java +++ b/app/src/main/java/app/fedilab/fedilabtube/helper/Helper.java @@ -111,6 +111,8 @@ public class Helper { public static final String WEBSITE_VALUE = "https://fedilab.app"; public static final String CLIENT_NAME_VALUE = "TubeLab"; public static final String OAUTH_SCOPES_PEERTUBE = "openid profile"; + public static final String OAUTH_SCOPES_MASTODON = "read write follow"; + public static final String REDIRECT_CONTENT = "urn:ietf:wg:oauth:2.0:oob"; public static final String PREF_KEY_OAUTH_TOKEN = "oauth_token"; public static final Pattern redirectPattern = Pattern.compile("externalAuthToken=(\\w+)&username=([\\w.-]+)"); public static final String SET_VIDEO_CACHE = "set_video_cache"; diff --git a/app/src/main/java/app/fedilab/fedilabtube/sqlite/AccountDAO.java b/app/src/main/java/app/fedilab/fedilabtube/sqlite/AccountDAO.java index 9bd83bf..1e2f767 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/sqlite/AccountDAO.java +++ b/app/src/main/java/app/fedilab/fedilabtube/sqlite/AccountDAO.java @@ -51,7 +51,7 @@ public class AccountDAO { * @param account Account * @return boolean */ - public boolean insertAccount(Account account) { + public boolean insertAccount(Account account, String software) { ContentValues values = new ContentValues(); if (account.getCreatedAt() == null) account.setCreatedAt(new Date()); @@ -74,6 +74,9 @@ public class AccountDAO { values.put(Sqlite.COL_AVATAR_STATIC, ""); values.put(Sqlite.COL_HEADER, ""); values.put(Sqlite.COL_HEADER_STATIC, ""); + if (software != null && software.toUpperCase().trim().compareTo("PEERTUBE") != 0) { + values.put(Sqlite.COL_SOFTWARE, software.toUpperCase().trim()); + } if (account.getClient_id() != null && account.getClient_secret() != null) { values.put(Sqlite.COL_CLIENT_ID, account.getClient_id()); values.put(Sqlite.COL_CLIENT_SECRET, account.getClient_secret()); diff --git a/app/src/main/java/app/fedilab/fedilabtube/sqlite/Sqlite.java b/app/src/main/java/app/fedilab/fedilabtube/sqlite/Sqlite.java index 5503449..c7c17e6 100644 --- a/app/src/main/java/app/fedilab/fedilabtube/sqlite/Sqlite.java +++ b/app/src/main/java/app/fedilab/fedilabtube/sqlite/Sqlite.java @@ -15,13 +15,19 @@ package app.fedilab.fedilabtube.sqlite; * see . */ import android.content.Context; +import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; +import android.text.TextUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; public class Sqlite extends SQLiteOpenHelper { - public static final int DB_VERSION = 3; + public static final int DB_VERSION = 4; public static final String DB_NAME = "mastodon_etalab_db"; /*** * List of tables to manage users and data @@ -67,6 +73,7 @@ public class Sqlite extends SQLiteOpenHelper { static final String TABLE_VIDEOS = "VIDEOS"; static final String COL_VIDEO_DATA = "VIDEO_DATA"; static final String COL_PLAYLIST_ID = "PLAYLIST_ID"; + static final String COL_SOFTWARE = "SOFTWARE"; private static final String CREATE_TABLE_USER_ACCOUNT = "CREATE TABLE " + TABLE_USER_ACCOUNT + " (" + COL_USER_ID + " TEXT, " + COL_USERNAME + " TEXT NOT NULL, " + COL_ACCT + " TEXT NOT NULL, " + COL_DISPLAYED_NAME + " TEXT NOT NULL, " + COL_LOCKED + " INTEGER NOT NULL, " @@ -79,8 +86,11 @@ public class Sqlite extends SQLiteOpenHelper { + COL_CLIENT_ID + " TEXT, " + COL_CLIENT_SECRET + " TEXT, " + COL_REFRESH_TOKEN + " TEXT," + COL_UPDATED_AT + " TEXT, " + COL_PRIVACY + " TEXT, " + + COL_SOFTWARE + " TEXT NOT NULL DEFAULT \"PEERTUBE\", " + COL_SENSITIVE + " INTEGER DEFAULT 0, " + COL_INSTANCE + " TEXT NOT NULL, " + COL_OAUTHTOKEN + " TEXT NOT NULL, " + COL_CREATED_AT + " TEXT NOT NULL)"; + + public static SQLiteDatabase db; private static Sqlite sInstance; private final String CREATE_TABLE_PEERTUBE_FAVOURITES = "CREATE TABLE " @@ -136,15 +146,44 @@ public class Sqlite extends SQLiteOpenHelper { @Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { switch (oldVersion) { + case 4: + dropColumn(TABLE_USER_ACCOUNT, new String[]{COL_SOFTWARE}); case 3: db.execSQL("DROP TABLE IF EXISTS " + TABLE_VIDEOS); db.execSQL("DROP TABLE IF EXISTS " + TABLE_LOCAL_PLAYLISTS); case 2: db.execSQL("DROP TABLE IF EXISTS " + TABLE_BOOKMARKED_INSTANCES); - } } + @SuppressWarnings("SameParameterValue") + private void dropColumn( + String tableName, + String[] colsToRemove) { + List updatedTableColumns = getTableColumns(tableName); + // Remove the columns we don't want anymore from the table's list of columns + updatedTableColumns.removeAll(Arrays.asList(colsToRemove)); + String columnsSeperated = TextUtils.join(",", updatedTableColumns); + db.execSQL("ALTER TABLE " + tableName + " RENAME TO " + tableName + "_old;"); + // Creating the table on its new format (no redundant columns) + db.execSQL("CREATE TABLE " + tableName); + // Populating the table with the data + db.execSQL("INSERT INTO " + tableName + "(" + columnsSeperated + ") SELECT " + + columnsSeperated + " FROM " + tableName + "_old;"); + db.execSQL("DROP TABLE " + tableName + "_old;"); + } + + public List getTableColumns(String tableName) { + ArrayList columns = new ArrayList<>(); + String cmd = "pragma table_info(" + tableName + ");"; + Cursor cur = db.rawQuery(cmd, null); + while (cur.moveToNext()) { + columns.add(cur.getString(cur.getColumnIndex("name"))); + } + cur.close(); + return columns; + } + @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { switch (oldVersion) { @@ -153,6 +192,8 @@ public class Sqlite extends SQLiteOpenHelper { case 2: db.execSQL(CREATE_TABLE_LOCAL_PLAYLISTS); db.execSQL(CREATE_TABLE_VIDEOS); + case 3: + db.execSQL("ALTER TABLE " + TABLE_USER_ACCOUNT + " ADD COLUMN " + COL_SOFTWARE + " TEXT NOT NULL DEFAULT \"PEERTUBE\""); } }