skypost 0.0.1
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 +7 -0
- data/README.md +61 -0
- data/lib/skypost/client.rb +116 -0
- data/lib/skypost/version.rb +3 -0
- data/lib/skypost.rb +8 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 72251c65823ba0eb09ed0383726432a97ee1cb1359fef32441158e4c7c090c89
|
4
|
+
data.tar.gz: bd91c3aa9a407183191f6e6203a3279c7b76c4d4518fbd9355c6f08e3361d9d4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aebd23ca3736be8ce1b4e80b084e28f5b3032557d747e0fd07186dd508775708f78339f0eff58789936559d3f0d78d96028e94509aa4c983e07bf5a1d498ea8e
|
7
|
+
data.tar.gz: fc2d2eb5d9bdf1a69b54c864f95aefd00b64f3d08cb56c8980e7848ad51447300624f3bb0fd8d3191559aabd39aaac6b845acdd6dfada4ddbff2e967e1381296
|
data/README.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# Skypost
|
2
|
+
|
3
|
+
A Ruby gem for posting messages to Bluesky social network.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'skypost'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle install
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install skypost
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require 'skypost'
|
25
|
+
|
26
|
+
# Initialize the client with your Bluesky credentials
|
27
|
+
# You can use either your custom domain or .bsky.social handle
|
28
|
+
client = Skypost::Client.new("username.com", "your-app-password")
|
29
|
+
# OR
|
30
|
+
client = Skypost::Client.new("username.bsky.social", "your-app-password")
|
31
|
+
|
32
|
+
# Post a message
|
33
|
+
client.post("Hello from Skypost!")
|
34
|
+
|
35
|
+
# Post a message with a clickable link
|
36
|
+
client.post('Check out this cool website: <a href="https://example.com">Example</a>!')
|
37
|
+
```
|
38
|
+
|
39
|
+
### App Password
|
40
|
+
To get your app password, go to your Bluesky account settings at [bsky.app/settings/app-passwords](https://bsky.app/settings/app-passwords) and create a new app password. Never use your main account password for API access.
|
41
|
+
|
42
|
+
### Handle Format
|
43
|
+
You can use either:
|
44
|
+
1. Your custom domain (if you have one), e.g., `username.com`
|
45
|
+
2. Your Bluesky handle in the format `username.bsky.social`
|
46
|
+
|
47
|
+
To find your handle, look at your profile URL in Bluesky. For example:
|
48
|
+
- If your profile is at `https://bsky.app/profile/username.com`, use `username.com`
|
49
|
+
- If your profile is at `https://bsky.app/profile/username.bsky.social`, use `username.bsky.social`
|
50
|
+
|
51
|
+
## Development
|
52
|
+
|
53
|
+
After checking out the repo, run `bundle install` to install dependencies.
|
54
|
+
|
55
|
+
## Contributing
|
56
|
+
|
57
|
+
Bug reports and pull requests are welcome on GitHub.
|
58
|
+
|
59
|
+
## License
|
60
|
+
|
61
|
+
The gem is available as open source under the terms of the MIT License.
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Skypost
|
5
|
+
class Client
|
6
|
+
BASE_URL = "https://bsky.social"
|
7
|
+
|
8
|
+
class AuthenticationError < StandardError; end
|
9
|
+
class ValidationError < StandardError; end
|
10
|
+
|
11
|
+
def initialize(identifier = nil, password = nil)
|
12
|
+
@identifier = identifier
|
13
|
+
@password = password
|
14
|
+
@session = nil
|
15
|
+
validate_identifier if identifier
|
16
|
+
end
|
17
|
+
|
18
|
+
def authenticate
|
19
|
+
raise AuthenticationError, "Identifier and password are required" if @identifier.nil? || @password.nil?
|
20
|
+
|
21
|
+
response = connection.post("/xrpc/com.atproto.server.createSession") do |req|
|
22
|
+
req.headers["Content-Type"] = "application/json"
|
23
|
+
req.body = JSON.generate({
|
24
|
+
identifier: @identifier,
|
25
|
+
password: @password
|
26
|
+
})
|
27
|
+
end
|
28
|
+
|
29
|
+
@session = JSON.parse(response.body)
|
30
|
+
@session
|
31
|
+
rescue Faraday::ResourceNotFound => e
|
32
|
+
raise AuthenticationError, "Authentication failed: Invalid credentials or incorrect handle format. Your handle should be either your custom domain (e.g., 'username.com') or your Bluesky handle (e.g., 'username.bsky.social')"
|
33
|
+
rescue Faraday::Error => e
|
34
|
+
raise AuthenticationError, "Failed to authenticate: #{e.message}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def post(text)
|
38
|
+
ensure_authenticated
|
39
|
+
|
40
|
+
current_time = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S.%3NZ")
|
41
|
+
facets = extract_links(text)
|
42
|
+
|
43
|
+
request_body = {
|
44
|
+
repo: @session["did"],
|
45
|
+
collection: "app.bsky.feed.post",
|
46
|
+
record: {
|
47
|
+
text: text.gsub(/<a href="[^"]*">|<\/a>/, ''), # Remove HTML tags but keep link text
|
48
|
+
facets: facets,
|
49
|
+
createdAt: current_time,
|
50
|
+
"$type": "app.bsky.feed.post"
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
response = connection.post("/xrpc/com.atproto.repo.createRecord") do |req|
|
55
|
+
req.headers["Content-Type"] = "application/json"
|
56
|
+
req.headers["Authorization"] = "Bearer #{@session["accessJwt"]}"
|
57
|
+
req.body = JSON.generate(request_body)
|
58
|
+
end
|
59
|
+
|
60
|
+
JSON.parse(response.body)
|
61
|
+
rescue Faraday::ResourceNotFound => e
|
62
|
+
raise "Failed to post: The API endpoint returned 404. Please check if you're authenticated and using the correct API endpoint."
|
63
|
+
rescue Faraday::Error => e
|
64
|
+
raise "Failed to post: #{e.message}"
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def validate_identifier
|
70
|
+
unless @identifier.include?(".")
|
71
|
+
raise ValidationError, "Invalid handle format. Handle must be either a custom domain (e.g., 'username.com') or a Bluesky handle (e.g., 'username.bsky.social')"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def ensure_authenticated
|
76
|
+
authenticate if @session.nil?
|
77
|
+
end
|
78
|
+
|
79
|
+
def connection
|
80
|
+
@connection ||= Faraday.new(url: BASE_URL) do |f|
|
81
|
+
f.request :json
|
82
|
+
f.response :raise_error
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def extract_links(text)
|
87
|
+
facets = []
|
88
|
+
link_pattern = /<a href="([^"]*)">(.*?)<\/a>/
|
89
|
+
|
90
|
+
# First, find all matches to calculate correct byte positions
|
91
|
+
matches = text.to_enum(:scan, link_pattern).map { Regexp.last_match }
|
92
|
+
plain_text = text.gsub(/<a href="[^"]*">|<\/a>/, '') # Text with HTML removed
|
93
|
+
|
94
|
+
matches.each do |match|
|
95
|
+
url = match[1]
|
96
|
+
link_text = match[2]
|
97
|
+
|
98
|
+
# Find the link text in the plain text to get correct byte positions
|
99
|
+
if link_position = plain_text.index(link_text)
|
100
|
+
facets << {
|
101
|
+
index: {
|
102
|
+
byteStart: link_position,
|
103
|
+
byteEnd: link_position + link_text.bytesize
|
104
|
+
},
|
105
|
+
features: [{
|
106
|
+
"$type": "app.bsky.richtext.facet#link",
|
107
|
+
uri: url
|
108
|
+
}]
|
109
|
+
}
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
facets
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/lib/skypost.rb
ADDED
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: skypost
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jeroen Roosenboom
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-11-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '13.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '13.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
description: A simple Ruby gem that allows posting messages to the Bluesky social
|
84
|
+
network
|
85
|
+
email:
|
86
|
+
- hi@jro7.com
|
87
|
+
executables: []
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- README.md
|
92
|
+
- lib/skypost.rb
|
93
|
+
- lib/skypost/client.rb
|
94
|
+
- lib/skypost/version.rb
|
95
|
+
homepage: https://github.com/jro7/skypost
|
96
|
+
licenses:
|
97
|
+
- MIT
|
98
|
+
metadata: {}
|
99
|
+
post_install_message:
|
100
|
+
rdoc_options: []
|
101
|
+
require_paths:
|
102
|
+
- lib
|
103
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: 2.6.0
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
requirements: []
|
114
|
+
rubygems_version: 3.5.23
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: A Ruby gem for posting to Bluesky
|
118
|
+
test_files: []
|