Commit 30d587ba authored by Benjamin Graillot's avatar Benjamin Graillot

Grosse maj

parent c6c0f739
operators = {'yournick': float('+inf')}
socket_path = './ninja.socket'
channel_start = { '#', '&' }
This diff is collapsed.
# Copyright (c) 2012 Mathieu Lecarme
# This code is licensed under the MIT license (see LICENSE for details)
import imaplib
def idle(connection):
tag = connection._new_tag()
connection.send(b"%s IDLE\r\n" % tag)
response = connection.readline()
connection.loop = True
if response == b'+ idling\r\n':
while connection.loop:
resp = connection.readline()
resp = resp[2:-2]
if resp.endswith(b' EXISTS'):
uid, message = resp.split(b' ')
yield uid, message
else:
raise Exception("IDLE not handled? : %s" % response)
def done(connection):
connection.send(b"DONE\r\n")
connection.loop = False
imaplib.IMAP4.idle = idle
imaplib.IMAP4.done = done
\ No newline at end of file
import socket
import config
# Sources
import wiki
import news
import phabricator
SOURCES = [wiki.Wiki(), news.News(), phabricator.Phabricator()]
if __name__ == "__main__":
with open(config.socket_path, 'w') as fifo:
fifo.write('SOURCES ' + ','.join([source.name for source in SOURCES]))
[ source.thread.join() for source in SOURCES ]
\ No newline at end of file
import datetime
import nntplib
import time
import source
class News(source.Source):
def __init__(self):
source.Source.__init__(self, 'news', 'news.crans.org')
def loop(self):
host = 'news.crans.org'
port = 119
nntp = nntplib.NNTP(host, port)
groups = nntp.newgroups(datetime.date(1970, 1, 1))[1]
posts = { group.group : int(group.last) for group in groups }
while True:
time.sleep(5)
try:
groups = nntp.newgroups(datetime.date(1970, 1, 1))[1]
for group in groups:
nntp.group(group.group)
if not group.group in posts:
posts[group.group] = 1
for i in range(posts[group.group]+1, int(group.last)+1):
try:
article = nntp.head(i)[1].lines
author = subject = ''
for j in range(len(article)):
line = article[j]
k = j + 1
while k < len(article):
if article[k][0] != 32:
break
line += article[k]
k += 1
line = line.decode('utf-8', 'ignore')
if line.startswith('From: '):
author = line[6:]
if line.startswith('Subject: '):
subject = email.header.decode_header(line[9:])[0]
if subject[1] is None:
subject = subject[0]
else:
subject = subject[0].decode(subject[1])
self.push_update(Source.News, group.group, '\x0310{group}\x03 \x033{author}\x03 {subject}\x03'.format(group=group.group, author=author, subject=subject))
except:
continue
posts = { group.group : int(group.last) for group in groups }
except:
nntp = nntplib.NNTP(host, port)
\ No newline at end of file
This diff is collapsed.
import base64
import email
import email.header
import quopri
import re
import html2text
from imapidle import imaplib
import secrets
import source
class Phabricator(source.Source):
def __init__(self):
source.Source.__init__(self, 'phabricator', 'noreply@phabricator.crans.org')
def loop(self):
print('phabricator: connecting to', secrets.host)
while True:
try:
imap_client = imaplib.IMAP4_SSL(host=secrets.host)
imap_client.login(secrets.user, secrets.password)
imap_client.select()
print('Running...')
while True:
for uid, msg in imap_client.idle():
if msg == b'EXISTS':
fetcher = imaplib.IMAP4_SSL(host=secrets.host)
fetcher.login(secrets.user, secrets.password)
fetcher.select()
mail = fetcher.fetch(uid.decode('ascii'), '(RFC822)')
fetcher.logout()
mail = email.message_from_bytes(mail[1][0][1])
sender = mail['From']
if self.address not in sender:
continue
try:
projects = [project.strip()[2:-1] for project in mail['X-Phabricator-Projects'].split(',')]
except:
projects = []
body = base64.b64decode(mail.get_payload()).decode('ascii')
subject = mail['Subject']
tags = []
for m in re.finditer(r'\[(?P<tag>[^]]*)\]', subject):
tags.append(m.group('tag'))
m = re.search(r'(?P<task>T\d+):\s+(?P<name>.*)$', subject)
if m is None:
print("No task")
continue
task = m.group('task')
if projects:
task = projects[0] + '/' + task
task_name = m.group('name')
m = re.search(r'"(?P<author>[^"]*)"', sender)
if m is None:
print("No author:", sender)
continue
author = m.group('author')
self.push_update(task, '\x0310{task}\x03 \x033{author}\x03 {tag}\x03 \x0315{name}\x03'.format(task=task, author=author, tag=tags[1], name=task_name))
except Exception as e:
raise e
import email
import email.header
from enum import Enum
import os
import quopri
import re
from imapidle import imaplib
import secrets
import source
class Information(Enum):
required = 0
optional = 1
class Update(Enum):
edit = 0
create = 1
remove = 2
rename = 3
attach = 4
delete_attach = 5
DEFAULT_SENDER = 'wiki@crans.org'
UPDATES = (
# fonction de pré-traitement du mail
lambda mail: quopri.decodestring(mail.get_payload()).decode('utf-8').replace('\r', ''), {
Update.edit: (
lambda **kwargs: '\x0310{page}\x03 \x033{user}\x03 {comment}\x03 \x0315(r{rev})\x03'.format(**kwargs) if kwargs['comment']\
else '\x0310{page}\x03 \x033{user}\x03 \x0315(r{rev})\x03'.format(**kwargs),
'page', [
(Information.required, ['page', 'user'], r'La page « (?P<page>.*) » a été modifiée par (?P<user>.*) :'),
(Information.required, ['rev'], r'\?action=diff&rev1=[0-9]+&rev2=(?P<rev>[0-9]+)\n'),
(Information.optional, ['comment'], r'\s*Commentaire :\s*\n\s*(?P<comment>[^\n]*)\n')
]
),
Update.create: (
lambda **kwargs: '\x0310{page}\x03 \x033{user}\x03 {comment}\x03 \x0315(r1)\x03'.format(**kwargs) if kwargs['comment']\
else '\x0310{page}\x03 \x033{user}\x03 \x0315(r1)\x03'.format(**kwargs),
'page', [
(Information.required, ['page', 'user'], r'La page « (?P<page>.*) » a été modifiée par (?P<user>.*) :'),
(Information.required, [], r'\s*Nouvelle page :\n'),
(Information.optional, ['comment'], r'\s*Commentaire :\s*\n\s*(?P<comment>[^\n]*)\n')
]
),
Update.remove: (
lambda **kwargs: '\x0310{page}\x03 \x033{user}\x03 {comment}\x03'.format(**kwargs) if kwargs['comment']\
else '\x0310{page}\x03 \x033{user}\x03'.format(**kwargs),
'page', [
(Information.required, ['page', 'user'], r'La page « (?P<page>.*) » a été supprimée par (?P<user>.*) :'),
(Information.optional, ['comment'], r'\s*Commentaire :\s*\n\s*(?P<comment>[^\n]*)\n')
]
),
Update.rename: (
lambda **kwargs: '\x0310{page}\x03 \x033{user}\x03 rename --> \x0310{new}\x03 {comment}\x03'.format(**kwargs) if kwargs['comment']\
else '\x0310{page}\x03 \x033{user}\x03 rename --> \x0310{new}\x03'.format(**kwargs),
'page', [
(Information.required, ['page', 'new', 'user'], r'La page « (?P<page>.*) » a été renommée « (?P<new>.*) » par (?P<user>.*) :'),
(Information.optional, ['comment'], r'\s*Commentaire :\s*\n\s*(?P<comment>[^\n]*)\n')
]
),
Update.attach: (
lambda **kwargs: '\x0310{page}\x03 \x033{user}\x03 ajout de la pièce jointe : \x0310{name}\x03'.format(**kwargs),
'page', [
(Information.required, ['page', 'user'], r'vous vous êtes abonné aux notifications de changements pour la page "(?P<page>.*)"\.Une pièce jointe vient d\'y être ajouté par (?P<user>.*)\. Quelques détails sur la pièce jointe :'),
(Information.required, ['name'], r'Nom\s*:\s*(?P<name>[^\n]*)\n')
]
),
Update.delete_attach:(
lambda **kwargs: '\x0310{page}\x03 \x033{user}\x03 suppression de la pièce jointe : \x0310{name}\x03'.format(**kwargs),
'page', [
(Information.required, ['page', 'user'], r'vous vous êtes abonné aux notifications de changements pour la page "(?P<page>.*)"\.Une pièce jointe de cette page vient d\'être supprimée par (?P<user>.*)\. Quelques détails sur la pièce jointe :'),
(Information.required, ['name'], r'Nom\s*:\s*(?P<name>[^\n]*)\n')
]
)
}
)
class Wiki(source.Source):
def __init__(self):
source.Source.__init__(self, 'wiki', 'wiki@crans.org')
def loop(self):
print('wiki: connecting to', secrets.host)
while True:
try:
imap_client = imaplib.IMAP4_SSL(host=secrets.host)
imap_client.login(secrets.user, secrets.password)
imap_client.select()
print('Running...')
while True:
for uid, msg in imap_client.idle():
if msg == b'EXISTS':
fetcher = imaplib.IMAP4_SSL(host=secrets.host)
fetcher.login(secrets.user, secrets.password)
fetcher.select()
mail = fetcher.fetch(uid.decode('ascii'), '(RFC822)')
fetcher.logout()
mail = email.message_from_bytes(mail[1][0][1])
sender = mail['From']
preprocessor, updates = UPDATES
body = preprocessor(mail)
for update in updates:
next_update = False
message, page, regexps = updates[update]
kwargs = {}
for info, groups, regexp in regexps:
m = re.search(regexp, body)
if info == Information.required and not m:
next_update = True
break
elif m:
for group in groups:
kwargs[group] = m.group(group)
else:
for group in groups:
kwargs[group] = None
if next_update: continue
message = message(**kwargs)
page = kwargs[page]
self.push_update(page, message)
except:
continue
\ No newline at end of file
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