forked from boyska/sito-hackit-17
Merge branch 'talk-plugins'
This commit is contained in:
commit
21da9e949a
10 changed files with 322 additions and 11 deletions
12
README.md
12
README.md
|
@ -19,3 +19,15 @@ firefox output/index.html
|
|||
Also, `make help` is your friend.
|
||||
|
||||
**Morte ai nemici dell'UTF-8**
|
||||
|
||||
Aggiungere un talk
|
||||
--------------------
|
||||
|
||||
```sh
|
||||
cp -r talks/_talk_example/ talks/MIOTALK/
|
||||
vim talks/MIOTALK/meta.yaml
|
||||
```
|
||||
|
||||
Quindi rifai `make publish` come spiegato prima: l'output ti informa di eventuali errori nei campi o
|
||||
sovrapposizioni con altri talk, leggilo!
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ appreciated!
|
|||
Hackmeeting (still) hasn't a proper translation system, but you can
|
||||
find a bunch of people to ask to do translations when you need it.
|
||||
|
||||
.. talkgrid::
|
||||
|
||||
.. talklist::
|
||||
|
||||
|
||||
|
|
|
@ -12,5 +12,7 @@ Leggi l'`invito a presentare dei contenuti
|
|||
<http://lists.autistici.org/message/20170502.165954.0e930b75.en.html>`_, fatti coraggio e proponi il tuo contenuto in `mailing
|
||||
list <{filename}contatti.rst>`_
|
||||
|
||||
.. talkgrid::
|
||||
|
||||
.. talklist::
|
||||
|
||||
|
|
152
plugins/talks.py
152
plugins/talks.py
|
@ -10,7 +10,10 @@ import logging
|
|||
import re
|
||||
import datetime
|
||||
import shutil
|
||||
import time
|
||||
from copy import copy
|
||||
|
||||
import markdown
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import directives, Directive
|
||||
|
||||
|
@ -19,6 +22,9 @@ import jinja2
|
|||
|
||||
|
||||
TALKS_PATH = 'talks'
|
||||
TALK_ATTACHMENT_PATH = 'res'
|
||||
TALK_ICS = 'schedule.ics'
|
||||
GRID_STEP = 15
|
||||
|
||||
|
||||
def memoize(function):
|
||||
|
@ -44,6 +50,34 @@ def get_talk_names():
|
|||
]
|
||||
|
||||
|
||||
def all_talks():
|
||||
return [get_talk_data(tn) for tn in get_talk_names()]
|
||||
|
||||
|
||||
def unique_attr(iterable, attr):
|
||||
return {x[attr] for x in iterable
|
||||
if attr in x}
|
||||
|
||||
|
||||
@memoize
|
||||
def get_global_data():
|
||||
fname = os.path.join(TALKS_PATH, 'meta.yaml')
|
||||
if not os.path.isfile(fname):
|
||||
return None
|
||||
with io.open(fname, encoding='utf8') as buf:
|
||||
try:
|
||||
data = yaml.load(buf)
|
||||
except Exception:
|
||||
logging.exception("Syntax error reading %s; skipping", fname)
|
||||
return None
|
||||
if data is None:
|
||||
return None
|
||||
if 'startdate' not in data:
|
||||
logging.error("Missing startdate in global data")
|
||||
data['startdate'] = datetime.datetime.now()
|
||||
return data
|
||||
|
||||
|
||||
@memoize
|
||||
def get_talk_data(talkname):
|
||||
fname = os.path.join(TALKS_PATH, talkname, 'meta.yaml')
|
||||
|
@ -68,19 +102,32 @@ def get_talk_data(talkname):
|
|||
.format(talkname))
|
||||
data['duration'] = 50
|
||||
data['duration'] = int(data['duration'])
|
||||
if data['duration'] < GRID_STEP:
|
||||
logging.info("Talk <{}> lasts only {} minutes; changing to {}"
|
||||
.format(talkname, data['duration'], GRID_STEP))
|
||||
data['duration'] = GRID_STEP
|
||||
if 'links' not in data or not data['links']:
|
||||
data['links'] = []
|
||||
if 'contacts' not in data or not data['contacts']:
|
||||
data['contacts'] = []
|
||||
if 'needs' not in data or not data['needs']:
|
||||
data['needs'] = []
|
||||
if 'room' not in data:
|
||||
logging.warn("Talk <{}> has no `room` field".format(talkname))
|
||||
if 'time' not in data or 'day' not in data:
|
||||
logging.warn("Talk <{}> has no `time` or `day`".format(talkname))
|
||||
if 'time' in data:
|
||||
if 'day' in data:
|
||||
data['day'] = get_global_data()['startdate'] + datetime.timedelta(days=data['day'])
|
||||
if 'time' in data and 'day' in data:
|
||||
timeparts = re.findall(r'\d+', str(data['time']))
|
||||
if 4 > len(timeparts) > 0:
|
||||
timeparts = [int(p) for p in timeparts]
|
||||
data['time'] = datetime.time(*timeparts)
|
||||
data['time'] = datetime.datetime.combine(data['day'],
|
||||
datetime.time(*timeparts))
|
||||
else:
|
||||
logging.error("Talk <{}> has malformed `time`".format(talkname))
|
||||
data['id'] = talkname
|
||||
resdir = os.path.join(TALKS_PATH, talkname, 'res')
|
||||
resdir = os.path.join(TALKS_PATH, talkname, TALK_ATTACHMENT_PATH)
|
||||
if os.path.isdir(resdir) and os.listdir(resdir):
|
||||
data['resources'] = resdir
|
||||
return data
|
||||
|
@ -90,6 +137,9 @@ jinja_env = jinja2.Environment(
|
|||
loader=jinja2.FileSystemLoader(os.path.join(TALKS_PATH, '_templates')),
|
||||
autoescape=True,
|
||||
)
|
||||
jinja_env.filters['markdown'] = lambda text: \
|
||||
jinja2.Markup(markdown.Markdown(extensions=['meta']).
|
||||
convert(text))
|
||||
|
||||
|
||||
class TalkListDirective(Directive):
|
||||
|
@ -123,7 +173,94 @@ class TalkDirective(Directive):
|
|||
format='html')
|
||||
]
|
||||
|
||||
# TODO: TalkGridDirective (griglia completa)
|
||||
|
||||
class TalkGridDirective(Directive):
|
||||
'''A complete grid'''
|
||||
required_arguments = 0
|
||||
|
||||
optional_arguments = 0
|
||||
final_argument_whitespace = True
|
||||
has_content = True
|
||||
|
||||
def run(self):
|
||||
tmpl = jinja_env.get_template('grid.html')
|
||||
output = []
|
||||
days = unique_attr(all_talks(), 'day')
|
||||
for day in sorted(days):
|
||||
talks = {talk['id'] for talk in all_talks()
|
||||
if talk.get('day', None) == day
|
||||
and 'time' in talk
|
||||
and 'room' in talk}
|
||||
if not talks:
|
||||
continue
|
||||
talks = [get_talk_data(t) for t in talks]
|
||||
rooms = tuple(sorted(unique_attr(talks, 'room')))
|
||||
mintime = min({talk['time'].hour * 60 +
|
||||
talk['time'].minute
|
||||
for talk in talks}) // GRID_STEP * GRID_STEP
|
||||
maxtime = max({talk['time'].hour * 60 +
|
||||
talk['time'].minute +
|
||||
talk['duration']
|
||||
for talk in talks})
|
||||
times = {}
|
||||
|
||||
for t in range(mintime, maxtime, GRID_STEP):
|
||||
times[t] = [None] * len(rooms)
|
||||
for talk in sorted(talks, key=lambda x: x['time']):
|
||||
talktime = talk['time'].hour * 60 + talk['time'].minute
|
||||
position = talktime // GRID_STEP * GRID_STEP # round
|
||||
assert position in times
|
||||
roomnum = rooms.index(talk['room'])
|
||||
if times[position][roomnum] is not None:
|
||||
logging.error("Talk {} and {} overlap! "
|
||||
.format(times[position][roomnum]['id'],
|
||||
talk['id']))
|
||||
continue
|
||||
times[position][roomnum] = copy(talk)
|
||||
times[position][roomnum]['skip'] = False
|
||||
for i in range(1, talk['duration'] // GRID_STEP):
|
||||
times[position + i*GRID_STEP][roomnum] = copy(talk)
|
||||
times[position + i*GRID_STEP][roomnum]['skip'] = True
|
||||
|
||||
render = tmpl.render(times=times,
|
||||
rooms=rooms,
|
||||
mintime=mintime, maxtime=maxtime,
|
||||
timestep=GRID_STEP,
|
||||
)
|
||||
output.append(nodes.raw('', u'<h4>%s</h4>' %
|
||||
day.strftime('%A %d').decode('utf8').title(),
|
||||
format='html'))
|
||||
output.append(nodes.raw('', render, format='html'))
|
||||
return output
|
||||
|
||||
|
||||
def talks_to_ics():
|
||||
content = 'BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:pelican\n'
|
||||
for t in all_talks():
|
||||
content += talk_to_ics(t)
|
||||
content += 'END:VCALENDAR\n'
|
||||
return content
|
||||
|
||||
|
||||
def talk_to_ics(talk):
|
||||
if 'time' not in talk:
|
||||
return ''
|
||||
start = talk['time']
|
||||
end = start + datetime.timedelta(minutes=talk['duration'])
|
||||
content = 'BEGIN:VEVENT\n'
|
||||
content += "UID:%s@%d.hackmeeting.org\n" % (talk['id'], talk['day'].year)
|
||||
content += "SUMMARY:%s\n" % talk['title']
|
||||
content += "DTSTAMP:%s\n" % time.strftime('%Y%m%dT%H%M%SZ',
|
||||
time.gmtime(float(start.strftime('%s'))))
|
||||
content += "DTSTART:%s\n" % time.strftime('%Y%m%dT%H%M%SZ',
|
||||
time.gmtime(float(
|
||||
start.strftime('%s'))))
|
||||
content += "DTEND:%s\n" % time.strftime('%Y%m%dT%H%M%SZ',
|
||||
time.gmtime(float(
|
||||
end.strftime('%s'))))
|
||||
content += "LOCATION:%s\n" % talk['room']
|
||||
content += 'END:VEVENT\n'
|
||||
return content
|
||||
|
||||
|
||||
class TalksGenerator(generators.Generator):
|
||||
|
@ -138,11 +275,13 @@ class TalksGenerator(generators.Generator):
|
|||
def generate_output(self, writer=None):
|
||||
for talkname in self.talks:
|
||||
if 'resources' in self.talks[talkname]:
|
||||
outdir = os.path.join(self.output_path, 'talks', talkname,
|
||||
'res')
|
||||
outdir = os.path.join(self.output_path, TALKS_PATH, talkname,
|
||||
TALK_ATTACHMENT_PATH)
|
||||
if os.path.isdir(outdir):
|
||||
shutil.rmtree(outdir)
|
||||
shutil.copytree(self.talks[talkname]['resources'], outdir)
|
||||
with open(os.path.join(self.output_path, TALK_ICS), 'w') as buf:
|
||||
buf.write(talks_to_ics())
|
||||
|
||||
|
||||
def add_talks_option_defaults(pelican):
|
||||
|
@ -167,3 +306,4 @@ else:
|
|||
signals.initialized.connect(add_talks_option_defaults)
|
||||
directives.register_directive('talklist', TalkListDirective)
|
||||
directives.register_directive('talk', TalkDirective)
|
||||
directives.register_directive('talkgrid', TalkGridDirective)
|
||||
|
|
|
@ -1,16 +1,25 @@
|
|||
# File di esempio; copialo e cambialo
|
||||
title: Il titolo del talk
|
||||
title: "Il titolo del talk"
|
||||
text: |
|
||||
Descrizione del talk divisa in molte righe
|
||||
Puoi scrivere quanto vuoi
|
||||
ma devi rimanere indentato
|
||||
|
||||
Puoi anche mettere delle spaziature.
|
||||
# Se ancora non è stata assegnata una stanza al talk, lasciala vuota. Non usare un valore tipo "qualunque" o
|
||||
|
||||
# Se ancora non è stata assegnata una stanza al talk, commentala. Non usare un valore tipo "qualunque" o
|
||||
# cose del genere, che ci si incasina tutto
|
||||
room: antani
|
||||
|
||||
# duration è la durata in minuti del talk
|
||||
# duration: 50
|
||||
|
||||
# Ci vanno le virgolette intorno! altrimenti 17.30 viene interpretato come un numero decimale
|
||||
time: "17.30"
|
||||
# day è il giorno in cui avverrà il talk. Finché non decommenti il talk non sarà schedulato
|
||||
# 0=giovedì, 1=venerdì, 2=sabato, 3=domenica
|
||||
# day: 0
|
||||
|
||||
tags:
|
||||
- tante
|
||||
- cose
|
||||
|
@ -20,7 +29,7 @@ links:
|
|||
- https://git.lattuga.net/asd/foo
|
||||
# mail dovrebbe contenere un link alla mail con cui il talk è stato proposto
|
||||
# così si può sapere chi contattare e se c'è stata una discussione
|
||||
mail: blabla
|
||||
mail: "blabla"
|
||||
|
||||
# Devi usare UTF-8, non t'inventare scuse, sappiamo ndo abiti
|
||||
# vim: set fileencoding=utf-8:
|
||||
|
|
39
talks/_templates/grid.html
Normal file
39
talks/_templates/grid.html
Normal file
|
@ -0,0 +1,39 @@
|
|||
<style>
|
||||
.talk-grid {
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
}
|
||||
.talk-grid > thead th:first-child {
|
||||
max-width: 5em;
|
||||
}
|
||||
td.talk {
|
||||
border: 1px solid;
|
||||
}
|
||||
</style>
|
||||
<table class="talk-grid">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
{% for room in rooms %}
|
||||
<th>{{room}}</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for time in range (mintime, maxtime, timestep) %}
|
||||
<tr>
|
||||
<td>{{time//60}}:{{ "%02d" % (time % 60)}}</td>
|
||||
{% for talk in times[time / timestep * timestep] %}
|
||||
{% if talk == None %}
|
||||
<td></td>
|
||||
{% elif talk != 'skip' %}
|
||||
<td class="talk" rowspan="{{talk.duration // timestep}}">
|
||||
<a href="#talk-{{talk.id}}"> {{talk.title}}</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{# vim: set ft=jinja: #}
|
|
@ -10,15 +10,25 @@
|
|||
{% if room is defined %}
|
||||
<p>Stanza {{ room }}</p>
|
||||
{% endif %}
|
||||
{% if needs: %}
|
||||
<div class="talk-needs">
|
||||
<strong>Materiale necessario:</strong>
|
||||
{{needs|join(", ")}}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="talk-description">{{text}}</div>
|
||||
<div class="talk-description">{{text | markdown}}
|
||||
{% if contacts: %}
|
||||
<p class="contacts">A cura di {{contacts|join(', ')}}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if links is defined or resources is defined or mail is defined %}
|
||||
<div class="talk-resources">
|
||||
<h4>Link utili:</h4>
|
||||
<ul>
|
||||
{% if links is defined: %}
|
||||
{% for link in links %}
|
||||
<li>{{link}}</li>
|
||||
<li>{{link|urlize}}</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if resources is defined: %}
|
||||
|
|
48
talks/cable/meta.yaml
Normal file
48
talks/cable/meta.yaml
Normal file
|
@ -0,0 +1,48 @@
|
|||
# File di esempio; copialo e cambialo
|
||||
title: "Cable: una rete federata di server Signal"
|
||||
text: |
|
||||
Signal è riconosciuto come uno degli strumenti più validi per quanto
|
||||
riguarda la messaggistica privata, avendo tutte le caratteristiche
|
||||
desiderabili a livello di protocollo e algoritmi e un'usabilità pari ai
|
||||
più diffusi prodotti commerciali. Si tratta purtroppo di un servizio
|
||||
centralizzato, i cui server sono interamente gestiti da una specifica
|
||||
entità.
|
||||
|
||||
I software che implementano il servizio (server e client) supportano
|
||||
però la federazione, è quindi possibile costruire una rete
|
||||
decentralizzata e indipendente. Il talk vuole esporre il lavoro che
|
||||
abbiamo fatto in questo senso in HacklabBo.
|
||||
|
||||
Programma di massima:
|
||||
|
||||
0. Il senso di questo lavoro
|
||||
1. Infrastruttura del servizio Signal
|
||||
2. Liberazione di client e server da servizi commerciali
|
||||
3. Federazione di due server
|
||||
4. Call for federation
|
||||
5. Discussione
|
||||
|
||||
# Se ancora non è stata assegnata una stanza al talk, commentala. Non usare un valore tipo "qualunque" o
|
||||
# cose del genere, che ci si incasina tutto
|
||||
# room: ""
|
||||
# Ci vanno le virgolette intorno! altrimenti 17.30 viene interpretato come un numero decimale
|
||||
duration: 90
|
||||
# time: "17.30"
|
||||
# day: 1
|
||||
tags:
|
||||
- comunicazione
|
||||
- servizi autogestiti
|
||||
# Devono essere dei link validi!
|
||||
links:
|
||||
- https://github.com/WhisperSystems/Signal-Server/wiki/API-Protocol
|
||||
# mail dovrebbe contenere un link alla mail con cui il talk è stato proposto
|
||||
# così si può sapere chi contattare e se c'è stata una discussione
|
||||
mail: http://lists.autistici.org/message/20170515.205020.ba238125.en.html
|
||||
needs:
|
||||
- proiettore
|
||||
contacts:
|
||||
- torn
|
||||
- gine
|
||||
|
||||
# Devi usare UTF-8, non t'inventare scuse, sappiamo ndo abiti
|
||||
# vim: set fileencoding=utf-8:
|
48
talks/copiaforense/meta.yaml
Normal file
48
talks/copiaforense/meta.yaml
Normal file
|
@ -0,0 +1,48 @@
|
|||
# File di esempio; copialo e cambialo
|
||||
title: "Copia forense, un'esperienza da tecnico di parte e il problema del pranzo"
|
||||
text: |
|
||||
Ripercorriamo la prima esperienza sul campo di hacklabbo/ams da
|
||||
consulenti tecnici di parte per una copia forense.
|
||||
Analizzeremo assieme il sequestro, la nomina e le operazioni compiute.
|
||||
|
||||
Parleremo di:
|
||||
|
||||
* imballi, sigilli e come devo essere maneggiati i dispositivi dal CTU
|
||||
* quale materiale il CTP deve portarsi il giorno della copia
|
||||
* il problema del pranzo
|
||||
* una piccola panoramica su Deft Zero
|
||||
* i formati di acquisizione
|
||||
* Ufed Cellbrite Touch, per l'estrapolazione dei dati dal telefono
|
||||
* la parti del verbale e cosa far scrivere
|
||||
* curiose anomalie
|
||||
* la figura del CTP, serve? Non serve? Cosa possiamo fare come hacklab
|
||||
per i/le compagni/e inguiati/e?
|
||||
|
||||
needs:
|
||||
- proiettore
|
||||
# Se ancora non è stata assegnata una stanza al talk, commentala. Non usare un valore tipo "qualunque" o
|
||||
# cose del genere, che ci si incasina tutto
|
||||
# room: antani
|
||||
|
||||
# duration è la durata in minuti del talk
|
||||
duration: 60
|
||||
|
||||
# Ci vanno le virgolette intorno! altrimenti 17.30 viene interpretato come un numero decimale
|
||||
# time: "17.30"
|
||||
# day è il giorno in cui avverrà il talk. Finché non decommenti il talk non sarà schedulato
|
||||
# 0=giovedì, 1=venerdì, 2=sabato, 3=domenica
|
||||
# day: 0
|
||||
|
||||
tags:
|
||||
- legale
|
||||
# Devono essere dei link validi!
|
||||
links:
|
||||
# mail dovrebbe contenere un link alla mail con cui il talk è stato proposto
|
||||
# così si può sapere chi contattare e se c'è stata una discussione
|
||||
mail: "http://lists.autistici.org/message/20170516.235536.3e0103ea.en.html"
|
||||
contacts:
|
||||
- jops
|
||||
- gine
|
||||
|
||||
# Devi usare UTF-8, non t'inventare scuse, sappiamo ndo abiti
|
||||
# vim: set fileencoding=utf-8:
|
1
talks/meta.yaml
Normal file
1
talks/meta.yaml
Normal file
|
@ -0,0 +1 @@
|
|||
startdate: 2017-06-15
|
Loading…
Reference in a new issue