Update ASCII plugin

This commit is contained in:
Pedro de Oliveira 2019-12-05 21:40:08 +00:00
parent 23af1cca99
commit 655dbf7e58
4 changed files with 1782 additions and 1817 deletions

View File

@ -1,6 +1,9 @@
[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=T8E56M6SP9JH2) [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=T8E56M6SP9JH2)
Try the plugin out in #ircart on EFnet. irc://irc.efnet.org/#ircart
<b>ASCII Art Plugin</b><br> <b>ASCII Art Plugin</b><br>
Convert text to ASCII art or image URLs to ASCII/ANSI art. Covert ASCII art to PNG. Get ASCII weather, moon phase, and cryptocurrecy rates. Convert text to ASCII art or image URLs to ASCII/ANSI art. Covert ASCII art to PNG. Get ASCII weather, moon phase, and cryptocurrecy rates.
@ -103,14 +106,15 @@ img --bg <0-99> <url> (set a background color)
img --fg <0-99> <url> (set a foreground color) img --fg <0-99> <url> (set a foreground color)
img --fast <url> (use Euclidean color difference.) img --fast <url> (use Euclidean color difference.)
img --slow <url> (use cie2000 color difference. best quality, default) img --slow <url> (use cie2000 color difference. best quality, default)
img --dither <url> (dither source image to 256 colors. trades off quality for speed) img --quantize <url> (quantize source image to 256 colors. trades off quality for speed)
img --no-quantize <url> (don't quantize source to 256 colors)
``` ```
Here are some images using 99 color default output: Here are some images using 99 color default output:
![Image of Img Command Output](https://i.imgur.com/33tCGXC.png)<br> ![Image of Img Command Output](https://i.imgur.com/NrMaQdg.png)<br>
^ output of img https://i.imgur.com/aF9wihd.jpg (image command with default settings) ^ output of img https://i.imgur.com/aF9wihd.jpg (image command with default settings)
![Image of Img Command Output](https://i.imgur.com/2BSUjnw.png)<br> ![Image of Img Command Output](https://i.imgur.com/ydNaDKc.png)<br>
^ output of img --block https://i.imgur.com/aF9wihd.jpg (image command with colored space blocks) ^ output of img --block https://i.imgur.com/aF9wihd.jpg (image command with colored space blocks)
![Image of Img Command Output](https://i.imgur.com/eOQAzTo.png)<br> ![Image of Img Command Output](https://i.imgur.com/Q2lsg3H.png)<br>
^ output of img --ascii https://i.imgur.com/aF9wihd.jpg (image command with colored space blocks) ^ output of img --ascii https://i.imgur.com/aF9wihd.jpg (image command with colored space blocks)
``` ```
***************+*++++++++++++++++++++++++++++++++++++++=++=++========================--------------- ***************+*++++++++++++++++++++++++++++++++++++++=++=++========================---------------

View File

@ -17,14 +17,15 @@ import supybot.world as world
__version__ = "" __version__ = ""
# XXX Replace this with an appropriate author or supybot.Author instance. # XXX Replace this with an appropriate author or supybot.Author instance.
__author__ = supybot.authors.unknown __author__ = supybot.Author('oddluck', 'oddluck',
'oddluck@riseup.net')
# This is a dictionary mapping supybot.Author instances to lists of # This is a dictionary mapping supybot.Author instances to lists of
# contributions. # contributions.
__contributors__ = {} __contributors__ = {}
# This is a url where the most recent plugin package can be downloaded. # This is a url where the most recent plugin package can be downloaded.
__url__ = '' __url__ = 'https://github.com/oddluck/limnoria-plugins/'
from . import config from . import config
from . import plugin from . import plugin

View File

@ -38,8 +38,11 @@ registry.Boolean(False, _("""Turns on and off paste.ee support""")))
conf.registerChannelValue(ASCII, 'delay', conf.registerChannelValue(ASCII, 'delay',
registry.Float(1.0, _("""Set the time delay betwen lines. Not currently implemented."""))) registry.Float(1.0, _("""Set the time delay betwen lines. Not currently implemented.""")))
conf.registerChannelValue(ASCII, 'dither', conf.registerChannelValue(ASCII, 'quantize',
registry.Boolean(True, _("""Enable dithering. Results in much faster rendering at a slight decrease in quality. Default: True"""))) registry.Boolean(False, _("""Enable quantizing to 256 colors before rendering. Results in much faster rendering at a slight decrease in quality. Default: False""")))
conf.registerChannelValue(ASCII, 'resize',
registry.Integer(3, _("""Set the resize algorithm. 0 = nearest, 1 = lanczos, 2 = bilinear, 3 = bicubic, 4 = box, 5 = hamming""")))
conf.registerChannelValue(ASCII, 'speed', conf.registerChannelValue(ASCII, 'speed',
registry.String('Slow', _("""Set the speed of the color rendering. 'Slow' (default) to use CIEDE2000 color difference. 'Fast' to use Euclidean color difference."""))) registry.String('Slow', _("""Set the speed of the color rendering. 'Slow' (default) to use CIEDE2000 color difference. 'Fast' to use Euclidean color difference.""")))
@ -51,7 +54,13 @@ conf.registerChannelValue(ASCII, 'asciiWidth',
registry.Integer(100, _("""Set the default column width for ascii art images"""))) registry.Integer(100, _("""Set the default column width for ascii art images""")))
conf.registerChannelValue(ASCII, 'blockWidth', conf.registerChannelValue(ASCII, 'blockWidth',
registry.Integer(70, _("""Set the default column width for 1/2 and 1/4 block art images"""))) registry.Integer(80, _("""Set the default column width for 1/2 and 1/4 block art images""")))
conf.registerChannelValue(ASCII, 'colors', conf.registerChannelValue(ASCII, 'colors',
registry.Integer(99, _("""Set the default number of colors to use. Options are 16 for colors 0-15 only, 83 for colors 16-98 only, and 99 (default) to use all available colors"""))) registry.Integer(99, _("""Set the default number of colors to use. Options are 16 for colors 0-15 only, 83 for colors 16-98 only, and 99 (default) to use all available colors""")))
conf.registerChannelValue(ASCII, 'fg',
registry.Integer(99, _("""Set the default foreground color for ascii art images. 0-98. 99 is disabled (default)""")))
conf.registerChannelValue(ASCII, 'bg',
registry.Integer(99, _("""Set the default background color for ascii art images. 0-98. 99 is disabled (default)""")))

View File

@ -10,6 +10,7 @@ import supybot.utils as utils
from supybot.commands import * from supybot.commands import *
import supybot.plugins as plugins import supybot.plugins as plugins
import supybot.ircutils as ircutils import supybot.ircutils as ircutils
import supybot.ircdb as ircdb
import supybot.callbacks as callbacks import supybot.callbacks as callbacks
import supybot.ircmsgs as ircmsgs import supybot.ircmsgs as ircmsgs
import os import os
@ -343,15 +344,15 @@ class ASCII(callbacks.Plugin):
self.x256colors83 = [88,28,32,30,36,38,34,96,94,52,56,54,60,62,58,98,88,36,36,48,48,60,32,34,47,47,47,72,32,33,34,59,59,59,44,45,45,46,71,71,44,68,45,69,46,83,56,68,57,57,69,58,28,38,37,49,49,60,30,93,47,72,72,72,31,33,34,59,59,59,43,45,45,46,71,71,56,68,57,69,70,83,56,68,68,57,69,70,28,39,38,49,49,61,41,93,50,50,72,72,30,30,94,84,84,84,43,43,45,46,71,71,43,68,80,81,82,83,55,68,68,80,81,70,40,51,51,50,50,61,41,64,63,50,73,73,30,41,76,87,85,84,42,42,95,96,84,84,55,67,79,81,82,83,55,67,80,80,81,82,40,51,51,50,50,73,41,64,63,75,62,73,53,53,76,87,85,85,42,65,77,76,87,85,42,66,78,78,97,97,55,67,79,79,81,82,52,64,63,63,62,62,52,64,63,75,75,74,53,64,76,87,87,86,65,65,65,76,87,86,54,77,77,77,97,86,54,66,66,78,78,98,88,89,89,90,91,91,92,92,92,93,93,94,94,94,95,95,95,96,96,96,97,97,97,97] self.x256colors83 = [88,28,32,30,36,38,34,96,94,52,56,54,60,62,58,98,88,36,36,48,48,60,32,34,47,47,47,72,32,33,34,59,59,59,44,45,45,46,71,71,44,68,45,69,46,83,56,68,57,57,69,58,28,38,37,49,49,60,30,93,47,72,72,72,31,33,34,59,59,59,43,45,45,46,71,71,56,68,57,69,70,83,56,68,68,57,69,70,28,39,38,49,49,61,41,93,50,50,72,72,30,30,94,84,84,84,43,43,45,46,71,71,43,68,80,81,82,83,55,68,68,80,81,70,40,51,51,50,50,61,41,64,63,50,73,73,30,41,76,87,85,84,42,42,95,96,84,84,55,67,79,81,82,83,55,67,80,80,81,82,40,51,51,50,50,73,41,64,63,75,62,73,53,53,76,87,85,85,42,65,77,76,87,85,42,66,78,78,97,97,55,67,79,79,81,82,52,64,63,63,62,62,52,64,63,75,75,74,53,64,76,87,87,86,65,65,65,76,87,86,54,77,77,77,97,86,54,66,66,78,78,98,88,89,89,90,91,91,92,92,92,93,93,94,94,94,95,95,95,96,96,96,97,97,97,97]
self.x16colors = { self.x16colors = {
'30':'01', '30':'01',
'31':'04', '31':'05',
'32':'03', '32':'03',
'33':'08', '33':'07',
'34':'02', '34':'02',
'35':'06', '35':'06',
'36':'10', '36':'10',
'37':'15', '37':'15',
'30;1':'14', '30;1':'14',
'31;1':'07', '31;1':'04',
'32;1':'09', '32;1':'09',
'33;1':'08', '33;1':'08',
'34;1':'12', '34;1':'12',
@ -359,15 +360,15 @@ class ASCII(callbacks.Plugin):
'36;1':'11', '36;1':'11',
'37;1':'00', '37;1':'00',
'40':'01', '40':'01',
'41':'04', '41':'05',
'42':'03', '42':'03',
'43':'08', '43':'07',
'44':'02', '44':'02',
'45':'06', '45':'06',
'46':'10', '46':'10',
'47':'15', '47':'15',
'40;1':'14', '40;1':'14',
'41;1':'07', '41;1':'04',
'42;1':'09', '42;1':'09',
'43;1':'08', '43;1':'08',
'44;1':'12', '44;1':'12',
@ -464,6 +465,9 @@ class ASCII(callbacks.Plugin):
return self.matches[pixel] return self.matches[pixel]
def rgb2lab (self, inputColor) : def rgb2lab (self, inputColor) :
try:
return self.labmatches[inputColor]
except:
num = 0 num = 0
RGB = [0, 0, 0] RGB = [0, 0, 0]
for value in inputColor : for value in inputColor :
@ -499,82 +503,54 @@ class ASCII(callbacks.Plugin):
Lab [ 0 ] = round( L, 4 ) Lab [ 0 ] = round( L, 4 )
Lab [ 1 ] = round( a, 4 ) Lab [ 1 ] = round( a, 4 )
Lab [ 2 ] = round( b, 4 ) Lab [ 2 ] = round( b, 4 )
return Lab self.labmatches[inputColor] = Lab
return self.labmatches[inputColor]
def ciede2000(self, color1, color2): def ciede2000(self, lab1, lab2):
""" """ CIEDE2000 color difference formula. https://peteroupc.github.io/colorgen.html"""
Calculates color difference according to the `CIEDE 2000`_ formula. This is dl=lab2[0]-lab1[0]
the most accurate algorithm currently implemented but also the most complex hl=lab1[0]+dl*0.5
and slowest. Like CIE1994 it is largely based in CIE L*C*h* space, but with sqb1=lab1[2]*lab1[2]
several modifications to account for perceptual uniformity flaws. sqb2=lab2[2]*lab2[2]
.. _CIEDE 2000: https://en.wikipedia.org/wiki/Color_difference#CIEDE2000 c1=math.sqrt(lab1[1]*lab1[1]+sqb1)
""" c2=math.sqrt(lab2[1]*lab2[1]+sqb2)
# See WP article and Sharma 2005 for important implementation notes: hc7=math.pow((c1+c2)*0.5,7)
# http://www.ece.rochester.edu/~gsharma/ciede2000/ciede2000noteCRNA.pdf trc=math.sqrt(hc7/(hc7+6103515625))
# t2=1.5-trc*0.5
# Yes, there's lots of locals; but this is easiest to understand as it's a ap1=lab1[1]*t2
# near straight translation of the math ap2=lab2[1]*t2
# pylint: disable=too-many-locals c1=math.sqrt(ap1*ap1+sqb1)
C_ = ( c2=math.sqrt(ap2*ap2+sqb2)
math.sqrt(color1[1] ** 2 + color1[2] ** 2) + dc=c2-c1
math.sqrt(color2[1] ** 2 + color2[2] ** 2) hc=c1+dc*0.5
) / 2 hc7=math.pow(hc,7)
trc=math.sqrt(hc7/(hc7+6103515625))
G = (1 - math.sqrt(C_ ** 7 / (C_ ** 7 + 25 ** 7))) / 2 h1=math.atan2(lab1[2],ap1)
a1_prime = (1 + G) * color1[1] if h1<0:
a2_prime = (1 + G) * color2[1] h1=h1+math.pi*2
C1_prime = math.sqrt(a1_prime ** 2 + color1[2] ** 2) h2=math.atan2(lab2[2],ap2)
C2_prime = math.sqrt(a2_prime ** 2 + color2[2] ** 2) if h2<0:
L_ = (color1[0] + color2[0]) / 2 h2=h2+math.pi*2
C_ = (C1_prime + C2_prime) / 2 hdiff=h2-h1
h1 = ( hh=h1+h2
0.0 if color1[2] == a1_prime == 0 else if abs(hdiff)>math.pi:
math.degrees(math.atan2(color1[2], a1_prime)) % 360 hh=hh+math.pi*2
) if h2<=h1:
h2 = ( hdiff=hdiff+math.pi*2
0.0 if color2[2] == a2_prime == 0 else
math.degrees(math.atan2(color2[2], a2_prime)) % 360
)
if C1_prime * C2_prime == 0.0:
dh = 0.0
h_ = h1 + h2
elif abs(h1 - h2) <= 180:
dh = h2 - h1
h_ = (h1 + h2) / 2
else: else:
if h2 > h1: hdiff=hdiff-math.pi*2
dh = h2 - h1 - 360 hh=hh*0.5
else: t2=1-0.17*math.cos(hh-math.pi/6)+0.24*math.cos(hh*2)
dh = h2 - h1 + 360 t2=t2+0.32*math.cos(hh*3+math.pi/30)
if h1 + h2 >= 360: t2=t2-0.2*math.cos(hh*4-math.pi*63/180)
h_ = (h1 + h2 - 360) / 2 dh=2*math.sqrt(c1*c2)*math.sin(hdiff*0.5)
else: sqhl=(hl-50)*(hl-50)
h_ = (h1 + h2 + 360) / 2 fl=dl/(1+(0.015*sqhl/math.sqrt(20+sqhl)))
fc=dc/(hc*0.045+1)
dL = color2[0] - color1[0] fh=dh/(t2*hc*0.015+1)
dC = C2_prime - C1_prime dt=30*math.exp(-math.pow(36*hh-55*math.pi,2)/(25*math.pi*math.pi))
dH = 2 * math.sqrt(C1_prime * C2_prime) * math.sin(math.radians(dh / 2)) r=-2*trc*math.sin(2*dt*math.pi/180)
T = ( return math.sqrt(fl*fl+fc*fc+fh*fh+r*fc*fh)
1 -
0.17 * math.cos(math.radians(h_ - 30)) +
0.24 * math.cos(math.radians(2 * h_)) +
0.32 * math.cos(math.radians(3 * h_ + 6)) -
0.20 * math.cos(math.radians(4 * h_ - 63))
)
SL = 1 + (0.015 * (L_ - 50) ** 2) / math.sqrt(20 + (L_ - 50) ** 2)
SC = 1 + 0.045 * C_
SH = 1 + 0.015 * C_ * T
RT = (
-2 * math.sqrt(C_ ** 7 / (C_ ** 7 + 25 ** 7)) *
math.sin(math.radians(60 * math.exp(-(((h_ - 275) / 25) ** 2))))
)
delta_e = math.sqrt(
(dL / SL) ** 2 +
(dC / SC) ** 2 +
(dH / SH) ** 2 +
RT * (dC / SC) * (dH / SH)
)
return delta_e
def distance(self, c1, c2, speed): def distance(self, c1, c2, speed):
if speed == 'fast': if speed == 'fast':
@ -619,12 +595,12 @@ class ASCII(callbacks.Plugin):
continue continue
elif int(ansi[i]) > 29 and int(ansi[i]) < 38: elif int(ansi[i]) > 29 and int(ansi[i]) < 38:
if effect == 1 or ansi[-1] == '1': if effect == 1 or ansi[-1] == '1':
x16color2 = self.x16colors['{0};1'.format(ansi[i])] x16color1 = self.x16colors['{0};1'.format(ansi[i])]
effect = None effect = None
i += 1 i += 1
continue continue
else: else:
x16color2 = self.x16colors[ansi[i]] x16color1 = self.x16colors[ansi[i]]
i += 1 i += 1
continue continue
elif int(ansi[i]) > 39 and int(ansi[i]) < 48: elif int(ansi[i]) > 39 and int(ansi[i]) < 48:
@ -690,9 +666,11 @@ class ASCII(callbacks.Plugin):
return '' return ''
def ansi2irc(self, output): def ansi2irc(self, output):
output = output.replace('\x1b[0m\x1b', '\x1b') output = output.replace('\x1b(B\x1b[m', '\x1b[0m')
output = output.replace('\x1b\x1b', '\x1b')
output = re.sub(r'\x1B\[[0-?]*[ -/]*[@-~]', lambda m: self.process_ansi(m.group(0)), output) output = re.sub(r'\x1B\[[0-?]*[ -/]*[@-~]', lambda m: self.process_ansi(m.group(0)), output)
output = re.sub('\x0399,(\d\d)\x03(\d\d)', '\x03\g<2>,\g<1>', output) output = re.sub('\x0399,(\d\d)\x03(\d\d)', '\x03\g<2>,\g<1>', output)
output = output.replace('\x0F\x03', '\x03')
return output return output
def png(self, irc, msg, args, optlist, url): def png(self, irc, msg, args, optlist, url):
@ -718,7 +696,11 @@ class ASCII(callbacks.Plugin):
else: else:
irc.reply("Invalid file type.", private=False, notice=False) irc.reply("Invalid file type.", private=False, notice=False)
return return
try:
file = file.content.decode() file = file.content.decode()
except:
file = file.content.decode('cp437')
file = re.sub('(\x03(\d+).*)\x03,', '\g<1>\x03\g<2>,', file).replace('\r\n','\n')
im, x, y = self.renderImage(file, 18, bg, fg) im, x, y = self.renderImage(file, 18, bg, fg)
path = os.path.dirname(os.path.abspath(__file__)) path = os.path.dirname(os.path.abspath(__file__))
filepath = "{0}/tmp/tldr.png".format(path) filepath = "{0}/tmp/tldr.png".format(path)
@ -795,7 +777,7 @@ class ASCII(callbacks.Plugin):
fontlist = wrap(fontlist) fontlist = wrap(fontlist)
def img(self, irc, msg, args, channel, optlist, url): def img(self, irc, msg, args, channel, optlist, url):
"""[<#channel>] [--delay #.#] [--w <###>] [--s <#.#] [--16] [--99] [--83] [--ascii] [--block] [--1/2] [--1/4] [--chars <text>] [--ramp <text>] [--bg <0-98>] [--fg <0-98>] [--no-color] [--invert] [--dither] [--no-dither] <url> """[<#channel>] [--delay #.#] [--w <###>] [--s <#.#] [--16] [--99] [--83] [--ascii] [--block] [--1/2] [--chars <text>] [--ramp <text>] [--bg <0-98>] [--fg <0-98>] [--no-color] [--invert] <url>
Image to ASCII Art. Image to ASCII Art.
--w columns. --w columns.
--s saturation (1.0). --s saturation (1.0).
@ -804,7 +786,6 @@ class ASCII(callbacks.Plugin):
--83 colors 16-98. --83 colors 16-98.
--ascii color ascii. --ascii color ascii.
--block space block. --block space block.
--1/4 for 1/4 block.
--1/2 for 1/2 block --1/2 for 1/2 block
--chars <TEXT> color text. --chars <TEXT> color text.
--ramp <TEXT> set ramp (".:-=+*#%@"). --ramp <TEXT> set ramp (".:-=+*#%@").
@ -812,11 +793,12 @@ class ASCII(callbacks.Plugin):
--fg <0-99> set fg. --fg <0-99> set fg.
--no-color greyscale ascii. --no-color greyscale ascii.
--invert inverts ramp. --invert inverts ramp.
--dither to reduce source colors.
--no-dither for no color reduction.
""" """
if not channel: if not channel:
channel = msg.args[0] channel = msg.args[0]
if channel != msg.args[0] and not ircdb.checkCapability(msg.prefix, 'admin'):
irc.errorNoCapability('admin')
return
optlist = dict(optlist) optlist = dict(optlist)
gscale = "\xa0" gscale = "\xa0"
if '16' in optlist: if '16' in optlist:
@ -837,20 +819,20 @@ class ASCII(callbacks.Plugin):
delay = optlist.get('delay') delay = optlist.get('delay')
else: else:
delay = self.registryValue('delay', msg.args[0]) delay = self.registryValue('delay', msg.args[0])
if 'dither' in optlist: if 'quantize' in optlist:
dither = True quantize = True
elif 'no-dither' in optlist: elif 'no-quantize' in optlist:
dither = False quantize = False
else: else:
dither = self.registryValue('dither', msg.args[0]) quantize = self.registryValue('quantize', msg.args[0])
if 'bg' in optlist: if 'bg' in optlist:
bg = optlist.get('bg') bg = optlist.get('bg')
else: else:
bg = 1 bg = self.registryValue('bg', msg.args[0])
if 'fg' in optlist: if 'fg' in optlist:
fg = optlist.get('fg') fg = optlist.get('fg')
else: else:
fg = 99 fg = self.registryValue('fg', msg.args[0])
if 'chars' in optlist: if 'chars' in optlist:
type = 'ascii' type = 'ascii'
gscale = optlist.get('chars') gscale = optlist.get('chars')
@ -863,8 +845,6 @@ class ASCII(callbacks.Plugin):
elif 'ascii' in optlist: elif 'ascii' in optlist:
type = 'ascii' type = 'ascii'
gscale = ".'`^\":;Il!i><~+_-?][}{1)(|\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$" gscale = ".'`^\":;Il!i><~+_-?][}{1)(|\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$"
elif '1/4' in optlist:
type = '1/4'
elif '1/2' in optlist: elif '1/2' in optlist:
type = '1/2' type = '1/2'
elif 'block' in optlist: elif 'block' in optlist:
@ -890,8 +870,6 @@ class ASCII(callbacks.Plugin):
cols = self.registryValue('asciiWidth', msg.args[0]) cols = self.registryValue('asciiWidth', msg.args[0])
else: else:
cols = self.registryValue('blockWidth', msg.args[0]) cols = self.registryValue('blockWidth', msg.args[0])
if type == '1/4':
cols = cols * 2
if 's' in optlist: if 's' in optlist:
s = float(optlist.get('s')) s = float(optlist.get('s'))
path = os.path.dirname(os.path.abspath(__file__)) path = os.path.dirname(os.path.abspath(__file__))
@ -912,7 +890,11 @@ class ASCII(callbacks.Plugin):
# open image and convert to grayscale # open image and convert to grayscale
image = Image.open(filename) image = Image.open(filename)
if image.mode == 'RGBA': if image.mode == 'RGBA':
image = Image.alpha_composite(Image.new("RGBA", image.size, self.rgbColors[bg] + (255,)), image) if bg == 99:
newbg = 1
else:
newbg = bg
image = Image.alpha_composite(Image.new("RGBA", image.size, self.rgbColors[newbg] + (255,)), image)
if image.mode != 'RGB': if image.mode != 'RGB':
image = image.convert('RGB') image = image.convert('RGB')
try: try:
@ -931,16 +913,20 @@ class ASCII(callbacks.Plugin):
h = w/scale h = w/scale
# compute number of rows # compute number of rows
rows = int(H/h) rows = int(H/h)
image = ImageOps.autocontrast(image) if 'resize' in optlist:
resize = optlist.get('resize')
else:
resize = self.registryValue('resize', msg.args[0])
if type != 'no-color': if type != 'no-color':
image2 = image.resize((cols, rows), Image.LANCZOS) image2 = image.resize((cols, rows), resize)
if 's' in optlist: if 's' in optlist:
image2 = ImageEnhance.Color(image2).enhance(s) image2 = ImageEnhance.Color(image2).enhance(s)
if dither: if quantize:
image2 = image2.convert('P', palette=Image.ADAPTIVE) image2 = image2.quantize(dither=None)
image2 = image2.convert('RGB') image2 = image2.convert('RGB')
colormap = np.array(image2) colormap = np.array(image2)
self.matches = {} self.matches = {}
self.labmatches = {}
# ascii image is a list of character strings # ascii image is a list of character strings
aimg = [] aimg = []
if type == '1/2': if type == '1/2':
@ -948,154 +934,111 @@ class ASCII(callbacks.Plugin):
for j in range(0, rows - 1, 2): for j in range(0, rows - 1, 2):
# append an empty string # append an empty string
aimg.append("") aimg.append("")
old_color = "99,99" old_color1 = "99"
old_color2 = "99"
old_char = None
for i in range(cols): for i in range(cols):
color1 = '%02d' % self.getColor(colormap[j][i].tolist(), speed) color1 = '%02d' % self.getColor(colormap[j][i].tolist(), speed)
color2 = '%02d' % self.getColor(colormap[j+1][i].tolist(), speed) color2 = '%02d' % self.getColor(colormap[j+1][i].tolist(), speed)
color = "{0},{1}".format(color1, color2)
if color != old_color:
if color1 == color2: if color1 == color2:
gsval = " " gsval = " "
color = "0,{0}".format(color1)
else: else:
gsval = "" gsval = ""
alt_gsval = "" if color1 == old_color1 and color2 == old_color2:
if gsval != " " and color == "{0},{1}".format(old_color.split(',')[1], old_color.split(',')[0]) and 'tops' not in optlist: aimg[k] += gsval
aimg[k] += alt_gsval old_char = gsval
elif gsval == " " and "{0}".format(color1) == "{0}".format(old_color.split(',')[1]): elif gsval == " " and color1 == old_color2:
aimg[k] += " " aimg[k] += " "
old_char = gsval
elif gsval == " " and color1 == old_color1 and old_char == '':
aimg[k] = aimg[k][:-1]
aimg[k] += "\x0301,{0} ".format(color1)
old_color1 = "01"
old_color2 = color1
old_char = gsval
elif gsval == " " and color1 == old_color1 and old_char == '^█':
aimg[k] = aimg[k][:-4]
aimg[k] += "\x0301,{0} ".format(color1)
old_color1 = "01"
old_color2 = color1
old_char = gsval
elif gsval == " " and color1 == old_color1 and old_char == "^^▀" and 'tops' not in optlist:
aimg[k] = aimg[k][:-7]
aimg[k] += "\x03{0},{1}".format(old_color2, color1)
old_color1 = old_color2
old_color2 = color1
old_char = gsval
elif gsval == " " and color1 == old_color1 and old_char != '' and 'tops' not in optlist:
aimg[k] += ""
old_char = ''
elif gsval == " " and 'tops' not in optlist:
aimg[k] += "\x03{0}".format(color1)
old_color1 = color1
old_char = '^█'
elif gsval != " " and color1 == old_color1 and old_char == '^█' and 'tops' not in optlist:
aimg[k] = aimg[k][:-4]
aimg[k] += "\x03{0},{1}".format(color2, color1)
old_color1 = color2
old_color2 = color1
old_char = ''
elif gsval != " " and color2 == old_color1 and old_char == '^█':
aimg[k] = aimg[k][:-4]
aimg[k] += "\x03{0},{1}".format(color1, color2)
old_color1 = color1
old_color2 = color2
old_char = gsval
elif gsval != " " and color1 == old_color2 and color2 == old_color1 and old_char == "^^▀" and 'tops' not in optlist:
aimg[k] = aimg[k][:-7]
aimg[k] += "\x03{0},{1}▄▀".format(color1, color2)
old_color1 = color1
old_color2 = color2
old_char = gsval
elif gsval != " " and color1 == old_color1 and color2 != old_color2 and old_char == "^^▀" and 'tops' not in optlist:
aimg[k] = aimg[k][:-7]
aimg[k] += "\x03{0},{1}\x03{2}".format(old_color2, color1, color2)
old_color1 = color2
old_color2 = color1
old_char = ''
elif gsval != " " and color1 == old_color1 and color2 != old_color2 and old_char == "^▀" and 'tops' not in optlist:
aimg[k] = aimg[k][:-4]
aimg[k] += "\x03{0},{1}\x03{2}".format(old_color2, color1, color2)
old_color1 = color2
old_color2 = color1
old_char = ''
elif gsval != " " and color1 == old_color2 and color2 == old_color1 and 'tops' not in optlist:
aimg[k] += ""
old_char = ''
elif gsval != " " and color1 == old_color2 and 'tops' not in optlist:
aimg[k] += "\x03{0}".format(color2)
old_color1 = color2
old_char = ''
elif color1 != old_color1 and color2 == old_color2:
aimg[k] += "\x03{0}{1}".format(color1, gsval)
old_color1 = color1
if gsval == ' ':
old_char = gsval
else: else:
aimg[k] += "\x03{0}{1}".format(color, gsval) old_char = '^▀'
old_color = color
else: else:
if color1 == color2: aimg[k] += "\x03{0},{1}{2}".format(color1, color2, gsval)
aimg[k] += " " old_color1 = color1
old_color2 = color2
if gsval == ' ':
old_char = gsval
else: else:
aimg[k] += "" old_char = '^^▀'
for i in range(0,98): if 'tops' in optlist:
i = '%02d' % i aimg[k] = re.sub("\x03\d\d,(\d\d\s+\x03)", "\x0301,\g<1>", aimg[k])
aimg[k] = re.sub("\x030,{0}(\s+)\x03(\d\d),{0}".format(i), "\x03\g<2>,{0}\g<1>".format(i), aimg[k]) aimg[k] = re.sub("\x03\d\d,(\d\d\s+$)", "\x0301,\g<1>", aimg[k])
for i in range(0,98): aimg[k] = re.sub("\x03\d\d,(\d\d\s\x03)", "\x0301,\g<1>", aimg[k])
i = '%02d' % i aimg[k] = re.sub("\x0301,(\d\d)(\s+)\x03(\d\d)([^,])", "\x03\g<3>,\g<1>\g<2>\g<4>", aimg[k])
aimg[k] = aimg[k].replace("{0}".format(i), "{0}".format(int(i)))
k += 1
elif type == '1/4':
k = 0
for j in range(0, rows - 1, 2):
# append an empty string
aimg.append("")
old_color = "99,99"
for i in range(0, cols - 1, 2):
color1 = '%02d' % self.getColor(colormap[j][i].tolist(), speed)
color2 = '%02d' % self.getColor(colormap[j+1][i].tolist(), speed)
color3 = '%02d' % self.getColor(colormap[j][i+1].tolist(), speed)
color4 = '%02d' % self.getColor(colormap[j+1][i+1].tolist(), speed)
if color1 == color2 and color1 == color3 and color1 == color4:
gsval = " "
color = "0,{0}".format(color1)
elif color1 == color4 and color2 == color3:
gsval = ""
color = "{0},{1}".format(color1, color2)
elif color1 == color2 and color1 == color3 and color1 != color4:
gsval = ""
color = "{0},{1}".format(color1, color4)
elif color3 == color4 and color2 == color4 and color3 != color1:
gsval = ""
color = "{0},{1}".format(color2, color1)
elif color1 == color2 and color1 == color4 and color1 != color3:
gsval = ""
color = "{0},{1}".format(color1, color3)
elif color1 == color3 and color1 == color4 and color1 != color2:
gsval = ""
color = "{0},{1}".format(color1, color2)
elif color1 == color3 and color2 == color4 and color1 != color2 and color3 != color4:
gsval = ""
color = "{0},{1}".format(color1, color4)
elif color1 == color2 and color3 == color4 and color1 != color3 and color2 != color4:
gsval = ""
color = "{0},{1}".format(color1, color4)
else:
row1 = '%02d' % self.getColor(np.average([tuple(colormap[j][i].tolist()), tuple(colormap[j][i+1].tolist())], axis=0).tolist(), speed)
row2 = '%02d' % self.getColor(np.average([tuple(colormap[j+1][i+1].tolist()), tuple(colormap[j][i+1].tolist())], axis=0).tolist(), speed)
if row2 == color1 and row2 != color3:
gsval = ""
color = "{0},{1}".format(row2, color3)
elif row1 == color2 and row1 != color4:
gsval = ""
color = "{0},{1}".format(row1, color4)
elif row2 == color3 and row2 != color1:
gsval = ""
color = "{0},{1}".format(row2, color1)
elif row1 == color4 and row1 != color2:
gsval = ""
color = "{0},{1}".format(row1, color2)
else:
col1 = '%02d' % self.getColor(np.average([tuple(colormap[j][i].tolist()), tuple(colormap[j+1][i].tolist())], axis=0).tolist(), speed)
col2 = '%02d' % self.getColor(np.average([tuple(colormap[j][i+1].tolist()), tuple(colormap[j+1][i+1].tolist())], axis=0).tolist(), speed)
if col1 == color4 and col1 != color3:
gsval = ""
color = "{0},{1}".format(col1, color3)
elif col1 == color3 and col1 != color4:
gsval = ""
color = "{0},{1}".format(col1, color4)
elif col2 == color2 and col2 != color1:
gsval = ""
color = "{0},{1}".format(col2, color1)
elif col2 == color1 and col2 != color2:
gsval = ""
color = "{0},{1}".format(col2, color2)
elif row1 != row2:
gsval = ""
color = "{0},{1}".format(row1, row2)
elif col1 != col2:
gsval = ""
color = "{0},{1}".format(col1, col2)
elif row1 == row2:
gsval = " "
color = "0,{0}".format(row1)
elif col1 == col2:
gsval = " "
color = "0,{0}".format(col1)
if color != old_color:
if gsval == " " and "{0}".format(color.split(',')[1]) == "{0}".format(old_color.split(',')[1]):
aimg[k] += "{0}".format(gsval)
elif gsval == "" and color == "{0},{1}".format(old_color.split(',')[1], old_color.split(',')[0]):
gsval = ""
aimg[k] += "{0}".format(gsval)
elif gsval == "" and color == "{0},{1}".format(old_color.split(',')[1], old_color.split(',')[0]):
gsval = ""
aimg[k] += "{0}".format(gsval)
elif gsval == "" and color == "{0},{1}".format(old_color.split(',')[1], old_color.split(',')[0]):
gsval = ""
aimg[k] += "{0}".format(gsval)
elif gsval == "" and color == "{0},{1}".format(old_color.split(',')[1], old_color.split(',')[0]):
gsval = ""
aimg[k] += "{0}".format(gsval)
elif gsval == "" and color == "{0},{1}".format(old_color.split(',')[1], old_color.split(',')[0]):
gsval = ""
aimg[k] += "{0}".format(gsval)
elif gsval == "" and color == "{0},{1}".format(old_color.split(',')[1], old_color.split(',')[0]):
gsval = ""
aimg[k] += "{0}".format(gsval)
elif gsval == "" and color == "{0},{1}".format(old_color.split(',')[1], old_color.split(',')[0]):
gsval = ""
aimg[k] += "{0}".format(gsval)
else:
old_color = color
# append char to string
aimg[k] += "\x03{0}{1}".format(color, gsval)
else:
aimg[k] += "{0}".format(gsval)
for i in range(0,98):
i = '%02d' % i
aimg[k] = re.sub("\x030,{0}(\s+)\x03(\d\d),{0}".format(i), "\x03\g<2>,{0}\g<1>".format(i), aimg[k])
for i in range(0,98): for i in range(0,98):
i = '%02d' % i i = '%02d' % i
aimg[k] = aimg[k].replace("{0}".format(i), "{0}".format(int(i))) aimg[k] = aimg[k].replace("{0}".format(i), "{0}".format(int(i)))
k += 1 k += 1
else: else:
if 'chars' not in optlist and gscale != '\xa0': if 'chars' not in optlist and gscale != '\xa0':
image = image.resize((cols, rows), Image.LANCZOS) image = image.resize((cols, rows), resize)
image = image.convert('L') image = image.convert('L')
lumamap = np.array(image) lumamap = np.array(image)
# generate list of dimensions # generate list of dimensions
@ -1121,33 +1064,27 @@ class ASCII(callbacks.Plugin):
else: else:
gsval = '\xa0' gsval = '\xa0'
# get color value # get color value
if type != 'no-color' and i == 0: if type != 'no-color' and gscale != '\xa0' and i == 0:
color = self.getColor(colormap[j][i].tolist(), speed) color = self.getColor(colormap[j][i].tolist(), speed)
old_color = color old_color = color
if 'bg' not in optlist: if bg != 99:
color = "{0},{1}".format(color, "{:02d}".format(int(bg)))
if gsval != '\xa0': if gsval != '\xa0':
if gsval.isdigit():
color = "{:02d}".format(int(color))
aimg[j] += "\x03{0}{1}".format(color, gsval) aimg[j] += "\x03{0}{1}".format(color, gsval)
else:
aimg[j] += "\x03{0}{1}".format(int(color), gsval)
else:
aimg[j] += "\x030,{0} ".format(int(color))
else:
if gsval != '\xa0':
if gsval.isdigit():
newbg = "{:02d}".format(int(bg))
aimg[j] += "\x03{0},{1}{2}".format(int(color), newbg, gsval)
else:
aimg[j] += "\x03{0},{1}{2}".format(int(color), int(bg), gsval)
else: else:
aimg[j] += "\x030,{0} ".format(int(color)) aimg[j] += "\x030,{0} ".format(int(color))
elif type == 'no-color' and i == 0:
if bg != 99 and fg != 99:
aimg[j] += "\x03{0},{1}{2}".format("{:02d}".format(int(fg)), "{:02d}".format(int(bg)), gsval)
elif fg != 99:
aimg[j] += "\x03{0}{1}".format("{:02d}".format(int(fg)), gsval)
elif bg != 99:
aimg[j] += "\x03{0},{1}{2}".format("{:02d}".format(int(fg)), "{:02d}".format(int(bg)), gsval)
elif type != 'no-color' and gsval != ' ': elif type != 'no-color' and gsval != ' ':
color = self.getColor(colormap[j][i].tolist(), speed) color = self.getColor(colormap[j][i].tolist(), speed)
if color != old_color: if color != old_color:
old_color = color old_color = color
# append ascii char to string # append ascii char to string
if 'bg' not in optlist:
if gsval != '\xa0': if gsval != '\xa0':
if gsval.isdigit(): if gsval.isdigit():
color = "{:02d}".format(int(color)) color = "{:02d}".format(int(color))
@ -1156,33 +1093,14 @@ class ASCII(callbacks.Plugin):
aimg[j] += "\x03{0}{1}".format(int(color), gsval) aimg[j] += "\x03{0}{1}".format(int(color), gsval)
else: else:
aimg[j] += "\x030,{0} ".format(int(color)) aimg[j] += "\x030,{0} ".format(int(color))
else:
if gsval != '\xa0':
if gsval.isdigit():
newbg = "{:02d}".format(int(bg))
aimg[j] += "\x03{0},{1}{2}".format(int(color), newbg, gsval)
else:
aimg[j] += "\x03{0},{1}{2}".format(int(color), int(bg), gsval)
else:
aimg[j] += "\x030,{0} ".format(int(color))
else: else:
aimg[j] += "{0}".format(gsval) aimg[j] += "{0}".format(gsval)
else: else:
aimg[j] += "{0}".format(gsval) aimg[j] += "{0}".format(gsval)
# return txt image
output = aimg output = aimg
paste = "" paste = ""
self.stopped[msg.args[0]] = False self.stopped[msg.args[0]] = False
for line in output: for line in output:
if type == 'no-color' and 'fg' in optlist and 'bg' in optlist:
newbg = "{:02d}".format(int(bg))
line = "\x03{0},{1}{2}".format(int(fg), newbg, line)
elif type == 'no-color' and 'fg' in optlist:
newfg = "{:02d}".format(int(fg))
line = "\x03{0}{1}".format(newfg, line)
elif type == 'no-color' and 'bg' in optlist:
newbg = "{:02d}".format(int(bg))
line = "\x0399,{0}{1}".format(newbg, line)
if self.registryValue('pasteEnable', msg.args[0]): if self.registryValue('pasteEnable', msg.args[0]):
paste += line + "\n" paste += line + "\n"
if not self.stopped[msg.args[0]]: if not self.stopped[msg.args[0]]:
@ -1190,7 +1108,7 @@ class ASCII(callbacks.Plugin):
irc.reply(line, prefixNick=False, noLengthCheck=True, private=False, notice=False, to=channel) irc.reply(line, prefixNick=False, noLengthCheck=True, private=False, notice=False, to=channel)
if self.registryValue('pasteEnable', msg.args[0]): if self.registryValue('pasteEnable', msg.args[0]):
irc.reply(self.doPaste(url, paste), private=False, notice=False, to=channel) irc.reply(self.doPaste(url, paste), private=False, notice=False, to=channel)
img = wrap(img,[optional('channel'), getopts({'w':'int', 'invert':'', 'fast':'', 'slow':'', '16':'', '99':'', '83':'', 'delay':'float', 'dither':'', 'no-dither':'', 'chars':'text', 'bg':'int', 'fg':'int', 'ramp':'text', 'no-color':'', 'block':'', 'ascii':'', '1/4':'', '1/2':'', 's':'float', 'tops':''}), ('text')]) img = wrap(img,[optional('channel'), getopts({'w':'int', 'invert':'', 'fast':'', 'slow':'', '16':'', '99':'', '83':'', 'delay':'float', 'resize':'int', 'quantize':'', 'no-quantize':'', 'chars':'text', 'bg':'int', 'fg':'int', 'ramp':'text', 'no-color':'', 'block':'', 'ascii':'', '1/2':'', 's':'float', 'tops':''}), ('text')])
def scroll(self, irc, msg, args, channel, optlist, url): def scroll(self, irc, msg, args, channel, optlist, url):
"""[<channel>] [--delay] <url> """[<channel>] [--delay] <url>
@ -1198,6 +1116,9 @@ class ASCII(callbacks.Plugin):
""" """
if not channel: if not channel:
channel = msg.args[0] channel = msg.args[0]
if channel != msg.args[0] and not ircdb.checkCapability(msg.prefix, 'admin'):
irc.errorNoCapability('admin')
return
optlist = dict(optlist) optlist = dict(optlist)
self.stopped[msg.args[0]] = False self.stopped[msg.args[0]] = False
if 'delay' in optlist: if 'delay' in optlist:
@ -1214,8 +1135,8 @@ class ASCII(callbacks.Plugin):
else: else:
irc.reply("Invalid file type.", private=False, notice=False) irc.reply("Invalid file type.", private=False, notice=False)
return return
file = file.content.decode() file = file.content.decode().replace('\r\n','\n')
for line in file.splitlines(): for line in file.split('\n'):
if line.strip() and not self.stopped[msg.args[0]]: if line.strip() and not self.stopped[msg.args[0]]:
time.sleep(delay) time.sleep(delay)
irc.reply(line, prefixNick = False, noLengthCheck=True, private=False, notice=False, to=channel) irc.reply(line, prefixNick = False, noLengthCheck=True, private=False, notice=False, to=channel)
@ -1227,6 +1148,9 @@ class ASCII(callbacks.Plugin):
""" """
if not channel: if not channel:
channel = msg.args[0] channel = msg.args[0]
if channel != msg.args[0] and not ircdb.checkCapability(msg.prefix, 'admin'):
irc.errorNoCapability('admin')
return
optlist = dict(optlist) optlist = dict(optlist)
opts = '' opts = ''
if 'l' in optlist: if 'l' in optlist:
@ -1238,7 +1162,7 @@ class ASCII(callbacks.Plugin):
if 'n' in optlist: if 'n' in optlist:
opts += '-n '.format(n) opts += '-n '.format(n)
if 'p' in optlist: if 'p' in optlist:
opts += '-p '.format(p) opts += '-p '
if 't' in optlist: if 't' in optlist:
t = optlist.get('t') t = optlist.get('t')
opts += '-t {0} '.format(t) opts += '-t {0} '.format(t)
@ -1260,7 +1184,7 @@ class ASCII(callbacks.Plugin):
filepath = "{0}/tmp".format(path) filepath = "{0}/tmp".format(path)
filename = "{0}/{1}".format(filepath, url.split('/')[-1]) filename = "{0}/{1}".format(filepath, url.split('/')[-1])
r = requests.get(url, headers=header) r = requests.get(url, headers=header)
open(filename, 'wb').write(r.content) open(filename, 'wb').write(r.content.replace(b';5;', b';'))
try: try:
output = pexpect.run('a2m {0} {1}'.format(opts.strip(), str(filename))) output = pexpect.run('a2m {0} {1}'.format(opts.strip(), str(filename)))
try: try:
@ -1278,16 +1202,21 @@ class ASCII(callbacks.Plugin):
return return
paste = "" paste = ""
self.stopped[msg.args[0]] = False self.stopped[msg.args[0]] = False
output = re.sub('(\x03(\d+).*)\x03,', '\g<1>\x03\g<2>,', output.decode())
for line in output.splitlines(): for line in output.splitlines():
line = line.decode()
if self.registryValue('pasteEnable', msg.args[0]): if self.registryValue('pasteEnable', msg.args[0]):
paste += line + "\n" paste += line + "\n"
if line.strip() and not self.stopped[msg.args[0]]: if line.strip() and not self.stopped[msg.args[0]]:
time.sleep(delay) time.sleep(delay)
irc.reply(line, prefixNick = False, noLengthCheck=True, private=False, notice=False, to=channel) irc.reply(line, prefixNick = False, noLengthCheck=True, private=False, notice=False, to=channel)
elif not line.strip() and not self.stopped[msg.args[0]]:
time.sleep(delay)
irc.reply('\xa0', prefixNick = False, noLengthCheck=True, private=False, notice=False, to=channel)
else:
return
if self.registryValue('pasteEnable', msg.args[0]): if self.registryValue('pasteEnable', msg.args[0]):
irc.reply(self.doPaste(url, paste), private=False, notice=False, to=channel) irc.reply(self.doPaste(url, paste), private=False, notice=False, to=channel)
a2m = wrap(a2m, [optional('channel'), getopts({'l':'int', 'r':'int', 't':'int', 'w':'int', 'delay':'float'}), ('text')]) a2m = wrap(a2m, [optional('channel'), getopts({'l':'int', 'r':'int', 't':'int', 'w':'int', 'p':'', 'delay':'float'}), ('text')])
def p2u(self, irc, msg, args, channel, optlist, url): def p2u(self, irc, msg, args, channel, optlist, url):
"""[<channel>] [--b] [--f] [--p] [--s] [--t] [--w] [--delay] <url> """[<channel>] [--b] [--f] [--p] [--s] [--t] [--w] [--delay] <url>
@ -1295,6 +1224,9 @@ class ASCII(callbacks.Plugin):
""" """
if not channel: if not channel:
channel = msg.args[0] channel = msg.args[0]
if channel != msg.args[0] and not ircdb.checkCapability(msg.prefix, 'admin'):
irc.errorNoCapability('admin')
return
optlist = dict(optlist) optlist = dict(optlist)
opts = '' opts = ''
if 'b' in optlist: if 'b' in optlist:
@ -1378,6 +1310,9 @@ class ASCII(callbacks.Plugin):
""" """
if not channel: if not channel:
channel = msg.args[0] channel = msg.args[0]
if channel != msg.args[0] and not ircdb.checkCapability(msg.prefix, 'admin'):
irc.errorNoCapability('admin')
return
optlist = dict(optlist) optlist = dict(optlist)
opts = '' opts = ''
if 'f' in optlist: if 'f' in optlist:
@ -1433,6 +1368,9 @@ class ASCII(callbacks.Plugin):
""" """
if not channel: if not channel:
channel = msg.args[0] channel = msg.args[0]
if channel != msg.args[0] and not ircdb.checkCapability(msg.prefix, 'admin'):
irc.errorNoCapability('admin')
return
optlist = dict(optlist) optlist = dict(optlist)
opts = '' opts = ''
if 'f' in optlist: if 'f' in optlist:
@ -1521,6 +1459,9 @@ class ASCII(callbacks.Plugin):
""" """
if not channel: if not channel:
channel = msg.args[0] channel = msg.args[0]
if channel != msg.args[0] and not ircdb.checkCapability(msg.prefix, 'admin'):
irc.errorNoCapability('admin')
return
optlist = dict(optlist) optlist = dict(optlist)
if 'delay' in optlist: if 'delay' in optlist:
delay = optlist.get('delay') delay = optlist.get('delay')
@ -1540,7 +1481,6 @@ class ASCII(callbacks.Plugin):
speed = 'fast' speed = 'fast'
file = requests.get("http://wttr.in/{0}".format(location)) file = requests.get("http://wttr.in/{0}".format(location))
output = file.content.decode() output = file.content.decode()
self.matches = {}
output = self.ansi2irc(output) output = self.ansi2irc(output)
output = re.sub('', '', output) output = re.sub('', '', output)
output = re.sub('', ' ', output) output = re.sub('', ' ', output)
@ -1571,6 +1511,9 @@ class ASCII(callbacks.Plugin):
""" """
if not channel: if not channel:
channel = msg.args[0] channel = msg.args[0]
if channel != msg.args[0] and not ircdb.checkCapability(msg.prefix, 'admin'):
irc.errorNoCapability('admin')
return
optlist = dict(optlist) optlist = dict(optlist)
if 'delay' in optlist: if 'delay' in optlist:
delay = optlist.get('delay') delay = optlist.get('delay')
@ -1594,7 +1537,6 @@ class ASCII(callbacks.Plugin):
sub = 'usd' sub = 'usd'
if not coin: if not coin:
coin = '' coin = ''
self.matches= {}
file = requests.get("http://{0}.rate.sx/{1}".format(sub, coin)) file = requests.get("http://{0}.rate.sx/{1}".format(sub, coin))
output = file.content.decode() output = file.content.decode()
output = self.ansi2irc(output) output = self.ansi2irc(output)
@ -1623,6 +1565,9 @@ class ASCII(callbacks.Plugin):
""" """
if not channel: if not channel:
channel = msg.args[0] channel = msg.args[0]
if channel != msg.args[0] and not ircdb.checkCapability(msg.prefix, 'admin'):
irc.errorNoCapability('admin')
return
optlist = dict(optlist) optlist = dict(optlist)
if 'delay' in optlist: if 'delay' in optlist:
delay = optlist.get('delay') delay = optlist.get('delay')
@ -1654,6 +1599,9 @@ class ASCII(callbacks.Plugin):
""" """
if not channel: if not channel:
channel = msg.args[0] channel = msg.args[0]
if channel != msg.args[0] and not ircdb.checkCapability(msg.prefix, 'admin'):
irc.errorNoCapability('admin')
return
optlist = dict(optlist) optlist = dict(optlist)
if 'delay' in optlist: if 'delay' in optlist:
delay = optlist.get('delay') delay = optlist.get('delay')
@ -1678,6 +1626,9 @@ class ASCII(callbacks.Plugin):
""" """
if not channel: if not channel:
channel = msg.args[0] channel = msg.args[0]
if channel != msg.args[0] and not ircdb.checkCapability(msg.prefix, 'admin'):
irc.errorNoCapability('admin')
return
optlist = dict(optlist) optlist = dict(optlist)
if 'delay' in optlist: if 'delay' in optlist:
delay = optlist.get('delay') delay = optlist.get('delay')