package net.dev123.mblog.tencent;
import static net.dev123.commons.util.ParseUtil.escapeAngleBrackets;
import static net.dev123.commons.util.ParseUtil.getInt;
import static net.dev123.commons.util.ParseUtil.getLong;
import static net.dev123.commons.util.ParseUtil.getRawString;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.dev123.commons.PagableList;
import net.dev123.commons.ServiceProvider;
import net.dev123.commons.util.ParseUtil;
import net.dev123.commons.util.StringUtil;
import net.dev123.exception.ExceptionCode;
import net.dev123.exception.LibException;
import net.dev123.mblog.Emotions;
import net.dev123.mblog.entity.Status;
import net.dev123.mblog.entity.User;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* TencentStatusAdaptor
*
* @version
* @author 马庆升
* @time 2010-8-31 上午01:06:38
*/
public class TencentStatusAdaptor {
private static final Pattern HREF_PATTERN = Pattern.compile("<a href=\"http://url\\.cn/[a-zA-Z0-9]+\" target=\"_blank\">(http://url\\.cn/[a-zA-Z0-9]+)</a>");
/**
* 从JSON字符串创建Status对象
*
* @param jsonString
* JSON字符串
* @return Status对象
* @throws LibException
*/
public static Status createStatus(String jsonString) throws LibException {
try {
JSONObject json = new JSONObject(jsonString);
return createStatus(json);
} catch (JSONException e) {
throw new LibException(ExceptionCode.JSON_PARSE_ERROR, e);
}
}
/**
* 从JSON字符串创建Status列表
*
* @param jsonString
* JSON字符串
* @return Status对象列表
* @throws LibException
*/
public static ArrayList<Status> createStatusList(String jsonString) throws LibException {
try {
if ("[]".equals(jsonString) || "{}".equals(jsonString)) {
return new ArrayList<Status>(0);
}
JSONArray jsonList = new JSONArray(jsonString);
int size = jsonList.length();
ArrayList<Status> statusList = new ArrayList<Status>(size);
for (int i = 0; i < size; i++) {
statusList.add(createStatus(jsonList.getJSONObject(i)));
}
return statusList;
} catch (JSONException e) {
throw new LibException(ExceptionCode.JSON_PARSE_ERROR, e);
}
}
public static PagableList<Status> createPagableStatusList(String jsonString) throws LibException {
try {
if ("[]".equals(jsonString) || "{}".equals(jsonString)) {
return new PagableList<Status>(0, -1, 0L);
}
JSONObject json = new JSONObject(jsonString);
if (!json.has("info")) {
return new PagableList<Status>(0, -1, 0L);
}
JSONArray jsonList = json.getJSONArray("info");
int hasNext = ParseUtil.getInt("hasnext", json);
long nextCursor = 1L; // 下一页
long previousCursor = 2L; // 上一页
if (hasNext == 1) {
//timeline接口,1表示数据已拉取完毕
nextCursor = 0L;
}
Map<String, String> nickToNameMap = new HashMap<String, String>();
JSONObject usernames = json.getJSONObject("user");
Iterator<?> iterator = usernames.keys();
while (iterator.hasNext()) {
String key = iterator.next().toString();
nickToNameMap.put(key, getRawString(key, usernames));
}
int size = jsonList.length();
PagableList<Status> statusList = new PagableList<Status>(size, previousCursor, nextCursor);
for (int i = 0; i < size; i++) {
Status status = createStatus(jsonList.getJSONObject(i));
//attachScreenName(status, nickToNameMap);
statusList.add(status);
}
return statusList;
} catch (JSONException e) {
throw new LibException(ExceptionCode.JSON_PARSE_ERROR, e);
}
}
public static PagableList<Status> createStatusSearchResult(String jsonString) throws LibException {
try {
if ("[]".equals(jsonString) || "{}".equals(jsonString)) {
return new PagableList<Status>(0, -1, 0L);
}
JSONObject json = new JSONObject(jsonString);
JSONArray jsonList = json.getJSONArray("info");
int hasNext = ParseUtil.getInt("hasnext", json);
long nextCursor = 1L; // 下一页
long previousCursor = 2L; // 上一页
if (hasNext == 2) {
//1表示数据还有下一页,可以下翻,
//2表示数据已经到最后一页,可以上翻
//3表示上下都可以翻
//数据已拉取完毕
nextCursor = 0L;
}
Map<String, String> nickToNameMap = new HashMap<String, String>();
JSONObject usernames = json.getJSONObject("user");
Iterator<?> iterator = usernames.keys();
while (iterator.hasNext()){
String key = iterator.next().toString();
nickToNameMap.put(key, getRawString(key, usernames));
}
int size = jsonList.length();
PagableList<Status> statusList = new PagableList<Status>(size, previousCursor, nextCursor);
for (int i = 0; i < size; i++) {
Status status = createStatus(jsonList.getJSONObject(i));
//attachScreenName(status, nickToNameMap);
statusList.add(status);
}
return statusList;
} catch (JSONException e) {
throw new LibException(ExceptionCode.JSON_PARSE_ERROR, e);
}
}
/**
* 从JSON对象创建Status对象,包级别访问控制
*
* @param json
* JSON对象
* @return Status对象
* @throws LibException
*/
static Status createStatus(JSONObject json) throws LibException {
try {
Status status = new Status();
status.setId(getRawString("id", json));
String text = getRawString("text", json);
//因腾讯的微博内容中的链接地址是HTML代码,此处去掉HTML代码
text = text.replaceAll(HREF_PATTERN.pattern(), "$1");
text = Emotions.normalizeEmotion(ServiceProvider.Tencent, text);
status.setText(escapeAngleBrackets(text));
status.setSource(getRawString("from", json));
status.setCreatedAt(new Date(getLong("timestamp", json) * 1000L));
status.setTruncated(false);
status.setInReplyToStatusId(null);
status.setInReplyToUserId(null);
status.setFavorited(false);
status.setInReplyToScreenName(null);
status.setRetweetCount(getInt("count", json));
status.setCommentCount(getInt("mcount", json));
if (!json.isNull("source")) { //源微博
status.setRetweetedStatus(createStatus(json.getJSONObject("source")));
}
User user = new User();
user.setServiceProvider(ServiceProvider.Tencent);
user.setName(getRawString("name", json));
user.setId(user.getName());
user.setScreenName(getRawString("nick", json));
user.setLocation(getRawString("location", json));
user.setVerified(getInt("isvip", json) == 1);
String head = getRawString("head", json);
if (StringUtil.isNotEmpty(head)) {
user.setProfileImageUrl(head + "/50");
}
status.setUser(user);
if (!json.isNull("image")) {
String imageString = getRawString("image", json);
String[] images = imageString.replaceAll("[\"\\[\\]]", "").replace("\\/", "/").split(",");
String image = images[0];
if (StringUtil.isNotEmpty(image)) {
status.setThumbnailPicture(image + "/160");
status.setMiddlePicture(image + "/460");
status.setOriginalPicture(image + "/2000");
}
}
if (StringUtil.isEmpty(status.getText())) {
//若微博内容为空
if (status.getRetweetedStatus() != null) {
//转发微博的时候,则自动补上“转发微博”
status.setText("转发微博");
} else if (status.getThumbnailPicture() != null) {
status.setText("分享图片");
}
}
status.setServiceProvider(ServiceProvider.Tencent);
return status;
} catch (JSONException e) {
throw new LibException(ExceptionCode.JSON_PARSE_ERROR, e);
}
}
private static void attachScreenName(Status status, Map<String, String> nameToNickMap){
if (status == null || nameToNickMap == null || nameToNickMap.size() == 0) {
return;
}
String text = status.getText();
Matcher matcher = NAME_PATTERN.matcher(text);
StringBuffer attached = new StringBuffer();
while (matcher.find()) {
String nick = nameToNickMap.get(matcher.group(1));
if (nick != null) {
matcher.appendReplacement(attached, String.format(NAME_LINK_FORMAT, matcher.group(), nick));
}
}
matcher.appendTail(attached);
status.setText(attached.toString());
attachScreenName(status.getRetweetedStatus(), nameToNickMap);
}
private static final Pattern NAME_PATTERN = Pattern.compile("@([a-zA-Z][a-zA-Z0-9_-]{1,19})");
private static final String NAME_LINK_FORMAT = "<a href=\"%1$s\">%2$s</a>";
public static void main(String[] args) {
String imageString = "[\"http:\\/\\/app.qpic.cn\\/mblogpic\\/dde803014c13e28511ac\", \"http:\\/\\/app.qpic.cn\\/mblogpic\\/c10550dcfb2efdea79da\",\"http:\\/\\/app.qpic.cn\\/mblogpic\\/5bf5b33e6b1fe82046de\",\"http:\\/\\/app.qpic.cn\\/mblogpic\\/e114d3764063ab3056d6\",\"http:\\/\\/app.qpic.cn\\/mblogpic\\/15ee33b4849e59bf2f68\",\"http:\\/\\/app.qpic.cn\\/mblogpic\\/bf753c29d789cba26a1e\",\"http:\\/\\/app.qpic.cn\\/mblogpic\\/820c8b1b858393f83da0\",\"http:\\/\\/app.qpic.cn\\/mblogpic\\/ac331753b7f0fd07de6c\",\"http:\\/\\/app.qpic.cn\\/mblogpic\\/4100a8f1a642600b91e2\"]";
String[] images = imageString.replaceAll("[\"\\[\\]]", "").replace("\\/", "/").split(",");
for (String url : images) {
System.out.println(url.trim());
}
}
}