Class: NNTP::Session

Inherits:
Object
  • Object
show all
Defined in:
lib/nntp/session.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Session

Returns a new instance of Session.

Parameters:

  • options (Hash)

    a customizable set of options

Options Hash (options):



17
18
19
20
21
22
23
24
# File 'lib/nntp/session.rb', line 17

def initialize(options)
  @group = nil
  @article = nil
  @connection = options.fetch(:connection) do
    raise ArgumentError ":connection missing"
  end
  check_initial_status
end

Instance Attribute Details

#articleNNTP::Article? (readonly)

The current article pointed to by the server or nil if unset.

Returns:



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/nntp/session.rb', line 13

class Session
  attr_reader :connection, :group, :article
  # @option options [NNTP::Connection, NNTP::SSLConnection] :connection
  #   The connection object.
  def initialize(options)
    @group = nil
    @article = nil
    @connection = options.fetch(:connection) do
      raise ArgumentError ":connection missing"
    end
    check_initial_status
  end

  # Authenticate to the server.
  #
  # @option args :user Username
  # @option args :pass Password
  # @option args :type (:standard)
  #   Which authentication type to use.  Currently only
  #   standard is supported.
  # @return [NNTP::Status]
  def auth(args)
    auth_method = args.fetch(:type, :standard)
    standard_auth(args) if auth_method == :standard
  end

  # Fetches and returns the list of groups from the server or, if it
  # has already been fetched, returns the saved list.
  # @return [Array<NNTP::Group>]
  def groups
    @groups ||= fetch_groups
  end

  # @!attribute [rw] group
  #   Retrieves current group, or
  #   sets current group, server-side, to assigned value.
  #   @param [String] group_name The name of the group to be selected.
  #   @return [NNTP::Group] The current group.
  def group=(group_name)
    connection.command(:group, group_name)
    if status[:code] == 211
      num, low, high, name = status[:msg].split
      @group = group_factory(name, low.to_i, high.to_i, num.to_i)
    end
  end

  # Fetch list of article numbers from a given group.
  # @param group  The name of the group to list defaults to {#group #group.name}
  # @param range (nil) If given, specifies the range of messages to retrieve
  # @return [Array<NNTP::Article>] The list of messages
  #   (only the article numbers will be populated).
  # @see https://tools.ietf.org/html/rfc3977#section-6.1.2
  def listgroup(*args)
    messages = []
    connection.query(:listgroup, *args) do |status, data|
      if status[:code] == 211
        data.each do |line|
          message = Article.new
          message.num = line.to_i
          messages << message
        end
      end
    end
    messages
  end

  # Fetch ID and/or Number of an article.
  #
  # If an article number is passed, the current article is changed
  # to the selected article.  If an ID is passed, the current article
  # is NOT changed.
  # @param id|num The article-id or article number to be selected.
  # @return [NNTP::Article, nil] a Article struct or nil upon failure.
  def stat(identifier = nil)
    params = [:stat]
    params += [identifier.to_s] unless identifier.nil?
    connection.command(*params)
    if status.code == 223
      message = article_from_status(status.msg)
      if identifier.to_i != 0
        @article = message
      end
      message
    else
      nil
    end
  end
  # Fetch list of messages from current group.
  # @return [Array<NNTP::Article>] The list of messages
  #   (The numbers AND the subjects will be populated).
  def subjects
    subjects = []
    range ="#{group[:first_message]}-"
    connection.query(:xhdr, "Subject", range) do |status, data|
      if status[:code] == 221
        data.each do |line|
          message = Article.new
          message.num, message.subject = line.split(' ', 2)
          subjects << message
        end
      end
    end
    subjects
  end

  # The most recent status from the server.
  def status
    connection.status
  end

  # (see NNTP::Connection#quit)
  def quit
    connection.quit
  end
  private
  def standard_auth(args)
    connection.command(:authinfo, "USER #{args[:user]}")
    if status[:code] == 381
      connection.command(:authinfo, "PASS #{args[:pass]}")
    elsif [281, 482, 502].include? status[:code]
      status
    end
  end

  def article_from_status(status_msg)
    message = Article.new
    num, id = status_msg.split(' ', 2)
    message.num = num.to_i unless num.to_i.zero?
    message.id = id
    message
  end

  def check_initial_status
    raise "#{status}" if [400, 502].include? connection.get_status.code
  end

  def group_from_list(group_string)
    params = group_string.split
    name = params[0]
    high_water_mark = params[1].to_i
    low_water_mark = params[2].to_i
    group_factory(name, low_water_mark, high_water_mark)
  end

  def group_factory(*args)
    name = args[0]
    low, high, num = args[1..-1].map { |arg| arg.to_i }
    NNTP::Group.new(name, low, high, num)
  end

  def fetch_groups
    group_list = []
    connection.query :list do |status, list|
      list.each do |group|
        group_list << group_from_list(group)
      end if status[:code] == 215
    end
    group_list
  end
end

#connectionObject (readonly)

Returns the value of attribute connection.



14
15
16
# File 'lib/nntp/session.rb', line 14

def connection
  @connection
end

#groupNNTP::Group

Retrieves current group, or sets current group, server-side, to assigned value.

Parameters:

  • group_name (String)

    The name of the group to be selected.

Returns:



51
52
53
# File 'lib/nntp/session.rb', line 51

def group
  @group
end

Instance Method Details

#auth(args) ⇒ NNTP::Status

Authenticate to the server.

Parameters:

  • args (Hash)

    a customizable set of options

Options Hash (args):

  • :user (Object)

    Username

  • :pass (Object)

    Password

  • :type (Object) — default: :standard

    Which authentication type to use. Currently only standard is supported.

Returns:



34
35
36
37
# File 'lib/nntp/session.rb', line 34

def auth(args)
  auth_method = args.fetch(:type, :standard)
  standard_auth(args) if auth_method == :standard
end

#groupsArray<NNTP::Group>

Fetches and returns the list of groups from the server or, if it has already been fetched, returns the saved list.

Returns:



42
43
44
# File 'lib/nntp/session.rb', line 42

def groups
  @groups ||= fetch_groups
end

#listgroup(*args) ⇒ Array<NNTP::Article>

Fetch list of article numbers from a given group.

Parameters:

  • group

    The name of the group to list defaults to #group.name

  • range (nil)

    If given, specifies the range of messages to retrieve

Returns:

  • (Array<NNTP::Article>)

    The list of messages (only the article numbers will be populated).

See Also:



65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/nntp/session.rb', line 65

def listgroup(*args)
  messages = []
  connection.query(:listgroup, *args) do |status, data|
    if status[:code] == 211
      data.each do |line|
        message = Article.new
        message.num = line.to_i
        messages << message
      end
    end
  end
  messages
end

#quitvoid

This method returns an undefined value.

Sends “QUIT\r\n” to the server, disconnects the socket.



124
125
126
# File 'lib/nntp/session.rb', line 124

def quit
  connection.quit
end

#stat(identifier = nil) ⇒ NNTP::Article?

Fetch ID and/or Number of an article.

If an article number is passed, the current article is changed to the selected article. If an ID is passed, the current article is NOT changed.

Parameters:

  • id|num

    The article-id or article number to be selected.

Returns:



86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/nntp/session.rb', line 86

def stat(identifier = nil)
  params = [:stat]
  params += [identifier.to_s] unless identifier.nil?
  connection.command(*params)
  if status.code == 223
    message = article_from_status(status.msg)
    if identifier.to_i != 0
      @article = message
    end
    message
  else
    nil
  end
end

#statusObject

The most recent status from the server.



119
120
121
# File 'lib/nntp/session.rb', line 119

def status
  connection.status
end

#subjectsArray<NNTP::Article>

Fetch list of messages from current group.

Returns:

  • (Array<NNTP::Article>)

    The list of messages (The numbers AND the subjects will be populated).



103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/nntp/session.rb', line 103

def subjects
  subjects = []
  range ="#{group[:first_message]}-"
  connection.query(:xhdr, "Subject", range) do |status, data|
    if status[:code] == 221
      data.each do |line|
        message = Article.new
        message.num, message.subject = line.split(' ', 2)
        subjects << message
      end
    end
  end
  subjects
end