start work switch to py3 and ircbot
This commit is contained in:
parent
12e6c0374e
commit
6eefcdda74
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,3 +6,4 @@ db.sqlite3
|
||||||
.env
|
.env
|
||||||
*.pyc
|
*.pyc
|
||||||
venv/
|
venv/
|
||||||
|
venv3/
|
||||||
|
|
|
@ -44,6 +44,7 @@ INSTALLED_APPS = [
|
||||||
'program',
|
'program',
|
||||||
'info',
|
'info',
|
||||||
'sponsors',
|
'sponsors',
|
||||||
|
'ircbot',
|
||||||
|
|
||||||
'allauth',
|
'allauth',
|
||||||
'allauth.account',
|
'allauth.account',
|
||||||
|
|
0
ircbot/__init__.py
Normal file
0
ircbot/__init__.py
Normal file
3
ircbot/admin.py
Normal file
3
ircbot/admin.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
7
ircbot/apps.py
Normal file
7
ircbot/apps.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class IrcbotConfig(AppConfig):
|
||||||
|
name = 'ircbot'
|
91
ircbot/irc3module.py
Normal file
91
ircbot/irc3module.py
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
import irc3
|
||||||
|
from ircbot.models import OutgoingIrcMessage
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
@irc3.plugin
|
||||||
|
class Plugin(object):
|
||||||
|
"""BornHack IRC3 class"""
|
||||||
|
|
||||||
|
requires = [
|
||||||
|
'irc3.plugins.core', # makes the bot able to connect to an irc server and do basic irc stuff
|
||||||
|
'irc3.plugins.userlist', # maintains a convenient list of the channels the bot is in and their users
|
||||||
|
'irc3.plugins.command', # what does this do?
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(self, bot):
|
||||||
|
self.bot = bot
|
||||||
|
self.log = self.bot.log
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################################
|
||||||
|
### builtin irc3 event methods
|
||||||
|
|
||||||
|
def server_ready(self, **kwargs):
|
||||||
|
"""triggered after the server sent the MOTD (require core plugin)"""
|
||||||
|
if settings.DEBUG:
|
||||||
|
print("inside server_ready(), kwargs: %s" % kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def connection_lost(self, **kwargs):
|
||||||
|
"""triggered when connection is lost"""
|
||||||
|
if settings.DEBUG:
|
||||||
|
print("inside connection_lost(), kwargs: %s" % kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def connection_made(self, **kwargs):
|
||||||
|
"""triggered when connection is up"""
|
||||||
|
if settings.DEBUG:
|
||||||
|
print("inside connection_made(), kwargs: %s" % kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################################
|
||||||
|
### decorated irc3 event methods
|
||||||
|
|
||||||
|
@irc3.event(irc3.rfc.JOIN_PART_QUIT)
|
||||||
|
def on_join_part_quit(self, **kwargs):
|
||||||
|
"""triggered when there is a join part or quit on a channel the bot is in"""
|
||||||
|
if settings.DEBUG:
|
||||||
|
print("inside on_join_part_quit(), kwargs: %s" % kwargs)
|
||||||
|
if self.bot.nick == kwargs['mask'].split("!")[0] and kwargs['channel'] == "#tirsdagsfilm":
|
||||||
|
self.bot.loop.call_later(1, self.bot.get_outgoing_messages)
|
||||||
|
|
||||||
|
|
||||||
|
@irc3.event(irc3.rfc.PRIVMSG)
|
||||||
|
def on_privmsg(self, **kwargs):
|
||||||
|
"""triggered when a privmsg is sent to the bot or to a channel the bot is in"""
|
||||||
|
if settings.DEBUG:
|
||||||
|
print("inside on_privmsg(), kwargs: %s" % kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@irc3.event(irc3.rfc.KICK)
|
||||||
|
def on_kick(self, **kwargs):
|
||||||
|
if settings.DEBUG:
|
||||||
|
print("inside on_kick(), kwargs: %s" % kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################################
|
||||||
|
### custom irc3 methods
|
||||||
|
@irc3.extend
|
||||||
|
def get_outgoing_messages(self):
|
||||||
|
"""
|
||||||
|
This method gets unprocessed OutgoingIrcMessage objects and attempts to send them to
|
||||||
|
the target channel. Messages are skipped if the bot is not in the channel.
|
||||||
|
"""
|
||||||
|
# TODO: handle privmsg to users
|
||||||
|
# TODO: set a timeout for messages.. a few minutes maybe?
|
||||||
|
# TODO: make sleep time configurable
|
||||||
|
print("inside get_outgoing_messages()")
|
||||||
|
for msg in OutgoingIrcMessage.objects.filter(processed=False).order_by('created_date'):
|
||||||
|
if msg.target[0] == "#" and msg.target in self.bot.channels:
|
||||||
|
print("sending privmsg to %s: %s" % (msg.target, msg.message))
|
||||||
|
self.bot.privmsg(msg.target, msg.message)
|
||||||
|
msg.processed=True
|
||||||
|
msg.save()
|
||||||
|
else:
|
||||||
|
print("skipping message to channel %s because the bot is not in the channel" % msg.target)
|
||||||
|
|
||||||
|
# call this function again in 60 seconds
|
||||||
|
self.bot.loop.call_later(60, self.bot.get_outgoing_messages)
|
||||||
|
|
||||||
|
|
0
ircbot/management/__init__.py
Normal file
0
ircbot/management/__init__.py
Normal file
0
ircbot/management/commands/__init__.py
Normal file
0
ircbot/management/commands/__init__.py
Normal file
30
ircbot/management/commands/ircbot.py
Normal file
30
ircbot/management/commands/ircbot.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.conf import settings
|
||||||
|
from django.utils import timezone
|
||||||
|
from time import sleep
|
||||||
|
import irc3, sys, asyncio
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
args = 'none'
|
||||||
|
help = 'Runs the BornHack IRC bot to announce talks and manage team channel permissions'
|
||||||
|
|
||||||
|
def output(self, message):
|
||||||
|
self.stdout.write('%s: %s' % (timezone.now().strftime("%Y-%m-%d %H:%M:%S"), message))
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
self.output('IRC bot worker running...')
|
||||||
|
# connect to IRC
|
||||||
|
config = {
|
||||||
|
'nick': 'BornHack',
|
||||||
|
'autojoins': ['#tirsdagsfilm'],
|
||||||
|
'host': 'ircd.tyknet.dk',
|
||||||
|
'port': 6697,
|
||||||
|
'ssl': True,
|
||||||
|
'timeout': 30,
|
||||||
|
'includes': [
|
||||||
|
'ircbot.irc3module',
|
||||||
|
],
|
||||||
|
}
|
||||||
|
irc3.IrcBot(**config).run(forever=True)
|
||||||
|
|
30
ircbot/migrations/0001_initial.py
Normal file
30
ircbot/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2017-01-29 20:29
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='OutgoingIrcMessage',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('created', models.DateTimeField(auto_now_add=True)),
|
||||||
|
('updated', models.DateTimeField(auto_now=True)),
|
||||||
|
('target', models.CharField(max_length=100)),
|
||||||
|
('message', models.CharField(max_length=200)),
|
||||||
|
('processed', models.BooleanField(default=False)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
0
ircbot/migrations/__init__.py
Normal file
0
ircbot/migrations/__init__.py
Normal file
10
ircbot/models.py
Normal file
10
ircbot/models.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from utils.models import UUIDModel, CreatedUpdatedModel
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class OutgoingIrcMessage(CreatedUpdatedModel):
|
||||||
|
target = models.CharField(max_length=100)
|
||||||
|
message = models.CharField(max_length=200)
|
||||||
|
processed = models.BooleanField(default=False)
|
||||||
|
|
3
ircbot/views.py
Normal file
3
ircbot/views.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
|
@ -4,6 +4,7 @@ Pillow==4.0.0
|
||||||
PyPDF2==1.26.0
|
PyPDF2==1.26.0
|
||||||
Unidecode==0.04.20
|
Unidecode==0.04.20
|
||||||
argparse==1.2.1
|
argparse==1.2.1
|
||||||
|
asyncio==3.4.3
|
||||||
bleach==1.5.0
|
bleach==1.5.0
|
||||||
django-allauth==0.30.0
|
django-allauth==0.30.0
|
||||||
django-bleach==0.3.0
|
django-bleach==0.3.0
|
||||||
|
@ -11,8 +12,10 @@ django-bootstrap3==8.1.0
|
||||||
django-debug-toolbar==1.6
|
django-debug-toolbar==1.6
|
||||||
django-environ==0.4.1
|
django-environ==0.4.1
|
||||||
django-wkhtmltopdf==3.1.0
|
django-wkhtmltopdf==3.1.0
|
||||||
|
docopt==0.6.2
|
||||||
future==0.16.0
|
future==0.16.0
|
||||||
html5lib==0.9999999
|
html5lib==0.9999999
|
||||||
|
irc3==0.9.8
|
||||||
oauthlib==2.0.1
|
oauthlib==2.0.1
|
||||||
olefile==0.44
|
olefile==0.44
|
||||||
psycopg2==2.6.2
|
psycopg2==2.6.2
|
||||||
|
@ -23,5 +26,6 @@ requests==2.12.5
|
||||||
requests-oauthlib==0.7.0
|
requests-oauthlib==0.7.0
|
||||||
six==1.10.0
|
six==1.10.0
|
||||||
sqlparse==0.2.2
|
sqlparse==0.2.2
|
||||||
|
venusian==1.0
|
||||||
webencodings==0.5
|
webencodings==0.5
|
||||||
wsgiref==0.1.2
|
wsgiref==0.1.2
|
||||||
|
|
30
requirements3.txt
Normal file
30
requirements3.txt
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
CommonMark==0.7.3
|
||||||
|
Django==1.10.5
|
||||||
|
Pillow==4.0.0
|
||||||
|
PyPDF2==1.26.0
|
||||||
|
Unidecode==0.04.20
|
||||||
|
argparse==1.2.1
|
||||||
|
asyncio==3.4.3
|
||||||
|
bleach==1.5.0
|
||||||
|
django-allauth==0.30.0
|
||||||
|
django-bleach==0.3.0
|
||||||
|
django-bootstrap3==8.1.0
|
||||||
|
django-debug-toolbar==1.6
|
||||||
|
django-environ==0.4.1
|
||||||
|
django-wkhtmltopdf==3.1.0
|
||||||
|
docopt==0.6.2
|
||||||
|
future==0.16.0
|
||||||
|
html5lib==0.9999999
|
||||||
|
irc3==0.9.8
|
||||||
|
oauthlib==2.0.1
|
||||||
|
olefile==0.44
|
||||||
|
psycopg2==2.6.2
|
||||||
|
python-openid==2.2.5
|
||||||
|
pytz==2016.10
|
||||||
|
qrcode==5.3
|
||||||
|
requests==2.12.5
|
||||||
|
requests-oauthlib==0.7.0
|
||||||
|
six==1.10.0
|
||||||
|
sqlparse==0.2.2
|
||||||
|
venusian==1.0
|
||||||
|
webencodings==0.5
|
|
@ -1,5 +1,5 @@
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from views import *
|
from .views import *
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^$', ShopIndexView.as_view(), name='index'),
|
url(r'^$', ShopIndexView.as_view(), name='index'),
|
||||||
|
|
|
@ -447,21 +447,18 @@ class EpayCallbackView(SingleObjectMixin, View):
|
||||||
|
|
||||||
if 'orderid' in request.GET:
|
if 'orderid' in request.GET:
|
||||||
query = OrderedDict(
|
query = OrderedDict(
|
||||||
map(
|
[tuple(x.split('=')) for x in request.META['QUERY_STRING'].split('&')]
|
||||||
lambda x: tuple(x.split('=')),
|
|
||||||
request.META['QUERY_STRING'].split('&')
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
order = get_object_or_404(Order, pk=query.get('orderid'))
|
order = get_object_or_404(Order, pk=query.get('orderid'))
|
||||||
if order.pk != self.get_object().pk:
|
if order.pk != self.get_object().pk:
|
||||||
print "bad epay callback, orders do not match!"
|
print("bad epay callback, orders do not match!")
|
||||||
return HttpResponse(status=400)
|
return HttpResponse(status=400)
|
||||||
|
|
||||||
if validate_epay_callback(query):
|
if validate_epay_callback(query):
|
||||||
callback.md5valid=True
|
callback.md5valid=True
|
||||||
callback.save()
|
callback.save()
|
||||||
else:
|
else:
|
||||||
print "bad epay callback!"
|
print("bad epay callback!")
|
||||||
return HttpResponse(status=400)
|
return HttpResponse(status=400)
|
||||||
|
|
||||||
if order.paid:
|
if order.paid:
|
||||||
|
@ -479,7 +476,7 @@ class EpayCallbackView(SingleObjectMixin, View):
|
||||||
### and mark order as paid (this will create tickets)
|
### and mark order as paid (this will create tickets)
|
||||||
order.mark_as_paid()
|
order.mark_as_paid()
|
||||||
else:
|
else:
|
||||||
print "valid epay callback with wrong amount detected"
|
print("valid epay callback with wrong amount detected")
|
||||||
else:
|
else:
|
||||||
return HttpResponse(status=400)
|
return HttpResponse(status=400)
|
||||||
|
|
||||||
|
@ -541,7 +538,7 @@ class CoinifyRedirectView(LoginRequiredMixin, EnsureUserOwnsOrderMixin, EnsureUn
|
||||||
# check if it expired
|
# check if it expired
|
||||||
if parse_datetime(order.coinifyapiinvoice.invoicejson['expire_time']) < timezone.now():
|
if parse_datetime(order.coinifyapiinvoice.invoicejson['expire_time']) < timezone.now():
|
||||||
# this coinifyinvoice expired, delete it
|
# this coinifyinvoice expired, delete it
|
||||||
print "deleting expired coinifyinvoice id %s" % order.coinifyapiinvoice.invoicejson['id']
|
print("deleting expired coinifyinvoice id %s" % order.coinifyapiinvoice.invoicejson['id'])
|
||||||
order.coinifyapiinvoice.delete()
|
order.coinifyapiinvoice.delete()
|
||||||
order = self.get_object()
|
order = self.get_object()
|
||||||
|
|
||||||
|
@ -568,10 +565,10 @@ class CoinifyRedirectView(LoginRequiredMixin, EnsureUserOwnsOrderMixin, EnsureUn
|
||||||
# Parse response
|
# Parse response
|
||||||
if not response['success']:
|
if not response['success']:
|
||||||
api_error = response['error']
|
api_error = response['error']
|
||||||
print "API error: %s (%s)" % (
|
print("API error: %s (%s)" % (
|
||||||
api_error['message'],
|
api_error['message'],
|
||||||
api_error['code']
|
api_error['code']
|
||||||
)
|
))
|
||||||
messages.error(request, "There was a problem with the payment provider. Please try again later")
|
messages.error(request, "There was a problem with the payment provider. Please try again later")
|
||||||
return HttpResponseRedirect(reverse_lazy('shop:order_detail', kwargs={'pk': self.get_object().pk}))
|
return HttpResponseRedirect(reverse_lazy('shop:order_detail', kwargs={'pk': self.get_object().pk}))
|
||||||
else:
|
else:
|
||||||
|
@ -580,7 +577,7 @@ class CoinifyRedirectView(LoginRequiredMixin, EnsureUserOwnsOrderMixin, EnsureUn
|
||||||
invoicejson = response['data'],
|
invoicejson = response['data'],
|
||||||
order = order,
|
order = order,
|
||||||
)
|
)
|
||||||
print "created new coinifyinvoice id %s" % coinifyinvoice.invoicejson['id']
|
print("created new coinifyinvoice id %s" % coinifyinvoice.invoicejson['id'])
|
||||||
return super(CoinifyRedirectView, self).dispatch(
|
return super(CoinifyRedirectView, self).dispatch(
|
||||||
request, *args, **kwargs
|
request, *args, **kwargs
|
||||||
)
|
)
|
||||||
|
@ -603,7 +600,7 @@ class CoinifyCallbackView(SingleObjectMixin, View):
|
||||||
|
|
||||||
# make a dict with all HTTP_ headers
|
# make a dict with all HTTP_ headers
|
||||||
headerdict = {}
|
headerdict = {}
|
||||||
for key, value in request.META.iteritems():
|
for key, value in request.META.items():
|
||||||
if key[:5] == 'HTTP_':
|
if key[:5] == 'HTTP_':
|
||||||
headerdict[key[5:]] = value
|
headerdict[key[5:]] = value
|
||||||
|
|
||||||
|
@ -625,7 +622,7 @@ class CoinifyCallbackView(SingleObjectMixin, View):
|
||||||
try:
|
try:
|
||||||
coinifyinvoice = CoinifyAPIInvoice.objects.get(invoicejson__id=callbackjson['data']['id'])
|
coinifyinvoice = CoinifyAPIInvoice.objects.get(invoicejson__id=callbackjson['data']['id'])
|
||||||
except CoinifyAPIInvoice.DoesNotExist:
|
except CoinifyAPIInvoice.DoesNotExist:
|
||||||
print "unable to find CoinifyAPIInvoice with id %s" % callbackjson['data']['id']
|
print("unable to find CoinifyAPIInvoice with id %s" % callbackjson['data']['id'])
|
||||||
return HttpResponseBadRequest('bad coinifyinvoice id')
|
return HttpResponseBadRequest('bad coinifyinvoice id')
|
||||||
|
|
||||||
# save new coinifyinvoice payload
|
# save new coinifyinvoice payload
|
||||||
|
@ -641,7 +638,7 @@ class CoinifyCallbackView(SingleObjectMixin, View):
|
||||||
else:
|
else:
|
||||||
return HttpResponseBadRequest('unsupported event')
|
return HttpResponseBadRequest('unsupported event')
|
||||||
else:
|
else:
|
||||||
print "invalid coinify callback detected"
|
print("invalid coinify callback detected")
|
||||||
return HttpResponseBadRequest('something is fucky')
|
return HttpResponseBadRequest('something is fucky')
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue