BDYDB ClipBot
BDYDB
ClipBot
The team clip platform. Built for esports orgs, open to everyone.
Sign In
Team members sign in with Twitch. Individual accounts welcome — no team required.
or enter your username
Powered by bdydb-clips.pages.dev
BDYDB
ClipBot
Choose Your Space
You have access to multiple spaces
Individual Account
No team yet — you still have full access to your personal clip tools. Find a team below or request to join one.
Public Teams
Or enter an invite code:
\s*(\d+):(\d+):(\d+)[,\.](\d+)/)
if(!tm)continue;
const start=parseInt(tm[1])*3600+parseInt(tm[2])*60+parseInt(tm[3])+parseInt(tm[4])/1000;
const end=parseInt(tm[5])*3600+parseInt(tm[6])*60+parseInt(tm[7])+parseInt(tm[8])/1000;
const text=lines.slice(2).join(" ").replace(/<[^>]+>/g,"").trim();
if(text)captions.push({start,end,text});
}
return captions;
}
function generateCaptionsFromText(text, duration) {
const words=text.split(/\s+/);
const captions=[];
const wordsPerCap=6;
const capDuration=2.5;
for(let i=0;i{startCanvasLoop();bindEditorControls();},100);
}
function deleteCaption(i){
EDITOR_CAPTIONS.splice(i,1);
selectedCaption=-1;
renderPage();
setTimeout(()=>{startCanvasLoop();bindEditorControls();},100);
}
function addTextLayer(){
const text=document.getElementById("new-text-inp")?.value||"TEXT";
const size=parseInt(document.getElementById("text-size")?.value||"32");
const color=document.getElementById("text-color")?.value||"#ffffff";
const [W,H]=getCanvasSize();
EDITOR_TEXT_LAYERS.push({text,size,color,x:W/2,y:H*0.4,isEmoji:false});
toast("Text added to canvas");
renderPage();
setTimeout(()=>{startCanvasLoop();bindEditorControls();},100);
}
function addSticker(emoji){
const [W,H]=getCanvasSize();
EDITOR_TEXT_LAYERS.push({text:emoji,size:48,color:"#fff",x:W/2+(Math.random()-0.5)*100,y:H/3+(Math.random()-0.5)*100,isEmoji:true});
toast("Sticker added");
renderPage();
setTimeout(()=>{startCanvasLoop();bindEditorControls();},100);
}
function addLogoLayer(text, color){
const [W,H]=getCanvasSize();
EDITOR_TEXT_LAYERS.push({text,size:36,color,x:W/2,y:H*0.08,isEmoji:false});
toast("Logo added");
renderPage();
setTimeout(()=>{startCanvasLoop();bindEditorControls();},100);
}
// ── TOAST + LOG ───────────────────────────────────────────────
function toast(msg,type="success"){const tc=document.getElementById("toast-c");if(!tc)return;const el=document.createElement("div");el.className="toast t"+type[0];el.textContent=msg;tc.appendChild(el);setTimeout(()=>el.remove(),3400);}
function addLog(msg){LOGS.unshift({id:Date.now(),time:new Date().toLocaleTimeString(),msg});if(LOGS.length>60)LOGS.pop();}
function setProc(v){const el=document.getElementById("tb-proc");if(el)el.style.display=v?"flex":"none";}
function setApiStatus(ok){const dot=document.getElementById("api-dot"),lbl=document.getElementById("api-lbl");if(dot)dot.style.background=ok?"var(--green)":"var(--muted)";if(lbl)lbl.textContent=ok?"Worker Live":"Demo";}
function showSpin(v,msg){const el=document.getElementById("screen-spin");if(el)el.style.display=v?"flex":"none";const m=document.getElementById("spin-msg");if(m&&msg)m.textContent=msg;}
function showErr(msg){const el=document.getElementById("lerr");if(el){el.textContent=msg;el.style.display="";}}
function showScreen(name){["login","pick","request","app"].forEach(s=>{const el=s==="app"?document.getElementById("shell"):document.getElementById("screen-"+s);if(el)el.style.display=s===name?"flex":"none";});showSpin(false);}
function updateBadges(){
const myC=CLIPS.filter(c=>c.login===ME?.login).length,teamC=CLIPS.length,appC=CLIPS.filter(c=>c.approved).length;
const bm=document.getElementById("b-mine");if(bm){bm.textContent=myC;bm.style.display=myC?"":"none";}
const bt=document.getElementById("b-team");if(bt){bt.textContent=teamC;bt.style.display=teamC?"":"none";}
const bs=document.getElementById("b-sched");if(bs){bs.textContent=appC;bs.style.display=appC?"":"none";}
const bv=document.getElementById("b-vods");if(bv){bv.textContent=VODS.length;bv.style.display=VODS.length?"":"none";}
}
function updateVodBadge(){const b=document.getElementById("b-vods");if(b){b.textContent=VODS.length;b.style.display=VODS.length?"":"none";}}
function buildSidebar(){
if(!ME)return;
const isTeam=!!CUR_TEAM,isAdmin=MY_ROLE==="admin"||MY_ROLE==="superAdmin",isSA=MY_ROLE==="superAdmin";
const sdot=document.getElementById("s-dot"),sname=document.getElementById("s-team-name");
if(sdot)sdot.style.background=CUR_TEAM?CUR_TEAM.col:"#9b5de5";
if(sname)sname.textContent=CUR_TEAM?CUR_TEAM.name:"Individual";
document.getElementById("n-team").style.display=isTeam?"":"none";
document.getElementById("n-tadmin").style.display=isAdmin&&isTeam?"":"none";
document.getElementById("n-sadmin").style.display=isSA?"":"none";
const bReq=document.getElementById("b-req");if(bReq&&CUR_TEAM){const n=CUR_TEAM.pendingRequests.length;bReq.textContent=n;bReq.style.display=n?"":"none";}
document.getElementById("u-name").textContent=ME.display;
document.getElementById("u-role-disp").innerHTML=`${MY_ROLE}`;
document.getElementById("u-ava").innerHTML=ava(ME,34,"var(--red)");
document.getElementById("btn-switch").style.display=MY_TEAMS.length>1?"":"none";
const ctxLbl=document.getElementById("tb-ctx-lbl"),ctxDot=document.getElementById("tb-ctx-dot");
if(ctxLbl)ctxLbl.textContent=CUR_TEAM?CUR_TEAM.name:"Individual";
if(ctxDot)ctxDot.style.background=CUR_TEAM?CUR_TEAM.col:"#9b5de5";
const rSec=document.getElementById("s-roster-sec"),tl=document.getElementById("team-list");
if(rSec)rSec.style.display=isTeam?"":"none";
if(tl&&isTeam&&CUR_TEAM){tl.innerHTML=CUR_TEAM.members.map(m=>{const u=USERS[m.login]||{display:m.login,ini:m.login.slice(0,2).toUpperCase()};const isMe=m.login===ME.login;return`${ava(u,26,teamColor(m.login))}
${u.display}${isMe?" ★":""}
${CLIPS.filter(c=>c.login===m.login).length} clips
`;}).join("");tl.querySelectorAll(".trow").forEach(row=>row.addEventListener("click",()=>{if(isAdmin)openPersonModal(row.dataset.login);else filterMember(row.dataset.login);}));}
else if(tl)tl.innerHTML="";
}
function buildPicker(){
const el=document.getElementById("picker-grid");if(!el)return;
const spaces=[...MY_TEAMS.map(t=>({type:"team",team:t})),{type:"individual"}];
el.innerHTML=spaces.map(s=>{if(s.type==="individual")return`Individual
Personal Space
Your private clip queue
`;const t=s.team,r=t.members.find(m=>m.login===ME.login)?.role||"member";return`${t.name}
${r}
${t.members.length} members
`;}).join("");
el.querySelectorAll(".tpc").forEach(card=>{card.addEventListener("click",()=>{const pick=card.dataset.pick;if(pick==="individual")enterIndividual();else{const t=TEAMS.find(x=>x.id===pick);if(t)enterTeam(t);}});});
}
function populatePublicTeams(){
const el=document.getElementById("public-teams-list");if(!el)return;
const pub=TEAMS.filter(t=>t.public&&!t.members.some(m=>m.login===ME.login));
el.innerHTML=pub.length?pub.map(t=>`${t.tag.slice(0,2)}
${t.name}
${t.members.length} members
`).join(""):`No public teams available.
`;
el.querySelectorAll("[data-rtid]").forEach(btn=>btn.addEventListener("click",()=>requestTeam(btn.dataset.rtid)));
document.getElementById("btn-use-code")?.addEventListener("click",()=>{const code=(document.getElementById("team-code-inp")?.value||"").trim();const e=document.getElementById("req-err");if(!code){e.textContent="Enter a code.";e.style.display="";return;}useInviteCode(code,null);});
}
function showTeamPicker(){MY_TEAMS=TEAMS.filter(t=>t.members.some(m=>m.login===ME.login));showScreen("pick");buildPicker();}
// ── INIT ─────────────────────────────────────────────────────
document.getElementById("btn-twitch").addEventListener("click",()=>window.location.href=AUTH_URL);
document.getElementById("btn-dev").addEventListener("click",()=>devLogin(document.getElementById("dev-user").value));
document.getElementById("dev-user").addEventListener("keydown",e=>{if(e.key==="Enter")devLogin(document.getElementById("dev-user").value);});
document.getElementById("btn-go-individual").addEventListener("click",()=>enterIndividual());
document.getElementById("btn-out").addEventListener("click",signOut);
document.getElementById("btn-out-pick").addEventListener("click",signOut);
document.getElementById("btn-out-req").addEventListener("click",signOut);
document.getElementById("btn-switch").addEventListener("click",showTeamPicker);
document.querySelectorAll(".nitem[data-p]").forEach(el=>el.addEventListener("click",()=>nav(el.dataset.p)));
["m1-ov","m2-ov","m3-ov"].forEach(id=>{document.getElementById(id)?.addEventListener("click",e=>{if(e.target===e.currentTarget)document.getElementById(id).classList.remove("open");});});
function signOut(){ME=null;TOKEN=null;CUR_TEAM=null;MY_ROLE=null;MY_TEAMS=[];CLIPS=[];VODS=[];LOGS=[];API_OK=false;EDITOR_CLIP=null;stopCanvasLoop();if(REFRESH_INT)clearInterval(REFRESH_INT);showScreen("login");setApiStatus(false);document.getElementById("dev-user").value="";}
if(checkOAuth()){loginWithToken(TOKEN);}