From 65a60d33fd4c5a93b738939c3fca3c4f52e3530a Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Tue, 26 Nov 2024 14:53:16 -0500 Subject: [PATCH] Refactor OVER, HDR Refactor OVER, HDR to be simpler, using a single convenience method to implement similar semantics for commands which operate on both single and ranges of messages --- lib/nntp/tiny/session.py | 143 ++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 83 deletions(-) diff --git a/lib/nntp/tiny/session.py b/lib/nntp/tiny/session.py index f6a64bf..5c2ce24 100644 --- a/lib/nntp/tiny/session.py +++ b/lib/nntp/tiny/session.py @@ -518,17 +518,62 @@ class Session(): return self.end() - def _message_by_id(self, identifier: str): - if identifier[0] == '<': - return self.db.get(Message, { - 'newsgroup_id': self.newsgroup.id, - 'message_id': identifier - }) + def _each_message_by_id(self, identifier: str): + if identifier is None: + if self.newsgroup is None: + self.respond(ResponseCode.NNTP_NEWSGROUP_NOT_SELECTED) + return + + if self.article_id is None: + self.respond(ResponseCode.NNTP_ARTICLE_INVALID_NUMBER) + return + + message = self.db.get(Message, self.article_id) + + if message is None: + self.respond(ResponseCode.NNTP_ARTICLE_INVALID_NUMBER) + return + + self.respond(ResponseCode.NNTP_INFORMATION_FOLLOWS) + + yield message + elif identifier[0] == '<': + message = self.db.query(Message, { + 'message_id': identifier + }).fetchone() + + if message is None: + self.respond(ResponseCode.NNTP_ARTICLE_NOT_FOUND_ID) + return + + self.respond(ResponseCode.NNTP_INFORMATION_FOLLOWS) + + yield message else: - return self.db.get(Message, { - 'newsgroup_id': self.newsgroup.id, - 'id': int(identifier) - }) + if self.newsgroup is None: + self.respond(ResponseCode.NNTP_NEWSGROUP_NOT_SELECTED) + return + + msgrange = MessageRange.parse(identifier) + + sql = f"select * from {Message.name} where " + sql += " newsgroup_id = ? and " + msgrange.where() + + cr = self.db.query_sql(Message, sql, (self.newsgroup.id,)) + + first = True + + for message in cr.each(): + if first: + first = False + self.respond(ResponseCode.NNTP_INFORMATION_FOLLOWS) + + yield message + + if first: + self.respond(ResponseCode.NNTP_ARTICLE_NOT_FOUND_RANGE) + + self.end() def _send_message_headers(self, message: Message): for name in message.headers: @@ -587,39 +632,9 @@ class Session(): message.id, message.headers.get(name, '') )) - def _cmd_hdr(self, name: str, msg: Optional[str]=None): - if self.newsgroup is None: - return self.respond(ResponseCode.NNTP_NEWSGROUP_NOT_SELECTED) - - if msg is None: - if self.article_id is None: - return self.respond(ResponseCode.NNTP_ARTICLE_INVALID_NUMBER) - - message = self.db.get(Message, self.article_id) - - self.respond(ResponseCode.NNTP_HEADERS_FOLLOW) + def _cmd_hdr(self, name: str, identifier: Optional[str]=None): + for message in self._each_message_by_id(identifier): self._send_message_header(message, name) - else: - msgrange = MessageRange.parse(msg) - - sql = f"select * from {Message.name} where " - sql += " newsgroup_id = ? and " + msgrange.where() - - cr = self.db.query_sql(Message, sql, (self.newsgroup.id,)) - - first = True - - for message in cr.each(): - if first: - first = False - self.respond(ResponseCode.NNTP_HEADERS_FOLLOW) - - self._send_message_header(message, name) - - if first: - return self.respond(ResponseCode.NNTP_ARTICLE_NOT_FOUND_RANGE) - - return self.end() def _message_overview(self, message: Message) -> dict: return map(lambda s: s.replace('\t', ' '), [ @@ -634,48 +649,10 @@ class Session(): ]) def _cmd_over(self, identifier: Optional[str]=None): - if identifier is None: - if self.newsgroup is None: - return self.respond(ResponseCode.NNTP_NEWSGROUP_NOT_SELECTED) + for message in self._each_message_by_id(identifier): + overview = self._message_overview(message) - if self.article_id is None: - return self.respond(ResponseCode.NNTP_ARTICLE_INVALID_NUMBER) - - message = self.db.get(Message, self.article_id) - - if message is None: - return self.respond(ResponseCode.NNTP_ARTICLE_INVALID_NUMBER) - elif identifier[0] == '<': - message = self.db.query(Message, { - 'message_id': identifier - }).fetchone() - - if message is None: - return self.respond(ResponseCode.NNTP_ARTICLE_NOT_FOUND_ID) - else: - if self.newsgroup is None: - return self.respond(ResponseCode.NNTP_NEWSGROUP_NOT_SELECTED) - - msgrange = MessageRange.parse(identifier) - - sql = f"select * from {Message.name} where " - sql += " newsgroup_id = ? and " + msgrange.where() - - cr = self.db.query_sql(Message, sql, (self.newsgroup.id,)) - - first = True - - for message in cr.each(): - if first: - first = False - self.respond(ResponseCode.NNTP_OVERVIEW_FOLLOWS) - - overview = self._message_overview(message) - - self.print('|'.join(overview)) - - if first: - return self.respond(ResponseCode.NNTP_ARTICLE_NOT_FOUND_RANGE) + self.print('|'.join(overview)) def _cmd_stat(self, identifier: Optional[str]=None): if self.newsgroup is None: