Gotta commit somethin' :X

This commit is contained in:
XANTRONIX Development 2024-11-22 23:57:14 -05:00
parent 277c4c0aab
commit 9a4febca5c
2 changed files with 146 additions and 4 deletions

View file

@ -1,10 +1,21 @@
import enum import enum
from nntp.tiny.db import Database
from nntp.tiny.newsgroup import Newsgroup
class ServerCapability(enum.Flag): class ServerCapability(enum.Flag):
NONE = 0 NONE = 0
AUTH = enum.auto() AUTH = enum.auto()
POST = enum.auto() POST = enum.auto()
class Server(): class Server():
def __init_(self): def __init_(self, db: Database):
self.capabilities = NNTPServerCapability.NONE self.db = db
self.capabilities = ServerCapability.NONE
self.newsgroups = dict()
self._init_groups()
def _init_newsgroups(self):
for newsgroup in self.db.query(Newsgroup).each():
self.newsgroups[newsgroup.name.casefold()] = newsgroup

View file

@ -2,8 +2,12 @@ import enum
import socket import socket
import re import re
from typing import Optional
from nntp.tiny.server import Server, ServerCapability from nntp.tiny.server import Server, ServerCapability
from nntp.tiny.response import Response from nntp.tiny.response import Response, ResponseCode
from nntp.tiny.newsgroup import Newsgroup
from nntp.tiny.message import Message
class SessionState(enum.Flag): class SessionState(enum.Flag):
NONE = 0 NONE = 0
@ -12,6 +16,70 @@ class SessionState(enum.Flag):
from nntp.tiny.buffer import LineBuffer, BufferOverflow from nntp.tiny.buffer import LineBuffer, BufferOverflow
class MessageRange():
__slots__ = 'id', 'min', 'max',
RE_NUM = re.compile('^(\d+)$')
RE_RANGE = re.compile('^(\d+)-(\d+)$')
RE_RANGE_LOWER = re.compile('^(\d+$)-$')
RE_RANGE_UPPER = re.compile('^-(\d+$)$')
def __init__(self):
self.id: int = None
self.min: int = None
self.max: int = None
def __str__(self):
if self.id is not None:
return str(self.id)
if self.min is not None and self.max is None:
return "%d-" % (self.min)
elif self.min is not None and self.max is not None:
return "%d-%d" % (self.min, self.max)
elif self.min is None and self.max is not None:
return "-%d" % (self.max)
return "?"
def __dict__(self):
if self.id is not None:
return {'id': self.id}
if self.min is not None and self.max is None:
return { 'min(id)': self.min }
elif self.min is not None and self.max is not None:
return { 'min(id)': self.min, 'max(id)': self.max }
elif self.min is None and self.max is not None:
return { 'max(id)': self.max }
@staticmethod
def parse(r: str):
match = __class__.RE_NUM.match(r)
if match:
obj = __class__()
obj.id = match[1]
return obj
match = __class__.RE_RANGE.match(r)
if match:
obj = __class__()
obj.min = match[1]
obj.max = match[2]
return obj
match = __class__.RE_RANGE_LOWER.match(r)
if match:
obj = __class__()
obj.min = match[1]
return obj
match = __class__.RE_RANGE_UPPER.match(r)
if match:
obj = __class__()
obj.max = match[1]
return obj
class Session(): class Session():
RE_SPLIT = re.compile(r'\s+') RE_SPLIT = re.compile(r'\s+')
@ -36,6 +104,8 @@ class Session():
self.sock: socket.socket = sock self.sock: socket.socket = sock
self.buf: LineBuffer = LineBuffer() self.buf: LineBuffer = LineBuffer()
self.newsgroup: Optional[Newsgroup] = None
def readline(self): def readline(self):
return self.buf.readline(self.sock) return self.buf.readline(self.sock)
@ -64,6 +134,67 @@ class Session():
self.end() self.end()
def _cmd_group(self, name: str):
if name not in self.server.newsgroups:
return self.respond(ResponseCode.NNTP_NEWSGROUP_NOT_FOUND)
newsgroup = self.server.newsgroups[name]
sql = """
select
count(id),
min(id),
max(id)
from
newsgroup_message
where
newsgroup_id = ?
"""
cr = self.server.db.execute(sql, (newsgroup.id))
row = cr.fetchone()
text = "%d %d %d %s" % (
row[0],
row[1],
row[2],
newsgroup.name
)
self.respond(ResponseCode.NNTP_GROUP_LISTING, text)
self.newsgroup = newsgroup
return
def _cmd_listgroup(self, *args):
newsgroup = self.newsgroup
if len(args) == 0 and newsgroup is None:
return self.respond(ResponseCode.NNTP_NEWSGROUP_NOT_SELECTED)
elif len(args) > 0:
newsgroup = self.server.newsgroups.get(args[0])
if newsgroup is None:
return self.respond(ResponseCode.NNTP_NEWSGROUP_NOT_FOUND)
values = {
'newsgroup_id': newsgroup.id
}
if len(args) > 1:
msgrange = MessageRange.parse(args[1])z
values.update(dict(msgrange))
cr = self.server.db.query(Message, values)
for message in cr.each():
self.print(str(message.id))
return self.end()
def handle(self): def handle(self):
line = self.readline() line = self.readline()