102102 .copy-button : hover : not (: disabled ) {
103103 background : # 45a049 ;
104104 }
105+ .gist-button {
106+ background : # 2ea44f ;
107+ margin-right : 10px ;
108+ }
109+ .gist-button : hover : not (: disabled ) {
110+ background : # 2c974b ;
111+ }
112+ .gist-links {
113+ margin : 10px 0 ;
114+ }
115+ .gist-links a {
116+ display : block;
117+ margin : 5px 0 ;
118+ color : # 0066cc ;
119+ }
120+ # authLink {
121+ color : # 0066cc ;
122+ cursor : pointer;
123+ text-decoration : underline;
124+ }
105125 </ style >
106126</ head >
107127< body >
@@ -136,6 +156,13 @@ <h1>Prompt GPT-4o audio</h1>
136156 </ div >
137157
138158 < div id ="jsonContainer " class ="json-container " style ="display: none; ">
159+ < div id ="gistContainer ">
160+ < span id ="authLinkContainer " style ="display: none; ">
161+ < a id ="authLink "> Authenticate with GitHub</ a >
162+ </ span >
163+ < button id ="saveGistBtn " class ="gist-button " style ="display: none; "> Save as Gist</ button >
164+ < div id ="gistLinks " class ="gist-links "> </ div >
165+ </ div >
139166 < h3 > API Response:</ h3 >
140167 < textarea id ="responseJson " readonly > </ textarea >
141168 < button id ="copyJsonBtn " class ="copy-button "> Copy to clipboard</ button >
@@ -154,6 +181,10 @@ <h3>API Response:</h3>
154181 const jsonContainer = document . getElementById ( 'jsonContainer' ) ;
155182 const responseJson = document . getElementById ( 'responseJson' ) ;
156183 const copyJsonBtn = document . getElementById ( 'copyJsonBtn' ) ;
184+ const saveGistBtn = document . getElementById ( 'saveGistBtn' ) ;
185+ const authLinkContainer = document . getElementById ( 'authLinkContainer' ) ;
186+ const authLink = document . getElementById ( 'authLink' ) ;
187+ const gistLinks = document . getElementById ( 'gistLinks' ) ;
157188
158189 function showError ( message ) {
159190 errorDiv . textContent = message ;
@@ -166,6 +197,84 @@ <h3>API Response:</h3>
166197 errorDiv . style . display = 'none' ;
167198 }
168199
200+ function checkGithubAuth ( ) {
201+ const token = localStorage . getItem ( 'github_token' ) ;
202+ if ( token ) {
203+ authLinkContainer . style . display = 'none' ;
204+ saveGistBtn . style . display = 'inline-block' ;
205+ } else {
206+ authLinkContainer . style . display = 'inline-block' ;
207+ saveGistBtn . style . display = 'none' ;
208+ }
209+ }
210+
211+ function startAuthPoll ( ) {
212+ const pollInterval = setInterval ( ( ) => {
213+ if ( localStorage . getItem ( 'github_token' ) ) {
214+ checkGithubAuth ( ) ;
215+ clearInterval ( pollInterval ) ;
216+ }
217+ } , 1000 ) ;
218+ }
219+
220+ authLink . addEventListener ( 'click' , ( ) => {
221+ window . open ( 'https://tools.simonwillison.net/github-auth' , 'github-auth' , 'width=600,height=800' ) ;
222+ startAuthPoll ( ) ;
223+ } ) ;
224+
225+ async function createGist ( ) {
226+ const token = localStorage . getItem ( 'github_token' ) ;
227+ if ( ! token ) {
228+ checkGithubAuth ( ) ;
229+ return ;
230+ }
231+
232+ try {
233+ saveGistBtn . disabled = true ;
234+ saveGistBtn . textContent = 'Saving...' ;
235+
236+ const response = await fetch ( 'https://api.github.com/gists' , {
237+ method : 'POST' ,
238+ headers : {
239+ 'Authorization' : `token ${ token } ` ,
240+ 'Content-Type' : 'application/json' ,
241+ } ,
242+ body : JSON . stringify ( {
243+ description : 'GPT-4o audio response' ,
244+ public : true ,
245+ files : {
246+ 'response.json' : {
247+ content : responseJson . value
248+ }
249+ }
250+ } )
251+ } ) ;
252+
253+ if ( ! response . ok ) {
254+ throw new Error ( 'Failed to create gist' ) ;
255+ }
256+
257+ const data = await response . json ( ) ;
258+ const gistId = data . id ;
259+ const gistUrl = data . html_url ;
260+ const playerUrl = `https://tools.simonwillison.net/gpt-4o-audio-player?gist=${ gistId } ` ;
261+
262+ gistLinks . innerHTML = `
263+ <a href="${ gistUrl } " target="_blank">View Gist</a>
264+ <a href="${ playerUrl } " target="_blank">Audio player</a>
265+ ` ;
266+ } catch ( error ) {
267+ console . error ( 'Gist creation failed:' , error ) ;
268+ localStorage . removeItem ( 'github_token' ) ;
269+ checkGithubAuth ( ) ;
270+ } finally {
271+ saveGistBtn . disabled = false ;
272+ saveGistBtn . textContent = 'Save as Gist' ;
273+ }
274+ }
275+
276+ saveGistBtn . addEventListener ( 'click' , createGist ) ;
277+
169278 function getAPIKey ( ) {
170279 let apiKey = localStorage . getItem ( 'openai_api_key' ) ;
171280 if ( ! apiKey ) {
@@ -244,15 +353,14 @@ <h3>API Response:</h3>
244353 throw new Error ( data . error ?. message || 'API request failed' ) ;
245354 }
246355
247- // Display raw JSON response
248356 responseJson . value = JSON . stringify ( data , null , 2 ) ;
249357 jsonContainer . style . display = 'block' ;
358+ gistLinks . innerHTML = '' ;
359+ checkGithubAuth ( ) ;
250360
251- // Extract audio data and transcript
252361 const audioData = data . choices [ 0 ] . message . audio . data ;
253362 const transcript = data . choices [ 0 ] . message . audio . transcript ;
254363
255- // Create audio blob and URL
256364 const binaryData = atob ( audioData ) ;
257365 const arrayBuffer = new ArrayBuffer ( binaryData . length ) ;
258366 const uint8Array = new Uint8Array ( arrayBuffer ) ;
@@ -262,13 +370,11 @@ <h3>API Response:</h3>
262370 const blob = new Blob ( [ uint8Array ] , { type : 'audio/wav' } ) ;
263371 const audioUrl = URL . createObjectURL ( blob ) ;
264372
265- // Update UI
266373 audioPlayer . src = audioUrl ;
267374 transcriptDiv . textContent = transcript ;
268375 playerContainer . style . display = 'block' ;
269376 clearError ( ) ;
270377
271- // Set up download button
272378 downloadBtn . onclick = ( ) => {
273379 const a = document . createElement ( 'a' ) ;
274380 a . href = audioUrl ;
@@ -286,14 +392,16 @@ <h3>API Response:</h3>
286392 }
287393 }
288394
289- // Handle form submission
290395 submitBtn . addEventListener ( 'click' , submitToAPI ) ;
291396
292397 promptInput . addEventListener ( 'keypress' , ( e ) => {
293398 if ( e . key === 'Enter' && e . ctrlKey ) {
294399 submitToAPI ( ) ;
295400 }
296401 } ) ;
402+
403+ // Initial GitHub auth check
404+ checkGithubAuth ( ) ;
297405 </ script >
298406</ body >
299407</ html >
0 commit comments