article 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 24f178bdea5023b318ac926df6c2cbafe6a813825ec8197d373cd2fa8f86e760
4
+ data.tar.gz: ff25214473b218a4f18070c0e10cdf1d0a150ef8ede81d3d2a49c8b6441023e2
5
+ SHA512:
6
+ metadata.gz: 70d8fc68951e797233e92010ed304febc056d473545e6592ce8984d06da2add8a5e22cc2dcd8c05ad66188e9ed836cb7ad3e22dfe9f1b67c3a0bbf4591450c2f
7
+ data.tar.gz: 7e947ecfc4ffc7c8facc673d64c44046786d7f055e479fbe4d845be2dbc1b064fa39364212b2686980bcfb56054eb749f078ad71db1dafe7f8354c23c2fe851c
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.standard.yml ADDED
@@ -0,0 +1,3 @@
1
+ # For available configuration options, see:
2
+ # https://github.com/standardrb/standard
3
+ ruby_version: 3.0
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Phillip Ridlen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # Article
2
+
3
+ Article is a Net News Transfer Protocol (NNTP) client library for Ruby.
4
+
5
+ ## Installation
6
+
7
+ TODO: Replace
8
+ `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your
9
+ gem name right after releasing it to RubyGems.org. Please do not do it earlier
10
+ due to security reasons. Alternatively, replace this section with instructions
11
+ to install your gem from git if you don't plan to release to RubyGems.org.
12
+
13
+ Install the gem and add to the application's Gemfile by executing:
14
+
15
+ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
16
+
17
+ If bundler is not being used to manage dependencies, install the gem by
18
+ executing:
19
+
20
+ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
21
+
22
+ ## Usage
23
+
24
+ TODO: Write usage instructions here
25
+
26
+ ## Contributing
27
+
28
+ Bug reports and pull requests are welcome on GitHub at
29
+ <https://github.com/philtr/article>.
30
+
31
+ ## License
32
+
33
+ The gem is available as open source under the terms of the [MIT
34
+ License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "standard/rake"
9
+
10
+ task default: %i[spec standard]
@@ -0,0 +1,93 @@
1
+ require "socket"
2
+ require "openssl"
3
+ require "timeout"
4
+ require "logger"
5
+
6
+ module Article
7
+ class Client
8
+ class ConnectionError < Article::Error; end
9
+ class AuthenticationError < Article::Error; end
10
+
11
+ def initialize(server, port, username, password, use_ssl: true)
12
+ @server = server
13
+ @port = port
14
+ @username = username
15
+ @password = password
16
+ @use_ssl = use_ssl
17
+ @logger = Logger.new(STDOUT)
18
+ end
19
+
20
+ def connect
21
+ @logger.info "Attempting to connect to #{@server}:#{@port} (SSL: #{@use_ssl})..."
22
+ Timeout.timeout(60) do
23
+ tcp_socket = TCPSocket.new(@server, @port)
24
+ if @use_ssl
25
+ ssl_context = OpenSSL::SSL::SSLContext.new
26
+ ssl_context.set_params(verify_mode: OpenSSL::SSL::VERIFY_NONE)
27
+ @socket = OpenSSL::SSL::SSLSocket.new(tcp_socket, ssl_context)
28
+ @socket.connect
29
+ else
30
+ @socket = tcp_socket
31
+ end
32
+ end
33
+ @logger.info "Connection established. Reading greeting..."
34
+ greeting = read_response
35
+ @logger.info "Server greeting: #{greeting}"
36
+ authenticate
37
+ yield self
38
+ rescue Timeout::Error
39
+ @logger.error "Connection to #{@server}:#{@port} timed out after 60 seconds"
40
+ raise ConnectionError, "Connection to #{@server}:#{@port} timed out"
41
+ rescue SocketError, OpenSSL::SSL::SSLError => e
42
+ @logger.error "Failed to connect to #{@server}:#{@port}: #{e.message}"
43
+ raise ConnectionError, "Failed to connect to #{@server}:#{@port}: #{e.message}"
44
+ ensure
45
+ @socket.close if @socket
46
+ end
47
+
48
+ def list
49
+ @logger.info "Sending LIST command..."
50
+ send_command("LIST")
51
+ response = read_multiline_response
52
+ @logger.info "Received #{response.size} groups"
53
+ response.map do |line|
54
+ name, last, first, flag = line.split(" ")
55
+ { name: name, last: last.to_i, first: first.to_i, flag: flag }
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def authenticate
62
+ @logger.info "Authenticating..."
63
+ response = send_command("AUTHINFO USER #{@username}")
64
+ if response.start_with?("381")
65
+ response = send_command("AUTHINFO PASS #{@password}")
66
+ raise AuthenticationError, "Authentication failed: #{response}" unless response.start_with?("281")
67
+ end
68
+ @logger.info "Authentication successful"
69
+ end
70
+
71
+ def send_command(command)
72
+ @logger.debug "Sending command: #{command}"
73
+ @socket.puts(command)
74
+ read_response
75
+ end
76
+
77
+ def read_response
78
+ response = @socket.gets&.chomp
79
+ @logger.debug "Received response: #{response}"
80
+ raise ConnectionError, "No response from server" if response.nil?
81
+ response
82
+ end
83
+
84
+ def read_multiline_response
85
+ response = []
86
+ while (line = @socket.gets&.chomp) != "."
87
+ break if line.nil?
88
+ response << line
89
+ end
90
+ response
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Article
4
+ VERSION = "0.0.1"
5
+ end
data/lib/article.rb ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "article/version"
4
+
5
+ module Article
6
+ class Error < StandardError; end
7
+
8
+ autoload :Client, "article/client"
9
+ end
data/sig/article.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Article
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: article
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Phillip Ridlen
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-08-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ description: Article is an NNTP client that can be used to fetch articles from a Usenet
28
+ server.
29
+ email:
30
+ - p@rdln.net
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - ".rspec"
36
+ - ".standard.yml"
37
+ - LICENSE.txt
38
+ - README.md
39
+ - Rakefile
40
+ - lib/article.rb
41
+ - lib/article/client.rb
42
+ - lib/article/version.rb
43
+ - sig/article.rbs
44
+ homepage: https://github.com/philtr/article
45
+ licenses:
46
+ - MIT
47
+ metadata:
48
+ homepage_uri: https://github.com/philtr/article
49
+ source_code_uri: https://github.com/philtr/article
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: 3.0.0
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubygems_version: 3.5.15
66
+ signing_key:
67
+ specification_version: 4
68
+ summary: NNTP client
69
+ test_files: []