diff --git a/modules/imdb.py b/modules/imdb.py index 108a286..fca1d65 100644 --- a/modules/imdb.py +++ b/modules/imdb.py @@ -7,35 +7,44 @@ Licensed under the Eiffel Forum License 2. http://inamidst.com/phenny/ """ -import json +import re import web -def imdb_search(query): +r_imdb_find = re.compile(r'href="/title/(.*?)/') +r_imdb_details = re.compile(r'(.*?) \((.*?)\) .*?name="description" content="(.*?)"') + +def imdb_search(query): query = query.replace('!', '') - query = query.encode('utf-8') query = web.quote(query) - uri = 'http://www.omdbapi.com/?i=&t=%s' % query + uri = 'http://imdb.com/find?q=%s' % query bytes = web.get(uri) - m = json.loads(bytes) - return m + m = r_imdb_find.search(bytes) + if not m: return m + ID = web.decode(m.group(1)) + uri = 'http://imdb.com/title/%s' % ID + bytes = web.get(uri) + bytes = bytes.replace('\n', '') + info = r_imdb_details.search(bytes) + info = {'Title': info.group(1), 'Year': info.group(2), 'Plot': info.group(3), 'imdbID': ID} + return info def imdb(phenny, input): - """.imdb <movie> - Use the OMDB API to find a link to a movie on IMDb.""" + """.imdb <movie> - Find a link to a movie on IMDb.""" query = input.group(2) if not query: return phenny.say('.imdb what?') m = imdb_search(query) - try: + if m: phenny.say('{0} ({1}): {2} http://imdb.com/title/{3}'.format( m['Title'], m['Year'], m['Plot'], m['imdbID'])) - except: + else: phenny.reply("No results found for '%s'." % query) imdb.commands = ['imdb'] imdb.example = '.imdb Promethius' diff --git a/modules/imdb.txt b/modules/imdb.txt new file mode 100644 index 0000000..022e859 --- /dev/null +++ b/modules/imdb.txt @@ -0,0 +1 @@ +<!DOCTYPE html><htmlxmlns:og="http://ogp.me/ns#"xmlns:fb="http://www.facebook.com/2008/fbml"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="apple-itunes-app" content="app-id=342792525, app-argument=imdb:///title/tt0096895?src=mdot"> <script type="text/javascript">var ue_t0=window.ue_t0||+new Date();</script> <script type="text/javascript"> var ue_mid = "A1EVAM02EL8SFB"; var ue_sn = "www.imdb.com"; var ue_furl = "fls-na.amazon.com"; var ue_sid = "537-4238043-5572716"; var ue_id = "0VC0PSAB0KJP39E2ZF5Z"; (function(e){var c=e;var a=c.ue||{};a.main_scope="mainscopecsm";a.q=[];a.t0=c.ue_t0||+new Date();a.d=g;function g(h){return +new Date()-(h?0:a.t0)}function d(h){return function(){a.q.push({n:h,a:arguments,t:a.d()})}}function b(m,l,h,j,i){var k={m:m,f:l,l:h,c:""+j,err:i,fromOnError:1,args:arguments};c.ueLogError(k);return false}b.skipTrace=1;e.onerror=b;function f(){c.uex("ld")}if(e.addEventListener){e.addEventListener("load",f,false)}else{if(e.attachEvent){e.attachEvent("onload",f)}}a.tag=d("tag");a.log=d("log");a.reset=d("rst");c.ue_csm=c;c.ue=a;c.ueLogError=d("err");c.ues=d("ues");c.uet=d("uet");c.uex=d("uex");c.uet("ue")})(window);(function(e,d){var a=e.ue||{};function c(g){if(!g){return}var f=d.head||d.getElementsByTagName("head")[0]||d.documentElement,h=d.createElement("script");h.async="async";h.src=g;f.insertBefore(h,f.firstChild)}function b(){var k=e.ue_cdn||"z-ecx.images-amazon.com",g=e.ue_cdns||"images-na.ssl-images-amazon.com",j="/images/G/01/csminstrumentation/",h=e.ue_file||"ue-full-11e51f253e8ad9d145f4ed644b40f692._V1_.js",f,i;if(h.indexOf("NSTRUMENTATION_FIL")>=0){return}if("ue_https" in e){f=e.ue_https}else{f=e.location&&e.location.protocol=="https:"?1:0}i=f?"https://":"http://";i+=f?g:k;i+=j;i+=h;c(i)}if(!e.ue_inline){if(a.loadUEFull){a.loadUEFull()}else{b()}}a.uels=c;e.ue=a})(window,document); if (!('CS' in window)) { window.CS = {}; } window.CS.loginLocation = "https://www.imdb.com/registration/signin?u=%2Ftitle%2Ftt0096895%2F"; </script> <script type="text/javascript">var IMDbTimer={starttime: new Date().getTime(),pt:'java'};</script> <script>(function(t){ (t.events = t.events || {})["csm_head_pre_title"] = new Date().getTime(); })(IMDbTimer);</script> <title>Batman (1989) - IMDb
The Dark Knight of Gotham City begins his war on crime with his first major enemy being the clownishly homicidal Joker.

Director:

Writers:

(Batman characters), (story) |2 more credits »
Reviews
Popularity
521 ( 100)

Watch Now

From $2.99 (SD) onAmazon Video

ON DISC
Won 1 Oscar. Another 9 wins & 22 nominations. See more awards »
Learn more

People who liked this also liked... 

Action
   1 2 3 4 5 6 7 8 9 107/10X 

When a corrupt businessman and the grotesque Penguin plot to take control of Gotham City, only Batman can stop them, while the Catwoman has her own agenda.

Director:Tim Burton
Stars: Michael Keaton, Danny DeVito, Michelle Pfeiffer
Action | Adventure | Fantasy
   1 2 3 4 5 6 7 8 9 105.4/10X 

Batman must battle Two-Face and The Riddler with help from an amorous psychologist and a young circus acrobat who becomes his sidekick, Robin.

Director:Joel Schumacher
Stars: Val Kilmer, Tommy Lee Jones, Jim Carrey
Beetlejuice (1988)
Comedy | Fantasy
   1 2 3 4 5 6 7 8 9 107.5/10X 

A couple of recently deceased ghosts contract the services of a "bio-exorcist" in order to remove the obnoxious new owners of their house.

Director:Tim Burton
Stars: Alec Baldwin, Geena Davis, Michael Keaton
Superman (1978)
Action | Adventure | Drama
   1 2 3 4 5 6 7 8 9 107.3/10X 

An alien orphan is sent from his dying planet to Earth, where he grows up to become his adoptive home's first and greatest superhero.

Director:Richard Donner
Stars: Christopher Reeve, Margot Kidder, Gene Hackman
Ghostbusters (1984)
Action | Adventure | Comedy
   1 2 3 4 5 6 7 8 9 107.8/10X 

Three former parapsychology professors set up shop as a unique ghost removal service.

Director:Ivan Reitman
Stars: Bill Murray, Dan Aykroyd, Sigourney Weaver
Action | Fantasy | Sci-Fi
   1 2 3 4 5 6 7 8 9 103.7/10X 

Batman and Robin try to keep their relationship together even as they must stop Mr. Freeze and Poison Ivy from freezing Gotham City.

Director:Joel Schumacher
Stars: Arnold Schwarzenegger, George Clooney, Chris O'Donnell
Mars Attacks! (1996)
Comedy | Sci-Fi
   1 2 3 4 5 6 7 8 9 106.3/10X 

Earth is invaded by Martians with unbeatable weapons and a cruel sense of humor.

Director:Tim Burton
Stars: Jack Nicholson, Pierce Brosnan, Sarah Jessica Parker
Drama | Fantasy | Romance
   1 2 3 4 5 6 7 8 9 107.9/10X 

A gentle man, with scissors for hands, is brought into a new community after living in isolation.

Director:Tim Burton
Stars: Johnny Depp, Winona Ryder, Dianne Wiest
Superman II (1980)
Action | Adventure | Sci-Fi
   1 2 3 4 5 6 7 8 9 106.8/10X 

Superman agrees to sacrifice his powers to start a relationship with Lois Lane, unaware that three Kryptonian criminals he inadvertently released are conquering Earth.

Directors:Richard Lester,Richard Donner
Stars: Gene Hackman, Christopher Reeve, Margot Kidder
Gremlins (1984)
Comedy | Fantasy | Horror
   1 2 3 4 5 6 7 8 9 107.2/10X 

A boy inadvertently breaks three important rules concerning his new pet and unleashes a horde of malevolently mischievous monsters on a small town.

Director:Joe Dante
Stars: Zach Galligan, Phoebe Cates, Hoyt Axton
Action | Comedy | Fantasy
   1 2 3 4 5 6 7 8 9 106.5/10X 

The discovery of a massive river of ectoplasm and a resurgence of spectral activity allows the staff of Ghostbusters to revive the business.

Director:Ivan Reitman
Stars: Bill Murray, Dan Aykroyd, Sigourney Weaver
Action | Adventure | Sci-Fi
   1 2 3 4 5 6 7 8 9 106.1/10X 

Superman reappears after a long absence, but is challenged by an old foe who uses Kryptonian technology for world domination.

Director:Bryan Singer
Stars: Brandon Routh, Kevin Spacey, Kate Bosworth
Edit

Cast

Cast overview, first billed only:
...
...
...
...
...
...
...
...
...
...
Lee Wallace ...
...
...
Carl Chase ...
Mac McDonald ...
Goon (as Mac Macdonald)
Edit

Storyline

Gotham City. Crime boss Carl Grissom (Jack Palance) effectively runs the town but there's a new crime fighter in town - Batman (Michael Keaton). Grissom's right-hand man is Jack Napier (Jack Nicholson), a brutal man who is not entirely sane... After falling out between the two Grissom has Napier set up with the Police and Napier falls to his apparent death in a vat of chemicals. However, he soon reappears as The Joker and starts a reign of terror in Gotham City. Meanwhile, reporter Vicki Vale (Kim Basinger) is in the city to do an article on Batman. She soon starts a relationship with Batman's everyday persona, billionaire Bruce Wayne. Written bygrantss

Plot Summary | Plot Synopsis

Taglines:

Only one will claim the night.

Genres:

Action | Adventure

Certificate:

PG-13| See all certifications »

Parents Guide:

 »
Edit

Details

Country:

|

Language:

|

Release Date:

23 June 1989 (USA)  »

Also Known As:

Betmen  »

Box Office

Budget:

$35,000,000 (estimated)

Gross:

$251,188,924 (USA)
 »

Company Credits

Show detailed on  »

Technical Specs

Runtime:

Sound Mix:

(70 mm prints)| (35 mm prints)| (DVD version)| (Dolby 5.1)

Color:

(Technicolor)

Aspect Ratio:

1.85 : 1
See  »
Edit

Did You Know?

Trivia

Michael Keaton hated the Batsuit because he suffered from claustrophobia. Director Tim Burton and Keaton both decided that it would enhance his performance, so they stuck with it. See more »

Goofs

When the family is mugged in the beginning, the Batman watching from the rooftop is clearly animated. See more »

Quotes

[first lines]
Passenger:Excuse me.
Tourist Dad:I'm sorry, this is my cab.
Passenger:Sorry.
Tourist Dad:Listen, I was here first!
[as the cab drives away]
Tourist Dad:Oh, God! Oh, taxi? Taxi!
See more »

Crazy Credits

The opening credits run with a 3-D Batman symbol being explored by a flying camera in extreme close-up. See more »

Connections

Featured in AMV Hell 3: The Motion Picture (2005) See more »

Soundtracks

There'll Be A Hot Time In The Old Town Tonight
Written by Joe Hayden, Theo. A. Metz (as Theodore A. Metz)
See more »

Frequently Asked Questions

See more (Spoiler Alert!) »

User Reviews

 
The "serious" comic book movie
23 May 2006 | by (New Jersey) – See all my reviews

No radioactive spider bites or guys turning green or supermodels painted blue here. Campy television series aside, Batman has always seemed the most serious, the most grounded, the most real of all the comic book sagas. Our hero has no magical, mystical superpowers...he's just a guy in a suit. But where does he get those wonderful toys? In this film Tim Burton does a very good job of bringing the Dark Knight to life while also seemingly giving the dark, foreboding city of Gotham a life of its own. Gotham is dark, gloomy, and dreary...almost oppressively so. The city is almost a character unto itself in the film...dark, mysterious and somehow quite real. The brilliantly conceived, stunning visuals are the perfect backdrop for the story which will unfold.

The story follows our Caped Crusader in his quest to clean up Gotham which is in the midst of a frightening crime wave. There was much unnecessary angst when comic actor Michael Keaton landed the title role with fans feeling that was a sure sign the film would lean towards the campy style evident in the famous television series. Nothing could have been further from the truth. Batman would be a serious film (well, as serious as a comic book movie can be) and Keaton was perfect in the Bruce Wayne/Batman role. Keaton's Wayne comes across as an ordinary guy doing extraordinary things. Keaton brings all the required seriousness to the role but also can add a little comic touch when necessary. Inspired casting pays off big time.

Good as he is Keaton is actually overshadowed in the film. Who else but Jack Nicholson could cause the actor playing Batman to get second billing in a movie titled Batman? Nicholson's performance as the Joker is simply terrific. Maybe a little over the top at times but, hey, it's the Joker...he's supposed to be over the top. Nicholson livens up every scene he's in, he simply owns the screen. With two terrific actors doing outstanding work bringing our hero and villain to life the film can hardly go wrong. It's certainly entertaining enough but the film as a whole doesn't quite match the brilliance of the two lead performances. The supporting cast, led by Kim Basinger as the requisite love interest, doesn't add much. Instead of leaving well enough alone with a fantastic Danny Elfman score the whole movie comes to a screeching halt a couple of times while we're forced to listen to some inane Prince songs. And the story just seems to lack a certain zest. We want to see the conflict between Batman and the Joker, these two great characters played by two great actors. And for too much of the film that conflict simply isn't there. But all in all, Batman is certainly a worthy effort. Some top-notch acting, stunning visuals and a story that does just enough to draw you in and hold your attention throughout. To call this film great might be a stretch but one could say it is very, very good. Certainly good enough to be worth your while.


98 of 127 people found this review helpful.  Was this review helpful to you?

Message Boards

Recent Posts
Why isn't this film more popular? K-B-M
Why I think this film is off. TheRandomCat
Michelle Pfeiffer as Vicki Vale...??? marialucia1985
The problems I have with this movie TheArtOfBeingRandom34523
Bob the Goon ukmale-93122
Face it, it's bad. TheArtOfBeingRandom34523
Discuss Batman (1989) on the IMDb message boards »

Contribute to This Page



\ No newline at end of file diff --git a/modules/mylife.py b/modules/mylife.py index 69f7ef9..e8d359e 100644 --- a/modules/mylife.py +++ b/modules/mylife.py @@ -18,24 +18,10 @@ def fml(phenny, input): raise GrumbleError("I tried to use .fml, but it was broken. FML") doc = lxml.html.fromstring(req) - quote = doc.find_class('article')[0][0].text_content() + quote = doc.find_class('block')[1][0].text_content() phenny.say(quote) fml.commands = ['fml'] -def mlia(phenny, input): - """.mlia - My life is average.""" - try: - req = web.get("http://mylifeisaverage.com/") - except: - raise GrumbleError("I tried to use .mlia, but it wasn't loading. MLIA") - - doc = lxml.html.fromstring(req) - quote = doc.find_class('story')[0][0].text_content() - quote = quote.strip() - phenny.say(quote) -mlia.commands = ['mlia'] - - if __name__ == '__main__': print(__doc__.strip()) diff --git a/modules/search.py b/modules/search.py index 6911242..6a02e90 100644 --- a/modules/search.py +++ b/modules/search.py @@ -10,31 +10,30 @@ http://inamidst.com/phenny/ import re import web -def google_ajax(query): - """Search using AjaxSearch, and return its JSON.""" - if isinstance(query, str): - query = query.encode('utf-8') - uri = 'https://ajax.googleapis.com/ajax/services/search/web' - args = '?v=1.0&safe=off&q=' + web.quote(query) - bytes = web.get(uri + args, headers={'Referer': 'https://github.com/sbp/phenny'}) - return web.json(bytes) + +r_google = re.compile(r'href="\/url\?q=(http.*?)\/&') def google_search(query): - results = google_ajax(query) - try: return results['responseData']['results'][0]['unescapedUrl'] - except IndexError: return None - except TypeError: - print(results) - return False + query = web.quote(query) + uri = 'https://google.co.uk/search?q=%s' % query + bytes = web.get(uri) + m = r_google.search(bytes) + if m: + result = web.decode(m.group(1)) + return web.unquote(result) + +r_google_count = re.compile(r'id="resultStats">About (.*?) ') def google_count(query): - results = google_ajax(query) - if 'responseData' not in results: return '0' - if 'cursor' not in results['responseData']: return '0' - if 'estimatedResultCount' not in results['responseData']['cursor']: - return '0' - return results['responseData']['cursor']['estimatedResultCount'] - + query = web.quote(query) + uri = 'https://google.co.uk/search?q=%s' % query + bytes = web.get(uri) + m = r_google_count.search(bytes) + if m: + result = web.decode(m.group(1)).replace(',', '') + return int(result) + else: return 0 + def formatnumber(n): """Format a number with beautiful commas.""" parts = list(str(n)) @@ -53,7 +52,6 @@ def g(phenny, input): if not hasattr(phenny.bot, 'last_seen_uri'): phenny.bot.last_seen_uri = {} phenny.bot.last_seen_uri[input.sender] = uri - elif uri is False: phenny.reply("Problem getting data from Google.") else: phenny.reply("No results found for '%s'." % query) g.commands = ['g'] g.priority = 'high' @@ -81,7 +79,6 @@ def gcs(phenny, input): queries = r_query.findall(input.group(2)) if len(queries) > 6: return phenny.reply('Sorry, can only compare up to six things.') - results = [] for i, query in enumerate(queries): query = query.strip('[]') @@ -114,7 +111,6 @@ def bing(phenny, input): else: lang = 'en-GB' if not query: return phenny.reply('.bing what?') - uri = bing_search(query, lang) if uri: phenny.reply(uri) @@ -125,7 +121,7 @@ def bing(phenny, input): bing.commands = ['bing'] bing.example = '.bing swhack' -r_duck = re.compile(r'nofollow" class="[^"]+" href="(http.*?)">') +r_duck = re.compile(r'nofollow" class="[^"]+" href=".+?(http.*?)">') def duck_search(query): query = query.replace('!', '') @@ -133,14 +129,26 @@ def duck_search(query): uri = 'https://duckduckgo.com/html/?q=%s&kl=uk-en' % query bytes = web.get(uri) m = r_duck.search(bytes) - if m: return web.decode(m.group(1)) + if m: + result = web.decode(m.group(1)) + return web.unquote(result) + +def duck_api(query): + uri = 'https://api.duckduckgo.com/?q=%s&format=json&no_redirect=1' % query + bytes = web.get(uri) + json = web.json(bytes) + if query[:1] == '!': + return json['Redirect'] + elif json['Abstract']: + return json['AbstractURL'] + ' : ' + json['Abstract'] + else: return json['AbstractURL'] def duck(phenny, input): """Queries DuckDuckGo for specified input.""" query = input.group(2) if not query: return phenny.reply('.ddg what?') - - uri = duck_search(query) + uri = duck_api(query) + if not uri: uri = duck_search(query) if uri: phenny.reply(uri) if not hasattr(phenny.bot, 'last_seen_uri'): diff --git a/modules/test/test_head.py b/modules/test/test_head.py index 0d936a3..db596e0 100644 --- a/modules/test/test_head.py +++ b/modules/test/test_head.py @@ -18,7 +18,7 @@ class TestHead(unittest.TestCase): out = self.phenny.reply.call_args[0][0] m = re.match('^200, text/html, utf-8, \d{4}\-\d{2}\-\d{2} '\ - '\d{2}:\d{2}:\d{2} UTC, [0-9\.]+ s$', out, flags=re.UNICODE) + '\d{2}:\d{2}:\d{2} UTC, [0-9]+ bytes, [0-9]+.[0-9]+ s$', out, flags=re.UNICODE) self.assertTrue(m) def test_head_404(self): diff --git a/modules/test/test_mylife.py b/modules/test/test_mylife.py index 15a3fb8..69c7bc5 100644 --- a/modules/test/test_mylife.py +++ b/modules/test/test_mylife.py @@ -15,7 +15,3 @@ class TestMylife(unittest.TestCase): def test_fml(self): mylife.fml(self.phenny, None) assert self.phenny.say.called is True - - def test_mlia(self): - mylife.mlia(self.phenny, None) - assert self.phenny.say.called is True diff --git a/modules/test/test_search.py b/modules/test/test_search.py index 1ad8567..10281ba 100644 --- a/modules/test/test_search.py +++ b/modules/test/test_search.py @@ -6,7 +6,7 @@ author: mutantmonkey import re import unittest from mock import MagicMock, Mock -from modules.search import google_ajax, google_search, google_count, \ +from modules.search import duck_api, google_search, google_count, \ formatnumber, g, gc, gcs, bing_search, bing, duck_search, duck, \ search, suggest @@ -15,12 +15,6 @@ class TestSearch(unittest.TestCase): def setUp(self): self.phenny = MagicMock() - def test_google_ajax(self): - data = google_ajax('phenny') - - assert 'responseData' in data - assert data['responseStatus'] == 200 - def test_google_search(self): out = google_search('phenny') @@ -31,8 +25,7 @@ class TestSearch(unittest.TestCase): input = Mock(group=lambda x: 'swhack') g(self.phenny, input) - self.phenny.reply.assert_not_called_with( - "Problem getting data from Google.") + assert self.phenny.reply.called is True def test_gc(self): query = 'extrapolate' @@ -73,6 +66,10 @@ class TestSearch(unittest.TestCase): assert self.phenny.reply.called is True + def test_duck_api(self): + input = Mock(group=lambda x: 'swhack') + duck(self.phenny, input) + def test_search(self): input = Mock(group=lambda x: 'vtluug') duck(self.phenny, input) diff --git a/modules/test/test_vtluugwiki.py b/modules/test/test_vtluugwiki.py index a1e1121..e2c81e8 100644 --- a/modules/test/test_vtluugwiki.py +++ b/modules/test/test_vtluugwiki.py @@ -8,32 +8,32 @@ import unittest from mock import MagicMock, Mock from modules import vtluugwiki - -class TestVtluugwiki(unittest.TestCase): - def setUp(self): - self.phenny = MagicMock() - - def test_vtluug(self): - input = Mock(groups=lambda: ['', "VT-Wireless"]) - vtluugwiki.vtluug(self.phenny, input) - - out = self.phenny.say.call_args[0][0] - m = re.match('^.* - https:\/\/vtluug\.org\/wiki\/VT-Wireless$', - out, flags=re.UNICODE) - self.assertTrue(m) - - def test_vtluug_invalid(self): - term = "EAP-TLS#netcfg" - input = Mock(groups=lambda: ['', term]) - vtluugwiki.vtluug(self.phenny, input) - - self.phenny.say.assert_called_once_with( "Can't find anything in "\ - "the VTLUUG Wiki for \"{0}\".".format(term)) - - def test_vtluug_none(self): - term = "Ajgoajh" - input = Mock(groups=lambda: ['', term]) - vtluugwiki.vtluug(self.phenny, input) - - self.phenny.say.assert_called_once_with( "Can't find anything in "\ - "the VTLUUG Wiki for \"{0}\".".format(term)) +# Disabling tests until wiki is up +#class TestVtluugwiki(unittest.TestCase): +# def setUp(self): +# self.phenny = MagicMock() +# +# def test_vtluug(self): +# input = Mock(groups=lambda: ['', "VT-Wireless"]) +# vtluugwiki.vtluug(self.phenny, input) +# +# out = self.phenny.say.call_args[0][0] +# m = re.match('^.* - https:\/\/vtluug\.org\/wiki\/VT-Wireless$', +# out, flags=re.UNICODE) +# self.assertTrue(m) +# +# def test_vtluug_invalid(self): +# term = "EAP-TLS#netcfg" +# input = Mock(groups=lambda: ['', term]) +# vtluugwiki.vtluug(self.phenny, input) +# +# self.phenny.say.assert_called_once_with( "Can't find anything in "\ +# "the VTLUUG Wiki for \"{0}\".".format(term)) +# +# def test_vtluug_none(self): +# term = "Ajgoajh" +# input = Mock(groups=lambda: ['', term]) +# vtluugwiki.vtluug(self.phenny, input) +# +# self.phenny.say.assert_called_once_with( "Can't find anything in "\ +# "the VTLUUG Wiki for \"{0}\".".format(term)) diff --git a/modules/tools.py b/modules/tools.py new file mode 100755 index 0000000..d3a659e --- /dev/null +++ b/modules/tools.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +""" +tools.py - Phenny Tools +Copyright 2008, Sean B. Palmer, inamidst.com +Licensed under the Eiffel Forum License 2. + +http://inamidst.com/phenny/ +""" + + +class GrumbleError(Exception): + pass + + +def deprecated(old): + def new(phenny, input, old=old): + self = phenny + origin = type('Origin', (object,), { + 'sender': input.sender, + 'nick': input.nick + })() + match = input.match + args = [input.bytes, input.sender, '@@'] + + old(self, origin, match, args) + new.__module__ = old.__module__ + new.__name__ = old.__name__ + return new + +if __name__ == '__main__': + print(__doc__.strip()) diff --git a/modules/web.py b/modules/web.py new file mode 100755 index 0000000..6c7c684 --- /dev/null +++ b/modules/web.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +""" +web.py - Web Facilities +Author: Sean B. Palmer, inamidst.com +About: http://inamidst.com/phenny/ +""" + +import re +import urllib.parse +import requests +import json as jsonlib + +from requests.exceptions import ConnectionError, HTTPError, InvalidURL +from html.entities import name2codepoint +from urllib.parse import quote, unquote + +user_agent = "Mozilla/5.0 (Phenny)" +default_headers = {'User-Agent': user_agent} + +def get(uri, headers={}, verify=True, **kwargs): + if not uri.startswith('http'): + return + headers.update(default_headers) + r = requests.get(uri, headers=headers, verify=verify, **kwargs) + r.raise_for_status() + return r.text + +def head(uri, headers={}, verify=True, **kwargs): + if not uri.startswith('http'): + return + headers.update(default_headers) + r = requests.head(uri, headers=headers, verify=verify, **kwargs) + r.raise_for_status() + return r.headers + +def post(uri, data, headers={}, verify=True, **kwargs): + if not uri.startswith('http'): + return + headers.update(default_headers) + r = requests.post(uri, data=data, headers=headers, verify=verify, **kwargs) + r.raise_for_status() + return r.text + +r_entity = re.compile(r'&([^;\s]+);') + +def entity(match): + value = match.group(1).lower() + if value.startswith('#x'): + return chr(int(value[2:], 16)) + elif value.startswith('#'): + return chr(int(value[1:])) + elif value in name2codepoint: + return chr(name2codepoint[value]) + return '[' + value + ']' + +def decode(html): + return r_entity.sub(entity, html) + +r_string = re.compile(r'("(\\.|[^"\\])*")') +r_json = re.compile(r'^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]+$') +env = {'__builtins__': None, 'null': None, 'true': True, 'false': False} + +def json(text): + """Evaluate JSON text safely (we hope).""" + return jsonlib.loads(text) + +if __name__=="__main__": + main()