shep 0.1.0.pre.alpha0

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.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/Copyright.txt +8 -0
  3. data/LICENSE.txt +697 -0
  4. data/README.md +101 -0
  5. data/Rakefile +52 -0
  6. data/doc/Shep/Entity/Account.html +193 -0
  7. data/doc/Shep/Entity/Context.html +165 -0
  8. data/doc/Shep/Entity/CustomEmoji.html +171 -0
  9. data/doc/Shep/Entity/MediaAttachment.html +175 -0
  10. data/doc/Shep/Entity/Notification.html +171 -0
  11. data/doc/Shep/Entity/Status.html +217 -0
  12. data/doc/Shep/Entity/StatusSource.html +167 -0
  13. data/doc/Shep/Entity/Status_Application.html +167 -0
  14. data/doc/Shep/Entity/Status_Mention.html +169 -0
  15. data/doc/Shep/Entity/Status_Tag.html +165 -0
  16. data/doc/Shep/Entity.html +1457 -0
  17. data/doc/Shep/Error/Caller.html +147 -0
  18. data/doc/Shep/Error/Http.html +329 -0
  19. data/doc/Shep/Error/Remote.html +143 -0
  20. data/doc/Shep/Error/Server.html +147 -0
  21. data/doc/Shep/Error/Type.html +233 -0
  22. data/doc/Shep/Error.html +149 -0
  23. data/doc/Shep/Session.html +4094 -0
  24. data/doc/Shep.html +128 -0
  25. data/doc/_index.html +300 -0
  26. data/doc/class_list.html +51 -0
  27. data/doc/css/common.css +1 -0
  28. data/doc/css/full_list.css +58 -0
  29. data/doc/css/style.css +497 -0
  30. data/doc/file.README.html +159 -0
  31. data/doc/file_list.html +56 -0
  32. data/doc/frames.html +17 -0
  33. data/doc/index.html +300 -0
  34. data/doc/js/app.js +314 -0
  35. data/doc/js/full_list.js +216 -0
  36. data/doc/js/jquery.js +4 -0
  37. data/doc/method_list.html +387 -0
  38. data/doc/top-level-namespace.html +110 -0
  39. data/lib/shep/entities.rb +164 -0
  40. data/lib/shep/entity_base.rb +378 -0
  41. data/lib/shep/exceptions.rb +78 -0
  42. data/lib/shep/session.rb +970 -0
  43. data/lib/shep/typeboxes.rb +180 -0
  44. data/lib/shep.rb +22 -0
  45. data/run_rake_test.example.sh +46 -0
  46. data/shep.gemspec +28 -0
  47. data/spec/data/smallimg.jpg +0 -0
  48. data/spec/data/smallish.jpg +0 -0
  49. data/spec/entity_common.rb +120 -0
  50. data/spec/entity_t1_spec.rb +168 -0
  51. data/spec/entity_t2_spec.rb +123 -0
  52. data/spec/entity_t3_spec.rb +30 -0
  53. data/spec/json_objects/account.1.json +25 -0
  54. data/spec/json_objects/account.2.json +36 -0
  55. data/spec/json_objects/status.1.json +85 -0
  56. data/spec/json_objects/status.2.json +59 -0
  57. data/spec/json_objects/status.3.json +95 -0
  58. data/spec/json_objects/status.4.json +95 -0
  59. data/spec/json_objects/status.5.json +74 -0
  60. data/spec/json_objects/status.6.json +140 -0
  61. data/spec/json_objects/status.7.json +84 -0
  62. data/spec/session_reader_1_unauth_spec.rb +366 -0
  63. data/spec/session_reader_2_auth_spec.rb +96 -0
  64. data/spec/session_writer_spec.rb +183 -0
  65. data/spec/spec_helper.rb +73 -0
  66. data/yard_helper.rb +30 -0
  67. metadata +154 -0
@@ -0,0 +1,183 @@
1
+
2
+ require 'fileutils'
3
+
4
+ require_relative 'spec_helper'
5
+ require_relative '../lib/shep'
6
+
7
+ include Shep
8
+
9
+ POST_UUID = "fc49e486-d445-4ca7-9d6d-a27c89c5c471" #SecureRandom.uuid
10
+
11
+ describe Session, :account_limited do
12
+ include_context :uses_temp_dir
13
+
14
+ before(:all) {
15
+ @new_posts = []
16
+ }
17
+
18
+ it "posts statuses" do
19
+ testpost = "Test post #{POST_UUID} "
20
+
21
+ ss = Session.new(host: HOST, token: TOKEN)
22
+
23
+ visibilities = %w{public unlisted private direct}
24
+ for vis in visibilities
25
+ post = ss.post_status(testpost + Time.now.to_s,
26
+ visibility: vis,
27
+ language: "en")
28
+ @new_posts.push post
29
+
30
+ expect( visibilities.index(post.visibility) )
31
+ .to be >= visibilities.index(vis)
32
+
33
+ retrieved_post = ss.fetch_status(post.id)
34
+ expect( retrieved_post ) .to eq post
35
+ end
36
+
37
+ spoiler_text = "is this a test post?"
38
+ post = ss.post_status(testpost + Time.now.to_s,
39
+ spoiler_text: spoiler_text)
40
+ @new_posts.push post
41
+ expect( post.spoiler_text ) .to eq spoiler_text
42
+ expect( post.sensitive ) .to be true
43
+
44
+ retrieved_post = ss.fetch_status(post.id)
45
+ expect( retrieved_post ) .to eq post
46
+ end
47
+
48
+ it "posts status with media" do
49
+ ss = Session.new(host: HOST, token: TOKEN)
50
+
51
+ file1 = File.join(File.dirname(__FILE__), "data", "smallimg.jpg")
52
+ file2 = File.join(File.dirname(__FILE__), "data", "smallish.jpg")
53
+
54
+ img1 = ss.upload_media(file1, content_type: 'image/jpeg')
55
+ expect( img1.type ) .to eq 'image'
56
+
57
+ desc = "IMAGE_TEXT!!!!"
58
+ img2 = ss.upload_media(file2,
59
+ description: desc,
60
+ focus_x: 0.0,
61
+ focus_y: 0.7)
62
+ expect( img2.type ) .to eq 'image'
63
+ expect( img2.description ) .to eq desc
64
+
65
+ msg = "Upload unit test post; #{Time.now.iso8601}; #{POST_UUID}"
66
+ post = ss.post_status(msg, media_ids: [img1.id, img2.id])
67
+ @new_posts.push(post) # so it gets deleted later
68
+
69
+ post2, files = ss.fetch_status_with_media(post.id, tmp_dir())
70
+ expect( post2.media_attachments[0].id ) .to eq img1.id
71
+ expect( post2.media_attachments[1].id ) .to eq img2.id
72
+
73
+ # It turns out that Mastodon modifies the image files so that what
74
+ # we get back isn't bit-identical to what we uploaded. Since
75
+ # there's no bulletproof way to extract stuff like extent from the
76
+ # image, we settle for just confirming that we get the correct
77
+ # number of onon-empty files.
78
+ expect( files.size ) .to eq 2
79
+ for path in files.values
80
+ expect( File.stat(path).size ) .to be > 1000
81
+ end
82
+ end
83
+
84
+ it "edits statuses" do
85
+ ss = Session.new(host: HOST, token: TOKEN)
86
+
87
+ base_text = "edited msg #{POST_UUID}\n#{Time.now}\n-"
88
+ post = ss.post_status(base_text, language: "en")
89
+ @new_posts.push(post) # delete it during the deletion test
90
+
91
+ expect( ss.fetch_status(post.id) ) .to eq post
92
+ expect( post.content ) .to include POST_UUID
93
+ expect( post.sensitive ) .to be false
94
+ expect( post.spoiler_text ) .to eq ""
95
+ expect( post.language ) .to eq "en"
96
+
97
+ src = ss.fetch_status_src(post.id)
98
+ expect(src.text) .to eq base_text
99
+
100
+ # Edit to update the text.
101
+ new_text = base_text + "!!!!"
102
+ post2 = ss.edit_status(post.id, new_text)
103
+ expect( ss.fetch_status(post.id) ) .to eq post2
104
+
105
+ expect( post2.content ) .to include '!!!'
106
+ expect( post2.sensitive ) .to be false
107
+ expect( post2.spoiler_text ) .to eq ""
108
+ expect( post2.language ) .to eq "en"
109
+
110
+ # Edit to change language, spoiler and sensitive
111
+ post2 = ss.edit_status(post.id, new_text,
112
+ spoiler_text: "spoiler",
113
+ language: "fr")
114
+ expect( ss.fetch_status(post.id) ) .to eq post2
115
+
116
+ expect( post2.content ) .to include '!!!'
117
+ expect( post2.sensitive ) .to be true
118
+ expect( post2.spoiler_text ) .to eq "spoiler"
119
+ expect( post2.language ) .to eq "fr"
120
+
121
+ # Edit to revert sensitive and language
122
+ post2 = ss.edit_status(post.id, new_text)
123
+ expect( ss.fetch_status(post.id) ) .to eq post2
124
+
125
+ expect( post2.content ) .to include '!!!'
126
+ expect( post2.sensitive ) .to be false
127
+ expect( post2.spoiler_text ) .to eq ""
128
+ expect( post2.language ) .to eq "en"
129
+
130
+ # Edit to add a media attachment
131
+ file1 = File.join(File.dirname(__FILE__), "data", "smallimg.jpg")
132
+ img1 = ss.upload_media(file1, content_type: 'image/jpeg')
133
+
134
+ new_text2 = new_text + "\n!PIX!\n"
135
+ post2 = ss.edit_status(post.id, new_text2,
136
+ spoiler_text: "pix",
137
+ media_ids: [img1.id],
138
+ )
139
+ expect( ss.fetch_status(post.id) ) .to eq post2
140
+
141
+ expect( post2.content ) .to include '!PIX!'
142
+ expect( post2.sensitive ) .to be true
143
+ expect( post2.spoiler_text ) .to eq "pix"
144
+ expect( post2.language ) .to eq "en"
145
+ expect( post2.media_attachments.map{|ma| ma.id} )
146
+ .to eq [img1.id]
147
+
148
+ # Edit to remove the media attachment
149
+ post2 = ss.edit_status(post.id, new_text2,
150
+ spoiler_text: "pix",
151
+ media_ids: [],
152
+ )
153
+ expect( ss.fetch_status(post.id) ) .to eq post2
154
+
155
+ expect( post2.content ) .to include '!PIX!'
156
+ expect( post2.sensitive ) .to be true
157
+ expect( post2.spoiler_text ) .to eq "pix"
158
+ expect( post2.language ) .to eq "en"
159
+ expect( post2.media_attachments ) .to eq []
160
+ end
161
+
162
+ it "deletes statuses" do
163
+ ss = Session.new(host: HOST, token: TOKEN)
164
+
165
+ # Test for the test itself
166
+ expect( @new_posts.size ) .to be > 0
167
+
168
+ # Fun fact: a Mastodon instance limits deletions to 30/hour, so
169
+ # running this test a few times will completely eat through that.
170
+ @new_posts.each do |status|
171
+ del_post = ss.delete_status(status.id)
172
+ expect( del_post.id ) .to eq status.id
173
+ expect( del_post.text.include? POST_UUID ) .to be true
174
+ end
175
+
176
+ @new_posts = []
177
+ end
178
+
179
+
180
+ # skip "" do ; end
181
+ # skip "" do ; end
182
+
183
+ end
@@ -0,0 +1,73 @@
1
+
2
+ $: << 'lib'
3
+
4
+ require 'tmpdir'
5
+
6
+ # The Mastodon instance to use for online testing
7
+ HOST = ENV['SHEP_TEST_HOST']
8
+
9
+ # Public account on HOST to use for unauthenticated feature testing
10
+ READ_ACCOUNT_HANDLE = ENV['SHEP_READ_ACCOUNT_HANDLE']
11
+ READ_ACCOUNT = ENV['SHEP_READ_ACCOUNT']
12
+
13
+ # Account details on HOST to use for authenticated/write feature
14
+ # testing
15
+ TOKEN = ENV['SHEP_TOKEN']
16
+ WRITE_ACCOUNT = ENV['SHEP_ACCOUNT']
17
+
18
+ # If set and everything else is in order, we also run the rate-limited
19
+ # tests.
20
+ ALL_TESTS_REQUESTED = !!ENV['SHEP_TEST_ALL']
21
+
22
+
23
+ # Tags:
24
+ #
25
+ # offline - runs without a Mastodon server
26
+ # anonymous - requires a server but no login
27
+ # account - requires normal server account (which it *may* modify!)
28
+ # account_limited - like 'account' but will also perform heavily
29
+ # rate-limited actions (e.g. delete, upload media)
30
+
31
+
32
+ RSpec.configure {|conf|
33
+ if conf.inclusion_filter.empty?
34
+ allow_anonymous = HOST && READ_ACCOUNT && READ_ACCOUNT_HANDLE
35
+ allow_account = allow_anonymous && TOKEN && WRITE_ACCOUNT
36
+ allow_limited = allow_account && ALL_TESTS_REQUESTED
37
+
38
+ if ALL_TESTS_REQUESTED && !allow_limited
39
+ puts "Requested all tests but some parameters are missing."
40
+ # I suppose I should say which...
41
+ exit 1
42
+ end
43
+
44
+ puts "Test groups chosen:"
45
+ if allow_limited
46
+ puts " * all tests"
47
+ else
48
+ puts " * offline tests"
49
+ puts " * anonymous online tests" if allow_anonymous
50
+ puts " * authenticated online test" if allow_account
51
+ end
52
+ puts
53
+
54
+ conf.filter_run_including(:offline)
55
+ conf.filter_run_including(:anonymous) if allow_anonymous
56
+ conf.filter_run_including(:account) if allow_account
57
+ conf.filter_run_including(:account_limited) if allow_limited
58
+ end
59
+
60
+ conf.default_formatter = 'doc'
61
+ }
62
+
63
+ # stolen from https://gist.github.com/sue445/d840d6f68771a14a48fc
64
+ shared_context :uses_temp_dir do
65
+ around do |example|
66
+ Dir.mktmpdir("rspec-") do |dir|
67
+ @tmp_dir = dir
68
+ example.run
69
+ end
70
+ end
71
+
72
+ attr_reader :tmp_dir
73
+ end
data/yard_helper.rb ADDED
@@ -0,0 +1,30 @@
1
+
2
+ require_relative "lib/shep.rb"
3
+
4
+ class EntityFieldDeclHandler < YARD::Handlers::Ruby::Base #AttributeHandler
5
+ handles method_call(:fields)
6
+ namespace_only
7
+
8
+ process do
9
+ mastotype = namespace.name.to_s.gsub(/_/, '::')
10
+ new_docstr = "Ruby object representing a Mastodon `#{mastotype}` object:\n\n"
11
+
12
+ nnt = Object.const_get(namespace.path).send(:names_and_types)
13
+ nnt.each do |name, type|
14
+ # We generate the argument list in Markdown because I am
15
+ # completely done fighting with YARD to get it to recognize my
16
+ # 'attr' tags.
17
+
18
+ new_docstr += " * #{name} (#{type.to_yard_s})\n"
19
+ end
20
+
21
+ new_docstr += "\n"
22
+ new_docstr += "See `Shep::Entity` for an overview.\n\n"
23
+ new_docstr += namespace.docstring.to_raw.strip
24
+
25
+ namespace.docstring.replace(new_docstr)
26
+ end
27
+ end
28
+
29
+
30
+
metadata ADDED
@@ -0,0 +1,154 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shep
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.pre.alpha0
5
+ platform: ruby
6
+ authors:
7
+ - Chris Reuter
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-06-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: 3.12.0
19
+ name: rspec
20
+ prerelease: false
21
+ type: :development
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.12.0
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: 0.9.34
33
+ name: yard
34
+ prerelease: false
35
+ type: :development
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.9.34
41
+ - !ruby/object:Gem::Dependency
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 13.0.6
47
+ name: rake
48
+ prerelease: false
49
+ type: :development
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 13.0.6
55
+ description: |
56
+ Shep is a library that provides access to the Mastodon Web API. It
57
+ has no gem dependencies beyond the base Ruby (3.0.x) installation and
58
+ can be tested without a dedicated Mastodon server. It is intended as
59
+ a slightly more feature-rich alternative to the mastodon-api gem.
60
+ email: chris@isplitonyourgrave.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - Copyright.txt
66
+ - LICENSE.txt
67
+ - README.md
68
+ - Rakefile
69
+ - doc/Shep.html
70
+ - doc/Shep/Entity.html
71
+ - doc/Shep/Entity/Account.html
72
+ - doc/Shep/Entity/Context.html
73
+ - doc/Shep/Entity/CustomEmoji.html
74
+ - doc/Shep/Entity/MediaAttachment.html
75
+ - doc/Shep/Entity/Notification.html
76
+ - doc/Shep/Entity/Status.html
77
+ - doc/Shep/Entity/StatusSource.html
78
+ - doc/Shep/Entity/Status_Application.html
79
+ - doc/Shep/Entity/Status_Mention.html
80
+ - doc/Shep/Entity/Status_Tag.html
81
+ - doc/Shep/Error.html
82
+ - doc/Shep/Error/Caller.html
83
+ - doc/Shep/Error/Http.html
84
+ - doc/Shep/Error/Remote.html
85
+ - doc/Shep/Error/Server.html
86
+ - doc/Shep/Error/Type.html
87
+ - doc/Shep/Session.html
88
+ - doc/_index.html
89
+ - doc/class_list.html
90
+ - doc/css/common.css
91
+ - doc/css/full_list.css
92
+ - doc/css/style.css
93
+ - doc/file.README.html
94
+ - doc/file_list.html
95
+ - doc/frames.html
96
+ - doc/index.html
97
+ - doc/js/app.js
98
+ - doc/js/full_list.js
99
+ - doc/js/jquery.js
100
+ - doc/method_list.html
101
+ - doc/top-level-namespace.html
102
+ - lib/shep.rb
103
+ - lib/shep/entities.rb
104
+ - lib/shep/entity_base.rb
105
+ - lib/shep/exceptions.rb
106
+ - lib/shep/session.rb
107
+ - lib/shep/typeboxes.rb
108
+ - run_rake_test.example.sh
109
+ - shep.gemspec
110
+ - spec/data/smallimg.jpg
111
+ - spec/data/smallish.jpg
112
+ - spec/entity_common.rb
113
+ - spec/entity_t1_spec.rb
114
+ - spec/entity_t2_spec.rb
115
+ - spec/entity_t3_spec.rb
116
+ - spec/json_objects/account.1.json
117
+ - spec/json_objects/account.2.json
118
+ - spec/json_objects/status.1.json
119
+ - spec/json_objects/status.2.json
120
+ - spec/json_objects/status.3.json
121
+ - spec/json_objects/status.4.json
122
+ - spec/json_objects/status.5.json
123
+ - spec/json_objects/status.6.json
124
+ - spec/json_objects/status.7.json
125
+ - spec/session_reader_1_unauth_spec.rb
126
+ - spec/session_reader_2_auth_spec.rb
127
+ - spec/session_writer_spec.rb
128
+ - spec/spec_helper.rb
129
+ - yard_helper.rb
130
+ homepage: https://codeberg.org/suetanvil/shep
131
+ licenses:
132
+ - AGPL with linking exemption
133
+ metadata: {}
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: 3.0.0
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">"
146
+ - !ruby/object:Gem::Version
147
+ version: 1.3.1
148
+ requirements:
149
+ - A Ruby implementing 3.0.x syntax and the standard libs.
150
+ rubygems_version: 3.3.25
151
+ signing_key:
152
+ specification_version: 4
153
+ summary: An alternate interface to the Mastodon Web API
154
+ test_files: []