1 package net.pterodactylus.sone.web.ajax
3 import com.fasterxml.jackson.databind.JsonNode
4 import com.fasterxml.jackson.databind.ObjectMapper
5 import net.pterodactylus.sone.core.ElementLoader
6 import net.pterodactylus.sone.core.LinkedElement
7 import net.pterodactylus.sone.data.Post
8 import net.pterodactylus.sone.data.PostReply
9 import net.pterodactylus.sone.data.Sone
10 import net.pterodactylus.sone.data.SoneOptions
11 import net.pterodactylus.sone.freenet.L10nFilter
12 import net.pterodactylus.sone.template.SoneAccessor
13 import net.pterodactylus.sone.text.TimeTextConverter
14 import net.pterodactylus.sone.utils.jsonObject
15 import net.pterodactylus.sone.utils.toArray
16 import net.pterodactylus.sone.web.WebInterface
17 import net.pterodactylus.sone.web.page.*
18 import java.text.SimpleDateFormat
19 import java.util.TimeZone
20 import javax.inject.Inject
23 * The “get status” AJAX handler returns all information that is necessary to
24 * update the web interface in real-time.
26 @ToadletPath("getStatus.ajax")
27 class GetStatusAjaxPage(webInterface: WebInterface, private val elementLoader: ElementLoader, private val timeTextConverter: TimeTextConverter, private val l10nFilter: L10nFilter, timeZone: TimeZone):
28 JsonPage(webInterface) {
30 @Inject constructor(webInterface: WebInterface, elementLoader: ElementLoader, timeTextConverter: TimeTextConverter, l10nFilter: L10nFilter):
31 this(webInterface, elementLoader, timeTextConverter, l10nFilter, TimeZone.getDefault())
33 private val dateFormatter = SimpleDateFormat("MMM d, yyyy, HH:mm:ss").apply {
34 this.timeZone = timeZone
37 override fun createJsonObject(request: FreenetRequest) =
38 getCurrentSone(request.toadletContext, false).let { currentSone ->
39 createSuccessJsonObject().apply {
40 this["loggedIn"] = currentSone != null
41 this["options"] = currentSone?.options?.toJsonOptions() ?: jsonObject {}
42 this["notificationHash"] = webInterface.getNotifications(currentSone).sortedBy { it.createdTime }.hashCode()
43 this["sones"] = request.httpRequest.getParam("soneIds").split(',').mapNotNull(core::getSone).plus(currentSone).filterNotNull().toJsonSones()
44 this["newPosts"] = webInterface.getNewPosts(currentSone).toJsonPosts()
45 this["newReplies"] = webInterface.getNewReplies(currentSone).toJsonReplies()
46 this["linkedElements"] = request.httpRequest.getParam("elements", "[]").asJson().map(JsonNode::asText).map(elementLoader::loadElement).toJsonElements()
50 private operator fun JsonReturnObject.set(key: String, value: JsonNode) = put(key, value)
51 private operator fun JsonReturnObject.set(key: String, value: Int) = put(key, value)
52 private operator fun JsonReturnObject.set(key: String, value: Boolean) = put(key, value)
54 private fun String.asJson() = ObjectMapper().readTree(this).asIterable()
56 override val needsFormPassword = false
57 override val requiresLogin = false
59 private fun SoneOptions.toJsonOptions() = jsonObject {
60 put("ShowNotification/NewSones", isShowNewSoneNotifications)
61 put("ShowNotification/NewPosts", isShowNewPostNotifications)
62 put("ShowNotification/NewReplies", isShowNewReplyNotifications)
65 private fun Iterable<Sone>.toJsonSones() = map { sone ->
68 put("name", SoneAccessor.getNiceName(sone))
69 put("local", sone.isLocal)
70 put("status", sone.status.name)
71 put("modified", core.isModifiedSone(sone))
72 put("locked", core.isLocked(sone))
73 put("lastUpdatedUnknown", sone.time == 0L)
74 synchronized(dateFormatter) {
75 put("lastUpdated", dateFormatter.format(sone.time))
77 put("lastUpdatedText", timeTextConverter.getTimeText(sone.time).l10nText.let { l10nFilter.format(null, it, emptyMap()) })
81 private fun Iterable<Post>.toJsonPosts() = map { post ->
84 put("sone", post.sone.id)
85 put("time", post.time)
86 put("recipient", post.recipientId.orNull())
90 private fun Iterable<PostReply>.toJsonReplies() = map { reply ->
93 put("sone", reply.sone.id)
94 put("post", reply.postId)
95 put("postSone", reply.post.get().sone.id)
99 private fun Iterable<LinkedElement>.toJsonElements() = map { (link, failed, loading) ->
102 put("loading", loading)
103 put("failed", failed)