-
-
TeleVex recently printed:
-
(last 25)
-
+
TeleVex recently printed:
+
+---
+(last 25)
+(this is a de-bugging tool that most likely will disappear again)
+---
{% set count = 25 %}
{% for x in range(1, 25) %}
{% set item = items["printed"][-x] %}
{% if item %}
-
- Source: {{ item.source }}
- Date: {{ item.date }}
- Printed: {{ item.printed }}
-
-
+
+
Source: {{ item.source }}
+
Date: {{ item.date }}
+
Printed:
+
{{ item.printed | replace('\n', '
') | safe }}
+
{% endif %}
{% set count = count - 1 %}
{% endfor %}
diff --git a/print/tools/asciiWriter/__init__.py b/print/tools/asciiWriter/__init__.py
new file mode 100644
index 0000000..63f77b6
--- /dev/null
+++ b/print/tools/asciiWriter/__init__.py
@@ -0,0 +1,2 @@
+#!/usr/bin/env python3
+
diff --git a/print/tools/asciiWriter/asciiWriter.py b/print/tools/asciiWriter/asciiWriter.py
new file mode 100644
index 0000000..03e16e1
--- /dev/null
+++ b/print/tools/asciiWriter/asciiWriter.py
@@ -0,0 +1,6 @@
+#!/usr/bin/env python3
+
+import utils
+import patterns
+import marks
+import text
\ No newline at end of file
diff --git a/print/tools/asciiWriter/draw.py b/print/tools/asciiWriter/draw.py
new file mode 100644
index 0000000..5dee52e
--- /dev/null
+++ b/print/tools/asciiWriter/draw.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+from utils import make_lines, merge, print_lines, rotate, visit, visit_horizontal
+from patterns import diagonal, horizontal, vertical, sinus_horizontal, sinus_vertical, image
+from marks import random_mark, sequence_mark, space
+from random import choice, random
+import math
+
+
+
+
+# marks = ['┼', '│', '░', '▓', 'X', '■', '≡', '·', '¦', ' ']
+# blank = ' '
+width = 75
+height = 50
+mark = sequence_mark('O.P.E.N D.E.S.I.G.N C.O.U.R.S.E ')
+
+
+layers = []
+
+# layers.append(visit(make_lines(width, height), image('blobs-small.png'), mark, space(' ')))
+
+for offset in range(-50, 50, 15):
+ lines = [[] for l in range(height)]
+ sinus = sinus_vertical(period=50, amplitude=25, offset=offset, offset_t=random())
+ layers.append(visit(make_lines(width, height), sinus, sequence_mark(' K A S K G E N T '), space()))
+
+for offset in range(-43, 57, 15):
+ lines = [[] for l in range(height)]
+ sinus = sinus_vertical(period=40, amplitude=10, offset=offset, offset_t=.5+random())
+ layers.append(visit(make_lines(width, height), sinus, mark, space()))
+
+print_lines(merge(width, height, space()(), layers))
+
+# for line in overlay(50, 50, ' ', [rotate(merged), merged]):
+# stdout.write('{}\n'.format(''.join(line)))
+
+# sinus = sinus_horizontal(period=30, amplitude=8)
+# for x in range(width):
+# for y in range(height):
+# lines[y].append(sinus(x, y, width, height, mark, space()))
+
+# for line in lines:
+# stdout.write('{}\n'.format(''.join(line)))
+
+# lines = [[draw(x, y, marks) for x in range(width)] for y in range(height)]
+
+# sys.sdout.write('\n'.join([''.join(line) for line in lines]))
+
+# sys.sdout.write('\n'.join([''.join([draw(x, y, marks) for x in range(width)]) for y in range(height)]))
diff --git a/print/tools/asciiWriter/marks.py b/print/tools/asciiWriter/marks.py
new file mode 100644
index 0000000..7610339
--- /dev/null
+++ b/print/tools/asciiWriter/marks.py
@@ -0,0 +1,24 @@
+from random import choice
+
+def random (marks=['']):
+ def func ():
+ return choice(marks)
+
+ return func
+
+def sentence (text):
+ chars = list(text)
+ def f():
+ char = chars.pop(0)
+ chars.append(char)
+ return char
+ return f
+
+def single (char):
+ def f():
+ return char
+
+ return f
+
+def space (space=' '):
+ return single(space)
diff --git a/print/tools/asciiWriter/patterns.py b/print/tools/asciiWriter/patterns.py
new file mode 100644
index 0000000..2c7a817
--- /dev/null
+++ b/print/tools/asciiWriter/patterns.py
@@ -0,0 +1,67 @@
+import math
+
+# # Linear
+def diagonal():
+ def f (x, y, width, height, mark, blank):
+ if x == math.floor((y / float(height)) * width):
+ return mark()
+ else:
+ return blank()
+
+ return f
+
+# Cross
+def cross ():
+ def f (x, y, width, height, mark, blank):
+ pos = math.floor((y / float(height)) * width)
+
+ if x == pos or (width - 1) - pos == x:
+ return mark()
+ else:
+ return blank()
+ return f
+
+def horizontal (position):
+ def f (x, y, width, height, mark, blank):
+ return mark() if position == y else blank()
+ return f
+
+def vertical (position):
+ def f (x, y, width, height, mark, blank):
+ return mark() if position == x else blank()
+ return f
+
+# Sinus
+def sinus_vertical (period=0.2, amplitude=0.5, offset_t=0, offset=0):
+ period = (period / (math.pi * 2))
+
+ def f (x, y, width, height, mark, blank):
+ middle = (width - 1) * .5
+ to_mark = math.floor(middle + math.sin(offset_t + y / period) * amplitude)
+ return mark() if (x + offset) == to_mark else blank()
+ return f
+
+def sinus_horizontal (period=0.2, amplitude=0.5, offset_t=0, offset=0):
+ period = (period / (math.pi * 2))
+ def f (x, y, width, height, mark, blank):
+ middle = (height - 1) * .5
+ to_mark = math.floor(middle + math.sin(offset_t + x / period) * amplitude)
+ return mark() if y + offset == to_mark else blank()
+
+ return f
+
+def image (path, threshold=128):
+ from PIL import Image
+
+ im = Image.open(path).convert('L')
+ image_width, image_height = im.size
+ pixels = im.load()
+
+ def f (x, y, width, height, mark, blank):
+ if x < image_width and y < image_height:
+ if pixels[x, y] < threshold:
+ return mark()
+
+ return blank()
+
+ return f
diff --git a/print/tools/asciiWriter/text.py b/print/tools/asciiWriter/text.py
new file mode 100644
index 0000000..5fa330b
--- /dev/null
+++ b/print/tools/asciiWriter/text.py
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+from .wrap_single_line import wrap_single_line
+from .utils import translate, merge
+
+def make_column(text, line_width=50, height=200, use_hyphenator=None, line_offset=0):
+
+ lines = []
+ remaining = text
+
+ while remaining and len(lines) < height:
+
+ if callable(line_width):
+ width = line_width(len(lines), height)
+ else:
+ width = line_width
+
+ if callable(line_offset):
+ offset = line_offset(len(lines), height)
+ else:
+ offset = line_offset
+
+ line, remaining = wrap_single_line(remaining, width, use_hyphenator=use_hyphenator, replace_whitespace=False, drop_whitespace=True)
+
+ line = list(line)
+
+ if offset != 0:
+ line = [None for _ in range(offset)] + line
+
+ lines.append(line)
+
+ return lines, remaining
+
+def make_multi_column(text, height=200, column_width=40, column_count=2, column_gap=5, use_hyphenator=None, space_char=None):
+ # todo: vertical offset?
+
+ remaining = text
+ i = 0
+
+ columns = []
+
+ while remaining and i < column_count:
+ column, remaining = make_column(remaining, line_width=column_width, height=height, use_hyphenator=use_hyphenator)
+ if i > 0:
+ offset = (column_width + column_gap) * i
+ column = translate(column, x=offset, y=0)
+ columns.append(column)
+ i += 1
+
+ width = (column_width + column_gap) * column_count
+ lines = merge(width, height, space_char, columns)
+ return lines, remaining
+
+
+if __name__ == '__main__':
+ print(make_column('Hello world!', line_width=25, height=10))
\ No newline at end of file
diff --git a/print/tools/asciiWriter/utils.py b/print/tools/asciiWriter/utils.py
new file mode 100644
index 0000000..ec7473b
--- /dev/null
+++ b/print/tools/asciiWriter/utils.py
@@ -0,0 +1,61 @@
+from sys import stdout
+
+def rotate(layer):
+ new_width = len(layer)
+ new_height = len(layer[0])
+ rotated = [['' for x in range(new_width)] for l in range(new_height)]
+
+ for y in range(len(layer)):
+ for x in range(len(layer[y])):
+ rotated[x][y] = layer[y][x]
+
+ return rotated
+
+def merge(width, height, space_char, layers):
+ output = [[space_char for x in range(width)] for y in range(height)]
+
+ for layer in layers:
+ for y in range(min(len(layer), height)):
+ for x in range(min(len(layer[y]), width)):
+ if layer[y][x] and layer[y][x] != space_char:
+ output[y][x] = layer[y][x]
+
+ return output
+
+# Make a multidimensional array
+# with the given dimensions
+def make_lines (width, height, fill_char = ''):
+ return [[ fill_char for _ in range(width) ] for __ in range(height)]
+
+def visit (lines, callback, mark, blank):
+ height = len(lines)
+ width = len(lines[0])
+
+ for y in range(height):
+ for x in range(width):
+ lines[y][x] = callback(x, y, width, height, mark, blank)
+
+ return lines
+
+def visit_horizontal (lines, callback, mark, blank):
+ height = len(lines)
+ width = len(lines[0])
+
+ for x in range(width):
+ for y in range(height):
+ lines[y][x] = callback(x, y, width, height, mark, blank)
+
+ return lines
+
+def print_lines (lines):
+ for line in lines:
+ stdout.write('{}\n'.format(''.join(line)))
+
+def translate(shape, x=0, y=0):
+ ## TODO implement a negative translation?
+ translated = [[] for _ in range(y)]
+
+ for line in shape:
+ translated.append([None for _ in range(x)] + line)
+
+ return translated
\ No newline at end of file
diff --git a/print/tools/asciiWriter/wrap_single_line.py b/print/tools/asciiWriter/wrap_single_line.py
new file mode 100644
index 0000000..b06f6e4
--- /dev/null
+++ b/print/tools/asciiWriter/wrap_single_line.py
@@ -0,0 +1,137 @@
+"""
+ Based on the textwrap2 module included in the PyHyphen library:
+ https://pypi.org/project/PyHyphen
+"""
+
+import textwrap
+
+class TextWrapper(textwrap.TextWrapper):
+ """
+ This class extends the Python 3 standard library's TextWrapper and adds an optional
+ use_hyphenator to its constructor arguments.
+ """
+
+ def __init__(self, *args, **kwargs):
+ self.use_hyphenator = kwargs.pop("use_hyphenator", None)
+ super().__init__(*args, **kwargs)
+
+ def _wrap_chunks(self, chunks):
+
+ lines = []
+ if (chunks):
+ """Override the mother class method.
+
+ Most of that method is directly copied from the original class, except
+ for the part with use_hyphenator.
+ """
+ if self.width <= 0:
+ raise ValueError("invalid width %r (must be > 0)" % self.width)
+ if self.max_lines is not None:
+ if self.max_lines > 1:
+ indent = self.subsequent_indent
+ else:
+ indent = self.initial_indent
+ if len(indent) + len(self.placeholder.lstrip()) > self.width:
+ raise ValueError("placeholder too large for max width")
+
+ # Arrange in reverse order so items can be efficiently popped
+ # from a stack of chucks.
+ chunks.reverse()
+
+ # Start the list of chunks that will make up the current line.
+ # cur_len is just the length of all the chunks in cur_line.
+ cur_line = []
+ cur_len = 0
+
+ # Figure out which static string will prefix this line.
+ if lines:
+ indent = self.subsequent_indent
+ else:
+ indent = self.initial_indent
+
+ # Maximum width for this line.
+ width = self.width - len(indent)
+
+ # First chunk on line is whitespace -- drop it, unless this
+ # is the very beginning of the text (ie. no lines started yet).
+ if self.drop_whitespace and chunks[-1].strip() == '' and chunks[-1][0] != '\n': # and lines:
+ del chunks[-1]
+
+ while chunks:
+ l = len(chunks[-1])
+
+ # Check for a newline character
+ if chunks[-1] == '\n':
+ return indent + ''.join(cur_line), ''.join(reversed(chunks[:-1]))
+ elif chunks[-1][0] == '\n':
+ return indent + ''.join(cur_line), ''.join(reversed(chunks[:-1] + [chunks[-1][1:]]))
+
+ # Can at least squeeze this chunk onto the current line.
+ if cur_len + l <= width:
+ cur_line.append(chunks.pop())
+ cur_len += l
+
+ # Nope, this line is full.
+ # But try hyphenation.
+ else:
+ if self.use_hyphenator and (width - cur_len >= 2):
+ hyphenated_chunk = self.use_hyphenator.wrap(chunks[-1], width - cur_len)
+ if hyphenated_chunk:
+ cur_line.append(hyphenated_chunk[0])
+ chunks[-1] = hyphenated_chunk[1]
+
+ break
+
+ # The current line is full, and the next chunk is too big to
+ # fit on *any* line (not just this one).
+ if chunks and len(chunks[-1]) > width:
+ self._handle_long_word(chunks, cur_line, cur_len, width)
+ cur_len = sum(map(len, cur_line))
+
+ # If the last chunk on this line is all whitespace, drop it.
+ if self.drop_whitespace and cur_line and cur_line[-1].strip() == '':
+ cur_len -= len(cur_line[-1])
+ del cur_line[-1]
+
+ if cur_line:
+ if (self.max_lines is None or
+ len(lines) + 1 < self.max_lines or
+ (not chunks or
+ self.drop_whitespace and
+ len(chunks) == 1 and
+ not chunks[0].strip()) and cur_len <= width):
+ # Convert current line back to a string and store it in
+ # list of all lines (return value).
+ return indent + ''.join(cur_line), ''.join(reversed(chunks))
+ else:
+ while cur_line:
+ if (cur_line[-1].strip() and
+ cur_len + len(self.placeholder) <= width):
+ cur_line.append(self.placeholder)
+
+ return indent + ''.join(cur_line), ''.join(reversed(chunks))
+
+ cur_len -= len(cur_line[-1])
+ del cur_line[-1]
+ else:
+ if lines:
+ prev_line = lines[-1].rstrip()
+ if (len(prev_line) + len(self.placeholder) <=
+ self.width):
+ lines[-1] = prev_line + self.placeholder
+
+ return indent + self.placeholder.lstrip(), ''.join(reversed(chunks))
+ else:
+ return '', ''
+
+def wrap_single_line (text, width=70, **kwargs):
+ w = TextWrapper(width=width, **kwargs)
+ return w.wrap(text)
+
+if __name__ == '__main__':
+ from hyphen import Hyphenator
+ h_en = Hyphenator('en_US')
+
+ line, remaining = wrap_single_line('https://stackoverflow.com/questions/3940128/how-can-i-reverse-a-list-in-python', width=46, use_hyphenator=h_en)
+
+ print(line, remaining)
\ No newline at end of file
diff --git a/print/tools/televex/televex.py b/print/tools/televex/televex.py
new file mode 100644
index 0000000..a15c4ea
--- /dev/null
+++ b/print/tools/televex/televex.py
@@ -0,0 +1,95 @@
+import sys, os, re, json
+from datetime import datetime, date
+import html2text
+from escpos import printer
+
+from tools.asciiWriter.text import make_column
+from tools.asciiWriter.utils import merge, print_lines, make_lines, translate
+
+def connect():
+ # Get the printer's USB initializing code with $ sudo lsbusb
+ try:
+ lp = printer.Usb(0x4b8,0xe15)
+ lp_printer = True
+ except:
+ lp = None
+ lp_printer = False
+
+ return lp, lp_printer
+
+def database(db):
+ if not os.path.exists(db):
+ with open(db, 'w') as f:
+ f.write(json.dumps({ "printed" : [] }, indent=4))
+
+ return db
+
+def html2plain(html):
+ # remove HTML tags
+ txt = re.sub(r'<.*?>', '', html)
+
+ # make line breaks
+ # https://git.vvvvvvaria.org/mb/ascii-art-but-with-unicode
+ width = 48
+ layers = []
+ lines, remaining = make_column(txt, line_width=width)
+ layers.append(lines)
+ merged = merge(width, len(lines), ' ', layers)
+ txt = ''
+ for line in merged:
+ txt += '{}\n'.format(''.join(line))
+
+ return txt
+
+def update_db(txt, source, db, post=None):
+ try:
+ items = json.loads(open(db).read())
+ except:
+ items = { "printed" : [] } # Hmm ...
+
+ # save the publishing date of this post
+ if post:
+ year = post['published_parsed'][0]
+ month = post['published_parsed'][1]
+ day = post['published_parsed'][2]
+ post_date = date(year, month, day)
+ date_str = post_date.strftime('%Y-%m-%d')
+ post = None
+ else:
+ post_date = datetime.now()
+ date_str = post_date.strftime('%Y-%m-%d_%H-%M-%S')
+
+ # clean txt from HTML tags
+ txt = html2plain(txt)
+
+ # add txt to database
+ # and check if this item is new
+ item = {
+ 'source' : source,
+ 'date' : date_str,
+ 'printed' : txt
+ }
+ if item not in items['printed']:
+ new_item = True
+ with open(db, 'w') as out:
+ items['printed'].append(item)
+ out.write(json.dumps(items, indent=4))
+ out.close()
+ else:
+ new_item = False
+
+ return new_item, txt
+
+def print_now(txt, source, db, post=None, lp=None, lp_printer=None):
+ # check if this is a new item
+ new_item, txt = update_db(txt, source, db, post=post)
+
+ # if this item is new
+ # then print!
+ if new_item == True:
+ if lp_printer == True:
+ lp.text(txt)
+ lp.cut()
+ else:
+ # or print in the terminal!
+ sys.stderr.write('Printing output to the terminal:\n\n'+txt+'\n\n')
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index 4f8a0fb..5b41a8e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -5,3 +5,4 @@ pypandoc
python-escpos
flask
Flask-APScheduler
+html2text
\ No newline at end of file