phenny/modules/head.py

199 lines
5.4 KiB
Python

#!/usr/bin/env python
"""
head.py - Phenny HTTP Metadata Utilities
Copyright 2008, Sean B. Palmer, inamidst.com
Licensed under the Eiffel Forum License 2.
http://inamidst.com/phenny/
"""
import re
import urllib.parse
import time
from html.entities import name2codepoint
import web
from tools import deprecated
def head(phenny, input):
"""Provide HTTP HEAD information."""
uri = input.group(2)
uri = (uri or '')
if ' ' in uri:
uri, header = uri.rsplit(' ', 1)
else:
uri, header = uri, None
if not uri and hasattr(phenny, 'last_seen_uri'):
try:
uri = phenny.last_seen_uri[input.sender]
except KeyError:
return phenny.say('?')
if not uri.startswith('htt'):
uri = 'http://' + uri
# uri = uri.replace('#!', '?_escaped_fragment_=')
start = time.time()
try:
info = web.head(uri)
info['status'] = '200'
except web.HTTPError as e:
if hasattr(e, 'code'):
return phenny.say(str(e.code))
else:
return phenny.say(str(e.response.status_code))
except web.ConnectionError:
return phenny.say("Can't connect to %s" % uri)
resptime = time.time() - start
if header is None:
data = []
if 'Status' in info:
data.append(info['Status'])
if 'content-type' in info:
data.append(info['content-type'].replace('; charset=', ', '))
if 'last-modified' in info:
modified = info['last-modified']
modified = time.strptime(modified, '%a, %d %b %Y %H:%M:%S %Z')
data.append(time.strftime('%Y-%m-%d %H:%M:%S UTC', modified))
if 'content-length' in info:
data.append(info['content-length'] + ' bytes')
data.append('{0:1.2f} s'.format(resptime))
phenny.reply(', '.join(data))
else:
headerlower = header.lower()
if headerlower in info:
phenny.say(header + ': ' + info.get(headerlower))
else:
msg = 'There was no %s header in the response.' % header
phenny.say(msg)
head.commands = ['head']
head.example = '.head http://www.w3.org/'
r_title = re.compile(r'(?ims)<title[^>]*>(.*?)</title\s*>')
r_entity = re.compile(r'&[A-Za-z0-9#]+;')
def noteuri(phenny, input):
uri = input.group(1)
if not hasattr(phenny.bot, 'last_seen_uri'):
phenny.bot.last_seen_uri = {}
phenny.bot.last_seen_uri[input.sender] = uri
noteuri.rule = r'.*(http[s]?://[^<> "\x01]+)[,.]?'
noteuri.priority = 'low'
def snarfuri(phenny, input):
uri = input.group(2)
title = gettitle(phenny, input, uri)
if title:
phenny.msg(input.sender, title)
snarfuri.rule = r'([^\.].*)?(http[s]?://[^<> "\x01]+)[,.]?'
snarfuri.priority = 'low'
snarfuri.thread = True
def gettitle(phenny, input, uri):
if not ':' in uri:
uri = 'http://' + uri
uri = uri.replace('#!', '?_escaped_fragment_=')
title = None
localhost = [
'http://localhost/', 'http://localhost:80/',
'http://localhost:8080/', 'http://127.0.0.1/',
'http://127.0.0.1:80/', 'http://127.0.0.1:8080/',
'https://localhost/', 'https://localhost:80/',
'https://localhost:8080/', 'https://127.0.0.1/',
'https://127.0.0.1:80/', 'https://127.0.0.1:8080/',
]
for s in localhost:
if uri.startswith(s):
return phenny.reply('Sorry, access forbidden.')
try:
redirects = 0
while True:
info = web.head(uri)
if not isinstance(info, list):
status = '200'
else:
status = str(info[1])
info = info[0]
if status.startswith('3'):
uri = urllib.parse.urljoin(uri, info['Location'])
else:
break
redirects += 1
if redirects >= 25:
return None
try:
mtype = info['content-type']
except:
return None
if not (('/html' in mtype) or ('/xhtml' in mtype)):
return None
bytes = web.get(uri)
#bytes = u.read(262144)
#u.close()
except:
return
m = r_title.search(bytes)
if m:
title = m.group(1)
title = title.strip()
title = title.replace('\t', ' ')
title = title.replace('\r', ' ')
title = title.replace('\n', ' ')
while ' ' in title:
title = title.replace(' ', ' ')
if len(title) > 200:
title = title[:200] + '[...]'
def e(m):
entity = m.group(0)
if entity.startswith('&#x'):
cp = int(entity[3:-1], 16)
return chr(cp)
elif entity.startswith('&#'):
cp = int(entity[2:-1])
return chr(cp)
else:
char = name2codepoint[entity[1:-1]]
return chr(char)
title = r_entity.sub(e, title)
if title:
title = title.replace('\n', '')
title = title.replace('\r', '')
title = "[ {0} ]".format(title)
if "posted" in phenny.variables:
from modules.posted import check_posted
posted = check_posted(phenny, input, uri)
if posted:
title = "{0} (posted: {1})".format(title, posted)
else:
title = None
return title
if __name__ == '__main__':
print(__doc__.strip())