nitter/src/experimental/parser/user.nim

88 lines
2.6 KiB
Nim
Raw Normal View History

2022-02-14 09:20:32 +01:00
import std/[algorithm, unicode, re, strutils, strformat, options, nre]
2022-01-16 06:00:11 +01:00
import jsony
import utils, slices
import ../types/user as userType
from ../../types import Result, User, Error
2022-01-16 06:00:11 +01:00
let
2022-02-14 09:20:32 +01:00
unRegex = re.re"(^|[^A-z0-9-_./?])@([A-z0-9_]{1,15})"
2022-01-16 06:00:11 +01:00
unReplace = "$1<a href=\"/$2\">@$2</a>"
2022-02-14 09:38:46 +01:00
htRegex = nre.re"""(*U)(^|[^\w-_.?])([#$])([\w_]*+)(?!</a>|">|#)"""
2022-01-16 06:00:11 +01:00
htReplace = "$1<a href=\"/search?q=%23$3\">$2$3</a>"
proc expandUserEntities(user: var User; raw: RawUser) =
2022-01-16 06:00:11 +01:00
let
orig = user.bio.toRunes
ent = raw.entities
2022-01-16 06:00:11 +01:00
if ent.url.urls.len > 0:
user.website = ent.url.urls[0].expandedUrl
2022-01-16 06:00:11 +01:00
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)
2022-02-14 09:20:32 +01:00
.replace(htRegex, htReplace)
2022-01-16 06:00:11 +01:00
proc getBanner(user: RawUser): string =
2022-01-16 06:00:11 +01:00
if user.profileBannerUrl.len > 0:
return user.profileBannerUrl & "/1500x500"
2022-01-16 06:00:11 +01:00
if user.profileLinkColor.len > 0:
return '#' & user.profileLinkColor
2022-01-26 20:27:11 +01:00
if user.profileImageExtensions.isSome:
let ext = get(user.profileImageExtensions)
if ext.mediaColor.r.ok.palette.len > 0:
let color = ext.mediaColor.r.ok.palette[0].rgb
return &"#{color.red:02x}{color.green:02x}{color.blue:02x}"
2022-01-26 17:24:03 +01:00
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 =
2022-01-16 06:00:11 +01:00
handleErrors:
2022-01-16 18:28:40 +01:00
case error.code
of suspended: return User(username: username, suspended: true)
2022-01-16 06:00:11 +01:00
of userNotFound: return
else: echo "[error - parseUser]: ", error
2022-01-26 17:24:03 +01:00
result = toUser json.fromJson(RawUser)
proc parseUsers*(json: string; after=""): Result[User] =
result = Result[User](beginning: after.len == 0)
# starting with '{' means it's an error
if json[0] == '[':
let raw = json.fromJson(seq[RawUser])
for user in raw:
result.content.add user.toUser