site/api/thread.lua (86 lines of code) (raw):

--[[ Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ]]-- -- This is thread.lua - a script for fetching a thread based on a message -- that is in said thread. local JSON = require 'cjson' local elastic = require 'lib/elastic' local aaa = require 'lib/aaa' local user = require 'lib/user' local cross = require 'lib/cross' local config = require 'lib/config' local utils = require 'lib/utils' local emls_thrd -- func that fetches all children of an original topic email thingy local function fetchChildren(r, pdoc, c, biglist, account) c = (c or 0) + 1 -- don't fetch more than 250 subtrees, we don't want to nest ad nauseam if c > 250 then return {} end -- biglist is for making sure we dont' fetch something twice biglist = biglist or {} local children = {} -- find any emails that reference this one local emid = r:escape(pdoc['message-id']) local docs = elastic.findFast( ('in-reply-to:"%s" OR references:"%s"'):format(emid, emid), 50, "mbox") for k, doc in pairs(docs) do -- if we haven't seen this email before, check for its kids and add it to the bunch if (not biglist[doc['message-id']]) and aaa.canAccessDoc(r, doc, account) then biglist[doc['message-id']] = true local mykids = fetchChildren(r, doc, c, biglist, account) if not account and config.antispam then doc = utils.anonymizeHdrs(doc) end local dc = { tid = doc.mid, mid = doc.mid, subject = doc.subject, from = doc.from, id = doc.request_id, epoch = doc.epoch, children = mykids, irt = doc['in-reply-to'] } table.insert(children, dc) table.insert(emls_thrd, dc) else biglist[doc['message-id']] = true docs[k] = nil end end return children end function handle(r) cross.contentType(r, "application/json; charset=UTF-8") local DEBUG = config.debug or false local START = DEBUG and r:clock() or nil local get = r:parseargs() -- get the parameter (if any) and tidy it up local eid = (get.id or ""):gsub("\"", "") -- If it is the empty string then set it to "1" so ES doesn't barf -- N.B. ?id is treated as ?id=1 if #eid == 0 then eid = "1" end local doc = elastic.get("mbox", eid, true) emls_thrd = {} -- Try searching by mid if not found, for backward compat if not doc or not doc.mid then local docs = elastic.find("message-id:\"" .. r:escape(eid) .. "\"", 1, "mbox") if #docs == 0 and #eid == utils.SHORTENED_LINK_LEN then docs = elastic.find("mid:" .. r:escape(eid) .. "*", 1, "mbox") end if #docs == 1 then doc = docs[1] end end if get.timetravel then doc = utils.findParent(r, doc, elastic) end local doclist = {} -- did we find an email? if doc then local account = user.get(r) if doc and doc.mid and aaa.canAccessDoc(r, doc, account) then if not account and config.antispam then doc = utils.anonymizeHdrs(doc) end table.insert(emls_thrd, doc) doc.children = fetchChildren(r, doc, 1, nil, account) doc.tid = doc.mid doc.id = doc.request_id --doc.body = nil r:puts(JSON.encode({ took = DEBUG and (r:clock() - START) or nil, emails = emls_thrd, })) return cross.OK end end r:puts(JSON.encode{error = "No such e-mail or you do not have access to it."}) return cross.OK end cross.start(handle)