#!/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,
}