Commit acbc8f15 authored by Mindiell's avatar Mindiell

Conversion of Wantzel from perl to python

parent f14c9cf0
#encoding: utf-8
"""
Configuration for IRC bot Wantzel.
"""
server = 'irc.freenode.net'
port = 6667
nickname = 'testBot'
password = '',
channels = [
'#testchannel'
]
#encoding: utf-8
"""
A simplistic IRC client connecting to freenode network.
"""
from twisted.internet import reactor, protocol
from twisted.words.protocols import irc
class IrcClient(irc.IRCClient):
def __init__(self, config):
self.config = config
self.nickname = "TestMan"
self.password = config.password
def connectionMade(self):
irc.IRCClient.connectionMade(self)
def connectionLost(self, reason):
irc.IRCClient.connectionLost(self, reason)
def signedOn(self):
for channel in self.config.channels:
self.join(channel)
class IrcClientFactory(protocol.ClientFactory):
def __init__(self, config):
self.config = config
def set_privmsg(self):
pass
def buildProtocol(self, addr):
print("Building protocol")
self.client = IrcClient(self.config)
self.set_privmsg()
return self.client
def clientConnectionLost(self, connector, reason):
"""If we get disconnected, reconnect to server."""
connector.connect()
def clientConnectionFailed(self, connector, reason):
print("Connection failed: %s" % reason)
reactor.stop()
if __name__ == '__main__':
factory = IrcClientFactory({'nickname':'','password':''})
reactor.connectTCP("irc.freenode.net", 6667, factory)
reactor.run()
#encoding: utf-8
"""
Ce fichier contient les messages utilisés par Wantzel.
Il les recharge à chaque fois qu'on lui fournit la commande '!reload' sur IRC.
"""
messages = {
"hello": """Bonjour, je suis le bot de la Quadrature du Net, vous pouvez me demander de l'aide si besoin. (wantzel help)""",
"help": """Toute l'aide se trouve ici : https://wiki.laquadrature.net/Wantzel""",
"help_rp": """""",
"help_stats": """""",
"help_quote": """""",
"help_tc": """""",
"help_kill": """""",
"merci_nouvel_article": """Merci %s, cette url a été ajoutée à la revue de presse ! À présent, que dirais-tu d'aider à choisir les extraits de l'article à publier sur #lqdn-rp ? <3""",
"merci_article_connu": """Merci %s! Un point a été ajouté à cet article : à partir de 3, il pourra être repris dans la revue de presse. D'ailleurs, que dirais-tu d'aider à choisir les extraits à publier sur #lqdn-rp ? <3""",
"merci_article_repris": """Merci %s! Un point a été ajouté à cet article : il va être repris dans la revue de presse. D'ailleurs, que dirais-tu d'aider à choisir les extraits à publier sur #lqdn-rp ? <3""",
}
#encoding: utf-8
"""
Bot Wantzel de La Quadrature du Net
Pour utiliser l'accès à une base de données MySQL :
- apt-get install libmysqlclient-dev
- pip install mysql-python
"""
from irc import IrcClientFactory
import json
import MySQLdb
import re
from twisted.internet import reactor
import urllib
import config
from messages import messages
class Wantzel(object):
"""
Wantzel bot.
"""
def __init__(self):
"""
Initialization of bot over IRC.
"""
self.irc = IrcClientFactory(config)
self.irc.set_privmsg = self.set_privmsg
reactor.connectTCP(config.server, config.port, self.irc)
def set_privmsg(self):
"""
This method set the methods to call for each callback received from IRC.
"""
self.irc.client.privmsg = self.on_privmsg
self.irc.client.joined = self.on_joined
#self.irc.client.left = self.on_left
#self.irc.client.noticed = self.on_noticed
#self.irc.client.modeChanged = self.on_mode_changed
#self.irc.client.kickedFrom = self.on_kicked_from
#self.irc.client.nickChanged = self.on_nick_changed
#self.irc.client.userJoined = self.on_user_joined
#self.irc.client.userLeft = self.on_user_left
#self.irc.client.userQuit = self.on_user_quit
#self.irc.client.userKicked = self.on_user_kicked
#self.irc.client.action = self.on_action
#self.irc.client.topicUpdated = self.on_topic_updated
#self.irc.client.userRenamed = self.on_user_renamed
def send_message(self, channel, messages):
"""
Sends a message on specified channel, cutting each line in a new message
"""
for message in messages.splitlines():
self.irc.client.msg(channel, message)
def on_privmsg(self, user, channel, msg):
"""
Wantzel can understand some commands :
- help
Returns a message about how to use the bot.
If a command is passed after help, the message explains how to use
the command.
- rp(acp)
- stats
- quote
- tc
- kill
"""
# Cleaning user name
user = re.search("([^!]*)!", user).group(1)
print("Message reçu: %s %s %s" % (user, channel, msg))
# Help command, specific
if "wantzel" in msg and ("help" in msg or "aide" in msg):
self.help(user, channel, msg)
# Find command with parameters
command = re.search("!(rp[acp]*|quote|tc|kill) ", msg)
if not command:
# Find command without parameters
command = re.search("^!(help|stats)$", msg)
if command:
print("Commande reçue: %s" % command.group(1))
command = command.group(1)
if command.startswith("rp"):
self.rp(command, user, channel, msg)
elif command=="help":
self.help(user, channel, msg)
elif command=="kill":
self.kill(user, channel, msg)
elif command=="stats":
self.stats(user, channel, msg)
elif command=="quote":
self.quote(user, channel, msg)
elif command=="tc":
self.tc(user, channel, msg)
def on_joined(self, channel):
"""
Say hello to everyone.
"""
print("Canal %s rejoint" % channel)
self.send_message("#mytipy", messages["hello"])
def help(self, user, channel, msg):
"""
Show global help.
If a known command is behind the !help command, an adequate message is
returned.
"""
print("help command")
self.send_message(channel, messages["help"])
def rp(self, command, user, channel, msg):
"""
Adding the article in rp database.
"""
print("rp command %s" % command)
cite = 0
note = 0
# On récupère tout ce qui suit la commande !rp
url = re.search("!rp (.*)", msg).group(1)
# On nettoie tout ce qui est http
url = re.search("(https?://)?(.*)", url).group(2)
# On vire l'ancre si elle existe
url = re.search("([^#]*)", url).group(0)
# On se débarasse des trackers
url = re.sub("", "", url)
print("url: %s" % url)
# On vérifie ensuite l'existence de l'url dans la base de données
db = MySQLdb.connect(host="localhost", user="root", passwd="root", db="site")
cursor = db.cursor()
cursor.execute("SELECT id, note, provenance FROM presse WHERE url = %s", (url, ))
rows = cursor.fetchall()
if not rows:
# LQdN is quoted
if "c" in command:
cite += 2
# the article speak about LQdN
if command.count("p")>1:
cite += 2
# Archive this article
if "a" in command:
note -= 2
#TODO: Gérer les autres champs qui n'ont pas de valeur par défaut
result = cursor.execute(
"INSERT INTO presse SET url=%s, provenance=%s, cite=%s, note=%s, datec=NOW()",
(url, user, cite, note)
)
self.send_message(channel, messages["merci_nouvel_article"] % user)
else:
print("Ajout d'un point par %s sur %s" % (rows[0][2], rows[0][0]))
if rows[0][2]!=user:
result = cursor.execute(
"UPDATE presse SET note=note+1 WHERE id=%s",
(rows[0][0], )
)
if (rows[0][1]+1)<3:
self.send_message(channel, messages["merci_article_connu"] % user)
else:
self.send_message(channel, messages["merci_article_repris"] % user)
def kill(self, user, channel, msg):
"""
Kill an article by removing 100 points to its score.
"""
print("kill command")
pass
def stats(self, user, channel, msg):
"""
Returns stats on articles in press review.
"""
print("stats command")
db = MySQLdb.connect(host="localhost", user="root", passwd="root", db="site")
cursor = db.cursor()
periods = [1, 3, 7, 15]
notes = [0, 3 ,4]
notnull = 0
somethingatall = 0
result = ""
for note in notes:
notnull = 0
result = result + " note: %s => " % note
for period in periods:
cursor.execute(
"""SELECT COUNT(id) AS cid FROM presse
WHERE nid=0
AND datec>(NOW()-INTERVAL %s DAY)
AND note>=%s""",
(period, note)
)
rows = cursor.fetchall()
if rows[0][0]>0:
result = result + "%sj:%s, " % (period, rows[0][0])
notnull = 1
somethingatall=1
if notnull:
result = result[:-2] + "\n"
if not somethingatall:
#TODO: Bravo!
result = "Bravo!"
self.send_message(channel, result)
def quote(self, user, channel, msg):
"""
Record a quote of a VIP during debates.
"""
print("quote command")
pass
def tc(self, user, channel, msg):
"""
Timecode...
"""
print("tc command")
pass
if __name__ == '__main__':
wantzel = Wantzel()
reactor.run()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment