mirror of
https://github.com/9001/copyparty.git
synced 2025-08-22 03:12:20 -06:00
write qrcode to file
This commit is contained in:
parent
cc4f4aef99
commit
202ddeac0d
|
@ -1115,6 +1115,7 @@ def add_qr(ap, tty):
|
||||||
ap2.add_argument("--qrz", metavar="N", type=int, default=0, help="[\033[32m1\033[0m]=1x, [\033[32m2\033[0m]=2x, [\033[32m0\033[0m]=auto (try [\033[32m2\033[0m] on broken fonts)")
|
ap2.add_argument("--qrz", metavar="N", type=int, default=0, help="[\033[32m1\033[0m]=1x, [\033[32m2\033[0m]=2x, [\033[32m0\033[0m]=auto (try [\033[32m2\033[0m] on broken fonts)")
|
||||||
ap2.add_argument("--qr-pin", metavar="N", type=int, default=0, help="sticky/pin the qr-code to always stay on-screen; [\033[32m0\033[0m]=disabled, [\033[32m1\033[0m]=with-url, [\033[32m2\033[0m]=just-qr")
|
ap2.add_argument("--qr-pin", metavar="N", type=int, default=0, help="sticky/pin the qr-code to always stay on-screen; [\033[32m0\033[0m]=disabled, [\033[32m1\033[0m]=with-url, [\033[32m2\033[0m]=just-qr")
|
||||||
ap2.add_argument("--qr-wait", metavar="SEC", type=float, default=0, help="wait \033[33mSEC\033[0m before printing the qr-code to the log")
|
ap2.add_argument("--qr-wait", metavar="SEC", type=float, default=0, help="wait \033[33mSEC\033[0m before printing the qr-code to the log")
|
||||||
|
ap2.add_argument("--qr-file", metavar="TXT", type=u, action="append", help="\033[34mREPEATABLE:\033[0m write qr-code to file.\n └─To create txt or svg, \033[33mTXT\033[0m is Filepath:Zoom:Pad, for example [\033[32mqr.txt:1:2\033[0m]\n └─To create png or gif, \033[33mTXT\033[0m is Filepath:Zoom:Pad:Foreground:Background, for example [\033[32mqr.png:8:2:333333:ffcc55\033[0m], or [\033[32mqr.png:8:2::ffcc55\033[0m] for transparent")
|
||||||
|
|
||||||
|
|
||||||
def add_fs(ap):
|
def add_fs(ap):
|
||||||
|
|
|
@ -200,6 +200,25 @@ class QrCode(object):
|
||||||
|
|
||||||
return "\n".join(rows)
|
return "\n".join(rows)
|
||||||
|
|
||||||
|
def to_png(self, zoom, pad, bg, fg, ap) -> None:
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
tab = self.modules
|
||||||
|
sz = self.size
|
||||||
|
psz = sz + pad * 2
|
||||||
|
if bg:
|
||||||
|
img = Image.new("RGB", (psz, psz), bg)
|
||||||
|
else:
|
||||||
|
img = Image.new("RGBA", (psz, psz), (0, 0, 0, 0))
|
||||||
|
fg = (fg[0], fg[1], fg[2], 255)
|
||||||
|
for y in range(sz):
|
||||||
|
for x in range(sz):
|
||||||
|
if tab[y][x]:
|
||||||
|
img.putpixel((x + pad, y + pad), fg)
|
||||||
|
if zoom != 1:
|
||||||
|
img = img.resize((sz * zoom, sz * zoom), Image.Resampling.NEAREST)
|
||||||
|
img.save(ap)
|
||||||
|
|
||||||
def _draw_function_patterns(self) -> None:
|
def _draw_function_patterns(self) -> None:
|
||||||
# Draw horizontal and vertical timing patterns
|
# Draw horizontal and vertical timing patterns
|
||||||
for i in range(self.size):
|
for i in range(self.size):
|
||||||
|
|
|
@ -9,7 +9,7 @@ import time
|
||||||
|
|
||||||
from .__init__ import ANYWIN, PY2, TYPE_CHECKING, unicode
|
from .__init__ import ANYWIN, PY2, TYPE_CHECKING, unicode
|
||||||
from .cert import gencert
|
from .cert import gencert
|
||||||
from .stolen.qrcodegen import QrCode
|
from .stolen.qrcodegen import QrCode, qr2svg
|
||||||
from .util import (
|
from .util import (
|
||||||
E_ACCESS,
|
E_ACCESS,
|
||||||
E_ADDR_IN_USE,
|
E_ADDR_IN_USE,
|
||||||
|
@ -621,6 +621,10 @@ class TcpSrv(object):
|
||||||
pad = self.args.qrp
|
pad = self.args.qrp
|
||||||
zoom = self.args.qrz
|
zoom = self.args.qrz
|
||||||
qrc = QrCode.encode_binary(btxt)
|
qrc = QrCode.encode_binary(btxt)
|
||||||
|
|
||||||
|
for zs in self.args.qr_file or []:
|
||||||
|
self._qr2file(qrc, zs)
|
||||||
|
|
||||||
if zoom == 0:
|
if zoom == 0:
|
||||||
try:
|
try:
|
||||||
tw, th = termsize()
|
tw, th = termsize()
|
||||||
|
@ -656,3 +660,29 @@ class TcpSrv(object):
|
||||||
t = t.replace("\n", "`\n`")
|
t = t.replace("\n", "`\n`")
|
||||||
|
|
||||||
return txt + t
|
return txt + t
|
||||||
|
|
||||||
|
def _qr2file(self, qrc: QrCode, txt: str):
|
||||||
|
if ".txt:" in txt or ".svg:" in txt:
|
||||||
|
ap, zs1, zs2 = txt.rsplit(":", 2)
|
||||||
|
bg = fg = ""
|
||||||
|
else:
|
||||||
|
ap, zs1, zs2, bg, fg = txt.rsplit(":", 4)
|
||||||
|
zoom = int(zs1)
|
||||||
|
pad = int(zs2)
|
||||||
|
|
||||||
|
if ap.endswith(".txt"):
|
||||||
|
if zoom not in (1, 2):
|
||||||
|
raise Exception("invalid zoom for qr.txt; must be 1 or 2")
|
||||||
|
with open(ap, "wb") as f:
|
||||||
|
f.write(qrc.render(zoom, pad).encode("utf-8"))
|
||||||
|
elif ap.endswith(".svg"):
|
||||||
|
with open(ap, "wb") as f:
|
||||||
|
f.write(qr2svg(qrc, pad).encode("utf-8"))
|
||||||
|
else:
|
||||||
|
qrc.to_png(zoom, pad, self._h2i(bg), self._h2i(fg), ap)
|
||||||
|
|
||||||
|
def _h2i(self, hs):
|
||||||
|
try:
|
||||||
|
return tuple(int(hs[i : i + 2], 16) for i in (0, 2, 4))
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
|
@ -170,7 +170,7 @@ class Cfg(Namespace):
|
||||||
ex = "ban_403 ban_404 ban_422 ban_pw ban_pwc ban_url spinner"
|
ex = "ban_403 ban_404 ban_422 ban_pw ban_pwc ban_url spinner"
|
||||||
ka.update(**{k: "no" for k in ex.split()})
|
ka.update(**{k: "no" for k in ex.split()})
|
||||||
|
|
||||||
ex = "ext_th grp idp_h_usr idp_hm_usr ipr on403 on404 xac xad xar xau xban xbc xbd xbr xbu xiu xm"
|
ex = "ext_th grp idp_h_usr idp_hm_usr ipr on403 on404 qr_file xac xad xar xau xban xbc xbd xbr xbu xiu xm"
|
||||||
ka.update(**{k: [] for k in ex.split()})
|
ka.update(**{k: [] for k in ex.split()})
|
||||||
|
|
||||||
ex = "exp_lg exp_md"
|
ex = "exp_lg exp_md"
|
||||||
|
|
Loading…
Reference in a new issue