Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- This file:
-- http://angg.twu.net/fbcache/fbcache.lua
-- http://angg.twu.net/fbcache/fbcache.lua.html
--  (find-angg        "fbcache/fbcache.lua")
--  See: (find-fbcache "README")
--       (find-TH "ferramentas-para-ativistas" "fbcache")
--  Author: Eduardo Ochs <[email protected]>
--  Version: 2014dec03
--  License: GPL3
--
-- Fbcache is library for keeping a cache of interesting Facebook posts.
-- More precisely, it is a set of functions that convert between Facebook
-- URLs (permalinks) and names of local files in the cache; between
-- Facebook URLs and IDs used internally by Facebook; that connects to
-- Facebook with a subset of your user's permissions to download posts
-- readable by you; and that converts these downloaded posts, which are
-- in JSON, to text.
--
-- WARNING: THIS IS A PROTOTYPE!
-- For the design & more info, see the README.
-- I am trying to make this easy to port to other languages.
-- PLEASE DO GET IN TOUCH!
--
-- «.requires»		(to "requires")
--
-- «.token»		(to "token")
-- «.curl»		(to "curl")
-- «.fbkinds»		(to "fbkinds")
-- «.all-fb-urls.lst»	(to "all-fb-urls.lst")
-- «.fburls»		(to "fburls")
-- «.json_parse»	(to "json_parse")
-- «.cache»		(to "cache")
-- «.sort-by-date»	(to "sort-by-date")
-- «.fbid_to_txt»	(to "fbid_to_txt")
-- «.good-and-bad-ids»	(to "good-and-bad-ids")
-- «.good-and-bad-urls»	(to "good-and-bad-urls")



--                       _               
--  _ __ ___  __ _ _   _(_)_ __ ___  ___ 
-- | '__/ _ \/ _` | | | | | '__/ _ \/ __|
-- | | |  __/ (_| | |_| | | | |  __/\__ \
-- |_|  \___|\__, |\__,_|_|_|  \___||___/
--              |_|                      
--
-- «requires» (to ".requires")

require "re"
require "posix"
userocks()         -- (find-angg "LUA/lua50init.lua" "userocks")
pretty = require 'pl.pretty'     -- (find-es "lua5" "pl.pretty")
pp0 = function (o) return pretty.write(o) end
pp  = function (o) print(pretty.write(o)) end

-- (find-es "lua5" "pl.pretty-fix")
longquote = function (str)
    local T = {}
    local f = function (eqs) T[#eqs+1] = 1 end
    if str:gsub("%](=*)", f) then
      local eqs = string.rep("=", #T)
      return '['..eqs..'[\n'..str..']'..eqs..']'
    end
    return '[[\n'..str..']]'
  end

-- (find-es "lua5" "pl.text.wrap")
wrap = (require "pl.text").wrap
wraps = function (bigstr)
    local f = function (li) return table.concat(wrap(li), "\n").."\n" end
    return (bigstr:gsub("([^\n]+)", f))
  end

-- (find-angg "LUA/lua50init.lua" "ee_ls")
no_dots = function (L)
    for i=#L,1,-1 do if L[i]=="." or L[i]==".." then table.remove(L, i) end end
    return L
  end
ee_ls         = function (dir) return (posix.dir(ee_expand(dir))) end
ee_ls_no_dots = function (dir) return sorted(no_dots(ee_ls(dir))) end

cfmt   = function (fmt) return function (...) return format(fmt, ...) end end
ee_fmt = function (fmt) return cfmt(ee_expand(fmt)) end



--                  _ 
--   ___ _   _ _ __| |
--  / __| | | | '__| |
-- | (__| |_| | |  | |
--  \___|\__,_|_|  |_|
--                    
-- «curl» (to ".curl")
fbcurl0 = function (url) return getoutput(format("curl -s '%s'", url)) end
fbcurl = function (query)
    local c = query:match"%?" and "&" or "?"
    local url = "https://graph.facebook.com/v2.5/"..
      query .. c .. "access_token=" .. token
    local cmd = format("curl -s '%s'", url)
    return getoutput(cmd)
  end
fbid_fetch_from_facebook = function (fbid) return fbcurl(fbid) end

-- «token» (to ".token")
-- (find-angg ".pythonrc.py")
-- https://developers.facebook.com/tools/explorer
token = "CAACEdEose0cBAJ4NZBqLZBqHP2vNyvyYfA2X2SVgUhiHZAGAA5UzSpnJym4YGKDGAf3jdhxZChqSzUNGZCJmNk4A5hEqSMGHQA6uk8brumqIjT3K2SyQz82LXsdoVokYTIjTNSHz3QV2MSVAhI6gERC4y9QZC4TQJ6Rpe0aWOJQOx7ZC3s2u8OqZCKsH2Y5FVbAAWNAlN9pSZAwZDZD"


--   __ _     _    _           _     
--  / _| |__ | | _(_)_ __   __| |___ 
-- | |_| '_ \| |/ / | '_ \ / _` / __|
-- |  _| |_) |   <| | | | | (_| \__ \
-- |_| |_.__/|_|\_\_|_| |_|\__,_|___/
--                                   
-- «fbkinds» (to ".fbkinds")
-- (find-fbcache "urls.lua" "translations0")
-- (find-fbcache "README")
-- (find-fbcachefile "README" "Fburls")
-- Some pages can't be retrieved because of this bug:
-- https://developers.facebook.com/bugs/1569724479914127/
-- https://developers.facebook.com/bugs/1558407907724578/

fbkinds0 = [[
  /events/N/permalink/N/R              21_ok
  /events/N/N/R                        21_ok
  /events/N/R                          1_ok
  /groups/N/permalink/N/R              21_ok
  /groups/W/permalink/N/R              0_nothingworks
  /groups/N/NR                         1_whydoesnt2work
  /groups/W/NR                         2_ok
  /groups/NR                           1_ok
  /groups/WR                           0_how_to_convert_name->id?
  /W/media_set?set=a.N.N.NR            0_nothingworks
  /media/set/?set=OR                   0_nothingworks
  /notes/W/W/NR                        0_3shouldworkbutdeprecated
  /notes/N/R                           0_1shouldworkbutdeprecated
  /pages/W/NR                          2_ok
  /permalink.php?story_fbid=N&id=NR    12_ok
  /photo.php?fbid=N&set=t.NR           0_nothingworks
  /photo.php?fbid=N&set=a.N.N.NR       0_nothingworks
  /photo.php?fbid=N&set=OR             1
  /N/photos/t.N/N/R                    13
  /N/photos/gm.N/N/R                   123
  /N/photos/a.N.N.N/N/R                1245
  /W/photos/a.N.N.N/N/R                0_untested
  /photo.php?v=N&set=OR                1
  /photo.php?v=NR                      1
  /W/posts/NR                          2
  /video.php?v=NR                      1
]]

fbkchars_make_fun = function (str)
    local tbl = {}
    for char,rgx in str:gmatch("(%S):(%S*)") do
      tbl[char] = rgx
    end
    return function (pat) return pat:gsub("[WNORL?.]", tbl) end
  end
fbkchars_make_re  = fbkchars_make_fun(
  " W:([^/]+) N:([0-9]+) O:([^/&?]+) R:(.*) L:([^_]+) .:%. ?:%? ")
fbkchars_make_fmt = fbkchars_make_fun(
  " W:%s      N:%s       O:%s        R:     L:%s      .:.  ?:?  ")

fbpat_to_fbkind = function (fbpat, fields, n)
    local bigpat = "https://www.facebook.com"..fbpat
    local re  = "^"..fbkchars_make_re(bigpat).."$"
    local fmt = fbkchars_make_fmt(bigpat)
    local fbkind = {
      pat    = fbpat,
      re     = re,
      fmt    = fmt,
      fields = fields,
      n      = n,
    } 
    return fbkind
  end

fbkinds = {}
for _,li in ipairs(splitlines(fbkinds0)) do
  local pat,fields = li:match("(%S+)%s+(%S+)")
  if pat then
    local n = #fbkinds + 1
    local fbkind = fbpat_to_fbkind(pat, fields, n)
    table.insert(fbkinds, fbkind)
  end
end

fburl_to_kparts = function (fburl)
    for kind,fbkind in ipairs(fbkinds) do
      local a,b,c,d,e,f,g = fburl:match(fbkind.re)
      if a then return kind, {a, b, c, d, e, f, g} end
    end
  end

fburl_to_fbids = function (fburl)
    local kind,parts = fburl_to_kparts(fburl)
    if kind then
      local fbkind = fbkinds[kind]
      local fields = fbkind.fields
      local digits = fields:match("^[1-9]*")
      local fbids  = {}
      for d in digits:gmatch(".") do
        local fbid = parts[0 + d]
        table.insert(fbids, fbid)
      end
      return fbids
    end
  end

fburl_clean = function (fburl)
    local kind,parts = fburl_to_kparts(fburl)
    if kind then
      local fbkind = fbkinds[kind]
      local fmt    = fbkind.fmt
      return format(fmt, unpack(parts))
    end
  end


--[[
-- (find-fbcache "urls.lua" "prubyks")
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "fbcache.lua"
pp(fbkinds)
pp(fbkinds[2])
url = "https://www.facebook.com/132127443469288/photos/a.691819544166739.1073741827.132127443469288/964194186929272/?type=1"

PP(fburl_to_kparts(url))
PP(fburl_to_fbids(url))
PP(fburl_clean(url))
--]]



--[[
-- (find-fbcache "urls.lua" "prubyks")
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "fbcache.lua"
-- https://www.facebook.com/messages/conversation-729894833762832
-- https://developers.facebook.com/docs/graph-api/reference/v2.1/conversation
-- https://developers.facebook.com/docs/graph-api/reference/v2.2/conversation/messages

--]]







--        _ _      __ _                    _       _     _   
--   __ _| | |    / _| |__      _   _ _ __| |___  | |___| |_ 
--  / _` | | |___| |_| '_ \ ___| | | | '__| / __| | / __| __|
-- | (_| | | |___|  _| |_) |___| |_| | |  | \__ \_| \__ \ |_ 
--  \__,_|_|_|   |_| |_.__/     \__,_|_|  |_|___(_)_|___/\__|
--                                                               
-- «all-fb-urls.lst» (to ".all-fb-urls.lst")
--[[
-- Here's how I produce my "all-fb-urls.lst"...
-- (find-fbcache "all-fb-urls.lst")
* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
cat ~/TODO \
    ~/ORG/index.org \
    ~/TH/ee.blogme \
    ~/TH/2014-xs.blogme \
    ~/TH/links-sobre-gaza.blogme \
  | grep https://www.facebook.com/ \
  | tr ' ' '\n' \
  | grep https://www.facebook.com/ \
  | sort | uniq \
  | tee /tmp/all-fb-urls.lst

ls -l /tmp/all-fb-urls.lst ~/fbcache/all-fb-urls.lst
cp -v /tmp/all-fb-urls.lst ~/fbcache/all-fb-urls.lst
--]]




--   __ _                _     
--  / _| |__  _   _ _ __| |___ 
-- | |_| '_ \| | | | '__| / __|
-- |  _| |_) | |_| | |  | \__ \
-- |_| |_.__/ \__,_|_|  |_|___/
--                             
-- «fburls» (to ".fburls")
fburls = {}
fbids  = {}
fburls_by_kind = {}
fburls_by_fbid = {}

fburls_fname = "~/fbcache/all-fb-urls.lst"

fburls_read = function (fname)
    fburls = splitlines(ee_readfile(fname or fburls_fname))
    fburls_read0()
  end
fburls_read0 = function ()
    fbids = {}
    fburls_by_kind = {}
    fburls_by_fbid = {}
    --
    for i=0,#fbkinds do fburls_by_kind[i] = {} end
    --
    for _,fburl in ipairs(fburls) do
      local kind,parts = fburl_to_kparts(fburl)
      table.insert(fburls_by_kind[kind or 0], fburl)
      for _,fbid in ipairs(fburl_to_fbids(fburl) or {}) do
        table.insert(fbids, fbid)
        if not fburls_by_fbid[fbid] then fburls_by_fbid[fbid] = {} end
        table.insert(fburls_by_fbid[fbid], fburl)
      end
    end
    --
    fbids = uniq(sorted(fbids))
  end






--[[
-- (find-fbcache "all-fb-urls.lst")
-- (find-fbcache "urls.lua" "prubyks")
-- (find-angg "LUA/lua50init.lua" "Set")

* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
# (find-fbcachefile "all-fb-urls.lst" "cezar.migliorin")
cd ~/fbcache/cache_json/
rm -v 573841232680302 722285504502540 724202420977515 724497177614706

* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "fbcache.lua"
-- fburls_read "~/fbcache/all-fb-urls.lst"
fburls_read()
-- pp(fburls_by_fbid)
-- pp(fburls_by_kind[0])

Fbids = Set.from(fbids)
Jsons = Set.from(json_ls())
Missing = Fbids - Jsons
= Fbids
= Jsons
= Missing
missing = Missing:ks()
pp(missing)
-- (find-fbcachefile "cache_json/")

-- Dowload the missing jsons
for _,fbid in ipairs(missing) do
  json = fbid_fetch_from_facebook(fbid)
  print(fbid.."   "..#json.." bytes")
  fbid_write_json(fbid, json)
end

-- List the jsons that don't parse
Jsons = Set.from(json_ls())
jsons = Jsons:ks()
badjsons = {}
for _,fbid in ipairs(jsons) do
  json = fbid_read_json(fbid)
  o    = json_parse(json)
  fbid_to_json[fbid] = json
  fbid_to_o   [fbid] = o
  if not o then
    local fmt = '(find-fbcachefile "cache_json/%s")'
    print(cfmt(fmt)(fbid))
    table.insert(badjsons, fbid)
  end
end

--]]




--    _                                                
--   (_)___  ___  _ __       _ __   __ _ _ __ ___  ___ 
--   | / __|/ _ \| '_ \     | '_ \ / _` | '__/ __|/ _ \
--   | \__ \ (_) | | | |    | |_) | (_| | |  \__ \  __/
--  _/ |___/\___/|_| |_|____| .__/ \__,_|_|  |___/\___|
-- |__/               |_____|_|                        
--
-- «json_parse» (to ".json_parse")
-- http://www.json.org/

json_grammar0 = [=[
  objrest <- obj {} [%s]* {.*}
  obj     <- bool / num / str / table / list
  objp    <- obj colon obj
  table   <- ("{" (objp (comma objp)*)* "}") -> totable
  list    <- ("[" (obj  (comma obj )*)* "]") -> tolist
  colon   <- [%s]* ":" [%s]*
  comma   <- [%s]* "," [%s]*
  bool    <- ("true" / "false") -> tobool
  num     <- ("-"? [0-9.]+)      -> tonum

  str <- (ustr / str0)
   ustr        <- "u" str0
   str0        <- ("'" (stritem / {'"'})* -> concat "'") /
                  ('"' (stritem / {"'"})* -> concat '"')
   stritem     <- strcnormals / strcc / strcx / strcu / strcU / strcother
   strcnormals <- {[^'"\]+}
   strcc       <- "\"  {['"\/]}
   strcx       <- "\x" ({[%x][%x]}                       -> hextoc)
   strcu       <- "\u" ({[%x][%x][%x][%x]}                 -> utoc)
   strcU       <- "\U" ({[%x][%x][%x][%x][%x][%x][%x][%x]} -> Utoc)
   strcother   <- "\" . -> otherc
]=]
json_chars_b = {n="\n", r="\r", t="\t", b="\b", ["/"]="/"}
json_chars_u = {["2018"]='"', ["2019"]='"', ["201c"]='"', ["201d"]='"',
                ["2013"]="---", }
json_chars_U = {}
json_defs = {
  tobool  = function (s) return s == "True" and true or false end,
  tonum   = function (s) return tonumber(s) end,
  tostr   = function (s) return s end,
  tolist  = function (...) return {...} end,
  totable = function (...)
      local L, T = {...}, {}
      for i=1,#L-1,2 do T[L[i]] = L[i+1] end
      return T
    end,
  hextoc  = function (hh) return string.char(tonumber(hh, 16)) end,
  utoc   = function  (h4)
      local n = tonumber(h4, 16)
      if n < 256 then return string.char(n) end
      return json_chars_u[h4] or "\\u"..h4
    end,
  Utoc   = function  (h8) return "\\U"..h8 end,
  concat  = function (...) return table.concat {...} end,
  otherc  = function (c)
      if json_chars_b[c] then return json_chars_b[c] end
      print("\\"..c)
      return "\\"..c
    end,
}
json_grammar = re.compile(json_grammar0, json_defs)
json_parse   = function (bigstr, pos) return json_grammar:match(bigstr, pos) end
json_test    = function (bigstr, pos) pp(json_parse(bigstr, pos)) end



--[[
-- (find-fbcachecurlfile "")
-- (find-fbcachecurlfile "10152027767115809")

* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "fbcache.lua"
json = ee_readfile "~/fbcache/cache_by_id_curl/10152027767115809"
--     (find-fline "~/fbcache/cache_by_id_curl/10152027767115809")
json_test (json)

-- (find-fbcachefile "cache_json/")


--]]




--                 _          
--   ___ __ _  ___| |__   ___ 
--  / __/ _` |/ __| '_ \ / _ \
-- | (_| (_| | (__| | | |  __/
--  \___\__,_|\___|_| |_|\___|
--                            
-- «cache» (to ".cache")
json_dir  = "~/fbcache/cache_json/"
pplua_dir = "~/fbcache/cache_pplua/"
json_ls   = function () return ee_ls_no_dots(json_dir)  end
pplua_ls  = function () return ee_ls_no_dots(pplua_dir) end
json_fname  = function (fbid) return ee_expand(json_dir ..fbid) end
pplua_fname = function (fbid) return ee_expand(pplua_dir..fbid) end
fbid_read_json  = function (fbid) return readfile(json_fname (fbid)) end
fbid_read_pplua = function (fbid) return readfile(pplua_fname(fbid)) end
fbid_write_json  = function (fbid, json) writefile(json_fname (fbid), json)  end
fbid_write_pplua = function (fbid, pplua) writefile(pplua_fname(fbid), pplua) end

fbid_to_json  = {}
fbid_to_o     = {}
fbid_to_pplua = {}


-- jsons_fetch (fbids): dowload jsons from FB and write them to the cache
-- jsons_read  (fbids): read jsons from the cache
-- jsons_parse (fbids, errf): 

jsons_fetch = function (fbids_list)
    for _,fbid in ipairs(fbids_list or fbids) do
      local json = fbid_fetch_from_facebook(fbid) -- fetch json from Facebook
      print(fbid.."   "..#json.." bytes")
      fbid_to_json[fbid] = json       -- store json into fbid_to_json[]
      fbid_write_json(fbid, json)     -- write json into the cache dir
    end
  end

jsons_read = function (fbids)
    for _,fbid in ipairs(fbids or json_ls()) do
      local json = fbid_read_json(fbid)
      fbid_to_json[fbid] = json      -- store json into fbid_to_json[]
    end
  end

jsons_parse = function (fbids, errf)
    for _,fbid in ipairs(fbids or sorted(keys(fbid_to_json))) do
      local json = fbid_to_json[fbid] -- read json from fbid_to_json[]
      local o    = json_parse(json)   -- convert json to o
      if o then
        fbid_to_o[fbid] = o           -- store o into fbid_to_o[]
      else
        if errf then errf(fbid, json) end
      end
    end
  end

ppluas_write = function (fbids, f)
    for _,fbid in ipairs(fbids or sorted(keys(fbid_to_o))) do
      local o     = fbid_to_o[fbid]  -- read o from fbid_to_o[]
      local pplua = pp0(o)           -- convert o to pplua
      fbid_to_pplua[fbid] = pplua    -- store pplua into fbid_to_pplua[]
      fbid_write_pplua(fbid, pplua)  -- write pplua into the cache dir
      if f then f(fbid, o, pplua) end
    end
  end

ppluas_read = function (fbids)
    for _,fbid in ipairs(fbids or pplua_ls()) do
      local pplua = fbid_read_pplua(fbid)  -- read pplua from cache dir
      local o     = expr(pplua)            -- convert pplua to o
      fbid_to_pplua[fbid] = pplua          -- store pplua into fbid_to_pplua[]
      fbid_to_o    [fbid] = o              -- store o into fbid_to_o[]
    end
  end

ppluas_single_fname = "~/fbcache/cache_pplua.lua"
ppluas_single = function (fbids)
    local entries = {}
    for _,fbid in ipairs(fbids or sorted(keys(fbid_to_pplua))) do
      local pplua = fbid_to_pplua[fbid]
      local entry = format('["%s"] = \n%s,\n', fbid, pplua)
      table.insert(entries, entry)
    end
    return "{\n"..table.concat(entries).."}\n"
  end
ppluas_write_single = function (fname, fbids)
    ee_writefile(fname or ppluas_single_fname, ppluas_single(fbids))
  end
ppluas_read_single = function (fname)
    fbid_to_o = expr(ee_readfile(fname or ppluas_single_fname))
  end



--[[
-- (find-fbcachefile "")
-- (find-fbcachecurlfile "")
-- (find-fbcachecurlfile "10152027767115809")
573841232680302
-- (find-fbcachefile "cache_json/")
-- (find-fbcachefile "cache_json/573841232680302")
-- (find-fbcachefile "cache_pplua/")

* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "fbcache.lua"
jsons_read()
jsons_parse()
ppluas_write(nil, function (fbid) print(fbid) end)
ppluas_write()
ppluas_write_single()

* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "fbcache.lua"
ppluas_read()
ppluas_write_single()
ppluas_read_single()

--]]





--                 _     _                 _       _       
--  ___  ___  _ __| |_  | |__  _   _    __| | __ _| |_ ___ 
-- / __|/ _ \| '__| __| | '_ \| | | |  / _` |/ _` | __/ _ \
-- \__ \ (_) | |  | |_  | |_) | |_| | | (_| | (_| | ||  __/
-- |___/\___/|_|   \__| |_.__/ \__, |  \__,_|\__,_|\__\___|
--                             |___/                       
--
-- «sort-by-date» (to ".sort-by-date")
fbid_date = function (fbid)
    local o    = fbid_to_o[fbid]
    local date = o.created_time or o.updated_time or " "..fbid
    return date
  end
fbids_sorted_by_date = function (fbids)
    local good_fbids = {}
    local good_fbid = function (fbid) return not fbid_to_o[fbid].error end
    for _,fbid in ipairs(fbids or keys(fbid_to_o)) do
      if good_fbid(fbid) then table.insert(good_fbids, fbid) end
    end
    local fbid_date_lt = function (fbid1, fbid2)
        return fbid_date(fbid1) < fbid_date(fbid2)
      end
    return sorted(good_fbids, fbid_date_lt)
  end


--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "fbcache.lua"
ppluas_read_single()
fburls_read()

fbd = fbids_sorted_by_date()
pp(fbd)
for _,fbid in ipairs(fbd) do print(fbid, fbid_date(fbid)) end

fbid = "580542262074186"
= fbid_to_txt(fbid)

bigstr = fbids_to_txt()
ee_writefile("/tmp/huge", bigstr)
-- (find-fline "/tmp/huge")

* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
ls -l /tmp/huge ~/fbcache/huge.txt
cp -v /tmp/huge ~/fbcache/huge.txt
# (find-fbcachefile "huge.txt")

--]]



-- «fbid_to_txt» (to ".fbid_to_txt")
--
fbid_to_sexp = function (fbid)
    return format('(find-fbcachepplua "%s")', fbid)
  end
fbid_to_txt_body = function (fbid)
    local o = fbid_to_o[fbid]
    local fmt = "From: $FROM\nDate: $DATE\n$URL\n  $SEXP\n\n$BODY"
    local T = { FROM = o.from and o.from.name or "(no FROM)",
                DATE = o.created_time or o.updated_time or "(no DATE)",
                URL  = o.link or "(no URL)",
                SEXP = fbid_to_sexp(o.id),
                BODY = wraps(o.caption or o.name or o.message or "(no NAME or MESSAGE)") }
    local f = function (name) return T[name] or error(name.." is nil") end
    return (fmt:gsub("%$([A-Z]+)", f))
  end
fbid_to_txt = function (fbid)
    local anchor = "\171"..fbid.."\187\n"
    local urls = mapconcat(cfmt "%s\n", fburls_by_fbid[fbid] or {})
    return anchor..urls..fbid_to_txt_body(fbid)
  end
fbids_to_txt = function (fbids)
    fbids = fbids or fbids_sorted_by_date()
    return mapconcat(fbid_to_txt, fbids, "\n\n---------------\n")
  end



--[[
-- «good-and-bad-ids» (to ".good-and-bad-ids")
-- «good-and-bad-urls» (to ".good-and-bad-urls")
-- (find-fbcache "fburls_bad.lst")
-- (find-fbcache "fburls_good.lst")
-- (find-fbcache "fburls_noid.lst")
-- http://angg.twu.net/fbcache/fburls_bad.lst.html
-- http://angg.twu.net/fbcache/fburls_good.lst.html
-- http://angg.twu.net/fbcache/fburls_noid.lst.html

* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "fbcache.lua"
ppluas_read_single()
fburls_read()

filter = function (f, A)
    local B = {}
    for _,a in ipairs(A) do if f(a) then table.insert(B, a) end end
    return B
  end
fbid_error_yes = function (fbid) return     fbid_to_o[fbid].error end
fbid_error_no  = function (fbid) return not fbid_to_o[fbid].error end

fbids_to_fburls = function (fbids)
    local fburls = {}
    for _,fbid in ipairs(fbids) do
      for _,fburl in ipairs(fburls_by_fbid[fbid] or {}) do
        table.insert(fburls, fburl)
      end
    end
    return sorted(fburls)
  end

fburls_bad  = fbids_to_fburls(filter(fbid_error_yes, keys(fbid_to_o)))
fburls_good = fbids_to_fburls(filter(fbid_error_no,  keys(fbid_to_o)))

pp(fburls_bad)
ee_writefile("fburls_bad.lst",  mapconcat(cfmt "%s\n", fburls_bad))
ee_writefile("fburls_good.lst", mapconcat(cfmt "%s\n", fburls_good))

pp(fburls_by_kind[0])
ee_writefile("fburls_noid.lst", mapconcat(cfmt "%s\n", fburls_by_kind[0]))

-- (find-fbcache "fburls_bad.lst")
-- (find-fbcache "fburls_good.lst")
-- (find-fbcache "fburls_noid.lst")


--]]





-- Local Variables:
-- coding: raw-text-unix
-- End: