nntp-client 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -1,17 +1,17 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec CHANGED
@@ -1,2 +1,2 @@
1
- --format specdoc
2
- --color
1
+ --format specdoc
2
+ --color
data/Gemfile CHANGED
@@ -1,8 +1,8 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in nntp.gemspec
4
- gem 'rake'
5
- gem "rspec"
6
- gem "rspec-core"
7
- gem "rspec-expectations"
8
- gem "rspec-mocks"
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in nntp.gemspec
4
+ gem 'rake'
5
+ gem "rspec"
6
+ gem "rspec-core"
7
+ gem "rspec-expectations"
8
+ gem "rspec-mocks"
@@ -1,22 +1,22 @@
1
- Copyright (c) 2012 Michael Westbom
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1
+ Copyright (c) 2012 Michael Westbom
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
22
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -1 +1 @@
1
- require "bundler/gem_tasks"
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ module NNTP
2
+ Article = Struct.new(:id, :subject, :group, :num)
3
+ end
@@ -7,7 +7,7 @@ module NNTP
7
7
  # Most communication with an NNTP server happens in a back-and-forth
8
8
  # style.
9
9
  #
10
- # The client sends a message to the server. The server will respond with a status response, and sometimes with extra data. See {https://tools.ietf.org/html/rfc3977 RFC 3977} for more details.
10
+ # The client sends a article to the server. The server will respond with a status response, and sometimes with extra data. See {https://tools.ietf.org/html/rfc3977 RFC 3977} for more details.
11
11
  #
12
12
  # This class handles this communication by providing two methods,
13
13
  # one for use when additional data is expected, and one for when it is not.
@@ -1,17 +1,22 @@
1
1
  require "nntp/group"
2
- require 'nntp/message'
2
+ require 'nntp/article'
3
3
 
4
4
  module NNTP
5
5
  # Most of the action happens here. This class describes the
6
6
  # object the user interacts with the most.
7
7
  # It is constructed by NNTP::open, but you can build your own
8
8
  # if you like.
9
+
10
+ # @!attribute [r] article
11
+ # The current article pointed to by the server or nil if unset.
12
+ # @return [NNTP::Article, nil]
9
13
  class Session
10
- attr_reader :connection, :group
14
+ attr_reader :connection, :group, :article
11
15
  # @option options [NNTP::Connection, NNTP::SSLConnection] :connection
12
16
  # The connection object.
13
17
  def initialize(options)
14
18
  @group = nil
19
+ @article = nil
15
20
  @connection = options.fetch(:connection) do
16
21
  raise ArgumentError ":connection missing"
17
22
  end
@@ -51,18 +56,18 @@ module NNTP
51
56
  end
52
57
  end
53
58
 
54
- # Fetch list of message numbers from a given group.
59
+ # Fetch list of article numbers from a given group.
55
60
  # @param group The name of the group to list defaults to {#group #group.name}
56
61
  # @param range (nil) If given, specifies the range of messages to retrieve
57
- # @return [Array<NNTP::Message>] The list of messages
58
- # (only the message numbers will be populated).
62
+ # @return [Array<NNTP::Article>] The list of messages
63
+ # (only the article numbers will be populated).
59
64
  # @see https://tools.ietf.org/html/rfc3977#section-6.1.2
60
65
  def listgroup(*args)
61
66
  messages = []
62
67
  connection.query(:listgroup, *args) do |status, data|
63
68
  if status[:code] == 211
64
69
  data.each do |line|
65
- message = Message.new
70
+ message = Article.new
66
71
  message.num = line.to_i
67
72
  messages << message
68
73
  end
@@ -71,8 +76,29 @@ module NNTP
71
76
  messages
72
77
  end
73
78
 
79
+ # Fetch ID and/or Number of an article.
80
+ #
81
+ # If an article number is passed, the current article is changed
82
+ # to the selected article. If an ID is passed, the current article
83
+ # is NOT changed.
84
+ # @param id|num The article-id or article number to be selected.
85
+ # @return [NNTP::Article, nil] a Article struct or nil upon failure.
86
+ def stat(identifier = nil)
87
+ params = [:stat]
88
+ params += [identifier.to_s] unless identifier.nil?
89
+ connection.command(*params)
90
+ if status.code == 223
91
+ message = article_from_status(status.msg)
92
+ if identifier.to_i != 0
93
+ @article = message
94
+ end
95
+ message
96
+ else
97
+ nil
98
+ end
99
+ end
74
100
  # Fetch list of messages from current group.
75
- # @return [Array<NNTP::Message>] The list of messages
101
+ # @return [Array<NNTP::Article>] The list of messages
76
102
  # (The numbers AND the subjects will be populated).
77
103
  def subjects
78
104
  subjects = []
@@ -80,7 +106,7 @@ module NNTP
80
106
  connection.query(:xhdr, "Subject", range) do |status, data|
81
107
  if status[:code] == 221
82
108
  data.each do |line|
83
- message = Message.new
109
+ message = Article.new
84
110
  message.num, message.subject = line.split(' ', 2)
85
111
  subjects << message
86
112
  end
@@ -108,6 +134,14 @@ module NNTP
108
134
  end
109
135
  end
110
136
 
137
+ def article_from_status(status_msg)
138
+ message = Article.new
139
+ num, id = status_msg.split(' ', 2)
140
+ message.num = num.to_i unless num.to_i.zero?
141
+ message.id = id
142
+ message
143
+ end
144
+
111
145
  def check_initial_status
112
146
  raise "#{status}" if [400, 502].include? connection.get_status.code
113
147
  end
@@ -1,7 +1,7 @@
1
- module NNTP
2
- Status = Struct.new(:code, :msg) do
3
- def to_s
4
- "#{self[:code]} #{self[:msg]}"
5
- end
6
- end
1
+ module NNTP
2
+ Status = Struct.new(:code, :msg) do
3
+ def to_s
4
+ "#{self[:code]} #{self[:msg]}"
5
+ end
6
+ end
7
7
  end
@@ -1,3 +1,3 @@
1
1
  module NNTP
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -100,4 +100,21 @@ describe NNTP::Session do
100
100
  message_subjects(nntp.subjects).should eq ['Foo bar', 'Baz bang']
101
101
  end
102
102
  end
103
+ describe "#stat" do
104
+ let(:article) do
105
+ msg = NNTP::Article.new
106
+ msg.num = 1
107
+ msg.id = "<foo@bar.baz>"
108
+ msg
109
+ end
110
+
111
+ it "can set the current article using an article number" do
112
+ sock.should_receive(:print).with("STAT 1\r\n")
113
+ sock.should_receive(:gets).and_return("223 1 <foo@bar.baz>\r\n")
114
+ nntp.stub(:group) {NNTP::Group.new("alt.bin.foo", 1, 2, 2)}
115
+ nntp.stat(1)
116
+ nntp.status.should eq NNTP::Status.new(223, "1 <foo@bar.baz>")
117
+ nntp.article.should eq article
118
+ end
119
+ end
103
120
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nntp-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-11 00:00:00.000000000 Z
12
+ date: 2013-01-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -40,12 +40,10 @@ files:
40
40
  - LICENSE.txt
41
41
  - README.md
42
42
  - Rakefile
43
- - lib/NNTPClient.rb
44
- - lib/article.rb
45
43
  - lib/nntp.rb
44
+ - lib/nntp/article.rb
46
45
  - lib/nntp/connection.rb
47
46
  - lib/nntp/group.rb
48
- - lib/nntp/message.rb
49
47
  - lib/nntp/session.rb
50
48
  - lib/nntp/ssl_connection.rb
51
49
  - lib/nntp/status.rb
@@ -87,4 +85,3 @@ test_files:
87
85
  - spec/nntp_spec.rb
88
86
  - spec/session_spec.rb
89
87
  - spec/spec_helper.rb
90
- has_rdoc:
@@ -1,120 +0,0 @@
1
- require 'socket'
2
- require_relative 'group'
3
- require_relative 'article'
4
- require "NNTPClient/version"
5
-
6
- class NNTPClient
7
- attr_reader :socket, :status, :current_group
8
-
9
- def initialize(options = {})
10
- @socket = open_socket(options)
11
- init_attributes
12
- end
13
-
14
- def groups
15
- @groups ||= list_groups
16
- end
17
-
18
- def group(group)
19
- send_message "GROUP #{group}"
20
- self.status = get_status
21
- if status[:code] == 211
22
- self.current_group = create_group(status)
23
- end
24
- end
25
-
26
- def articles
27
- @articles ||= fetch_articles
28
- end
29
-
30
- def auth(options = {})
31
- send_message "AUTHINFO USER #{options[:user]}"
32
- self.status = get_status
33
- send_message "AUTHINFO PASS #{options[:pass]}"
34
- self.status = get_status
35
- if status[:code] == 281
36
- true
37
- else
38
- false
39
- end
40
- end
41
- private
42
- def fetch_articles
43
- send_message "XHDR Subject #{current_group.first}-"
44
- self.status = get_status
45
- return nil unless status[:code] == 221
46
- get_data_block.map do |line|
47
- article_id, article_subject = line.split(' ', 2)
48
- NNTP::Article.new(article_id, article_subject)
49
- end
50
- end
51
-
52
- def init_attributes
53
- @current_group = nil
54
- @status = nil
55
- @groups = nil
56
- @articles = nil
57
- end
58
-
59
- def create_group(status)
60
- params = status[:params]
61
- # TODO: This is ugly
62
- NNTP::Group.new(*params[1..-1])
63
- end
64
-
65
- def open_socket(options)
66
- options.fetch(:socket) {
67
- url = options.fetch(:url) { raise ArgumentError, ':url is required' }
68
- port = options.fetch(:port, 119)
69
- socket_factory = options.fetch(:socket_factory) { TCPSocket }
70
- socket_factory.new(url, port)
71
- }
72
- end
73
-
74
- def list_groups
75
- send_message "LIST"
76
- status = get_status
77
- return nil unless status[:code] == 215
78
-
79
- get_data_block
80
- end
81
-
82
- def groups=(list=[])
83
- @groups = list
84
- end
85
-
86
- def status=(status)
87
- @status = status
88
- end
89
-
90
- def current_group=(group)
91
- @current_group = group
92
- end
93
-
94
- def get_status
95
- line = get_line
96
- {
97
- :code => line[0..2].to_i,
98
- :message => line[3..-1].lstrip,
99
- :params => line.split
100
- }
101
- end
102
-
103
- def get_data_block
104
- lines = []
105
- current_line = get_line
106
- until current_line == '.'
107
- lines << current_line
108
- current_line = get_line
109
- end
110
- lines
111
- end
112
-
113
- def get_line
114
- socket.gets().chomp
115
- end
116
-
117
- def send_message(msg)
118
- socket.print "#{msg}\r\n"
119
- end
120
- end
@@ -1,7 +0,0 @@
1
- module NNTP
2
- Article = Struct.new(:number, :subject, :article_id) do
3
- def to_s
4
- subject
5
- end
6
- end
7
- end
@@ -1,3 +0,0 @@
1
- module NNTP
2
- Message = Struct.new(:id, :subject, :group, :num)
3
- end