README: Add crate layout guide
This commit is contained in:
parent
96ce1aeef6
commit
6afe84d34a
2 changed files with 62 additions and 2 deletions
13
README.rst
13
README.rst
|
|
@ -27,7 +27,18 @@ Each bottle contains a LED with a WS2801 driver. Each crate contains a chain of
|
|||
2. Poke a 12mm hole in the lid
|
||||
3. Put it in a crate
|
||||
4. Repeat from step 1
|
||||
5. Stick a loop of LEDs through the lids of the bottles
|
||||
5. Stick a loop of LEDs through the lids of the bottles like this:
|
||||
.. code::
|
||||
┏━━━┯━━━┯━━━┯━━━┯━━━┓
|
||||
{start}→┃ ○ → ○ → ○ → ○ → ○ ┃
|
||||
┠───┼───┼───┼───┼─↓─┨
|
||||
{ end}←┃ ○ │ ○ ← ○ ← ○ ← ○ ┃
|
||||
┠─↑─┼─↓─┼───┼───┼───┨
|
||||
┃ ○ │ ○ → ○ → ○ → ○ ┃
|
||||
┠─↑─┼───┼───┼───┼─↓─┨
|
||||
┃ ○ ← ○ ← ○ ← ○ ← ○ ┃
|
||||
┗━━━┷━━━┷━━━┷━━━┷━━━┛
|
||||
|
||||
6. Repeat from step 1
|
||||
7. Stack up a bunch of these crates and tie them together with zip ties and straps
|
||||
8. Connect all the wires together (mis-)using wonderful XLR connectors
|
||||
|
|
|
|||
|
|
@ -1,7 +1,56 @@
|
|||
|
||||
from collections import defaultdict
|
||||
import signal
|
||||
|
||||
|
||||
RATELIMIT_THRESHOLD = 20
|
||||
GRAYLIST_LENGTH = 8
|
||||
|
||||
class SpamError(ValueError):
|
||||
def __str__(self):
|
||||
return ' '.join(self.args)
|
||||
|
||||
|
||||
def loadlist(fn):
|
||||
try:
|
||||
with open(fn) as f:
|
||||
return [ l for l in ( l.strip() for l in f.readlines() if not l.startswith('#')) if l ]
|
||||
except:
|
||||
return []
|
||||
|
||||
greenlist = set()
|
||||
|
||||
graylist = []
|
||||
def do_graylist(msg):
|
||||
global graylist
|
||||
graylist = [msg] + graylist[:GRAYLIST_LENGTH-1]
|
||||
|
||||
blacklist = loadlist('blacklist')
|
||||
badwords = loadlist('badwords')
|
||||
def signal_handler(_signum, _frame):
|
||||
global blacklist, badwords
|
||||
blacklist = load_blacklist()
|
||||
badwords = load_badwords()
|
||||
signal.signal(signal.SIGHUP, signal_handler)
|
||||
|
||||
ratelimitdict = defaultdict(lambda: 0)
|
||||
def empty_ratelimit(_signum, _frame):
|
||||
global ratelimitdict
|
||||
ratelimitdict = defaultdict(lambda: 0)
|
||||
signal.signal(signal.SIGALRM, empty_ratelimit)
|
||||
signal.setitimer(signal.ITIMER_REAL, 60)
|
||||
|
||||
def check_spam(addr, data):
|
||||
pass
|
||||
ratelimitdict[addr] += 1
|
||||
try:
|
||||
if ratelimitdict[addr] > RATELIMIT_THRESHOLD:
|
||||
raise SpamError('rate-limit')
|
||||
if any(word in data.lower() for word in badwords):
|
||||
raise SpamError('badwords filter')
|
||||
if addr not in greenlist and data in graylist:
|
||||
raise SpamError('graylist')
|
||||
except SpamError as err:
|
||||
do_graylist(data)
|
||||
blacklist.append(addr)
|
||||
raise err
|
||||
greenlist.add(addr)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue