Warning: this is an htmlized version!
The original is here, and
the conversion rules are here.
-- fbkinds.lua: tools to handle the various kinds of Facebook URLs
-- This file:
-- http://angg.twu.net/fbcache/fbkinds.lua
-- http://angg.twu.net/fbcache/fbkinds.lua.html
--  (find-angg        "fbcache/fbkinds.lua")
--
-- (find-fbcache "fbcache2.lua" "fbkinds")

-- «.fbkinds_bigstr»	(to "fbkinds_bigstr")
-- «.fbpatexpand»	(to "fbpatexpand")
-- «.fbpatexpand-tests»	(to "fbpatexpand-tests")
-- «.Fbkind-class»	(to "Fbkind-class")
-- «.Fbkind-tests»	(to "Fbkind-tests")
-- «.Fbkinds-class»	(to "Fbkinds-class")
-- «.fbkinds»		(to "fbkinds")
-- «.fbdl»		(to "fbdl")
-- «.fbdl-tests»	(to "fbdl-tests")

require "lpeg"      -- (find-es "lua-intro" "lpeg-quickref")
-- require "re"     -- (find-es "lua-intro" "lpeg-re-1")
require "fbcache3"  -- (find-fbcache "fbcache3.lua")




--   __ _     _    _           _         _     _           _        
--  / _| |__ | | _(_)_ __   __| |___    | |__ (_) __ _ ___| |_ _ __ 
-- | |_| '_ \| |/ / | '_ \ / _` / __|   | '_ \| |/ _` / __| __| '__|
-- |  _| |_) |   <| | | | | (_| \__ \   | |_) | | (_| \__ \ |_| |   
-- |_| |_.__/|_|\_\_|_| |_|\__,_|___/___|_.__/|_|\__, |___/\__|_|   
--                                 |_____|       |___/              
--
-- «fbkinds_bigstr» (to ".fbkinds_bigstr")
-- This table, stored as a big string, represent in a VERY ompact form
-- all the kinds of Facebook URLs that we support. For example, the
-- pattern "groupwpn", which is
--
--   /groups/W/permalink/N/R
--
-- matches:
--
--   https://www.facebook.com/groups/contatimprovbra/permalink/947586865274406/
--
-- the "W" matches the "contatimprovbra" (a word),
-- the "N" matches the "947586865274406" (a number), and
-- the "R" matches the empty string at the end (the rest).

fbkinds_bigstr = [[
  eventnpn   /events/N/permalink/N/R              21_ok
  eventnn    /events/N/N/R                        21_ok
  eventn     /events/N/R                          1_ok
  groupnpn   /groups/N/permalink/N/R              21_ok
  groupwpn   /groups/W/permalink/N/R              0_nothingworks
  groupnn    /groups/N/NR                         1_whydoesnt2work
  groupwn    /groups/W/NR                         2_ok
  groupn     /groups/NR                           1_ok
  groupw     /groups/WR                           0_how_to_convert_name->id?
  mediawannn /W/media_set?set=a.N.N.NR            0_nothingworks
  mediawnnn  /media/set/?set=W.N.N.NR             0_nothingworks
  mediawn    /media/set/?set=W.NR                 0_nothingworks
  noteswwn   /notes/W/W/NR                        0_3shouldworkbutdeprecated
  notesn     /notes/N/R                           0_1shouldworkbutdeprecated
  pageswn    /pages/W/NR                          2_ok
  storynn    /permalink.php?story_fbid=N&id=NR    12_ok
  photonn    /photo.php?fbid=N&set=t.NR           0_nothingworks
  photonnnn  /photo.php?fbid=N&set=a.N.N.NR       0_nothingworks
  photono    /photo.php?fbid=N&set=OR             1
  photot     /N/photos/t.N/N/R                    13
  photogm    /N/photos/gm.N/N/R                   123
  photona    /N/photos/a.N.N.N/N/R                1245
  photowa    /W/photos/a.N.N.N/N/R                0_untested
  photovs    /photo.php?v=N&set=OR                1
  photov     /photo.php?v=NR                      1
  postwn     /W/posts/NR                          2
  videon     /video.php?v=NR                      1
]]



--   __ _                 _                                  _ 
--  / _| |__  _ __   __ _| |_ _____  ___ __   __ _ _ __   __| |
-- | |_| '_ \| '_ \ / _` | __/ _ \ \/ / '_ \ / _` | '_ \ / _` |
-- |  _| |_) | |_) | (_| | ||  __/>  <| |_) | (_| | | | | (_| |
-- |_| |_.__/| .__/ \__,_|\__\___/_/\_\ .__/ \__,_|_| |_|\__,_|
--           |_|                      |_|                      
--
-- «fbpatexpand» (to ".fbpatexpand")
-- (find-fbcache "fbcache2.lua" "fbpatcompile")
-- Convert patterns like the above ones into lpeg patterns.
-- For example,
--
--   "/events/N/permalink/N/R"
--
-- becomes this (as a string, to be compiled later):
--
--   lpeg.P"/events/" * PatN * lpeg.P"/permalink/" * PatN * lpeg.P"/" * PatR
--
-- and this:
--
--   (lpeg.Cp():Cg("bpos") *
--    lpeg.P"/events/" * PatN * lpeg.P"/permalink/" * PatN * lpeg.P"/" * PatR *
--    lpeg.Cc("eventnpn"):Cg("kind") * lpeg.Cc(1):Cg("kindn")
--   ):Ct()
--
PatN = (lpeg.R("09")^1):C()
PatO = ((lpeg.R("09") + lpeg.S(" "))^1):C()
PatW = ((lpeg.R("09") + lpeg.R("AZ") + lpeg.R("az") + lpeg.S("."))^1):C()
PatR = (lpeg.P(1)^0):C()
PatR = lpeg.Cp():Cg("rpos") * (lpeg.P(1)^0):C()
PatR = lpeg.Cp():Cg("rpos") * (lpeg.R("!~")^0):C()
fbpatexpand0 = function (pat)
    local mkp       = function (s) return "Pat"..s end
    local mks       = function (s) return 'lpeg.P"'..s..'"' end
    local mka       = function (...) return table.concat({...}, " * ") end
    local Upcase    = lpeg.R("AZ")
    local NonUpcase = (1 - Upcase)^1
    local Parts     = ((NonUpcase/mks) * (Upcase/mkp))^1
    return lpeg.match(Parts/mka, pat)
  end
fbpatexpand = function (n, name, pat)
    local patexp = fbpatexpand0(pat)
    local ppos   = 'lpeg.Cp():Cg("bpos")'
    local pname  = 'lpeg.Cc("' ..name..'"):Cg("name")'
    local pn     = 'lpeg.Cc('  ..n..    '):Cg("n")'
    return format("(%s *\n %s *\n %s * %s\n):Ct()", ppos, patexp, pname, pn)
  end

-- «fbpatexpand-tests» (to ".fbpatexpand-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "fbkinds.lua"
pat   = "/events/N/permalink/N/R"
pat0  = fbpatexpand0(pat)
pate  = fbpatexpand (1, "eventnpn", pat)
= pat0
= pate

url  = "https://www.facebook.com/events/1397247553878845/permalink/1412951502308450/"
u    =                         "/events/1397247553878845/permalink/1412951502308450/"
patc  = expr(pate)
PP(patc:match(u))
--> {1="1397247553878845", 2="1412951502308450", 3="", "bpos"=1, "kind"="eventp", "rpos"=53}

--]]



--  _____ _     _    _           _ 
-- |  ___| |__ | | _(_)_ __   __| |
-- | |_  | '_ \| |/ / | '_ \ / _` |
-- |  _| | |_) |   <| | | | | (_| |
-- |_|   |_.__/|_|\_\_|_| |_|\__,_|
--                                 
-- «Fbkind-class» (to ".Fbkind-class")

Fbkind = Class {
  type = "Fbkind",
  new  = function (n, name, pat, comment)
      return Fbkind {n=n, name=name, pat=pat, comment=comment}
    end,
  __tostring = function (fbk) return fbk:tostring() end,
  __index = {
    tostring = function (fbk)
        return format("%2s  %-12s  %-40s  %s",
                      tostring(fbk.n), fbk.name, fbk.pat, fbk.comment or "")
      end,
    patexpand = function (fbk)
        return fbpatexpand(fbk.n, fbk.name, fbk.pat)
      end,
    match = function (fbk, u)
        local pat = fbk:patexpand()
        return expr(pat):match(u)
      end,
  },
}

-- «Fbkind-tests» (to ".Fbkind-tests")
--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "fbkinds.lua"
fbk = Fbkind.new(1, "eventnpn", "/events/N/permalink/N/R", "c")
= fbk
--> 1  eventnpn      /events/N/permalink/N/R                   c
PP(fbk)
--> {"comment"="c", "n"=1, "name"="eventnpn", "pat"="/events/N/permalink/N/R"}
= fbk:patexpand()
--> (lpeg.Cp():Cg("bpos") *
--   lpeg.P"/events/" * PatN * lpeg.P"/permalink/" * PatN * lpeg.P"/" * PatR *
--   lpeg.Cc("eventnpn"):Cg("name") * lpeg.Cc(1):Cg("n")
--  ):Ct()

url  = "https://www.facebook.com/events/1397247553878845/permalink/1412951502308450/"
u    =                         "/events/1397247553878845/permalink/1412951502308450/"
PP(fbk:match(u))
--> {1="1397247553878845", 2="1412951502308450", 3="", "bpos"=1, "n"=1, "name"="eventnpn", "rpos"=53}

--]]





--  _____ _     _    _           _     
-- |  ___| |__ | | _(_)_ __   __| |___ 
-- | |_  | '_ \| |/ / | '_ \ / _` / __|
-- |  _| | |_) |   <| | | | | (_| \__ \
-- |_|   |_.__/|_|\_\_|_| |_|\__,_|___/
--                                     
-- «Fbkinds-class» (to ".Fbkinds-class")

Fbkinds = Class {
  type = "Fbkinds",
  new  = function () return Fbkinds {} end,
  from = function (bigstr)
      return Fbkinds.new():addlines(bigstr):patcompile()
    end,
  __tostring = function (fbks) return fbks:tostring() end,
  __index = {
    add = function (fbks, name, pat, comment)
        local n   = #fbks+1
        local fbk = Fbkind.new(n, name, pat, comment)
        fbks[n]    = fbk
        fbks[name] = fbk
        return fbks
      end,
    addline = function (fbks, line)
        local name, pat, comment = line:match("^%s*(%S+)%s+(%S+)%s*(.*)$")
        if name then fbks:add(name, pat, comment) end
        return fbks
      end,
    addlines = function (fbks, bigstr)
        for line in bigstr:gmatch("[^\n]+") do fbks:addline(line) end
        return fbks
      end,
    --
    tostring = function (fbks)
        local f = function (n) return tostring(fbks[n]) end
        return mapconcat(f, seq(1, #fbks), "\n")
      end,
    --
    patexpand0 = function (fbks)
        local f = function (n) return fbks[n]:patexpand() end
        return mapconcat(f, seq(1, #fbks), " +\n\n")
      end,
    patexpand = function (fbks)
        return 'lpeg.P"https://www.facebook.com" * (\n\n' ..
                 fbks:patexpand0() .. '\n\n)'
      end,
    patcompile = function (fbks)
        fbks.pat = expr(fbks:patexpand())
        return fbks
      end,
    --
    match = function (fbks, str) return fbks.pat:match(str) end,
    in_string = function (fbks, bigstr)
        return cow(function ()
            for _,url in ipairs(split(bigstr)) do
              local tbl = fbks:match(url)
              if tbl then coy(tbl.name, tbl, url) end
            end
          end)
      end,
    in_file = function (fbks, fname)
        return fbks:in_string(ee_readfile(fname))
      end,
  },
}


--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "fbkinds.lua"
bigstr = [=[
  eventnpn   /events/N/permalink/N/R              21_ok
  eventnn    /events/N/N/R                        21_ok
  eventn     /events/N/R                          1_ok
]=]
fbkinds = Fbkinds.from(bigstr)
= fbkinds
= fbkinds:patexpand()

-- fbkinds:patcompile()
= fbkinds.pat

url  = "https://www.facebook.com/events/1397247553878845/permalink/1412951502308450/"
u    =                         "/events/1397247553878845/permalink/1412951502308450/"
PP(fbkinds:match(url))

= fbkinds.eventn
= fbkinds[1]
PP(fbkinds[1]:match(u))
PP(fbkinds:match(url))

for name,tbl,url in fbkinds:in_file "~/TODO" do print(url) end

--]==]





--   __ _     _    _           _     
--  / _| |__ | | _(_)_ __   __| |___ 
-- | |_| '_ \| |/ / | '_ \ / _` / __|
-- |  _| |_) |   <| | | | | (_| \__ \
-- |_| |_.__/|_|\_\_|_| |_|\__,_|___/
--                                   
-- «fbkinds» (to ".fbkinds")
-- The default value for fbkinds is the table from fbkinds_bigstr, compiled.
fbkinds = Fbkinds.from(fbkinds_bigstr)

-- (find-es "facebook" "eventnpn")
fbkinds.eventnpn.ex = "https://www.facebook.com/events/1397247553878845/permalink/1412951502308450/"
fbkinds.eventnpn.dl = 'g(f(1)); g(f(2)); g(f(1).."_"..f(2))'
-- (find-es "facebook" "eventnn")
fbkinds.eventnn.ex = "https://www.facebook.com/events/1553809231523002/1563468630557062/"
fbkinds.eventnn.dl = 'g(f(1)); g(f(2)); g(f(1).."_"..f(2))'
-- (find-es "facebook" "eventn")
fbkinds.eventn.ex = "https://www.facebook.com/events/1006218776073768/"
fbkinds.eventn.dl = "g(f(1))"
-- (find-es "facebook" "groupnpn")
fbkinds.groupnpn.ex = "https://www.facebook.com/groups/249360678448319/permalink/621939097857140/"
fbkinds.groupnpn.dl = "g(f(1)); g(f(2)); g(f(1)..'_'..f(2))"
-- (find-es "facebook" "groupwpn")
fbkinds.groupwpn.ex = "https://www.facebook.com/groups/contatimprovbra/permalink/947586865274406/"
fbkinds.groupwpn.dl = "g(nid(f(1))); g(f(2)); g(nid(f(1))..'_'..f(2))"
-- (find-es "facebook" "groupnn")
fbkinds.groupnn.ex = "https://www.facebook.com/groups/105487286280461/240851649410690/"
fbkinds.groupnn.dl = "g(f(1)); g(f(2)); g(f(1)..'_'..f(2))"
-- (find-es "facebook" "groupwn")
fbkinds.groupwn.ex = "https://www.facebook.com/groups/transgente/639092892836474/"
fbkinds.groupwn.dl = "g(nid(f(1))); g(f(2)); g(nid(f(1))..'_'..f(2))"
-- (find-es "facebook" "groupn")
fbkinds.groupn.ex = "https://www.facebook.com/groups/1398505100440487/"
fbkinds.groupn.dl = "g(f(1))"
-- (find-es "facebook" "groupw")
fbkinds.groupw.ex = "https://www.facebook.com/groups/transgente"
fbkinds.groupw.dl = "g(nid(f(1)))"
-- (find-es "facebook" "mediawannn")
fbkinds.mediawannn.ex = "https://www.facebook.com/paulakossatz/media_set?set=a.10202222226170686.1073741844.1040842293&type=1"
fbkinds.mediawannn.dl = "g(f(4))"
-- (find-es "facebook" "mediawnnn")
fbkinds.mediawnnn.err = "I don't have urls of this kind"
-- (find-es "facebook" "mediawn")
fbkinds.mediawn.err = "I don't have urls of this kind"
-- (find-es "facebook" "noteswwn")
fbkinds.noteswwn.err = "I don't have urls of this kind"
-- (find-es "facebook" "notesn")
fbkinds.notesn.ex = "https://www.facebook.com/notes/320469381448610/"
fbkinds.notesn.err = "(#12) notes API is deprecated for versions v2.0 and higher"
-- (find-es "facebook" "pageswn")
fbkinds.pageswn.ex = "https://www.facebook.com/pages/Viomundo/109725279084911"
fbkinds.pageswn.dl = "g(f(2))"
-- (find-es "facebook" "storynn")
fbkinds.storynn.ex = "https://www.facebook.com/permalink.php?story_fbid=10152640860900894&id=696685893&fref=nf"
fbkinds.storynn.dl = "g(f(2))"
fbkinds.storynn.err = "(#12) singular statuses API is deprecated for versions v2.4 and higher"
-- (find-es "facebook" "photonn")
fbkinds.photonn.ex = "https://www.facebook.com/photo.php?fbid=10151256245188625&set=t.100002233344951"
fbkinds.photonn.dl = "g(f(1)); g(f(2))"
fbkinds.photonn.err = "I don't know how to retrieve the photo"
-- (find-es "facebook" "photonnnn")
fbkinds.photonnnn.ex = "https://www.facebook.com/photo.php?fbid=10201336092313990&set=a.1569106477271.73917.1523735650&type=1&permPage=1"
fbkinds.photonnnn.dl = "g(f(1))"
-- (find-es "facebook" "photono")
fbkinds.photono.err = "I don't have urls of this kind"
-- (find-es "facebook" "photot")
fbkinds.photot.ex = "https://www.facebook.com/102015223300293/photos/t.100000842030889/317158085119338/"
fbkinds.photot.dl = "g(f(1)); g(f(2)); g(f(3))"
-- (find-es "facebook" "photogm")
fbkinds.photogm.ex = "https://www.facebook.com/1442002182737691/photos/gm.1466213243643988/1471817019756207/?type=1"
fbkinds.photogm.dl = "g(f(1)); g(f(2)); g(f(3))"
-- (find-es "facebook" "photona")
fbkinds.photona.ex = "https://www.facebook.com/21038112178/photos/a.441569537178.245171.21038112178/10152790891782179/?type=1&fref=nf"
fbkinds.photona.dl = "g(f(1)); g(f(2)); g(f(4))"
-- (find-es "facebook" "photowa")
fbkinds.photowa.ex = "https://www.facebook.com/AKPress/photos/a.215376115248.261941.205965845248/10154741098510249/?type=1"
fbkinds.photowa.dl = "g(f(1)); g(f(4)); g(f(5))"
-- (find-es "facebook" "photovs")
fbkinds.photovs.err = "I don't have urls of this kind"
-- (find-es "facebook" "photov")
fbkinds.photov.ex = "https://www.facebook.com/photo.php?v=10152413352959175"
fbkinds.photov.dl = "g(f(1))"
-- (find-es "facebook" "postwn")
fbkinds.postwn.ex = "https://www.facebook.com/CopBlock/posts/10152706679833189"
fbkinds.postwn.dl = "g(nid(f(1))); g(nid(f(1))..'_'..f(2))"
-- (find-es "facebook" "videon")
fbkinds.videon.ex = "https://www.facebook.com/video.php?v=823660551012161"
fbkinds.videon.dl = "g(f(1))"




--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "fbkinds.lua"
= fbkinds
for name,tbl,url in fbkinds:in_file "~/TODO" do print(url) end

name = "eventnpn"
fbk = fbkinds[name]
= fbk.ex
tbl = PP(fbkinds:match(fbk.ex))
= tbl.name == name

--]==]




--   __ _         _ _ 
--  / _| |__   __| | |
-- | |_| '_ \ / _` | |
-- |  _| |_) | (_| | |
-- |_| |_.__/ \__,_|_|
--                    
-- «fbdl» (to ".fbdl")
-- See: (find-fbcache "fbnameid.lua" "nameid_maybe")
-- and: (find-fbcache "fbnameid.lua" "fbget_maybe")
--
-- Experimental & messy

isfbid = function (str) return not str:match"%?" end
fbdl_f = function (n) return (tbl and tbl[n]) or "?" end
fbdl_g = function (fbid) if isfbid(fbid) then fbget(fbid) end; return fbid end
fbdl_g = function (fbid) if isfbid(fbid) then fbget(fbid) end; return PP(fbid) end
fbdl_nid = function (fbid) return isfbid(fbid) and nameid_maybe(fbid) or "?" end

fbdl_preamble = [[
  tbl = ...
  local f, g, nid = fbdl_f, fbdl_g, fbdl_nid
]]
fbdl_eval = function (url, tbl, dlcode)
    return loadstring(fbdl_preamble .. dlcode, "fdbl:"..tbl.name)(tbl)
  end
fbdl = function (url, tbl)
    local tbl = tbl or fbkinds:match(url)
    if not tbl then return "Not a Facebook URL" end
    local dlcode = fbkinds[tbl.name].dl
    if not dlcode then return "No download code" end
    return fbdl_eval(url, tbl, dlcode)
  end


-- «fbdl-tests» (to ".fbdl-tests")
--[==[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
require "fbkinds"  -- (find-fbcache "fbcache3.lua")
name = "eventnpn"
= fbkinds[name].ex
= fbkinds[name].dl
= fbdl(fbkinds[name].ex)

name = "eventnpn"
url = fbkinds[name].ex
tbl = fbkinds:match(url)
f, g, nid = fbdl_f, fbdl_g, fbdl_nid
= fbkinds[name].dl
g(f(1)); g(f(2)); g(f(1).."_"..f(2))

--]==]




--[[
* (eepitch-lua51)
* (eepitch-kill)
* (eepitch-lua51)
dofile "fbkinds.lua"
PP(fbkinds:match "https://www.facebook.com/photo.php?fbid=10205742030739697&set=pb.1523735650.-2207520000.1453614397.&type=3&theater")
-- new

--]]


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