├── .gitignore ├── ChangeLog ├── LICENSE ├── MANIFEST.in ├── README.md ├── contrib ├── django-memebot │ ├── .gitignore │ └── gruntle │ │ ├── __init__.py │ │ ├── apache │ │ └── wsgi.py │ │ ├── bin │ │ ├── fix-busted-slack-links.py │ │ ├── fix-harder.py │ │ ├── fixtimes.py │ │ └── migrate.py │ │ ├── manage.py │ │ ├── memebot │ │ ├── __init__.py │ │ ├── context_processors.py │ │ ├── decorators.py │ │ ├── exceptions.py │ │ ├── feeds │ │ │ ├── __init__.py │ │ │ ├── hugs.py │ │ │ ├── images.py │ │ │ └── text.py │ │ ├── fields.py │ │ ├── forms.py │ │ ├── management │ │ │ ├── __init__.py │ │ │ └── commands │ │ │ │ ├── __init__.py │ │ │ │ ├── archive.py │ │ │ │ ├── bounce.py │ │ │ │ ├── rebuild.py │ │ │ │ ├── replay.py │ │ │ │ ├── scan.py │ │ │ │ ├── scantest.py │ │ │ │ ├── stats.py │ │ │ │ └── updater.py │ │ ├── media │ │ │ ├── admin │ │ │ │ ├── css │ │ │ │ │ ├── base.css │ │ │ │ │ ├── changelists.css │ │ │ │ │ ├── dashboard.css │ │ │ │ │ ├── forms.css │ │ │ │ │ ├── ie.css │ │ │ │ │ ├── login.css │ │ │ │ │ ├── rtl.css │ │ │ │ │ └── widgets.css │ │ │ │ ├── img │ │ │ │ │ ├── admin │ │ │ │ │ │ ├── arrow-down.gif │ │ │ │ │ │ ├── arrow-up.gif │ │ │ │ │ │ ├── changelist-bg.gif │ │ │ │ │ │ ├── changelist-bg_rtl.gif │ │ │ │ │ │ ├── chooser-bg.gif │ │ │ │ │ │ ├── chooser_stacked-bg.gif │ │ │ │ │ │ ├── default-bg-reverse.gif │ │ │ │ │ │ ├── default-bg.gif │ │ │ │ │ │ ├── deleted-overlay.gif │ │ │ │ │ │ ├── icon-no.gif │ │ │ │ │ │ ├── icon-unknown.gif │ │ │ │ │ │ ├── icon-yes.gif │ │ │ │ │ │ ├── icon_addlink.gif │ │ │ │ │ │ ├── icon_alert.gif │ │ │ │ │ │ ├── icon_calendar.gif │ │ │ │ │ │ ├── icon_changelink.gif │ │ │ │ │ │ ├── icon_clock.gif │ │ │ │ │ │ ├── icon_deletelink.gif │ │ │ │ │ │ ├── icon_error.gif │ │ │ │ │ │ ├── icon_searchbox.png │ │ │ │ │ │ ├── icon_success.gif │ │ │ │ │ │ ├── inline-delete-8bit.png │ │ │ │ │ │ ├── inline-delete.png │ │ │ │ │ │ ├── inline-restore-8bit.png │ │ │ │ │ │ ├── inline-restore.png │ │ │ │ │ │ ├── inline-splitter-bg.gif │ │ │ │ │ │ ├── nav-bg-grabber.gif │ │ │ │ │ │ ├── nav-bg-reverse.gif │ │ │ │ │ │ ├── nav-bg.gif │ │ │ │ │ │ ├── selector-add.gif │ │ │ │ │ │ ├── selector-addall.gif │ │ │ │ │ │ ├── selector-remove.gif │ │ │ │ │ │ ├── selector-removeall.gif │ │ │ │ │ │ ├── selector-search.gif │ │ │ │ │ │ ├── selector_stacked-add.gif │ │ │ │ │ │ ├── selector_stacked-remove.gif │ │ │ │ │ │ ├── tool-left.gif │ │ │ │ │ │ ├── tool-left_over.gif │ │ │ │ │ │ ├── tool-right.gif │ │ │ │ │ │ ├── tool-right_over.gif │ │ │ │ │ │ ├── tooltag-add.gif │ │ │ │ │ │ ├── tooltag-add_over.gif │ │ │ │ │ │ ├── tooltag-arrowright.gif │ │ │ │ │ │ └── tooltag-arrowright_over.gif │ │ │ │ │ └── gis │ │ │ │ │ │ ├── move_vertex_off.png │ │ │ │ │ │ └── move_vertex_on.png │ │ │ │ └── js │ │ │ │ │ ├── LICENSE-JQUERY.txt │ │ │ │ │ ├── SelectBox.js │ │ │ │ │ ├── SelectFilter2.js │ │ │ │ │ ├── actions.js │ │ │ │ │ ├── actions.min.js │ │ │ │ │ ├── admin │ │ │ │ │ ├── DateTimeShortcuts.js │ │ │ │ │ ├── RelatedObjectLookups.js │ │ │ │ │ └── ordering.js │ │ │ │ │ ├── calendar.js │ │ │ │ │ ├── collapse.js │ │ │ │ │ ├── collapse.min.js │ │ │ │ │ ├── compress.py │ │ │ │ │ ├── core.js │ │ │ │ │ ├── dateparse.js │ │ │ │ │ ├── getElementsBySelector.js │ │ │ │ │ ├── inlines.js │ │ │ │ │ ├── inlines.min.js │ │ │ │ │ ├── jquery.init.js │ │ │ │ │ ├── jquery.js │ │ │ │ │ ├── jquery.min.js │ │ │ │ │ ├── prepopulate.js │ │ │ │ │ ├── prepopulate.min.js │ │ │ │ │ ├── timeparse.js │ │ │ │ │ └── urlify.js │ │ │ ├── css │ │ │ │ ├── main.css │ │ │ │ └── rss.css │ │ │ ├── external │ │ │ │ ├── css │ │ │ │ │ └── redmond │ │ │ │ │ │ ├── images │ │ │ │ │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ │ │ │ │ │ ├── ui-bg_flat_55_fbec88_40x100.png │ │ │ │ │ │ ├── ui-bg_glass_75_d0e5f5_1x400.png │ │ │ │ │ │ ├── ui-bg_glass_85_dfeffc_1x400.png │ │ │ │ │ │ ├── ui-bg_glass_95_fef1ec_1x400.png │ │ │ │ │ │ ├── ui-bg_gloss-wave_55_5c9ccc_500x100.png │ │ │ │ │ │ ├── ui-bg_inset-hard_100_f5f8f9_1x100.png │ │ │ │ │ │ ├── ui-bg_inset-hard_100_fcfdfd_1x100.png │ │ │ │ │ │ ├── ui-icons_217bc0_256x240.png │ │ │ │ │ │ ├── ui-icons_2e83ff_256x240.png │ │ │ │ │ │ ├── ui-icons_469bdd_256x240.png │ │ │ │ │ │ ├── ui-icons_6da8d5_256x240.png │ │ │ │ │ │ ├── ui-icons_cd0a0a_256x240.png │ │ │ │ │ │ ├── ui-icons_d8e7f3_256x240.png │ │ │ │ │ │ └── ui-icons_f9bd01_256x240.png │ │ │ │ │ │ └── jquery-ui.css │ │ │ │ └── js │ │ │ │ │ ├── jquery-ui.min.js │ │ │ │ │ ├── jquery.metadata.js │ │ │ │ │ └── jquery.min.js │ │ │ ├── img │ │ │ │ └── cow_icon_01.png │ │ │ └── snd │ │ │ │ ├── ecto.mp3 │ │ │ │ ├── ecto1.mid │ │ │ │ ├── ecto1.mp3 │ │ │ │ ├── ecto2.mp3 │ │ │ │ └── sleigh.mp3 │ │ ├── models.py │ │ ├── scanner │ │ │ ├── __init__.py │ │ │ ├── bolt.py │ │ │ ├── default.py │ │ │ ├── html.py │ │ │ ├── image.py │ │ │ ├── imgur.py │ │ │ └── youtube.py │ │ ├── templates │ │ │ ├── 404.html │ │ │ ├── 500.html │ │ │ ├── base.html │ │ │ ├── base │ │ │ │ ├── banner.html │ │ │ │ ├── menu.html │ │ │ │ └── messages.html │ │ │ ├── memebot │ │ │ │ ├── browse.html │ │ │ │ ├── check-link.html │ │ │ │ ├── index.html │ │ │ │ ├── profile.html │ │ │ │ ├── rss-index.html │ │ │ │ ├── scanner │ │ │ │ │ └── rss │ │ │ │ │ │ ├── base.html │ │ │ │ │ │ ├── default.html │ │ │ │ │ │ ├── html.html │ │ │ │ │ │ ├── image-text.html │ │ │ │ │ │ ├── image.html │ │ │ │ │ │ ├── youtube-text.html │ │ │ │ │ │ └── youtube.html │ │ │ │ ├── scores.html │ │ │ │ └── view-link.html │ │ │ ├── registration │ │ │ │ └── login.html │ │ │ └── root │ │ │ │ ├── calc.html │ │ │ │ ├── index.html │ │ │ │ └── robots.txt │ │ ├── templatetags │ │ │ ├── __init__.py │ │ │ └── rss_filters.py │ │ ├── urls │ │ │ ├── __init__.py │ │ │ ├── accounts.py │ │ │ ├── memebot.py │ │ │ └── root.py │ │ ├── utils │ │ │ ├── __init__.py │ │ │ ├── blacklist.py │ │ │ ├── browser.py │ │ │ ├── locking.py │ │ │ ├── rss.py │ │ │ ├── text.py │ │ │ ├── tzdatetime.py │ │ │ └── xml.py │ │ └── views │ │ │ ├── __init__.py │ │ │ ├── accounts.py │ │ │ ├── memebot.py │ │ │ └── root.py │ │ ├── settings.py-sample │ │ └── urls.py ├── fix-wtf-broken-tags.sh ├── get_delicious_auth_keys.py ├── get_twiter_auth_keys.py ├── migrate_madcow_1to2.py └── wiki.md ├── doc └── pollmail.txt ├── madcow ├── __init__.py ├── conf │ ├── __init__.py │ ├── defaults.py │ └── response.grufti ├── include │ ├── BeautifulSoup.py │ ├── chardet │ │ ├── __init__.py │ │ ├── big5freq.py │ │ ├── big5prober.py │ │ ├── chardistribution.py │ │ ├── charsetgroupprober.py │ │ ├── charsetprober.py │ │ ├── codingstatemachine.py │ │ ├── constants.py │ │ ├── escprober.py │ │ ├── escsm.py │ │ ├── eucjpprober.py │ │ ├── euckrfreq.py │ │ ├── euckrprober.py │ │ ├── euctwfreq.py │ │ ├── euctwprober.py │ │ ├── gb2312freq.py │ │ ├── gb2312prober.py │ │ ├── hebrewprober.py │ │ ├── jisfreq.py │ │ ├── jpcntx.py │ │ ├── langbulgarianmodel.py │ │ ├── langcyrillicmodel.py │ │ ├── langgreekmodel.py │ │ ├── langhebrewmodel.py │ │ ├── langhungarianmodel.py │ │ ├── langthaimodel.py │ │ ├── latin1prober.py │ │ ├── mbcharsetprober.py │ │ ├── mbcsgroupprober.py │ │ ├── mbcssm.py │ │ ├── sbcharsetprober.py │ │ ├── sbcsgroupprober.py │ │ ├── sjisprober.py │ │ ├── universaldetector.py │ │ └── utf8prober.py │ ├── feedparser.py │ ├── fonts.zip │ ├── httplib2 │ │ ├── __init__.py │ │ └── iri2uri.py │ ├── irclib.py │ ├── oauth2 │ │ ├── __init__.py │ │ └── clients │ │ │ ├── __init__.py │ │ │ ├── imap.py │ │ │ └── smtp.py │ ├── oauthlib │ │ ├── __init__.py │ │ ├── common.py │ │ ├── oauth1 │ │ │ ├── __init__.py │ │ │ └── rfc5849 │ │ │ │ ├── __init__.py │ │ │ │ ├── endpoints │ │ │ │ ├── __init__.py │ │ │ │ ├── access_token.py │ │ │ │ ├── authorization.py │ │ │ │ ├── base.py │ │ │ │ ├── pre_configured.py │ │ │ │ ├── request_token.py │ │ │ │ └── resource.py │ │ │ │ ├── errors.py │ │ │ │ ├── parameters.py │ │ │ │ ├── request_validator.py │ │ │ │ ├── signature.py │ │ │ │ └── utils.py │ │ ├── oauth2 │ │ │ ├── __init__.py │ │ │ └── rfc6749 │ │ │ │ ├── __init__.py │ │ │ │ ├── clients │ │ │ │ ├── __init__.py │ │ │ │ ├── backend_application.py │ │ │ │ ├── base.py │ │ │ │ ├── legacy_application.py │ │ │ │ ├── mobile_application.py │ │ │ │ └── web_application.py │ │ │ │ ├── endpoints │ │ │ │ ├── __init__.py │ │ │ │ ├── authorization.py │ │ │ │ ├── base.py │ │ │ │ ├── pre_configured.py │ │ │ │ ├── resource.py │ │ │ │ ├── revocation.py │ │ │ │ └── token.py │ │ │ │ ├── errors.py │ │ │ │ ├── grant_types │ │ │ │ ├── __init__.py │ │ │ │ ├── authorization_code.py │ │ │ │ ├── base.py │ │ │ │ ├── client_credentials.py │ │ │ │ ├── implicit.py │ │ │ │ ├── refresh_token.py │ │ │ │ └── resource_owner_password_credentials.py │ │ │ │ ├── parameters.py │ │ │ │ ├── request_validator.py │ │ │ │ ├── tokens.py │ │ │ │ └── utils.py │ │ └── uri_validate.py │ ├── pyfiglet.py │ ├── pymegahal │ │ ├── db │ │ │ ├── megahal.aux │ │ │ ├── megahal.ban │ │ │ ├── megahal.swp │ │ │ ├── megahal.trn │ │ │ └── timecube.trn │ │ ├── megahal.c │ │ ├── megahal.h │ │ ├── python.c │ │ └── setup.py │ ├── requests │ │ ├── __init__.py │ │ ├── adapters.py │ │ ├── api.py │ │ ├── auth.py │ │ ├── cacert.pem │ │ ├── certs.py │ │ ├── compat.py │ │ ├── cookies.py │ │ ├── exceptions.py │ │ ├── hooks.py │ │ ├── models.py │ │ ├── packages │ │ │ ├── __init__.py │ │ │ ├── chardet │ │ │ │ ├── __init__.py │ │ │ │ ├── big5freq.py │ │ │ │ ├── big5prober.py │ │ │ │ ├── chardetect.py │ │ │ │ ├── chardistribution.py │ │ │ │ ├── charsetgroupprober.py │ │ │ │ ├── charsetprober.py │ │ │ │ ├── codingstatemachine.py │ │ │ │ ├── compat.py │ │ │ │ ├── constants.py │ │ │ │ ├── cp949prober.py │ │ │ │ ├── escprober.py │ │ │ │ ├── escsm.py │ │ │ │ ├── eucjpprober.py │ │ │ │ ├── euckrfreq.py │ │ │ │ ├── euckrprober.py │ │ │ │ ├── euctwfreq.py │ │ │ │ ├── euctwprober.py │ │ │ │ ├── gb2312freq.py │ │ │ │ ├── gb2312prober.py │ │ │ │ ├── hebrewprober.py │ │ │ │ ├── jisfreq.py │ │ │ │ ├── jpcntx.py │ │ │ │ ├── langbulgarianmodel.py │ │ │ │ ├── langcyrillicmodel.py │ │ │ │ ├── langgreekmodel.py │ │ │ │ ├── langhebrewmodel.py │ │ │ │ ├── langhungarianmodel.py │ │ │ │ ├── langthaimodel.py │ │ │ │ ├── latin1prober.py │ │ │ │ ├── mbcharsetprober.py │ │ │ │ ├── mbcsgroupprober.py │ │ │ │ ├── mbcssm.py │ │ │ │ ├── sbcharsetprober.py │ │ │ │ ├── sbcsgroupprober.py │ │ │ │ ├── sjisprober.py │ │ │ │ ├── universaldetector.py │ │ │ │ └── utf8prober.py │ │ │ └── urllib3 │ │ │ │ ├── __init__.py │ │ │ │ ├── _collections.py │ │ │ │ ├── connection.py │ │ │ │ ├── connectionpool.py │ │ │ │ ├── contrib │ │ │ │ ├── __init__.py │ │ │ │ ├── ntlmpool.py │ │ │ │ └── pyopenssl.py │ │ │ │ ├── exceptions.py │ │ │ │ ├── fields.py │ │ │ │ ├── filepost.py │ │ │ │ ├── packages │ │ │ │ ├── __init__.py │ │ │ │ ├── ordered_dict.py │ │ │ │ ├── six.py │ │ │ │ └── ssl_match_hostname │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── _implementation.py │ │ │ │ ├── poolmanager.py │ │ │ │ ├── request.py │ │ │ │ ├── response.py │ │ │ │ └── util.py │ │ ├── sessions.py │ │ ├── status_codes.py │ │ ├── structures.py │ │ └── utils.py │ ├── requests_oauthlib │ │ ├── __init__.py │ │ ├── compliance_fixes │ │ │ ├── __init__.py │ │ │ ├── facebook.py │ │ │ ├── linkedin.py │ │ │ └── weibo.py │ │ ├── oauth1_auth.py │ │ ├── oauth1_session.py │ │ ├── oauth2_auth.py │ │ ├── oauth2_session.py │ │ └── utils.py │ ├── simplejson │ │ ├── __init__.py │ │ ├── decoder.py │ │ ├── encoder.py │ │ ├── ordered_dict.py │ │ ├── scanner.py │ │ ├── tests │ │ │ ├── __init__.py │ │ │ ├── test_check_circular.py │ │ │ ├── test_decimal.py │ │ │ ├── test_decode.py │ │ │ ├── test_default.py │ │ │ ├── test_dump.py │ │ │ ├── test_encode_basestring_ascii.py │ │ │ ├── test_encode_for_html.py │ │ │ ├── test_fail.py │ │ │ ├── test_float.py │ │ │ ├── test_indent.py │ │ │ ├── test_pass1.py │ │ │ ├── test_pass2.py │ │ │ ├── test_pass3.py │ │ │ ├── test_recursion.py │ │ │ ├── test_scanstring.py │ │ │ ├── test_separators.py │ │ │ ├── test_speedups.py │ │ │ └── test_unicode.py │ │ └── tool.py │ ├── twisted │ │ ├── __init__.py │ │ ├── _version.py │ │ ├── internet │ │ │ ├── __init__.py │ │ │ ├── _baseprocess.py │ │ │ ├── abstract.py │ │ │ ├── address.py │ │ │ ├── base.py │ │ │ ├── defer.py │ │ │ ├── error.py │ │ │ ├── fdesc.py │ │ │ ├── interfaces.py │ │ │ ├── main.py │ │ │ ├── posixbase.py │ │ │ ├── process.py │ │ │ ├── protocol.py │ │ │ ├── reactor.py │ │ │ ├── selectreactor.py │ │ │ ├── ssl.py │ │ │ ├── tcp.py │ │ │ ├── threads.py │ │ │ ├── udp.py │ │ │ └── unix.py │ │ ├── persisted │ │ │ ├── __init__.py │ │ │ └── styles.py │ │ ├── python │ │ │ ├── __init__.py │ │ │ ├── compat.py │ │ │ ├── components.py │ │ │ ├── context.py │ │ │ ├── deprecate.py │ │ │ ├── failure.py │ │ │ ├── hashlib.py │ │ │ ├── hook.py │ │ │ ├── lockfile.py │ │ │ ├── log.py │ │ │ ├── reflect.py │ │ │ ├── runtime.py │ │ │ ├── threadable.py │ │ │ ├── threadpool.py │ │ │ ├── util.py │ │ │ └── versions.py │ │ └── words │ │ │ ├── __init__.py │ │ │ ├── _version.py │ │ │ └── protocols │ │ │ ├── __init__.py │ │ │ └── oscar.py │ ├── twitter │ │ ├── __init__.py │ │ ├── _file_cache.py │ │ ├── api.py │ │ ├── direct_message.py │ │ ├── error.py │ │ ├── hashtag.py │ │ ├── list.py │ │ ├── parse_tweet.py │ │ ├── status.py │ │ ├── trend.py │ │ ├── url.py │ │ └── user.py │ └── zope │ │ ├── __init__.py │ │ └── interface │ │ ├── __init__.py │ │ ├── adapter.py │ │ ├── advice.py │ │ ├── declarations.py │ │ ├── exceptions.py │ │ ├── interface.py │ │ ├── interfaces.py │ │ └── ro.py ├── modules │ ├── __init__.py │ ├── alias.py │ ├── area.py │ ├── artfart.py │ ├── bash.py │ ├── bbcnews.py │ ├── beer.py │ ├── bible.py │ ├── blog.py │ ├── calc.py │ ├── care.py │ ├── chuck.py │ ├── clock.py │ ├── cnn.py │ ├── company.py │ ├── dictionary.py │ ├── djmemebot.py │ ├── election.py │ ├── factoids.py │ ├── figlet.py │ ├── fmylife.py │ ├── google.py │ ├── grufti.py │ ├── inspirobot.py │ ├── jinx.py │ ├── joke.py │ ├── karma.py │ ├── learn.py │ ├── links.py │ ├── livejournal.py │ ├── lyrics.py │ ├── megahal.py │ ├── memebot.py │ ├── movie.py │ ├── notes.py │ ├── nslookup.py │ ├── pollmail.py │ ├── realname.py │ ├── roll.py │ ├── seen.py │ ├── slut.py │ ├── spellcheck.py │ ├── staff.py │ ├── steam.py │ ├── stockquote.py │ ├── summon.py │ ├── sunrise.py │ ├── texts.py │ ├── translate.py │ ├── trek.py │ ├── trump.py │ ├── twitter.py │ ├── urban.py │ ├── weather.py │ ├── webtender.py │ ├── welcome.py │ ├── wikihow.py │ ├── wikimedia.py │ ├── wikiquotes.py │ ├── wolfram.py │ ├── woot.py │ ├── xray.py │ ├── yelp.py │ └── youtube.py ├── protocol │ ├── __init__.py │ ├── aim.py │ ├── cli.py │ ├── ipython.py │ ├── irc.py │ ├── pysilc.py │ └── slack.py ├── tasks │ ├── __init__.py │ ├── ircops.py │ ├── pollmail.py │ └── tweets.py └── util │ ├── __init__.py │ ├── auth.py │ ├── color.py │ ├── encoding.py │ ├── gateway.py │ ├── google.py │ ├── http.py │ ├── imap.py │ ├── logging.py │ ├── shell.py │ ├── text.py │ └── wunderground.py ├── run-standalone-madcow ├── scripts └── madcow ├── setup.cfg └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # python bytecode 2 | *.pyo 3 | *.pyc 4 | 5 | # backups 6 | *.bak 7 | *?~ 8 | 9 | # other VCS 10 | .svn/ 11 | CVS/ 12 | RCS/ 13 | 14 | # common build artifacts 15 | *.class 16 | *.so 17 | *.dylib 18 | *.o 19 | *.d 20 | *.a 21 | 22 | # distutils output 23 | /build/ 24 | /dist/ 25 | /MANIFEST 26 | 27 | # dev stuff 28 | /test.py 29 | 30 | # git is not a place to backup releases plz 31 | *.tar.gz 32 | *.tar.bz2 33 | *.tgz 34 | *.tbz 35 | *.zip 36 | 37 | # data files when running in-place 38 | /settings.py 39 | /db/ 40 | /log/ 41 | /data/ 42 | 43 | # apple bullshit 44 | .DS_Store 45 | .localized 46 | .localized/ 47 | .metadata_never_index 48 | .TemporaryItems/ 49 | .DocumentRevisions-V100/ 50 | .Spotlight-V100/ 51 | .Trashes/ 52 | .fseventsd/ 53 | .vol/ 54 | ._* 55 | ._*/ 56 | 57 | # logging 58 | typescript 59 | nohup.out 60 | *.log 61 | 62 | # common tmp file/dirs 63 | foo 64 | foo/ 65 | foo.* 66 | foo.*/ 67 | bar 68 | bar/ 69 | bar.* 70 | bar.*/ 71 | 1 72 | 2 73 | 3 74 | tmp* 75 | tmp*/ 76 | work/ 77 | X.* 78 | X.*/ 79 | Y.* 80 | Y.*/ 81 | 1/ 82 | 2/ 83 | 3/ 84 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | graft * 2 | prune dist 3 | prune contrib/django-memebot 4 | exclude setup.cfg 5 | include README.md 6 | include ChangeLog 7 | include LICENSE 8 | include run-standalone-madcow 9 | -------------------------------------------------------------------------------- /contrib/django-memebot/.gitignore: -------------------------------------------------------------------------------- 1 | /gruntle/data 2 | /gruntle/settings.py 3 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/__init__.py -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/apache/wsgi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Apache+WSGI Bridge""" 4 | 5 | import errno 6 | import sys 7 | import os 8 | 9 | from django.core.handlers.wsgi import WSGIHandler 10 | 11 | class MemeBot(WSGIHandler): 12 | 13 | """WSGI application for memebot""" 14 | 15 | def __init__(self, *args, **kwargs): 16 | settings_filename = kwargs.pop('settings_filename', 'settings.py') 17 | 18 | # walk down, looking for settings file along the way 19 | project_dir = os.path.realpath(__file__) 20 | while True: 21 | project_dir = os.path.dirname(project_dir) 22 | if os.path.exists(os.path.join(project_dir, settings_filename)): 23 | break 24 | if project_dir in ('', os.sep): 25 | raise IOError(errno.ENOENT, os.strerror(errno.ENOENT), settings_filename) 26 | 27 | install_dir, project_name = os.path.split(project_dir) 28 | 29 | # add both the install and project dir to path if not already there 30 | for import_dir in project_dir, install_dir: 31 | if import_dir not in sys.path: 32 | sys.path.append(import_dir) 33 | 34 | # configure application 35 | sys.dont_write_bytecode = True 36 | os.environ['DJANGO_SETTINGS_MODULE'] = '%s.%s' % (project_name, os.path.splitext(settings_filename)[0]) 37 | super(MemeBot, self).__init__(*args, **kwargs) 38 | 39 | 40 | application = MemeBot() 41 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/bin/fixtimes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from itertools import * 4 | from operator import * 5 | from os.path import * 6 | import sys 7 | import os 8 | 9 | os.environ['DJANGO_SETTINGS_MODULE'] = 'gruntle.settings' 10 | prefix = dirname(abspath(__file__)) 11 | base = dirname(prefix) 12 | for dir in prefix, base: 13 | while dir in sys.path: 14 | sys.path.remove(dir) 15 | sys.path.insert(0, dir) 16 | sys.dont_write_bytecode = True 17 | 18 | from django.conf import settings 19 | from gruntle.memebot import models 20 | from django.db.models import get_models 21 | from django.db.models.fields import AutoField, DateTimeField 22 | 23 | def main(): 24 | for model in get_models(): 25 | fields, models = izip(*model._meta.get_fields_with_model()) 26 | fixes = set() 27 | for field in fields: 28 | for key in 'auto_now', 'auto_now_add': 29 | if getattr(field, key, False): 30 | setattr(field, key, True) 31 | fixes.add(field.attname) 32 | 33 | if fixes: 34 | news = model.objects.using('default').all() 35 | olds = model.objects.using('old').all() 36 | pk = model._meta.pk.attname 37 | pkget = attrgetter(pk) 38 | newpks = imap(pkget, news) 39 | oldpks = imap(pkget, olds) 40 | shared = set(oldpks) & set(newpks) 41 | olds = olds.filter(pk__in=shared) 42 | news = news.filter(pk__in=shared) 43 | lookupnew = {new.pk: new for new in news} 44 | for old in olds: 45 | new = lookupnew[old.pk] 46 | updates = {attr: getattr(old, attr) for attr in fixes} 47 | model.objects.filter(pk=new.pk).update(**updates) 48 | 49 | return 0 50 | 51 | if __name__ == '__main__': 52 | sys.exit(main()) 53 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/bin/migrate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from os.path import * 4 | import sys 5 | import os 6 | 7 | os.environ['DJANGO_SETTINGS_MODULE'] = 'gruntle.settings' 8 | prefix = dirname(abspath(__file__)) 9 | base = dirname(prefix) 10 | for dir in prefix, base: 11 | while dir in sys.path: 12 | sys.path.remove(dir) 13 | sys.path.insert(0, dir) 14 | sys.dont_write_bytecode = True 15 | 16 | from django.conf import settings 17 | from gruntle.memebot import models 18 | from django.db.models import get_models 19 | from django.db.models.fields import AutoField, DateTimeField 20 | 21 | def main(): 22 | for model in get_models(): 23 | olds = model.objects.using('old').all() 24 | news = model.objects.using('default').all() 25 | if olds.count() != news.count(): 26 | print model._meta, olds.count(), news.count() 27 | for new in news: 28 | new.delete() 29 | if olds.count() == 0: 30 | print 'empty:', model._meta 31 | else: 32 | fields = zip(*model._meta.get_fields_with_model())[0] 33 | keys = [] 34 | for field in fields: 35 | if isinstance(field, DateTimeField): 36 | field.auto_now_add = field.auto_now = False 37 | keys.append(field.attname) 38 | for old in olds: 39 | model.objects.using('default').create(**{key: getattr(old, key) for key in keys}) 40 | 41 | 42 | 43 | return 0 44 | 45 | if __name__ == '__main__': 46 | sys.exit(main()) 47 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """Run project manager tool in local environment""" 4 | 5 | import sys 6 | import os 7 | 8 | sys.dont_write_bytecode = True 9 | os.environ['DEV_SERVER'] = 'true' 10 | 11 | from django.core.management import execute_manager, setup_environ 12 | import settings 13 | 14 | def main(): 15 | """Command-line interface""" 16 | if len(sys.argv) == 2 and sys.argv[1] == 'runserver': 17 | sys.argv.append(settings.DEV_SERVER_ADDR) 18 | execute_manager(settings) 19 | 20 | if __name__ == '__main__': 21 | sys.exit(main()) 22 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/__init__.py -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/context_processors.py: -------------------------------------------------------------------------------- 1 | """MemeBot context processors""" 2 | 3 | from django.contrib.sites.models import Site 4 | from django.conf import settings 5 | 6 | current_site = Site.objects.get_current() 7 | 8 | def site(request): 9 | """Add information about the site to template contexts""" 10 | return {'site_name': current_site.name, 11 | 'site_domain': current_site.domain, 12 | 'site_style': settings.STYLE_NAME} 13 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/feeds/hugs.py: -------------------------------------------------------------------------------- 1 | """All links posted to #hugs""" 2 | 3 | from gruntle.memebot.feeds import BaseFeed 4 | 5 | class Feed(BaseFeed): 6 | 7 | title = '#hugs urls' 8 | description = __doc__ 9 | 10 | def filter(self, published_links): 11 | """Filter published links to the ones we care about""" 12 | return published_links.filter(source__type='slack', source__name='hugs') 13 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/feeds/images.py: -------------------------------------------------------------------------------- 1 | """All images posted to #hugs (resized and cached locally)""" 2 | 3 | from gruntle.memebot.feeds import hugs 4 | 5 | class Feed(hugs.Feed): 6 | 7 | title = '#hugs images' 8 | description = __doc__ 9 | 10 | def filter(self, published_links): 11 | """Filter published links to the ones we care about""" 12 | links = super(Feed, self).filter(published_links) 13 | return links.filter(content_type__startswith='image/') 14 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/feeds/text.py: -------------------------------------------------------------------------------- 1 | """All links posted to #hugs, text-only SFW version""" 2 | 3 | from gruntle.memebot.feeds import hugs 4 | 5 | class Feed(hugs.Feed): 6 | 7 | title = hugs.Feed.title + ' [text]' 8 | description = __doc__ 9 | format = 'text' 10 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/management/__init__.py: -------------------------------------------------------------------------------- 1 | """Some management signal handlers""" 2 | 3 | from django.contrib.sites import models as sites_app 4 | from django.db.models import signals 5 | from django.conf import settings 6 | 7 | from gruntle.memebot.utils import get_domain 8 | 9 | DEFAULT_DOMAIN = get_domain() 10 | DEFAULT_NAME = 'MemeBot' 11 | 12 | def set_site(created_models, interactive, **kwargs): 13 | """Prompt user to set SITE specific properties""" 14 | if sites_app.Site in created_models: 15 | domain = DEFAULT_DOMAIN 16 | name = DEFAULT_NAME 17 | if interactive: 18 | domain = raw_input('Site domain [%s]: ' % domain) or domain 19 | name = raw_input('Site name [%s]: ' % name) or name 20 | site, created = sites_app.Site.objects.get_or_create(id=settings.SITE_ID) 21 | site.domain = domain 22 | site.name = name 23 | site.save() 24 | sites_app.Site.objects.clear_cache() 25 | 26 | signals.post_syncdb.connect(set_site, sender=sites_app, dispatch_uid='set_site') 27 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/management/commands/__init__.py -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/management/commands/rebuild.py: -------------------------------------------------------------------------------- 1 | """Rebuilds the RSS feed""" 2 | 3 | from optparse import make_option 4 | import sys 5 | from django.core.management.base import NoArgsCommand, CommandError 6 | from django.conf import settings 7 | from gruntle.memebot.exceptions import LockError 8 | from gruntle.memebot import feeds 9 | 10 | class Command(NoArgsCommand): 11 | 12 | help = __doc__ 13 | 14 | option_list = (make_option('-q', dest='log_stream', default=sys.stderr, action='store_const', const=None, 15 | help="don't log messages to console"), 16 | make_option('-f', dest='force', default=False, action='store_true', help='force rss generation'), 17 | ) + NoArgsCommand.option_list 18 | 19 | def handle_noargs(self, log_stream=None, force=False, **kwargs): 20 | try: 21 | feeds.run(log_stream=log_stream, force=force) 22 | except LockError, exc: 23 | raise CommandError(exc) 24 | except KeyboardInterrupt: 25 | print '\nCancelled' 26 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/management/commands/updater.py: -------------------------------------------------------------------------------- 1 | """Automatically scans for new links and rebuilds RSS""" 2 | 3 | from optparse import make_option 4 | 5 | import time 6 | import sys 7 | 8 | from django.core.management.base import NoArgsCommand, CommandError 9 | from django.conf import settings 10 | 11 | from gruntle.memebot.utils import human_readable_duration 12 | from gruntle.memebot.exceptions import TrapError, TrapErrors 13 | from gruntle.memebot.decorators import locked, logged 14 | from gruntle.memebot import scanner, feeds 15 | 16 | class Command(NoArgsCommand): 17 | 18 | help = __doc__ 19 | option_list = ( 20 | make_option('-i', '--interval', metavar='', type='int', default=settings.UPDATER_INTERVAL, 21 | help='how often to process (default: %default)'), 22 | ) + NoArgsCommand.option_list 23 | 24 | def handle_noargs(self, interval=None, **kwargs): 25 | if interval is None: 26 | interval = settings.UPDATER_INTERVAL 27 | try: 28 | with TrapErrors(): 29 | self.run(interval, log_stream=sys.stdout) 30 | except KeyboardInterrupt: 31 | raise CommandError('Interrupted') 32 | except TrapError, exc: 33 | raise CommandError(exc.args[1]) 34 | 35 | @logged('updater', append=True, method=True) 36 | @locked('updater', 0) 37 | def run(self, interval): 38 | self.log.info('Starting updater service') 39 | last_update = 0 40 | while True: 41 | now = time.time() 42 | sleep = interval + last_update - now 43 | if sleep > 0: 44 | self.log.info('Sleeping for %s', human_readable_duration(sleep)) 45 | time.sleep(sleep) 46 | try: 47 | with TrapErrors(): 48 | scanner.run(logger=self.log) 49 | feeds.run(logger=self.log, force=False) 50 | except TrapError, exc: 51 | self.log.error('Processing Error', exc_info=exc.args) 52 | last_update = now 53 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/css/dashboard.css: -------------------------------------------------------------------------------- 1 | /* DASHBOARD */ 2 | 3 | .dashboard .module table th { 4 | width: 100%; 5 | } 6 | 7 | .dashboard .module table td { 8 | white-space: nowrap; 9 | } 10 | 11 | .dashboard .module table td a { 12 | display: block; 13 | padding-right: .6em; 14 | } 15 | 16 | /* RECENT ACTIONS MODULE */ 17 | 18 | .module ul.actionlist { 19 | margin-left: 0; 20 | } 21 | 22 | ul.actionlist li { 23 | list-style-type: none; 24 | } 25 | 26 | ul.actionlist li.changelink { 27 | overflow: hidden; 28 | text-overflow: ellipsis; 29 | -o-text-overflow: ellipsis; 30 | } -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/css/ie.css: -------------------------------------------------------------------------------- 1 | /* IE 6 & 7 */ 2 | 3 | /* Proper fixed width for dashboard in IE6 */ 4 | 5 | .dashboard #content { 6 | *width: 768px; 7 | } 8 | 9 | .dashboard #content-main { 10 | *width: 535px; 11 | } 12 | 13 | /* IE 6 ONLY */ 14 | 15 | /* Keep header from flowing off the page */ 16 | 17 | #container { 18 | _position: static; 19 | } 20 | 21 | /* Put the right sidebars back on the page */ 22 | 23 | .colMS #content-related { 24 | _margin-right: 0; 25 | _margin-left: 10px; 26 | _position: static; 27 | } 28 | 29 | /* Put the left sidebars back on the page */ 30 | 31 | .colSM #content-related { 32 | _margin-right: 10px; 33 | _margin-left: -115px; 34 | _position: static; 35 | } 36 | 37 | .form-row { 38 | _height: 1%; 39 | } 40 | 41 | /* Fix right margin for changelist filters in IE6 */ 42 | 43 | #changelist-filter ul { 44 | _margin-right: -10px; 45 | } 46 | 47 | /* IE ignores min-height, but treats height as if it were min-height */ 48 | 49 | .change-list .filtered { 50 | _height: 400px; 51 | } 52 | 53 | /* IE doesn't know alpha transparency in PNGs */ 54 | 55 | .inline-deletelink { 56 | background: transparent url(../img/admin/inline-delete-8bit.png) no-repeat; 57 | } -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/css/login.css: -------------------------------------------------------------------------------- 1 | /* LOGIN FORM */ 2 | 3 | body.login { 4 | background: #eee; 5 | } 6 | 7 | .login #container { 8 | background: white; 9 | border: 1px solid #ccc; 10 | width: 28em; 11 | min-width: 300px; 12 | margin-left: auto; 13 | margin-right: auto; 14 | margin-top: 100px; 15 | } 16 | 17 | .login #content-main { 18 | width: 100%; 19 | } 20 | 21 | .login form { 22 | margin-top: 1em; 23 | } 24 | 25 | .login .form-row { 26 | padding: 4px 0; 27 | float: left; 28 | width: 100%; 29 | } 30 | 31 | .login .form-row label { 32 | float: left; 33 | width: 9em; 34 | padding-right: 0.5em; 35 | line-height: 2em; 36 | text-align: right; 37 | font-size: 1em; 38 | color: #333; 39 | } 40 | 41 | .login .form-row #id_username, .login .form-row #id_password { 42 | width: 14em; 43 | } 44 | 45 | .login span.help { 46 | font-size: 10px; 47 | display: block; 48 | } 49 | 50 | .login .submit-row { 51 | clear: both; 52 | padding: 1em 0 0 9.4em; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/arrow-down.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/arrow-down.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/arrow-up.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/arrow-up.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/changelist-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/changelist-bg.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/changelist-bg_rtl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/changelist-bg_rtl.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/chooser-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/chooser-bg.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/chooser_stacked-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/chooser_stacked-bg.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/default-bg-reverse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/default-bg-reverse.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/default-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/default-bg.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/deleted-overlay.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/deleted-overlay.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon-no.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon-no.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon-unknown.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon-unknown.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon-yes.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon-yes.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_addlink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_addlink.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_alert.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_alert.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_calendar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_calendar.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_changelink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_changelink.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_clock.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_clock.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_deletelink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_deletelink.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_error.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_error.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_searchbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_searchbox.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_success.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/icon_success.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/inline-delete-8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/inline-delete-8bit.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/inline-delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/inline-delete.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/inline-restore-8bit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/inline-restore-8bit.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/inline-restore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/inline-restore.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/inline-splitter-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/inline-splitter-bg.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/nav-bg-grabber.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/nav-bg-grabber.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/nav-bg-reverse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/nav-bg-reverse.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/nav-bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/nav-bg.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/selector-add.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/selector-add.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/selector-addall.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/selector-addall.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/selector-remove.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/selector-remove.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/selector-removeall.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/selector-removeall.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/selector-search.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/selector-search.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/selector_stacked-add.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/selector_stacked-add.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/selector_stacked-remove.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/selector_stacked-remove.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tool-left.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tool-left.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tool-left_over.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tool-left_over.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tool-right.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tool-right.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tool-right_over.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tool-right_over.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tooltag-add.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tooltag-add.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tooltag-add_over.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tooltag-add_over.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tooltag-arrowright.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tooltag-arrowright.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tooltag-arrowright_over.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/admin/tooltag-arrowright_over.gif -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/gis/move_vertex_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/gis/move_vertex_off.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/img/gis/move_vertex_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/admin/img/gis/move_vertex_on.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/js/LICENSE-JQUERY.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 John Resig, http://jquery.com/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/js/collapse.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | $(document).ready(function() { 3 | // Add anchor tag for Show/Hide link 4 | $("fieldset.collapse").each(function(i, elem) { 5 | // Don't hide if fields in this fieldset have errors 6 | if ( $(elem).find("div.errors").length == 0 ) { 7 | $(elem).addClass("collapsed"); 8 | $(elem).find("h2").first().append(' (' + gettext("Show") + 10 | ')'); 11 | } 12 | }); 13 | // Add toggle to anchor tag 14 | $("fieldset.collapse a.collapse-toggle").toggle( 15 | function() { // Show 16 | $(this).text(gettext("Hide")); 17 | $(this).closest("fieldset").removeClass("collapsed"); 18 | return false; 19 | }, 20 | function() { // Hide 21 | $(this).text(gettext("Show")); 22 | $(this).closest("fieldset").addClass("collapsed"); 23 | return false; 24 | } 25 | ); 26 | }); 27 | })(django.jQuery); 28 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/js/collapse.min.js: -------------------------------------------------------------------------------- 1 | (function(a){a(document).ready(function(){a("fieldset.collapse").each(function(c,b){if(a(b).find("div.errors").length==0){a(b).addClass("collapsed");a(b).find("h2").first().append(' ('+gettext("Show")+")")}});a("fieldset.collapse a.collapse-toggle").toggle(function(){a(this).text(gettext("Hide"));a(this).closest("fieldset").removeClass("collapsed");return false},function(){a(this).text(gettext("Show"));a(this).closest("fieldset").addClass("collapsed"); 2 | return false})})})(django.jQuery); 3 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/js/compress.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import optparse 4 | import subprocess 5 | import sys 6 | 7 | here = os.path.dirname(__file__) 8 | 9 | def main(): 10 | usage = "usage: %prog [file1..fileN]" 11 | description = """With no file paths given this script will automatically 12 | compress all jQuery-based files of the admin app. Requires the Google Closure 13 | Compiler library and Java version 6 or later.""" 14 | parser = optparse.OptionParser(usage, description=description) 15 | parser.add_option("-c", dest="compiler", default="~/bin/compiler.jar", 16 | help="path to Closure Compiler jar file") 17 | parser.add_option("-v", "--verbose", 18 | action="store_true", dest="verbose") 19 | parser.add_option("-q", "--quiet", 20 | action="store_false", dest="verbose") 21 | (options, args) = parser.parse_args() 22 | 23 | compiler = os.path.expanduser(options.compiler) 24 | if not os.path.exists(compiler): 25 | sys.exit("Google Closure compiler jar file %s not found. Please use the -c option to specify the path." % compiler) 26 | 27 | if not args: 28 | if options.verbose: 29 | sys.stdout.write("No filenames given; defaulting to admin scripts\n") 30 | args = [os.path.join(here, f) for f in [ 31 | "actions.js", "collapse.js", "inlines.js", "prepopulate.js"]] 32 | 33 | for arg in args: 34 | if not arg.endswith(".js"): 35 | arg = arg + ".js" 36 | to_compress = os.path.expanduser(arg) 37 | if os.path.exists(to_compress): 38 | to_compress_min = "%s.min.js" % "".join(arg.rsplit(".js")) 39 | cmd = "java -jar %s --js %s --js_output_file %s" % (compiler, to_compress, to_compress_min) 40 | if options.verbose: 41 | sys.stdout.write("Running: %s\n" % cmd) 42 | subprocess.call(cmd.split()) 43 | else: 44 | sys.stdout.write("File %s not found. Sure it exists?\n" % to_compress) 45 | 46 | if __name__ == '__main__': 47 | main() 48 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/js/jquery.init.js: -------------------------------------------------------------------------------- 1 | // Puts the included jQuery into our own namespace 2 | var django = { 3 | "jQuery": jQuery.noConflict(true) 4 | }; 5 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/js/prepopulate.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | $.fn.prepopulate = function(dependencies, maxLength) { 3 | /* 4 | Depends on urlify.js 5 | Populates a selected field with the values of the dependent fields, 6 | URLifies and shortens the string. 7 | dependencies - array of dependent fields id's 8 | maxLength - maximum length of the URLify'd string 9 | */ 10 | return this.each(function() { 11 | var field = $(this); 12 | 13 | field.data('_changed', false); 14 | field.change(function() { 15 | field.data('_changed', true); 16 | }); 17 | 18 | var populate = function () { 19 | // Bail if the fields value has changed 20 | if (field.data('_changed') == true) return; 21 | 22 | var values = []; 23 | $.each(dependencies, function(i, field) { 24 | if ($(field).val().length > 0) { 25 | values.push($(field).val()); 26 | } 27 | }) 28 | field.val(URLify(values.join(' '), maxLength)); 29 | }; 30 | 31 | $(dependencies.join(',')).keyup(populate).change(populate).focus(populate); 32 | }); 33 | }; 34 | })(django.jQuery); 35 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/admin/js/prepopulate.min.js: -------------------------------------------------------------------------------- 1 | (function(a){a.fn.prepopulate=function(d,g){return this.each(function(){var b=a(this);b.data("_changed",false);b.change(function(){b.data("_changed",true)});var c=function(){if(b.data("_changed")!=true){var e=[];a.each(d,function(h,f){a(f).val().length>0&&e.push(a(f).val())});b.val(URLify(e.join(" "),g))}};a(d.join(",")).keyup(c).change(c).focus(c)})}})(django.jQuery); 2 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/css/rss.css: -------------------------------------------------------------------------------- 1 | /* rss css */ 2 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_flat_55_fbec88_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_flat_55_fbec88_40x100.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_glass_85_dfeffc_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_glass_85_dfeffc_1x400.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_glass_95_fef1ec_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_glass_95_fef1ec_1x400.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-icons_217bc0_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-icons_217bc0_256x240.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-icons_469bdd_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-icons_469bdd_256x240.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-icons_6da8d5_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-icons_6da8d5_256x240.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-icons_d8e7f3_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-icons_d8e7f3_256x240.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-icons_f9bd01_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/external/css/redmond/images/ui-icons_f9bd01_256x240.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/img/cow_icon_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/img/cow_icon_01.png -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/snd/ecto.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/snd/ecto.mp3 -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/snd/ecto1.mid: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/snd/ecto1.mid -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/snd/ecto1.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/snd/ecto1.mp3 -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/snd/ecto2.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/snd/ecto2.mp3 -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/media/snd/sleigh.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/media/snd/sleigh.mp3 -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/scanner/bolt.py: -------------------------------------------------------------------------------- 1 | """Extract image from gallery view of imgur links, but grab the title on the way""" 2 | 3 | from gruntle.memebot.scanner.image import ImageScanner 4 | from gruntle.memebot.exceptions import InvalidContent, trapped 5 | 6 | class BoltScanner(ImageScanner): 7 | 8 | url_match = {'netloc_regex': r'^reddit.bo.lt$', 'netloc_ignorecase': True} 9 | 10 | def handle(self, response, log, browser): 11 | with trapped: 12 | url = response.data.body.find('img', style="max-width: 100%")['src'] 13 | response = browser.open(url, follow_meta_redirect=True) 14 | return super(BoltScanner, self).handle(response, log, browser) 15 | raise InvalidContent(response, 'could not parse image from bolt page') 16 | 17 | 18 | scanner = BoltScanner() 19 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/scanner/default.py: -------------------------------------------------------------------------------- 1 | """Should be called last, if nothing can do a better job with the URL""" 2 | 3 | from gruntle.memebot.scanner import Scanner, ScanResult 4 | 5 | class DefaultScanner(Scanner): 6 | 7 | rss_templates = {None: 'memebot/scanner/rss/default.html'} 8 | 9 | def handle(self, response, log, browser): 10 | return ScanResult(response=response, 11 | override_url=None, 12 | title=None, 13 | content_type=None, 14 | content=None, 15 | attr=None) 16 | 17 | 18 | scanner = DefaultScanner() 19 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/scanner/imgur.py: -------------------------------------------------------------------------------- 1 | """Extract image from gallery view of imgur links, but grab the title on the way""" 2 | 3 | from gruntle.memebot.utils.browser import render_node, strip_site_name 4 | from gruntle.memebot.utils.browser import decode_entities 5 | from gruntle.memebot.scanner.image import ImageScanner 6 | from gruntle.memebot.exceptions import InvalidContent, trapped 7 | from gruntle.memebot.scanner import ScanResult 8 | 9 | class IMGurScanner(ImageScanner): 10 | 11 | url_match = {'netloc_regex': r'^(?:www\.)?imgur\.com$', 'netloc_ignorecase': True} 12 | 13 | def handle(self, response, log, browser): 14 | if response.data_type != 'soup': 15 | raise InvalidContent(response, 'Not an HTML file') 16 | soup = response.data 17 | 18 | title = None 19 | with trapped: 20 | title = strip_site_name(render_node(soup.head.title), response.url) 21 | 22 | with trapped: 23 | url = soup.head.find('link', rel='image_src')['href'] 24 | response = browser.open(url, follow_meta_redirect=True) 25 | result = super(IMGurScanner, self).handle(response, log, browser) 26 | return ScanResult(response=result.response, 27 | override_url=result.override_url, 28 | title=result.title if title is None else title, 29 | content_type=result.content_type, 30 | content=result.content, 31 | attr=result.attr) 32 | 33 | raise InvalidContent(response, "Couldn't find the image") 34 | 35 | 36 | scanner = IMGurScanner() 37 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Page Not Found{% endblock %} 3 | {% block content %} 4 |
5 |

Sorry, the page you requested could not be found.

6 |
7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/500.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Internal Server Error{% endblock %} 3 | {% block content %} 4 |
5 |

Sorry, something seems to have broken. Click something different, maybe.

6 |
7 | {% endblock %} 8 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block title %}{{ site_domain }}{% endblock %} - {{ site_name }} 6 | 7 | 8 | {% ifnotequal site_style "main" %} 9 | 10 | {% endifnotequal %} 11 | {% block styles %}{% endblock %} 12 | 13 | 14 | 15 | {% block scripts %}{% endblock %} 16 | {% block headers %}{% endblock %} 17 | 18 | 19 |
20 | 21 | 22 | 23 |
{% include "base/messages.html" %}
24 |
{% block helpers %}{% endblock %}
25 |
{% block content %}{% endblock %}
26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/base/banner.html: -------------------------------------------------------------------------------- 1 | {{ site_name }} 2 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/base/menu.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/base/messages.html: -------------------------------------------------------------------------------- 1 | {# this is automatically populated by context processors #} 2 | {% if messages %} 3 | 8 | {% endif %} 9 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/memebot/browse.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}browse{% endblock %} 3 | {% block head %} 4 | 5 | 11 | {% endblock %} 12 | {% block content %} 13 |
14 | 15 | 16 | 17 | {% for link in links %} 18 | 19 | 20 | 21 | 22 | 23 | {% endfor %} 24 | 25 |
{{ link.user.username }}{{ link.created|date:"Y-m-d H:i:s" }}{{ link.url }}
26 |
27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/memebot/check-link.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Check URL{% endblock %} 3 | {% block content %} 4 |

Check URL

5 | 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/memebot/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}home{% endblock %} 4 | 5 | {% block scripts %} 6 | 31 | {% endblock %} 32 | 33 | {% block helpers %} 34 |
Are you sure?
35 | {% endblock %} 36 | 37 | {% block content %} 38 | 39 |
40 | 50 |
51 | 52 | {% endblock %} 53 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/memebot/profile.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}edit profile{% endblock %} 3 | {% block content %} 4 |
5 |
6 | {% csrf_token %} 7 | {{ form.as_p }} 8 | 9 |
10 |
11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/memebot/rss-index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load rss_filters %} 3 | {% block title %}available rss feeds{% endblock %} 4 | 5 | {% comment %} 6 | {% block breadcrumbs %} 7 | home › rss 8 | {% endblock %} 9 | {% endcomment %} 10 | 11 | {% block content %} 12 |

RSS Feeds

13 | 18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/memebot/scanner/rss/base.html: -------------------------------------------------------------------------------- 1 | {% spaceless %} 2 |
{% block content %}{% endblock %}
3 | {% endspaceless %} 4 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/memebot/scanner/rss/default.html: -------------------------------------------------------------------------------- 1 | {% extends "memebot/scanner/rss/base.html" %} 2 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/memebot/scanner/rss/html.html: -------------------------------------------------------------------------------- 1 | {% extends "memebot/scanner/rss/base.html" %} 2 | {% spaceless %} 3 | {% block content %}{{ link.content }}{% endblock %} 4 | {% endspaceless %} 5 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/memebot/scanner/rss/image-text.html: -------------------------------------------------------------------------------- 1 | {% extends "memebot/scanner/rss/base.html" %} 2 | {% load rss_filters %} 3 | {% spaceless %} 4 | {% block content %} 5 | 6 | Image: [{{ link.attr.size|readable_size }}] {{ link.attr.width }}x{{ link.attr.height }} {{ link.attr.format }} 7 | {% if link.attr.info %} 8 |
9 |

{{ link.attr.info|pretty_repr }}

10 | {% endif %} 11 | {% endblock %} 12 | {% endspaceless %} 13 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/memebot/scanner/rss/image.html: -------------------------------------------------------------------------------- 1 | {% extends "memebot/scanner/rss/base.html" %} 2 | {% spaceless %} 3 | {% block content %} 4 | 5 | {% endblock %} 6 | {% endspaceless %} 7 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/memebot/scanner/rss/youtube-text.html: -------------------------------------------------------------------------------- 1 | {% extends "memebot/scanner/rss/base.html" %} 2 | {% load rss_filters %} 3 | {% spaceless %} 4 | {% block content %} 5 | {% if link.attr.uploader %}

{{ link.attr.uploader }}

{% endif %} 6 | {% if link.attr.summary %}

{{ link.attr.summary|summarize }}

{% endif %} 7 | 12 | {% endblock %} 13 | {% endspaceless %} 14 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/memebot/scanner/rss/youtube.html: -------------------------------------------------------------------------------- 1 | {% extends "memebot/scanner/rss/base.html" %} 2 | {% load rss_filters %} 3 | {% spaceless %} 4 | {% block content %} 5 |
6 | {% if link.attr.uploader %}

{{ link.attr.uploader }}

{% endif %} 7 | {% if link.attr.summary %}

{{ link.attr.summary|summarize }}

{% endif %} 8 | 13 | {% endblock %} 14 | {% endspaceless %} 15 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/memebot/scores.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}scores{% endblock %} 3 | {% block content %} 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {% for profile in profiles %} 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | {% endfor %} 25 | 26 |
scorenicklinksrepostscredits
{{ profile.score }}{{ profile.user.username }}{{ profile.posted_new }}{{ profile.posted_old }}{{ profile.reposts }}
27 |
28 | {% endblock %} 29 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}login{% endblock %} 3 | {% block content %} 4 |

login

5 |
6 | {% csrf_token %} 7 | {{ form.as_p }} 8 | 9 | 10 |
11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/root/calc.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Minecraft Time Calc{% endblock %} 3 | {% block content %} 4 |

Minecraft Time Calc

5 |
6 |
7 | {% csrf_token %} 8 | {{ form.as_p }} 9 | 10 |
11 | {% if seconds != None %} 12 |

time = {{ seconds }}

13 | {% endif %} 14 |
15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templates/root/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /media/ 3 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/templatetags/__init__.py -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/urls/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/urls/__init__.py -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/urls/accounts.py: -------------------------------------------------------------------------------- 1 | """Accounts URL config""" 2 | 3 | from django.conf.urls.defaults import * 4 | 5 | urlpatterns = patterns('django.contrib.auth.views', 6 | url('^login/$', 'login', name='accounts-login'), 7 | url('^logout/$', 'logout_then_login', name='accounts-logout'), 8 | ) 9 | 10 | urlpatterns += patterns('gruntle.memebot.views.accounts', 11 | url(r'^profile/$', 'view_profile', name='accounts-view-profile'), 12 | url(r'^profile/edit/$', 'edit_profile', name='accounts-edit-profile'), 13 | ) 14 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/urls/memebot.py: -------------------------------------------------------------------------------- 1 | """MemeBot URL config""" 2 | 3 | from django.conf.urls.defaults import * 4 | 5 | urlpatterns = patterns('gruntle.memebot.views.memebot', 6 | url(r'^$', 'view_index', name='memebot-view-index'), 7 | url(r'^scores/$', 'view_scores', name='memebot-view-scores'), 8 | url(r'^browse/$', 'browse_links', name='memebot-browse-links'), 9 | url(r'^link/$', 'check_link', name='memebot-check-link'), 10 | url(r'^link/(?P\d+)/$', 'view_link', name='memebot-view-link'), 11 | url(r'^link/(?P\d+)/content/$', 'view_link_content', name='memebot-view-link-content'), 12 | url(r'^rss/$', 'view_rss_index', name='memebot-view-rss-index'), 13 | url(r'^rss/(?P[a-zA-Z0-9_]+).xml$', 'view_rss', name='memebot-view-rss'), 14 | ) 15 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/urls/root.py: -------------------------------------------------------------------------------- 1 | """Root URL config""" 2 | 3 | from django.conf.urls.defaults import * 4 | 5 | urlpatterns = patterns('gruntle.memebot.views.root', 6 | url(r'^$', 'view_index', name='root-view-index'), 7 | url(r'^robots.txt$', 'view_robots', name='root-view-robots'), 8 | url(r'^calc$', 'view_calc', name='root-view-calc'), 9 | 10 | # roll our own 404 to get some control over it 11 | url('^(?:memebot|accounts|admin)/', 'friendly_404', name='root-friendly-404'), 12 | url('', 'harsh_404', name='root-harsh-404'), 13 | ) 14 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/views/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/contrib/django-memebot/gruntle/memebot/views/__init__.py -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/views/accounts.py: -------------------------------------------------------------------------------- 1 | """Accounts management views""" 2 | 3 | from django.views.generic.simple import direct_to_template 4 | from django.contrib.auth.decorators import login_required 5 | from django.http import Http404 6 | from gruntle.memebot.forms import EditProfileForm 7 | 8 | @login_required 9 | def edit_profile(request): 10 | """Update user profile""" 11 | if request.method == 'POST': 12 | form = EditProfileForm(request.POST, instance=request.user) 13 | if form.is_valid(): 14 | form.save() 15 | request.user.message_set.create(message='Your profile has been updated') 16 | else: 17 | form = EditProfileForm(instance=request.user) 18 | return direct_to_template(request, 'memebot/profile.html', {'form': form}) 19 | 20 | 21 | @login_required 22 | def view_profile(request): 23 | raise Http404 24 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/memebot/views/root.py: -------------------------------------------------------------------------------- 1 | """View functions for root of site""" 2 | 3 | import time 4 | 5 | from django.views.generic.simple import direct_to_template 6 | from django.http import HttpResponse, Http404 7 | from gruntle.memebot.forms import AMPMTimeForm 8 | 9 | def view_index(request): 10 | """Front page""" 11 | return direct_to_template(request, 'root/index.html', {}) 12 | 13 | 14 | def view_robots(request): 15 | """View the site robots.txt file""" 16 | return direct_to_template(request, 'root/robots.txt', mimetype='text/plain') 17 | 18 | 19 | def friendly_404(request): 20 | """Raise 404 normally, uses 404.html template with site style""" 21 | raise Http404 22 | 23 | 24 | def harsh_404(request): 25 | """Spartan 404 that reveaals notthing about the site, used when people are digging""" 26 | return HttpResponse('no.', 'text/plain', 404) 27 | 28 | 29 | def view_calc(request): 30 | """MInecraft time calculator""" 31 | seconds = None 32 | if request.method == 'POST': 33 | form = AMPMTimeForm(request.POST) 34 | if form.is_valid(): 35 | try: 36 | seconds = _convert_minecraft_time(form.cleaned_data['hour'], 37 | form.cleaned_data['minute'], 38 | form.cleaned_data['phase']) 39 | except: 40 | pass 41 | 42 | else: 43 | form = AMPMTimeForm() 44 | return direct_to_template(request, 'root/calc.html', {'form': form, 'seconds': seconds}) 45 | 46 | 47 | def _convert_minecraft_time(h, m, p): 48 | ts = time.strptime('%02d:%02d %s' % (h, m, p), '%I:%M %p') 49 | h = ts.tm_hour - 6 50 | if h < 0: 51 | h += 24 52 | return h * 1000 + ts.tm_min * 1000 / 60 53 | -------------------------------------------------------------------------------- /contrib/django-memebot/gruntle/urls.py: -------------------------------------------------------------------------------- 1 | """Site URL config""" 2 | 3 | from django.conf.urls.defaults import * 4 | from django.contrib import admin 5 | from django.conf import settings 6 | 7 | admin.autodiscover() 8 | 9 | urlpatterns = patterns('', 10 | url(r'^memebot/', include('gruntle.memebot.urls.memebot')), 11 | url(r'^accounts/', include('gruntle.memebot.urls.accounts')), 12 | #url(r'^admin/doc/', include('django.contrib.admindocs.urls')), 13 | url(r'^admin/', include(admin.site.urls)), 14 | ) 15 | 16 | if settings.DEV_SERVER: 17 | import re 18 | urlpatterns += patterns('django.views', 19 | url(r'^%s(?P.*)' % re.escape(settings.MEDIA_URL[1:]), 'static.serve', 20 | {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}), 21 | ) 22 | 23 | 24 | # check here before 404'ing 25 | urlpatterns += patterns('', 26 | url(r'', include('gruntle.memebot.urls.root')), 27 | ) 28 | -------------------------------------------------------------------------------- /contrib/fix-wtf-broken-tags.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh - 2 | # re-adds all the tags that are all.. weird. so they are no longer.. weird. 3 | printf "don't just run this without looking at what it does\n" 1>&2 4 | tput bel 5 | exit 255 6 | 7 | set -ef +xva -- 8 | 9 | head="$(git rev-parse HEAD)" 10 | git for-each-ref refs/tags | \ 11 | while read -r hash type refname 12 | do 13 | if test x"$type" = xcommit 14 | then 15 | tag="${refname#refs/tags/}" 16 | if test x"$hash" = x"$(git rev-parse "$tag")" 17 | then 18 | realhash="$(git merge-base "$hash" "$head")" 19 | if test x"$realhash" != x"$hash" 20 | then 21 | printf "%s -> %s\n" "$(git name-rev "$realhash")" "$tag" 1>&2 22 | IFS="" read -r author <<-__SHOW__ 23 | $(git show -s --date=raw --pretty=tformat:"%an <%ae> %ad" "$realhash") 24 | __SHOW__ 25 | tagid="$( 26 | git mktag <<-__TAG__ 27 | object $realhash 28 | type commit 29 | tag $tag 30 | tagger $author 31 | 32 | release $tag 33 | __TAG__ 34 | )" 35 | if test x"$tagid" = x 36 | then 37 | printf "failed to create tag somehow..\n" 1>&2 38 | exit 1 39 | fi 40 | git tag -d "$tag" && \ 41 | git update-ref refs/tags/"$tag" "$tagid" "" 42 | printf "fixed tag: %s\n" "$tag" 43 | 44 | fi 45 | fi 46 | fi 47 | done 48 | 49 | -------------------------------------------------------------------------------- /doc/pollmail.txt: -------------------------------------------------------------------------------- 1 | POLLMAIL MODULE HELP 2 | 3 | The pollmail module is a unidirectional IMAP-to-IRC gateway. 4 | 5 | It periodically checks an IMAP mailbox for mail, searches for JSON in that mail, and outputs the 6 | 'msg' property of the JSON, if any. It can optionally require at least one JSON message to include a 7 | password property so that pollmail doesn't process spam or unintended mail. This poor mans' 8 | security should be complemented by (1) ensuring IMAP_USER_SSL is true (so password is not sent in the clear) 9 | and (2) keeping the email address private 10 | 11 | Messages are deleted on the IMAP server after being processed. 12 | 13 | JSON can be anywhere in the mail: headers, body, subject. Typically, you should include it in custom mail 14 | headers, but the capability to include it in the subj/body is convenient for senders who cannot output custom 15 | mail headers (e.g., sending from gmail, JIRA, or other 3rd-party applications) 16 | 17 | Thus, if you can control the headers, you can do this: 18 | 19 | X-MADCOW: {{"msg": "I'll show up on IRC"}} 20 | 21 | The JSON specifying the password does not require a message. So you could also send another header: 22 | X-MADCOW-PASSWORD: {{"password": "supersecret"}} 23 | 24 | The pollmail module has ten settings: 25 | 26 | POLLMAIL_FREQUENCY: How often to check for mail. 27 | POLLMAIL_USE_PASSWORD: Whether or not at least one JSON message must include a password 28 | POLLMAIL_PASSWORD: The password to check for. 29 | POLLMAIL_AUTOSTART: Only useful with the task -- sets whether the task should poll periodically at start. 30 | POLLMAIL_JSON_REGEX: The regex to look for JSON. By default, expects the JSON to be wraped by another set of 31 | curly braces: {{ ... }} *not { ... } in order to reduce the risk of accidentally processing unintended strings. 32 | 33 | IMAP_SERVER, IMAP_PORT, IMAP_USERNAME, IMAP_PASSWORD, IMAP_USE_SSL: IMAP Connection settings 34 | 35 | The pollmail module responds to three commands: 36 | 37 | !pollmail now - Forces pollmail to poll now 38 | !pollmail start - Enables the pollmail task to poll periodically. Only allowed by OWNER_NICK. 39 | !pollmail stop - Disables the pollmail task from polling periodically. Only allowed by OWNER_NICK. 40 | -------------------------------------------------------------------------------- /madcow/conf/__init__.py: -------------------------------------------------------------------------------- 1 | """Wraps defaults settings with custom settings""" 2 | 3 | import os 4 | import sys 5 | 6 | RELATIVE_PATHS = ['PIDFILE'] 7 | 8 | class Settings(object): 9 | 10 | def __init__(self): 11 | self.__loaded = False 12 | 13 | def __getattribute__(self, key): 14 | try: 15 | return super(Settings, self).__getattribute__(key) 16 | except AttributeError: 17 | if not self.__loaded: 18 | self.__load() 19 | return self.__getattribute__(key) 20 | 21 | def __load(self): 22 | base = os.environ.get('MADCOW_BASE', os.curdir) 23 | if base not in sys.path: 24 | sys.path.insert(0, base) 25 | import settings 26 | from madcow.conf import defaults 27 | for key in dir(defaults): 28 | if key.isupper(): 29 | default = getattr(defaults, key) 30 | val = getattr(settings, key, default) 31 | if key in RELATIVE_PATHS: 32 | val = os.path.join(base, val) 33 | setattr(self, key, val) 34 | self.__loaded = True 35 | 36 | settings = Settings() 37 | -------------------------------------------------------------------------------- /madcow/include/chardet/__init__.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # This library is free software; you can redistribute it and/or 3 | # modify it under the terms of the GNU Lesser General Public 4 | # License as published by the Free Software Foundation; either 5 | # version 2.1 of the License, or (at your option) any later version. 6 | # 7 | # This library is distributed in the hope that it will be useful, 8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | # Lesser General Public License for more details. 11 | # 12 | # You should have received a copy of the GNU Lesser General Public 13 | # License along with this library; if not, write to the Free Software 14 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 15 | # 02110-1301 USA 16 | ######################### END LICENSE BLOCK ######################### 17 | 18 | __version__ = "1.0.1" 19 | 20 | def detect(aBuf): 21 | import universaldetector 22 | u = universaldetector.UniversalDetector() 23 | u.reset() 24 | u.feed(aBuf) 25 | u.close() 26 | return u.result 27 | -------------------------------------------------------------------------------- /madcow/include/chardet/big5prober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is Mozilla Communicator client code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 1998 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # 12 | # This library is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU Lesser General Public 14 | # License as published by the Free Software Foundation; either 15 | # version 2.1 of the License, or (at your option) any later version. 16 | # 17 | # This library is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | # Lesser General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU Lesser General Public 23 | # License along with this library; if not, write to the Free Software 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 25 | # 02110-1301 USA 26 | ######################### END LICENSE BLOCK ######################### 27 | 28 | from mbcharsetprober import MultiByteCharSetProber 29 | from codingstatemachine import CodingStateMachine 30 | from chardistribution import Big5DistributionAnalysis 31 | from mbcssm import Big5SMModel 32 | 33 | class Big5Prober(MultiByteCharSetProber): 34 | def __init__(self): 35 | MultiByteCharSetProber.__init__(self) 36 | self._mCodingSM = CodingStateMachine(Big5SMModel) 37 | self._mDistributionAnalyzer = Big5DistributionAnalysis() 38 | self.reset() 39 | 40 | def get_charset_name(self): 41 | return "Big5" 42 | -------------------------------------------------------------------------------- /madcow/include/chardet/charsetprober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is Mozilla Universal charset detector code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 2001 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # Shy Shalom - original C code 12 | # 13 | # This library is free software; you can redistribute it and/or 14 | # modify it under the terms of the GNU Lesser General Public 15 | # License as published by the Free Software Foundation; either 16 | # version 2.1 of the License, or (at your option) any later version. 17 | # 18 | # This library is distributed in the hope that it will be useful, 19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | # Lesser General Public License for more details. 22 | # 23 | # You should have received a copy of the GNU Lesser General Public 24 | # License along with this library; if not, write to the Free Software 25 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 26 | # 02110-1301 USA 27 | ######################### END LICENSE BLOCK ######################### 28 | 29 | import constants, re 30 | 31 | class CharSetProber: 32 | def __init__(self): 33 | pass 34 | 35 | def reset(self): 36 | self._mState = constants.eDetecting 37 | 38 | def get_charset_name(self): 39 | return None 40 | 41 | def feed(self, aBuf): 42 | pass 43 | 44 | def get_state(self): 45 | return self._mState 46 | 47 | def get_confidence(self): 48 | return 0.0 49 | 50 | def filter_high_bit_only(self, aBuf): 51 | aBuf = re.sub(r'([\x00-\x7F])+', ' ', aBuf) 52 | return aBuf 53 | 54 | def filter_without_english_letters(self, aBuf): 55 | aBuf = re.sub(r'([A-Za-z])+', ' ', aBuf) 56 | return aBuf 57 | 58 | def filter_with_english_letters(self, aBuf): 59 | # TODO 60 | return aBuf 61 | -------------------------------------------------------------------------------- /madcow/include/chardet/constants.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is Mozilla Universal charset detector code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 2001 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # Shy Shalom - original C code 12 | # 13 | # This library is free software; you can redistribute it and/or 14 | # modify it under the terms of the GNU Lesser General Public 15 | # License as published by the Free Software Foundation; either 16 | # version 2.1 of the License, or (at your option) any later version. 17 | # 18 | # This library is distributed in the hope that it will be useful, 19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | # Lesser General Public License for more details. 22 | # 23 | # You should have received a copy of the GNU Lesser General Public 24 | # License along with this library; if not, write to the Free Software 25 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 26 | # 02110-1301 USA 27 | ######################### END LICENSE BLOCK ######################### 28 | 29 | _debug = 0 30 | 31 | eDetecting = 0 32 | eFoundIt = 1 33 | eNotMe = 2 34 | 35 | eStart = 0 36 | eError = 1 37 | eItsMe = 2 38 | 39 | SHORTCUT_THRESHOLD = 0.95 40 | 41 | import __builtin__ 42 | if not hasattr(__builtin__, 'False'): 43 | False = 0 44 | True = 1 45 | else: 46 | False = __builtin__.False 47 | True = __builtin__.True 48 | -------------------------------------------------------------------------------- /madcow/include/chardet/euckrprober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is mozilla.org code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 1998 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # 12 | # This library is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU Lesser General Public 14 | # License as published by the Free Software Foundation; either 15 | # version 2.1 of the License, or (at your option) any later version. 16 | # 17 | # This library is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | # Lesser General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU Lesser General Public 23 | # License along with this library; if not, write to the Free Software 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 25 | # 02110-1301 USA 26 | ######################### END LICENSE BLOCK ######################### 27 | 28 | from mbcharsetprober import MultiByteCharSetProber 29 | from codingstatemachine import CodingStateMachine 30 | from chardistribution import EUCKRDistributionAnalysis 31 | from mbcssm import EUCKRSMModel 32 | 33 | class EUCKRProber(MultiByteCharSetProber): 34 | def __init__(self): 35 | MultiByteCharSetProber.__init__(self) 36 | self._mCodingSM = CodingStateMachine(EUCKRSMModel) 37 | self._mDistributionAnalyzer = EUCKRDistributionAnalysis() 38 | self.reset() 39 | 40 | def get_charset_name(self): 41 | return "EUC-KR" 42 | -------------------------------------------------------------------------------- /madcow/include/chardet/euctwprober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is mozilla.org code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 1998 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # 12 | # This library is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU Lesser General Public 14 | # License as published by the Free Software Foundation; either 15 | # version 2.1 of the License, or (at your option) any later version. 16 | # 17 | # This library is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | # Lesser General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU Lesser General Public 23 | # License along with this library; if not, write to the Free Software 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 25 | # 02110-1301 USA 26 | ######################### END LICENSE BLOCK ######################### 27 | 28 | from mbcharsetprober import MultiByteCharSetProber 29 | from codingstatemachine import CodingStateMachine 30 | from chardistribution import EUCTWDistributionAnalysis 31 | from mbcssm import EUCTWSMModel 32 | 33 | class EUCTWProber(MultiByteCharSetProber): 34 | def __init__(self): 35 | MultiByteCharSetProber.__init__(self) 36 | self._mCodingSM = CodingStateMachine(EUCTWSMModel) 37 | self._mDistributionAnalyzer = EUCTWDistributionAnalysis() 38 | self.reset() 39 | 40 | def get_charset_name(self): 41 | return "EUC-TW" 42 | -------------------------------------------------------------------------------- /madcow/include/chardet/gb2312prober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is mozilla.org code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 1998 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # 12 | # This library is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU Lesser General Public 14 | # License as published by the Free Software Foundation; either 15 | # version 2.1 of the License, or (at your option) any later version. 16 | # 17 | # This library is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | # Lesser General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU Lesser General Public 23 | # License along with this library; if not, write to the Free Software 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 25 | # 02110-1301 USA 26 | ######################### END LICENSE BLOCK ######################### 27 | 28 | from mbcharsetprober import MultiByteCharSetProber 29 | from codingstatemachine import CodingStateMachine 30 | from chardistribution import GB2312DistributionAnalysis 31 | from mbcssm import GB2312SMModel 32 | 33 | class GB2312Prober(MultiByteCharSetProber): 34 | def __init__(self): 35 | MultiByteCharSetProber.__init__(self) 36 | self._mCodingSM = CodingStateMachine(GB2312SMModel) 37 | self._mDistributionAnalyzer = GB2312DistributionAnalysis() 38 | self.reset() 39 | 40 | def get_charset_name(self): 41 | return "GB2312" 42 | -------------------------------------------------------------------------------- /madcow/include/chardet/mbcsgroupprober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is Mozilla Universal charset detector code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 2001 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # Shy Shalom - original C code 12 | # Proofpoint, Inc. 13 | # 14 | # This library is free software; you can redistribute it and/or 15 | # modify it under the terms of the GNU Lesser General Public 16 | # License as published by the Free Software Foundation; either 17 | # version 2.1 of the License, or (at your option) any later version. 18 | # 19 | # This library is distributed in the hope that it will be useful, 20 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 | # Lesser General Public License for more details. 23 | # 24 | # You should have received a copy of the GNU Lesser General Public 25 | # License along with this library; if not, write to the Free Software 26 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 27 | # 02110-1301 USA 28 | ######################### END LICENSE BLOCK ######################### 29 | 30 | from charsetgroupprober import CharSetGroupProber 31 | from utf8prober import UTF8Prober 32 | from sjisprober import SJISProber 33 | from eucjpprober import EUCJPProber 34 | from gb2312prober import GB2312Prober 35 | from euckrprober import EUCKRProber 36 | from big5prober import Big5Prober 37 | from euctwprober import EUCTWProber 38 | 39 | class MBCSGroupProber(CharSetGroupProber): 40 | def __init__(self): 41 | CharSetGroupProber.__init__(self) 42 | self._mProbers = [ \ 43 | UTF8Prober(), 44 | SJISProber(), 45 | EUCJPProber(), 46 | GB2312Prober(), 47 | EUCKRProber(), 48 | Big5Prober(), 49 | EUCTWProber()] 50 | self.reset() 51 | -------------------------------------------------------------------------------- /madcow/include/fonts.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/madcow/include/fonts.zip -------------------------------------------------------------------------------- /madcow/include/oauth2/clients/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/madcow/include/oauth2/clients/__init__.py -------------------------------------------------------------------------------- /madcow/include/oauth2/clients/imap.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License 3 | 4 | Copyright (c) 2007-2010 Leah Culver, Joe Stump, Mark Paschal, Vic Fryzel 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | import oauth2 26 | import imaplib 27 | 28 | 29 | class IMAP4_SSL(imaplib.IMAP4_SSL): 30 | """IMAP wrapper for imaplib.IMAP4_SSL that implements XOAUTH.""" 31 | 32 | def authenticate(self, url, consumer, token): 33 | if consumer is not None and not isinstance(consumer, oauth2.Consumer): 34 | raise ValueError("Invalid consumer.") 35 | 36 | if token is not None and not isinstance(token, oauth2.Token): 37 | raise ValueError("Invalid token.") 38 | 39 | imaplib.IMAP4_SSL.authenticate(self, 'XOAUTH', 40 | lambda x: oauth2.build_xoauth_string(url, consumer, token)) 41 | -------------------------------------------------------------------------------- /madcow/include/oauth2/clients/smtp.py: -------------------------------------------------------------------------------- 1 | """ 2 | The MIT License 3 | 4 | Copyright (c) 2007-2010 Leah Culver, Joe Stump, Mark Paschal, Vic Fryzel 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | """ 24 | 25 | import oauth2 26 | import smtplib 27 | import base64 28 | 29 | 30 | class SMTP(smtplib.SMTP): 31 | """SMTP wrapper for smtplib.SMTP that implements XOAUTH.""" 32 | 33 | def authenticate(self, url, consumer, token): 34 | if consumer is not None and not isinstance(consumer, oauth2.Consumer): 35 | raise ValueError("Invalid consumer.") 36 | 37 | if token is not None and not isinstance(token, oauth2.Token): 38 | raise ValueError("Invalid token.") 39 | 40 | self.docmd('AUTH', 'XOAUTH %s' % \ 41 | base64.b64encode(oauth2.build_xoauth_string(url, consumer, token))) 42 | -------------------------------------------------------------------------------- /madcow/include/oauthlib/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | oauthlib 3 | ~~~~~~~~ 4 | 5 | A generic, spec-compliant, thorough implementation of the OAuth 6 | request-signing logic. 7 | 8 | :copyright: (c) 2011 by Idan Gazit. 9 | :license: BSD, see LICENSE for details. 10 | """ 11 | 12 | __author__ = 'Idan Gazit ' 13 | __version__ = '0.6.1' 14 | -------------------------------------------------------------------------------- /madcow/include/oauthlib/oauth1/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import absolute_import, unicode_literals 3 | 4 | """ 5 | oauthlib.oauth1 6 | ~~~~~~~~~~~~~~ 7 | 8 | This module is a wrapper for the most recent implementation of OAuth 1.0 Client 9 | and Server classes. 10 | """ 11 | 12 | from .rfc5849 import Client 13 | from .rfc5849 import SIGNATURE_HMAC, SIGNATURE_RSA, SIGNATURE_PLAINTEXT 14 | from .rfc5849 import SIGNATURE_TYPE_AUTH_HEADER, SIGNATURE_TYPE_QUERY 15 | from .rfc5849 import SIGNATURE_TYPE_BODY 16 | from .rfc5849.request_validator import RequestValidator 17 | from .rfc5849.endpoints import RequestTokenEndpoint, AuthorizationEndpoint 18 | from .rfc5849.endpoints import AccessTokenEndpoint, ResourceEndpoint 19 | from .rfc5849.endpoints import WebApplicationServer 20 | -------------------------------------------------------------------------------- /madcow/include/oauthlib/oauth1/rfc5849/endpoints/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .base import BaseEndpoint 4 | from .request_token import RequestTokenEndpoint 5 | from .authorization import AuthorizationEndpoint 6 | from .access_token import AccessTokenEndpoint 7 | from .resource import ResourceEndpoint 8 | from .pre_configured import WebApplicationServer 9 | -------------------------------------------------------------------------------- /madcow/include/oauthlib/oauth1/rfc5849/endpoints/pre_configured.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, unicode_literals 2 | 3 | from . import RequestTokenEndpoint, AuthorizationEndpoint 4 | from . import AccessTokenEndpoint, ResourceEndpoint 5 | 6 | 7 | class WebApplicationServer(RequestTokenEndpoint, AuthorizationEndpoint, 8 | AccessTokenEndpoint, ResourceEndpoint): 9 | 10 | def __init__(self, request_validator): 11 | RequestTokenEndpoint.__init__(self, request_validator) 12 | AuthorizationEndpoint.__init__(self, request_validator) 13 | AccessTokenEndpoint.__init__(self, request_validator) 14 | ResourceEndpoint.__init__(self, request_validator) 15 | -------------------------------------------------------------------------------- /madcow/include/oauthlib/oauth2/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import absolute_import, unicode_literals 3 | 4 | """ 5 | oauthlib.oauth2 6 | ~~~~~~~~~~~~~~ 7 | 8 | This module is a wrapper for the most recent implementation of OAuth 2.0 Client 9 | and Server classes. 10 | """ 11 | 12 | from .rfc6749.clients import Client 13 | from .rfc6749.clients import WebApplicationClient 14 | from .rfc6749.clients import MobileApplicationClient 15 | from .rfc6749.clients import LegacyApplicationClient 16 | from .rfc6749.clients import BackendApplicationClient 17 | from .rfc6749.endpoints import AuthorizationEndpoint 18 | from .rfc6749.endpoints import TokenEndpoint 19 | from .rfc6749.endpoints import ResourceEndpoint 20 | from .rfc6749.endpoints import RevocationEndpoint 21 | from .rfc6749.endpoints import Server 22 | from .rfc6749.endpoints import WebApplicationServer 23 | from .rfc6749.endpoints import MobileApplicationServer 24 | from .rfc6749.endpoints import LegacyApplicationServer 25 | from .rfc6749.endpoints import BackendApplicationServer 26 | from .rfc6749.errors import * 27 | from .rfc6749.grant_types import AuthorizationCodeGrant 28 | from .rfc6749.grant_types import ImplicitGrant 29 | from .rfc6749.grant_types import ResourceOwnerPasswordCredentialsGrant 30 | from .rfc6749.grant_types import ClientCredentialsGrant 31 | from .rfc6749.grant_types import RefreshTokenGrant 32 | from .rfc6749.request_validator import RequestValidator 33 | from .rfc6749.tokens import BearerToken 34 | -------------------------------------------------------------------------------- /madcow/include/oauthlib/oauth2/rfc6749/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import absolute_import, unicode_literals 3 | 4 | """ 5 | oauthlib.oauth2.rfc6749 6 | ~~~~~~~~~~~~~~~~~~~~~~~ 7 | 8 | This module is an implementation of various logic needed 9 | for consuming and providing OAuth 2.0 RFC6749. 10 | """ 11 | import functools 12 | 13 | from oauthlib.common import log 14 | from .errors import TemporarilyUnavailableError, ServerError 15 | from .errors import FatalClientError, OAuth2Error 16 | 17 | 18 | class BaseEndpoint(object): 19 | def __init__(self): 20 | self._available = True 21 | self._catch_errors = False 22 | 23 | @property 24 | def available(self): 25 | return self._available 26 | 27 | @available.setter 28 | def available(self, available): 29 | self._available = available 30 | 31 | @property 32 | def catch_errors(self): 33 | return self._catch_errors 34 | 35 | @catch_errors.setter 36 | def catch_errors(self, catch_errors): 37 | self._catch_errors = catch_errors 38 | 39 | 40 | def catch_errors_and_unavailability(f): 41 | @functools.wraps(f) 42 | def wrapper(endpoint, uri, *args, **kwargs): 43 | if not endpoint.available: 44 | e = TemporarilyUnavailableError() 45 | log.info('Endpoint unavailable, ignoring request %s.' % uri) 46 | return {}, e.json, 503 47 | 48 | if endpoint.catch_errors: 49 | try: 50 | return f(endpoint, uri, *args, **kwargs) 51 | except OAuth2Error: 52 | raise 53 | except FatalClientError: 54 | raise 55 | except Exception as e: 56 | error = ServerError() 57 | log.warning('Exception caught while processing request, %s.' % e) 58 | return {}, error.json, 500 59 | else: 60 | return f(endpoint, uri, *args, **kwargs) 61 | return wrapper 62 | -------------------------------------------------------------------------------- /madcow/include/oauthlib/oauth2/rfc6749/clients/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import absolute_import, unicode_literals 3 | 4 | """ 5 | oauthlib.oauth2.rfc6749 6 | ~~~~~~~~~~~~~~~~~~~~~~~ 7 | 8 | This module is an implementation of various logic needed 9 | for consuming OAuth 2.0 RFC6749. 10 | """ 11 | 12 | from .base import * 13 | from .web_application import WebApplicationClient 14 | from .mobile_application import MobileApplicationClient 15 | from .legacy_application import LegacyApplicationClient 16 | from .backend_application import BackendApplicationClient 17 | -------------------------------------------------------------------------------- /madcow/include/oauthlib/oauth2/rfc6749/endpoints/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import absolute_import, unicode_literals 3 | 4 | """ 5 | oauthlib.oauth2.rfc6749 6 | ~~~~~~~~~~~~~~~~~~~~~~~ 7 | 8 | This module is an implementation of various logic needed 9 | for consuming and providing OAuth 2.0 RFC6749. 10 | """ 11 | 12 | from .authorization import AuthorizationEndpoint 13 | from .token import TokenEndpoint 14 | from .resource import ResourceEndpoint 15 | from .revocation import RevocationEndpoint 16 | from .pre_configured import Server 17 | from .pre_configured import WebApplicationServer 18 | from .pre_configured import MobileApplicationServer 19 | from .pre_configured import LegacyApplicationServer 20 | from .pre_configured import BackendApplicationServer 21 | -------------------------------------------------------------------------------- /madcow/include/oauthlib/oauth2/rfc6749/endpoints/base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import absolute_import, unicode_literals 3 | 4 | """ 5 | oauthlib.oauth2.rfc6749 6 | ~~~~~~~~~~~~~~~~~~~~~~~ 7 | 8 | This module is an implementation of various logic needed 9 | for consuming and providing OAuth 2.0 RFC6749. 10 | """ 11 | import functools 12 | 13 | from oauthlib.common import log 14 | 15 | from ..errors import TemporarilyUnavailableError, ServerError 16 | from ..errors import FatalClientError, OAuth2Error 17 | 18 | 19 | class BaseEndpoint(object): 20 | def __init__(self): 21 | self._available = True 22 | self._catch_errors = False 23 | 24 | @property 25 | def available(self): 26 | return self._available 27 | 28 | @available.setter 29 | def available(self, available): 30 | self._available = available 31 | 32 | @property 33 | def catch_errors(self): 34 | return self._catch_errors 35 | 36 | @catch_errors.setter 37 | def catch_errors(self, catch_errors): 38 | self._catch_errors = catch_errors 39 | 40 | 41 | def catch_errors_and_unavailability(f): 42 | @functools.wraps(f) 43 | def wrapper(endpoint, uri, *args, **kwargs): 44 | if not endpoint.available: 45 | e = TemporarilyUnavailableError() 46 | log.info('Endpoint unavailable, ignoring request %s.' % uri) 47 | return {}, e.json, 503 48 | 49 | if endpoint.catch_errors: 50 | try: 51 | return f(endpoint, uri, *args, **kwargs) 52 | except OAuth2Error: 53 | raise 54 | except FatalClientError: 55 | raise 56 | except Exception as e: 57 | error = ServerError() 58 | log.warning('Exception caught while processing request, %s.' % e) 59 | return {}, error.json, 500 60 | else: 61 | return f(endpoint, uri, *args, **kwargs) 62 | return wrapper 63 | -------------------------------------------------------------------------------- /madcow/include/oauthlib/oauth2/rfc6749/grant_types/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | oauthlib.oauth2.rfc6749.grant_types 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 | """ 6 | from __future__ import unicode_literals, absolute_import 7 | 8 | from .authorization_code import AuthorizationCodeGrant 9 | from .implicit import ImplicitGrant 10 | from .resource_owner_password_credentials import ResourceOwnerPasswordCredentialsGrant 11 | from .client_credentials import ClientCredentialsGrant 12 | from .refresh_token import RefreshTokenGrant 13 | -------------------------------------------------------------------------------- /madcow/include/oauthlib/oauth2/rfc6749/grant_types/base.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | oauthlib.oauth2.rfc6749.grant_types 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5 | """ 6 | from __future__ import unicode_literals, absolute_import 7 | 8 | from oauthlib.common import log 9 | from oauthlib.oauth2.rfc6749 import errors, utils 10 | 11 | 12 | class GrantTypeBase(object): 13 | error_uri = None 14 | request_validator = None 15 | 16 | def create_authorization_response(self, request, token_handler): 17 | raise NotImplementedError('Subclasses must implement this method.') 18 | 19 | def create_token_response(self, request, token_handler): 20 | raise NotImplementedError('Subclasses must implement this method.') 21 | 22 | def validate_grant_type(self, request): 23 | if not self.request_validator.validate_grant_type(request.client_id, 24 | request.grant_type, request.client, request): 25 | log.debug('Unauthorized from %r (%r) access to grant type %s.', 26 | request.client_id, request.client, request.grant_type) 27 | raise errors.UnauthorizedClientError(request=request) 28 | 29 | def validate_scopes(self, request): 30 | if not request.scopes: 31 | request.scopes = utils.scope_to_list(request.scope) or utils.scope_to_list( 32 | self.request_validator.get_default_scopes(request.client_id, request)) 33 | log.debug('Validating access to scopes %r for client %r (%r).', 34 | request.scopes, request.client_id, request.client) 35 | if not self.request_validator.validate_scopes(request.client_id, 36 | request.scopes, request.client, request): 37 | raise errors.InvalidScopeError(state=request.state, request=request) 38 | -------------------------------------------------------------------------------- /madcow/include/pymegahal/db/megahal.aux: -------------------------------------------------------------------------------- 1 | # 2 | # This is a list of words which can be used as keywords only 3 | # in order to supplement other keywords 4 | # 5 | DISLIKE 6 | HE 7 | HER 8 | HERS 9 | HIM 10 | HIS 11 | I 12 | I'D 13 | I'LL 14 | I'M 15 | I'VE 16 | LIKE 17 | ME 18 | MINE 19 | MY 20 | MYSELF 21 | ONE 22 | SHE 23 | THREE 24 | TWO 25 | YOU 26 | YOU'D 27 | YOU'LL 28 | YOU'RE 29 | YOU'VE 30 | YOUR 31 | YOURS 32 | YOURSELF 33 | -------------------------------------------------------------------------------- /madcow/include/pymegahal/db/megahal.swp: -------------------------------------------------------------------------------- 1 | # 2 | # The word on the left is changed to the word on the 3 | # right when used as a keyword 4 | # 5 | DISLIKE LIKE 6 | HATE LOVE 7 | I YOU 8 | I'D YOU'D 9 | I'LL YOU'LL 10 | I'M YOU'RE 11 | I'VE YOU'VE 12 | LIKE DISLIKE 13 | LOVE HATE 14 | ME YOU 15 | MINE YOURS 16 | MY YOUR 17 | MYSELF YOURSELF 18 | NO YES 19 | WHY BECAUSE 20 | YES NO 21 | YOU I 22 | YOU ME 23 | YOU'D I'D 24 | YOU'LL I'LL 25 | YOU'RE I'M 26 | YOU'VE I'VE 27 | YOUR MY 28 | YOURS MINE 29 | YOURSELF MYSELF 30 | -------------------------------------------------------------------------------- /madcow/include/pymegahal/megahal.h: -------------------------------------------------------------------------------- 1 | #ifndef MEGAHAL_H 2 | #define MEGAHAL_H 1 3 | #ifdef SUNOS 4 | extern double drand48(void); 5 | extern void srand48(long); 6 | #endif 7 | void megahal_setdirectory (char *dir); 8 | void megahal_initialize(void); 9 | char *megahal_do_reply(char *input, int log); 10 | void megahal_learn_no_reply(char *input, int log); 11 | void megahal_cleanup(void); 12 | #endif 13 | -------------------------------------------------------------------------------- /madcow/include/pymegahal/python.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "megahal.h" 3 | 4 | static PyObject *mhinitbrain(PyObject *self, PyObject *args) 5 | { 6 | char *dir; 7 | if (!PyArg_ParseTuple(args, "s", &dir)) 8 | return NULL; 9 | megahal_setdirectory(dir); 10 | megahal_initialize(); 11 | Py_INCREF(Py_None); 12 | return Py_None; 13 | } 14 | 15 | static PyObject *mhdoreply(PyObject *self, PyObject *args) 16 | { 17 | char *input; 18 | char *output = NULL; 19 | if (!PyArg_ParseTuple(args, "s", &input)) 20 | return NULL; 21 | output = megahal_do_reply(input, 1); 22 | return PyString_FromString(output); 23 | } 24 | 25 | static PyObject *mhlearn(PyObject *self, PyObject *args) 26 | { 27 | char *input; 28 | if (!PyArg_ParseTuple(args, "s", &input)) 29 | return NULL; 30 | megahal_learn_no_reply(input, 1); 31 | Py_INCREF(Py_None); 32 | return Py_None; 33 | } 34 | 35 | static PyObject *mhcleanup(PyObject *self, PyObject *args) 36 | { 37 | megahal_cleanup(); 38 | Py_INCREF(Py_None); 39 | return Py_None; 40 | } 41 | 42 | static struct PyMethodDef mh_methods[] = { 43 | {"init", mhinitbrain, METH_VARARGS, "Initialize megahal brain"}, 44 | {"process", mhdoreply, METH_VARARGS, "Generate a reply"}, 45 | {"save", mhcleanup, METH_VARARGS,"Save database"}, 46 | {"learn", mhlearn, METH_VARARGS, "Learn from a sentence"}, 47 | {NULL, NULL, 0, NULL} 48 | }; 49 | 50 | void initcmegahal() 51 | { 52 | Py_InitModule("cmegahal", mh_methods); 53 | if(PyErr_Occurred()) 54 | Py_FatalError("can't initialize module megahal"); 55 | } 56 | -------------------------------------------------------------------------------- /madcow/include/pymegahal/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup, Extension 4 | import sys 5 | import os 6 | 7 | def main(): 8 | """Build megahal lib and copy to dst""" 9 | setup(name='megahal', 10 | version='9.0.3', 11 | author='David N. Welton', 12 | author_email='david@dedasys.com', 13 | url='http://www.megahal.net', 14 | license='GPL', 15 | description='markov bot', 16 | ext_modules=[Extension('cmegahal', ['python.c', 'megahal.c'])]) 17 | return 0 18 | 19 | if __name__ == '__main__': 20 | sys.exit(main()) 21 | -------------------------------------------------------------------------------- /madcow/include/requests/certs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | certs.py 6 | ~~~~~~~~ 7 | 8 | This module returns the preferred default CA certificate bundle. 9 | 10 | If you are packaging Requests, e.g., for a Linux distribution or a managed 11 | environment, you can change the definition of where() to return a separately 12 | packaged CA bundle. 13 | """ 14 | 15 | import os.path 16 | 17 | 18 | def where(): 19 | """Return the preferred certificate bundle.""" 20 | # vendored bundle inside Requests 21 | return os.path.join(os.path.dirname(__file__), 'cacert.pem') 22 | 23 | if __name__ == '__main__': 24 | print(where()) 25 | -------------------------------------------------------------------------------- /madcow/include/requests/hooks.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | requests.hooks 5 | ~~~~~~~~~~~~~~ 6 | 7 | This module provides the capabilities for the Requests hooks system. 8 | 9 | Available hooks: 10 | 11 | ``response``: 12 | The response generated from a Request. 13 | 14 | """ 15 | 16 | 17 | HOOKS = ['response'] 18 | 19 | 20 | def default_hooks(): 21 | hooks = {} 22 | for event in HOOKS: 23 | hooks[event] = [] 24 | return hooks 25 | 26 | # TODO: response is the only one 27 | 28 | 29 | def dispatch_hook(key, hooks, hook_data, **kwargs): 30 | """Dispatches a hook dictionary on a given piece of data.""" 31 | 32 | hooks = hooks or dict() 33 | 34 | if key in hooks: 35 | hooks = hooks.get(key) 36 | 37 | if hasattr(hooks, '__call__'): 38 | hooks = [hooks] 39 | 40 | for hook in hooks: 41 | _hook_data = hook(hook_data, **kwargs) 42 | if _hook_data is not None: 43 | hook_data = _hook_data 44 | 45 | return hook_data 46 | -------------------------------------------------------------------------------- /madcow/include/requests/packages/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from . import urllib3 4 | -------------------------------------------------------------------------------- /madcow/include/requests/packages/chardet/__init__.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # This library is free software; you can redistribute it and/or 3 | # modify it under the terms of the GNU Lesser General Public 4 | # License as published by the Free Software Foundation; either 5 | # version 2.1 of the License, or (at your option) any later version. 6 | # 7 | # This library is distributed in the hope that it will be useful, 8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | # Lesser General Public License for more details. 11 | # 12 | # You should have received a copy of the GNU Lesser General Public 13 | # License along with this library; if not, write to the Free Software 14 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 15 | # 02110-1301 USA 16 | ######################### END LICENSE BLOCK ######################### 17 | 18 | __version__ = "2.2.1" 19 | from sys import version_info 20 | 21 | 22 | def detect(aBuf): 23 | if ((version_info < (3, 0) and isinstance(aBuf, unicode)) or 24 | (version_info >= (3, 0) and not isinstance(aBuf, bytes))): 25 | raise ValueError('Expected a bytes object, not a unicode object') 26 | 27 | from . import universaldetector 28 | u = universaldetector.UniversalDetector() 29 | u.reset() 30 | u.feed(aBuf) 31 | u.close() 32 | return u.result 33 | -------------------------------------------------------------------------------- /madcow/include/requests/packages/chardet/big5prober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is Mozilla Communicator client code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 1998 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # 12 | # This library is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU Lesser General Public 14 | # License as published by the Free Software Foundation; either 15 | # version 2.1 of the License, or (at your option) any later version. 16 | # 17 | # This library is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | # Lesser General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU Lesser General Public 23 | # License along with this library; if not, write to the Free Software 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 25 | # 02110-1301 USA 26 | ######################### END LICENSE BLOCK ######################### 27 | 28 | from .mbcharsetprober import MultiByteCharSetProber 29 | from .codingstatemachine import CodingStateMachine 30 | from .chardistribution import Big5DistributionAnalysis 31 | from .mbcssm import Big5SMModel 32 | 33 | 34 | class Big5Prober(MultiByteCharSetProber): 35 | def __init__(self): 36 | MultiByteCharSetProber.__init__(self) 37 | self._mCodingSM = CodingStateMachine(Big5SMModel) 38 | self._mDistributionAnalyzer = Big5DistributionAnalysis() 39 | self.reset() 40 | 41 | def get_charset_name(self): 42 | return "Big5" 43 | -------------------------------------------------------------------------------- /madcow/include/requests/packages/chardet/chardetect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Script which takes one or more file paths and reports on their detected 4 | encodings 5 | 6 | Example:: 7 | 8 | % chardetect somefile someotherfile 9 | somefile: windows-1252 with confidence 0.5 10 | someotherfile: ascii with confidence 1.0 11 | 12 | If no paths are provided, it takes its input from stdin. 13 | 14 | """ 15 | from io import open 16 | from sys import argv, stdin 17 | 18 | from chardet.universaldetector import UniversalDetector 19 | 20 | 21 | def description_of(file, name='stdin'): 22 | """Return a string describing the probable encoding of a file.""" 23 | u = UniversalDetector() 24 | for line in file: 25 | u.feed(line) 26 | u.close() 27 | result = u.result 28 | if result['encoding']: 29 | return '%s: %s with confidence %s' % (name, 30 | result['encoding'], 31 | result['confidence']) 32 | else: 33 | return '%s: no result' % name 34 | 35 | 36 | def main(): 37 | if len(argv) <= 1: 38 | print(description_of(stdin)) 39 | else: 40 | for path in argv[1:]: 41 | with open(path, 'rb') as f: 42 | print(description_of(f, path)) 43 | 44 | 45 | if __name__ == '__main__': 46 | main() 47 | -------------------------------------------------------------------------------- /madcow/include/requests/packages/chardet/charsetprober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is Mozilla Universal charset detector code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 2001 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # Shy Shalom - original C code 12 | # 13 | # This library is free software; you can redistribute it and/or 14 | # modify it under the terms of the GNU Lesser General Public 15 | # License as published by the Free Software Foundation; either 16 | # version 2.1 of the License, or (at your option) any later version. 17 | # 18 | # This library is distributed in the hope that it will be useful, 19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | # Lesser General Public License for more details. 22 | # 23 | # You should have received a copy of the GNU Lesser General Public 24 | # License along with this library; if not, write to the Free Software 25 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 26 | # 02110-1301 USA 27 | ######################### END LICENSE BLOCK ######################### 28 | 29 | from . import constants 30 | import re 31 | 32 | 33 | class CharSetProber: 34 | def __init__(self): 35 | pass 36 | 37 | def reset(self): 38 | self._mState = constants.eDetecting 39 | 40 | def get_charset_name(self): 41 | return None 42 | 43 | def feed(self, aBuf): 44 | pass 45 | 46 | def get_state(self): 47 | return self._mState 48 | 49 | def get_confidence(self): 50 | return 0.0 51 | 52 | def filter_high_bit_only(self, aBuf): 53 | aBuf = re.sub(b'([\x00-\x7F])+', b' ', aBuf) 54 | return aBuf 55 | 56 | def filter_without_english_letters(self, aBuf): 57 | aBuf = re.sub(b'([A-Za-z])+', b' ', aBuf) 58 | return aBuf 59 | 60 | def filter_with_english_letters(self, aBuf): 61 | # TODO 62 | return aBuf 63 | -------------------------------------------------------------------------------- /madcow/include/requests/packages/chardet/compat.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # Contributor(s): 3 | # Ian Cordasco - port to Python 4 | # 5 | # This library is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU Lesser General Public 7 | # License as published by the Free Software Foundation; either 8 | # version 2.1 of the License, or (at your option) any later version. 9 | # 10 | # This library is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # Lesser General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Lesser General Public 16 | # License along with this library; if not, write to the Free Software 17 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 18 | # 02110-1301 USA 19 | ######################### END LICENSE BLOCK ######################### 20 | 21 | import sys 22 | 23 | 24 | if sys.version_info < (3, 0): 25 | base_str = (str, unicode) 26 | else: 27 | base_str = (bytes, str) 28 | 29 | 30 | def wrap_ord(a): 31 | if sys.version_info < (3, 0) and isinstance(a, base_str): 32 | return ord(a) 33 | else: 34 | return a 35 | -------------------------------------------------------------------------------- /madcow/include/requests/packages/chardet/constants.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is Mozilla Universal charset detector code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 2001 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # Shy Shalom - original C code 12 | # 13 | # This library is free software; you can redistribute it and/or 14 | # modify it under the terms of the GNU Lesser General Public 15 | # License as published by the Free Software Foundation; either 16 | # version 2.1 of the License, or (at your option) any later version. 17 | # 18 | # This library is distributed in the hope that it will be useful, 19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | # Lesser General Public License for more details. 22 | # 23 | # You should have received a copy of the GNU Lesser General Public 24 | # License along with this library; if not, write to the Free Software 25 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 26 | # 02110-1301 USA 27 | ######################### END LICENSE BLOCK ######################### 28 | 29 | _debug = 0 30 | 31 | eDetecting = 0 32 | eFoundIt = 1 33 | eNotMe = 2 34 | 35 | eStart = 0 36 | eError = 1 37 | eItsMe = 2 38 | 39 | SHORTCUT_THRESHOLD = 0.95 40 | -------------------------------------------------------------------------------- /madcow/include/requests/packages/chardet/cp949prober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is mozilla.org code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 1998 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # 12 | # This library is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU Lesser General Public 14 | # License as published by the Free Software Foundation; either 15 | # version 2.1 of the License, or (at your option) any later version. 16 | # 17 | # This library is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | # Lesser General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU Lesser General Public 23 | # License along with this library; if not, write to the Free Software 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 25 | # 02110-1301 USA 26 | ######################### END LICENSE BLOCK ######################### 27 | 28 | from .mbcharsetprober import MultiByteCharSetProber 29 | from .codingstatemachine import CodingStateMachine 30 | from .chardistribution import EUCKRDistributionAnalysis 31 | from .mbcssm import CP949SMModel 32 | 33 | 34 | class CP949Prober(MultiByteCharSetProber): 35 | def __init__(self): 36 | MultiByteCharSetProber.__init__(self) 37 | self._mCodingSM = CodingStateMachine(CP949SMModel) 38 | # NOTE: CP949 is a superset of EUC-KR, so the distribution should be 39 | # not different. 40 | self._mDistributionAnalyzer = EUCKRDistributionAnalysis() 41 | self.reset() 42 | 43 | def get_charset_name(self): 44 | return "CP949" 45 | -------------------------------------------------------------------------------- /madcow/include/requests/packages/chardet/euckrprober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is mozilla.org code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 1998 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # 12 | # This library is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU Lesser General Public 14 | # License as published by the Free Software Foundation; either 15 | # version 2.1 of the License, or (at your option) any later version. 16 | # 17 | # This library is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | # Lesser General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU Lesser General Public 23 | # License along with this library; if not, write to the Free Software 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 25 | # 02110-1301 USA 26 | ######################### END LICENSE BLOCK ######################### 27 | 28 | from .mbcharsetprober import MultiByteCharSetProber 29 | from .codingstatemachine import CodingStateMachine 30 | from .chardistribution import EUCKRDistributionAnalysis 31 | from .mbcssm import EUCKRSMModel 32 | 33 | 34 | class EUCKRProber(MultiByteCharSetProber): 35 | def __init__(self): 36 | MultiByteCharSetProber.__init__(self) 37 | self._mCodingSM = CodingStateMachine(EUCKRSMModel) 38 | self._mDistributionAnalyzer = EUCKRDistributionAnalysis() 39 | self.reset() 40 | 41 | def get_charset_name(self): 42 | return "EUC-KR" 43 | -------------------------------------------------------------------------------- /madcow/include/requests/packages/chardet/euctwprober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is mozilla.org code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 1998 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # 12 | # This library is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU Lesser General Public 14 | # License as published by the Free Software Foundation; either 15 | # version 2.1 of the License, or (at your option) any later version. 16 | # 17 | # This library is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | # Lesser General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU Lesser General Public 23 | # License along with this library; if not, write to the Free Software 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 25 | # 02110-1301 USA 26 | ######################### END LICENSE BLOCK ######################### 27 | 28 | from .mbcharsetprober import MultiByteCharSetProber 29 | from .codingstatemachine import CodingStateMachine 30 | from .chardistribution import EUCTWDistributionAnalysis 31 | from .mbcssm import EUCTWSMModel 32 | 33 | class EUCTWProber(MultiByteCharSetProber): 34 | def __init__(self): 35 | MultiByteCharSetProber.__init__(self) 36 | self._mCodingSM = CodingStateMachine(EUCTWSMModel) 37 | self._mDistributionAnalyzer = EUCTWDistributionAnalysis() 38 | self.reset() 39 | 40 | def get_charset_name(self): 41 | return "EUC-TW" 42 | -------------------------------------------------------------------------------- /madcow/include/requests/packages/chardet/gb2312prober.py: -------------------------------------------------------------------------------- 1 | ######################## BEGIN LICENSE BLOCK ######################## 2 | # The Original Code is mozilla.org code. 3 | # 4 | # The Initial Developer of the Original Code is 5 | # Netscape Communications Corporation. 6 | # Portions created by the Initial Developer are Copyright (C) 1998 7 | # the Initial Developer. All Rights Reserved. 8 | # 9 | # Contributor(s): 10 | # Mark Pilgrim - port to Python 11 | # 12 | # This library is free software; you can redistribute it and/or 13 | # modify it under the terms of the GNU Lesser General Public 14 | # License as published by the Free Software Foundation; either 15 | # version 2.1 of the License, or (at your option) any later version. 16 | # 17 | # This library is distributed in the hope that it will be useful, 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | # Lesser General Public License for more details. 21 | # 22 | # You should have received a copy of the GNU Lesser General Public 23 | # License along with this library; if not, write to the Free Software 24 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 25 | # 02110-1301 USA 26 | ######################### END LICENSE BLOCK ######################### 27 | 28 | from .mbcharsetprober import MultiByteCharSetProber 29 | from .codingstatemachine import CodingStateMachine 30 | from .chardistribution import GB2312DistributionAnalysis 31 | from .mbcssm import GB2312SMModel 32 | 33 | class GB2312Prober(MultiByteCharSetProber): 34 | def __init__(self): 35 | MultiByteCharSetProber.__init__(self) 36 | self._mCodingSM = CodingStateMachine(GB2312SMModel) 37 | self._mDistributionAnalyzer = GB2312DistributionAnalysis() 38 | self.reset() 39 | 40 | def get_charset_name(self): 41 | return "GB2312" 42 | -------------------------------------------------------------------------------- /madcow/include/requests/packages/urllib3/__init__.py: -------------------------------------------------------------------------------- 1 | # urllib3/__init__.py 2 | # Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt) 3 | # 4 | # This module is part of urllib3 and is released under 5 | # the MIT License: http://www.opensource.org/licenses/mit-license.php 6 | 7 | """ 8 | urllib3 - Thread-safe connection pooling and re-using. 9 | """ 10 | 11 | __author__ = 'Andrey Petrov (andrey.petrov@shazow.net)' 12 | __license__ = 'MIT' 13 | __version__ = '1.8' 14 | 15 | 16 | from .connectionpool import ( 17 | HTTPConnectionPool, 18 | HTTPSConnectionPool, 19 | connection_from_url 20 | ) 21 | 22 | from . import exceptions 23 | from .filepost import encode_multipart_formdata 24 | from .poolmanager import PoolManager, ProxyManager, proxy_from_url 25 | from .response import HTTPResponse 26 | from .util import make_headers, get_host, Timeout 27 | 28 | 29 | # Set default logging handler to avoid "No handler found" warnings. 30 | import logging 31 | try: # Python 2.7+ 32 | from logging import NullHandler 33 | except ImportError: 34 | class NullHandler(logging.Handler): 35 | def emit(self, record): 36 | pass 37 | 38 | logging.getLogger(__name__).addHandler(NullHandler()) 39 | 40 | def add_stderr_logger(level=logging.DEBUG): 41 | """ 42 | Helper for quickly adding a StreamHandler to the logger. Useful for 43 | debugging. 44 | 45 | Returns the handler after adding it. 46 | """ 47 | # This method needs to be in this __init__.py to get the __name__ correct 48 | # even if urllib3 is vendored within another package. 49 | logger = logging.getLogger(__name__) 50 | handler = logging.StreamHandler() 51 | handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s %(message)s')) 52 | logger.addHandler(handler) 53 | logger.setLevel(level) 54 | logger.debug('Added an stderr logging handler to logger: %s' % __name__) 55 | return handler 56 | 57 | # ... Clean up. 58 | del NullHandler 59 | -------------------------------------------------------------------------------- /madcow/include/requests/packages/urllib3/contrib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cjones/madcow/e4f154b3ca4b2e31870bb314daa53ad7dc26aabf/madcow/include/requests/packages/urllib3/contrib/__init__.py -------------------------------------------------------------------------------- /madcow/include/requests/packages/urllib3/packages/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from . import ssl_match_hostname 4 | 5 | -------------------------------------------------------------------------------- /madcow/include/requests/packages/urllib3/packages/ssl_match_hostname/__init__.py: -------------------------------------------------------------------------------- 1 | try: 2 | # Python 3.2+ 3 | from ssl import CertificateError, match_hostname 4 | except ImportError: 5 | try: 6 | # Backport of the function from a pypi module 7 | from backports.ssl_match_hostname import CertificateError, match_hostname 8 | except ImportError: 9 | # Our vendored copy 10 | from ._implementation import CertificateError, match_hostname 11 | 12 | # Not needed, but documenting what we provide. 13 | __all__ = ('CertificateError', 'match_hostname') 14 | -------------------------------------------------------------------------------- /madcow/include/requests_oauthlib/__init__.py: -------------------------------------------------------------------------------- 1 | from .oauth1_auth import OAuth1 2 | from .oauth1_session import OAuth1Session 3 | from .oauth2_auth import OAuth2 4 | from .oauth2_session import OAuth2Session, TokenUpdated 5 | 6 | __version__ = '0.4.0' 7 | -------------------------------------------------------------------------------- /madcow/include/requests_oauthlib/compliance_fixes/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .facebook import facebook_compliance_fix 4 | from .linkedin import linkedin_compliance_fix 5 | from .weibo import weibo_compliance_fix 6 | -------------------------------------------------------------------------------- /madcow/include/requests_oauthlib/compliance_fixes/facebook.py: -------------------------------------------------------------------------------- 1 | from json import dumps 2 | from oauthlib.common import urldecode 3 | from urlparse import parse_qsl 4 | 5 | 6 | def facebook_compliance_fix(session): 7 | 8 | def _compliance_fix(r): 9 | # if Facebook claims to be sending us json, let's trust them. 10 | if 'application/json' in r.headers['content-type']: 11 | return r 12 | 13 | # Facebook returns a content-type of text/plain when sending their 14 | # x-www-form-urlencoded responses, along with a 200. If not, let's 15 | # assume we're getting JSON and bail on the fix. 16 | if 'text/plain' in r.headers['content-type'] and r.status_code == 200: 17 | token = dict(parse_qsl(r.text, keep_blank_values=True)) 18 | else: 19 | return r 20 | 21 | expires = token.get('expires') 22 | if expires is not None: 23 | token['expires_in'] = expires 24 | token['token_type'] = 'Bearer' 25 | r._content = dumps(token) 26 | return r 27 | 28 | session.register_compliance_hook('access_token_response', _compliance_fix) 29 | return session 30 | -------------------------------------------------------------------------------- /madcow/include/requests_oauthlib/compliance_fixes/linkedin.py: -------------------------------------------------------------------------------- 1 | from json import loads, dumps 2 | 3 | from oauthlib.common import add_params_to_uri 4 | 5 | 6 | def linkedin_compliance_fix(session): 7 | 8 | def _missing_token_type(r): 9 | token = loads(r.text) 10 | token['token_type'] = 'Bearer' 11 | r._content = dumps(token) 12 | return r 13 | 14 | def _non_compliant_param_name(url, headers, data): 15 | token = [('oauth2_access_token', session._client.access_token)] 16 | url = add_params_to_uri(url, token) 17 | return url, headers, data 18 | 19 | session._client.default_token_placement = 'query' 20 | session.register_compliance_hook('access_token_response', 21 | _missing_token_type) 22 | session.register_compliance_hook('protected_request', 23 | _non_compliant_param_name) 24 | return session 25 | -------------------------------------------------------------------------------- /madcow/include/requests_oauthlib/compliance_fixes/weibo.py: -------------------------------------------------------------------------------- 1 | from json import loads, dumps 2 | 3 | from oauthlib.common import add_params_to_uri 4 | 5 | 6 | def weibo_compliance_fix(session): 7 | 8 | def _missing_token_type(r): 9 | token = loads(r.text) 10 | token['token_type'] = 'Bearer' 11 | r._content = dumps(token).encode('UTF-8') 12 | return r 13 | 14 | session._client.default_token_placement = 'query' 15 | session.register_compliance_hook('access_token_response', 16 | _missing_token_type) 17 | return session 18 | -------------------------------------------------------------------------------- /madcow/include/requests_oauthlib/oauth2_auth.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | from oauthlib.oauth2 import WebApplicationClient, InsecureTransportError 3 | 4 | from .utils import is_secure_transport 5 | 6 | 7 | class OAuth2(object): 8 | """Adds proof of authorization (OAuth2 token) to the request.""" 9 | 10 | def __init__(self, client_id=None, client=None, token=None): 11 | """Construct a new OAuth 2 authorization object. 12 | 13 | :param client_id: Client id obtained during registration 14 | :param client: :class:`oauthlib.oauth2.Client` to be used. Default is 15 | WebApplicationClient which is useful for any 16 | hosted application but not mobile or desktop. 17 | :param token: Token dictionary, must include access_token 18 | and token_type. 19 | """ 20 | self._client = client or WebApplicationClient(client_id, token=token) 21 | if token: 22 | for k, v in token.items(): 23 | setattr(self._client, k, v) 24 | 25 | def __call__(self, r): 26 | """Append an OAuth 2 token to the request. 27 | 28 | Note that currently HTTPS is required for all requests. There may be 29 | a token type that allows for plain HTTP in the future and then this 30 | should be updated to allow plain HTTP on a white list basis. 31 | """ 32 | if not is_secure_transport(r.url): 33 | raise InsecureTransportError() 34 | r.url, r.headers, r.body = self._client.add_token(r.url, 35 | http_method=r.method, body=r.body, headers=r.headers) 36 | return r 37 | -------------------------------------------------------------------------------- /madcow/include/requests_oauthlib/utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | import os 3 | 4 | 5 | def is_secure_transport(uri): 6 | """Check if the uri is over ssl.""" 7 | if os.environ.get('DEBUG'): 8 | return True 9 | return uri.lower().startswith('https://') 10 | -------------------------------------------------------------------------------- /madcow/include/simplejson/tests/__init__.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import doctest 3 | 4 | 5 | class OptionalExtensionTestSuite(unittest.TestSuite): 6 | def run(self, result): 7 | import simplejson 8 | run = unittest.TestSuite.run 9 | run(self, result) 10 | simplejson._toggle_speedups(False) 11 | run(self, result) 12 | simplejson._toggle_speedups(True) 13 | return result 14 | 15 | 16 | def additional_tests(suite=None): 17 | import simplejson 18 | import simplejson.encoder 19 | import simplejson.decoder 20 | if suite is None: 21 | suite = unittest.TestSuite() 22 | for mod in (simplejson, simplejson.encoder, simplejson.decoder): 23 | suite.addTest(doctest.DocTestSuite(mod)) 24 | suite.addTest(doctest.DocFileSuite('../../index.rst')) 25 | return suite 26 | 27 | 28 | def all_tests_suite(): 29 | suite = unittest.TestLoader().loadTestsFromNames([ 30 | 'simplejson.tests.test_check_circular', 31 | 'simplejson.tests.test_decode', 32 | 'simplejson.tests.test_default', 33 | 'simplejson.tests.test_dump', 34 | 'simplejson.tests.test_encode_basestring_ascii', 35 | 'simplejson.tests.test_encode_for_html', 36 | 'simplejson.tests.test_fail', 37 | 'simplejson.tests.test_float', 38 | 'simplejson.tests.test_indent', 39 | 'simplejson.tests.test_pass1', 40 | 'simplejson.tests.test_pass2', 41 | 'simplejson.tests.test_pass3', 42 | 'simplejson.tests.test_recursion', 43 | 'simplejson.tests.test_scanstring', 44 | 'simplejson.tests.test_separators', 45 | 'simplejson.tests.test_speedups', 46 | 'simplejson.tests.test_unicode', 47 | 'simplejson.tests.test_decimal', 48 | ]) 49 | suite = additional_tests(suite) 50 | return OptionalExtensionTestSuite([suite]) 51 | 52 | 53 | def main(): 54 | runner = unittest.TextTestRunner() 55 | suite = all_tests_suite() 56 | runner.run(suite) 57 | 58 | 59 | if __name__ == '__main__': 60 | import os 61 | import sys 62 | sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) 63 | main() 64 | -------------------------------------------------------------------------------- /madcow/include/simplejson/tests/test_check_circular.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | import simplejson as json 3 | 4 | def default_iterable(obj): 5 | return list(obj) 6 | 7 | class TestCheckCircular(TestCase): 8 | def test_circular_dict(self): 9 | dct = {} 10 | dct['a'] = dct 11 | self.assertRaises(ValueError, json.dumps, dct) 12 | 13 | def test_circular_list(self): 14 | lst = [] 15 | lst.append(lst) 16 | self.assertRaises(ValueError, json.dumps, lst) 17 | 18 | def test_circular_composite(self): 19 | dct2 = {} 20 | dct2['a'] = [] 21 | dct2['a'].append(dct2) 22 | self.assertRaises(ValueError, json.dumps, dct2) 23 | 24 | def test_circular_default(self): 25 | json.dumps([set()], default=default_iterable) 26 | self.assertRaises(TypeError, json.dumps, [set()]) 27 | 28 | def test_circular_off_default(self): 29 | json.dumps([set()], default=default_iterable, check_circular=False) 30 | self.assertRaises(TypeError, json.dumps, [set()], check_circular=False) 31 | -------------------------------------------------------------------------------- /madcow/include/simplejson/tests/test_decimal.py: -------------------------------------------------------------------------------- 1 | from decimal import Decimal 2 | from unittest import TestCase 3 | 4 | import simplejson as json 5 | 6 | class TestDecimal(TestCase): 7 | NUMS = "1.0", "10.00", "1.1", "1234567890.1234567890", "500" 8 | def test_decimal_encode(self): 9 | for d in map(Decimal, self.NUMS): 10 | self.assertEquals(json.dumps(d, use_decimal=True), str(d)) 11 | 12 | def test_decimal_decode(self): 13 | for s in self.NUMS: 14 | self.assertEquals(json.loads(s, parse_float=Decimal), Decimal(s)) 15 | 16 | def test_decimal_roundtrip(self): 17 | for d in map(Decimal, self.NUMS): 18 | # The type might not be the same (int and Decimal) but they 19 | # should still compare equal. 20 | self.assertEquals( 21 | json.loads( 22 | json.dumps(d, use_decimal=True), parse_float=Decimal), 23 | d) 24 | self.assertEquals( 25 | json.loads( 26 | json.dumps([d], use_decimal=True), parse_float=Decimal), 27 | [d]) 28 | 29 | def test_decimal_defaults(self): 30 | d = Decimal(1) 31 | # use_decimal=False is the default 32 | self.assertRaises(TypeError, json.dumps, d, use_decimal=False) 33 | self.assertRaises(TypeError, json.dumps, d) -------------------------------------------------------------------------------- /madcow/include/simplejson/tests/test_default.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | 3 | import simplejson as json 4 | 5 | class TestDefault(TestCase): 6 | def test_default(self): 7 | self.assertEquals( 8 | json.dumps(type, default=repr), 9 | json.dumps(repr(type))) 10 | -------------------------------------------------------------------------------- /madcow/include/simplejson/tests/test_dump.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | from cStringIO import StringIO 3 | 4 | import simplejson as json 5 | 6 | class TestDump(TestCase): 7 | def test_dump(self): 8 | sio = StringIO() 9 | json.dump({}, sio) 10 | self.assertEquals(sio.getvalue(), '{}') 11 | 12 | def test_dumps(self): 13 | self.assertEquals(json.dumps({}), '{}') 14 | 15 | def test_encode_truefalse(self): 16 | self.assertEquals(json.dumps( 17 | {True: False, False: True}, sort_keys=True), 18 | '{"false": true, "true": false}') 19 | self.assertEquals(json.dumps( 20 | {2: 3.0, 4.0: 5L, False: 1, 6L: True, "7": 0}, sort_keys=True), 21 | '{"false": 1, "2": 3.0, "4.0": 5, "6": true, "7": 0}') 22 | 23 | def test_ordered_dict(self): 24 | # http://bugs.python.org/issue6105 25 | items = [('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)] 26 | s = json.dumps(json.OrderedDict(items)) 27 | self.assertEqual(s, '{"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}') -------------------------------------------------------------------------------- /madcow/include/simplejson/tests/test_encode_for_html.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import simplejson.decoder 4 | import simplejson.encoder 5 | 6 | 7 | class TestEncodeForHTML(unittest.TestCase): 8 | 9 | def setUp(self): 10 | self.decoder = simplejson.decoder.JSONDecoder() 11 | self.encoder = simplejson.encoder.JSONEncoderForHTML() 12 | 13 | def test_basic_encode(self): 14 | self.assertEqual(r'"\u0026"', self.encoder.encode('&')) 15 | self.assertEqual(r'"\u003c"', self.encoder.encode('<')) 16 | self.assertEqual(r'"\u003e"', self.encoder.encode('>')) 17 | 18 | def test_basic_roundtrip(self): 19 | for char in '&<>': 20 | self.assertEqual( 21 | char, self.decoder.decode( 22 | self.encoder.encode(char))) 23 | 24 | def test_prevent_script_breakout(self): 25 | bad_string = '' 26 | self.assertEqual( 27 | r'"\u003c/script\u003e\u003cscript\u003e' 28 | r'alert(\"gotcha\")\u003c/script\u003e"', 29 | self.encoder.encode(bad_string)) 30 | self.assertEqual( 31 | bad_string, self.decoder.decode( 32 | self.encoder.encode(bad_string))) 33 | -------------------------------------------------------------------------------- /madcow/include/simplejson/tests/test_float.py: -------------------------------------------------------------------------------- 1 | import math 2 | from unittest import TestCase 3 | 4 | import simplejson as json 5 | 6 | class TestFloat(TestCase): 7 | def test_floats(self): 8 | for num in [1617161771.7650001, math.pi, math.pi**100, 9 | math.pi**-100, 3.1]: 10 | self.assertEquals(float(json.dumps(num)), num) 11 | self.assertEquals(json.loads(json.dumps(num)), num) 12 | self.assertEquals(json.loads(unicode(json.dumps(num))), num) 13 | 14 | def test_ints(self): 15 | for num in [1, 1L, 1<<32, 1<<64]: 16 | self.assertEquals(json.dumps(num), str(num)) 17 | self.assertEquals(int(json.dumps(num)), num) 18 | self.assertEquals(json.loads(json.dumps(num)), num) 19 | self.assertEquals(json.loads(unicode(json.dumps(num))), num) 20 | -------------------------------------------------------------------------------- /madcow/include/simplejson/tests/test_indent.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | 3 | import simplejson as json 4 | import textwrap 5 | 6 | class TestIndent(TestCase): 7 | def test_indent(self): 8 | h = [['blorpie'], ['whoops'], [], 'd-shtaeou', 'd-nthiouh', 9 | 'i-vhbjkhnth', 10 | {'nifty': 87}, {'field': 'yes', 'morefield': False} ] 11 | 12 | expect = textwrap.dedent("""\ 13 | [ 14 | \t[ 15 | \t\t"blorpie" 16 | \t], 17 | \t[ 18 | \t\t"whoops" 19 | \t], 20 | \t[], 21 | \t"d-shtaeou", 22 | \t"d-nthiouh", 23 | \t"i-vhbjkhnth", 24 | \t{ 25 | \t\t"nifty": 87 26 | \t}, 27 | \t{ 28 | \t\t"field": "yes", 29 | \t\t"morefield": false 30 | \t} 31 | ]""") 32 | 33 | 34 | d1 = json.dumps(h) 35 | d2 = json.dumps(h, indent='\t', sort_keys=True, separators=(',', ': ')) 36 | d3 = json.dumps(h, indent=' ', sort_keys=True, separators=(',', ': ')) 37 | d4 = json.dumps(h, indent=2, sort_keys=True, separators=(',', ': ')) 38 | 39 | h1 = json.loads(d1) 40 | h2 = json.loads(d2) 41 | h3 = json.loads(d3) 42 | h4 = json.loads(d4) 43 | 44 | self.assertEquals(h1, h) 45 | self.assertEquals(h2, h) 46 | self.assertEquals(h3, h) 47 | self.assertEquals(h4, h) 48 | self.assertEquals(d3, expect.replace('\t', ' ')) 49 | self.assertEquals(d4, expect.replace('\t', ' ')) 50 | # NOTE: Python 2.4 textwrap.dedent converts tabs to spaces, 51 | # so the following is expected to fail. Python 2.4 is not a 52 | # supported platform in simplejson 2.1.0+. 53 | self.assertEquals(d2, expect) 54 | -------------------------------------------------------------------------------- /madcow/include/simplejson/tests/test_pass2.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | import simplejson as json 3 | 4 | # from http://json.org/JSON_checker/test/pass2.json 5 | JSON = r''' 6 | [[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] 7 | ''' 8 | 9 | class TestPass2(TestCase): 10 | def test_parse(self): 11 | # test in/out equivalence and parsing 12 | res = json.loads(JSON) 13 | out = json.dumps(res) 14 | self.assertEquals(res, json.loads(out)) 15 | -------------------------------------------------------------------------------- /madcow/include/simplejson/tests/test_pass3.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | 3 | import simplejson as json 4 | 5 | # from http://json.org/JSON_checker/test/pass3.json 6 | JSON = r''' 7 | { 8 | "JSON Test Pattern pass3": { 9 | "The outermost value": "must be an object or array.", 10 | "In this test": "It is an object." 11 | } 12 | } 13 | ''' 14 | 15 | class TestPass3(TestCase): 16 | def test_parse(self): 17 | # test in/out equivalence and parsing 18 | res = json.loads(JSON) 19 | out = json.dumps(res) 20 | self.assertEquals(res, json.loads(out)) 21 | -------------------------------------------------------------------------------- /madcow/include/simplejson/tests/test_recursion.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | 3 | import simplejson as json 4 | 5 | class JSONTestObject: 6 | pass 7 | 8 | 9 | class RecursiveJSONEncoder(json.JSONEncoder): 10 | recurse = False 11 | def default(self, o): 12 | if o is JSONTestObject: 13 | if self.recurse: 14 | return [JSONTestObject] 15 | else: 16 | return 'JSONTestObject' 17 | return json.JSONEncoder.default(o) 18 | 19 | 20 | class TestRecursion(TestCase): 21 | def test_listrecursion(self): 22 | x = [] 23 | x.append(x) 24 | try: 25 | json.dumps(x) 26 | except ValueError: 27 | pass 28 | else: 29 | self.fail("didn't raise ValueError on list recursion") 30 | x = [] 31 | y = [x] 32 | x.append(y) 33 | try: 34 | json.dumps(x) 35 | except ValueError: 36 | pass 37 | else: 38 | self.fail("didn't raise ValueError on alternating list recursion") 39 | y = [] 40 | x = [y, y] 41 | # ensure that the marker is cleared 42 | json.dumps(x) 43 | 44 | def test_dictrecursion(self): 45 | x = {} 46 | x["test"] = x 47 | try: 48 | json.dumps(x) 49 | except ValueError: 50 | pass 51 | else: 52 | self.fail("didn't raise ValueError on dict recursion") 53 | x = {} 54 | y = {"a": x, "b": x} 55 | # ensure that the marker is cleared 56 | json.dumps(x) 57 | 58 | def test_defaultrecursion(self): 59 | enc = RecursiveJSONEncoder() 60 | self.assertEquals(enc.encode(JSONTestObject), '"JSONTestObject"') 61 | enc.recurse = True 62 | try: 63 | enc.encode(JSONTestObject) 64 | except ValueError: 65 | pass 66 | else: 67 | self.fail("didn't raise ValueError on default recursion") 68 | -------------------------------------------------------------------------------- /madcow/include/simplejson/tests/test_separators.py: -------------------------------------------------------------------------------- 1 | import textwrap 2 | from unittest import TestCase 3 | 4 | import simplejson as json 5 | 6 | 7 | class TestSeparators(TestCase): 8 | def test_separators(self): 9 | h = [['blorpie'], ['whoops'], [], 'd-shtaeou', 'd-nthiouh', 'i-vhbjkhnth', 10 | {'nifty': 87}, {'field': 'yes', 'morefield': False} ] 11 | 12 | expect = textwrap.dedent("""\ 13 | [ 14 | [ 15 | "blorpie" 16 | ] , 17 | [ 18 | "whoops" 19 | ] , 20 | [] , 21 | "d-shtaeou" , 22 | "d-nthiouh" , 23 | "i-vhbjkhnth" , 24 | { 25 | "nifty" : 87 26 | } , 27 | { 28 | "field" : "yes" , 29 | "morefield" : false 30 | } 31 | ]""") 32 | 33 | 34 | d1 = json.dumps(h) 35 | d2 = json.dumps(h, indent=' ', sort_keys=True, separators=(' ,', ' : ')) 36 | 37 | h1 = json.loads(d1) 38 | h2 = json.loads(d2) 39 | 40 | self.assertEquals(h1, h) 41 | self.assertEquals(h2, h) 42 | self.assertEquals(d2, expect) 43 | -------------------------------------------------------------------------------- /madcow/include/simplejson/tests/test_speedups.py: -------------------------------------------------------------------------------- 1 | import decimal 2 | from unittest import TestCase 3 | 4 | from simplejson import decoder, encoder, scanner 5 | 6 | def has_speedups(): 7 | return encoder.c_make_encoder is not None 8 | 9 | class TestDecode(TestCase): 10 | def test_make_scanner(self): 11 | if not has_speedups(): 12 | return 13 | self.assertRaises(AttributeError, scanner.c_make_scanner, 1) 14 | 15 | def test_make_encoder(self): 16 | if not has_speedups(): 17 | return 18 | self.assertRaises(TypeError, encoder.c_make_encoder, 19 | None, 20 | "\xCD\x7D\x3D\x4E\x12\x4C\xF9\x79\xD7\x52\xBA\x82\xF2\x27\x4A\x7D\xA0\xCA\x75", 21 | None) 22 | -------------------------------------------------------------------------------- /madcow/include/simplejson/tool.py: -------------------------------------------------------------------------------- 1 | r"""Command-line tool to validate and pretty-print JSON 2 | 3 | Usage:: 4 | 5 | $ echo '{"json":"obj"}' | python -m simplejson.tool 6 | { 7 | "json": "obj" 8 | } 9 | $ echo '{ 1.2:3.4}' | python -m simplejson.tool 10 | Expecting property name: line 1 column 2 (char 2) 11 | 12 | """ 13 | import sys 14 | import simplejson as json 15 | 16 | def main(): 17 | if len(sys.argv) == 1: 18 | infile = sys.stdin 19 | outfile = sys.stdout 20 | elif len(sys.argv) == 2: 21 | infile = open(sys.argv[1], 'rb') 22 | outfile = sys.stdout 23 | elif len(sys.argv) == 3: 24 | infile = open(sys.argv[1], 'rb') 25 | outfile = open(sys.argv[2], 'wb') 26 | else: 27 | raise SystemExit(sys.argv[0] + " [infile [outfile]]") 28 | try: 29 | obj = json.load(infile, 30 | object_pairs_hook=json.OrderedDict, 31 | use_decimal=True) 32 | except ValueError, e: 33 | raise SystemExit(e) 34 | json.dump(obj, outfile, sort_keys=True, indent=' ', use_decimal=True) 35 | outfile.write('\n') 36 | 37 | 38 | if __name__ == '__main__': 39 | main() 40 | -------------------------------------------------------------------------------- /madcow/include/twisted/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- test-case-name: twisted -*- 2 | 3 | # Copyright (c) 2001-2004 Twisted Matrix Laboratories. 4 | # See LICENSE for details. 5 | 6 | 7 | """ 8 | Twisted: The Framework Of Your Internet. 9 | """ 10 | 11 | # Ensure the user is running the version of python we require. 12 | import sys 13 | if not hasattr(sys, "version_info") or sys.version_info < (2,3): 14 | raise RuntimeError("Twisted requires Python 2.3 or later.") 15 | del sys 16 | 17 | # Ensure compat gets imported 18 | from twisted.python import compat 19 | del compat 20 | 21 | # setup version 22 | from twisted._version import version 23 | __version__ = version.short() 24 | 25 | -------------------------------------------------------------------------------- /madcow/include/twisted/_version.py: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. Do not edit it. 2 | from twisted.python import versions 3 | version = versions.Version('twisted', 8, 2, 0) 4 | -------------------------------------------------------------------------------- /madcow/include/twisted/internet/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2001-2008 Twisted Matrix Laboratories. 2 | # See LICENSE for details. 3 | 4 | """ 5 | Twisted Internet: Asynchronous I/O and Events. 6 | 7 | Twisted Internet is a collection of compatible event-loops for Python. It contains 8 | the code to dispatch events to interested observers and a portable API so that 9 | observers need not care about which event loop is running. Thus, it is possible 10 | to use the same code for different loops, from Twisted's basic, yet portable, 11 | select-based loop to the loops of various GUI toolkits like GTK+ or Tk. 12 | """ 13 | -------------------------------------------------------------------------------- /madcow/include/twisted/internet/_baseprocess.py: -------------------------------------------------------------------------------- 1 | # -*- test-case-name: twisted.test.test_process -*- 2 | # Copyright (c) 2008 Twisted Matrix Laboratories. 3 | # See LICENSE for details. 4 | 5 | """ 6 | Cross-platform process-related functionality used by different 7 | L{IReactorProcess} implementations. 8 | """ 9 | 10 | from twisted.python.reflect import qual 11 | from twisted.python.deprecate import getWarningMethod 12 | from twisted.python.failure import Failure 13 | from twisted.python.log import err 14 | from twisted.persisted.styles import Ephemeral 15 | 16 | _missingProcessExited = ("Since Twisted 8.2, IProcessProtocol.processExited " 17 | "is required. %s must implement it.") 18 | 19 | class BaseProcess(Ephemeral): 20 | pid = None 21 | status = None 22 | lostProcess = 0 23 | proto = None 24 | 25 | def __init__(self, protocol): 26 | self.proto = protocol 27 | 28 | 29 | def _callProcessExited(self, reason): 30 | default = object() 31 | processExited = getattr(self.proto, 'processExited', default) 32 | if processExited is default: 33 | getWarningMethod()( 34 | _missingProcessExited % (qual(self.proto.__class__),), 35 | DeprecationWarning, stacklevel=0) 36 | else: 37 | processExited(Failure(reason)) 38 | 39 | 40 | def processEnded(self, status): 41 | """ 42 | This is called when the child terminates. 43 | """ 44 | self.status = status 45 | self.lostProcess += 1 46 | self.pid = None 47 | self._callProcessExited(self._getReason(status)) 48 | self.maybeCallProcessEnded() 49 | 50 | 51 | def maybeCallProcessEnded(self): 52 | """ 53 | Call processEnded on protocol after final cleanup. 54 | """ 55 | if self.proto is not None: 56 | reason = self._getReason(self.status) 57 | proto = self.proto 58 | self.proto = None 59 | try: 60 | proto.processEnded(Failure(reason)) 61 | except: 62 | err(None, "unexpected error in processEnded") 63 | -------------------------------------------------------------------------------- /madcow/include/twisted/internet/main.py: -------------------------------------------------------------------------------- 1 | # -*- test-case-name: twisted.test.test_app -*- 2 | # Copyright (c) 2001-2004 Twisted Matrix Laboratories. 3 | # See LICENSE for details. 4 | 5 | 6 | """Backwards compatability, and utility functions. 7 | 8 | In general, this module should not be used, other than by reactor authors 9 | who need to use the 'installReactor' method. 10 | 11 | Maintainer: Itamar Shtull-Trauring 12 | """ 13 | 14 | import error 15 | 16 | CONNECTION_DONE = error.ConnectionDone('Connection done') 17 | CONNECTION_LOST = error.ConnectionLost('Connection lost') 18 | 19 | def installReactor(reactor): 20 | # this stuff should be common to all reactors. 21 | from twisted import internet 22 | import sys 23 | assert not sys.modules.has_key('twisted.internet.reactor'), \ 24 | "reactor already installed" 25 | internet.reactor = reactor 26 | sys.modules['twisted.internet.reactor'] = reactor 27 | 28 | __all__ = ["CONNECTION_LOST", "CONNECTION_DONE", "installReactor"] 29 | -------------------------------------------------------------------------------- /madcow/include/twisted/internet/reactor.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2001-2008 Twisted Matrix Laboratories. 2 | # See LICENSE for details. 3 | 4 | """ 5 | The reactor is the Twisted event loop within Twisted, the loop which drives 6 | applications using Twisted. The reactor provides APIs for networking, 7 | threading, dispatching events, and more. 8 | 9 | The default reactor is based on C{select(2)} and will be installed if this 10 | module is imported without another reactor being explicitly installed. 11 | Regardless of which reactor is installed, importing this module is the correct 12 | way to get a reference to it. 13 | 14 | New application code should prefer to pass and accept the reactor as a 15 | parameter where it is needed, rather than relying on being able to import this 16 | module to get a reference. This simplifies unit testing and may make it easier 17 | to one day support multiple reactors (as a performance enhancement), though 18 | this is not currently possible. 19 | 20 | @see: L{IReactorCore} 21 | @see: L{IReactorTime} 22 | @see: L{IReactorProcess} 23 | @see: L{IReactorTCP} 24 | @see: L{IReactorSSL} 25 | @see: L{IReactorUDP} 26 | @see: L{IReactorMulticast} 27 | @see: L{IReactorUNIX} 28 | @see: L{IReactorUNIXDatagram} 29 | @see: L{IReactorFDSet} 30 | @see: L{IReactorThreads} 31 | @see: L{IReactorArbitrary} 32 | @see: L{IReactorPluggableResolver} 33 | """ 34 | 35 | import sys 36 | del sys.modules['twisted.internet.reactor'] 37 | from twisted.internet import selectreactor 38 | selectreactor.install() 39 | -------------------------------------------------------------------------------- /madcow/include/twisted/persisted/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) 2001-2004 Twisted Matrix Laboratories. 3 | # See LICENSE for details. 4 | 5 | 6 | """ 7 | 8 | Twisted Persisted: utilities for managing persistence. 9 | 10 | """ 11 | -------------------------------------------------------------------------------- /madcow/include/twisted/python/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | # Copyright (c) 2001-2004 Twisted Matrix Laboratories. 3 | # See LICENSE for details. 4 | 5 | 6 | """ 7 | 8 | Twisted Python: Utilities and Enhancements for Python. 9 | 10 | """ 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /madcow/include/twisted/python/hashlib.py: -------------------------------------------------------------------------------- 1 | # -*- test-case-name: twisted.python.test.test_hashlib -*- 2 | # Copyright (c) 2008 Twisted Matrix Laboratories. 3 | # See LICENSE for details. 4 | 5 | """ 6 | L{twisted.python.hashlib} presents a subset of the interface provided by 7 | U{hashlib}. The subset is the 8 | interface required by various parts of Twisted. This allows application code 9 | to transparently use APIs which existed before C{hashlib} was introduced or to 10 | use C{hashlib} if it is available. 11 | """ 12 | 13 | 14 | try: 15 | _hashlib = __import__("hashlib") 16 | except ImportError: 17 | from md5 import md5 18 | from sha import sha as sha1 19 | else: 20 | md5 = _hashlib.md5 21 | sha1 = _hashlib.sha1 22 | 23 | 24 | __all__ = ["md5", "sha1"] 25 | -------------------------------------------------------------------------------- /madcow/include/twisted/words/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- test-case-name: twisted.words.test -*- 2 | # Copyright (c) 2001-2005 Twisted Matrix Laboratories. 3 | # See LICENSE for details. 4 | 5 | 6 | """Twisted Words: a Twisted Chat service. 7 | """ 8 | 9 | from twisted.words._version import version 10 | __version__ = version.short() 11 | -------------------------------------------------------------------------------- /madcow/include/twisted/words/_version.py: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. Do not edit it. 2 | from twisted.python import versions 3 | version = versions.Version('twisted.words', 8, 2, 0) 4 | -------------------------------------------------------------------------------- /madcow/include/twisted/words/protocols/__init__.py: -------------------------------------------------------------------------------- 1 | "Chat protocols" 2 | -------------------------------------------------------------------------------- /madcow/include/twitter/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # vim: sw=2 ts=2 sts=2 4 | # 5 | # Copyright 2007 The Python-Twitter Developers 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | 19 | '''A library that provides a Python interface to the Twitter API''' 20 | 21 | __author__ = 'python-twitter@googlegroups.com' 22 | __version__ = '2.0' 23 | 24 | try: 25 | # Python >= 2.6 26 | import json as simplejson 27 | except ImportError: 28 | try: 29 | # Python < 2.6 30 | import simplejson 31 | except ImportError: 32 | try: 33 | # Google App Engine 34 | from django.utils import simplejson 35 | except ImportError: 36 | raise ImportError, "Unable to load a json library" 37 | # parse_qsl moved to urlparse module in v2.6 38 | try: 39 | from urlparse import parse_qsl, parse_qs 40 | except ImportError: 41 | from cgi import parse_qsl, parse_qs 42 | 43 | try: 44 | from hashlib import md5 45 | except ImportError: 46 | from md5 import md5 47 | 48 | from _file_cache import _FileCache 49 | from error import TwitterError 50 | from direct_message import DirectMessage 51 | from hashtag import Hashtag 52 | from parse_tweet import ParseTweet 53 | from trend import Trend 54 | from url import Url 55 | from status import Status 56 | from user import User, UserStatus 57 | from list import List 58 | from api import Api 59 | -------------------------------------------------------------------------------- /madcow/include/twitter/error.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | class TwitterError(Exception): 4 | '''Base class for Twitter errors''' 5 | 6 | @property 7 | def message(self): 8 | '''Returns the first argument used to construct this error.''' 9 | return self.args[0] 10 | -------------------------------------------------------------------------------- /madcow/include/twitter/hashtag.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from twitter import TwitterError 4 | 5 | class Hashtag(object): 6 | ''' A class representing a twitter hashtag 7 | ''' 8 | def __init__(self, 9 | text=None): 10 | self.text = text 11 | 12 | @staticmethod 13 | def NewFromJsonDict(data): 14 | '''Create a new instance based on a JSON dict. 15 | 16 | Args: 17 | data: 18 | A JSON dict, as converted from the JSON in the twitter API 19 | 20 | Returns: 21 | A twitter.Hashtag instance 22 | ''' 23 | return Hashtag(text=data.get('text', None)) 24 | -------------------------------------------------------------------------------- /madcow/include/twitter/trend.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from twitter import TwitterError 4 | 5 | class Trend(object): 6 | ''' A class representing a trending topic 7 | ''' 8 | def __init__(self, name=None, query=None, timestamp=None, url=None): 9 | self.name = name 10 | self.query = query 11 | self.timestamp = timestamp 12 | self.url = url 13 | 14 | def __repr__(self): 15 | return self.name 16 | 17 | def __str__(self): 18 | return 'Name: %s\nQuery: %s\nTimestamp: %s\nSearch URL: %s\n' % (self.name, self.query, self.timestamp, self.url) 19 | 20 | def __ne__(self, other): 21 | return not self.__eq__(other) 22 | 23 | def __eq__(self, other): 24 | try: 25 | return other and \ 26 | self.name == other.name and \ 27 | self.query == other.query and \ 28 | self.timestamp == other.timestamp and \ 29 | self.url == self.url 30 | except AttributeError: 31 | return False 32 | 33 | @staticmethod 34 | def NewFromJsonDict(data, timestamp=None): 35 | '''Create a new instance based on a JSON dict 36 | 37 | Args: 38 | data: 39 | A JSON dict 40 | timestamp: 41 | Gets set as the timestamp property of the new object 42 | 43 | Returns: 44 | A twitter.Trend object 45 | ''' 46 | return Trend(name=data.get('name', None), 47 | query=data.get('query', None), 48 | url=data.get('url', None), 49 | timestamp=timestamp) 50 | -------------------------------------------------------------------------------- /madcow/include/twitter/url.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from twitter import TwitterError 4 | 5 | class Url(object): 6 | '''A class representing an URL contained in a tweet''' 7 | def __init__(self, 8 | url=None, 9 | expanded_url=None): 10 | self.url = url 11 | self.expanded_url = expanded_url 12 | 13 | @staticmethod 14 | def NewFromJsonDict(data): 15 | '''Create a new instance based on a JSON dict. 16 | 17 | Args: 18 | data: 19 | A JSON dict, as converted from the JSON in the twitter API 20 | 21 | Returns: 22 | A twitter.Url instance 23 | ''' 24 | return Url(url=data.get('url', None), 25 | expanded_url=data.get('expanded_url', None)) 26 | -------------------------------------------------------------------------------- /madcow/include/zope/__init__.py: -------------------------------------------------------------------------------- 1 | # this is a namespace package 2 | try: 3 | import pkg_resources 4 | pkg_resources.declare_namespace(__name__) 5 | except ImportError: 6 | import pkgutil 7 | __path__ = pkgutil.extend_path(__path__, __name__) 8 | -------------------------------------------------------------------------------- /madcow/include/zope/interface/ro.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # 3 | # Copyright (c) 2003 Zope Corporation and Contributors. 4 | # All Rights Reserved. 5 | # 6 | # This software is subject to the provisions of the Zope Public License, 7 | # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. 8 | # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 9 | # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 10 | # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 11 | # FOR A PARTICULAR PURPOSE. 12 | # 13 | ############################################################################## 14 | """Compute a resolution order for an object and it's bases 15 | 16 | $Id: ro.py 70897 2006-10-24 08:21:55Z flox $ 17 | """ 18 | __docformat__ = 'restructuredtext' 19 | 20 | 21 | def ro(object): 22 | """Compute a "resolution order" for an object 23 | """ 24 | return mergeOrderings([_flatten(object, [])]) 25 | 26 | def mergeOrderings(orderings, seen=None): 27 | """Merge multiple orderings so that within-ordering order is preserved 28 | 29 | Orderings are constrained in such a way that if an object appears 30 | in two or more orderings, then the suffix that begins with the 31 | object must be in both orderings. 32 | 33 | For example: 34 | 35 | >>> _mergeOrderings([ 36 | ... ['x', 'y', 'z'], 37 | ... ['q', 'z'], 38 | ... [1, 3, 5], 39 | ... ['z'] 40 | ... ]) 41 | ['x', 'y', 'q', 1, 3, 5, 'z'] 42 | 43 | """ 44 | 45 | if seen is None: 46 | seen = {} 47 | result = [] 48 | orderings.reverse() 49 | for ordering in orderings: 50 | ordering = list(ordering) 51 | ordering.reverse() 52 | for o in ordering: 53 | if o not in seen: 54 | seen[o] = 1 55 | result.append(o) 56 | 57 | result.reverse() 58 | return result 59 | 60 | def _flatten(ob, result): 61 | result.append(ob) 62 | for base in ob.__bases__: 63 | _flatten(base, result) 64 | 65 | return result 66 | -------------------------------------------------------------------------------- /madcow/modules/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | activestate.blog 3 | activestate.company 4 | activestate.links 5 | activestate.notes 6 | activestate.realname 7 | activestate.staff 8 | activestate.welcome 9 | activestate.xray 10 | 11 | broken.beer 12 | broken.bible 13 | broken.chp 14 | broken.clock 15 | broken.cnn 16 | broken.delicious 17 | broken.election 18 | broken.fmylife 19 | broken.movie 20 | broken.sunrise 21 | broken.terror 22 | broken.texts 23 | broken.translate 24 | broken.urban 25 | broken.yelp 26 | 27 | contrib.djmemebot 28 | contrib.pollmail 29 | contrib.steam 30 | contrib.summon 31 | contrib.twitter 32 | 33 | local.alias 34 | local.care 35 | local.factoids 36 | local.figlet 37 | local.grufti 38 | local.jinx 39 | local.karma 40 | local.learn 41 | local.megahal 42 | local.memebot 43 | local.obama 44 | local.roll 45 | local.seen 46 | 47 | remote.area 48 | remote.artfart 49 | remote.bash 50 | remote.bbcnews 51 | remote.calc 52 | remote.chuck 53 | remote.dictionary 54 | remote.google 55 | remote.joke 56 | remote.livejournal 57 | remote.lyrics 58 | remote.nslookup 59 | remote.slut 60 | remote.spellcheck 61 | remote.stockquote 62 | remote.trek 63 | remote.weather 64 | remote.webtender 65 | remote.wikihow 66 | remote.wikimedia 67 | remote.wikiquotes 68 | remote.wolfram 69 | remote.woot 70 | remote.youtube 71 | ''' 72 | -------------------------------------------------------------------------------- /madcow/modules/area.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """This module looks up area codes and returns the most likely city""" 4 | 5 | import re 6 | from madcow.util import Module 7 | from madcow.util.text import * 8 | 9 | render = lambda node: decode(node.renderContents(), 'utf-8').strip() 10 | proper = lambda name: ' '.join(word.capitalize() for word in name.split()) 11 | 12 | class Main(Module): 13 | 14 | pattern = re.compile(u'^\s*area(?:\s+code)?\s+(\d+)\s*', re.I) 15 | require_addressing = True 16 | help = u'area - what city does it belong to' 17 | url = 'http://www.melissadata.com/lookups/ZipCityPhone.asp' 18 | error = u"I couldn't look that up for some reason. D:" 19 | 20 | def response(self, nick, args, kwargs): 21 | soup = self.getsoup(self.url, {'InData': args[0]}) 22 | city = soup.body.find('table', bgcolor='#ffffcc').a 23 | return u'%s: %s: %s, %s' % ( 24 | nick, args[0], proper(render(city).capitalize()), 25 | proper(render(city.parent.findNext('td')))) 26 | -------------------------------------------------------------------------------- /madcow/modules/artfart.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Get a random offensive ASCII art""" 4 | 5 | from urlparse import urljoin 6 | import re 7 | import random 8 | import urllib 9 | from madcow.util import Module, strip_html 10 | 11 | class Main(Module): 12 | 13 | pattern = re.compile(r'^\s*artfart(?:\s+(.+?))?\s*$', re.I) 14 | require_addressing = True 15 | help = u'artfart - displays some offensive ascii art' 16 | baseurl = u'http://www.asciiartfarts.com/' 17 | random_url = urljoin(baseurl, u'random.cgi') 18 | artfart = re.compile(r'

#\d+: (.*?)

.*?(
.*?
)', re.DOTALL) 19 | error = u"I had a problem with that, sorry." 20 | 21 | def response(self, nick, args, kwargs): 22 | kwargs['req'].blockquoted = True 23 | query = args[0] 24 | if query is None or query == u'': 25 | url = self.random_url 26 | else: 27 | query = u' '.join(query.split()) 28 | query = query.replace(u' ', u'_') 29 | query = urllib.quote(query) + u'.html' 30 | url = urljoin(self.baseurl, query) 31 | doc = self.geturl(url) 32 | results = self.artfart.findall(doc) 33 | result = random.choice(results) 34 | title, art = result 35 | art = strip_html(art) 36 | return u'>>> %s <<<\n%s' % (title, art) 37 | -------------------------------------------------------------------------------- /madcow/modules/bbcnews.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Scrape BBC news""" 4 | 5 | import re 6 | import feedparser 7 | from madcow.util import Module 8 | import urllib 9 | from urlparse import urljoin 10 | 11 | class Main(Module): 12 | 13 | pattern = re.compile(u'^\s*bbc(?:news)?\s*$', re.I) 14 | require_addressing = True 15 | help = u'bbcnews - get BBC headline news' 16 | error = u'Looks like the BBC aren\'t co-operating today.' 17 | 18 | _rss_url = u'http://newsrss.bbc.co.uk/' 19 | _world_url = urljoin(_rss_url, u'/rss/newsonline_uk_edition/world/rss.xml') 20 | 21 | def response(self, nick, args, kwargs): 22 | item = feedparser.parse(self._world_url).entries[0] 23 | return u' | '.join([item.link, item.description, item.updated]) 24 | -------------------------------------------------------------------------------- /madcow/modules/beer.py: -------------------------------------------------------------------------------- 1 | """Restaraunt reviews""" 2 | 3 | from madcow.util import Module 4 | from urlparse import urljoin 5 | import re 6 | 7 | class Main(Module): 8 | 9 | baseurl = 'http://beeradvocate.com/' 10 | searchurl = baseurl + 'search' 11 | pattern = re.compile(r'^\s*beer\s+(.+?)\s*$', re.I) 12 | help = 'beer - BEER' 13 | 14 | def response(self, nick, args, kwargs): 15 | page = self.getsoup(self.searchurl, q=args[0], qt='beer', retired='N') 16 | content = page.find('div', id='ba-content') 17 | url = urljoin(self.baseurl, content.ul.li.a['href']) 18 | page = self.getsoup(url) 19 | return page.find('meta', property='og:description')['content'] 20 | -------------------------------------------------------------------------------- /madcow/modules/blog.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Grab the latest blog post from an RSS feed""" 4 | 5 | """ Copyright 2013 ActiveState Software Inc. """ 6 | 7 | import re 8 | import feedparser 9 | from madcow.util import Module 10 | from madcow.conf import settings 11 | import urllib 12 | from urlparse import urljoin 13 | 14 | class Main(Module): 15 | 16 | pattern = re.compile(u'^\s*blog\s*$', re.I) 17 | require_addressing = False 18 | _rss_url = settings.BLOG_RSS_URL 19 | help = u'blog - get the latest blog post from %s' % (_rss_url) 20 | error = u'Looks like the blog isn\'t co-operating today.' 21 | 22 | def response(self, nick, args, kwargs): 23 | entries = feedparser.parse(self._rss_url).entries 24 | if entries: 25 | item = entries[0] 26 | return u'\n'.join([item.title, item.link, item.updated]) 27 | else: 28 | return u'%s' % (self.error) 29 | -------------------------------------------------------------------------------- /madcow/modules/calc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Use Google as a calculator""" 4 | 5 | import re 6 | from madcow.util import Module 7 | from google import Google 8 | 9 | class Main(Module): 10 | 11 | pattern = re.compile(u'^\s*calc\s+(.+)', re.I) 12 | require_addressing = True 13 | help = u'calc - pass expression to google calculator' 14 | error = 'No results (bad syntax?)' 15 | 16 | def init(self): 17 | self.google = Google() 18 | 19 | def response(self, nick, args, kwargs): 20 | return u'%s: %s' % (nick, self.google.calculator(args[0])) 21 | -------------------------------------------------------------------------------- /madcow/modules/chuck.py: -------------------------------------------------------------------------------- 1 | """Get a random joke""" 2 | 3 | from madcow.util import Module 4 | import re 5 | import json 6 | 7 | 8 | class Main(Module): 9 | 10 | pattern = re.compile(r'^\s*chuck(?:\s+(.+?))?\s*$', re.I) 11 | require_addressing = True 12 | help = (u'Chuck Norris won\'t help you') 13 | baseurl = u'http://api.icndb.com/jokes/random' 14 | 15 | def response(self, nick, args, kwargs): 16 | doc = json.loads(self.geturl(self.baseurl)) 17 | return doc['value']['joke'].replace('"', "'") 18 | -------------------------------------------------------------------------------- /madcow/modules/clock.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Use Google to get time's in various places""" 4 | 5 | from madcow.util import Module 6 | from google import Google 7 | import re 8 | 9 | class Main(Module): 10 | 11 | pattern = re.compile(r'^\s*(?:clock|time)(?:\s*[:-]\s*|\s+)(.+?)\s*$', re.I) 12 | help = u'time - ask google what time it is somewhere' 13 | in_re = re.compile(r'^\s*in\s+', re.I) 14 | 15 | def init(self): 16 | self.google = Google() 17 | 18 | def response(self, nick, args, kwargs): 19 | query = args[0] 20 | query = self.in_re.sub('', query) 21 | result = self.google.clock(query) 22 | if result: 23 | return u'%s: %s' % (nick, result) 24 | else: 25 | return u"%s: They don't do the whole time thing in \"%s\"" % (nick, query) 26 | -------------------------------------------------------------------------------- /madcow/modules/cnn.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """CNN Headline""" 4 | 5 | import re 6 | import feedparser 7 | from madcow.util import strip_html, Module 8 | 9 | class Main(Module): 10 | 11 | pattern = re.compile(r'^\s*cnn\s*$', re.I) 12 | help = 'cnn - cnn headline' 13 | url = 'http://rss.cnn.com/rss/cnn_topstories.rss' 14 | 15 | def response(self, nick, args, kwargs): 16 | item = feedparser.parse(self.url).entries[0] 17 | body = strip_html(item.description).strip() 18 | return u' | '.join([item.link, body, item.updated]) 19 | -------------------------------------------------------------------------------- /madcow/modules/dictionary.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Look up word definitions""" 4 | 5 | from urlparse import urljoin 6 | from urllib import quote 7 | import re 8 | from madcow.util import strip_html, Module 9 | from madcow.util.text import * 10 | 11 | class Main(Module): 12 | 13 | pattern = re.compile(r'^\s*def(?:ine)?\s+(.+?)\s*$', re.I) 14 | help = 'define - get a definition' 15 | base_url = 'http://definr.com/' 16 | define_url = urljoin(base_url, '/definr/show/toe') 17 | whitespace_re = re.compile(r'\s{2,}') 18 | error = u'Stop making words up' 19 | 20 | def response(self, nick, args, kwargs): 21 | return u'%s: %s' % (nick, self.lookup(args[0])) 22 | 23 | def lookup(self, term, idx=1): 24 | """Lookup term in dictionary""" 25 | url = urljoin(self.define_url, quote(term.lower())) 26 | soup = self.getsoup(url, referer=self.base_url) 27 | for br in soup('br'): 28 | br.extract() 29 | val = strip_html(decode(soup.renderContents(), 'utf-8')) 30 | val = val.replace(u'\xa0', ' ').replace('\n', ' ') 31 | return self.whitespace_re.sub(' ', val).strip() 32 | -------------------------------------------------------------------------------- /madcow/modules/election.py: -------------------------------------------------------------------------------- 1 | """Predicted Electoral Vote Count""" 2 | 3 | import re 4 | from madcow.util.color import ColorLib 5 | from madcow.util import Module, strip_html 6 | 7 | class Main(Module): 8 | 9 | pattern = re.compile(r'^\s*(election|ev)\s*$', re.I) 10 | help = u'ev - current election 2008 vote prediction' 11 | baseurl = u'http://www.electoral-vote.com/' 12 | 13 | def init(self): 14 | if self.madcow is None: 15 | self.colorlib = ColorLib('ansi') 16 | else: 17 | self.colorlib = self.madcow.colorlib 18 | 19 | def colorize(self, color, key, val): 20 | return u'%s: %s' % (key, val) 21 | 22 | def render(self, node): 23 | pass 24 | 25 | def response(self, nick, args, kwargs): 26 | soup = self.getsoup(self.baseurl) 27 | out = [] 28 | for box in soup.find('div', 'score-box').findAll('div', 'box'): 29 | score = [] 30 | for key in 'name', 'score': 31 | val = strip_html(box.find('span', key).renderContents()).replace(u'\xa0', u'').strip() 32 | if key == 'name': 33 | if val == u'Obama': 34 | color = 'blue' 35 | elif val == 'Romney': 36 | color = 'red' 37 | else: 38 | color = None 39 | if color: 40 | val = self.colorlib.get_color(color, text=val) 41 | if val: 42 | score.append(val) 43 | if score: 44 | out.append(u'%s: %s' % tuple(score)) 45 | return u'%s: %s' % (nick, u', '.join(out)) 46 | #from IPython.Shell import IPShellEmbed as S; #S()() 47 | -------------------------------------------------------------------------------- /madcow/modules/figlet.py: -------------------------------------------------------------------------------- 1 | """Generate ASCII text using figlet! """ 2 | 3 | import re 4 | import pyfiglet 5 | from madcow.util import Module, encoding 6 | import random 7 | import os 8 | 9 | __author__ = u'James Johnston ' 10 | 11 | class Main(Module): 12 | 13 | pattern = re.compile(u'^\s*figlet\s+(.+?)\s*$') 14 | require_addressing = True 15 | allow_threading = False 16 | help = u'figlet - ASCII text generator' 17 | 18 | # pre-approved list of fonts to use 19 | fonts = ( 20 | u'5lineoblique', u'acrobatic', u'alligator', u'alligator2', u'asc_____', 21 | u'ascii___', u'avatar', u'big', u'bigchief', u'block', u'bubble', 22 | u'bulbhead', u'chunky', u'colossal', u'computer', u'cosmic', 23 | u'crawford', u'cursive', u'digital', u'dotmatrix', u'double', 24 | u'drpepper', u'eftifont', u'eftirobot', u'eftiwall', u'eftiwater', 25 | u'epic', u'fourtops', u'fuzzy', u'goofy', u'graceful', u'gradient', 26 | u'graffiti', u'hollywood', u'invita', u'italic', u'larry3d', u'lean', 27 | u'maxfour', u'mini', u'nvscript', u'o8', u'pawp', u'pepper', u'puffy', 28 | u'rectangles', u'shadow', u'slant', u'small', u'smkeyboard', 29 | u'smshadow', u'smslant', u'speed', u'stampatello', u'standard', 30 | u'straight', u'twopoint' 31 | ) 32 | 33 | def init(self): 34 | self.zipfile = os.path.join(os.path.dirname(pyfiglet.__file__), 'fonts.zip') 35 | 36 | def response(self, nick, args, kwargs): 37 | kwargs['req'].blockquoted = True 38 | figlet = pyfiglet.Figlet(zipfile=self.zipfile) 39 | figlet.set_font(font_name=random.choice(self.fonts)) 40 | return encoding.convert(figlet.render_text(args[0])) 41 | -------------------------------------------------------------------------------- /madcow/modules/fmylife.py: -------------------------------------------------------------------------------- 1 | """Get a random confession from fmylife.com""" 2 | 3 | from madcow.util import Module, strip_html 4 | from madcow.util.text import * 5 | from urlparse import urljoin 6 | import re 7 | 8 | class Main(Module): 9 | 10 | pattern = re.compile(u'^\s*fml\s*(\d+)?\s*$', re.I) 11 | require_addressing = True 12 | help = u'fml - misery from fmylife.com' 13 | base_url = 'http://www.fmylife.com/' 14 | rand_url = urljoin(base_url, 'random') 15 | spec_url = urljoin(base_url, '%d') 16 | error = u'Today I couldn\'t seem to access fmylife.com.. FML' 17 | 18 | def response(self, nick, args, kwargs): 19 | soup = self.getsoup(self.spec_url % int(args[0]) if args[0] else self.rand_url) 20 | entry = soup.body('a', 'fmllink')[0] 21 | id = int(entry['href'].split('/')[-1]) 22 | body = strip_html(decode(entry.renderContents())) 23 | return u'%s: (%d) %s' % (nick, id, body) 24 | -------------------------------------------------------------------------------- /madcow/modules/google.py: -------------------------------------------------------------------------------- 1 | """I'm feeling lucky""" 2 | 3 | from madcow.util import Module 4 | import re 5 | from madcow.util.google import Google 6 | 7 | class Main(Module): 8 | 9 | pattern = re.compile(r'^(?:search|g(?:oog(?:le)?)?)\s+(.+)\s*$', re.I) 10 | require_addressing = True 11 | help = u"(g[oog[le]]|search) - i'm feeling lucky" 12 | error = u'not so lucky today..' 13 | 14 | def init(self): 15 | self.google = Google() 16 | 17 | def response(self, nick, args, kwargs): 18 | query = args[0] 19 | return u'{}: {}'.format(nick, self.google.lucky(query)) 20 | -------------------------------------------------------------------------------- /madcow/modules/inspirobot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Interface for getting really stupid IRC quotes""" 4 | 5 | import re 6 | import requests 7 | from madcow.util import Module, strip_html 8 | 9 | 10 | class Main(Module): 11 | 12 | pattern = re.compile(u'^\s*(inspire|inspirobot)(?:\s+(\S+))?', re.I) 13 | require_addressing = True 14 | help = u'inspire - get inspirational image' 15 | url = 'http://inspirobot.me/api?generate=true' 16 | error = u':(' 17 | 18 | def response(self, nick, args, kwargs): 19 | r = requests.get(url) 20 | if r.ok: 21 | return r.content 22 | -------------------------------------------------------------------------------- /madcow/modules/joke.py: -------------------------------------------------------------------------------- 1 | """Get a random joke""" 2 | 3 | from madcow.util import Module, strip_html 4 | from madcow.util.text import * 5 | import re 6 | from urlparse import urljoin 7 | import urllib 8 | 9 | class Main(Module): 10 | 11 | pattern = re.compile(r'^\s*joke(?:\s+(.+?))?\s*$', re.I) 12 | require_addressing = True 13 | help = (u'joke - displ' 16 | u'ays a random joke') 17 | baseurl = u'http://www.randomjoke.com/topic/' 18 | random_url = urljoin(baseurl, u'haha.php') 19 | joke = re.compile(r'next.joke.*?

(.*?)

', re.DOTALL) 20 | 21 | def response(self, nick, args, kwargs): 22 | query = args[0] 23 | if query is None or query == u'': 24 | url = self.random_url 25 | else: 26 | query = u' '.join(query.split()) 27 | query = query.replace(u' ', u'_') 28 | query = encode(query, 'utf-8') 29 | query = urllib.quote(query) + u'.php' 30 | url = urljoin(self.baseurl, query) 31 | doc = self.geturl(url) 32 | result = self.joke.findall(doc)[0] 33 | result = strip_html(result) 34 | 35 | # cleanup output a bit.. some funny whitespace in it -cj 36 | result = result.replace(u'\x14', u' ') 37 | result = result.replace(u'\n', u' ') 38 | result = re.sub(r'\s{2,}', u' ', result) 39 | return result.strip() 40 | -------------------------------------------------------------------------------- /madcow/modules/learn.py: -------------------------------------------------------------------------------- 1 | """Module to handle learning""" 2 | 3 | import re 4 | from madcow.util import Module 5 | from madcow.util.text import * 6 | import os 7 | 8 | try: 9 | import dbm 10 | except ImportError: 11 | import anydbm as dbm 12 | 13 | class Main(Module): 14 | 15 | pattern = re.compile(u'^\s*set\s+(\S+)\s+(\S+)\s+(.+)$', re.I) 16 | require_addressing = True 17 | allow_threading = False 18 | help = u'set - set db attribs' 19 | _allowed = [u'location', u'email', u'karma'] 20 | 21 | def __init__(self, madcow=None): 22 | self.prefix = madcow.base 23 | 24 | def dbfile(self, db): 25 | return os.path.join(self.prefix, 'db', db) 26 | 27 | def dbm(self, db): 28 | dbfile = self.dbfile(db) 29 | return dbm.open(dbfile, u'c', 0640) 30 | 31 | def get_db(self, db): 32 | dbm = self.dbm(db) 33 | try: 34 | return dict(dbm) 35 | finally: 36 | dbm.close() 37 | 38 | def lookup(self, db, key): 39 | dbm = self.dbm(db) 40 | try: 41 | key = encode(key.lower()) 42 | if dbm.has_key(key): 43 | return decode(dbm[key]) 44 | finally: 45 | dbm.close() 46 | 47 | def set(self, db, key, val): 48 | dbm = self.dbm(db) 49 | try: 50 | key = encode(key.lower()) 51 | val = encode(val) 52 | dbm[key] = val 53 | finally: 54 | dbm.close() 55 | 56 | def response(self, nick, args, kwargs): 57 | db, key, val = args 58 | if db not in self._allowed: 59 | return u'%s: unknown database' % nick 60 | self.set(db, key, val) 61 | return u'%s: set %s\'s %s to %s' % (nick, key, db, val) 62 | -------------------------------------------------------------------------------- /madcow/modules/livejournal.py: -------------------------------------------------------------------------------- 1 | """Read from LiveJournal""" 2 | 3 | import re 4 | import feedparser 5 | from madcow.util import Module, strip_html 6 | from urlparse import urljoin 7 | 8 | class Main(Module): 9 | 10 | enabled = True 11 | pattern = re.compile(u'^\s*(?:livejournal|lj)(?:\s+(\S+))?') 12 | require_addressing = True 13 | help = u'lj [user] - get latest entry to an lj, omit user for a random one' 14 | baseURL = u'http://livejournal.com' 15 | randomURL = urljoin(baseURL, u'/random.bml') 16 | max = 800 17 | error = u"Couldn't load the page LJ returned D:" 18 | 19 | def response(self, nick, args, kwargs): 20 | kwargs['req'].blockquoted = True 21 | try: 22 | user = args[0] 23 | except: 24 | user = None 25 | if user is None or user == u'': 26 | doc = self.geturl(self.randomURL) 27 | user = re.search(u'"currentJournal":\s*"(.*?)"', doc).group(1) 28 | url = urljoin(self.baseURL, u'/users/%s/data/rss' % user) 29 | rss = feedparser.parse(url) 30 | entry = strip_html(rss.entries[0].description)[:self.max] 31 | page = strip_html(rss.channel.link) 32 | return u'%s: [%s] %s' % (nick, page, entry) 33 | -------------------------------------------------------------------------------- /madcow/modules/nslookup.py: -------------------------------------------------------------------------------- 1 | """Perform DNS lookups""" 2 | 3 | import re 4 | import socket 5 | from madcow.util import Module 6 | 7 | class Main(Module): 8 | 9 | pattern = re.compile(u'^\s*nslookup\s+(\S+)') 10 | require_addressing = True 11 | help = u'nslookup - perform DNS lookup' 12 | _byip = re.compile(r'^(\d+\.){3}\d+$') 13 | 14 | def response(self, nick, args, kwargs): 15 | query = args[0] 16 | if self._byip.search(query): 17 | try: 18 | response = socket.gethostbyaddr(query)[0] 19 | except: 20 | response = u'No hostname for that IP' 21 | else: 22 | try: 23 | response = socket.gethostbyname(query) 24 | except: 25 | response = u'No IP for that hostname' 26 | return u'%s: %s' % (nick, response) 27 | -------------------------------------------------------------------------------- /madcow/modules/pollmail.py: -------------------------------------------------------------------------------- 1 | """Poll email address""" 2 | 3 | import re 4 | import imaplib 5 | import json as JSON 6 | from madcow.util import Module 7 | from madcow.conf import settings 8 | from madcow.util.text import * 9 | from madcow.util.imap import ImapPoller 10 | 11 | class Main(Module): 12 | pattern = re.compile(r'^\s*pollmail\s+(.+?)\s*$') 13 | help = '\n'.join([ 14 | 'start - start automatic polling of email for messages', 15 | 'stop - stop automatic polling of email for messages', 16 | 'now - force one-time poll' 17 | ]) 18 | error = u"I had an error" 19 | 20 | def init(self): 21 | try: 22 | self.madcow.imap_poller 23 | except AttributeError: 24 | self.madcow.imap_poller = ImapPoller(self.madcow) 25 | 26 | self.poller = self.madcow.imap_poller 27 | 28 | def response(self, nick, args, kwargs): 29 | command = args[0] 30 | 31 | if command == 'now': 32 | response = self.poller(True) 33 | 34 | if response == "": 35 | return "No new messages." 36 | else: 37 | return response 38 | 39 | if command == 'start': 40 | return self.poller.start(nick) 41 | 42 | if command == 'stop': 43 | return self.poller.stop(nick) -------------------------------------------------------------------------------- /madcow/modules/spellcheck.py: -------------------------------------------------------------------------------- 1 | """Spellcheck using google""" 2 | 3 | from urlparse import urljoin 4 | import re 5 | from madcow.util import Module, strip_html 6 | from madcow.util.text import * 7 | 8 | class Main(Module): 9 | 10 | pattern = re.compile(r'^\s*spell(?:\s*check)?\s+(.+?)\s*$', re.I) 11 | help = u'spellcheck - use google to spellcheck' 12 | google_url = 'http://www.google.com/' 13 | google_search = urljoin(google_url, '/search') 14 | error = 'I had trouble with that' 15 | 16 | def response(self, nick, args, kwargs): 17 | opts = {'hl': 'en', 'safe': 'off', 'q': args[0]} 18 | soup = self.getsoup(self.google_search, opts, referer=self.google_url) 19 | correct = soup.body.find('a', href=re.compile(r'^/search.*spell=1')) 20 | if correct: 21 | res = strip_html(decode(correct.renderContents(), 'utf-8')) 22 | else: 23 | res = u'spelled correctly. probably.' 24 | return u'%s: %s' % (nick, res) 25 | -------------------------------------------------------------------------------- /madcow/modules/summon.py: -------------------------------------------------------------------------------- 1 | """Summon people""" 2 | 3 | import re 4 | from learn import Main as Learn 5 | from madcow.util import Module 6 | from smtplib import SMTP 7 | from madcow.conf import settings 8 | from madcow.util.text import * 9 | 10 | class Main(Module): 11 | 12 | pattern = re.compile(r'^\s*summons?\s+(\S+)(?:\s+(.*?))?\s*$') 13 | require_addressing = True 14 | help = u'summon [reason] - summon user' 15 | error = u"I couldn't make that summon" 16 | 17 | def init(self): 18 | self.learn = Learn(self.madcow) 19 | 20 | def response(self, nick, args, kwargs): 21 | sendto, reason = args 22 | email = self.learn.lookup('email', sendto) 23 | if email is None: 24 | return u"%s: I don't know the email for %s" % (nick, sendto) 25 | body = u'\n'.join((u'To: %s <%s>' % (sendto, email), 26 | u'From: ' + settings.SMTP_FROM, 27 | u'Subject: Summon from ' + nick, 28 | u'', 29 | u'You were summoned by %s. Reason: %s' % (nick, reason))) 30 | smtp = SMTP(settings.SMTP_SERVER) 31 | smtp.ehlo() 32 | smtp.starttls() 33 | smtp.ehlo() 34 | if settings.SMTP_USER and settings.SMTP_PASS: 35 | smtp.login(settings.SMTP_USER, settings.SMTP_PASS) 36 | smtp.sendmail(settings.SMTP_FROM, [encode(email, 'ascii')], encode(body)) 37 | return u"%s: summoned %s" % (nick, sendto) 38 | -------------------------------------------------------------------------------- /madcow/modules/sunrise.py: -------------------------------------------------------------------------------- 1 | """Get sunrise or sunset from google""" 2 | 3 | import re 4 | from madcow.util import Module, strip_html 5 | from madcow.util.color import ColorLib 6 | from learn import Main as Learn 7 | from google import Google 8 | 9 | class Main(Module): 10 | 11 | pattern = re.compile(r'^\s*(sunrise|sunset)(?:\s+(@?)(.+?))?\s*$', re.I) 12 | help = '(sunrise|sunset) [location|@nick] - get time of sun rise/set' 13 | error = u"That place doesn't have a sun, sorry" 14 | 15 | def init(self): 16 | self.colorlib = self.madcow.colorlib 17 | try: 18 | self.learn = Learn(madcow=madcow) 19 | except: 20 | self.learn = None 21 | self.google = Google() 22 | 23 | def response(self, nick, args, kwargs): 24 | query, args = args[0], args[1:] 25 | if not args[1]: 26 | args = 1, nick 27 | if args[0]: 28 | location = self.learn.lookup('location', args[1]) 29 | if not location: 30 | return u'%s: Try: set location ' % nick 31 | else: 32 | location = args[1] 33 | response = self.google.sunrise_sunset(query, location) 34 | return u'%s: %s' % (nick, response) 35 | -------------------------------------------------------------------------------- /madcow/modules/texts.py: -------------------------------------------------------------------------------- 1 | """Texts from last night""" 2 | 3 | import random 4 | import re 5 | from BeautifulSoup import BeautifulSoup 6 | from madcow.util import strip_html, Module 7 | from madcow.util.text import * 8 | import re 9 | 10 | url = 'http://www.textsfromlastnight.com/random/' 11 | 12 | class Main(Module): 13 | 14 | pattern = re.compile(r'^\s*(?:txt|texts|tfln)\s*$', re.I) 15 | help = 'txt - random texts from last night' 16 | 17 | def response(self, nick, args, kwargs): 18 | kwargs['req'].quoted = True 19 | soup = self.getsoup(url) 20 | posts = soup.body('div', 'content') 21 | contents = [] 22 | for post in posts: 23 | a = post.find('a', href=re.compile(r'Text-Replies')) 24 | if a is not None: 25 | content = u' '.join(strip_html(decode(a.renderContents())).strip().splitlines()) 26 | contents.append(content) 27 | return random.choice(contents) 28 | -------------------------------------------------------------------------------- /madcow/modules/trek.py: -------------------------------------------------------------------------------- 1 | """Star Trek failure generator""" 2 | 3 | from BeautifulSoup import BeautifulSoup 4 | from madcow.util import strip_html, Module 5 | import re 6 | 7 | class Main(Module): 8 | 9 | pattern = re.compile(r'^\s*(?:star\s*)?trek\s*$', re.I) 10 | help = u'startrek - generate technobabble' 11 | url = 'http://hyotynen.kapsi.fi/trekfailure/' 12 | fail_re = re.compile(r'^[ \n]*- (.*?) -[ \n]*$') 13 | spaces_re = re.compile(r'\s{2,}') 14 | error = u'Too much fail for technobabble' 15 | 16 | def init(self): 17 | self.col = self.madcow.colorlib.get_color 18 | 19 | def response(self, nick, args, kwargs): 20 | fail = BeautifulSoup(self.geturl(self.url)).h1 21 | return self.spaces_re.sub(' ', strip_html( 22 | u'%s: %s: %s %s: %s' % ( 23 | nick, self.col('red', text='FAIL'), 24 | self.fail_re.search(fail.renderContents()).group(1), 25 | self.col('green', text='FIX'), 26 | self.fail_re.search(fail.findNext('h1').renderContents()).group(1)))) 27 | -------------------------------------------------------------------------------- /madcow/modules/webtender.py: -------------------------------------------------------------------------------- 1 | """Look up drink mixing ingredients""" 2 | 3 | import re 4 | from madcow.util import Module, strip_html 5 | from urlparse import urljoin 6 | 7 | class Main(Module): 8 | 9 | pattern = re.compile(u'^\s*drinks?\s+(.+)', re.I) 10 | require_addressing = True 11 | help = u'drinks - look up mixing instructions' 12 | baseurl = u'http://www.webtender.com/' 13 | search = urljoin(baseurl, u'/cgi-bin/search') 14 | drink = re.compile(u'') 15 | title = re.compile(u'

(.*?)

') 16 | ingredients = re.compile(u'
  • (.*?CLASS=ingr.+)') 17 | instructions = re.compile(u'

    Mixing instructions:

    .*?

    (.*?)

    ', re.DOTALL) 18 | error = u"Something ungood happened looking that up, sry" 19 | 20 | def response(self, nick, args, kwargs): 21 | try: 22 | query = args[0] 23 | doc = self.geturl(self.search, opts={u'verbose': u'on', u'name': query}) 24 | drink = self.drink.search(doc).group(1) 25 | url = urljoin(self.baseurl, drink) 26 | doc = self.geturl(url) 27 | title = self.title.search(doc).group(1) 28 | ingredients = self.ingredients.findall(doc) 29 | instructions = self.instructions.search(doc).group(1) 30 | response = strip_html(u'%s - %s - %s' % (title, u', '.join(ingredients), instructions)) 31 | except Exception, error: 32 | response = u"That's a made-up drink, sorry." 33 | return u'%s: %s' % (nick, response) 34 | -------------------------------------------------------------------------------- /madcow/modules/welcome.py: -------------------------------------------------------------------------------- 1 | """Send/receive a welcome message""" 2 | 3 | """ Copyright 2013 ActiveState Software Inc. """ 4 | 5 | import re 6 | from madcow.util import Module 7 | from madcow.util.text import * 8 | from madcow.conf import settings 9 | from staff import Main as Staff 10 | import os 11 | 12 | try: 13 | import dbm 14 | except ImportError: 15 | import anydbm as dbm 16 | 17 | class Main(Module): 18 | pattern = re.compile(u'^\s*(welcome)(?:\s+(.*)$)?') 19 | require_addressing = False 20 | help = u'welcome get the #stackato welcome package: links for downloads, docs, and support.\n\ 21 | welcome send another user the #stackato welcome package (staff only)' 22 | 23 | def init(self): 24 | self.staff = Staff(madcow=self.madcow) 25 | 26 | def response(self, nick, args, kwargs): 27 | kwargs[u'req'].make_private() # welcome package is always private 28 | cmd = args[0] 29 | target_nick = args[1].strip() if args[1] else None 30 | msg_nick = nick 31 | 32 | # only staff members & bot owner are allowed to set/change shortcuts 33 | if target_nick and (self.staff.is_staff(nick) or settings.OWNER_NICK == nick): 34 | kwargs['req'].set_sendto(target_nick) 35 | msg_nick = target_nick 36 | 37 | return u'Welcome to %s, %s!\n%s' % (kwargs[u'channel'], msg_nick, settings.WELCOME_MSG) -------------------------------------------------------------------------------- /madcow/modules/woot.py: -------------------------------------------------------------------------------- 1 | """get the current woot - author: Twid""" 2 | 3 | import re 4 | import feedparser 5 | from madcow.util import Module, strip_html 6 | 7 | class Main(Module): 8 | 9 | pattern = re.compile(u'^\s*woot\s*$', re.I) 10 | require_addressing = True 11 | help = u'woot - get latest offer from woot.com' 12 | url = u'http://woot.com/Blog/Rss.aspx' 13 | max = 200 14 | break_re = re.compile(r'\s*[\r\n]+\s*') 15 | 16 | def response(self, nick, args, kwargs): 17 | rss = feedparser.parse(self.url) 18 | entry = rss.entries[0] 19 | title, summary, link = map( 20 | strip_html, [entry.title, entry.summary, entry.link]) 21 | summary = self.break_re.sub(u' ', summary) 22 | if len(summary) > self.max: 23 | summary = summary[:self.max - 4] + u' ...' 24 | return u'%s [%s] %s' % (title, link, summary) 25 | -------------------------------------------------------------------------------- /madcow/modules/youtube.py: -------------------------------------------------------------------------------- 1 | """Mystery meat demistifier: Scrape youtube titles""" 2 | 3 | from madcow.util.text import decode 4 | from madcow.util import Module, strip_html 5 | from urlparse import urlparse 6 | 7 | import cgi 8 | import re 9 | import os 10 | 11 | SCHEMES = frozenset({'http', 'https'}) 12 | DOMAINS = frozenset({'youtube.com'}) 13 | 14 | class Main(Module): 15 | 16 | pattern = re.compile(r'(https?://(?:\w+\.)?youtube\.com/\S+)', re.I) 17 | require_addressing = False 18 | priority = 90 19 | allow_threading = True 20 | terminate = False 21 | 22 | def response(self, nick, args, kwargs): 23 | try: 24 | url = args[0] 25 | uri = urlparse(url) 26 | if (uri.scheme.lower() in SCHEMES and 27 | '.'.join(uri.netloc.lower().split('.')[-2:]) in DOMAINS and 28 | os.path.split(os.path.normpath(uri.path))[-1] == 'watch' and 29 | 'v' in cgi.parse_qs(uri.query)): 30 | soup = self.getsoup(url) 31 | title = strip_html(decode(soup.title.renderContents())).replace(u' - YouTube', u'').strip() 32 | if title: 33 | self.madcow.output(title, kwargs['req']) 34 | except (KeyboardInterrupt, SystemExit): 35 | raise 36 | except: 37 | raise 38 | pass 39 | -------------------------------------------------------------------------------- /madcow/protocol/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /madcow/tasks/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /madcow/tasks/ircops.py: -------------------------------------------------------------------------------- 1 | """Periodically checks for people that need to be opped""" 2 | 3 | from time import time as unix_time, sleep 4 | from madcow.conf import settings 5 | from madcow.util import Task 6 | 7 | class Main(Task): 8 | 9 | def init(self): 10 | if settings.PROTOCOL != 'irc': 11 | raise ValueError('ircops only relevant for irc protocol') 12 | self.frequency = settings.IRC_GIVE_OPS_FREQ 13 | self.output = None 14 | 15 | def response(self, *args): 16 | # determine who can be opped 17 | auto_op = [] 18 | passwd = self.madcow.admin.authlib.get_passwd() 19 | for nick, data in passwd.items(): 20 | if u'o' in data[u'flags']: 21 | auto_op.append(nick.lower()) 22 | 23 | # issue NAMES update and wait for it to refresh (handled in irc.py) 24 | self.madcow.server.names(self.madcow.channels) 25 | while True: 26 | now = unix_time() 27 | delta = now - self.madcow.last_names_update 28 | if delta < self.frequency: 29 | break 30 | if delta >= (self.frequency * 2 -1): 31 | return 32 | sleep(.25) 33 | 34 | for channel, names in self.madcow.names.items(): 35 | nicks = [nick for nick, opped in names.items() if not opped] 36 | if self.madcow.server.get_nickname() in nicks: 37 | self.log.warn(u'cannot give ops until i get it myself') 38 | return 39 | nicks = [nick for nick in nicks if nick in auto_op] 40 | for i in range(0, len(nicks), 6): 41 | line = nicks[i:i+6] 42 | self.log.info(u'opping on %s to %s' % (channel, u' '.join(line))) 43 | line = u'+' + (u'o' * len(line)) + u' ' + u' '.join(line) 44 | self.madcow.server.mode(channel, line) 45 | -------------------------------------------------------------------------------- /madcow/tasks/pollmail.py: -------------------------------------------------------------------------------- 1 | """ Imap Polling Task """ 2 | 3 | from madcow.util.imap import ImapPoller 4 | from madcow.util import Task 5 | from madcow.conf import settings 6 | 7 | # the poller property is set by the pollmap module. Make sure it is enabled before enabling this. 8 | 9 | class Main(Task): 10 | output = 'ALL' 11 | 12 | def init(self): 13 | # self.frequency = settings.POLLMAIL_FREQUENCY 14 | 15 | try: 16 | self.madcow.poller 17 | except AttributeError: 18 | self.madcow.poller = ImapPoller(self.madcow) 19 | 20 | def response(self, name, args, kwargs): 21 | self.log.debug("[PollMail Task] Polling IMAP") 22 | return self.madcow.poller() -------------------------------------------------------------------------------- /run-standalone-madcow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """run madcow as a standalone bot""" 4 | 5 | import importlib 6 | import argparse 7 | import sys 8 | import os 9 | 10 | BASEDIR = os.path.dirname(os.path.abspath(__file__)) 11 | 12 | class MadcowVersion(argparse._VersionAction): 13 | 14 | """argparse action to fetch the current madcow version""" 15 | 16 | def __call__(self, parser, namespace, values, option_string=None): 17 | try: 18 | madcow = self.import_madcow(basedir=namespace.basedir) 19 | except (SystemExit, KeyboardInterrupt): 20 | raise 21 | except: 22 | ret, version = 1, 'UNKNOWN' 23 | else: 24 | ret, version = 0, madcow.__version__ 25 | parser.exit(ret, version + os.linesep) 26 | 27 | @classmethod 28 | def import_madcow(cls, basedir=None): 29 | """attempt to import madcow from the given lib base""" 30 | if basedir is None: 31 | basedir = BASEDIR 32 | sys.path.insert(0, basedir) 33 | sys.dont_write_bytecode = True 34 | return importlib.import_module('madcow') 35 | 36 | 37 | def main(args=None): 38 | """command-line interface""" 39 | parser = argparse.ArgumentParser(description=__doc__, add_help=False) 40 | _ = parser.add_argument_group('options').add_argument 41 | _('-b', dest='basedir', metavar='', default=BASEDIR, 42 | help='base runtime dir [%(default)s]') 43 | _('-d', dest='datadir', metavar='', default='data', 44 | help='bot data dir (relative to base or absolute) [%(default)s]') 45 | _('-n', dest='noeditor', default=False, action='store_true', 46 | help="suppress launching $EDITOR settings.py on first run") 47 | _('-h', action='help', 48 | help='show this help message and exit') 49 | _('-v', action=MadcowVersion, 50 | help="show program's version number and exit") 51 | opts = parser.parse_args(args) 52 | madcow = MadcowVersion.import_madcow(basedir=opts.basedir) 53 | madcow.run(base=opts.datadir, noeditor=opts.noeditor) 54 | return 0 55 | 56 | if __name__ == '__main__': 57 | sys.exit(main()) 58 | -------------------------------------------------------------------------------- /scripts/madcow: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from optparse import OptionParser 4 | import traceback 5 | import sys 6 | import os 7 | 8 | sys.dont_write_bytecode = True 9 | 10 | import madcow 11 | 12 | __usage__ = '%prog [-b ]' 13 | __doc__ = 'Run the Madcow infobot' 14 | 15 | DEFAULT_BASE = os.path.realpath(os.path.join(os.environ.get('HOME', ''), '.madcow')) 16 | 17 | def main(argv=None): 18 | optparse = OptionParser(__usage__, version=madcow.__version__, description=__doc__) 19 | optparse.add_option('-b', '--base', metavar='', default=DEFAULT_BASE, help='madcow base (%default)') 20 | opts, args = optparse.parse_args(argv) 21 | if args: 22 | optparse.error('%prog expects no arguments') 23 | try: 24 | madcow.run(base=opts.base) 25 | return 0 26 | except (SystemExit, KeyboardInterrupt): 27 | raise 28 | except madcow.MadcowError, exc: 29 | print >> sys.stderr, exc 30 | except: 31 | traceback.print_exc() 32 | return 1 33 | 34 | if __name__ == '__main__': 35 | sys.exit(main()) 36 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [sdist] 2 | formats=bztar 3 | owner=0 4 | group=0 5 | --------------------------------------------------------------------------------