Files
store/github-utilities/github-ratelimit.sune

1 line
9.9 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[{"id":"7tcehix","name":"Github Rate Limit","pinned":false,"avatar":"","url":"gh://sune-org/store/github-utilities/github-ratelimit.sune","updatedAt":1762718343720,"settings":{"model":"google/gemini-2.5-pro","temperature":"","top_p":"","top_k":"","frequency_penalty":"","repetition_penalty":"","min_p":"","top_a":"","verbosity":"","reasoning_effort":"default","system_prompt":"","html":"<section id=\"rateLimitSune\" class=\"mx-3 my-3 max-w-xl rounded-2xl border border-gray-200 bg-white/95 shadow-sm px-3 py-2 space-y-2 text-xs text-gray-800\">\n <div class=\"flex items-center justify-between gap-2\">\n <div class=\"flex items-center gap-2\">\n <span class=\"inline-flex h-6 w-6 items-center justify-center rounded-full bg-gray-900 text-white text-xs\">✺</span>\n <div class=\"leading-tight\">\n <div class=\"font-semibold text-[11px] tracking-wide uppercase text-gray-600\">\n GitHub Rate Limits\n </div>\n <div class=\"text-[10px] text-gray-400\">\n v1.0.0 · Live from api.github.com/rate_limit\n </div>\n </div>\n </div>\n <button id=\"ghRateRefresh\" class=\"h-7 px-2 flex items-center gap-1 rounded-xl bg-gray-900 text-white text-[9px] hover:bg-gray-800 active:scale-[.97] transition\">\n <svg class=\"w-3 h-3\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M21 12a9 9 0 0 0-9-9 9.002 9.002 0 0 0-8.485 6M3 12a9 9 0 0 0 9 9 9.002 9.002 0 0 0 8.485-6M3 3v6h6M21 21v-6h-6\"/>\n </svg>\n <span>Refresh</span>\n </button>\n </div>\n\n <div class=\"grid grid-cols-2 gap-2\">\n <div class=\"border border-gray-100 rounded-xl px-2 py-1.5 bg-gray-50/80\">\n <div class=\"flex items-center justify-between gap-1 mb-0.5\">\n <span class=\"font-semibold text-[9px] text-gray-600 uppercase tracking-wide\">Unauthenticated</span>\n <span id=\"ghNoTokenStatus\" class=\"text-[8px] px-1.5 py-0.5 rounded-full bg-gray-200 text-gray-700\">…</span>\n </div>\n <div class=\"flex items-baseline gap-1\">\n <span id=\"ghNoTokenRemaining\" class=\"font-semibold text-[15px] text-gray-900\">-</span>\n <span class=\"text-[8px] text-gray-500\">remaining</span>\n </div>\n <div class=\"flex items-center justify-between gap-1\">\n <div class=\"flex flex-col\">\n <span class=\"text-[8px] text-gray-500\">Limit</span>\n <span id=\"ghNoTokenLimit\" class=\"text-[9px] text-gray-700\">-</span>\n </div>\n <div class=\"flex flex-col text-right\">\n <span class=\"text-[8px] text-gray-500\">Resets</span>\n <span id=\"ghNoTokenReset\" class=\"text-[8px] text-gray-700\">-</span>\n </div>\n </div>\n <div class=\"mt-1 h-1.5 w-full bg-gray-200 rounded-full overflow-hidden\">\n <div id=\"ghNoTokenBar\" class=\"h-full bg-gray-900 rounded-full transition-all duration-300\" style=\"width:0%\"></div>\n </div>\n </div>\n\n <div class=\"border border-gray-100 rounded-xl px-2 py-1.5 bg-gray-50/80\">\n <div class=\"flex items-center justify-between gap-1 mb-0.5\">\n <span class=\"font-semibold text-[9px] text-gray-600 uppercase tracking-wide flex items-center gap-1\">\n With Token\n <span id=\"ghTokenDot\" class=\"inline-block w-1.5 h-1.5 rounded-full bg-gray-300\"></span>\n </span>\n <span id=\"ghTokenStatus\" class=\"text-[8px] px-1.5 py-0.5 rounded-full bg-gray-200 text-gray-700\">No token</span>\n </div>\n <div class=\"flex items-baseline gap-1\">\n <span id=\"ghTokenRemaining\" class=\"font-semibold text-[15px] text-gray-900\">-</span>\n <span class=\"text-[8px] text-gray-500\">remaining</span>\n </div>\n <div class=\"flex items-center justify-between gap-1\">\n <div class=\"flex flex-col\">\n <span class=\"text-[8px] text-gray-500\">Limit</span>\n <span id=\"ghTokenLimit\" class=\"text-[9px] text-gray-700\">-</span>\n </div>\n <div class=\"flex flex-col text-right\">\n <span class=\"text-[8px] text-gray-500\">Resets</span>\n <span id=\"ghTokenReset\" class=\"text-[8px] text-gray-700\">-</span>\n </div>\n </div>\n <div class=\"mt-1 h-1.5 w-full bg-gray-200 rounded-full overflow-hidden\">\n <div id=\"ghTokenBar\" class=\"h-full bg-gray-900 rounded-full transition-all duration-300\" style=\"width:0%\"></div>\n </div>\n </div>\n </div>\n\n <div class=\"flex items-center gap-1 justify-between\">\n <div class=\"flex items-center gap-1\">\n <span class=\"inline-flex items-center rounded-full bg-gray-50 text-[7px] px-1.5 py-0.5 text-gray-500\">\n Uses USER.githubToken if set. No token is stored on our servers.\n </span>\n </div>\n <div class=\"flex items-center gap-1 text-[7px] text-gray-400\">\n <span id=\"ghRateUpdatedAt\">Last: —</span>\n </div>\n </div>\n\n <script>\n ;(()=>{const S=window.SUNE?.id||\"gh-rate-limit\"\n const Q=e=>document.getElementById(e)\n const T=(u=0)=>{if(!u)return\"\";const d=new Date(u*1e3),n=new Date(Date.now())\n const m=Math.max(0,Math.round((d-n)/6e4))\n return m?m+\"m (\"+d.toLocaleTimeString()+\")\":\"now\"}\n const B=(r,l)=>{if(!l||!r)return\"0%\";const p=Math.max(0,Math.min(1,r/l));return(100*p).toFixed(0)+\"%\"}\n const U=ts=>{Q(\"ghRateUpdatedAt\").textContent=\"Last: \"+(ts?new Date(ts).toLocaleTimeString():\"—\")}\n const L=(p,b)=>{if(!p||!p.remaining&&p.remaining!==0)return{remaining:\"-\",limit:\"-\",reset:\"\",bar:\"0%\"}\n return{\n remaining:p.remaining,\n limit:p.limit,\n reset:T(p.reset),\n bar:B(p.remaining,p.limit)\n }}\n const F=async(h,token)=>{try{\n const r=await fetch(\"https://api.github.com/rate_limit\",{headers:h})\n const j=await r.json()\n return{ok:r.ok,data:j,error:!r.ok?j?.message||r.statusText:\"\",ts:r.headers.get(\"date\")?Date.parse(r.headers.get(\"date\")):Date.now()}\n }catch(e){return{ok:!1,data:null,error:e.message,ts:Date.now()}}}\n const P=async()=>{const token=window.USER?.githubToken||window.USER?.ghToken\n const has=!!token\n const headersBase={'Accept':'application/vnd.github+json'}\n const [noTok, tok]=await Promise.all([\n F(headersBase),\n has?F({...headersBase,'Authorization':\"Bearer \"+token,'X-GitHub-Api-Version':'2022-11-28'}):Promise.resolve({ok:!1,data:null,error:\"No token\",ts:Date.now()})\n ])\n // unauth\n if(noTok.data?.resources?.core){\n const s=L(noTok.data.resources.core,\"ghNoTokenBar\")\n Q(\"ghNoTokenRemaining\").textContent=s.remaining\n Q(\"ghNoTokenLimit\").textContent=s.limit\n Q(\"ghNoTokenReset\").textContent=s.reset\n Q(\"ghNoTokenBar\").style.width=s.bar\n Q(\"ghNoTokenStatus\").textContent=noTok.ok?\"OK\":\"Err\"\n }else{\n Q(\"ghNoTokenRemaining\").textContent=\"-\"\n Q(\"ghNoTokenLimit\").textContent=\"-\"\n Q(\"ghNoTokenReset\").textContent=\"\"\n Q(\"ghNoTokenBar\").style.width=\"0%\"\n Q(\"ghNoTokenStatus\").textContent=\"Err\"\n }\n // token\n const dot=Q(\"ghTokenDot\"),st=Q(\"ghTokenStatus\")\n if(!has){\n st.textContent=\"No token\"\n dot.className=\"inline-block w-1.5 h-1.5 rounded-full bg-gray-300\"\n Q(\"ghTokenRemaining\").textContent=\"-\"\n Q(\"ghTokenLimit\").textContent=\"-\"\n Q(\"ghTokenReset\").textContent=\"\"\n Q(\"ghTokenBar\").style.width=\"0%\"\n }else if(tok.data?.resources?.core){\n const s=L(tok.data.resources.core,\"ghTokenBar\")\n Q(\"ghTokenRemaining\").textContent=s.remaining\n Q(\"ghTokenLimit\").textContent=s.limit\n Q(\"ghTokenReset\").textContent=s.reset\n Q(\"ghTokenBar\").style.width=s.bar\n st.textContent=tok.ok?\"Token OK\":\"Token Err\"\n dot.className=\"inline-block w-1.5 h-1.5 rounded-full \"+(tok.ok?\"bg-emerald-500\":\"bg-amber-400\")\n }else{\n st.textContent=tok.error||\"Token Err\"\n dot.className=\"inline-block w-1.5 h-1.5 rounded-full bg-amber-400\"\n Q(\"ghTokenRemaining\").textContent=\"-\"\n Q(\"ghTokenLimit\").textContent=\"-\"\n Q(\"ghTokenReset\").textContent=\"\"\n Q(\"ghTokenBar\").style.width=\"0%\"\n }\n U(tok.ts||noTok.ts)\n try{localStorage.setItem(S,JSON.stringify({noTok,tok,at:Date.now()}))}catch{}\n }\n // hydrate from cache (fast)\n ;(()=>{try{\n const c=localStorage.getItem(S);if(!c)return\n const{noTok,tok,at}=JSON.parse(c)||{}\n if(noTok?.data?.resources?.core){\n const s=L(noTok.data.resources.core)\n Q(\"ghNoTokenRemaining\").textContent=s.remaining\n Q(\"ghNoTokenLimit\").textContent=s.limit\n Q(\"ghNoTokenReset\").textContent=s.reset\n Q(\"ghNoTokenBar\").style.width=s.bar\n Q(\"ghNoTokenStatus\").textContent=noTok.ok?\"OK\":\"Err\"\n }\n if(tok){\n const has=!!(window.USER?.githubToken||window.USER?.ghToken)\n const dot=Q(\"ghTokenDot\"),st=Q(\"ghTokenStatus\")\n if(has&&tok.data?.resources?.core){\n const s=L(tok.data.resources.core)\n Q(\"ghTokenRemaining\").textContent=s.remaining\n Q(\"ghTokenLimit\").textContent=s.limit\n Q(\"ghTokenReset\").textContent=s.reset\n Q(\"ghTokenBar\").style.width=s.bar\n st.textContent=tok.ok?\"Token OK\":\"Token Err\"\n dot.className=\"inline-block w-1.5 h-1.5 rounded-full \"+(tok.ok?\"bg-emerald-500\":\"bg-amber-400\")\n }else if(!has){\n st.textContent=\"No token\"\n dot.className=\"inline-block w-1.5 h-1.5 rounded-full bg-gray-300\"\n }\n }\n U(at)\n }catch(e){}\n })()\n Q(\"ghRateRefresh\").onclick=e=>{e.preventDefault();P()}\n P()\n })()\n </script>\n</section>\n","extension_html":"<sune src='https://raw.githubusercontent.com/sune-org/store/refs/heads/main/sync.sune' private></sune>","hide_composer":false,"include_thoughts":false,"json_output":false,"ignore_master_prompt":false,"json_schema":""},"storage":{}}]