import std/[algorithm, unicode, re, strutils] import jsony import utils, slices import ../types/user as userType from ../../types import User, Error let unRegex = re"(^|[^A-z0-9-_./?])@([A-z0-9_]{1,15})" unReplace = "$1@$2" htRegex = re"(^|[^\w-_./?])([##$])([\w_]+)" htReplace = "$1$2$3" proc expandUserEntities(user: var User; raw: RawUser) = let orig = user.bio.toRunes ent = raw.entities if ent.url.urls.len > 0: user.website = ent.url.urls[0].expandedUrl var replacements = newSeq[ReplaceSlice]() for u in ent.description.urls: replacements.extractUrls(u, orig.high) replacements.dedupSlices replacements.sort(cmp) user.bio = orig.replacedWith(replacements, 0 .. orig.len) .replacef(unRegex, unReplace) .replacef(htRegex, htReplace) proc getBanner(user: RawUser): string = if user.profileBannerUrl.len > 0: return user.profileBannerUrl & "/1500x500" if user.profileLinkColor.len > 0: return '#' & user.profileLinkColor proc toUser*(raw: RawUser): User = result = User( id: raw.idStr, username: raw.screenName, fullname: raw.name, location: raw.location, bio: raw.description, following: raw.friendsCount, followers: raw.followersCount, tweets: raw.statusesCount, likes: raw.favouritesCount, media: raw.mediaCount, verified: raw.verified, protected: raw.protected, joinDate: parseTwitterDate(raw.createdAt), banner: getBanner(raw), userPic: getImageUrl(raw.profileImageUrlHttps).replace("_normal", "") ) if raw.pinnedTweetIdsStr.len > 0: result.pinnedTweet = parseBiggestInt(raw.pinnedTweetIdsStr[0]) result.expandUserEntities(raw) proc parseUser*(json: string; username=""): User = handleErrors: case error.code of suspended: return User(username: username, suspended: true) of userNotFound: return else: echo "[error - parseUser]: ", error result = toUser json.fromJson(RawUser)