furaffinity 0.1.0 → 0.2.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +4 -0
- data/lib/furaffinity/cli.rb +58 -2
- data/lib/furaffinity/cli_utils.rb +27 -0
- data/lib/furaffinity/client.rb +99 -12
- data/lib/furaffinity/queue.rb +51 -19
- data/lib/furaffinity/queue_hook.rb +65 -0
- data/lib/furaffinity/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 486881425319cc8b49b196f58f5e4784462d39baa62aa27e985c91a0606c0f21
|
4
|
+
data.tar.gz: 81eef14d9b5b32e2874ae3d1e83e6811086cdc902b47b3e861f0e70d0a1f6810
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1d4ea145d6886a771017f00189153022947575f5184d8328ec0252748b29d17802188ad307dc9abee02806ff7af2d4bc5552cfa94f5d9e6119ca87369d7c59d6
|
7
|
+
data.tar.gz: 8e91c5403692b846cf7078735af81a67f4e462d8e04e99d51d4268fa13d7778e70ecb22c2ef2690690bfc1f25c8186d27903d179ab48c29e652a60f88855caa8
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.2.0] - 2023-12-21
|
4
|
+
|
5
|
+
## Added
|
6
|
+
- `fa edit` command to edit submissions
|
7
|
+
- `after_upload` hook to queues
|
8
|
+
|
9
|
+
## Changed
|
10
|
+
- `folder_name` is now called `create_folder_name` as it should
|
11
|
+
|
3
12
|
## [0.1.0] - 2023-11-04
|
4
13
|
|
5
14
|
- Initial release
|
data/README.md
CHANGED
@@ -30,6 +30,10 @@ fa notifications
|
|
30
30
|
|
31
31
|
# upload a new submission
|
32
32
|
fa upload my_image.png --title "test post please ignore" --description "This is an image as you can see" --rating general --scrap
|
33
|
+
|
34
|
+
# interactively update a submission, this needs your preferred editor in ENV
|
35
|
+
export EDITOR=vi
|
36
|
+
fa edit 54328944
|
33
37
|
```
|
34
38
|
|
35
39
|
There is also a way to upload submissions in bulk: `fa queue`
|
data/lib/furaffinity/cli.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "json"
|
4
|
+
require "tempfile"
|
4
5
|
require "thor"
|
6
|
+
require "yaml"
|
5
7
|
|
6
8
|
module Furaffinity
|
7
9
|
class Cli < Thor
|
@@ -63,9 +65,9 @@ module Furaffinity
|
|
63
65
|
type: :string,
|
64
66
|
desc: "Keywords, separated by spaces.",
|
65
67
|
default: ""
|
66
|
-
option :
|
68
|
+
option :create_folder_name,
|
67
69
|
type: :string,
|
68
|
-
desc: "
|
70
|
+
desc: "Create a new folder and place this submission into it.",
|
69
71
|
default: ""
|
70
72
|
def upload(file_path)
|
71
73
|
set_log_level(options)
|
@@ -83,6 +85,55 @@ module Furaffinity
|
|
83
85
|
say "Submission uploaded! #{url}", :green
|
84
86
|
end
|
85
87
|
|
88
|
+
EDIT_TEMPLATE = <<~YAML
|
89
|
+
---
|
90
|
+
# Submission info for %<id>s
|
91
|
+
|
92
|
+
# Required field:
|
93
|
+
title: %<title>s
|
94
|
+
|
95
|
+
# Required field
|
96
|
+
description: |-
|
97
|
+
%<description>s
|
98
|
+
|
99
|
+
# Optional field, keywords separated by spaces:
|
100
|
+
keywords: %<keywords>s
|
101
|
+
|
102
|
+
# Required field, one of: [#{Furaffinity::Client::RATING_MAP.keys.join(", ")}]
|
103
|
+
rating: %<rating>s
|
104
|
+
|
105
|
+
scrap: %<scrap>s
|
106
|
+
lock_comments: %<lock_comments>s
|
107
|
+
|
108
|
+
# vim: syntax=yaml
|
109
|
+
YAML
|
110
|
+
|
111
|
+
desc "edit ID", "Edit submission info"
|
112
|
+
def edit_interactive(id)
|
113
|
+
set_log_level(options)
|
114
|
+
config = config_for(options)
|
115
|
+
client = config.new_client
|
116
|
+
|
117
|
+
submission_info = client.submission_info(id)
|
118
|
+
# write template
|
119
|
+
file = Tempfile.new("facli_edit_#{id}")
|
120
|
+
file.puts format(EDIT_TEMPLATE,
|
121
|
+
id:,
|
122
|
+
**submission_info.slice(:title, :keywords, :scrap, :lock_comments).transform_values(&:inspect),
|
123
|
+
description: submission_info.fetch(:message).gsub(/^/, " "),
|
124
|
+
rating: submission_info.fetch(:rating),
|
125
|
+
)
|
126
|
+
file.close
|
127
|
+
CliUtils.open_editor file.path, fatal: true
|
128
|
+
params = YAML.safe_load_file(file.path, permitted_classes: [Symbol]).transform_keys(&:to_sym)
|
129
|
+
|
130
|
+
url = client.update(id:, **params)
|
131
|
+
say "Submission updated! #{url}", :green
|
132
|
+
ensure
|
133
|
+
file.close
|
134
|
+
file.unlink
|
135
|
+
end
|
136
|
+
|
86
137
|
desc "queue SUBCOMMAND ...ARGS", "Manage an upload queue"
|
87
138
|
long_desc <<~LONG_DESC, wrap: false
|
88
139
|
`#{basename} queue` manages an upload queue.
|
@@ -122,5 +173,10 @@ module Furaffinity
|
|
122
173
|
#{basename} queue clean
|
123
174
|
LONG_DESC
|
124
175
|
subcommand "queue", CliQueue
|
176
|
+
|
177
|
+
map %w[--version -v] => :__print_version
|
178
|
+
|
179
|
+
desc "--version, -v", "Print the version"
|
180
|
+
def __print_version = puts "furaffinity-cli/#{VERSION}"
|
125
181
|
end
|
126
182
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "shellwords"
|
4
|
+
|
5
|
+
module Furaffinity
|
6
|
+
module CliUtils
|
7
|
+
module_function
|
8
|
+
|
9
|
+
include SemanticLogger::Loggable
|
10
|
+
|
11
|
+
def open_editor(file, fatal: false)
|
12
|
+
editor = ENV["FA_EDITOR"] || ENV["VISUAL"] || ENV["EDITOR"]
|
13
|
+
unless editor
|
14
|
+
logger.warn "could not open editor for #{file.inspect}, set one of FA_EDITOR, VISUAL, or EDITOR in your ENV"
|
15
|
+
raise "No suitable editor found to edit #{file.inspect}, set one of FA_EDITOR, VISUAL, or EDITOR in your ENV" if fatal
|
16
|
+
|
17
|
+
return
|
18
|
+
end
|
19
|
+
|
20
|
+
system(*Shellwords.shellwords(editor), file).tap do
|
21
|
+
next if $?.exitstatus == 0
|
22
|
+
|
23
|
+
logger.error "could not run #{editor} #{file}, exit code: #{$?.exitstatus}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/furaffinity/client.rb
CHANGED
@@ -73,23 +73,18 @@ module Furaffinity
|
|
73
73
|
adult: 1,
|
74
74
|
}.freeze
|
75
75
|
|
76
|
-
def fake_upload(file, title:, rating:, description:, keywords:,
|
77
|
-
type
|
78
|
-
|
79
|
-
rating = rating.to_sym
|
80
|
-
raise ArgumentError.new("#{rating.inspect} is not in #{RATING_MAP.keys.inspect}") unless RATING_MAP.include?(rating)
|
76
|
+
def fake_upload(file, title:, rating:, description:, keywords:, create_folder_name: "", lock_comments: false, scrap: false, type: :submission)
|
77
|
+
validate_args!(type:, rating:) => { type:, rating: }
|
78
|
+
|
81
79
|
raise "not a file" unless file.is_a?(File)
|
82
80
|
params = { MAX_FILE_SIZE: "10485760" }
|
83
81
|
raise ArgumentError.new("file size of #{file.size} is greater than FA limit of #{params[:MAX_FILE_SIZE]}") if file.size > params[:MAX_FILE_SIZE].to_i
|
84
|
-
"https
|
82
|
+
"https://www.furaffinity.net/view/54328944/?upload-successful"
|
85
83
|
end
|
86
84
|
|
87
85
|
# @param file [File]
|
88
|
-
def upload(file, title:, rating:, description:, keywords:,
|
89
|
-
type
|
90
|
-
raise ArgumentError.new("#{type.inspect} is not in #{SUBMISSION_TYPES.inspect}") unless SUBMISSION_TYPES.include?(type)
|
91
|
-
rating = rating.to_sym
|
92
|
-
raise ArgumentError.new("#{rating.inspect} is not in #{RATING_MAP.keys.inspect}") unless RATING_MAP.include?(rating)
|
86
|
+
def upload(file, title:, rating:, description:, keywords:, create_folder_name: "", lock_comments: false, scrap: false, type: :submission)
|
87
|
+
validate_args!(type:, rating:) => { type:, rating: }
|
93
88
|
|
94
89
|
client = http_client
|
95
90
|
|
@@ -143,7 +138,7 @@ module Furaffinity
|
|
143
138
|
message: description,
|
144
139
|
keywords: keywords,
|
145
140
|
|
146
|
-
create_folder_name
|
141
|
+
create_folder_name:,
|
147
142
|
|
148
143
|
# finalize button :)
|
149
144
|
finalize: "Finalize ",
|
@@ -164,8 +159,100 @@ module Furaffinity
|
|
164
159
|
end
|
165
160
|
end
|
166
161
|
|
162
|
+
# Returns submission information from your own gallery.
|
163
|
+
def submission_info(id)
|
164
|
+
client = http_client
|
165
|
+
|
166
|
+
logger.trace { "Retrieving submission information for #{id}" }
|
167
|
+
response = get("/controls/submissions/changeinfo/#{id}/", client:).then(&method(:parse_response))
|
168
|
+
|
169
|
+
{}.tap do |h|
|
170
|
+
h[:title] = response.css("form[name=MsgForm] input[name=title]").first.attr(:value)
|
171
|
+
|
172
|
+
%i[message keywords].each do |field|
|
173
|
+
h[field] = response.css("form[name=MsgForm] textarea[name=#{field}]").first.text
|
174
|
+
end
|
175
|
+
|
176
|
+
h[:rating] = RATING_MAP.invert.fetch(response.css("form[name=MsgForm] input[name=rating][checked]").first.attr(:value).to_i)
|
177
|
+
|
178
|
+
%i[lock_comments scrap].each do |field|
|
179
|
+
h[field] = !!response.css("form[name=MsgForm] input[name=#{field}][checked]").first&.attr(:value)
|
180
|
+
end
|
181
|
+
|
182
|
+
%i[cat atype species gender].each do |field|
|
183
|
+
h[field] = response.css("form[name=MsgForm] select[name=#{field}] option[selected]").first.attr(:value)
|
184
|
+
end
|
185
|
+
|
186
|
+
h[:folder_ids] = response.css("form[name=MsgForm] input[name=\"folder_ids[]\"][checked]").map { _1.attr(:value) }
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def fake_update(id:, title:, rating:, description:, keywords:, lock_comments: false, scrap: false)
|
191
|
+
validate_args!(rating:) => { rating: }
|
192
|
+
|
193
|
+
"https://www.furaffinity.net/view/54328944/"
|
194
|
+
end
|
195
|
+
|
196
|
+
# NOTE: only tested with `type=submission`
|
197
|
+
def update(id:, title:, rating:, description:, keywords:, lock_comments: false, scrap: false)
|
198
|
+
validate_args!(rating:) => { rating: }
|
199
|
+
|
200
|
+
client = http_client
|
201
|
+
|
202
|
+
# step 1: get the required keys
|
203
|
+
logger.trace { "Extracting keys from submission #{id}" }
|
204
|
+
response = get("/controls/submissions/changeinfo/#{id}/", client:).then(&method(:parse_response))
|
205
|
+
already_set_params = {
|
206
|
+
key: response.css("form[name=MsgForm] input[name=key]").first.attr(:value),
|
207
|
+
folder_ids: response.css("form[name=MsgForm] input[name=\"folder_ids[]\"][checked]").map { _1.attr(:value) },
|
208
|
+
}.tap do |h|
|
209
|
+
%i[cat atype species gender].each do |field|
|
210
|
+
h[field] = response.css("form[name=MsgForm] select[name=#{field}] option[selected]").first.attr(:value)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
params = {
|
215
|
+
update: "yes",
|
216
|
+
|
217
|
+
rating: RATING_MAP.fetch(rating),
|
218
|
+
title: title,
|
219
|
+
message: description,
|
220
|
+
keywords: keywords,
|
221
|
+
|
222
|
+
**already_set_params,
|
223
|
+
|
224
|
+
# update button ;-)
|
225
|
+
submit: "Update",
|
226
|
+
}
|
227
|
+
params[:lock_comments] = "1" if lock_comments
|
228
|
+
params[:scrap] = "1" if scrap
|
229
|
+
|
230
|
+
logger.debug { "Updating submission #{id}..." }
|
231
|
+
update_response = post("/controls/submissions/changeinfo/#{id}/", form: params, client:)
|
232
|
+
if update_response.status == 302
|
233
|
+
redirect_location = update_response.headers[:location]
|
234
|
+
url = File.join(BASE_URL, redirect_location)
|
235
|
+
logger.info "Updated! #{url}"
|
236
|
+
return url
|
237
|
+
else
|
238
|
+
fa_error = parse_response(update_response).css(".redirect-message").text
|
239
|
+
raise Error.new("FA returned: #{fa_error}")
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
167
243
|
private
|
168
244
|
|
245
|
+
def validate_args!(type: nil, rating:)
|
246
|
+
if type
|
247
|
+
type = type.to_sym
|
248
|
+
raise ArgumentError.new("#{type.inspect} is not in #{SUBMISSION_TYPES.inspect}") unless SUBMISSION_TYPES.include?(type)
|
249
|
+
end
|
250
|
+
rating = rating.to_sym
|
251
|
+
raise ArgumentError.new("#{rating.inspect} is not in #{RATING_MAP.keys.inspect}") unless RATING_MAP.include?(rating)
|
252
|
+
|
253
|
+
{ type:, rating: }
|
254
|
+
end
|
255
|
+
|
169
256
|
def parse_response(httpx_response)
|
170
257
|
logger.measure_trace "Parsing response" do
|
171
258
|
Nokogiri::HTML.parse(httpx_response)
|
data/lib/furaffinity/queue.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "fileutils"
|
4
|
-
require "shellwords"
|
5
4
|
require "yaml"
|
6
5
|
|
7
6
|
module Furaffinity
|
@@ -35,8 +34,46 @@ module Furaffinity
|
|
35
34
|
scrap: false
|
36
35
|
lock_comments: false
|
37
36
|
|
38
|
-
#
|
39
|
-
|
37
|
+
# Create a new folder to place this submission under, leave blank if none should be created.
|
38
|
+
create_folder_name: ""
|
39
|
+
|
40
|
+
# Run this Ruby code after uploading
|
41
|
+
after_upload: |-
|
42
|
+
# Quick reference
|
43
|
+
#
|
44
|
+
# Available objects:
|
45
|
+
# - `client` (Furaffinity::Client)
|
46
|
+
# The client object used to interact with FurAffinity.
|
47
|
+
# - `submission_info` (Hash)
|
48
|
+
# The current submission information of this YAML file. Keys are symbols.
|
49
|
+
# To get the description use e.g. `submission_info[:description]`.
|
50
|
+
# This also contains the ID of the uploaded submission, e.g.
|
51
|
+
# `submission_info[:id]`.
|
52
|
+
# - `file_info` (Hash)
|
53
|
+
# A hash of all YAML files. Format is
|
54
|
+
# `{ "filename.png" => { submission_info } }`.
|
55
|
+
# Like `submission_info` it also contains the submission's ID as the `:id`
|
56
|
+
# field if it's been uploaded.
|
57
|
+
#
|
58
|
+
# Helper functions:
|
59
|
+
# - `submission_url(submission_id)`
|
60
|
+
# Generates a submission URL, e.g.
|
61
|
+
# "https://www.furaffinity.net/view/54328944/"
|
62
|
+
# - `link_to(url_or_submission, text)`
|
63
|
+
# Generates a link. If the first parameter is a submission info hash it will
|
64
|
+
# generate the URL using `submission_url(submission_info[:id])`.
|
65
|
+
|
66
|
+
# Remove this `return` if you want to run Ruby code
|
67
|
+
return
|
68
|
+
|
69
|
+
# Append a link to this submission to a previously uploaded one
|
70
|
+
previous_submission = file_info.fetch("previous_file.png")
|
71
|
+
previous_submission[:description] += ("\n\n" + link_to(submission_info, "Alt version 2"))
|
72
|
+
client.update(**previous_submission)
|
73
|
+
|
74
|
+
# Append a link to the previous submission to the current one
|
75
|
+
submission_info[:description] += ("\n\n" + link_to(previous_submission, "Alt version 1"))
|
76
|
+
client.update(**submission_info)
|
40
77
|
YAML
|
41
78
|
|
42
79
|
attr_reader :client, :queue_dir, :queue, :upload_status, :file_info
|
@@ -109,7 +146,7 @@ module Furaffinity
|
|
109
146
|
end
|
110
147
|
|
111
148
|
submission_info_path = create_submission_info(file)
|
112
|
-
open_editor submission_info_path
|
149
|
+
CliUtils.open_editor submission_info_path
|
113
150
|
|
114
151
|
queue << file
|
115
152
|
upload_status[file] = {
|
@@ -151,12 +188,14 @@ module Furaffinity
|
|
151
188
|
end
|
152
189
|
|
153
190
|
def reorder
|
154
|
-
open_editor fa_info_path("queue.yml")
|
191
|
+
CliUtils.open_editor fa_info_path("queue.yml")
|
155
192
|
end
|
156
193
|
|
157
194
|
def upload(wait_time = 60)
|
158
195
|
raise ArgumentError.new("wait_time must be at least 30") if wait_time < 30
|
159
196
|
|
197
|
+
hook_handler = QueueHook.new(client, file_info)
|
198
|
+
|
160
199
|
while file_name = queue.shift
|
161
200
|
info = file_info[file_name]
|
162
201
|
unless info
|
@@ -164,6 +203,8 @@ module Furaffinity
|
|
164
203
|
next
|
165
204
|
end
|
166
205
|
|
206
|
+
code = file_info[file_name].delete(:after_upload)
|
207
|
+
|
167
208
|
logger.info "Uploading #{info[:title].inspect} (#{file_name.inspect})"
|
168
209
|
url = client.upload(
|
169
210
|
File.new(file_name),
|
@@ -175,6 +216,11 @@ module Furaffinity
|
|
175
216
|
|
176
217
|
save
|
177
218
|
|
219
|
+
if code
|
220
|
+
hook_handler.update_ids(upload_status)
|
221
|
+
hook_handler.run_hook(file_name, code)
|
222
|
+
end
|
223
|
+
|
178
224
|
unless queue.empty?
|
179
225
|
logger.info "Waiting #{wait_time} seconds until the next upload"
|
180
226
|
sleep wait_time
|
@@ -210,19 +256,5 @@ module Furaffinity
|
|
210
256
|
|
211
257
|
submission_info_path
|
212
258
|
end
|
213
|
-
|
214
|
-
def open_editor(file)
|
215
|
-
editor = ENV["FA_EDITOR"] || ENV["VISUAL"] || ENV["EDITOR"]
|
216
|
-
unless editor
|
217
|
-
logger.warn "could not open editor for #{file.inspect}, set one of FA_EDITOR, VISUAL, or EDITOR in your ENV"
|
218
|
-
return
|
219
|
-
end
|
220
|
-
|
221
|
-
system(*Shellwords.shellwords(editor), file).tap do
|
222
|
-
next if $?.exitstatus == 0
|
223
|
-
|
224
|
-
logger.error "could not run #{editor} #{file}, exit code: #{$?.exitstatus}"
|
225
|
-
end
|
226
|
-
end
|
227
259
|
end
|
228
260
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Furaffinity
|
4
|
+
class QueueHook
|
5
|
+
include SemanticLogger::Loggable
|
6
|
+
|
7
|
+
class HookRunner
|
8
|
+
include SemanticLogger::Loggable
|
9
|
+
|
10
|
+
attr_reader :client, :file_info, :submission_info
|
11
|
+
|
12
|
+
def initialize(client, file_info, file_name)
|
13
|
+
@client = client
|
14
|
+
@file_info = file_info
|
15
|
+
@submission_info = file_info.fetch(file_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def submission_url(submission_id) = "https://www.furaffinity.net/view/#{submission_id}/"
|
19
|
+
|
20
|
+
def link_to(url_or_submission, text)
|
21
|
+
url = case url_or_submission
|
22
|
+
in { id: }
|
23
|
+
submission_url(id)
|
24
|
+
else
|
25
|
+
if url_or_submission.is_a?(Hash)
|
26
|
+
logger.warn { "passed hash does not have an ID, probably not uploaded yet? hash keys: #{url_or_submission.keys.inspect}" }
|
27
|
+
end
|
28
|
+
url_or_submission.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
"[url=#{url}]#{text}[/url]"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_reader :client, :file_info
|
36
|
+
|
37
|
+
def initialize(client, file_info)
|
38
|
+
@client = client
|
39
|
+
@file_info = file_info.each_with_object({}) do |(file_name, info), h|
|
40
|
+
# Hash#except duplicates the hash, which is good here as we don't want
|
41
|
+
# to modify the queue.
|
42
|
+
# exclude after_upload as it's not needed, and create_folder_name and
|
43
|
+
# type is only relevant when initially uploading the submission.
|
44
|
+
h[file_name] = info.except(:create_folder_name, :after_upload, :type)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def update_ids(upload_status)
|
49
|
+
logger.trace { "Updating file info ids" }
|
50
|
+
upload_status.each do |file_name, status|
|
51
|
+
next unless status[:uploaded]
|
52
|
+
|
53
|
+
@file_info[file_name][:id] = status[:url].match(%{/view/(?<id>[^/]+)})[:id]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def run_hook(file_name, code)
|
58
|
+
logger.debug { "Running hook" }
|
59
|
+
logger.trace { "Hook code:\n#{code}" }
|
60
|
+
HookRunner
|
61
|
+
.new(client, file_info, file_name)
|
62
|
+
.instance_eval(code, File.join(Dir.pwd, "#{file_name}.info.yml"), 0)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/furaffinity/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: furaffinity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Georg Gadinger
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httpx
|
@@ -113,9 +113,11 @@ files:
|
|
113
113
|
- lib/furaffinity/cli.rb
|
114
114
|
- lib/furaffinity/cli_base.rb
|
115
115
|
- lib/furaffinity/cli_queue.rb
|
116
|
+
- lib/furaffinity/cli_utils.rb
|
116
117
|
- lib/furaffinity/client.rb
|
117
118
|
- lib/furaffinity/config.rb
|
118
119
|
- lib/furaffinity/queue.rb
|
120
|
+
- lib/furaffinity/queue_hook.rb
|
119
121
|
- lib/furaffinity/version.rb
|
120
122
|
homepage: https://github.com/nilsding/furaffinity-cli
|
121
123
|
licenses:
|