diff options
| -rw-r--r-- | emacsconf-pad.el | 82 | ||||
| -rw-r--r-- | emacsconf-publish.el | 208 | ||||
| -rw-r--r-- | emacsconf-schedule.el | 84 | ||||
| -rw-r--r-- | emacsconf.el | 12 | 
4 files changed, 257 insertions, 129 deletions
diff --git a/emacsconf-pad.el b/emacsconf-pad.el index 1c08721..bf82412 100644 --- a/emacsconf-pad.el +++ b/emacsconf-pad.el @@ -23,7 +23,8 @@  ;; Prepopulate the Etherpad  (defcustom emacsconf-pad-base "http://pad.emacsconf.org/" -  "Base URL for the Etherpad. Include trailing slash." +  "Base URL for the Etherpad. Include trailing slash. +Use \"wikimedia\" to use etherpad.wikimedia.org instead."    :group 'emacsconf    :type 'string) @@ -122,50 +123,69 @@ You can find it in $ETHERPAD_PATH/APIKEY.txt"    (concat emacsconf-pad-slug-base "-" (plist-get o :slug)))  (defun emacsconf-pad-url (o) -  (concat emacsconf-pad-base emacsconf-pad-directory (emacsconf-pad-id o))) +  (if (string= emacsconf-pad-base "wikimedia") +      (format "https://etherpad.wikimedia.org/p/emacsconf-%s-%s" +              emacsconf-year +              (plist-get o :slug)) +    (concat emacsconf-pad-base emacsconf-pad-directory (emacsconf-pad-id o))))  (defvar emacsconf-pad-number-of-next-talks 3 "Integer limiting the number of next talks to link to from the pad.")  (defun emacsconf-pad-initial-content (o)    (emacsconf-replace-plist-in-string -      (append (list :base-url emacsconf-base-url -                    :channel (concat "emacsconf-" (downcase (plist-get o :track))) -                    :bbb-info -                    (if (plist-get o :bbb-room) -                        (concat "<div>Q&A room: ${bbb-room}</div>") -                      "") -                    :next-talk-list -                    (if (plist-get o :next-talks) -                        (concat "<div>Next talks:\n<ul>" -                                (mapconcat -                                 (lambda (o) -                                   (format "<li>%s: %s %s</li>" -                                           (plist-get o :track) -                                           (emacsconf-pad-url o) -                                           (plist-get o :title))) -                                 (plist-get o :next-talks) -                                 "\n") -                                "</ul></div>") -                      "") -                    :irc-nick-details -                    (if (plist-get o :irc) -                        (concat "Speaker nick: " (plist-get o :irc) " - ") -                      "") -                    :irc-url (concat "https://chat.emacsconf.org/#/connect?join=emacsconf-" (downcase (plist-get o :track)))) -              o) -      "<div> +   (append (list :base-url emacsconf-base-url +                 :channel (concat "emacsconf-" (plist-get (emacsconf-get-track (plist-get o :track)) :id)) +                 :bbb-info +                 (if (plist-get o :bbb-room) +                     (concat "<div>Q&A room: ${bbb-room}</div>") +                   "") +                 :next-talk-list +                 (if (plist-get o :next-talks) +                     (concat "<div>Next talks:\n<ul>" +                             (mapconcat +                              (lambda (o) +                                (format "<li>%s: %s %s</li>" +                                        (plist-get o :track) +                                        (plist-get o :title) +                                        (emacsconf-pad-url o))) +                              (plist-get o :next-talks) +                              "\n") +                             "</ul></div>") +                   "") +                 :track-id +                 (plist-get (emacsconf-get-track (plist-get o :track)) :id) +                 :watch +                 (concat emacsconf-base-url emacsconf-year "/watch/" (plist-get (emacsconf-get-track (plist-get o :track)) :id) "/") +                 :talks +                 (concat emacsconf-base-url emacsconf-year "/talks/") +                 :notes +                 (string-join (make-list 6 "<li></li>")) +                 :questions +                 (string-join (make-list 6 "<li>Q: <ul><li>A: </li></ul></li>")) +                 :irc-nick-details +                 (if (plist-get o :irc) +                     (concat "Speaker nick: " (plist-get o :irc) " - ") +                   "") +                 :irc-url (concat "" )) +           o) +   "<div> +<div>All talks: ${talks}</div>  <div><strong>${title}</strong></div>  <div>${base-url}${url} - ${speakers} - Track: ${track}</div>  ${bbb-info} -<div>IRC: ${irc-nick-details}<a href=\"${irc-url}\">${irc-url}</a> or #${channel} on libera.chat network</div> -<div>How to watch/participate: ${base-url}${year}</div> +<div>Watch/participate: ${watch}</div> +<div>IRC: ${irc-nick-details} https://chat.emacsconf.org/#/connect?join=emacsconf-${track-id} or #emacsconf-${track-id} on libera.chat network</div>  <div>Guidelines for conduct: ${base-url}conduct</div>  <div>See end of file for license (CC Attribution-ShareAlike 4.0 + GPLv3 or later)</div>  <div>----------------------------------------------------------------</div> +<div>Notes and links:</div> +<ul>${notes}</ul> +<div>----------------------------------------------------------------</div>  <div>Questions and discussion go here:</div> -<ul><li>Q1. </li><li>Q2. </li><li>Q3. </li><li>Q4. </li><li>Q5. </li><li>Q6. </li><li></li><li></li><li></li></ul> +<ul>${questions}</ul>  <div>----------------------------------------------------------------</div>  ${next-talk-list} +<div>----------------------------------------------------------------</div>  <div>This pad will be archived at ${base-url}${url} after the conference.</div>  <div>Except where otherwise noted, the material on the EmacsConf pad are dual-licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International Public License; and the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) an later version. Copies of these two licenses are included in the EmacsConf wiki repository, in the COPYING.GPL and COPYING.CC-BY-SA files (https://emacsconf.org/COPYING/)</div> diff --git a/emacsconf-publish.el b/emacsconf-publish.el index f1d4b96..7ecaa29 100644 --- a/emacsconf-publish.el +++ b/emacsconf-publish.el @@ -544,8 +544,6 @@ Entries are sorted chronologically, with different tracks interleaved."                                                         (plist-get o :include-in-info)))                                                   (or info (emacsconf-get-talk-info)))                                       #'emacsconf-sort-by-scheduled))) -         (track-colors '(("General" . "#ffdab9") -                         ("Development" . "#87CEEB")))           (dates (seq-map (lambda (o) (plist-get (cadr o) :start-time))                           by-day))           (links (mapcar (lambda (o) @@ -555,61 +553,37 @@ Entries are sorted chronologically, with different tracks interleaved."                          dates))           (height 150)           (width 600)) -         (mapconcat (lambda (day) -                      (let ((day-start (date-to-time -					(concat (format-time-string "%Y-%m-%dT09:00" (plist-get (cadr day) :start-time)) -						emacsconf-timezone-offset))) -			    (day-end (date-to-time (concat (format-time-string "%Y-%m-%dT17:00" (plist-get (cadr day) :start-time)) -							   emacsconf-timezone-offset)))) -                        ;; (with-temp-file (expand-file-name (concat emacsconf-year "/talks/" -                        ;;                                           (format-time-string "schedule-%Y-%m-%d.svg"  -                        ;;                                                               (plist-get (cadr day) :start-time) -                        ;;                                                               emacsconf-timezone)) -                        ;;                                   emacsconf-directory) -                        ;;   (let ((height 200) (width 800)) -                        ;;(svg-print -                        ;;      (emacsconf-schedule-svg-day -                        ;;       (svg-create width height) -                        ;;       (format-time-string "%a" (plist-get (cadr day) :start-time) emacsconf-timezone) -                        ;;       width height -                        ;;       day-start -                        ;;       day-end -                        ;;       (list (seq-filter (lambda (o) (string= (plist-get o :track) "General")) (cdr day)) -                        ;;             (seq-filter (lambda (o) (string= (plist-get o :track) "Development")) (cdr day))) -                        ;;       )))) -                        (concat -                         (svg-print -                          (emacsconf-schedule-svg-day -                           (svg-create width height) -                           (format-time-string "%a" (plist-get (cadr day) :start-time) emacsconf-timezone) -                           width height -                           day-start -                           day-end -                           (list (seq-filter (lambda (o) (string= (plist-get o :track) "General")) (cdr day)) -                                 (seq-filter (lambda (o) (string= (plist-get o :track) "Development")) (cdr day))) -                           (lambda (o node) -                             (when (assoc-default (plist-get o :track) track-colors) -                               (dom-set-attribute node 'fill (assoc-default (plist-get o :track) track-colors))) -                             node))) -                         "\n\n" -                         (if (> (length links) 1) (concat "Jump to: " (string-join links " - ")) "") -                         (format "<a name=\"date-%s\"></a>\n" -                                 (format-time-string "%Y-%m-%d" -                                                     (plist-get (cadr day) :start-time) -                                                     emacsconf-timezone)) -                         (format-time-string "# %A %b %-e, %Y\n" (plist-get (cadr day) :start-time) emacsconf-timezone) -                         ;; (format "<img src=\"/%s/talks/schedule-%s.svg\" alt=\"Schedule\"/>  \n" -                         ;;         emacsconf-year -                         ;;         (format-time-string "%Y-%m-%d" -                         ;;                             (plist-get (cadr day) :start-time) -                         ;;                             emacsconf-timezone)) -                         (format "<div class=\"schedule\" data-start=\"%s\" data-end=\"%s\" data-tracks=\"General,Development\">\n" -                                 (format-time-string "%FT%T%z" day-start t) -                                 (format-time-string "%FT%T%z" day-end t)) -                         (emacsconf-format-main-schedule (cdr day)) -                         "</div>"))) -                    by-day -                    "\n\n"))) +    (mapconcat (lambda (day) +                 (let ((day-start (date-to-time +					                         (concat (format-time-string "%Y-%m-%dT09:00" (plist-get (cadr day) :start-time)) +						                               emacsconf-timezone-offset))) +			                 (day-end (date-to-time (concat (format-time-string "%Y-%m-%dT17:00" (plist-get (cadr day) :start-time)) +							                                        emacsconf-timezone-offset)))) +                   (concat +                    (with-temp-buffer +                      (svg-print +                       (emacsconf-schedule-svg-day +                        (svg-create width height) +                        (format-time-string "%a" (plist-get (cadr day) :start-time) emacsconf-timezone) +                        width height +                        day-start +                        day-end +                        (emacsconf-by-tracks (cdr day)))) +                      (buffer-string)) +                    "\n\n" +                    (if (> (length links) 1) (concat "Jump to: " (string-join links " - ")) "") +                    (format "<a name=\"date-%s\"></a>\n" +                            (format-time-string "%Y-%m-%d" +                                                (plist-get (cadr day) :start-time) +                                                emacsconf-timezone)) +                    (format-time-string "# %A %b %-e, %Y\n" (plist-get (cadr day) :start-time) emacsconf-timezone) +                    (format "<div class=\"schedule\" data-start=\"%s\" data-end=\"%s\" data-tracks=\"General,Development\">\n" +                            (format-time-string "%FT%T%z" day-start t) +                            (format-time-string "%FT%T%z" day-end t)) +                    (emacsconf-format-main-schedule (cdr day)) +                    "</div>"))) +               by-day +               "\n\n")))  (defun emacsconf-generate-main-schedule (&optional info)    (interactive) @@ -663,19 +637,8 @@ Entries are sorted chronologically, with different tracks interleaved."                      (apply '+ (mapcar (lambda (info) (string-to-number (plist-get info :duration)))                                        received))))) - -(defun emacsconf-format-main-schedule (info) -  (let* ((cancelled (seq-filter (lambda (o) (string= (plist-get o :status) "CANCELLED")) info))) -    (concat -     (mapconcat -      (lambda (o) -        (let* ((status (pcase (plist-get o :status) -                         ("CAPTIONED" "captioned") -                         ("PREREC_RECEIVED" "received") -                         ("DONE" "done") -                         ("STARTED" "now playing") -                         (_ nil)))) -          (format "[[!template id=sched%s%s]]" +(defun emacsconf-publish-sched-directive (o) +  (format "[[!template id=sched%s%s]]"                    (let ((result "")                          (attrs (append                                  (list @@ -687,7 +650,12 @@ Entries are sorted chronologically, with different tracks interleaved."                                    (list                                     :track (plist-get o :track)                                     :slug (plist-get o :slug) -                                   :status status +                                   :status (pcase (plist-get o :status) +                                             ("CAPTIONED" "captioned") +                                             ("PREREC_RECEIVED" "received") +                                             ("DONE" "done") +                                             ("STARTED" "now playing") +                                             (_ nil))                                     :time (plist-get o :time)                                     :startutc (format-time-string "%FT%T%z" (plist-get o :start-time) t)                                     :endutc (format-time-string "%FT%T%z" (plist-get o :end-time) t) @@ -707,9 +675,12 @@ Entries are sorted chronologically, with different tracks interleaved."                                                   (list :base-url (format "%s%s/" emacsconf-media-base-url emacsconf-year)))                                           (append emacsconf-main-extensions '("--main.webm")))                                          "")) -                    "")))) -      (emacsconf-active-talks info) -      "\n") +                    ""))) + +(defun emacsconf-format-main-schedule (info) +  (let* ((cancelled (seq-filter (lambda (o) (string= (plist-get o :status) "CANCELLED")) info))) +    (concat +     (mapconcat #'emacsconf-publish-sched-directive o (emacsconf-active-talks info) "\n")       "\n"       (if (> (length cancelled) 0)           (format "<div class=\"cancelled\">Cancelled:<ul>%s</ul></div>" @@ -1184,5 +1155,94 @@ Entries are sorted chronologically, with different tracks interleaved."      )) +(defmacro emacsconf-publish-with-wiki-change (&rest body) +  (declare (indent 0) (debug t)) +  `(progn +     ,@body +     (let ((default-directory emacsconf-directory)) +       (magit-stage-modified) +       (magit-status-setup-buffer)))) + +(defun emacsconf-publish-watch-pages () +  "Update /year/watch pages." +  (interactive) +  (emacsconf-publish-with-wiki-change +    (mapc (lambda (track) +            (plist-put track :year emacsconf-year) +            (plist-put track :stream (concat emacsconf-stream-base (plist-get track :id) ".webm")) +            (plist-put track :480p (concat emacsconf-stream-base (plist-get track :id) "-480p.webm")) +            (plist-put track :webchat (concat emacsconf-chat-base "?join=emacsconf-" (plist-get track :id))) +            (plist-put track :channel (concat "#emacsconf-" (plist-get track :id)))) +          emacsconf-tracks) +    (let* ((info (sort (emacsconf-get-talk-info) #'emacsconf-sort-by-scheduled)) +           (emacsconf-publishing-phase 'schedule) +           (sched (with-temp-buffer (svg-print (emacsconf-schedule-svg 800 300 (emacsconf-get-talk-info))) +                                    (buffer-string)))) +      (unless (file-directory-p (expand-file-name "watch" (expand-file-name emacsconf-year emacsconf-directory))) +        (make-directory (expand-file-name "watch" (expand-file-name emacsconf-year emacsconf-directory)))) +      (with-temp-file (expand-file-name "watch/info.md" (expand-file-name emacsconf-year emacsconf-directory)) +        (insert +         "<!-- Automatically generated by emacsconf-publish-watch-pages -->\n[[!sidebar content=\"\"]] +# Tracks\n\n" +         "<table width=\"100%\"><tr><th>Watch page</th><th>IRC channel (libera.chat)</th><th>Alternative for streaming player</th><th>Low res</th></tr>\n" +         (mapconcat (lambda (track) +                      (emacsconf-replace-plist-in-string +                       track +                       "<tr><td><a href=\"/${year}/watch/${id}\">${name}</a></td><td><a href=\"${webchat}\">${channel}</a></td><td><a href=\"${stream}\">${stream}</a></td><td><a href=\"${480p}\">${id}-480p.webm</a></tr>")) +                    emacsconf-tracks +                    "\n") +         "</table>\n\n" sched)) +       +      (mapc (lambda (track) +              (with-temp-file (expand-file-name (format "%s/watch/%s.md" +                                                        emacsconf-year +                                                        (plist-get track :id)) +                                                emacsconf-directory) +                (insert +                 (emacsconf-replace-plist-in-string +                  (append +                   (list :links (concat +                                 "<a href=\"#watch\">Watch</a> - <a href=\"#chat\">Chat</a> - <a href=\"#sched\">View schedule</a> - \nStreams: " +                                 (mapconcat (lambda (tr) +                                              (if (string= (plist-get tr :name) (plist-get track :name)) +                                                  (format "**%s**" (plist-get track :name)) +                                                (format "<a href=\"/%s/watch/%s/\">%s</a>" +                                                        emacsconf-year +                                                        (plist-get tr :id) +                                                        (plist-get tr :name)))) +                                            emacsconf-tracks +                                            " - ")) +                         :sched sched +                         :talks (mapconcat #'emacsconf-publish-sched-directive +                                             (seq-filter (lambda (o) (string= (plist-get o :track) +                                                                              (plist-get track :name))) +                                                         info) +                                             "\n")) +                   track) +                  "<!-- Automatically generated by emacsconf-publish-watch-pages --> +[[!inline pages=\"internal(2022/info/watch-announce)\" raw=\"yes\"]] +[[!meta title=\"${name} stream\"]] +[[!sidebar content=\"\"]] + +<a name=\"watch\"></a> +${links} +\n<video controls><source src=\"${stream}\" type=\"video/webm\" /></video> +Alternatively, load <${stream}> or <${480p}> (low-res) in a streaming media player such as MPV. + +<a name=\"chat\"></a> +${links} + +Chat: [${channel} on libera.chat](${webchat}) + +<div class=\"chat-iframe\" data-track=\"${id}\"></div> + +<a name=\"sched\"></a> +${links} + +${sched}\n + +${talks} +")))) +            emacsconf-tracks))))  (provide 'emacsconf-publish) diff --git a/emacsconf-schedule.el b/emacsconf-schedule.el index d0f476f..8d4e75a 100644 --- a/emacsconf-schedule.el +++ b/emacsconf-schedule.el @@ -223,8 +223,8 @@ Each function should take the info and manipulate it as needed, returning the ne                (org-entry-put (point) "TIME" (plist-get talk :time)))              (emacsconf-filter-talks info))))) - -(defun emacsconf-schedule-svg-track (svg base-x base-y width height start-time end-time info &optional modify-func) +(defvar emacsconf-schedule-svg-modify-functions '(emacsconf-schedule-svg-color-by-track) "Functions to run to modify the display of each item.") +(defun emacsconf-schedule-svg-track (svg base-x base-y width height start-time end-time info)    (let ((scale (/ width (float-time (time-subtract end-time start-time)))))      (mapc       (lambda (o) @@ -238,10 +238,7 @@ Each function should take the info and manipulate it as needed, returning the ne             'a             `((href . ,(concat "/" (plist-get o :url)))               (title . ,(plist-get o :title))) -           (dom-node -            'title -            nil -            (plist-get o :title)) +           (dom-node 'title nil (plist-get o :title))             (let ((node (dom-node                          'rect                          `((x . ,x) @@ -262,24 +259,25 @@ Each function should take the info and manipulate it as needed, returning the ne                                                     (or (plist-get o :availability) ""))                                       "lightgray")                                      (t "lightgreen"))))))) -             (if modify-func -                 (funcall modify-func o node) -               node)) +             (run-hook-with-args +              'emacsconf-schedule-svg-modify-functions +              o node) +             node)             (dom-node              'g -            `((transform . ,(format "translate(%d,%d)" -                                    (+ x size -2) (+ y height -2)))) -            (dom-node -             'text -             '((fill . "black") -               (x . 0) -               (y . 0) -               (font-size . 10) -               (transform . "rotate(-90)")) -             (svg--encode-text (or (plist-get o :slug) (plist-get o :title))))))))) -     info))) - -(defun emacsconf-schedule-svg-day (elem label width height start end tracks &optional modify-func) +             `((transform . ,(format "translate(%d,%d)" +                                     (+ x size -2) (+ y height -2)))) +             (dom-node +              'text +               '((fill . "black") +                 (x . 0) +                 (y . 0) +                 (font-size . 10) +                 (transform . "rotate(-90)")) +                (svg--encode-text (or (plist-get o :slug) (plist-get o :title))))))))) +    info))) + +(defun emacsconf-schedule-svg-day (elem label width height start end tracks)    (let* ((label-margin 15)           (track-height (/ (- height (* 2 label-margin)) (length tracks)))           (x 0) (y label-margin) @@ -290,7 +288,7 @@ Each function should take the info and manipulate it as needed, returning the ne      (mapc (lambda (track)              (emacsconf-schedule-svg-track               elem x y width track-height -             start end track modify-func) +             start end track)              (setq y (+ y track-height)))            tracks)      ;; draw grid @@ -319,7 +317,45 @@ Each function should take the info and manipulate it as needed, returning the ne          (setq time (time-add time (seconds-to-time 3600)))))      elem)) -(defun emacsconf-schedule-svg (width height days) +(defun emacsconf-by-tracks (info) +  (mapcar (lambda (track) +            (seq-filter +             (lambda (talk) +               (string= (plist-get talk :track) (plist-get track :name))) +             info)) +          emacsconf-tracks)) + +(defun emacsconf-schedule-svg-color-by-track (o node) +  (let ((track (emacsconf-get-track (plist-get o :track)))) +    (when track +      (dom-set-attribute node 'fill (plist-get track :color))))) + +(defun emacsconf-schedule-svg (width height &optional info) +  (setq info (or info (emacsconf-get-talk-info))) +  (let ((days (seq-group-by (lambda (o) +                              (format-time-string "%Y-%m-%d" (plist-get o :start-time) emacsconf-timezone)) +                            (sort (seq-filter (lambda (o) +                                                (or (plist-get o :slug) +                                                    (plist-get o :include-in-info))) +                                              info) +                                  #'emacsconf-sort-by-scheduled)))) +    (emacsconf-schedule-svg-days +     width height +     (mapcar (lambda (o) +               (let ((start (concat (car o) "T09:00:00" emacsconf-timezone-offset)) +                     (end (concat (car o) "T17:00:00" emacsconf-timezone-offset))) +                 (list :label (format-time-string "%A" (date-to-time (car o))) +                       :start start +                       :end end +                       :tracks (mapcar (lambda (track) +                                         (seq-filter +                                          (lambda (talk) +                                            (string= (plist-get talk :track) (plist-get track :name))) +                                          (cdr o))) +                                       emacsconf-tracks)))) +             days)))) + +(defun emacsconf-schedule-svg-days (width height days)    (let ((svg (svg-create width height :background "white"))          (day-height (/ height (length days)))          (y 0)) diff --git a/emacsconf.el b/emacsconf.el index 12c5cf3..b850302 100644 --- a/emacsconf.el +++ b/emacsconf.el @@ -75,6 +75,9 @@    :type 'file    :group 'emacsconf) +(defvar emacsconf-stream-base "https://live0.emacsconf.org/") +(defvar emacsconf-chat-base "https://chat.emacsconf.org/") +  (defcustom emacsconf-download-directory "~/Downloads"    "Directory to check for downloaded files."    :type 'directory @@ -911,5 +914,14 @@ Include some other things, too, such as emacsconf-year, title, name, email, url,              '((emacsconf-pad-api-key . etherpad_api_key)                (emacsconf-pad-base . etherpad_url))))))  ;; (emacsconf-ansible-load-vars (expand-file-name "prod-vars.yml" emacsconf-ansible-directory)) +;;; Tracks +(defvar emacsconf-tracks '((:name "General" :color "peachpuff" :id "gen") +                           (:name "Development" :color "skyblue" :id "dev"))) + +(defun emacsconf-get-track (name) +  (seq-find (lambda (track) (string= name (plist-get track :name))) emacsconf-tracks)) + + +  (provide 'emacsconf)  ;;; emacsconf.el ends here  | 
