package me.ccrama.redditslide; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.AsyncTask; import android.widget.Toast; import net.dean.jraw.ApiException; import net.dean.jraw.managers.AccountManager; import net.dean.jraw.managers.MultiRedditManager; import net.dean.jraw.models.MultiReddit; import net.dean.jraw.models.MultiSubreddit; import net.dean.jraw.models.Subreddit; import net.dean.jraw.models.UserRecord; import net.dean.jraw.paginators.ImportantUserPaginator; import net.dean.jraw.paginators.UserSubredditsPaginator; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import me.ccrama.redditslide.Activities.Login; import me.ccrama.redditslide.Activities.MainActivity; import me.ccrama.redditslide.Activities.MultiredditOverview; import me.ccrama.redditslide.DragSort.ReorderSubreddits; import me.ccrama.redditslide.util.NetworkUtil; /** * Created by carlo_000 on 1/16/2016. */ public class UserSubscriptions { public static final String SUB_NAME_TO_PROPERTIES = "multiNameToSubs"; public static final List<String> defaultSubs = Arrays.asList("frontpage", "all", "announcements", "Art", "AskReddit", "askscience", "aww", "blog", "books", "creepy", "dataisbeautiful", "DIY", "Documentaries", "EarthPorn", "explainlikeimfive", "Fitness", "food", "funny", "Futurology", "gadgets", "gaming", "GetMotivated", "gifs", "history", "IAmA", "InternetIsBeautiful", "Jokes", "LifeProTips", "listentothis", "mildlyinteresting", "movies", "Music", "news", "nosleep", "nottheonion", "OldSchoolCool", "personalfinance", "philosophy", "photoshopbattles", "pics", "science", "Showerthoughts", "space", "sports", "television", "tifu", "todayilearned", "TwoXChromosomes", "UpliftingNews", "videos", "worldnews", "WritingPrompts"); public static final List<String> specialSubreddits = Arrays.asList("frontpage", "all", "random", "randnsfw", "myrandom", "friends", "mod", "popular"); public static SharedPreferences subscriptions; public static SharedPreferences multiNameToSubs; public static SharedPreferences pinned; public static void setSubNameToProperties(String name, String descrption) { multiNameToSubs.edit().putString(name, descrption).apply(); } public static Map<String, String> getMultiNameToSubs(boolean all) { Map<String, String> multiNameToSubsMapBase = new HashMap<>(); Map<String, ?> multiNameToSubsObject = multiNameToSubs.getAll(); for (Map.Entry<String, ?> entry : multiNameToSubsObject.entrySet()) { multiNameToSubsMapBase.put(entry.getKey(), entry.getValue().toString()); } if (all) multiNameToSubsMapBase.putAll(getSubsNameToMulti()); Map<String, String> multiNameToSubsMap = new HashMap<>(); for (Map.Entry<String, String> entries : multiNameToSubsMapBase.entrySet()) { multiNameToSubsMap.put(entries.getKey().toLowerCase(), entries.getValue()); } return multiNameToSubsMap; } private static Map<String, String> getSubsNameToMulti() { Map<String, String> multiNameToSubsMap = new HashMap<>(); Map<String, ?> multiNameToSubsObject = multiNameToSubs.getAll(); for (Map.Entry<String, ?> entry : multiNameToSubsObject.entrySet()) { multiNameToSubsMap.put(entry.getValue().toString(), entry.getKey()); } return multiNameToSubsMap; } public static void doMainActivitySubs(MainActivity c) { if (NetworkUtil.isConnected(c)) { String s = subscriptions.getString(Authentication.name, ""); if (s.isEmpty()) { //get online subs c.updateSubs(syncSubscriptionsOverwrite(c)); } else { CaseInsensitiveArrayList subredditsForHome = new CaseInsensitiveArrayList(); for (String s2 : s.split(",")) { subredditsForHome.add(s2.toLowerCase()); } c.updateSubs(subredditsForHome); } c.updateMultiNameToSubs(getMultiNameToSubs(false)); } else { String s = subscriptions.getString(Authentication.name, ""); List<String> subredditsForHome = new CaseInsensitiveArrayList(); if (!s.isEmpty()) { for (String s2 : s.split(",")) { subredditsForHome.add(s2.toLowerCase()); } } CaseInsensitiveArrayList finals = new CaseInsensitiveArrayList(); List<String> offline = OfflineSubreddit.getAllFormatted(); for (String subs : subredditsForHome) { if (offline.contains(subs)) { finals.add(subs); } } for (String subs : offline) { if (!finals.contains(subs)) { finals.add(subs); } } c.updateSubs(finals); c.updateMultiNameToSubs(getMultiNameToSubs(false)); } } public static void doCachedModSubs() { if (modOf == null || modOf.isEmpty()) { String s = subscriptions.getString(Authentication.name + "mod", ""); if (!s.isEmpty()) { modOf = new CaseInsensitiveArrayList(); for (String s2 : s.split(",")) { modOf.add(s2.toLowerCase()); } } } } public static void cacheModOf() { subscriptions.edit() .putString(Authentication.name + "mod", Reddit.arrayToString(modOf)) .apply(); } public static class SyncMultireddits extends AsyncTask<Void, Void, Boolean> { Context c; public SyncMultireddits(Context c) { this.c = c; } @Override public void onPostExecute(Boolean b) { Intent i = new Intent(c, MultiredditOverview.class); c.startActivity(i); ((Activity) c).finish(); } @Override public Boolean doInBackground(Void... params) { syncMultiReddits(c); return null; } } public static CaseInsensitiveArrayList getSubscriptions(Context c) { String s = subscriptions.getString(Authentication.name, ""); if (s.isEmpty()) { //get online subs return syncSubscriptionsOverwrite(c); } else { CaseInsensitiveArrayList subredditsForHome = new CaseInsensitiveArrayList(); for (String s2 : s.split(",")) { if (!subredditsForHome.contains(s2)) subredditsForHome.add(s2); } return subredditsForHome; } } public static CaseInsensitiveArrayList pins; public static CaseInsensitiveArrayList getPinned() { String s = pinned.getString(Authentication.name, ""); if (s.isEmpty()) { //get online subs return new CaseInsensitiveArrayList(); } else if (pins == null) { pins = new CaseInsensitiveArrayList(); for (String s2 : s.split(",")) { if (!pins.contains(s2)) pins.add(s2); } return pins; } else { return pins; } } public static CaseInsensitiveArrayList getSubscriptionsForShortcut(Context c) { String s = subscriptions.getString(Authentication.name, ""); if (s.isEmpty()) { //get online subs return syncSubscriptionsOverwrite(c); } else { CaseInsensitiveArrayList subredditsForHome = new CaseInsensitiveArrayList(); for (String s2 : s.split(",")) { if (!s2.contains("/m/")) subredditsForHome.add(s2.toLowerCase()); } return subredditsForHome; } } public static boolean hasSubs() { String s = subscriptions.getString(Authentication.name, ""); return s.isEmpty(); } public static CaseInsensitiveArrayList modOf; public static ArrayList<MultiReddit> multireddits; public static HashMap<String, List<MultiReddit>> public_multireddits = new HashMap<String, List<MultiReddit>>(); public static void doOnlineSyncing() { if (Authentication.mod) { doModOf(); } doFriendsOf(); loadMultireddits(); } public static CaseInsensitiveArrayList toreturn; public static CaseInsensitiveArrayList friends = new CaseInsensitiveArrayList(); public static CaseInsensitiveArrayList syncSubscriptionsOverwrite(final Context c) { toreturn = new CaseInsensitiveArrayList(); new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { toreturn = syncSubreddits(c); toreturn = sort(toreturn); setSubscriptions(toreturn); return null; } }.execute(); if (toreturn.isEmpty()) { //failed, load defaults toreturn.addAll(defaultSubs); } return toreturn; } public static CaseInsensitiveArrayList syncSubreddits(Context c) { CaseInsensitiveArrayList toReturn = new CaseInsensitiveArrayList(); if (Authentication.isLoggedIn && NetworkUtil.isConnected(c)) { UserSubredditsPaginator pag = new UserSubredditsPaginator(Authentication.reddit, "subscriber"); pag.setLimit(100); try { while (pag.hasNext()) { for (net.dean.jraw.models.Subreddit s : pag.next()) { toReturn.add(s.getDisplayName().toLowerCase()); } } if (toReturn.isEmpty() && subscriptions.getString(Authentication.name, "") .isEmpty()) { toreturn.addAll(defaultSubs); } } catch (Exception e) { //failed; e.printStackTrace(); } addSubsToHistory(toReturn, true); return toReturn; } else { toReturn.addAll(defaultSubs); return toReturn; } } public static void syncMultiReddits(Context c) { try { multireddits = new ArrayList<>(new MultiRedditManager(Authentication.reddit).mine()); for (MultiReddit multiReddit : multireddits) { if (MainActivity.multiNameToSubsMap.containsKey( ReorderSubreddits.MULTI_REDDIT + multiReddit.getDisplayName())) { StringBuilder concatenatedSubs = new StringBuilder(); for (MultiSubreddit subreddit : multiReddit.getSubreddits()) { concatenatedSubs.append(subreddit.getDisplayName()); concatenatedSubs.append("+"); } MainActivity.multiNameToSubsMap.put( ReorderSubreddits.MULTI_REDDIT + multiReddit.getDisplayName(), concatenatedSubs.toString()); UserSubscriptions.setSubNameToProperties( ReorderSubreddits.MULTI_REDDIT + multiReddit.getDisplayName(), concatenatedSubs.toString()); } } } catch (ApiException e) { e.printStackTrace(); } } public static void setSubscriptions(CaseInsensitiveArrayList subs) { subscriptions.edit().putString(Authentication.name, Reddit.arrayToString(subs)).apply(); } public static void setPinned(CaseInsensitiveArrayList subs) { pinned.edit().putString(Authentication.name, Reddit.arrayToString(subs)).apply(); pins = null; } public static void switchAccounts() { SharedPreferences.Editor editor = Reddit.appRestart.edit(); editor.putBoolean("back", true); editor.putString("subs", ""); Authentication.authentication.edit().remove("backedCreds").remove("expires").apply(); editor.putBoolean("loggedin", Authentication.isLoggedIn); editor.putString("name", Authentication.name); editor.commit(); } /** * @return list of multireddits if they are available, null if could not fetch multireddits */ public static void getMultireddits(final MultiCallback callback) { new AsyncTask<Void, Void, List<MultiReddit>>() { @Override protected List<MultiReddit> doInBackground(Void... params) { loadMultireddits(); return multireddits; } @Override protected void onPostExecute(List<MultiReddit> multiReddits) { callback.onComplete(multiReddits); } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } public interface MultiCallback { void onComplete(List<MultiReddit> multis); } public static void loadMultireddits() { if (Authentication.isLoggedIn && Authentication.didOnline && (multireddits == null || multireddits.isEmpty())) { try { multireddits = new ArrayList<>(new MultiRedditManager(Authentication.reddit).mine()); } catch (Exception e) { multireddits = null; e.printStackTrace(); } } } /** * @return list of multireddits if they are available, null if could not fetch multireddits */ public static void getPublicMultireddits(MultiCallback callback, final String profile) { if (profile.isEmpty()) { getMultireddits(callback); } if (public_multireddits.get(profile) == null) { // It appears your own multis are pre-loaded at some point // but some other user's multis obviously can't be so // don't return until we've loaded them. loadPublicMultireddits(callback, profile); } } private static void loadPublicMultireddits(final MultiCallback callback, final String profile) { new AsyncTask<Void, Void, List<MultiReddit>>() { @Override protected List<MultiReddit> doInBackground(Void... params) { try { public_multireddits.put(profile, new ArrayList( new MultiRedditManager(Authentication.reddit).getPublicMultis(profile))); } catch (Exception e) { public_multireddits.put(profile, null); e.printStackTrace(); } return public_multireddits.get(profile); } @Override protected void onPostExecute(List<MultiReddit> multiReddits) { callback.onComplete(multiReddits); } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } private static CaseInsensitiveArrayList doModOf() { CaseInsensitiveArrayList finished = new CaseInsensitiveArrayList(); UserSubredditsPaginator pag = new UserSubredditsPaginator(Authentication.reddit, "moderator"); pag.setLimit(100); try { while (pag.hasNext()) { for (net.dean.jraw.models.Subreddit s : pag.next()) { finished.add(s.getDisplayName().toLowerCase()); } } modOf = (finished); cacheModOf(); } catch (Exception e) { //failed; e.printStackTrace(); } return finished; } public static void doFriendsOfMain(MainActivity main) { main.doFriends(doFriendsOf()); } private static List<String> doFriendsOf() { if (friends == null || friends.isEmpty()) { friends = new CaseInsensitiveArrayList(); CaseInsensitiveArrayList finished = new CaseInsensitiveArrayList(); ImportantUserPaginator pag = new ImportantUserPaginator(Authentication.reddit, "friends"); pag.setLimit(100); try { while (pag.hasNext()) { for (UserRecord s : pag.next()) { finished.add(s.getFullName()); } } friends = (finished); return friends; } catch (Exception e) { //failed; e.printStackTrace(); } } return friends; } public static MultiReddit getMultiredditByDisplayName(String displayName) { if (multireddits != null) { for (MultiReddit multiReddit : multireddits) { if (multiReddit.getDisplayName().equals(displayName)) { return multiReddit; } } } return null; } public static MultiReddit getPublicMultiredditByDisplayName(String profile, String displayName) { if (profile.isEmpty()) { return getMultiredditByDisplayName(displayName); } if (public_multireddits.get(profile) != null) { for (MultiReddit multiReddit : public_multireddits.get(profile)) { if (multiReddit.getDisplayName().equals(displayName)) { return multiReddit; } } } return null; } //Gets user subscriptions + top 500 subs + subs in history public static CaseInsensitiveArrayList getAllSubreddits(Context c) { CaseInsensitiveArrayList finalReturn = new CaseInsensitiveArrayList(); CaseInsensitiveArrayList history = getHistory(); CaseInsensitiveArrayList defaults = getDefaults(c); finalReturn.addAll(getSubscriptions(c)); for (String s : finalReturn) { if (history.contains(s)) { history.remove(s); } if (defaults.contains(s)) { defaults.remove(s); } } for (String s : history) { if (defaults.contains(s)) { defaults.remove(s); } } for (String s : history) { if (!finalReturn.contains(s)) { finalReturn.add(s); } } for (String s : defaults) { if (!finalReturn.contains(s)) { finalReturn.add(s); } } return finalReturn; } //Gets user subscriptions + top 500 subs + subs in history public static CaseInsensitiveArrayList getAllUserSubreddits(Context c) { CaseInsensitiveArrayList finalReturn = new CaseInsensitiveArrayList(); finalReturn.addAll(getSubscriptions(c)); finalReturn.removeAll(getHistory()); finalReturn.addAll(getHistory()); return finalReturn; } public static CaseInsensitiveArrayList getHistory() { String[] hist = subscriptions.getString("subhistory", "").toLowerCase().split(","); CaseInsensitiveArrayList history = new CaseInsensitiveArrayList(); Collections.addAll(history, hist); return history; } public static CaseInsensitiveArrayList getDefaults(Context c) { CaseInsensitiveArrayList history = new CaseInsensitiveArrayList(); Collections.addAll(history, c.getString(R.string.top_500_csv).split(",")); return history; } public static void addSubreddit(String s, Context c) { CaseInsensitiveArrayList subs = getSubscriptions(c); subs.add(s); if (SettingValues.alphabetizeOnSubscribe) { setSubscriptions(sortNoExtras(subs)); } else { setSubscriptions(subs); } } public static void removeSubreddit(String s, Context c) { CaseInsensitiveArrayList subs = getSubscriptions(c); subs.remove(s); setSubscriptions(subs); } public static void addPinned(String s, Context c) { CaseInsensitiveArrayList subs = getPinned(); subs.add(s); setPinned(subs); } public static void removePinned(String s, Context c) { CaseInsensitiveArrayList subs = getPinned(); subs.remove(s); setPinned(subs); } //Sets sub as "searched for", will apply to all accounts public static void addSubToHistory(String s) { String history = subscriptions.getString("subhistory", ""); if (!history.contains(s.toLowerCase())) { history += "," + s.toLowerCase(); subscriptions.edit().putString("subhistory", history).apply(); } } //Sets a list of subreddits as "searched for", will apply to all accounts public static void addSubsToHistory(ArrayList<Subreddit> s2) { String history = subscriptions.getString("subhistory", "").toLowerCase(); for (Subreddit s : s2) { if (!history.contains(s.getDisplayName().toLowerCase())) { history += "," + s.getDisplayName().toLowerCase(); } } subscriptions.edit().putString("subhistory", history).apply(); } public static void addSubsToHistory(CaseInsensitiveArrayList s2, boolean b) { String history = subscriptions.getString("subhistory", "").toLowerCase(); for (String s : s2) { if (!history.contains(s.toLowerCase())) { history += "," + s.toLowerCase(); } } subscriptions.edit().putString("subhistory", history).apply(); } public static ArrayList<Subreddit> syncSubredditsGetObject() { ArrayList<Subreddit> toReturn = new ArrayList<>(); if (Authentication.isLoggedIn) { UserSubredditsPaginator pag = new UserSubredditsPaginator(Authentication.reddit, "subscriber"); pag.setLimit(100); try { while (pag.hasNext()) { for (net.dean.jraw.models.Subreddit s : pag.next()) { toReturn.add(s); } } } catch (Exception e) { //failed; e.printStackTrace(); } addSubsToHistory(toReturn); return toReturn; } return toReturn; } public static void syncSubredditsGetObjectAsync(final Login mainActivity) { final ArrayList<Subreddit> toReturn = new ArrayList<>(); new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { if (Authentication.isLoggedIn) { UserSubredditsPaginator pag = new UserSubredditsPaginator(Authentication.reddit, "subscriber"); pag.setLimit(100); try { while (pag.hasNext()) { for (net.dean.jraw.models.Subreddit s : pag.next()) { toReturn.add(s); } } } catch (Exception e) { //failed; e.printStackTrace(); } } return null; } @Override protected void onPostExecute(Void aVoid) { mainActivity.doLastStuff(toReturn); } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } /** * Sorts the subreddit ArrayList, keeping special subreddits at the top of the list (e.g. * frontpage, all, the random subreddits). Always adds frontpage and all * * @param unsorted the ArrayList to sort * @return the sorted ArrayList * @see #sortNoExtras(CaseInsensitiveArrayList) */ public static CaseInsensitiveArrayList sort(CaseInsensitiveArrayList unsorted) { CaseInsensitiveArrayList subs = new CaseInsensitiveArrayList(unsorted); if (!subs.contains("frontpage")) { subs.add("frontpage"); } if (!subs.contains("all")) { subs.add("all"); } return sortNoExtras(subs); } /** * Sorts the subreddit ArrayList, keeping special subreddits at the top of the list (e.g. * frontpage, all, the random subreddits) * * @param unsorted the ArrayList to sort * @return the sorted ArrayList * @see #sort(CaseInsensitiveArrayList) */ public static CaseInsensitiveArrayList sortNoExtras(CaseInsensitiveArrayList unsorted) { List<String> subs = new CaseInsensitiveArrayList(unsorted); CaseInsensitiveArrayList finals = new CaseInsensitiveArrayList(); for (String subreddit : getPinned()) { if (subs.contains(subreddit)) { subs.remove(subreddit); finals.add(subreddit); } } for (String subreddit : specialSubreddits) { if (subs.contains(subreddit)) { subs.remove(subreddit); finals.add(subreddit); } } java.util.Collections.sort(subs, String.CASE_INSENSITIVE_ORDER); finals.addAll(subs); return finals; } public static boolean isSubscriber(String s, Context c) { return getSubscriptions(c).contains(s.toLowerCase()); } public static class SubscribeTask extends AsyncTask<String, Void, Void> { Context context; public SubscribeTask(Context context){ this.context = context; } @Override protected Void doInBackground(String... subreddits) { final AccountManager m = new AccountManager(Authentication.reddit); for (String subreddit : subreddits) { try { m.subscribe(Authentication.reddit.getSubreddit(subreddit)); } catch(Exception e){ Toast.makeText(context, "Couldn't subscribe, subreddit is private, quarantined, or invite only", Toast.LENGTH_SHORT).show(); } } return null; } } public static class UnsubscribeTask extends AsyncTask<String, Void, Void> { @Override protected Void doInBackground(String... subreddits) { final AccountManager m = new AccountManager(Authentication.reddit); try { for (String subreddit : subreddits) { m.unsubscribe(Authentication.reddit.getSubreddit(subreddit)); } } catch(Exception e){ } return null; } } }