diff options
author | Sacha Chua <sacha@sachachua.com> | 2025-08-27 21:14:01 -0400 |
---|---|---|
committer | Sacha Chua <sacha@sachachua.com> | 2025-08-27 21:14:01 -0400 |
commit | b74a01462d72ae12f626ad6fd6700638e060b324 (patch) | |
tree | 60e9f67267172f33386847d44bc3b50cb137f02d | |
parent | a57eea70cc0ac443d5ac2e7ef89355a1ec3114c2 (diff) | |
download | emacsconf-el-main.tar.xz emacsconf-el-main.zip |
-rw-r--r-- | emacsconf-publish.el | 157 |
1 files changed, 144 insertions, 13 deletions
diff --git a/emacsconf-publish.el b/emacsconf-publish.el index 24c364f..3204da9 100644 --- a/emacsconf-publish.el +++ b/emacsconf-publish.el @@ -475,9 +475,15 @@ (let ((extra-info (mapconcat #'identity (delq nil (list (unless (string= (plist-get o :pronunciation) "nil") - (emacsconf-surround "Pronunciation: " (plist-get o :pronunciation) "")) + (emacsconf-surround "Pronunciation: " + (if (string-match "\\[" (or (plist-get o :pronunciation) "")) + (org-export-string-as (plist-get o :pronunciation) 'md t) + (plist-get o :pronunciation)) + "")) (when (plist-get o :irc) (format "IRC: %s" (plist-get o :irc))) - (plist-get o :public-contact) + (if (string-match "\\[" (or (plist-get o :public-contact) "")) + (org-export-string-as (plist-get o :public-contact) 'md t) + (plist-get o :public-contact)) (when (plist-get o :public-email) (format "<mailto:%s>" (plist-get o :public-email))))) ", "))) (concat (plist-get o :speakers-with-pronouns) @@ -613,7 +619,10 @@ ${categories} (emacsconf-surround " <" (and (member emacsconf-publishing-phase '(schedule conference)) (plist-get o :qa-url)) ">" "")) (concat (or (plist-get o :video-time) - (plist-get o :time)) "-min talk cancelled")) + (plist-get o :time)) + (if (string= (plist-get o :status) "CANCELLED") + "-min talk cancelled" + "-min talk"))) :pad-info (if (and talk-p emacsconf-publish-include-pads (not (and (member emacsconf-publishing-phase '(schedule conference)) (string= (plist-get o :qa-type) "etherpad")))) @@ -728,7 +737,7 @@ This includes the intro note, the schedule, and talk resources." (setq info (or info (emacsconf-publish-prepare-for-display (emacsconf-get-talk-info)))) (with-temp-file (expand-file-name (format "%s-before.md" (plist-get talk :slug)) (expand-file-name "info" (expand-file-name emacsconf-year emacsconf-directory))) - + (hack-dir-local-variables-non-file-buffer) (insert "<!-- Automatically generated by emacsconf-publish-before-page -->\n") (insert (emacsconf-surround "" (plist-get talk :intro-note) "\n\n" "")) (let ((is-live (emacsconf-talk-live-p talk))) @@ -751,7 +760,7 @@ This includes the intro note, the schedule, and talk resources." (let ((msecs (elt sub 1))) (concat (if (and (elt sub 4) (not (string= (elt sub 4) ""))) - (format "\n[[!template new=\"1\" text=\"\"\"%s\"\"\" start=\"%s\" video=\"%s\" id=\"subtitle\"%s]]\n\n" + (format "\n<div class=\"transcript-heading\">[[!template new=\"1\" text=\"\"\"%s\"\"\" start=\"%s\" video=\"%s\" id=\"subtitle\"%s]]</div>" (string-trim (replace-regexp-in-string "^NOTE[ \n]" "" (elt sub 4))) (concat (format-seconds "%02h:%02m:%02s" (/ (floor msecs) 1000)) "." (format "%03d" (mod (floor msecs) 1000))) @@ -836,12 +845,13 @@ This includes captions, contact, and an invitation to participate." ;; Contact information (with-temp-file (expand-file-name (format "%s-after.md" (plist-get talk :slug)) (expand-file-name "info" (expand-file-name emacsconf-year emacsconf-directory))) + (hack-dir-local-variables-non-file-buffer) (insert "<!-- Automatically generated by emacsconf-publish-after-page -->\n" "\n\n" ;; main transcript (if (plist-get talk :public) (emacsconf-publish-format-captions talk) "") - (if (emacsconf-talk-file talk "--answers.vtt") + (if (and (plist-get talk :qa-public) (emacsconf-talk-file talk "--answers.vtt")) (emacsconf-publish-format-transcript (append (list :chapter-file (emacsconf-talk-file talk "--answers--chapters.vtt") @@ -1189,7 +1199,7 @@ You can also get this schedule as iCalendar files: ${icals}. Importing that into (with-temp-file (expand-file-name "schedule-details.md" (expand-file-name emacsconf-year emacsconf-directory)) (emacsconf-publish-schedule-with-times info))) - ((or 'cfp 'program) + ((or 'cfp 'program 'harvest 'resources) (with-temp-file (expand-file-name "schedule-details.md" (expand-file-name emacsconf-year emacsconf-directory)) (emacsconf-publish-program-without-times info)) @@ -1287,6 +1297,8 @@ You can also get this schedule as iCalendar files: ${icals}. Importing that into (or (plist-get o :toobnix-url) (plist-get o :video-file))) "video posted") + (when (plist-get o :qa-public) + "Q&A posted") (emacsconf-surround "video: " (plist-get o :video-duration) "" nil) (emacsconf-surround "answers: " (and (plist-get o :qa-public) (plist-get o :qa-video-duration)) @@ -1583,7 +1595,7 @@ answers without needing to listen to everything again. You can see <a href=\"htt ;; further tests (pcase f ((rx (seq "--" - (or "reencoded" "normalized" "final" "old" "bbb" "backstage"))) + (or "reencoded" "normalized" "final" "old" "bbb" "backstage" "pad" "silences"))) nil) ((rx ".diff") nil) ((rx "--original") @@ -2662,17 +2674,19 @@ The Q&A room for ${title} has finished. You can find more information about the There is no live Q&A room for ${title}. You can find more information about the talk at <a href=\"${base-url}${url}\">${base-url}${url}</a>.</body></html>" ))))))) -(defun emacsconf-publish-media-files-on-change (talk) +(defun emacsconf-publish-media-files-on-change (talk &optional always-update) "Publish the files and update the index." - (interactive (list (emacsconf-complete-talk-info))) + (interactive (list (emacsconf-complete-talk-info) current-prefix-arg)) (let ((org-state (if (boundp 'org-state) org-state (plist-get talk :status)))) (if (plist-get talk :public) ;; Copy main files from backstage to public (let ((public-files (emacsconf-publish-filter-public-files talk))) (mapc (lambda (file) - (when (not (file-exists-p (expand-file-name file emacsconf-public-media-directory))) - (copy-file (expand-file-name file emacsconf-backstage-dir) - (expand-file-name file emacsconf-public-media-directory) t))) + (when (or always-update (not (file-exists-p (expand-file-name file emacsconf-public-media-directory)))) + (copy-file (if (file-exists-p (expand-file-name file emacsconf-backstage-dir)) + (expand-file-name file emacsconf-backstage-dir) + (expand-file-name file emacsconf-cache-dir)) + (expand-file-name file emacsconf-public-media-directory) t))) public-files)) ;; Remove files from public (let ((files (directory-files emacsconf-public-media-directory nil @@ -2823,6 +2837,9 @@ Tends to be quota-limited, though." arguments) " ")) (with-current-buffer (get-buffer-create "*YouTube*") (erase-buffer) + (kill-new (concat (car emacsconf-publish-youtube-upload-command) + " " + (mapconcat #'shell-quote-argument arguments " "))) (apply #'call-process (car emacsconf-publish-youtube-upload-command) nil t t @@ -3029,5 +3046,119 @@ Tends to be quota-limited, though." (expand-file-name (concat (plist-get talk :file-prefix) "--intro.webm") emacsconf-backstage-dir) t)))) + +(defun emacsconf-publish-update-transcript () + (interactive) + (emacsconf-subed-make-chapter-file-based-on-comments) + (let ((talk (emacsconf-resolve-talk (emacsconf-get-slug-from-string (buffer-file-name))))) + (emacsconf-publish-media-files-on-change talk) + (emacsconf-publish-with-wiki-change + (emacsconf-publish-captions-in-wiki talk) + (emacsconf-publish-info-pages-for-talk talk)))) + +;; for emacs.tv +(defun emacsconf-publish-insert-video-entries (&optional info tags) + (interactive) + (setq tags (or tags (format ":emacsconf:emacsconf%s:" emacsconf-year))) + (dolist (talk (emacsconf-publish-prepare-for-display (or info (emacsconf-get-talk-info)))) + (when (emacsconf-talk-file talk "--main.webm") + (let ((new-entry (emacsconf-replace-plist-in-string + (append + (list + :conf-name emacsconf-name + :conf-year emacsconf-year + :media-url (format "https://media.emacsconf.org/%s/%s--main.webm" + emacsconf-year + (plist-get talk :file-prefix)) + :transcript-url + (if (emacsconf-talk-file "--main.vtt" + (format "https://media.emacsconf.org/%s/%s--main.vtt" + emacsconf-year + (plist-get talk :file-prefix))) + "") + :duration (or (plist-get talk :qa-video-duration) + (emacsconf-format-seconds + (/ (compile-media-get-file-duration-ms (emacsconf-talk-file talk "--main.webm")) + 1000))) + :url (concat emacsconf-base-url (plist-get talk :url)) + :tags (if (plist-get talk :tags) (concat tags (substring (plist-get talk :tags) 1)) tags) + :date (format-time-string "%FT%T%z" (plist-get talk :start-time) t)) + talk + (list :youtube-url "" :toobnix-url "" :speakers "")) + "* ${title} ${tags} +:PROPERTIES: +:DATE: ${date} +:URL: ${url} +:DURATION: ${duration} +:MEDIA_URL: ${media-url} +:YOUTUBE_URL: ${youtube-url} +:TOOBNIX_URL: ${toobnix-url} +:TRANSCRIPT_URL: ${transcript-url} +:SPEAKERS: ${speakers} +:SERIES: ${conf-name} ${conf-year} +:END: +" + ))) + (with-current-buffer (find-file-noselect emacstv-index-org) + (if (and (plist-get talk :youtube-url) (emacstv-find-by-youtube-url (plist-get talk :youtube-url))) + (org-entry-put (point) "DATE" (format-time-string "%FT%T%z" (plist-get talk :start-time) t)) + (goto-char (point-max)) + (insert new-entry))))))) + +(defun emacsconf-publish-insert-video-entries-for-answers (&optional info tags) + (interactive) + (setq tags (or tags (format ":answers:emacsconf:emacsconf%s:" emacsconf-year))) + (dolist (talk (emacsconf-publish-prepare-for-display (or info (emacsconf-get-talk-info)))) + (when (emacsconf-talk-file talk "--answers.webm") + (let ((new-entry (emacsconf-replace-plist-in-string + (append + (list + :conf-name emacsconf-name + :conf-year emacsconf-year + :youtube-url (plist-get talk :qa-youtube) + :toobnix-url (plist-get talk :qa-toobnix) + :media-url (format "https://media.emacsconf.org/%s/%s--answers.webm" + emacsconf-year + (plist-get talk :file-prefix)) + :transcript-url (if (emacsconf-talk-file talk "--answers.vtt") + (format "https://media.emacsconf.org/%s/%s--answers.vtt" + emacsconf-year + (plist-get talk :file-prefix)) + "") + :url (concat emacsconf-base-url (plist-get talk :url)) + :duration (or (plist-get talk :qa-video-duration) + (emacsconf-format-seconds + (/ (compile-media-get-file-duration-ms (emacsconf-talk-file talk "--answers.webm")) + 1000))) + :tags (if (plist-get talk :tags) (concat tags (substring (plist-get talk :tags) 1)) tags) + :date (format-time-string "%FT%T%z" (plist-get talk :start-time) t)) + talk + (list :youtube-url "" :toobnix-url "" :speakers "")) + "* Q&A: ${title} ${tags} +:PROPERTIES: +:DATE: ${date} +:URL: ${url} +:DURATION: ${duration} +:MEDIA_URL: ${media-url} +:YOUTUBE_URL: ${youtube-url} +:TOOBNIX_URL: ${toobnix-url} +:TRANSCRIPT_URL: ${transcript-url} +:SPEAKERS: ${speakers} +:SERIES: ${conf-name} ${conf-year} +:END: +" + ))) + (with-current-buffer (find-file-noselect emacstv-index-org) + (if (and (plist-get talk :qa-youtube) (emacstv-find-by-youtube-url (plist-get talk :qa-youtube))) + (progn + (org-entry-put (point) "DATE" (format-time-string "%FT%T%z" (plist-get talk :start-time) t)) + (org-entry-put (point) + "TRANSCRIPT_URL" + (if (emacsconf-talk-file talk "--answers.vtt") + (format "https://media.emacsconf.org/%s/%s--answers.vtt" + emacsconf-year + (plist-get talk :file-prefix)) + ""))) + (insert new-entry))))))) ;; (provide 'emacsconf-publish) |