#!/usr/bin/env lua local util = require("lib.util") local extract = function(name, patterns) local r for _, p in pairs(patterns) do r = r or name:match(p) name = name:gsub(p, "") end return name, r end local build_dlim = function(name, attrs) local dlim, r attrs = attrs or {} dlim = "[%-%.%s]?" local vcodecs = { "[M]m[Pp][Ee][Gg]" .. dlim .. "[1234]", } local acodecs = { "[Dd][Tt][Ss]" .. dlim .. "[Hh][Dd]", "[Dd][Dd]" .. dlim .. "[57]%.1", } local sources = { "[Ww][Ee][Bb]" .. dlim .. "[Dd][Ll]", "[Hh][Dd]" .. dlim .. "[Tt][Vv]", "[Hh][Dd]" .. dlim .. "[Tt][Ss]", } local series = { "[Ss]%d%d?" .. dlim .. "[Ee]%d%d?", "[Ss]%d%d?" .. dlim .. "[Ee][Pp]" .. dlim .. "%d%d?", "Season" .. dlim .. "%d%d?" .. dlim .. "Episode" .. dlim .. "%d%d?", } local sizes = { "%d%d%d" .. dlim .. "[Mm][Bb]", "%d%d?%.%d%d?" .. dlim .. "[Gg][Bb]", } local depths = { "1[02]" .. dlim .. "[Bb][Ii][Tt]", } name, attrs.vcodec = extract(name, vcodecs) name, attrs.source = extract(name, sources) name, attrs.acodecs = extract(name, acodecs) name, attrs.size = extract(name, sizes) name, attrs.depth = extract(name, depths) name, r = extract(name, series) if r then attrs.season = tonumber(r:match("%d+")) attrs.episode = tonumber(r:match("%d+$")) end return name, attrs end local build_atom = function(name, attrs) local r, year attrs = attrs or {} local vcodecs = { "[Aa][Vv]1", "[xXHh]26[345]", "[Aa][Vv][Cc]", "[Hh][Ee][Vv][Cc]", "[Xx][Vv][Ii][Dd]", } local acodecs = { "[Oo][Pp][Uu][Ss]", "[Aa][Aa][Cc]", "[Ee]?[Aa][Cc]3", "[Dd][Tt][Ss]", } local sources = { "[Bb][Ll][Uu][Rr][Aa][Yy]", "[Bb][Rr][Rr][Ii][Pp]", "[Dd][Vv][Dd][Rr][Ii][Pp]", "[Ww][Ee][Bb][Rr][Ii][Pp]", "[Hh][Dd][Rr][Ii][Pp]", "[Rr][Ee][Rr][Ii][Pp]", } local reses = { "2160[Pp]", "1440[Pp]", "1080[Pp]", "720[Pp]", "480[Pp]", "[Uu][Hh][Dd]", "4[Kk]", } local series = { "%d%d[Xx]%d%d", } local channels = { "6[Cc][Hh]", "[57]%.1", } name, attrs.vcodec = extract(name, vcodecs) name, attrs.source = extract(name, sources) name, attrs.res = extract(name, reses) name, attrs.acodecs = extract(name, acodecs) name, attrs.channel = extract(name, channels) name, r = extract(name, series) if r then attrs.season = tonumber(r:match("%d+")) attrs.episode = tonumber(r:match("%d+$")) end for y in name:gmatch("%d%d%d%d") do year = tonumber(y) if year > 1900 and year <= tonumber(os.date("%Y")) then attrs.year = y end end if attrs.year then name = name:gsub(tostring(attrs.year), "") end return name, attrs end local build_low = function(name, attrs) local low_attr, lows lows = { "SDH" } low_attr = {} for _, low in pairs(lows) do low_attr[#low_attr + 1] = name:match(low) name = name:gsub(low, "") end attrs = attrs or {} if #low_attr > 0 then attrs.low = low_attr end return name, attrs end local build_title = function(name, attrs) attrs.title = {} for w in name:gmatch("%w+") do attrs.title[#attrs.title + 1] = w end if #attrs.title > 1 then attrs.scene = attrs.title[#attrs.title] attrs.title[#attrs.title] = nil end return attrs end local build = function(name) local attrs = {} name = build_dlim(name, attrs) name = build_atom(name, attrs) name = build_low(name, attrs) build_title(name, attrs) return attrs end local weigh = function(a1, a2) local key_score, score key_score = { season = 15, episode = 15, title = 10, source = 7, scene = 5, vcodec = 3, acodec = 3, rese = 2, default = 1, } score = 0 for k, v in pairs(a1) do if not a2[k] or k == "episode" then goto continue end if k == "title" then for _, title in pairs(v) do if util.array_search(a2.title, title) then score = score + key_score.title end end elseif k == "season" then if a1.season == a2.season and a1.episode == a2.episode then score = score + key_score.season + key_score.episode end else if v == a2[k] then score = score + (key_score[k] or key_score.default) end end ::continue:: end return score end local fuzzy = function(name, tab) local name_attr, high, score high = { score = 0, name = next(tab), } name_attr = build(name) for k in pairs(tab) do score = weigh(name_attr, build(k)) if score > high.score then high.score = score high.name = k end end return tab[high.name] end return { build = build, fuzzy = fuzzy, }