-- vim:set ft=lua:
dofile(mg.script_name:gsub('[^\\/]*$','')..'util.lua')
vtag=GetVarInt(mg.request_info.query_string,'vtag') or -1
ct=CreateContentBuilder(GZIP_THRESHOLD_BYTE)
ct:Append((vtag<=0 and DOCTYPE_HTML4_STRICT or '\n')..[=[
リスト番組表 - EDCB
リスト番組表
]=])
onid,tsid,sid=GetVarServiceID(mg.request_info.query_string,'id')
date=GetVarInt(mg.request_info.query_string,'date',-10000,0) or 0
--dateクエリは今日(0時区切り)を基準(=0)とする
now=os.time()
--UTC+9の今日の始まりの日付と時刻
baseDate=math.floor((now+9*3600)/(24*3600))
baseTime=baseDate*24*3600
showServices={}
for i,v in ipairs(SelectChDataList(edcb.GetChDataList())) do
if not HIDE_SERVICES[''..v.onid..'-'..v.tsid..'-'..v.sid] then
showServices[v.onid..'-'..v.tsid..'-'..v.sid]=true
end
end
st={}
edcb.htmlEscape=15
for i,v in ipairs(edcb.GetServiceList() or {}) do
if showServices[''..v.onid..'-'..v.tsid..'-'..v.sid] then
table.insert(st, v)
end
end
SortServiceListInplace(st)
if sid==0 then
ct:Append('
\n
\n')
--3時間前までの番組
pastEvents=edcb.EnumEventInfo(st,{startTime=os.date('!*t',now+(9-3)*3600),durationSecond=3*3600})
for i,v in ipairs(st) do
present=nil
for j=BinarySearchBound(pastEvents,v,CompareFields('onid',false,'tsid',false,'sid')),#pastEvents do
if pastEvents[j].nid~=v.nid or pastEvents[j].tsid~=v.tsid or pastEvents[j].sid~=v.sid then
break
elseif not present or TimeWithZone(pastEvents[j].startTime)>TimeWithZone(present.startTime) then
present=pastEvents[j]
end
end
if not present then
--3時間前までに番組が見つからないときは9時間前まで調べる
for j,w in ipairs(edcb.EnumEventInfo({v},{startTime=os.date('!*t',now+(9-9)*3600),durationSecond=9*3600})) do
if not present or TimeWithZone(w.startTime)>TimeWithZone(present.startTime) then
present=w
end
end
end
ct:Append('
'..v.service_name..''
..(present and (not present.durationSecond or TimeWithZone(present.startTime)+present.durationSecond>now+9*3600) and present.shortInfo and
''..present.shortInfo.event_name..'' or '')
..'
\n')
end
ct:Append('
\n
\n')
else
rt={}
for i,v in ipairs(edcb.GetReserveData()) do
if v.onid==onid and v.tsid==tsid and v.sid==sid then
v.startTime=os.time(v.startTime)
rt[#rt+1]=v
end
end
--安定ソートのためreserveIDをつける
table.sort(rt,CompareFields('eid',false,'reserveID'))
rtComp=CompareFields('eid')
programReservedStart=BinarySearchBound(rt,{eid=65535},rtComp)
--前後2週間の番組だけ取得する
range={startTime=os.date('!*t',baseTime+(date-14)*24*3600),durationSecond=28*24*3600}
et=edcb.EnumEventInfo({{onid=onid,tsid=tsid,sid=sid}},range) or {}
for i,v in ipairs(edcb.EnumEventInfoArchive and edcb.EnumEventInfoArchive({{onid=onid,tsid=tsid,sid=sid}},range) or {}) do
v.past=true
table.insert(et, v)
end
table.sort(et, function(a,b) return (a.startTime and os.time(a.startTime) or 0)<(b.startTime and os.time(b.startTime) or 0) end)
ct:Append('
\n')
more=nil
for i,v in ipairs(et) do
sub=v.eventGroupInfo and #v.eventGroupInfo.eventDataList==1 and (
v.eventGroupInfo.eventDataList[1].onid~=v.onid or
v.eventGroupInfo.eventDataList[1].tsid~=v.tsid or
v.eventGroupInfo.eventDataList[1].sid~=v.sid or
v.eventGroupInfo.eventDataList[1].eid~=v.eid)
if not sub then
if v.startTime and TimeWithZone(v.startTime,9*3600)<=now and
#et>i and et[i+1].startTime and TimeWithZone(et[i+1].startTime,9*3600)>now then
v.now=true
more=more or 8
end
cont=v.contentInfoList and #v.contentInfoList>0 and math.floor(v.contentInfoList[1].content_nibble/256)%16 or 16
ct:Append('
'
..(v.startTime and ('%02d/%02d%s %02d:%02d'):format(v.startTime.month, v.startTime.day, ({'日','月','火','水','木','金','土'})[v.startTime.wday], v.startTime.hour, v.startTime.min) or '不明'))
if not v.past and (v.startTime or i==#et or et[i+1].startTime) then
--範囲内のプログラム予約
rangeStart=i>1 and v.startTime and os.time(v.startTime)
rangeEnd=i<#et and os.time(et[i+1].startTime)
for j=programReservedStart,#rt do
if rt[j].eid~=65535 then break end
if (not rangeStart or rangeStart<=rt[j].startTime) and (not rangeEnd or rt[j].startTimeプ予')
end
end
end
--通常予約
reservedIndex=not v.past and BinarySearchBound(rt,v,rtComp)
if not reservedIndex or reservedIndex>=programReservedStart or rt[reservedIndex].eid~=v.eid then
reservedIndex=nil
else
--最後以外は「重予」(重複予約)
while reservedIndex+1重予')
reservedIndex=reservedIndex+1
end
end
ct:Append((reservedIndex and ' 予' or '')..' '
..(v.shortInfo and v.shortInfo.event_name or ' ')..''
..'
\n')
if more and more>0 then
more=more-1
if more==0 then
ct:Append('\n
]=])
if sid==0 then
ct:Append([=[
]=])
else
n=GetVarInt(mg.request_info.query_string,'n',0,3) or 0
xq=GetTranscodeQueries(mg.request_info.query_string)
ct:Append('視聴 →'..(vtag==0 and 'Video' or 'DL')..'\n'
..'')
if vtag==1 then
src='view.lua?n='..n..'&id='..onid..'-'..tsid..'-'..sid..ConstructTranscodeQueries(xq)..'&ctok='..CsrfToken('view.lua')
ct:Append('\n'..VideoWrapperBegin()
..(xq.tslive and '' or
'')
..VideoWrapperEnd()..'\n'
..'
'..src..'
\n'..TranscodeScriptTemplate(true,xq.caption,xq.jikkyo,{n=n,id=onid..'-'..tsid..'-'..sid}))
if xq.tslive then
ct:Append(TsliveScriptTemplate())
elseif ALLOW_HLS then
ct:Append(HlsScriptTemplate('view.lua'))
end
end
end
ct:Append([=[
]=]
--現在の番組名を動的に追記
..(sid~=0 and [=[
]=] or '')..[=[
]=])
ct:Finish()
mg.write(ct:Pop(Response(200,'text/html','utf-8',ct.len,ct.gzip)
..'Cross-Origin-Embedder-Policy: require-corp\r\n'
..'Cross-Origin-Opener-Policy: same-origin\r\n'
..'\r\n'))