diff options
-rw-r--r-- | lib/attr.lua | 232 | ||||
-rw-r--r-- | lib/util.lua | 11 | ||||
-rw-r--r-- | main.lua | 8 | ||||
-rw-r--r-- | server/opensubtitles.lua | 90 |
4 files changed, 335 insertions, 6 deletions
diff --git a/lib/attr.lua b/lib/attr.lua new file mode 100644 index 0000000..8c1613a --- /dev/null +++ b/lib/attr.lua @@ -0,0 +1,232 @@ +#!/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?', + } + 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 = { + name = 10, + season = 10, + episode = 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] then + goto continue + end + + if k == 'name' then + for _, name in pairs(v) do + if util.array_search(a2.name, name) then + score = score + key_score.name + end + 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, +} diff --git a/lib/util.lua b/lib/util.lua index d52922d..6263507 100644 --- a/lib/util.lua +++ b/lib/util.lua @@ -70,6 +70,16 @@ local array_merge = function (a1, a2) return a end +local array_search = function (a, key) + for _, v in pairs(a) do + if v == key then + return true + end + end + + return false +end + local table_print = function (t) for k, v in pairs(t) do print( '|'.. k .. '=' .. v .. '|') @@ -186,6 +196,7 @@ return { table_print = table_print, table_match_or_any = table_match_or_any, array_merge = array_merge, + array_search = array_search, zip_ext_first = zip_ext_first, string_vid_path_to_name = string_vid_path_to_name, opensubtitles_hash = opensubtitles_hash, @@ -42,7 +42,7 @@ local sub_needed = function () end local sub_setup = function () - local out, name, path, rc + local out, name, path, rc, filesize mp.osd_message('fetching subtitle') @@ -61,8 +61,12 @@ local sub_setup = function () if not util.file_exists(path) then name = mp.get_property_native('media-title') end + filesize = mp.get_property_native('file-size') - rc = opensubtitles.search(path, out, name) + rc = opensubtitles.search(path, out, { + name = name, + filesize = filesize + }) if not rc then rc = subscene.search(path, out, name) end diff --git a/server/opensubtitles.lua b/server/opensubtitles.lua index b797f44..f0c6195 100644 --- a/server/opensubtitles.lua +++ b/server/opensubtitles.lua @@ -2,6 +2,7 @@ local curl = require 'lib/curl' local util = require 'lib/util' +local attr = require 'lib/attr' -- [[ languages supported by opensubtitles ]] -- local languages = { @@ -134,14 +135,94 @@ local search_ohash = function (ohash) end end -local search = function (path, out, name) - local ohash, link +local ids_fetch = function (page) + local iter, no_name, line, id, name, tab + + tab = {} + no_name = 0 + iter = page:gmatch('[^\n\r]+') + while true do + line = iter() + if not line then + break + end + + id = line:match('/en/subtitles/%d*') + if id then + id = id:match('%d+$') + + line = iter() -- movie + if line:find('%.%.%.$') then + -- name cuts off... + name = line:gsub('"[^"]*$', '') + name = name:match('[^"]+$') + else + name = line:gsub('<br/><a rel.*$', '') + name = name:match('[^>]+$') + end + + if not name then + line = iter() + + if line:find('^%[S%d%dE%d%d%]$') then + -- it's a series + line = iter() + if line:find('%.%.%.$') then + name = line:gsub('^.*title="', '') + name = name:match('[^"]+') + else + name = line:match('[^<]+') + end + else + -- no name + name = tostring(no_name) + no_name = no_name + 1 + end + end + + tab[name] = id + end + end + + return tab +end + +local search_filesize = function (filesize, name) + local fetch, hcode, url, id, a + + a = attr.build(name) + + url = domain .. '/en' .. '/search/sublanguageid-' .. languages[language] + if a.season and a.episode then + url = url .. '/season-' .. a.season .. '/episode-' .. a.episode + end + url = url .. '/moviebytesize-' .. filesize + + fetch, hcode = curl.get(url, nil, nil, tries) + if not hcode then + return nil + end + + print(url) + util.table_print(ids_fetch(fetch)) + id = attr.fuzzy(name, ids_fetch(fetch)) + if id then + print(domain .. '/en/subtitleserve/sub/' .. id) + return domain .. '/en/subtitleserve/sub/' .. id + end +end + +local search = function (path, out, info) + local ohash, link, name if util.file_exists(path) then ohash = util.opensubtitles_hash(path) link = search_ohash(ohash) - else - name = name or util.string_vid_path_to_name(path) + end + + if not link then + name = info.name or util.string_vid_path_to_name(path) + link = search_filesize(info.filesize, name) end if link then @@ -151,5 +232,6 @@ end return { search_ohash = search_ohash, + search_filesize = search_filesize, search = search } |