package com.vaguehope.onosendai.update;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.Callable;
import java.util.regex.Pattern;
import android.text.Spanned;
import com.vaguehope.onosendai.model.Meta;
import com.vaguehope.onosendai.model.MetaType;
import com.vaguehope.onosendai.provider.twitter.TwitterUrls;
import com.vaguehope.onosendai.storage.CachedStringGroup;
import com.vaguehope.onosendai.storage.DbInterface;
import com.vaguehope.onosendai.util.HtmlTitleParser;
import com.vaguehope.onosendai.util.HttpHelper;
import com.vaguehope.onosendai.util.HttpHelper.FinalUrlHandler;
import com.vaguehope.onosendai.util.HttpHelper.TooManyRedirectsException;
import com.vaguehope.onosendai.util.LogWrapper;
public class FetchLinkTitle implements Callable<Void> {
public interface FetchTitleListener {
void onLinkTitle (Meta m, String title, URL finalUrl) throws IOException;
}
private static final Pattern UNTITLEABLE_URL = Pattern.compile("^.*\\.(mp[0-9]|m3u8|mov|webm|mpd|jpe?g|png|gif|pdf)$", Pattern.CASE_INSENSITIVE);
private static final LogWrapper LOG = new LogWrapper("FLT");
public static boolean shouldFetchTitle (final Meta m) {
return m.getType() == MetaType.URL &&
m.getData() != null &&
TwitterUrls.readTweetSidFromUrl(m.getData()) == null &&
!UNTITLEABLE_URL.matcher(m.getData()).matches();
}
public static boolean isTitleCached (final DbInterface db, final Meta meta) {
return db.cachedString(CachedStringGroup.LINK_DEST_URL, meta.getData()) != null
|| db.cachedString(CachedStringGroup.LINK_TITLE, meta.getData()) != null;
}
public static void fetchTitle (final DbInterface db, final Meta m, final FetchTitleListener l) throws IOException {
final String cachedTitle = db.cachedString(CachedStringGroup.LINK_TITLE, m.getData());
final String cachedDestUrl = db.cachedString(CachedStringGroup.LINK_DEST_URL, m.getData());
if (cachedTitle != null || cachedDestUrl != null) {
if (l != null) l.onLinkTitle(m, cachedTitle, cachedDestUrl != null ? new URL(cachedDestUrl) : null);
}
else {
final FinalUrlHandler<Spanned> handler = new FinalUrlHandler<Spanned>(HtmlTitleParser.INSTANCE);
try {
final CharSequence title = HttpHelper.get(m.getData(), handler);
final String finalUrl = handler.getUrl().toString();
LOG.i("%s: '%s' %s.", m.getData(), title, finalUrl);
if (l != null) l.onLinkTitle(m, title != null ? title.toString() : null, handler.getUrl());
if (title != null) {
db.cacheString(CachedStringGroup.LINK_TITLE, m.getData(), title.toString());
}
db.cacheString(CachedStringGroup.LINK_DEST_URL, m.getData(), finalUrl);
}
catch (final TooManyRedirectsException e) {
final String lastUrl = e.getLastUrl().toString();
LOG.w("%s: too many redirects, stopped at: %s.", m.getData(), lastUrl);
if (l != null) l.onLinkTitle(m, null, handler.getUrl());
db.cacheString(CachedStringGroup.LINK_DEST_URL, m.getData(), lastUrl);
}
}
}
public static void setTitle (final DbInterface db, final Meta m, final String title) {
db.cacheString(CachedStringGroup.LINK_TITLE, m.getData(), title);
}
private final DbInterface db;
private final Meta meta;
public FetchLinkTitle (final DbInterface db, final Meta meta) {
if (db == null) throw new IllegalArgumentException("db can not be null.");
if (meta == null) throw new IllegalArgumentException("meta can not be null.");
if (meta.getData() == null) throw new IllegalArgumentException("meta.data can not be null.");
this.db = db;
this.meta = meta;
}
@Override
public Void call () throws Exception {
fetchTitle(this.db, this.meta, null);
return null;
}
}