summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSacha Chua <sacha@sachachua.com>2022-10-14 19:56:29 -0400
committerSacha Chua <sacha@sachachua.com>2022-10-14 19:56:29 -0400
commit70bce881088df27dfe2912638ef1d43669011408 (patch)
tree28914971cd5fdb2218b0c2255fcb62931d559c1a
parent41c92b684268f57ec3fc6263647b9bafa9dbc9dd (diff)
downloademacsconf-el-70bce881088df27dfe2912638ef1d43669011408.tar.xz
emacsconf-el-70bce881088df27dfe2912638ef1d43669011408.zip
Update pad template, generate watch pages
-rw-r--r--emacsconf-pad.el82
-rw-r--r--emacsconf-publish.el208
-rw-r--r--emacsconf-schedule.el84
-rw-r--r--emacsconf.el12
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&amp;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&amp;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