bandcamp-discover 0.6.1 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2f1f8a4daa65012813a3a09bd62db1afc77e51751f14d9f69fa39ecfb144dab
4
- data.tar.gz: f0311426fe47b54f71c722869395a9b435f63b13085e3c6779e0b82d40e81a77
3
+ metadata.gz: 0f788095223220ca96084269592bcfacc5ffcd11bdc4ccc27c43312f9a4f019e
4
+ data.tar.gz: d8428295e7b665d2ae448f34f4a84b74bd1290357499d6266e6859fe9b60b7fd
5
5
  SHA512:
6
- metadata.gz: ff76b0b9b44909e568340ad18db61ed52af685391e9607ea88478bb23ba8feb346a96504a9624b9aed68b5c17b2f074bf38a2c9d26dde9f215c36b803a360bbc
7
- data.tar.gz: 503083930726ae15941c4cbcf63a7783aed3c921c4f25af1745e1ef684481743f69efd4d87cae53c0ec572df95fdcd7ac197ac69291a59b9e9f4f2a94c9a688a
6
+ metadata.gz: 97041bbe3141a01e73712b5fa8f1a175ce437ad8ec6f9c38a09447c21e828af10390a248a508d63048447c982b2ac27fcef24bd1f82f285421537aaeb0acbd5a
7
+ data.tar.gz: cd751e7ed3dd432b66e3988c89277cf6b91363193dd3a174f5803a2d34e620ad0ec0a2ad347b4c8636c19d263fedde9beb114d9a7594f7182922bc91bca35fb2
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bandcamp-discover (0.6.1)
4
+ bandcamp-discover (0.7.1)
5
5
  async
6
6
  base64
7
7
  concurrent-ruby
data/README.rdoc CHANGED
@@ -17,7 +17,9 @@ accepts demos. The model and both prompts can be set by the host app:
17
17
  Before the bio is asked, the /music grid is read: a page whose releases carry
18
18
  no artist credit other than the owner is an artist, not a label, and is
19
19
  rejected without a model call. The credits that remain are appended to the
20
- bio for the model and returned as +artists+ in the scrape result.
20
+ bio for the model and returned as +artists+ in the scrape result; each
21
+ entry in +albums+ carries its own credit as +artist+ (nil when the release
22
+ is credited to the page owner).
21
23
 
22
24
  Without a token, +label?+ falls back to matching /label|platform|records/i
23
25
  and +accepts_demos?+ is always false.
@@ -43,7 +43,13 @@ module BandcampDiscover
43
43
  extras: {response_format: {type: "json_object"}}
44
44
  )
45
45
 
46
- JSON.parse(response["choices"][0]["message"]["content"])["answer"]&.to_s&.downcase == "true"
46
+ answer(response["choices"][0]["message"]["content"])["answer"]&.to_s&.downcase == "true"
47
+ end
48
+
49
+ # response_format is advisory on OpenRouter: Anthropic models return the
50
+ # object inside a ```json fence, and some prepend a sentence.
51
+ def answer(content)
52
+ JSON.parse(content[/\{.*\}/m] || content)
47
53
  end
48
54
 
49
55
  # The bio alone cannot tell one person releasing under aliases from a
@@ -31,7 +31,7 @@ module BandcampDiscover
31
31
  items.map do |item|
32
32
  {
33
33
  url: absolute(item.query_selector("a")[:href]),
34
- credit: item.query_selector(".artist-override")&.inner_text
34
+ credit: item.query_selector(".artist-override")&.inner_text&.strip
35
35
  }
36
36
  end
37
37
  end
@@ -41,6 +41,9 @@ module BandcampDiscover
41
41
  Roster.new(band_name: band_name, credits: grid.map { _1[:credit] }, releases: grid.size)
42
42
  end
43
43
 
44
+ # Each album carries the credit its grid item showed: the artist's name,
45
+ # or nil when the release is credited to the page owner. The grid is the
46
+ # only place the credit appears without another page load.
44
47
  def albums(grid)
45
48
  guarded do
46
49
  semaphore = Async::Semaphore.new(@max_tasks)
@@ -53,12 +56,12 @@ module BandcampDiscover
53
56
 
54
57
  puts "done scraping #{item[:url]}"
55
58
 
56
- album
59
+ [item, album]
57
60
  end
58
61
  end.map(&:wait)
59
62
 
60
- albums.map! do |album_url, album_title, album_tags, album_player|
61
- {url: album_url, title: album_title, tags: album_tags, player_url: album_player}
63
+ albums.map! do |item, (album_url, album_title, album_tags, album_player)|
64
+ {url: album_url, title: album_title, tags: album_tags, player_url: album_player, artist: item[:credit]}
62
65
  end
63
66
 
64
67
  [albums, normalize_tally(albums.map { _1[:tags] }.flatten.tally)]
@@ -1,3 +1,3 @@
1
1
  module BandcampDiscover
2
- VERSION = "0.6.1"
2
+ VERSION = "0.7.1"
3
3
  end
@@ -23,12 +23,12 @@ module OpenRouter
23
23
 
24
24
  class Client
25
25
  class << self
26
- attr_accessor :requests, :answer
26
+ attr_accessor :requests, :answer, :raw
27
27
  end
28
28
 
29
29
  def complete(messages, model:, extras:)
30
30
  self.class.requests << {messages: messages, model: model, extras: extras}
31
- {"choices" => [{"message" => {"content" => JSON.generate("answer" => self.class.answer)}}]}
31
+ {"choices" => [{"message" => {"content" => self.class.raw || JSON.generate("answer" => self.class.answer)}}]}
32
32
  end
33
33
  end
34
34
  end
@@ -41,6 +41,7 @@ class AnalyzerTest < Minitest::Test
41
41
  OpenRouter.configuration.access_token = "token"
42
42
  OpenRouter::Client.requests = []
43
43
  OpenRouter::Client.answer = true
44
+ OpenRouter::Client.raw = nil
44
45
  end
45
46
 
46
47
  def teardown
@@ -99,6 +100,18 @@ class AnalyzerTest < Minitest::Test
99
100
  assert_equal "", OpenRouter::Client.requests.last[:messages].last[:content]
100
101
  end
101
102
 
103
+ def test_reads_the_answer_out_of_a_markdown_fence
104
+ OpenRouter::Client.raw = "```json\n{\"answer\": false}\n```"
105
+
106
+ refute Analyzer.new("bio").label?
107
+ end
108
+
109
+ def test_reads_the_answer_out_of_surrounding_prose
110
+ OpenRouter::Client.raw = "Sure. {\"answer\": true} Hope that helps."
111
+
112
+ assert Analyzer.new("bio").label?
113
+ end
114
+
102
115
  def test_parses_the_answer
103
116
  OpenRouter::Client.answer = false
104
117
 
@@ -0,0 +1,46 @@
1
+ require_relative "test_helper"
2
+ require "bandcamp-discover/scrapers/music"
3
+
4
+ # The album pages are stubbed; what is under test is how the grid's credits
5
+ # travel into the album hashes.
6
+ class MusicTest < Minitest::Test
7
+ Music = BandcampDiscover::Scrapers::Music
8
+
9
+ FakeBrowser = Struct.new(:pages) do
10
+ def new_page = nil
11
+ end
12
+
13
+ FakeAlbum = Struct.new(:url) do
14
+ def scrape = [url, "Title of #{url}", ["drone"], nil]
15
+ end
16
+
17
+ def setup
18
+ @music = Music.new(url: "https://kranky.bandcamp.com/music", browser: FakeBrowser.new, max_tasks: 2)
19
+ end
20
+
21
+ def test_each_album_carries_the_credit_from_its_grid_item
22
+ grid = [
23
+ {url: "https://kranky.bandcamp.com/album/one", credit: "Helen"},
24
+ {url: "https://kranky.bandcamp.com/album/two", credit: nil}
25
+ ]
26
+
27
+ albums, tags = BandcampDiscover::Scrapers::Album.stub(:new, ->(url:, **) { FakeAlbum.new(url) }) do
28
+ Sync { @music.albums(grid) }
29
+ end
30
+
31
+ assert_equal ["Helen", nil], albums.map { _1[:artist] }
32
+ assert_equal ["https://kranky.bandcamp.com/album/one", "https://kranky.bandcamp.com/album/two"], albums.map { _1[:url] }
33
+ assert_equal({"drone" => 1.0}, tags)
34
+ end
35
+
36
+ def test_a_timed_out_album_still_keeps_its_credit
37
+ grid = [{url: "https://kranky.bandcamp.com/album/gone", credit: "Helen"}]
38
+ timed_out = Struct.new(:url) { def scrape = nil }
39
+
40
+ albums, _tags = BandcampDiscover::Scrapers::Album.stub(:new, ->(url:, **) { timed_out.new(url) }) do
41
+ Sync { @music.albums(grid) }
42
+ end
43
+
44
+ assert_equal [{url: nil, title: nil, tags: nil, player_url: nil, artist: "Helen"}], albums
45
+ end
46
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bandcamp-discover
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian RUbisch
@@ -206,6 +206,7 @@ files:
206
206
  - test/analyzer_test.rb
207
207
  - test/default_test.rb
208
208
  - test/discover_test.rb
209
+ - test/music_test.rb
209
210
  - test/roster_test.rb
210
211
  - test/test_helper.rb
211
212
  homepage: https://julianrubisch.at