at_protocol 0.0.4.1 → 0.0.4.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b9079f38f8b754c7aab1c556dd3b79e98a5f95ffa5091ce0a36f3f3da483b69d
4
- data.tar.gz: b3423fa8c0a4595f7afb81cbb823c38a58a6d5e609dff38ebe297b85dfd4c84b
3
+ metadata.gz: e0dd450b9e79e59d5df52330a9e0fd00135db4e2a8eddce654780133835ca69f
4
+ data.tar.gz: bda2354c8c63d85eee0075c5fda834e1018e31e9c8b5daba221695644998e338
5
5
  SHA512:
6
- metadata.gz: 066a7e0ba5ea613209e4b180be05c25c82251968fad5e7b611fa3200ae820ceb41268c1759d0ec77eb733aa410c8878cbd6890c61e7bf47ebd1171c364ca84ed
7
- data.tar.gz: b106124acf97f5d6443aae45adcf65eac04319d923f92e08e3404bb87c8912ab59ff7feb739ef9b0a377c9b23e83fa0789bed8ba8128dd5e8ad9be4d4a7c0dad
6
+ metadata.gz: 19eec8bd3383a55ae752ed3561bcced63c5a438fe1060dcd1a08fe46249e56d469b7ded6a026c73d82a84a78ef4fd2af35572ccd610fa854287b1babf43e3e8f
7
+ data.tar.gz: e8d0dc32c9e1a4101fb8dc30b0ca16a49955f3d096fbc75d36ce20486590cefb67df66c83268dabde43716495247706b6f8a7599a6b530a67b75d1b096c621db
@@ -0,0 +1,3 @@
1
+ require "mkmf"
2
+
3
+ create_makefile("at_protocol/tid")
@@ -0,0 +1,130 @@
1
+ #include <ruby.h>
2
+ #include <time.h>
3
+ #include <stdio.h>
4
+ #include <stdint.h>
5
+ #include <math.h>
6
+
7
+ static VALUE atproto_module;
8
+ static VALUE tid_class;
9
+ const char b32_chars[32] = "234567abcdefghijklmnopqrstuvwxyz";
10
+
11
+ typedef struct {
12
+ uint64_t timestamp;
13
+ uint64_t clock_identifier;
14
+ } TID;
15
+
16
+ static VALUE tid_alloc(VALUE klass) {
17
+ TID *tid = ALLOC(TID);
18
+ return Data_Wrap_Struct(klass, 0, xfree, tid);
19
+ }
20
+
21
+ static VALUE tid_initialize(int argc, VALUE *argv, VALUE self) {
22
+ VALUE time_arg = Qnil;
23
+ rb_scan_args(argc, argv, "01", &time_arg);
24
+
25
+ TID *tid;
26
+ Data_Get_Struct(self, TID, tid);
27
+
28
+ if (NIL_P(time_arg)) {
29
+ struct timeval tv;
30
+ gettimeofday(&tv, NULL);
31
+ tid->timestamp = (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec;
32
+ } else {
33
+ if (!rb_obj_is_kind_of(time_arg, rb_cTime)) {
34
+ rb_raise(rb_eTypeError, "Argument must be a Time object or nil");
35
+ return Qnil;
36
+ }
37
+
38
+ struct timeval tv;
39
+ tv.tv_sec = NUM2LONG(rb_funcall(time_arg, rb_intern("tv_sec"), 0));
40
+ tv.tv_usec = NUM2LONG(rb_funcall(time_arg, rb_intern("tv_usec"), 0));
41
+ tid->timestamp = (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec;
42
+ }
43
+
44
+ tid->clock_identifier = rand() & 0x3FF;
45
+
46
+ return self;
47
+ }
48
+
49
+ static VALUE tid_to_time(VALUE self) {
50
+ TID *tid;
51
+ Data_Get_Struct(self, TID, tid);
52
+
53
+ VALUE sec = LL2NUM(tid->timestamp / 1000000);
54
+ VALUE usec = LL2NUM(tid->timestamp % 1000000);
55
+
56
+ return rb_funcall(rb_cTime, rb_intern("at"), 2, sec, usec);
57
+ }
58
+
59
+ static VALUE tid_to_s(VALUE self) {
60
+ TID *tid;
61
+ Data_Get_Struct(self, TID, tid);
62
+
63
+ char tid_str[14];
64
+ for (int i = 0; i < 11; i++) {
65
+ int index = (int)((tid->timestamp >> (50 - i * 5)) & 0x1F);
66
+ tid_str[i] = b32_chars[index];
67
+ }
68
+ tid_str[11] = b32_chars[(int)(tid->clock_identifier >> 6) & 0x1F];
69
+ tid_str[12] = b32_chars[(int)tid->clock_identifier & 0x1F];
70
+ tid_str[13] = '\0';
71
+
72
+ return rb_str_new_cstr(tid_str);
73
+ }
74
+
75
+ static VALUE tid_from_string(VALUE klass, VALUE str) {
76
+ Check_Type(str, T_STRING);
77
+
78
+ TID *tid;
79
+ VALUE tid_obj = Data_Make_Struct(klass, TID, NULL, xfree, tid);
80
+
81
+ if (RSTRING_LEN(str) != 13) {
82
+ rb_raise(rb_eArgError, "TID string must be 13 characters long");
83
+ return Qnil;
84
+ }
85
+
86
+ char tid_str[14];
87
+ strncpy(tid_str, StringValueCStr(str), sizeof(tid_str));
88
+ tid_str[13] = '\0';
89
+
90
+ // Convert the TID string back to a TID object
91
+ uint64_t timestamp = 0;
92
+ for (int i = 0; i < 11; i++) {
93
+ char c = tid_str[i];
94
+ const char *pos = strchr(b32_chars, c);
95
+ if (pos == NULL) {
96
+ rb_raise(rb_eArgError, "Invalid character in TID string");
97
+ return Qnil;
98
+ }
99
+ int index = (int)(pos - b32_chars);
100
+ timestamp = (timestamp << 5) | (index & 0x1F);
101
+ }
102
+
103
+ uint64_t clock_identifier = 0;
104
+ for (int i = 11; i < 13; i++) {
105
+ char c = tid_str[i];
106
+ const char *pos = strchr(b32_chars, c);
107
+ if (pos == NULL) {
108
+ rb_raise(rb_eArgError, "Invalid character in TID string");
109
+ return Qnil;
110
+ }
111
+ int index = (int)(pos - b32_chars);
112
+ clock_identifier = (clock_identifier << 5) | (index & 0x1F);
113
+ }
114
+
115
+ tid->timestamp = timestamp;
116
+ tid->clock_identifier = clock_identifier;
117
+
118
+ return tid_obj;
119
+ }
120
+
121
+ void Init_tid(void) {
122
+ atproto_module = rb_define_module("ATProto");
123
+
124
+ tid_class = rb_define_class_under(atproto_module, "TID", rb_cObject);
125
+ rb_define_alloc_func(tid_class, tid_alloc);
126
+ rb_define_method(tid_class, "initialize", tid_initialize, -1);
127
+ rb_define_method(tid_class, "to_time", tid_to_time, 0);
128
+ rb_define_method(tid_class, "to_s", tid_to_s, 0);
129
+ rb_define_singleton_method(tid_class, "from_string", tid_from_string, 1);
130
+ }
@@ -13,6 +13,10 @@ module ATProto
13
13
 
14
14
  module_function :at_uri
15
15
  end
16
+
17
+ def self.AtUri(str)
18
+ RequestUtils.at_uri(str)
19
+ end
16
20
  end
17
21
 
18
22
  module ATProto
@@ -9,22 +9,10 @@ module ATProto
9
9
  const(:repo, ATProto::Repo)
10
10
  const(:collection, String)
11
11
 
12
- sig { params(limit: Integer).returns(T::Array[ATProto::Record]) }
13
-
14
- def list(limit = 10)
15
- self.repo.xrpc
16
- .get.com_atproto_repo_listRecords(
17
- repo: self.repo.did,
18
- collection: self.collection,
19
- limit: limit,
20
- )["records"]
21
- .map { |record|
22
- ATProto::Record.from_hash(record)
23
- }
24
- end
12
+ sig { params(count: T.nilable(Integer)).returns(T::Array[ATProto::Record]) }
25
13
 
26
- def list_all()
27
- T.must(get_paginated_data(self.repo, :com_atproto_repo_listRecords.to_s, key: "records", params: { repo: self.repo.to_s, collection: self.to_s }, cursor: nil) do |record|
14
+ def list(count = nil)
15
+ T.must(get_paginated_data(self.repo, :com_atproto_repo_listRecords.to_s, key: "records", params: { repo: self.repo.to_s, collection: self.to_s }, count: count, cursor: nil) do |record|
28
16
  ATProto::Record.from_hash(record)
29
17
  end)
30
18
  end
@@ -78,6 +78,9 @@ module ATProto
78
78
  cursor: T.nilable(
79
79
  String
80
80
  ),
81
+ count: T.nilable(
82
+ Integer
83
+ ),
81
84
  map_block: T.nilable(Proc),
82
85
  )
83
86
  .returns(T
@@ -86,7 +89,7 @@ module ATProto
86
89
  ))
87
90
  }
88
91
 
89
- def get_paginated_data(session, method, key:, params:, cursor: nil, &map_block)
92
+ def get_paginated_data(session, method, key:, params:, cursor: nil, count: nil, &map_block)
90
93
  params.merge({ limit: 100, cursor: cursor }).then do |send_data|
91
94
  session.xrpc.get.public_send(method, **send_data).then do |response|
92
95
  response.dig(key).then do |data|
@@ -94,26 +97,19 @@ module ATProto
94
97
  return []
95
98
  end
96
99
 
97
- if block_given?
98
- data.map(&map_block).then do |results|
99
- response.dig("cursor").then do |next_cursor|
100
- if next_cursor.nil?
101
- return results
102
- else
103
- get_paginated_data(session, method, key: key, params: params, cursor: next_cursor, &map_block).then do |next_results|
104
- return results + next_results
105
- end
106
- end
107
- end
100
+ results = if block_given?
101
+ data.map(&map_block)
102
+ else
103
+ data
108
104
  end
109
- else
110
- response.dig("cursor").then do |next_cursor|
111
- if next_cursor.nil?
112
- return data
113
- else
114
- get_paginated_data(session, method, key: key, params: params, cursor: next_cursor, &map_block).then do |next_results|
115
- return data + next_results
116
- end
105
+
106
+ response.dig("cursor").then do |next_cursor|
107
+ if next_cursor.nil? || (count && results.length >= count)
108
+ return results[0..count]
109
+ else
110
+ remaining_count = count ? count - results.length : nil
111
+ get_paginated_data(session, method, key: key, params: params, cursor: next_cursor, count: remaining_count, &map_block).then do |next_results|
112
+ return (results + next_results)
117
113
  end
118
114
  end
119
115
  end
@@ -123,3 +119,26 @@ module ATProto
123
119
  end
124
120
  end
125
121
  end
122
+
123
+ module ATProto
124
+ module RequestUtils
125
+ class XRPCResponseCode < T::Enum
126
+ enums do
127
+ Unknown = new(1)
128
+ InvalidResponse = new(2)
129
+ Success = new(200)
130
+ InvalidRequest = new(400)
131
+ AuthRequired = new(401)
132
+ Forbidden = new(403)
133
+ XRPCNotSupported = new(404)
134
+ PayloadTooLarge = new(413)
135
+ RateLimitExceeded = new(429)
136
+ InternalServerError = new(500)
137
+ MethodNotImplemented = new(501)
138
+ UpstreamFailure = new(502)
139
+ NotEnoughResouces = new(503)
140
+ UpstreamTimeout = new(504)
141
+ end
142
+ end
143
+ end
144
+ end
@@ -66,6 +66,10 @@ module ATProto
66
66
  raise UnauthorizedError
67
67
  end
68
68
  end
69
+
70
+ def inspect
71
+ "#<ATProto::Session(did: #{did}, access_token: #{access_token})>"
72
+ end
69
73
  end
70
74
  end
71
75
 
@@ -0,0 +1,19 @@
1
+ require "at_protocol/tid"
2
+
3
+ class Time
4
+ def to_tid
5
+ ATProto::TID.new(self)
6
+ end
7
+ end
8
+
9
+ class String
10
+ def to_tid
11
+ ATProto::TID.from_string(self)
12
+ end
13
+ end
14
+
15
+ class ATProto::TID
16
+ def inspect
17
+ "#<ATProto::TID(#{self.to_s})>"
18
+ end
19
+ end
@@ -1,4 +1,4 @@
1
1
  # typed: strict
2
2
  module ATProto
3
- VERSION = "0.0.4.1"
3
+ VERSION = "0.0.4.3"
4
4
  end
@@ -1,5 +1,7 @@
1
1
  # typed: true
2
2
  module ATProto
3
+ extend T::Sig
4
+
3
5
  class Writes < T::Struct
4
6
  class Write < T::Struct
5
7
  class Action < T::Enum
@@ -101,14 +103,13 @@ module ATProto
101
103
 
102
104
  class << self
103
105
  extend T::Sig
104
- sig { params(block: Proc).returns(T::Array[Write]) }
105
-
106
- def generate(&block)
107
- Collector.new.instance_eval(&block)
108
- end
109
106
  end
110
107
  end
111
108
 
109
+ def self.Writes(session, &block)
110
+ Writes.new(writes: Writes::Collector.new.instance_eval(&block), session: session, repo: Repo.new(session.did))
111
+ end
112
+
112
113
  class Writes
113
114
  class Collector
114
115
  include RequestUtils
data/lib/at_protocol.rb CHANGED
@@ -15,9 +15,21 @@ class Class
15
15
  end
16
16
  end
17
17
 
18
+ module ATProto
19
+ class << self
20
+ def method_missing(method_name, *args, &block)
21
+ if const_defined?(method_name)
22
+ Object.const_get(method_name).new(*args, &block)
23
+ else
24
+ super
25
+ end
26
+ end
27
+ end
28
+ end
29
+
18
30
  require "skyfall/cid"
19
31
  require "xrpc"
20
32
 
21
- %w(requests session repo collection at_uri writes record record/strongref).each do |name|
33
+ %w(requests session repo collection at_uri writes record record/strongref tid_ext).each do |name|
22
34
  require "at_protocol/#{name}"
23
35
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: at_protocol
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4.1
4
+ version: 0.0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shreyan Jain
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-09-01 00:00:00.000000000 Z
12
+ date: 2023-10-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: xrpc
@@ -25,13 +25,30 @@ dependencies:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: 0.1.5
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake-compiler
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
28
42
  description: A Ruby gem for interacting with AT Protocol
29
43
  email:
30
44
  - shreyan.jain.9@outlook.com
31
45
  executables: []
32
- extensions: []
46
+ extensions:
47
+ - ext/at_protocol/extconf.rb
33
48
  extra_rdoc_files: []
34
49
  files:
50
+ - "./ext/at_protocol/extconf.rb"
51
+ - "./ext/at_protocol/tid.c"
35
52
  - "./lib/at_protocol.rb"
36
53
  - "./lib/at_protocol/at_uri.rb"
37
54
  - "./lib/at_protocol/collection.rb"
@@ -40,8 +57,10 @@ files:
40
57
  - "./lib/at_protocol/repo.rb"
41
58
  - "./lib/at_protocol/requests.rb"
42
59
  - "./lib/at_protocol/session.rb"
60
+ - "./lib/at_protocol/tid_ext.rb"
43
61
  - "./lib/at_protocol/version.rb"
44
62
  - "./lib/at_protocol/writes.rb"
63
+ - ext/at_protocol/extconf.rb
45
64
  homepage: https://github.com/ShreyanJain9/at_protocol
46
65
  licenses:
47
66
  - MIT
@@ -50,6 +69,7 @@ post_install_message:
50
69
  rdoc_options: []
51
70
  require_paths:
52
71
  - lib
72
+ - ext
53
73
  required_ruby_version: !ruby/object:Gem::Requirement
54
74
  requirements:
55
75
  - - ">="