amplify_syndication 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2710bd59fa2d3c01b488bba30392f7bdf296741fbc698e8119c2a65c3ba5c33
4
- data.tar.gz: d61cecb2245118e3db17c27c973c4c9a32f37d7f65f159bc48973da0c32edda4
3
+ metadata.gz: c904621a09cb44ba73a694784f8f3ca99361b845f4f8f79e9c07d284b32f1f7c
4
+ data.tar.gz: '01094a0769aa29721d17bf14567daa765debbb580a9456913139459ec25d2bb1'
5
5
  SHA512:
6
- metadata.gz: 707bb585b4afc0d5476d874464d477f2632d51df1d7a3bd76c56a6a0f1c863fa71cdc4e9b8fd74e8740040527beafe9a2e1a84ed028fd0148911c826fb747562
7
- data.tar.gz: 54e3c195ab9a89484722166f2a1146227c85d65e8c0e47ee4aa70c28b6c5f35edbfb20aaa58bcc31aadf9527f51f9d2be887e8ebb25bc33cfdf4489cec409de0
6
+ metadata.gz: 82ac0a3a1682ed77be6487b41be10b41b1f48efb9fed201ee1c5c9935dbd2d965c5e68a199b4103fb1f2ae5f0b2f3838dcdb34532be28536ff27a5e299100449
7
+ data.tar.gz: 42309083ecdf14c0112dad8d8d36438daf591648ccb3bd374ba5925a8ec8d588a23224fe166b5bd4c59bde993f25eed79b2e033237039f43e3e5c366b7933448
data/.DS_Store ADDED
Binary file
@@ -0,0 +1,243 @@
1
+ module AmplifySyndication
2
+ class API
3
+ def initialize(client = Client.new)
4
+ @client = client
5
+ end
6
+
7
+ # Fetch metadata
8
+ def fetch_metadata
9
+ @client.get("$metadata?$format=json")
10
+ end
11
+
12
+ # Fetch property fields
13
+ def fetch_property_fields(batch_size: 50, sleep_seconds: 10)
14
+ offset = 0
15
+ fields = []
16
+
17
+ loop do
18
+ query_options = {
19
+ "$filter" => "ResourceName eq 'Property'",
20
+ "$top" => batch_size,
21
+ "$skip" => offset
22
+ }.compact
23
+ response = fetch_with_options("Field", query_options)
24
+ batch = response["value"]
25
+ break if batch.empty?
26
+
27
+ fields.concat(batch)
28
+
29
+ offset += batch_size
30
+
31
+ # Safety sleep between API calls
32
+ sleep(sleep_seconds) if sleep_seconds.positive?
33
+ end
34
+
35
+ fields
36
+ end
37
+
38
+ def fetch_all_lookups(batch_size: 50, sleep_seconds: 10, filter: nil)
39
+ offset = 0
40
+ values = []
41
+
42
+ loop do
43
+ query_options = {
44
+ "$top" => batch_size,
45
+ "$skip" => offset
46
+ }
47
+
48
+ # Apply filter only when provided
49
+ if filter.present?
50
+ combined_filter =
51
+ filter.is_a?(Array) ? filter.join(" and ") : filter
52
+ query_options["$filter"] = combined_filter
53
+ end
54
+
55
+ response = fetch_with_options("Lookup", query_options)
56
+ batch = response["value"] || []
57
+ break if batch.empty?
58
+
59
+ values.concat(batch)
60
+
61
+ offset += batch_size
62
+
63
+ # Safety sleep between API calls
64
+ sleep(sleep_seconds) if sleep_seconds.positive?
65
+ end
66
+
67
+ values
68
+ end
69
+
70
+ # get lookup name values
71
+ def lookup(lookup_name, batch_size: 50, sleep_seconds: 10)
72
+ offset = 0
73
+ values = []
74
+
75
+ loop do
76
+ query_options = {
77
+ "$filter" => "LookupName eq '#{lookup_name}'",
78
+ "$top" => batch_size,
79
+ "$skip" => offset
80
+ }.compact
81
+ response = fetch_with_options("Lookup", query_options)
82
+ batch = response["value"]
83
+ break if batch.empty?
84
+
85
+ values.concat(batch)
86
+ offset += batch_size
87
+
88
+ # Safety sleep between API calls
89
+ sleep(sleep_seconds) if sleep_seconds.positive?
90
+ end
91
+
92
+ values
93
+ end
94
+
95
+ # Fetch basic property data
96
+ def fetch_property_data(limit = 1)
97
+ @client.get("Property", "$top" => limit)
98
+ end
99
+
100
+ # Fetch data with query options
101
+ def fetch_with_options(resource, query_options = {})
102
+ @client.get_with_options(resource, query_options)
103
+ end
104
+
105
+ # Fetch properties with specific filtering, sorting, and pagination
106
+ def fetch_filtered_properties(filter: nil, select: nil, orderby: nil, top: nil, skip: nil, count: nil)
107
+ query_options = {
108
+ "$filter" => filter,
109
+ "$select" => select,
110
+ "$orderby" => orderby,
111
+ "$top" => top,
112
+ "$skip" => skip,
113
+ "$count" => count
114
+ }.compact
115
+ fetch_with_options("Property", query_options)
116
+ end
117
+
118
+ # Fetch the total count of properties
119
+ def fetch_property_count
120
+ fetch_filtered_properties(count: "true", top: 0)
121
+ end
122
+
123
+ ### Replication Methods ###
124
+
125
+ # Perform initial download for replication
126
+ def perform_initial_download(
127
+ resource: "Property",
128
+ batch_size: 100,
129
+ fields: ["ModificationTimestamp", "ListingKey"],
130
+ filter: nil,
131
+ sleep_seconds: 10,
132
+ checkpoint: { last_timestamp: "1970-01-01T00:00:00Z", last_key: 0 },
133
+ )
134
+ puts "Starting initial download..."
135
+ all_records = [] # Array to collect all records
136
+
137
+ loop do
138
+ puts "Fetching batch with timestamp > #{checkpoint[:last_timestamp]} and key > #{checkpoint[:last_key]}..."
139
+
140
+ # Build batch filter
141
+ batch_filter = []
142
+ batch_filter << "#{filter}" if filter
143
+ batch_filter << "(ModificationTimestamp gt #{URI.encode_www_form_component(checkpoint[:last_timestamp])})"
144
+ batch_filter << "or (ModificationTimestamp eq #{URI.encode_www_form_component(checkpoint[:last_timestamp])} and ListingKey gt '#{checkpoint[:last_key]}')"
145
+ batch_filter = batch_filter.join(" ")
146
+
147
+ # Query options
148
+ query_options = {
149
+ "$select" => fields.join(","),
150
+ "$filter" => batch_filter,
151
+ "$orderby" => "ModificationTimestamp,ListingKey",
152
+ "$top" => batch_size
153
+ }
154
+
155
+ # Debugging: Print the full query options
156
+ puts "Query options: #{query_options.inspect}"
157
+
158
+ # Send request
159
+ response = fetch_with_options(resource, query_options)
160
+ records = response["value"]
161
+ break if records.empty?
162
+
163
+ # Collect batch records
164
+ all_records.concat(records)
165
+
166
+ # Update checkpoint with the last record in the batch
167
+ last_record = records.last
168
+ checkpoint[:last_timestamp] = last_record["ModificationTimestamp"]
169
+ checkpoint[:last_key] = last_record["ListingKey"]
170
+
171
+ # Stop if the number of records is less than the batch size
172
+ break if records.size < batch_size
173
+
174
+ # Safety sleep between API calls
175
+ sleep(sleep_seconds) if sleep_seconds.positive?
176
+ end
177
+
178
+ puts "Initial download complete."
179
+ all_records # Return the collected records
180
+ end
181
+
182
+ # Fetch updates since the last checkpoint
183
+ def fetch_updates(
184
+ resource: "Property",
185
+ batch_size: 100,
186
+ fields: ["ModificationTimestamp", "ListingKey"],
187
+ filter: nil,
188
+ checkpoint: { last_timestamp: "1970-01-01T00:00:00Z", last_key: 0 }
189
+ )
190
+ perform_initial_download(
191
+ resource: resource,
192
+ batch_size: batch_size,
193
+ fields: fields,
194
+ filter: filter,
195
+ checkpoint: checkpoint
196
+ ) do |batch|
197
+ # Process updates
198
+ yield(batch) if block_given?
199
+ end
200
+ end
201
+
202
+ # Fetch full details of a property by ListingKey
203
+ def fetch_property_by_key(listing_key)
204
+ endpoint = "Property('#{listing_key}')"
205
+ puts "Fetching property details for ListingKey: #{listing_key}"
206
+ @client.get(endpoint)
207
+ end
208
+
209
+ ### Media Methods ###
210
+
211
+ # Fetch a media record by MediaKey
212
+ def fetch_media_by_key(media_key)
213
+ endpoint = "Media('#{media_key}')"
214
+ @client.get(endpoint)
215
+ end
216
+
217
+ # Fetch recently created/modified media records
218
+ def fetch_recent_media(
219
+ filter: "ImageSizeDescription eq 'Large' and ResourceName eq 'Property'",
220
+ modification_date: "2023-07-27T04:00:00Z",
221
+ orderby: "ModificationTimestamp,MediaKey",
222
+ batch_size: 100
223
+ )
224
+ query_options = {
225
+ "$filter" => "#{filter} and ModificationTimestamp ge #{modification_date}",
226
+ "$orderby" => orderby,
227
+ "$top" => batch_size
228
+ }
229
+ fetch_with_options("Media", query_options)
230
+ end
231
+
232
+ # Fetch media by ResourceName and ResourceRecordKey
233
+ def fetch_media_by_resource(resource_name, resource_key, batch_size = 100)
234
+ filter = "ResourceRecordKey eq '#{resource_key}' and ResourceName eq '#{resource_name}'"
235
+ query_options = {
236
+ "$filter" => filter,
237
+ "$orderby" => "ModificationTimestamp,MediaKey",
238
+ "$top" => batch_size
239
+ }
240
+ fetch_with_options("Media", query_options)
241
+ end
242
+ end
243
+ end
@@ -0,0 +1,44 @@
1
+ require "httpclient"
2
+ require "json"
3
+ require "uri"
4
+
5
+ module AmplifySyndication
6
+ class Client
7
+ def initialize
8
+ @http_client = HTTPClient.new
9
+ @base_url = AmplifySyndication.configuration.base_url
10
+ @access_token = AmplifySyndication.configuration.access_token
11
+ end
12
+
13
+ def get(endpoint, params = {})
14
+ url = "#{@base_url}/#{endpoint}".gsub(%r{//}, '/').sub(%r{:/}, '://')
15
+ headers = {
16
+ "Authorization" => "Bearer #{@access_token}",
17
+ "Accept" => "application/json"
18
+ }
19
+ response = @http_client.get(url, params, headers)
20
+ parse_response(response)
21
+ end
22
+
23
+ def get_with_options(endpoint, options = {})
24
+ query_string = options.map { |key, value| "#{key}=#{value}" }.join("&")
25
+ get("#{endpoint}?#{query_string}")
26
+ end
27
+
28
+ private
29
+
30
+ # Converts a hash of query options into a URL-encoded query string
31
+ def build_query_string(options)
32
+ URI.encode_www_form(options)
33
+ end
34
+
35
+ # Parses JSON response, raises an error for non-200 responses
36
+ def parse_response(response)
37
+ if response.status == 200
38
+ JSON.parse(response.body)
39
+ else
40
+ raise StandardError, "HTTP Error: #{response.status} - #{response.body}"
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,10 @@
1
+ module AmplifySyndication
2
+ class Configuration
3
+ attr_accessor :access_token, :base_url
4
+
5
+ def initialize
6
+ @access_token = nil
7
+ @base_url = "https://query.ampre.ca/odata"
8
+ end
9
+ end
10
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AmplifySyndication
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amplify_syndication
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Higgins
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-12-09 00:00:00.000000000 Z
11
+ date: 2025-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httpclient
@@ -32,11 +32,15 @@ executables: []
32
32
  extensions: []
33
33
  extra_rdoc_files: []
34
34
  files:
35
+ - ".DS_Store"
35
36
  - CHANGELOG.md
36
37
  - LICENSE.txt
37
38
  - README.md
38
39
  - Rakefile
39
40
  - lib/amplify_syndication.rb
41
+ - lib/amplify_syndication/api.rb
42
+ - lib/amplify_syndication/client.rb
43
+ - lib/amplify_syndication/configuration.rb
40
44
  - lib/amplify_syndication/version.rb
41
45
  - sig/amplify_syndication.rbs
42
46
  homepage: https://github.com/gryphonandrook/amplify_syndication