-- Copyright 2025 David Vazgenovich Shakaryan local util = require('util') local catalogue = {} local mt = {} mt.__index = mt function catalogue.new() o = setmetatable({data = {}}, mt) o:add({ type = 'group', id = 'root', }) o:add({ type = 'group', id = 'favourites', parent_id = 'root', name = 'Favourites', lazy = true, -- prevent infinite recursion on search }) return o end function mt:get(id) return self.data[id] end function mt:add(entry) self.data[entry.id] = entry if entry.type == 'group' then entry.children = {} end if not entry.parent_id then return end -- dump any entries referencing nonexistent categories into a single -- catchall category if not self.data[entry.parent_id] then entry.parent_id = entry.section .. ':category:catchall' if not self.data[entry.parent_id] then self:add({ section = entry.section, type = 'group', group_type = 'category', id = entry.parent_id, parent_id = entry.section .. ':category:0', -- non-ascii symbol to sort near end name = '🞷CATCHALL🞷', }) end end local parent_children = self.data[entry.parent_id].children parent_children[#parent_children+1] = entry end function mt:load_xc_section(section) self:add({ section = section.id, type = 'group', group_type = 'category', id = section.id .. ':category:0', parent_id = 'root', name = section.name, }) -- currently, this will not correctly handle subcategories which come -- before their parent category for _, v in ipairs(section.categories) do self:add({ section = section.id, type = 'group', group_type = 'category', id = section.id .. ':category:' .. v.category_id, parent_id = section.id .. ':category:' .. v.parent_id, name = util.strip(v.category_name), }) end for _, v in ipairs(section.elements) do local vv = { section = section.id, parent_id = section.id .. ':category:' .. v.category_id, name = util.strip(v.name), } if section.type == 'series' then vv.type = 'group' vv.group_type = 'series' vv.id = section.id .. ':series:' .. v.series_id vv.series_id = v.series_id vv.image = v.cover vv.lazy = true -- avoid API calls on search else vv.type = 'stream' vv.id = section.id .. ':stream:' .. v.stream_id vv.stream_type = v.stream_type vv.stream_id = v.stream_id vv.image = v.stream_icon vv.epg_channel_id = v.epg_channel_id end self:add(vv) end end function mt:load_xc_data(sections) for _, v in ipairs(sections) do self:load_xc_section(v) end end return catalogue