aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjaseg <code@jaseg.net>2016-01-24 18:34:03 +0100
committerjaseg <code@jaseg.net>2016-01-24 18:40:10 +0100
commit6afe84d34afa76071f45b0eb9ca4d1f5cd0417c1 (patch)
tree6cf1c087f68859c8ccda9f3d0a24cbc97f58216e
parent96ce1aeef68f0cad397bea43b82eff1a5e407c2c (diff)
downloadmatelight-6afe84d34afa76071f45b0eb9ca4d1f5cd0417c1.tar.gz
matelight-6afe84d34afa76071f45b0eb9ca4d1f5cd0417c1.tar.bz2
matelight-6afe84d34afa76071f45b0eb9ca4d1f5cd0417c1.zip
README: Add crate layout guide
-rw-r--r--README.rst13
-rw-r--r--host/secret_sauce.py51
2 files changed, 62 insertions, 2 deletions
diff --git a/README.rst b/README.rst
index f0a5269..6b3caac 100644
--- a/README.rst
+++ b/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
diff --git a/host/secret_sauce.py b/host/secret_sauce.py
index bf183ac..3682b0e 100644
--- a/host/secret_sauce.py
+++ b/host/secret_sauce.py
@@ -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)