diff --git a/lib/nntp/tiny/response.py b/lib/nntp/tiny/response.py index 5115748..952aad2 100644 --- a/lib/nntp/tiny/response.py +++ b/lib/nntp/tiny/response.py @@ -46,6 +46,7 @@ class ResponseCode(enum.Enum): 201: "NNTP Service Ready, posting prohibited", 205: "Connection closing", 215: "Information follows", + 223: "Article exists", 224: "Overview information follows (multi-line)", 225: "Headers follow (multi-line)", 231: "List of new newsgroups follows", diff --git a/lib/nntp/tiny/session.py b/lib/nntp/tiny/session.py index d2ce980..fa123fd 100644 --- a/lib/nntp/tiny/session.py +++ b/lib/nntp/tiny/session.py @@ -503,6 +503,51 @@ class Session(): return self.end() + def _cmd_stat(self, identifier: Optional[str]=None): + if self.newsgroup is None: + return self.respond(ResponseCode.NNTP_NEWSGROUP_NOT_SELECTED) + + sql = """ + select + id, message_id + from + newsgroup_message + where + newsgroup_id = ? + """ + + row = None + + if identifier is None: + if self.article_id is None: + return self.respond(ResponseCode.NNTP_ARTICLE_INVALID_NUMBER) + + identifier = str(self.article_id) + + if identifier[0] == '<': + cr = self.db.execute(sql + " and message_id = ?", + (self.newsgroup.id, identifier)) + + row = cr.fetchone() + + if row is None: + return self.respond(ResponseCode.NNTP_ARTICLE_NOT_FOUND_ID) + else: + cr = self.db.execute(sql + " and id = ?", + (self.newsgroup.id, int(identifier))) + + row = cr.fetchone() + + if row is None: + return self.respond(ResponseCode.NNTP_ARTICLE_NOT_FOUND_NUM) + + text = "%d %s" % (row[0], row[1]) + + if self.article_id is None: + self.article_id = int(row[0]) + + return self.respond(ResponseCode.NNTP_ARTICLE_STAT_RESPONSE, text) + COMMANDS = { 'CAPABILITIES': _cmd_capabilities, 'GROUP': _cmd_group, @@ -514,6 +559,7 @@ class Session(): 'BODY': _cmd_body, 'ARTICLE': _cmd_article, 'HDR': _cmd_hdr, + 'STAT': _cmd_stat, } def handle(self):