package me.ccrama.redditslide; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.net.Uri; import java.net.MalformedURLException; import java.util.Arrays; import me.ccrama.redditslide.Activities.CommentsScreenSingle; import me.ccrama.redditslide.Activities.LiveThread; import me.ccrama.redditslide.Activities.Profile; import me.ccrama.redditslide.Activities.Search; import me.ccrama.redditslide.Activities.SendMessage; import me.ccrama.redditslide.Activities.SubredditView; import me.ccrama.redditslide.Activities.Website; import me.ccrama.redditslide.Activities.Wiki; import me.ccrama.redditslide.Visuals.Palette; import me.ccrama.redditslide.util.LinkUtil; import me.ccrama.redditslide.util.LogUtil; public class OpenRedditLink { public OpenRedditLink(Context context, String url) { openUrl(context, url, true); } public OpenRedditLink(Context context, String url, boolean openIfOther) { openUrl(context, url, openIfOther); } //Returns true if link was in fact handled by this method. If false, further action should be taken public static boolean openUrl(Context context, String url, boolean openIfOther) { String oldUrl = url; boolean np = false; LogUtil.v("Link is " + url); url = formatRedditUrl(url); if (url.isEmpty()) { LinkUtil.openExternally(oldUrl, context, false); return false; } else if (url.startsWith("np")) { np = true; url = url.substring(2); } RedditLinkType type = getRedditLinkType(url); String[] parts = url.split("/"); String endParameters = ""; if (parts[parts.length - 1].startsWith("?")) { endParameters = parts[parts.length - 1]; parts = Arrays.copyOf(parts, parts.length - 1); } switch (type) { case SHORTENED: { Intent i = new Intent(context, CommentsScreenSingle.class); i.putExtra(CommentsScreenSingle.EXTRA_SUBREDDIT, Reddit.EMPTY_STRING); i.putExtra(CommentsScreenSingle.EXTRA_CONTEXT, Reddit.EMPTY_STRING); i.putExtra(CommentsScreenSingle.EXTRA_NP, np); i.putExtra(CommentsScreenSingle.EXTRA_SUBMISSION, parts[1]); context.startActivity(i); break; } case LIVE: { Intent i = new Intent(context, LiveThread.class); i.putExtra(LiveThread.EXTRA_LIVEURL, parts[2]); context.startActivity(i); } break; case WIKI: { Intent i = new Intent(context, Wiki.class); i.putExtra(Wiki.EXTRA_SUBREDDIT, parts[2]); String page; if (parts.length >= 5) { page = parts[4]; if (page.contains("#")) { page = page.substring(0, page.indexOf("#")); } i.putExtra(Wiki.EXTRA_PAGE, page); } context.startActivity(i); break; } case SEARCH: { Intent i = new Intent(context, Search.class); String end = parts[parts.length - 1]; end = end.replace(":", "%3A"); boolean restrictSub = end.contains("restrict_sr=on"); if (restrictSub) { i.putExtra(Search.EXTRA_SUBREDDIT, parts[2]); } else { i.putExtra(Search.EXTRA_SUBREDDIT, "all"); } Uri urlParams = Uri.parse(oldUrl); if (urlParams.getQueryParameterNames().contains("q")) { i.putExtra(Search.EXTRA_TERM, urlParams.getQueryParameter("q")); } if (urlParams.getQueryParameterNames().contains("author")) { i.putExtra(Search.EXTRA_AUTHOR, urlParams.getQueryParameter("author")); } if (urlParams.getQueryParameterNames().contains("nsfw")) { i.putExtra(Search.EXTRA_NSFW, urlParams.getQueryParameter("nsfw").equals("yes")); } if (urlParams.getQueryParameterNames().contains("self")) { i.putExtra(Search.EXTRA_SELF, urlParams.getQueryParameter("self").equals("yes")); } if (urlParams.getQueryParameterNames().contains("selftext")) { i.putExtra(Search.EXTRA_SELF, urlParams.getQueryParameter("selftext").equals("yes")); } if (urlParams.getQueryParameterNames().contains("url")) { i.putExtra(Search.EXTRA_URL, urlParams.getQueryParameter("url")); } if (urlParams.getQueryParameterNames().contains("site")) { i.putExtra(Search.EXTRA_SITE, urlParams.getQueryParameter("site")); } context.startActivity(i); break; } case COMMENT_PERMALINK: { Intent i = new Intent(context, CommentsScreenSingle.class); i.putExtra(CommentsScreenSingle.EXTRA_SUBREDDIT, parts[2]); i.putExtra(CommentsScreenSingle.EXTRA_SUBMISSION, parts[4]); i.putExtra(CommentsScreenSingle.EXTRA_NP, np); if (parts.length >= 7) { i.putExtra(CommentsScreenSingle.EXTRA_LOADMORE, true); String end = parts[6]; String endCopy = end; if (end.contains("?")) end = end.substring(0, end.indexOf("?")); if (end.length() >= 3) i.putExtra(CommentsScreenSingle.EXTRA_CONTEXT, end); if (endCopy.contains("?context=") || !endParameters.isEmpty()) { if (!endParameters.isEmpty()) { endCopy = endParameters; } LogUtil.v("Adding end params"); try { int contextNumber = Integer.valueOf( endCopy.substring(endCopy.indexOf("?context=") + 9, endCopy.length())); i.putExtra(CommentsScreenSingle.EXTRA_CONTEXT_NUMBER, contextNumber); } catch (Exception ignored) { } } } context.startActivity(i); break; } case SUBMISSION: { Intent i = new Intent(context, CommentsScreenSingle.class); i.putExtra(CommentsScreenSingle.EXTRA_SUBREDDIT, parts[2]); i.putExtra(CommentsScreenSingle.EXTRA_CONTEXT, Reddit.EMPTY_STRING); i.putExtra(CommentsScreenSingle.EXTRA_NP, np); i.putExtra(CommentsScreenSingle.EXTRA_SUBMISSION, parts[4]); context.startActivity(i); break; } case SUBMISSION_WITHOUT_SUB: { Intent i = new Intent(context, CommentsScreenSingle.class); i.putExtra(CommentsScreenSingle.EXTRA_SUBREDDIT, Reddit.EMPTY_STRING); i.putExtra(CommentsScreenSingle.EXTRA_CONTEXT, Reddit.EMPTY_STRING); i.putExtra(CommentsScreenSingle.EXTRA_NP, np); i.putExtra(CommentsScreenSingle.EXTRA_SUBMISSION, parts[2]); context.startActivity(i); break; } case SUBREDDIT: { Intent intent = new Intent(context, SubredditView.class); intent.putExtra(SubredditView.EXTRA_SUBREDDIT, parts[2]); context.startActivity(intent); break; } case MESSAGE: { Intent i = new Intent(context, SendMessage.class); try { Uri urlParams = Uri.parse(oldUrl); if (urlParams.getQueryParameterNames().contains("to")) { i.putExtra(SendMessage.EXTRA_NAME, urlParams.getQueryParameter("to")); } if (urlParams.getQueryParameterNames().contains("subject")) { i.putExtra(SendMessage.EXTRA_SUBJECT, urlParams.getQueryParameter("subject")); } if (urlParams.getQueryParameterNames().contains("message")) { i.putExtra(SendMessage.EXTRA_MESSAGE, urlParams.getQueryParameter("message")); } context.startActivity(i); } catch (Exception e) { e.printStackTrace(); } break; } case USER: { String name = parts[2]; if (name.equals("me") && Authentication.isLoggedIn) name = Authentication.name; Intent myIntent = new Intent(context, Profile.class); myIntent.putExtra(Profile.EXTRA_PROFILE, name); context.startActivity(myIntent); break; } case OTHER: { if (openIfOther) { if (context instanceof Activity) { LinkUtil.openUrl(oldUrl, Palette.getStatusBarColor(), (Activity) context); } else { Intent i = new Intent(context, Website.class); i.putExtra(Website.EXTRA_URL, oldUrl); context.startActivity(i); } } else { return false; } break; } } return true; } public OpenRedditLink(Context c, String submission, String subreddit, String id) { Intent i = new Intent(c, CommentsScreenSingle.class); i.putExtra(CommentsScreenSingle.EXTRA_SUBREDDIT, subreddit); i.putExtra(CommentsScreenSingle.EXTRA_CONTEXT, id); i.putExtra(CommentsScreenSingle.EXTRA_SUBMISSION, submission); c.startActivity(i); } /** * Takes an reddit.com url and formats it for easier use * * @param url The url to format * @return Formatted url without subdomains, language tags & other unused prefixes */ public static String formatRedditUrl(String url) { if(url == null){ return ""; } // Strip unused prefixes that don't require special handling url = url.replaceFirst("(?i)^(https?://)?(www\\.)?((ssl|pay|amp)\\.)?", ""); if (url.matches("(?i)[a-z0-9-_]+\\.reddit\\.com.*")) { // tests for subdomain String subdomain = url.split("\\.", 2)[0]; String domainRegex = "(?i)" + subdomain + "\\.reddit\\.com"; if (subdomain.equalsIgnoreCase("np")) { // no participation link: https://www.reddit.com/r/NoParticipation/wiki/index url = url.replaceFirst(domainRegex, "reddit.com"); url = "np" + url; } else if (subdomain.matches("beta|blog|code|mod|out|store")) { return ""; } else if (subdomain.matches("(?i)([_a-z0-9]{2}-)?[_a-z0-9]{1,2}")) { /* Either the subdomain is a language tag (with optional region) or a single letter domain, which for simplicity are ignored. */ url = url.replaceFirst(domainRegex, "reddit.com"); } else { // subdomain is a subreddit, change subreddit.reddit.com to reddit.com/r/subreddit url = url.replaceFirst(domainRegex, "reddit.com/r/" + subdomain); } } if (url.startsWith("/")) url = "reddit.com" + url; if (url.endsWith("/")) url = url.substring(0, url.length() - 1); // Converts links such as reddit.com/help to reddit.com/r/reddit.com/wiki if (url.matches("(?i)[^/]++/(?>wiki|help)(?>$|/.*)")) { url = url.replaceFirst("(?i)/(?>wiki|help)", "/r/reddit.com/wiki"); } return url; } /** * Determines the reddit link type * * @param url Reddit.com link * @return LinkType */ public static RedditLinkType getRedditLinkType(String url) { if (url.matches("(?i)redd\\.it/\\w+")) { // Redd.it link. Format: redd.it/post_id return RedditLinkType.SHORTENED; } else if (url.matches("(?i)reddit\\.com/live/[^/]*")) { return RedditLinkType.LIVE; } else if (url.matches("(?i)reddit\\.com/message/compose.*")) { return RedditLinkType.MESSAGE; } else if (url.matches("(?i)reddit\\.com(?:/r/[a-z0-9-_.]+)?/(?:wiki|help).*")) { // Wiki link. Format: reddit.com/r/$subreddit/wiki/$page [optional] return RedditLinkType.WIKI; } else if (url.matches("(?i)reddit\\.com/r/[a-z0-9-_.]+/about.*")) { // Unhandled link. Format: reddit.com/r/$subreddit/about/$page [optional] return RedditLinkType.OTHER; } else if (url.matches("(?i)reddit\\.com/r/[a-z0-9-_.]+/search.*")) { // Wiki link. Format: reddit.com/r/$subreddit/search?q= [optional] return RedditLinkType.SEARCH; } else if (url.matches("(?i)reddit\\.com/r/[a-z0-9-_.]+/comments/\\w+/\\w*/.*")) { // Permalink to comments. Format: reddit.com/r/$subreddit/comments/$post_id/$post_title [can be empty]/$comment_id return RedditLinkType.COMMENT_PERMALINK; } else if (url.matches("(?i)reddit\\.com/r/[a-z0-9-_.]+/comments/\\w+.*")) { // Submission. Format: reddit.com/r/$subreddit/comments/$post_id/$post_title [optional] return RedditLinkType.SUBMISSION; } else if (url.matches("(?i)reddit\\.com/comments/\\w+.*")) { // Submission without a given subreddit. Format: reddit.com/comments/$post_id/$post_title [optional] return RedditLinkType.SUBMISSION_WITHOUT_SUB; } else if (url.matches("(?i)reddit\\.com/r/[a-z0-9-_.]+.*")) { // Subreddit. Format: reddit.com/r/$subreddit/$sort [optional] return RedditLinkType.SUBREDDIT; } else if (url.matches("(?i)reddit\\.com/u(?:ser)?/[a-z0-9-_]+.*")) { // User. Format: reddit.com/u [or user]/$username/$page [optional] return RedditLinkType.USER; } else { //Open all links that we can't open in another app return RedditLinkType.OTHER; } } public enum RedditLinkType { SHORTENED, WIKI, COMMENT_PERMALINK, SUBMISSION, SUBMISSION_WITHOUT_SUB, SUBREDDIT, USER, SEARCH, MESSAGE, MULTIREDDIT, LIVE, OTHER } }