ruqqus 1.1.0 → 1.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +24 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +33 -0
- data/CODE_OF_CONDUCT.md +51 -0
- data/CONTRIBUTING.md +24 -0
- data/README.md +18 -7
- data/TODO.md +0 -2
- data/assets/ruby-ruqqus.png +0 -0
- data/assets/ruqqus_text_logo.png +0 -0
- data/exe/ruqqus-oauth +2 -2
- data/lib/ruqqus.rb +184 -14
- data/lib/ruqqus/client.rb +126 -16
- data/lib/ruqqus/token.rb +18 -31
- data/lib/ruqqus/types/comment.rb +18 -12
- data/lib/ruqqus/types/guild.rb +60 -33
- data/lib/ruqqus/types/item_base.rb +21 -13
- data/lib/ruqqus/types/post.rb +32 -14
- data/lib/ruqqus/types/submission.rb +68 -46
- data/lib/ruqqus/types/user.rb +55 -30
- data/lib/ruqqus/version.rb +7 -3
- data/ruqqus.gemspec +4 -2
- metadata +17 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62b35161bf5278e264c66836f39a80de3492dcd627f7e1e9d701a5439af30649
|
4
|
+
data.tar.gz: 0cbc0628bcceebaac0770ed2c2fa5558d632ab3f02f5c7c9deb500f9552c3e4f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da177c6d90e02598bb5438d79b3c0fca5219922a1bda1d20a67e458be8bebf078621c45bdbf557f84c278bfa2d668cee6002911512a98ce6dda8945383c97c72
|
7
|
+
data.tar.gz: 46f0839094cfd3e134df3719cc7bf189df295963f34a106c0540063af57d5dac887c7ca5c019e1afb7152c4d4051a025b1dbe12dd7f287ac4c316e9fe265bc18
|
@@ -0,0 +1,24 @@
|
|
1
|
+
---
|
2
|
+
name: Bug report
|
3
|
+
about: Create a report to help us improve
|
4
|
+
title: "[BUG] "
|
5
|
+
labels: ''
|
6
|
+
assignees: ''
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
**Describe the bug**
|
11
|
+
A clear and concise description of what the bug is.
|
12
|
+
|
13
|
+
**To Reproduce**
|
14
|
+
Steps to reproduce the behavior:
|
15
|
+
1. Go to '...'
|
16
|
+
2. Click on '....'
|
17
|
+
3. Scroll down to '....'
|
18
|
+
4. See error
|
19
|
+
|
20
|
+
**Expected behavior**
|
21
|
+
A clear and concise description of what you expected to happen.
|
22
|
+
|
23
|
+
**Additional context**
|
24
|
+
Add any other context about the problem here.
|
@@ -0,0 +1,17 @@
|
|
1
|
+
---
|
2
|
+
name: Feature request
|
3
|
+
about: Suggest an idea for this project
|
4
|
+
title: ''
|
5
|
+
labels: ''
|
6
|
+
assignees: ''
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
**Is your feature request related to a problem? Please describe.**
|
11
|
+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
12
|
+
|
13
|
+
**Describe the solution you'd like**
|
14
|
+
A clear and concise description of what you want to happen.
|
15
|
+
|
16
|
+
**Additional context**
|
17
|
+
Add any other context or screenshots about the feature request here.
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,39 @@
|
|
2
2
|
|
3
3
|
Documentation for library API changes.
|
4
4
|
|
5
|
+
Versioning system:
|
6
|
+
|
7
|
+
`MAJOR.MINOR.REVISION`
|
8
|
+
|
9
|
+
* `MAJOR` Corresponds to the native Ruqqus API major version
|
10
|
+
* `MINOR` Indicates possible breaking API changes for existing code
|
11
|
+
* `REVISION` Added functionality, bug-fixes, and other non-breaking alterations
|
12
|
+
|
13
|
+
## Version 1.1.5
|
14
|
+
|
15
|
+
* Added `Ruqqus::Clien#post_delete` method
|
16
|
+
* Added `Ruqqus::Guild#guildmasters` attribute
|
17
|
+
|
18
|
+
## Version 1.1.4
|
19
|
+
|
20
|
+
* Improved the way refreshing works to do so within a certain threshold
|
21
|
+
|
22
|
+
## Version 1.1.3
|
23
|
+
|
24
|
+
* Implemented browser-based confirmation process
|
25
|
+
* Implemented capturing confirmation code from `localhost` OAuth redirects
|
26
|
+
* Fixed bug in querying guild/username availability
|
27
|
+
|
28
|
+
## Version 1.1.2
|
29
|
+
|
30
|
+
* Implemented enumerating comments of guilds and posts
|
31
|
+
|
32
|
+
## Version 1.1.1
|
33
|
+
|
34
|
+
* BUGFIX: Added acceptance of variable args to `Token#to_json`
|
35
|
+
* BUGFIX: Fixed regex validator in `ruqqus-oauth` for the client ID
|
36
|
+
* Separated the client ID/secret from the `Token` class, and placed within `Client` to now handle this logic
|
37
|
+
|
5
38
|
## Version 1.1.0
|
6
39
|
|
7
40
|
* Implemented `Ruqqus::Token` class to handle OAuth2 authentication
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of
|
4
|
+
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
+
contribute through reporting issues, posting feature requests, updating
|
6
|
+
documentation, submitting pull requests or patches, and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a harassment-free
|
9
|
+
experience for everyone, regardless of level of experience, gender, gender
|
10
|
+
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
+
body size, race, ethnicity, age, religion, or nationality.
|
12
|
+
|
13
|
+
Examples of unacceptable behavior by participants include:
|
14
|
+
|
15
|
+
* The use of sexualized language or imagery
|
16
|
+
* Personal attacks
|
17
|
+
* Trolling or insulting/derogatory comments
|
18
|
+
* Public or private harassment
|
19
|
+
* Publishing other's private information, such as physical or electronic
|
20
|
+
addresses, without explicit permission
|
21
|
+
* Other unethical or unprofessional conduct
|
22
|
+
|
23
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
+
threatening, offensive, or harmful. This will always involve a public and
|
28
|
+
open discussion of the action beinng taken in full transparency.
|
29
|
+
|
30
|
+
By adopting this Code of Conduct, project maintainers commit themselves to
|
31
|
+
fairly and consistently applying these principles to every aspect of managing
|
32
|
+
this project. Project maintainers who do not follow or enforce the Code of
|
33
|
+
Conduct may be permanently removed from the project team.
|
34
|
+
|
35
|
+
This code of conduct applies both within project spaces and in public spaces
|
36
|
+
when an individual is representing the project or its community.
|
37
|
+
|
38
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
39
|
+
reported by contacting a project maintainer at efreed09@gmail.com. All
|
40
|
+
complaints will be reviewed and investigated and will result in a response that
|
41
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
42
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
43
|
+
incident.
|
44
|
+
|
45
|
+
|
46
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
47
|
+
version 1.3.0, available at
|
48
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
49
|
+
|
50
|
+
[homepage]: http://contributor-covenant.org
|
51
|
+
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# How to contribute
|
2
|
+
First of all, thank you for taking the time to contribute to this project. We've tried to make a stable project and try to fix bugs and add new features continuously. You can help us do more.
|
3
|
+
|
4
|
+
## Getting started
|
5
|
+
|
6
|
+
### Check out existing issues/pull requests
|
7
|
+
|
8
|
+
If there is a bug or a feature that is not listed in the **issues** page or there is no one assigned to the issue, feel free to fix/add it! Although it's better to discuss it in the issue or create a new issue for it so there is no confilcting code.
|
9
|
+
|
10
|
+
### Writing some code!
|
11
|
+
|
12
|
+
Contributing to a project on Github is pretty straight forward. If this is you're first time, these are the steps you should take.
|
13
|
+
|
14
|
+
- Fork this repo.
|
15
|
+
|
16
|
+
And that's it! Read the code available and change the part you don't like! You're change should not break the existing code and should pass the tests.
|
17
|
+
|
18
|
+
If you're adding a new functionality, start from the branch **master**. It would be a better practice to create a new branch and work in there.
|
19
|
+
|
20
|
+
When you're done, submit a pull request and for one of the maintainers to check it out. We would let you know if there is any problem or any changes that should be considered.
|
21
|
+
|
22
|
+
### Documentation
|
23
|
+
|
24
|
+
This project enforces 100% documentation coverage, even on non-public methods that aren't part of the API surface. We use [YARD](https://www.rubydoc.info/gems/yard/file/docs/Tags.md) as our tool of choice for documentation. It is rather intuitive, but feel free to ask if you questions if unsure or are unfamiliar with it. Pull requests will not be merged unless documented, so please don't forget to include it!
|
data/README.md
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
<p align="center">
|
2
|
-
<img src="https://raw.githubusercontent.com/
|
2
|
+
<img src="https://raw.githubusercontent.com/ForeverZer0/ruqqus/master/assets/ruqqus_text_logo.png" width="360"/>
|
3
3
|
</p>
|
4
4
|
|
5
5
|
<hr>
|
@@ -41,7 +41,7 @@ To use the `ruqqus-oauth` helper to generate user tokens for desktop development
|
|
41
41
|
|
42
42
|
Ruqqus enables 3rd-party client authorization using the [OAuth2 protocol](https://oauth.net/2/). Before it is possible
|
43
43
|
to interact with the API, you will need to first [register an application](https://ruqqus.com/settings/apps), which can
|
44
|
-
be supply you with an API key/secret pair. This key will allow you to authorize users and grant privileges with
|
44
|
+
be supply you with an API key/secret pair. This key will allow you to authorize users and grant privileges with an
|
45
45
|
assortment of scopes to fit your needs.
|
46
46
|
|
47
47
|
### Desktop Development
|
@@ -67,7 +67,11 @@ code = 'XXXXXX' # The generated code (or the one you obtained via tradi
|
|
67
67
|
|
68
68
|
# You must implement a responsible way of storing this token for reuse.
|
69
69
|
token = Ruqqus::Token.new(client_id, client_secret, code)
|
70
|
-
client = Ruqqus::Client.new(token)
|
70
|
+
client = Ruqqus::Client.new(client_id, client_secret, token)
|
71
|
+
|
72
|
+
# Alternatively, you can create a new token and a client with a single call.
|
73
|
+
# This will perform the "grant" action of the code while creating it automatically
|
74
|
+
client = Ruqqus::Client.new(client_id, client_secret, code)
|
71
75
|
```
|
72
76
|
|
73
77
|
The token will automatically refresh itself as-needed, but you will need to handle storing its new value for repeated
|
@@ -75,12 +79,16 @@ uses. To facilitate this and make it easier, there is a callback that can be sub
|
|
75
79
|
time the access key is updated.
|
76
80
|
|
77
81
|
```ruby
|
82
|
+
# Load an existing token that has already been authorized
|
78
83
|
token = Ruqqus::Token.load_json('./token.json')
|
79
|
-
|
84
|
+
|
85
|
+
# Create your client
|
86
|
+
client = Ruqqus::Client.new(client_id, client_secret, token)
|
87
|
+
|
88
|
+
# Set the callback block to automatically update the saved token when it refreshes
|
89
|
+
client.token_refreshed do |t|
|
80
90
|
t.save_json('./token.json')
|
81
91
|
end
|
82
|
-
|
83
|
-
client = Ruqqus::Client.new(token)
|
84
92
|
```
|
85
93
|
|
86
94
|
The token obtains sensitive material, and due to the security issues of storing it in plain text, this functionality is
|
@@ -89,7 +97,10 @@ and where you store this information so that it is not compromised.
|
|
89
97
|
|
90
98
|
## Usage
|
91
99
|
|
92
|
-
|
100
|
+
For in-depth documentation and instructions on how to get started, please see the following resources:
|
101
|
+
|
102
|
+
* [API Documentation](https://www.rubydoc.info/gems/ruqqus) - Complete documentation of the entire API (100% coverage)
|
103
|
+
* [Wiki](https://github.com/ForeverZer0/ruqqus/wiki) - Public wiki with more in-depth explanation, code samples, best practices, etc.
|
93
104
|
|
94
105
|
### Features
|
95
106
|
|
data/TODO.md
CHANGED
@@ -8,8 +8,6 @@ A scratch pad for things to do and ideas to look into
|
|
8
8
|
* Update README with more examples
|
9
9
|
* Create wiki on GitHub
|
10
10
|
* Finish and cleanup and `ruqqus-oauth` app
|
11
|
-
* Groups in documentation
|
12
|
-
* Front page method?
|
13
11
|
* Embed comment/posts API
|
14
12
|
|
15
13
|
# Missing API features
|
Binary file
|
Binary file
|
data/exe/ruqqus-oauth
CHANGED
@@ -41,11 +41,11 @@ class RuqqusOAuth
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def ask_client_id(prompt)
|
44
|
-
prompt.ask('Client ID: ') { |q| q.validate(/^[A-
|
44
|
+
prompt.ask('Client ID: ') { |q| q.validate(/^[A-Za-z0-9_-]+$/, "Invalid client ID") }
|
45
45
|
end
|
46
46
|
|
47
47
|
def ask_client_secret(prompt)
|
48
|
-
prompt.ask('Client Secret: ') { |q| q.validate(/^[A-
|
48
|
+
prompt.ask('Client Secret: ') { |q| q.validate(/^[A-Za-z0-9_-]+$/, "Invalid client secret") }
|
49
49
|
end
|
50
50
|
|
51
51
|
def ask_client_redirect(prompt)
|
data/lib/ruqqus.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
|
-
require '
|
1
|
+
require 'base64'
|
2
2
|
require 'json'
|
3
|
+
require 'rbconfig'
|
4
|
+
require 'rest-client'
|
5
|
+
require 'securerandom'
|
6
|
+
require 'socket'
|
3
7
|
|
4
8
|
require_relative 'ruqqus/token'
|
5
9
|
require_relative 'ruqqus/routes'
|
@@ -44,12 +48,48 @@ module Ruqqus
|
|
44
48
|
class Error < StandardError
|
45
49
|
end
|
46
50
|
|
51
|
+
##
|
52
|
+
# @!attribute self.proxy [rw]
|
53
|
+
# @return [URI?] the URI of the proxy server in use, or `nil` if none has been set.
|
54
|
+
|
55
|
+
##
|
56
|
+
# Obtains a list of URIs of free proxy servers that can be used to route network traffic through.
|
57
|
+
#
|
58
|
+
# @param anon [Symbol] anonymity filter for the servers to return, either `:transparent`, `:anonymous`, or `:elite`.
|
59
|
+
# @param country [String,Symbol] country filter for servers to return, an ISO-3166 two digit county code.
|
60
|
+
#
|
61
|
+
# @return [Array<URI>] an array of proxy URIs that match the input filters.
|
62
|
+
# @note These proxies are free, keep that in mind. They are refreshed frequently, can go down unexpectedly, be slow,
|
63
|
+
# and other manners of inconvenience that can be expected with free services.
|
64
|
+
# @see https://www.nationsonline.org/oneworld/country_code_list.htm
|
65
|
+
def self.proxy_list(anon: :elite, country: nil)
|
66
|
+
raise(ArgumentError, 'invalid anonymity value') unless %i(transparent anonymous elite).include?(anon.to_sym)
|
67
|
+
|
68
|
+
url = "https://www.proxy-list.download/api/v1/get?type=https&anon=#{anon}"
|
69
|
+
url << "&country=#{country}" if country
|
70
|
+
|
71
|
+
RestClient.get(url) do |resp|
|
72
|
+
break if resp.code != 200
|
73
|
+
return resp.body.split.map { |proxy| URI.parse("https://#{proxy}") }
|
74
|
+
end
|
75
|
+
Array.new
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.proxy
|
79
|
+
RestClient.proxy
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.proxy=(uri)
|
83
|
+
raise(TypeError, "#{uri} is not a URI") if uri && !uri.is_a?(URI)
|
84
|
+
RestClient.proxy = uri
|
85
|
+
end
|
86
|
+
|
47
87
|
##
|
48
88
|
# Helper function to automate uploading images to Imgur anonymously and returning the direct image link.
|
49
89
|
#
|
50
90
|
# @param client_id [String] an Imgur client ID
|
51
91
|
# @param image_path [String] the path to an image file.
|
52
|
-
# @
|
92
|
+
# @param opts [Hash] the options hash.
|
53
93
|
# @option opts [String] :title a title to set on the Imgur post
|
54
94
|
# @option opts [String] :description a description to set on the Imgur post
|
55
95
|
#
|
@@ -77,7 +117,14 @@ module Ruqqus
|
|
77
117
|
#
|
78
118
|
# @return [Boolean] `true` is name is available, otherwise `false` if it has been reserved or is in use.
|
79
119
|
def self.guild_available?(guild_name)
|
80
|
-
|
120
|
+
begin
|
121
|
+
response = RestClient.get("#{Routes::GUILD_AVAILABLE}#{guild_name}")
|
122
|
+
json = JSON.parse(response.body, symbolize_names: true)
|
123
|
+
return json[:available]
|
124
|
+
rescue
|
125
|
+
puts 'err'
|
126
|
+
return false
|
127
|
+
end
|
81
128
|
end
|
82
129
|
|
83
130
|
##
|
@@ -87,22 +134,145 @@ module Ruqqus
|
|
87
134
|
#
|
88
135
|
# @return [Boolean] `true` is name is available, otherwise `false` if it has been reserved or is in use.
|
89
136
|
def self.username_available?(username)
|
90
|
-
|
137
|
+
begin
|
138
|
+
response = RestClient.get("#{Routes::USERNAME_AVAILABLE}#{username}")
|
139
|
+
json = JSON.parse(response.body)
|
140
|
+
return json[username]
|
141
|
+
rescue
|
142
|
+
return false
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
##
|
147
|
+
# Generates a URL for the user to navigate to that will allow them to authorize an application.
|
148
|
+
#
|
149
|
+
# @param client_id [String] the unique ID of the approved client to authorize.
|
150
|
+
# @param redirect [String] the redirect URL where the client sends the OAuth authorization code.
|
151
|
+
# @param scopes [Array<Symbol>] a collection of values indicating the permissions the application is requesting from
|
152
|
+
# the user. See {Ruqqus::Client::SCOPES} for valid values.
|
153
|
+
# @param permanent [Boolean] `true` if authorization should persist until user explicitly revokes it,
|
154
|
+
# otherwise `false`.
|
155
|
+
# @param csrf [String] a token to authenticate and prevent a cross-site request forgery (CSRF) attack, or `nil` if
|
156
|
+
# you do not plan to validate the presence of the cookie in the redirection.
|
157
|
+
#
|
158
|
+
# @see https://ruqqus.com/settings/apps
|
159
|
+
# @see https://owasp.org/www-community/attacks/csrf
|
160
|
+
def self.authorize_url(client_id, redirect, scopes, permanent = true, csrf = nil)
|
161
|
+
|
162
|
+
raise(ArgumentError, 'invalid redirect URI') unless URI.regexp =~ redirect
|
163
|
+
raise(ArgumentError, 'scopes cannot be empty') unless scopes && !scopes.empty?
|
164
|
+
|
165
|
+
scopes = scopes.map(&:to_sym)
|
166
|
+
raise(ArgumentError, "invalid scopes specified") unless scopes.all? { |s| Client::SCOPES.include?(s) }
|
167
|
+
if scopes.any? { |s| [:create, :update, :guildmaster].include?(s) } && !scopes.include?(:identity)
|
168
|
+
# Add identity permission if missing, which is obviously required for a few other permissions
|
169
|
+
scopes << :identity
|
170
|
+
end
|
171
|
+
|
172
|
+
url = 'https://ruqqus.com/oauth/authorize'
|
173
|
+
url << "?client_id=#{client_id || raise(ArgumentError, 'client ID cannot be nil')}"
|
174
|
+
url << "&redirect_uri=#{redirect}"
|
175
|
+
url << "&scope=#{scopes.join(',')}"
|
176
|
+
url << "&state=#{csrf || Base64.encode64(SecureRandom.uuid).chomp}"
|
177
|
+
url << "&permanent=#{permanent}"
|
178
|
+
url
|
91
179
|
end
|
92
180
|
|
93
|
-
private
|
94
181
|
|
95
182
|
##
|
96
|
-
#
|
183
|
+
# Opens a URL in the system's default web browser, using the appropriate command for the host platform.
|
97
184
|
#
|
98
|
-
# @param
|
99
|
-
# @param regex [Regex] a validation regex for the name.
|
100
|
-
# @param route [String] the API endpoint to invoke.
|
185
|
+
# @param [String] the URL to open.
|
101
186
|
#
|
102
|
-
# @return [
|
103
|
-
def self.
|
104
|
-
|
105
|
-
|
106
|
-
|
187
|
+
# @return [void]
|
188
|
+
def self.open_browser(url)
|
189
|
+
|
190
|
+
cmd = case RbConfig::CONFIG['host_os']
|
191
|
+
when /mswin|mingw|cygwin/ then "start \"\"#{url}\"\""
|
192
|
+
when /darwin/ then "open '#{url}'"
|
193
|
+
when /linux|bsd/ then "xdg-open '#{url}'"
|
194
|
+
else raise(Ruqqus::Error, 'unable to determine how to open URL for current platform')
|
195
|
+
end
|
196
|
+
|
197
|
+
system(cmd)
|
198
|
+
end
|
199
|
+
|
200
|
+
##
|
201
|
+
# If using a `localhost` address for your application's OAuth redirect, this method can be used to open a socket and
|
202
|
+
# listen for a request, returning the authorization code once it arrives.
|
203
|
+
#
|
204
|
+
# @param port [Integer] the port to listen on.
|
205
|
+
# @param timeout [Numeric] sets the number of seconds to wait before cancelling and returning `nil`.
|
206
|
+
#
|
207
|
+
# @return [String?] the authorization code, `nil` if an error occurred.
|
208
|
+
# @note This method is blocking, and will *not* return until a connection is made and data is received on the
|
209
|
+
# specified port, or the timeout is reached.
|
210
|
+
def self.wait_for_code(port, timeout = 30)
|
211
|
+
|
212
|
+
thread = Thread.new do
|
213
|
+
sleep(timeout)
|
214
|
+
TCPSocket.open('localhost', port) { |s| s.puts }
|
215
|
+
end
|
216
|
+
|
217
|
+
params = {}
|
218
|
+
TCPServer.open('localhost', port) do |server|
|
219
|
+
|
220
|
+
session = server.accept
|
221
|
+
request = session.gets
|
222
|
+
match = /^GET [\/?]+(.*) HTTP.*/.match(request)
|
223
|
+
|
224
|
+
Thread.kill(thread)
|
225
|
+
return nil unless match
|
226
|
+
|
227
|
+
$1.split('&').each do |str|
|
228
|
+
key, value = str.split('=')
|
229
|
+
next unless key && value
|
230
|
+
params[key.to_sym] = value
|
231
|
+
end
|
232
|
+
|
233
|
+
session.puts "HTTP/1.1 200\r\n"
|
234
|
+
session.puts "Content-Type: text/html\r\n"
|
235
|
+
session.puts "\r\n"
|
236
|
+
session.puts create_response(!!params[:code])
|
237
|
+
|
238
|
+
session.close
|
239
|
+
end
|
240
|
+
|
241
|
+
params[:code]
|
242
|
+
end
|
243
|
+
|
244
|
+
private
|
245
|
+
|
246
|
+
##
|
247
|
+
# @return [String] a generic confirmation page to display in the user's browser after confirming application access.
|
248
|
+
def self.create_response(success)
|
249
|
+
args = success ? ['#339966', 'Authorization Confirmed'] : ['#ff0000', 'Authorization Failed']
|
250
|
+
format ='<h1 style="text-align: center;"><span style="color: %s;"><strong>%s</strong></span></h1>'
|
251
|
+
message = sprintf(format, *args)
|
252
|
+
<<-EOS
|
253
|
+
<html>
|
254
|
+
<head>
|
255
|
+
<style>
|
256
|
+
.center {
|
257
|
+
margin: 0;
|
258
|
+
position: absolute;
|
259
|
+
top: 50%;
|
260
|
+
left: 50%;
|
261
|
+
-ms-transform: translate(-50%, -50%);
|
262
|
+
transform: translate(-50%, -50%);
|
263
|
+
}
|
264
|
+
</style>
|
265
|
+
</head>
|
266
|
+
<body>
|
267
|
+
<div class="center">
|
268
|
+
<div><img src="https://raw.githubusercontent.com/ruqqus/ruqqus/master/ruqqus/assets/images/logo/ruqqus_text_logo.png" alt="" width="365" height="92" /></div>
|
269
|
+
<p style="text-align: center;"> </p>
|
270
|
+
#{message}
|
271
|
+
<p style="text-align: center;"> </p>
|
272
|
+
<p style="text-align: center;"><span style="color: #808080;">You can safely close the tab/browser and return to the application.</span></p>
|
273
|
+
</div>
|
274
|
+
</body>
|
275
|
+
</html>
|
276
|
+
EOS
|
107
277
|
end
|
108
278
|
end
|