96 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import enum
 | 
						|
import socket
 | 
						|
 | 
						|
from typing import Optional
 | 
						|
 | 
						|
class ResponseCode(enum.Enum):
 | 
						|
    NNTP_HELP_FOLLOWS                  = 100
 | 
						|
    NNTP_CAPABILITIES_FOLLOW           = 101
 | 
						|
    NNTP_DATE                          = 111
 | 
						|
    NNTP_SERVICE_READY_POST_ALLOWED    = 200
 | 
						|
    NNTP_SERVICE_READY_POST_PROHIBITED = 201
 | 
						|
    NNTP_CONNECTION_CLOSING            = 205
 | 
						|
    NNTP_GROUP_LISTING                 = 211
 | 
						|
    NNTP_INFORMATION_FOLLOWS           = 215
 | 
						|
    NNTP_ARTICLE_BODY                  = 220
 | 
						|
    NNTP_ARTICLE_LISTING               = 221
 | 
						|
    NNTP_BODY_LISTING                  = 222
 | 
						|
    NNTP_ARTICLE_STAT_RESPONSE         = 223
 | 
						|
    NNTP_OVERVIEW_FOLLOWS              = 224
 | 
						|
    NNTP_HEADERS_FOLLOW                = 225
 | 
						|
    NNTP_ARTICLE_LISTING_ID_FOLLOWS    = 230
 | 
						|
    NNTP_GROUPS_NEW_FOLLOW             = 231
 | 
						|
    NNTP_ARTICLE_RECEIVED_ID           = 235
 | 
						|
    NNTP_ARTICLE_RECEIVED              = 240
 | 
						|
    NNTP_AUTH_ACCEPTED                 = 281
 | 
						|
    NNTP_INQUIRY_ARTICLE_ID            = 335
 | 
						|
    NNTP_INQUIRY_ARTICLE               = 340
 | 
						|
    NNTP_INQUIRY_PASSPHRASE            = 381
 | 
						|
    NNTP_NEWSGROUP_NOT_FOUND           = 411
 | 
						|
    NNTP_NEWSGROUP_NOT_SELECTED        = 412
 | 
						|
    NNTP_ARTICLE_INVALID_NUMBER        = 420
 | 
						|
    NNTP_ARTICLE_NO_NEXT               = 421
 | 
						|
    NNTP_ARTICLE_NO_PREVIOUS           = 422
 | 
						|
    NNTP_ARTICLE_NOT_FOUND_NUM         = 423
 | 
						|
    NNTP_ARTICLE_NOT_FOUND_ID          = 430
 | 
						|
    NNTP_ARTICLE_NOT_WANTED_ID         = 435
 | 
						|
    NNTP_POST_PROHIBITED               = 440
 | 
						|
    NNTP_POST_FAILED                   = 441
 | 
						|
    NNTP_AUTH_FAILED                   = 481
 | 
						|
    NNTP_AUTH_BAD_SEQUENCE             = 482
 | 
						|
    NNTP_COMMAND_UNKNOWN               = 500
 | 
						|
    NNTP_SYNTAX_ERROR                  = 501
 | 
						|
    NNTP_COMMAND_UNAVAILABLE           = 502
 | 
						|
    NNTP_GROUPS_UNAVAILABLE            = 503
 | 
						|
 | 
						|
    def message(self):
 | 
						|
        return {
 | 
						|
            100: "Help text follows",
 | 
						|
            101: "Capabilities follow",
 | 
						|
            200: "NNTP Service Ready, posting allowed",
 | 
						|
            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",
 | 
						|
            235: "Article received OK",
 | 
						|
            240: "Article received OK",
 | 
						|
            281: "Authentication accepted",
 | 
						|
            335: "Input article; end with <CR><LF>.<CR><LF>",
 | 
						|
            340: "Input article; end with <CR><LF>.<CR><LF>",
 | 
						|
            381: "Enter passphrase",
 | 
						|
            411: "No such newsgroup",
 | 
						|
            412: "No newsgroup selected",
 | 
						|
            420: "Current article number is invalid",
 | 
						|
            421: "No next article in this group",
 | 
						|
            422: "No previous article in this group",
 | 
						|
            423: "No article found by that message number",
 | 
						|
            430: "No article found by that message ID",
 | 
						|
            435: "Article not wanted",
 | 
						|
            440: "Posting prohibited",
 | 
						|
            441: "Posting failed",
 | 
						|
            481: "Authentication failed",
 | 
						|
            482: "Authentication commands issued out of sequence",
 | 
						|
            500: "Unknown command",
 | 
						|
            501: "Syntax error",
 | 
						|
            502: "Command unavailable",
 | 
						|
            503: "No list of recommended newsgroups available"
 | 
						|
        }.get(self.value)
 | 
						|
 | 
						|
class Response():
 | 
						|
    __slots__ = 'code', 'message', 'body',
 | 
						|
    
 | 
						|
    def __init__(self, code: ResponseCode, message: Optional[str]=None, body: Optional[str]=None):
 | 
						|
        self.code    = code
 | 
						|
        self.message = message or code.message() or "Unknown response"
 | 
						|
        self.body    = body
 | 
						|
 | 
						|
    def __str__(self):
 | 
						|
        ret = "%d %s" % (self.code.value, self.message)
 | 
						|
 | 
						|
        if self.body:
 | 
						|
            ret += "\r\n" + self.body
 | 
						|
 | 
						|
        return ret
 |