/******************************************************************************* * This file is part of RedReader. * * RedReader 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. * * RedReader 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 RedReader. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package org.quantumbadger.redreader.reddit.things; import android.os.Parcel; import android.os.Parcelable; import org.apache.commons.lang3.StringEscapeUtils; import org.quantumbadger.redreader.common.General; import org.quantumbadger.redreader.common.UnexpectedInternalStateException; import org.quantumbadger.redreader.io.WritableObject; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; public class RedditSubreddit implements Parcelable, Comparable<RedditSubreddit>, WritableObject<String> { public String getKey() { try { return getCanonicalName(); } catch(InvalidSubredditNameException e) { throw new UnexpectedInternalStateException(String.format(Locale.US, "Cannot save subreddit '%s'", url)); } } public long getTimestamp() { return downloadTime; } @WritableObjectVersion public static int DB_VERSION = 1; public static final class InvalidSubredditNameException extends Exception { public InvalidSubredditNameException(String subredditName) { super(String.format(Locale.US, "Invalid subreddit name '%s'.", subredditName == null ? "NULL" : subredditName)); } } @WritableField public String header_img, header_title; @WritableField public String description, description_html, public_description; @WritableField public String id, name, title, display_name, url; @WritableField public long created, created_utc; @WritableField public Integer accounts_active, subscribers; @WritableField public boolean over18; @WritableObjectTimestamp public long downloadTime; private static final Pattern NAME_PATTERN = Pattern.compile("(/)?(r/)?([\\w\\+\\-\\.:]+)/?"); public RedditSubreddit(CreationData creationData) { this(); downloadTime = creationData.timestamp; } public static String stripRPrefix(String name) throws InvalidSubredditNameException { final Matcher matcher = NAME_PATTERN.matcher(name); if(matcher.matches()) { return matcher.group(3); } else { throw new InvalidSubredditNameException(name); } } /** * @param name a subreddit name in the form "subreddit", "r/subreddit" or "/r/subreddit" (case-insensitive) * @return a subreddit name in the form "/r/subreddit" (lower-cased) * @throws InvalidSubredditNameException if {@code name} is null or not in the expected format */ public static String getCanonicalName(String name) throws InvalidSubredditNameException { return "/r/" + General.asciiLowercase(stripRPrefix(name)); } public String getCanonicalName() throws InvalidSubredditNameException { return getCanonicalName(url); } public static String getDisplayNameFromCanonicalName(String canonicalName) { return canonicalName.substring(3); } public int describeContents() { return 0; } public void writeToParcel(final Parcel out, final int flags) { out.writeString(header_img); out.writeString(header_title); out.writeString(description); out.writeString(description_html); out.writeString(public_description); out.writeString(id); out.writeString(name); out.writeString(title); out.writeString(display_name); out.writeString(url); out.writeLong(created); out.writeLong(created_utc); out.writeInt(accounts_active == null ? -1 : accounts_active); out.writeInt(subscribers == null ? -1 : subscribers); out.writeInt(over18 ? 1 : 0); } public RedditSubreddit() {} public RedditSubreddit(String url, String title, final boolean isSortable) { this.url = url; this.title = title; } public RedditSubreddit(final Parcel parcel) { header_img = parcel.readString(); header_title = parcel.readString(); description = parcel.readString(); description_html = parcel.readString(); public_description = parcel.readString(); id = parcel.readString(); name = parcel.readString(); title = parcel.readString(); display_name = parcel.readString(); url = parcel.readString(); created = parcel.readLong(); created_utc = parcel.readLong(); accounts_active = parcel.readInt(); subscribers = parcel.readInt(); if(accounts_active < 0) accounts_active = null; if(subscribers < 0) subscribers = null; over18 = parcel.readInt() == 1; } public static final Parcelable.Creator<RedditSubreddit> CREATOR = new Parcelable.Creator<RedditSubreddit>() { public RedditSubreddit createFromParcel(final Parcel in) { return new RedditSubreddit(in); } public RedditSubreddit[] newArray(final int size) { return new RedditSubreddit[size]; } }; public int compareTo(final RedditSubreddit another) { return General.asciiLowercase(display_name).compareTo(General.asciiLowercase(another.display_name)); } public String getSidebarHtml(boolean nightMode) { final String unescaped = StringEscapeUtils.unescapeHtml4(description_html); final StringBuilder result = new StringBuilder(unescaped.length() + 512); result.append("<html>"); result.append("<head>"); result.append("<meta name=\"viewport\" content=\"width=device-width, user-scalable=yes\">"); if(nightMode) { result.append("<style>"); result.append("body {color: white; background-color: black;}"); result.append("a {color: #3399FF; background-color: 000033;}"); result.append("</style>"); } result.append("</head>"); result.append("<body>"); result.append(unescaped); result.append("</body>"); result.append("</html>"); return result.toString(); } }