forked from zgrep/happybot
The happybot revolves around the Earth.
The Earth revolves around the God. The God gives you a world full of viral diseases. You curse God. You revolve around God. God revolves around a door. The door opens. This is going nowhere, you can stop reading now. I said you could stop. Okay, that's it, I'm really ending it now.
This commit is contained in:
parent
499ddbdf28
commit
8b6c9697e0
|
@ -0,0 +1,51 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
special = {
|
||||||
|
'heart': '\u2764',
|
||||||
|
'zwsp': '\u200b',
|
||||||
|
}
|
||||||
|
|
||||||
|
colors = {name: code for code, *names in map(str.split, '''
|
||||||
|
00 white w
|
||||||
|
01 black b
|
||||||
|
02 blue navy navyblue
|
||||||
|
03 green
|
||||||
|
04 red 05 brown maroon
|
||||||
|
06 purple
|
||||||
|
07 orange olive
|
||||||
|
08 yellow
|
||||||
|
09 lightgreen lime
|
||||||
|
10 teal greenbluecyan
|
||||||
|
11 lightcyan cyan aqua
|
||||||
|
12 lightblue royalblue royal
|
||||||
|
13 pink lightpurple fuchsia
|
||||||
|
14 grey gray
|
||||||
|
15 lightgrey lightgray silver
|
||||||
|
99 default
|
||||||
|
'''.strip().split('\n')) for name in names}
|
||||||
|
|
||||||
|
from sys import argv
|
||||||
|
chan = argv[1]
|
||||||
|
output = ''
|
||||||
|
for arg in argv[2:]:
|
||||||
|
try:
|
||||||
|
if arg[0] == '-':
|
||||||
|
arg = arg[1:]
|
||||||
|
if arg[0] == '-':
|
||||||
|
output += arg
|
||||||
|
elif arg in special:
|
||||||
|
output += special[arg]
|
||||||
|
elif arg[0] == 'x':
|
||||||
|
output += chr(int(arg[1:]))
|
||||||
|
elif ',' in arg:
|
||||||
|
a, b = arg.split(',')
|
||||||
|
output += '\x03' + colors[a] + ',' + colors[b]
|
||||||
|
else:
|
||||||
|
output += '\x03' + colors[arg]
|
||||||
|
else:
|
||||||
|
output += arg
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
with open('/home/zgrep/offtopiabday/irc.freenode.net/' + chan + '/in', 'w') as fh:
|
||||||
|
fh.write(output + '\n')
|
|
@ -0,0 +1,259 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
from urllib.request import urlopen, quote, Request
|
||||||
|
from json import loads as dejson
|
||||||
|
from re import compile as regex
|
||||||
|
|
||||||
|
def cmd(args):
|
||||||
|
proc = Popen(args, stdout=PIPE)
|
||||||
|
while True:
|
||||||
|
line = proc.stdout.readline()
|
||||||
|
if line:
|
||||||
|
line = line[:-1]
|
||||||
|
yield str(line, 'utf-8', 'ignore')
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Imports are finished, as is the preparation for things later.
|
||||||
|
# Time to implement the searchers!
|
||||||
|
|
||||||
|
def relevantxkcd(query):
|
||||||
|
try:
|
||||||
|
url = "https://relevantxkcd.appspot.com/process?action=xkcd&query=" + quote(query)
|
||||||
|
req = urlopen(url)
|
||||||
|
if req.code != 200:
|
||||||
|
return None
|
||||||
|
res = req.read().split()
|
||||||
|
sure = float(res[0])
|
||||||
|
if sure < 0.07:
|
||||||
|
return None
|
||||||
|
num = int(res[2])
|
||||||
|
return 'https://xkcd.com/' + str(num)
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def explainxkcd(query):
|
||||||
|
try:
|
||||||
|
url = "https://explainxkcd.com/wiki/api.php?action=query&list=search&srwhat=text&format=json&srsearch=" + quote(query)
|
||||||
|
url = Request(url, headers={'User-Agent': 'Mozilla'})
|
||||||
|
req = urlopen(url)
|
||||||
|
if req.code != 200:
|
||||||
|
return None
|
||||||
|
res = dejson(req.read().decode())
|
||||||
|
for item in res['query']['search']:
|
||||||
|
try:
|
||||||
|
num = int(item['title'].split(':')[0])
|
||||||
|
return 'https://xkcd.com/' + str(num)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
googleapi = 'AIzaSyDr1gkHH-18QheEJpdGwUMmhYYvtlIJ3bA'
|
||||||
|
googlecse = '017423361205507730360:p6-h8trjn5c'
|
||||||
|
googlereg = regex(r'xkcd\.com/(\d+)')
|
||||||
|
|
||||||
|
def googlexkcd(query):
|
||||||
|
try:
|
||||||
|
url = 'https://www.googleapis.com/customsearch/v1?key=' + googleapi + '&cx=' + googlecse + '&q=' + quote(query)
|
||||||
|
req = urlopen(url)
|
||||||
|
if req.code != 200:
|
||||||
|
return None
|
||||||
|
print('| | Opened URL, status code 200.')
|
||||||
|
res = dejson(req.read().decode())
|
||||||
|
print('| | Decoded JSON.')
|
||||||
|
for item in res['items']:
|
||||||
|
print('| | Checking:', item['link'])
|
||||||
|
match = googlereg.search(item['link'])
|
||||||
|
try:
|
||||||
|
num = int(match.group(1))
|
||||||
|
print('| | Found a match:', num)
|
||||||
|
return 'https://xkcd.com/' + str(num)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
tvtropesapi = 'AIzaSyCVAXiUzRYsML1Pv6RwSG1gunmMikTzQqY'
|
||||||
|
tvtropescse = '006443654034974345143:kc4pt9dnkle'
|
||||||
|
def googletvtropes(query):
|
||||||
|
try:
|
||||||
|
url = 'https://www.googleapis.com/customsearch/v1element?key=' + tvtropesapi + '&cx=' + tvtropescse + '&q=' + quote(query)
|
||||||
|
req = urlopen(url)
|
||||||
|
if req.code != 200:
|
||||||
|
return None
|
||||||
|
print('| | Opened URL, status code 200.')
|
||||||
|
res = dejson(req.read().decode())
|
||||||
|
print('| | Decoded JSON.')
|
||||||
|
if 'results' in res.keys() and res['results']:
|
||||||
|
return(res['results'][0]['url'])
|
||||||
|
print('| | No results.')
|
||||||
|
return None
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def numberxkcd(segment):
|
||||||
|
query = ''
|
||||||
|
original = segment
|
||||||
|
while segment and segment[0].isdigit():
|
||||||
|
query += segment[0]
|
||||||
|
segment = segment[1:]
|
||||||
|
if query:
|
||||||
|
return 'https://xkcd.com/' + query, '', segment
|
||||||
|
return '', '', original
|
||||||
|
|
||||||
|
# Righty, so all our searching mechanisms are above us. Let's table 'em up in a dict.
|
||||||
|
|
||||||
|
methods = {
|
||||||
|
'xkcd': (relevantxkcd, googlexkcd, explainxkcd),
|
||||||
|
# 'smbc': (),
|
||||||
|
# 'satw': (),
|
||||||
|
# 'ssss': (),
|
||||||
|
'tvtropes': (googletvtropes,),
|
||||||
|
}
|
||||||
|
|
||||||
|
# They return answer, query, segment
|
||||||
|
special = {
|
||||||
|
'xkcd': numberxkcd,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Now for matching quotes.
|
||||||
|
|
||||||
|
matching = [
|
||||||
|
('"', '"'),
|
||||||
|
("'", "'"),
|
||||||
|
('“', '”'),
|
||||||
|
('„', '”', '“'),
|
||||||
|
('<', '>'),
|
||||||
|
('«', '»'),
|
||||||
|
('»', '«'),
|
||||||
|
('‹', '›'),
|
||||||
|
('《', '》'),
|
||||||
|
('〈', '〉'),
|
||||||
|
('「', '」'),
|
||||||
|
('﹁', '﹂'),
|
||||||
|
('『', '』'),
|
||||||
|
('﹃', '﹄'),
|
||||||
|
('(', ')'),
|
||||||
|
('[', ']'),
|
||||||
|
('{', '}'),
|
||||||
|
('【', '】'),
|
||||||
|
('〔', '〕'),
|
||||||
|
('⦗', '⦘'),
|
||||||
|
('〖', '〗'),
|
||||||
|
('〘', '〙'),
|
||||||
|
('‚', '’', '‘'),
|
||||||
|
('lu', "li'u")
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# And for an attempt to extract a comic.
|
||||||
|
|
||||||
|
def attempt(line):
|
||||||
|
output = []
|
||||||
|
segment = line
|
||||||
|
|
||||||
|
while segment:
|
||||||
|
i = len(segment)
|
||||||
|
c = ''
|
||||||
|
for comic in methods.keys():
|
||||||
|
try:
|
||||||
|
n = segment.index(comic + '!')
|
||||||
|
if n < i:
|
||||||
|
i = n
|
||||||
|
c = comic
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not c:
|
||||||
|
# We have not found any comic-related things in this line. Bye!
|
||||||
|
return None
|
||||||
|
print('Searching for ' + c + ':')
|
||||||
|
|
||||||
|
i += len(c) + 1 # len(comic + '!')
|
||||||
|
segment = segment[i:] # Right, skippity skip.
|
||||||
|
query = ''
|
||||||
|
|
||||||
|
# Special cases.
|
||||||
|
if c in special.keys():
|
||||||
|
print("| There's a special case:")
|
||||||
|
result, query, segment = special[c](segment)
|
||||||
|
if result:
|
||||||
|
print("| | Result:", result)
|
||||||
|
output.append(result)
|
||||||
|
continue
|
||||||
|
if not query:
|
||||||
|
print("| | Special case did not match.")
|
||||||
|
|
||||||
|
if not query:
|
||||||
|
# See if there's a quoted thing.
|
||||||
|
for pair in matching:
|
||||||
|
start, *ends = pair
|
||||||
|
l = len(start)
|
||||||
|
if segment[:l] != start:
|
||||||
|
continue
|
||||||
|
print('| Found matching initial quote:', start)
|
||||||
|
segment = segment[l:]
|
||||||
|
for end in ends:
|
||||||
|
try:
|
||||||
|
i = segment.index(end)
|
||||||
|
query = segment[:i]
|
||||||
|
segment = segment[i + len(end):]
|
||||||
|
print('| Found matching end:', end)
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if query:
|
||||||
|
break
|
||||||
|
|
||||||
|
if not query:
|
||||||
|
while segment:
|
||||||
|
if not segment[0].isspace():
|
||||||
|
query += segment[0]
|
||||||
|
segment = segment[1:]
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
if '_' in query:
|
||||||
|
print('| Replacing "_" with " ".')
|
||||||
|
query = query.replace('_', ' ')
|
||||||
|
elif '-' in query:
|
||||||
|
print('| Replacing "-" with " ".')
|
||||||
|
query = query.replace('-', ' ')
|
||||||
|
|
||||||
|
if query:
|
||||||
|
query = query.strip()
|
||||||
|
print('| Searching for:', query)
|
||||||
|
for method in methods[c]:
|
||||||
|
print('| Search using:', method.__name__)
|
||||||
|
result = method(query)
|
||||||
|
if result is not None:
|
||||||
|
output.append(result)
|
||||||
|
print('| Result:', result)
|
||||||
|
break
|
||||||
|
|
||||||
|
return ' '.join(output)
|
||||||
|
|
||||||
|
# Connect it to happybot.
|
||||||
|
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
if len(argv) != 3:
|
||||||
|
print('Usage: ./xkcd.py out in')
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
for line in cmd(['tail', '-f', argv[1]]):
|
||||||
|
line = line.split(' ', 3)[3]
|
||||||
|
# ACTIONs shmacktions, I don't give a char 'bout that.
|
||||||
|
if line[:8] == '\x01ACTION ' and line[-1] == '\x01':
|
||||||
|
line = line[8:-1]
|
||||||
|
# Oh, oh noes! We can't look at these lines! HUMANS ARE EVIL!
|
||||||
|
if line.startswith('\u200b') or line.startswith('nolog:') or line.startswith('[nolog]'):
|
||||||
|
continue
|
||||||
|
# I'm trying... trying...
|
||||||
|
result = attempt(line)
|
||||||
|
if result:
|
||||||
|
with open(argv[2], 'w') as fh:
|
||||||
|
fh.write('\u200b' + result + '\n')
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
echo -e "$(cat /home/zgrep/zwsp)\x02\x0311,01Happy $@! ♥" >> "/home/zgrep/offtopiabday/irc.freenode.net/#offtopia/in";
|
|
@ -1,24 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import requests as rq
|
|
||||||
from lxml import html
|
|
||||||
|
|
||||||
from sys import argv
|
|
||||||
if len(argv) != 2:
|
|
||||||
print('Not enough arguments. Bug zgrep.')
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
q = argv[1]
|
|
||||||
|
|
||||||
r = rq.get('http://ichi.moe/cl/qr/', params={'q': q})
|
|
||||||
|
|
||||||
if r.status_code != 200:
|
|
||||||
print('Non-200 status code. Bug zgrep.')
|
|
||||||
exit()
|
|
||||||
|
|
||||||
# tree
|
|
||||||
t = html.fromstring(r.content)
|
|
||||||
|
|
||||||
ichi = ''.join(t.xpath('//span[@class="ds-text"]//text()'))
|
|
||||||
|
|
||||||
print(ichi)
|
|
|
@ -1,9 +0,0 @@
|
||||||
#!/usr/bin/env ash
|
|
||||||
|
|
||||||
. /home/zgrep/offtopiabday/happybot/common.sh
|
|
||||||
|
|
||||||
irc | while read -r n m; do
|
|
||||||
if reg '^(happy|hate)bot[:,] ichi (.*)' "$m"; then
|
|
||||||
python3 happybot/ichi.py "$(m 2)" | say;
|
|
||||||
fi;
|
|
||||||
done;
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
echo -e "$(cat /home/zgrep/zwsp)\x02\x0311,01Happy$@! ♥" >> "/home/zgrep/offtopiabday/irc.freenode.net/#offtopia/in";
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
rm /home/zgrep/offtopiabday/hateweekfile;
|
||||||
|
echo -e "$(cat /home/zgrep/zwsp)\x02\x0304,01I hate how hateweek is over!" >> "/home/zgrep/offtopiabday/irc.freenode.net/#offtopia/in";
|
||||||
|
echo "/n happybot" >> "/home/zgrep/offtopiabday/irc.freenode.net/in";
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
touch /home/zgrep/offtopiabday/hateweekfile;
|
||||||
|
echo "/n hatebot" >> "/home/zgrep/offtopiabday/irc.freenode.net/in";
|
||||||
|
echo -e "$(cat /home/zgrep/zwsp)\x02\x0304,01Hateweek is here! Hate how it's only once a year!" >> "/home/zgrep/offtopiabday/irc.freenode.net/#offtopia/in";
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
happy=':-*D|=D|(:|։|܃|܄|᛬|︰|᠃|᠉|⁚|׃|˸|꞉|∶|ː|ꓽ|⠨|⡁|⠅)(ᴅ|Ⅾ|ⅅ|𝐃|𝐷|𝑫|𝒟|𝓓|𝔇|𝔻|𝕯|𝖣|𝗗|𝘋|𝘿|𝙳|Ꭰ|ᗞ|ᗪ|ꓓ|ᴰ|Ɖ|Ð|⫐|𐌃|Ɒ)'
|
||||||
|
tail -n 200 "/home/zgrep/offtopiabday/irc.freenode.net/##:d/out" | awk '{if($3=="-!-")gsub(/\([^)]+\)/,"");if(/^\S+ \S+ \S+ :D$/){}else if(/'"$happy"'/){sub(/>.*/, "> [REDACTED: NON-CONFORMANT]")}else{sub(/>.*/, "> [REDACTED: NON-HAPPY]")};print}'
|
|
@ -0,0 +1,77 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from sys import argv
|
||||||
|
import re
|
||||||
|
import requests as rq
|
||||||
|
from lxml import html
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
|
||||||
|
if len(argv) != 2:
|
||||||
|
print('Usage:', argv[0], '#channel')
|
||||||
|
exit(1)
|
||||||
|
chan = argv[1]
|
||||||
|
|
||||||
|
def cmd(args):
|
||||||
|
proc = Popen(args, stdout=PIPE)
|
||||||
|
while True:
|
||||||
|
line = proc.stdout.readline()
|
||||||
|
if line:
|
||||||
|
try:
|
||||||
|
yield str(line[:-1], 'utf-8', 'ignore')
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
fdir = '/home/zgrep/offtopiabday/irc.freenode.net/' + chan
|
||||||
|
fin = fdir + '/in'
|
||||||
|
fout = fdir + '/out'
|
||||||
|
|
||||||
|
def irc():
|
||||||
|
for line in cmd(['tail', '-n', '0', '-f', fout]):
|
||||||
|
date, time, nick, line = line.split(' ', 3)
|
||||||
|
print(line)
|
||||||
|
m = re.match(r'(?i)((happy|hate)bot[:,]\s+ichi|ハピロボット[:,])\s(.+)', line)
|
||||||
|
if m:
|
||||||
|
q = m.group(3)
|
||||||
|
print('Matched!', q)
|
||||||
|
r = get(q)
|
||||||
|
print('Result!', r)
|
||||||
|
with open(fin, 'w') as fh:
|
||||||
|
fh.write(r + '\n')
|
||||||
|
|
||||||
|
omitnum = 3
|
||||||
|
|
||||||
|
def ichi(q, extra=False):
|
||||||
|
r = rq.get('http://ichi.moe/cl/qr/', params={'q': q})
|
||||||
|
if r.status_code != 200:
|
||||||
|
return 'Non-200 status code. Bug zgrep.'
|
||||||
|
t = html.fromstring(r.content)
|
||||||
|
ichi = ''.join(t.xpath('//span[@class="ds-text"]//text()'))
|
||||||
|
more = ''
|
||||||
|
if extra:
|
||||||
|
e = t.xpath('//span[@class="gloss-desc"]//text()')
|
||||||
|
more = ' - '.join(e[:omitnum])
|
||||||
|
if len(e) > omitnum:
|
||||||
|
more += ' - \x1dmore omitted\x0f'
|
||||||
|
if more:
|
||||||
|
more = ' (' + more + ')'
|
||||||
|
return '"' + ichi + '"' + more
|
||||||
|
|
||||||
|
def kanji(q):
|
||||||
|
r = rq.get('http://ichi.moe/cl/kanji/', params={'q': q})
|
||||||
|
if r.status_code != 200:
|
||||||
|
return None
|
||||||
|
if 'No kanji found' in r.text:
|
||||||
|
return None
|
||||||
|
t = html.fromstring(r.content)
|
||||||
|
return 'Not yet implemented.'
|
||||||
|
|
||||||
|
def get(q):
|
||||||
|
if len(q) == 1:
|
||||||
|
# k = kanji(q)
|
||||||
|
# if k: return k
|
||||||
|
return ichi(q, True)
|
||||||
|
return ichi(q)
|
||||||
|
|
||||||
|
irc()
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
nick="$1"; shift;
|
||||||
|
|
||||||
|
echo "/privmsg $nick :$@" >> "/home/zgrep/offtopiabday/irc.freenode.net/in";
|
|
@ -0,0 +1,313 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
from random import choice, random
|
||||||
|
from time import sleep
|
||||||
|
from os import chdir
|
||||||
|
|
||||||
|
map_url = 'https://zgrep.org/taxreturns/rfk.txt'
|
||||||
|
|
||||||
|
# Log.
|
||||||
|
|
||||||
|
def logging(msg):
|
||||||
|
with open('log.txt', 'a') as fh:
|
||||||
|
fh.write(msg.strip() + '\n')
|
||||||
|
|
||||||
|
# Items.
|
||||||
|
|
||||||
|
def get_items():
|
||||||
|
with open('rfk.txt') as fh:
|
||||||
|
return [l.strip() for l in fh]
|
||||||
|
|
||||||
|
def add_item(item):
|
||||||
|
items = set(get_items() + [item])
|
||||||
|
with open('rfk.txt', 'w') as fh:
|
||||||
|
fh.write('\n'.join(items) + '\n')
|
||||||
|
logging('add item: ' + item)
|
||||||
|
return 'Added item: ' + item
|
||||||
|
|
||||||
|
def del_item(item):
|
||||||
|
items = set(get_items())
|
||||||
|
if item in items:
|
||||||
|
items.remove(item)
|
||||||
|
with open('rfk.txt', 'w') as fh:
|
||||||
|
fh.write('\n'.join(items) + '\n')
|
||||||
|
logging('del item: ' + item)
|
||||||
|
return 'Removed item: ' + item
|
||||||
|
else:
|
||||||
|
removal = None
|
||||||
|
for maybe in items:
|
||||||
|
if maybe.lower().startswith(item.lower()):
|
||||||
|
if removal:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
removal = maybe
|
||||||
|
else:
|
||||||
|
if removal:
|
||||||
|
items.remove(removal)
|
||||||
|
with open('rfk.txt', 'w') as fh:
|
||||||
|
fh.write('\n'.join(items) + '\n')
|
||||||
|
logging('del item: ' + removal)
|
||||||
|
return 'Removed item: ' + removal
|
||||||
|
else:
|
||||||
|
return 'No items matched: ' + item
|
||||||
|
return 'More than one item matched: ' + item
|
||||||
|
|
||||||
|
# Robot finds kitten bits below.
|
||||||
|
|
||||||
|
grid = {}
|
||||||
|
width, height = 30, 15
|
||||||
|
rx, ry = width // 2, height // 2
|
||||||
|
percent = 0.1
|
||||||
|
blind = False
|
||||||
|
found = False
|
||||||
|
|
||||||
|
def string(): # prints the grid as a string
|
||||||
|
global grid, rx, ry, width, height, found
|
||||||
|
result = ''
|
||||||
|
for y in range(height):
|
||||||
|
for x in range(width):
|
||||||
|
if (x, y) in grid:
|
||||||
|
item = grid[(x, y)]
|
||||||
|
if found and item[2]:
|
||||||
|
result += 'K'
|
||||||
|
else:
|
||||||
|
result += item[0]
|
||||||
|
elif x == rx and y == ry:
|
||||||
|
result += '#'
|
||||||
|
else:
|
||||||
|
result += ' '
|
||||||
|
result += '\n'
|
||||||
|
return result
|
||||||
|
|
||||||
|
def move(x, y): # teleports to location
|
||||||
|
global rx, ry, width, height, grid, found
|
||||||
|
if x < 0 or y < 0 or x >= width or y >= height:
|
||||||
|
return 'There is a wall in the way.'
|
||||||
|
elif (x, y) in grid:
|
||||||
|
result = grid[(x, y)]
|
||||||
|
if result[2]:
|
||||||
|
found = True
|
||||||
|
return result[1]
|
||||||
|
else:
|
||||||
|
rx, ry = x, y
|
||||||
|
return None
|
||||||
|
|
||||||
|
up = lambda: move(rx, ry - 1)
|
||||||
|
down = lambda: move(rx, ry + 1)
|
||||||
|
left = lambda: move(rx - 1, ry)
|
||||||
|
right = lambda: move(rx + 1, ry)
|
||||||
|
|
||||||
|
symbols = '~!@$%^&*()`[]{}=+\\/?|-_;:\'"<>,.abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||||
|
|
||||||
|
def reset(): # Set up a new game.
|
||||||
|
global width, height, rx, ry, grid, percent, found
|
||||||
|
grid = {}
|
||||||
|
found = False
|
||||||
|
items = get_items()
|
||||||
|
rx, ry = width // 2, height // 2
|
||||||
|
for y in range(height):
|
||||||
|
for x in range(width):
|
||||||
|
if random() <= percent and x != rx and y != ry:
|
||||||
|
grid[(x, y)] = (choice(symbols), choice(items), False)
|
||||||
|
if not grid:
|
||||||
|
kitten = (rx - 2, ry - 2)
|
||||||
|
else:
|
||||||
|
kitten = choice(list(grid))
|
||||||
|
with open('found.txt') as fh:
|
||||||
|
messages = [f.strip('\n') for f in fh.read().strip('\n').split('\n%\n')]
|
||||||
|
grid[kitten] = (choice(symbols), choice(messages), True)
|
||||||
|
if len(grid) == 1:
|
||||||
|
objects = 'there is 1 object'
|
||||||
|
else:
|
||||||
|
objects = 'there are {} objects'.format(len(grid))
|
||||||
|
if not blind:
|
||||||
|
append = 'Map: ' + map_url
|
||||||
|
else:
|
||||||
|
append = 'No map is being made, blind is set to true.'
|
||||||
|
return 'New game! The grid is {} by {}, and {}. You are in the center. {}'\
|
||||||
|
.format(width, height, objects, append)
|
||||||
|
|
||||||
|
# Parsing input.
|
||||||
|
|
||||||
|
def tofile():
|
||||||
|
global blind
|
||||||
|
if not blind:
|
||||||
|
with open('/home/zgrep/tax/rfk.txt', 'w') as fh:
|
||||||
|
fh.write(string())
|
||||||
|
|
||||||
|
def dedup(gen):
|
||||||
|
prev = None
|
||||||
|
for item in gen:
|
||||||
|
if item == prev:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
prev = item
|
||||||
|
yield item
|
||||||
|
|
||||||
|
def parse(cmd, normalcase):
|
||||||
|
global width, height, percent, blind
|
||||||
|
if all(c in 'udlrnsew^v<>←↑→↓' for c in cmd):
|
||||||
|
for c in cmd:
|
||||||
|
if c in 'u^n↑':
|
||||||
|
yield up()
|
||||||
|
elif c in 'dvs→':
|
||||||
|
yield down()
|
||||||
|
elif c in 'l<w←':
|
||||||
|
yield left()
|
||||||
|
elif c in 'r>e↓':
|
||||||
|
yield right()
|
||||||
|
tofile()
|
||||||
|
elif cmd in ('up', 'north'):
|
||||||
|
yield up()
|
||||||
|
tofile()
|
||||||
|
elif cmd in ('down', 'south'):
|
||||||
|
yield down()
|
||||||
|
tofile()
|
||||||
|
elif cmd in ('left', 'west'):
|
||||||
|
yield left()
|
||||||
|
tofile()
|
||||||
|
elif cmd in ('right', 'east'):
|
||||||
|
yield right()
|
||||||
|
tofile()
|
||||||
|
elif cmd.startswith('size '):
|
||||||
|
cmd = cmd.replace('size ', '', 1)
|
||||||
|
try:
|
||||||
|
w, h = map(int, cmd.split('x'))
|
||||||
|
w = min(max(w, 5), 1000)
|
||||||
|
h = min(max(h, 5), 1000)
|
||||||
|
width, height = w, h
|
||||||
|
yield reset()
|
||||||
|
tofile()
|
||||||
|
yield topic()
|
||||||
|
except:
|
||||||
|
yield 'The correct format for size is 10x10.'
|
||||||
|
elif cmd.startswith('blind '):
|
||||||
|
cmd = cmd.replace('blind ', '', 1)
|
||||||
|
if ' ' not in cmd:
|
||||||
|
if cmd in ('true', 'yes', 'on', '1'):
|
||||||
|
blind = True
|
||||||
|
with open('/home/zgrep/tax/rfk.txt', 'w') as fh:
|
||||||
|
fh.write('Blind is turned on, no map is being generated.\n')
|
||||||
|
yield topic()
|
||||||
|
yield 'Blind has been set to true, no new maps with be generated.'
|
||||||
|
elif cmd in ('false', 'no', 'off', '0'):
|
||||||
|
blind = False
|
||||||
|
tofile()
|
||||||
|
yield topic()
|
||||||
|
yield 'Blind has been turned off, a map has been generated: ' + map_url
|
||||||
|
else:
|
||||||
|
yield 'Expected either true or false.'
|
||||||
|
elif cmd.startswith('prob '):
|
||||||
|
cmd = cmd.replace('prob ', '', 1)
|
||||||
|
try:
|
||||||
|
m = 1
|
||||||
|
if cmd[-1] == '%':
|
||||||
|
cmd = cmd[:-1]
|
||||||
|
m = 0.01
|
||||||
|
p = min(max(m*float(cmd), 0), 1)
|
||||||
|
percent = p
|
||||||
|
yield reset()
|
||||||
|
tofile()
|
||||||
|
yield topic()
|
||||||
|
except:
|
||||||
|
yield 'The correct format for prob is 0.1 or 10%.'
|
||||||
|
elif cmd.startswith('add item '):
|
||||||
|
yield add_item(normalcase[9:])
|
||||||
|
elif cmd.startswith('del item '):
|
||||||
|
yield del_item(normalcase[9:])
|
||||||
|
elif cmd in ('reset', 'new game', 'restart'):
|
||||||
|
yield reset()
|
||||||
|
tofile()
|
||||||
|
yield topic()
|
||||||
|
elif cmd == 'help':
|
||||||
|
yield 'Commands: size, prob, add item, del item, up (north), down (south), left (west), right (east), new game, blind, map, help.'
|
||||||
|
yield '^<>vudlrnsew becomes up left right down up down left right north south east west. Only the one-character short commands can be chained together in one IRC message.'
|
||||||
|
if not blind:
|
||||||
|
yield 'A map of the grid can be found at: {}'.format(map_url)
|
||||||
|
else:
|
||||||
|
yield 'Currently blind is set to true, and therefore no map of the grid is generated. But normally, it would be found here: {}'.format(map_url)
|
||||||
|
elif cmd in ('map', 'grid'):
|
||||||
|
yield map_url
|
||||||
|
elif cmd == 'size':
|
||||||
|
yield '{} by {}'.format(width, height)
|
||||||
|
elif cmd == 'prob':
|
||||||
|
s = 's'
|
||||||
|
if len(grid) == 1: s = ''
|
||||||
|
yield '{}%, with {} object{} on the current grid.'\
|
||||||
|
.format(percent*100, len(grid), s)
|
||||||
|
elif cmd == 'blind':
|
||||||
|
yield ('blind is set to false, a map is being generated.',
|
||||||
|
'blind is set to true, no map is being generated.')[blind]
|
||||||
|
|
||||||
|
# IRC-specific bits below.
|
||||||
|
|
||||||
|
def topic():
|
||||||
|
global found, width, height, grid
|
||||||
|
s = 's'
|
||||||
|
if len(grid) == 1: s = ''
|
||||||
|
append = 'No map.'
|
||||||
|
if not blind:
|
||||||
|
append = 'Map: ' + map_url
|
||||||
|
finding = ''
|
||||||
|
if found is True:
|
||||||
|
finding = ' Kitten has been found!'
|
||||||
|
elif found:
|
||||||
|
finding = ' Kitten has been found by {}!'.format(found)
|
||||||
|
return '/t Robot finds kitten. To play, type "help". | The grid is {} by {}, and has {} object{}.{} {}'\
|
||||||
|
.format(width, height, len(grid), s, finding, append)
|
||||||
|
|
||||||
|
def cmd(args):
|
||||||
|
proc = Popen(args, stdout=PIPE)
|
||||||
|
while True:
|
||||||
|
line = proc.stdout.readline()
|
||||||
|
if line:
|
||||||
|
try:
|
||||||
|
yield str(line[:-1], 'utf-8', 'ignore')
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
def begin(fin, fout):
|
||||||
|
global found
|
||||||
|
|
||||||
|
fin = '/home/zgrep/offtopiabday/' + fin
|
||||||
|
fout = '/home/zgrep/offtopiabday/' + fout
|
||||||
|
|
||||||
|
def send(msg):
|
||||||
|
if msg:
|
||||||
|
with open(fin, 'w') as fh:
|
||||||
|
fh.write(msg.strip() + '\n')
|
||||||
|
|
||||||
|
send(reset())
|
||||||
|
tofile()
|
||||||
|
send(topic())
|
||||||
|
|
||||||
|
for line in cmd(['tail', '-n', '0', '-f', fout]):
|
||||||
|
_, _, nick, line = line.split(' ', 3)
|
||||||
|
nick = nick[1:-1]
|
||||||
|
if nick in ('happybot', 'hatebot'):
|
||||||
|
continue
|
||||||
|
output = list(dedup(parse(line.lower(), line)))
|
||||||
|
if found is True:
|
||||||
|
found = nick
|
||||||
|
with open('finders.txt', 'a') as fh:
|
||||||
|
fh.write(found + '\n')
|
||||||
|
send(topic())
|
||||||
|
time = 0
|
||||||
|
if len(output) > 3:
|
||||||
|
time = 0.5
|
||||||
|
for line in output:
|
||||||
|
send(line)
|
||||||
|
sleep(time)
|
||||||
|
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
if len(argv) != 3:
|
||||||
|
print('Usage: in out')
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
chdir('/home/zgrep/offtopiabday/rfk')
|
||||||
|
|
||||||
|
begin(*argv[1:])
|
|
@ -0,0 +1,140 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
def sizeof_fmt(num, suffix='B'):
|
||||||
|
for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']:
|
||||||
|
if abs(num) < 1024.0:
|
||||||
|
return "%3.1f%s%s" % (num, unit, suffix)
|
||||||
|
num /= 1024.0
|
||||||
|
return "%.1f%s%s" % (num, 'Yi', suffix)
|
||||||
|
|
||||||
|
from re import compile as regex
|
||||||
|
|
||||||
|
urls = regex(r'(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?')
|
||||||
|
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
|
||||||
|
def cmd(*args):
|
||||||
|
proc = Popen(args, stdout=PIPE)
|
||||||
|
while True:
|
||||||
|
line = proc.stdout.readline()
|
||||||
|
if line:
|
||||||
|
try:
|
||||||
|
yield str(line[:-1], 'utf-8', 'ignore')
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
if len(argv) != 2:
|
||||||
|
print('Usage:', argv[0], '#channel')
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
chan = '/home/zgrep/offtopiabday/irc.freenode.net/' + argv[1]
|
||||||
|
|
||||||
|
from urllib.request import Request, urlopen
|
||||||
|
|
||||||
|
def quote(url):
|
||||||
|
res = ''
|
||||||
|
for c in url:
|
||||||
|
if ord(c) > 127:
|
||||||
|
res += ''.join('%' + hex(b)[2:] for b in c.encode('utf-8'))
|
||||||
|
else:
|
||||||
|
res += c
|
||||||
|
return res
|
||||||
|
|
||||||
|
irccloud_none = 'irccloud.com/pastebin/'
|
||||||
|
irccloud_with = irccloud_none + 'raw/'
|
||||||
|
|
||||||
|
for line in cmd('tail', '-n', '0', '-f', chan + '/out'):
|
||||||
|
date, time, nick, line = line.split(' ', 3)
|
||||||
|
nick = nick[1:-1]
|
||||||
|
if nick in ('happybot', 'hatebot'):
|
||||||
|
continue
|
||||||
|
result = []
|
||||||
|
print('Doing line:', line)
|
||||||
|
for url in urls.findall(line):
|
||||||
|
url = quote(url)
|
||||||
|
if irccloud_none in url and irccloud_with not in url:
|
||||||
|
result.append(url.replace(irccloud_none, irccloud_with, 1))
|
||||||
|
continue
|
||||||
|
if url[-5:] == '.gifv': # hack for imgur gifv's
|
||||||
|
url = url[:-5]
|
||||||
|
print('| Got gifv:', url)
|
||||||
|
try:
|
||||||
|
r = urlopen(Request(url + '.mp4', method='HEAD'))
|
||||||
|
contenttype = r.getheader('content-type')
|
||||||
|
length1 = r.getheader('content-length')
|
||||||
|
r.close()
|
||||||
|
except:
|
||||||
|
print('| Could not get mp4.')
|
||||||
|
if 'video' not in contenttype.lower():
|
||||||
|
print('| Video is not a video?')
|
||||||
|
result.append('???')
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
r = urlopen(Request(url + '.gif', method='HEAD'))
|
||||||
|
contenttype = r.getheader('content-type')
|
||||||
|
length2 = r.getheader('content-length')
|
||||||
|
r.close()
|
||||||
|
except:
|
||||||
|
print('| Could not get gif.')
|
||||||
|
if 'image' not in contenttype.lower():
|
||||||
|
print('| Image is not an image?')
|
||||||
|
result.append('???')
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
length1 = int(length1)
|
||||||
|
length2 = int(length2)
|
||||||
|
except:
|
||||||
|
print('| Lengths are not ints.')
|
||||||
|
continue
|
||||||
|
if length1 <= length2:
|
||||||
|
url += '.mp4'
|
||||||
|
length = length1
|
||||||
|
else:
|
||||||
|
url += '.gif'
|
||||||
|
length = length2
|
||||||
|
result.append(url + ' ' + sizeof_fmt(length))
|
||||||
|
continue
|
||||||
|
print('| Got URL:', url)
|
||||||
|
rq = Request(url, method='HEAD')
|
||||||
|
try:
|
||||||
|
r = urlopen(rq)
|
||||||
|
contenttype = r.getheader('content-type').lower()
|
||||||
|
length = r.getheader('content-length')
|
||||||
|
r.close()
|
||||||
|
print('| | HEAD request completed.')
|
||||||
|
download = 0 # 0 ignore, 1 get from HEAD, 2+ get from HEAD otherwise GET
|
||||||
|
if 'image' in contenttype:
|
||||||
|
download = 2 # download images, fine...
|
||||||
|
elif 'video' in contenttype:
|
||||||
|
download = 1 # Eh... I'll draw the line at videos.
|
||||||
|
if download > 0:
|
||||||
|
if length:
|
||||||
|
try:
|
||||||
|
b = int(length)
|
||||||
|
except:
|
||||||
|
b = -1
|
||||||
|
elif download > 1:
|
||||||
|
try:
|
||||||
|
rq = Request(url, method='HEAD')
|
||||||
|
r = urlopen(rq)
|
||||||
|
b = len(r.read())
|
||||||
|
r.close()
|
||||||
|
print('| | Normal request required and complete.')
|
||||||
|
except:
|
||||||
|
b = -1
|
||||||
|
print('| | Normal request required and failed.')
|
||||||
|
if b < 0:
|
||||||
|
print('| | Failure.')
|
||||||
|
result.append('???')
|
||||||
|
else:
|
||||||
|
print('| | Success.')
|
||||||
|
result.append(sizeof_fmt(b))
|
||||||
|
except:
|
||||||
|
print('| | Failure.')
|
||||||
|
if result:
|
||||||
|
with open(chan + '/in', 'w') as fh:
|
||||||
|
fh.write('[' + '] ['.join(result) + ']\n')
|
Loading…
Reference in New Issue