take Arch's dicebot pinhook example and extrapolate out to log.py (proto for comics scripts) and munger.py (ported from cloudbot)

This commit is contained in:
Joel Kirchartz 2019-02-13 17:57:48 +00:00
commit d156ecefee
5 changed files with 479 additions and 0 deletions

101
.gitignore vendored Normal file
View File

@ -0,0 +1,101 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# dotenv
.env
# virtualenv
.venv
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/

11
pinhook.py Executable file
View File

@ -0,0 +1,11 @@
#!/usr/bin/env python
from pinhook.bot import Bot
ph = Bot(
channels=['#fnord'],
nickname='DocVuDu',
server='irc.maddshark.net',
ops=['derkirche']
)
ph.start()

29
plugins/dice.py Normal file
View File

@ -0,0 +1,29 @@
import random
import re
import pinhook.plugin
dicepattern = re.compile('(?P<amount>\d+)d(?P<sides>\d+)\+?(?P<modifier>\d+)?')
def build_output(rolls, modifier):
if len(rolls) == 1:
start = str(sum(rolls))
else:
all_rolls = ''.join([str(i)+', ' for i in rolls]).strip(', ')
start = '{} = {}'.format(all_rolls, sum(rolls))
if modifier:
output = start + ' + {} = {}'.format(modifier, sum(rolls) + int(modifier))
else:
output = start
return output
@pinhook.plugin.register('!roll')
def roll(msg):
matches = dicepattern.match(msg.arg)
if matches:
msg.logger.info('Valid dice roll: {}'.format(msg.arg))
rolls = [random.randrange(1, int(matches.group('sides'))+1) for i in range(int(matches.group('amount')))]
output = build_output(rolls, matches.group('modifier'))
else:
output = '{}: improper format, should be NdN+N'.format(msg.nick)
return pinhook.plugin.message(output)

40
plugins/log.py Normal file
View File

@ -0,0 +1,40 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
import pinhook.plugin
output =[]
keeplines = 10
characters = [];
def char(nick):
global characters
for char in characters:
if char.nick == nick:
break
else:
characters.push(dict(nick=nick, img=randomCharacter()))
@pinhook.plugin.listener('ears')
def ears(msg):
global output
global keeplines
output.append(dict(nick=msg.nick, text=msg.text))
# only keep last X lines
if len(output) >= keeplines:
output.pop(0)
@pinhook.plugin.register('!log', 'check ' + str(keeplines) + ' lines of backlog')
def log(msg):
global output
comic = list()
for line in output:
comic.push(dict(
nick=line.nick,
text=line.text,
char=char(line.nick)
))
return pinhook.plugin.message(' | '.join(output))

298
plugins/munger.py Normal file
View File

@ -0,0 +1,298 @@
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2018 jkirchartz <me@jkirchartz.com>
#
# Distributed under terms of the NPL (Necessary Public License) license.
import pinhook.plugin
from datetime import datetime
import json
import random
import re
mcache = dict()
buffer_size = 1
# spongemock.py
# author: Noah Krim
# email: nkrim62@gmail.com
def mock(text, diversity_bias=0.5, random_seed=None):
# Error handling
if diversity_bias < 0 or diversity_bias > 1:
raise ValueError('diversity_bias must be between the inclusive range [0,1]')
# Seed the random number generator
random.seed(random_seed)
# Mock the text
out = ''
last_was_upper = True
swap_chance = 0.5
for c in text:
if c.isalpha():
if random.random() < swap_chance:
last_was_upper = not last_was_upper
swap_chance = 0.5
c = c.upper() if last_was_upper else c.lower()
swap_chance += (1-swap_chance)*diversity_bias
out += c
return out
# end spongemock
def vaporwave(text):
output = ""
for c in list(text):
a = ord(c)
if a >= 33 and a <= 126:
output += chr( (a - 33) + 65281 )
else:
output += c
return output
unicode_offsets = {
"cursive": {"upper": 119951, "lower": 119945},
"circle": {"upper": 9333, "lower": 9327}
}
def unicode_offset(text, fun):
output = ""
for c in list(text):
a = ord(c)
if a > 64 and a < 91:
output += chr( a + unicode_offsets[fun]["upper"] )
elif a > 96 and a < 123:
output += chr( a + unicode_offsets[fun]["lower"] )
else:
output += c
return output
json_mungers = {}
json_mungers['russian'] = {
"A": ["Д"],
"B": ["Б", "Ъ", "Ь"],
"C": ["Ҫ"],
"E": ["Ԑ", "Є", "Э"],
"F": ["Ӻ", "Ғ"],
"H": ["Њ", "Ҥ", "Ӊ", "Ң"],
"I": ["Ї"],
"K": ["Қ", "Ҡ", "Ҝ", "Ԟ"],
"M": ["Ԡ"],
"N": ["И", "Ѝ", "Й"],
"O": ["Ф"],
"R": ["Я"],
"T": ["Г", "Ґ", "Ҭ"],
"U": ["Ц","Џ"],
"W": ["Ш", "Щ"],
"X": ["Ӿ", "Ҳ", "Ӽ", "Ж"],
"Y": ["Ч", "Ұ"]
}
json_mungers['tiny'] = {
"a":"",
"b":"",
"c":"",
"d":"",
"e":"",
"f":"",
"g":"",
"h":"ʰ",
"i":"",
"j":"ʲ",
"k":"",
"l":"",
"m":"",
"n":"",
"o":"",
"p":"",
"q":"",
"r":"ʳ",
"s":"ˢ",
"t":"",
"u":"",
"v":"",
"w":"ʷ",
"x":"ˣ",
"y":"ʸ",
"z":"",
"A":"",
"B":"",
"C":"",
"D":"",
"E":"",
"F":"",
"G":"",
"H":"",
"I":"",
"J":"",
"K":"",
"L":"",
"M":"",
"N":"",
"O":"",
"P":"",
"Q":"",
"R":"ᴿ",
"S":"ˢ",
"T":"",
"U":"",
"V":"",
"W":"",
"X":"ˣ",
"Y":"ʸ",
"Z":"",
"`":"`",
"~":"~",
"!":"",
"@":"@",
"#":"#",
"$":"",
"%":"",
"^":"^",
"&":"",
"*":"",
"(":"",
")":"",
"_":"",
"-":"",
"=":"",
"+":"+",
"{":"{",
"[":"[",
"}":"}",
"]":"]",
":":"",
";":"",
"?":"",
}
json_mungers['upsidedown'] = {
'A':'',
'B':'𐐒',
'C':'Ɔ',
'E':'Ǝ',
'F':'',
'G':'פ',
'H':'H',
'I':'I',
'J':'ſ',
'L':'˥',
'M':'W',
'N':'N',
'P':'Ԁ',
'R':'',
'T':'',
'U':'',
'V':'Λ',
'Y':'',
'a':'ɐ',
'b':'q',
'c':'ɔ',
'd':'p',
'e':'ǝ',
'f':'ɟ',
'g':'ƃ',
'h':'ɥ',
'i':'',
'j':'ɾ',
'k':'ʞ',
'm':'ɯ',
'n':'u',
'p':'d',
'q':'b',
'r':'ɹ',
't':'ʇ',
'u':'n',
'v':'ʌ',
'w':'ʍ',
'1':'Ɩ',
'2':'',
'3':'Ɛ',
'4':'',
'5':'ϛ',
'6':'9',
'7':'',
'8':'8',
'9':'6',
'0':'0',
'.':'˙',
',':'\'',
'\'':',',
'"':',,',
'`':',',
'<':'>',
'>':'<',
'':'',
'&':'',
'_':'',
'?':'¿',
'!':'¡',
'[':']',
']':'[',
'(':')',
')':'(',
'{':'}',
'}':'{'
}
def munger(text, json_type='russian'):
output = ""
json_munger = json_mungers[json_type]
if json_type == 'russian':
text = text.upper()
for c in text:
if c in json_munger:
output += random.choice(json_munger[c])
else:
output += c
return output
def munge(text, function='mock'):
fun = function.lower()
if fun == 'flip':
fun = 'upsidedown'
text = text[::-1]
if fun == 'aesthetic' or fun == 'vaporwave':
return vaporwave(text)
elif fun == 'ubbi':
return re.sub(r"[aeiou]+", r"ub$0");
elif fun == 'mock':
return mock(text)
if fun == 'circled':
return unicode_offset(text, "circle");
elif fun in unicode_offsets:
return unicode_offset(text, fun)
elif fun in json_mungers:
return munger(text, fun)
else:
return " ".join(["no munger named", fun])
@pinhook.plugin.listener('track')
def track(msg):
if not str(msg.text).startswith(('!', '.', ';', ':')):
key = (msg.channel, msg.nick)
mcache[key] = str(msg.text)
@pinhook.plugin.register("!m", "!munge <format> -- munges previous line, or provided text")
@pinhook.plugin.register("!munge", "!munge <format> -- munges previous line, or provided text")
def munge_command(msg):
"""!m(unge) ubbi, circle, flip, vaporwave, mock, russian; works on either the last line of text in the channel, or any text placed after the munge style"""
output = ""
text = msg.arg
if len(text.split()) >= 2:
text = text.split()
output = munge(" ".join(text[1:]), text[0])
else:
try:
if len(text):
output = munge(mcache[(msg.channel, msg.nick)], text)
else:
output = munge(mcache[(msg.channel, msg.nick)])
except KeyError:
output = "Not Enough Messages."
return pinhook.plugin.message(output)