track_parser 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 41f48fe39a78f9c5bc0852de5826ba1473fd487e
4
+ data.tar.gz: 303e183dc8057a76b3585ea9a048bcb04f6e9c09
5
+ SHA512:
6
+ metadata.gz: f2d9a92b145ee0172a4ab131e0542fe5847b7c47217c86a9a5f393bcdc6ebb576e1b3c6727796ddf338dcc7606fc69f807c20d4c17ae0622515cec96c5626b7c
7
+ data.tar.gz: cb4bdda3a49365c7360f62ecf4d976e42f4c71d0f78de9db2b67dbada973b63866aef0342789cbcb9d6d78e77bbc87799ade5ca4e6b5616569708f0e66b4b6df
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --warnings
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in track_parser.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Alexandre Quintino
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # TrackParser
2
+
3
+ Tries to parse the name of a track (e.g. ArtistA - ABC (ArtistB remix)) and extract metadata from it (e.g. artists = ArtistA, track-name = ABC, remixer = ArtistB)
4
+ It makes a best effort to extract the metadata by passing the track through a set of rules that most tracks follow. If the track does not follow those rules, the results might not be accurate.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'track_parser'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install track_parser
21
+
22
+ ## Usage
23
+
24
+ ### Simple
25
+ ```ruby
26
+ require "track_parser"
27
+ TrackParser::Parser.do("Derek Marin - We've Been Expecting You - Hreno's Deep Pockets Dub")
28
+ => {:artists=>["Derek Marin"], :track_name=>"We've Been Expecting You", :remixer=>"Hreno", :remix_name=>"Deep Pockets Dub"}
29
+ ```
30
+
31
+ ### Structured
32
+ You might know already the artists. In that case you can use:
33
+ ```ruby
34
+ require "track_parser"
35
+ TrackParser::Parser.do(artists: ["Derek Marin], name: "We've Been Expecting You - Hreno's Deep Pockets Dub")
36
+ => {:artists=>["Derek Marin"], :track_name=>"We've Been Expecting You", :remixer=>"Hreno", :remix_name=>"Deep Pockets Dub"}
37
+ ```
38
+
39
+ ## Non-exhaustive list of formats supported (for more check the [tests](https://github.com/alexquintino/track_parser/blob/master/spec/parser_spec.rb))
40
+
41
+ * `<artist> - <track name>`
42
+ * `<artist> - <track name> [-] (<remixer> Remix|Vocal|Dub|Mix)`
43
+ * `<artist> - <track name> (<remixer>'s <remix name>)`
44
+ * `<artist> & <artist> - <track name>`
45
+
46
+ ## Contributing
47
+
48
+ 1. Fork it ( https://github.com/alexquintino/track_parser/fork )
49
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
50
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
51
+ 4. Push to the branch (`git push origin my-new-feature`)
52
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,5 @@
1
+ require "track_parser/version"
2
+ require "track_parser/parser"
3
+
4
+ module TrackParser
5
+ end
@@ -0,0 +1,21 @@
1
+ require_relative "filters/remix_filter"
2
+ require_relative "filters/featuring_filter"
3
+ require_relative "filtered_parts"
4
+
5
+ module TrackParser
6
+ class FilterPipeline
7
+
8
+ FILTERS = [RemixFilter, FeaturingFilter] #order matters currently
9
+
10
+ def self.filter(text)
11
+ size_last_pass = 0
12
+ filtered = nil
13
+ loop do #make several passes until nothing new is found
14
+ filtered = FILTERS.reduce(FilteredParts.new(text)) { |data, filter_class| filter_class.filter(data) }
15
+ break if filtered.parts.size == size_last_pass
16
+ size_last_pass = filtered.parts.size
17
+ end
18
+ return filtered.parts, filtered.text
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ module TrackParser
2
+ class FilteredParts
3
+
4
+ def initialize(text)
5
+ @remaining = text
6
+ @parts = []
7
+ end
8
+
9
+ def text
10
+ @remaining
11
+ end
12
+
13
+ def add_part(type, text)
14
+ @parts << {type: type, text: text}
15
+ end
16
+
17
+ def remove_text(text)
18
+ @remaining = @remaining.gsub(text, "")
19
+ end
20
+
21
+ def parts
22
+ @parts
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,30 @@
1
+ module TrackParser
2
+ class FeaturingFilter
3
+
4
+ def self.filter(data)
5
+ self.new(data).filter
6
+ end
7
+
8
+ def initialize(data)
9
+ @data = data
10
+ end
11
+
12
+ def filter
13
+ if has_featuring?
14
+ featuring_text = regexp.match(@data.text)[:featuring]
15
+ @data.add_part(:featuring, featuring_text)
16
+ @data.remove_text(featuring_text) #remove featuring artists from trackname
17
+ end
18
+ return @data
19
+ end
20
+
21
+ def has_featuring?
22
+ !!regexp.match(@data.text)
23
+ end
24
+
25
+ def regexp
26
+ /(?<featuring>\(?(#{FeaturingNode::VERSIONS_REGEXP})\s.*\)?)/i #find featuring keywords
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,12 @@
1
+ require_relative '../nodes/remix_node'
2
+ require_relative '../nodes/featuring_node'
3
+
4
+ module TrackParser
5
+ class FilterNodesMapping
6
+ FILTERS_NODES_MAPPING = {remix: RemixNode, featuring: FeaturingNode}
7
+
8
+ def self.to_nodes(parts)
9
+ parts.map { |part| FILTERS_NODES_MAPPING[part[:type]].new(part[:text])}
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,41 @@
1
+ require_relative "../nodes/remix_node"
2
+
3
+ module TrackParser
4
+ class RemixFilter
5
+
6
+ def self.filter(data)
7
+ self.new(data).filter
8
+ end
9
+
10
+ def initialize(data)
11
+ @data = data
12
+ end
13
+
14
+ def filter
15
+ if has_remix?
16
+ extracted = content.select {|match| !regexp.match(match).nil?}.first #select first that matches a remix
17
+ @data.add_part(:remix, extracted)
18
+ @data.remove_text "(#{extracted})" #remove remix string from
19
+ end
20
+ return @data
21
+ end
22
+
23
+ def has_remix?
24
+ !!regexp #find remix keywords
25
+ end
26
+
27
+ def content
28
+ text = @data.text
29
+ if text =~ /(\(|\))+/
30
+ text.scan(/\((?<content>.*?)\)/).flatten
31
+ else
32
+ [text]
33
+ end
34
+ end
35
+
36
+ def regexp
37
+ /(?<remix>.*?\b(#{RemixNode::VERSIONS_REGEXP})+)\b/i
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,14 @@
1
+ require_relative 'base_node'
2
+
3
+ module TrackParser
4
+ class ArtistNode < BaseNode
5
+
6
+ def initialize(raw)
7
+ super(:artist, raw)
8
+ end
9
+
10
+ def name
11
+ @raw.strip
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,31 @@
1
+ require_relative 'artist_node'
2
+ require_relative 'base_node'
3
+
4
+ module TrackParser
5
+ class ArtistsNode < BaseNode
6
+
7
+ def initialize(artists)
8
+ super(:artists, artists)
9
+ end
10
+
11
+ def children
12
+ if @raw.is_a? String
13
+ if multiple?
14
+ @raw.split(regex).map { |capture| ArtistNode.new(capture) }
15
+ else
16
+ [ArtistNode.new(@raw)]
17
+ end
18
+ else
19
+ @raw.map { |artist| ArtistNode.new(artist) }
20
+ end
21
+ end
22
+
23
+ def multiple?
24
+ !!regex.match(@raw)
25
+ end
26
+
27
+ def regex
28
+ /\s(?:and|&)\s/i
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ require 'ast'
2
+ require_relative 'empty_node'
3
+
4
+ module TrackParser
5
+ class BaseNode < AST::Node
6
+
7
+ def self.new(text)
8
+ return EmptyNode.new if text.nil? || (text.is_a?(String) && text.strip.empty?)
9
+ super(text)
10
+ end
11
+
12
+ def initialize(type, text)
13
+ super(type, [], {raw: text})
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,7 @@
1
+ require 'ast'
2
+
3
+ class EmptyNode < AST::Node
4
+ def initialize
5
+ super(:empty, [])
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'artist_node'
2
+ require_relative 'base_node'
3
+
4
+ module TrackParser
5
+ class FeaturingNode < BaseNode
6
+
7
+ VERSIONS_REGEXP = ["feat.", "featuring", "ft."].join("|")
8
+
9
+ def initialize(artists)
10
+ super(:featuring, artists)
11
+ end
12
+
13
+ def regexp
14
+ /\(?(#{FeaturingNode::VERSIONS_REGEXP})\s(?<artist>[^\)]*)\)?/i
15
+ end
16
+
17
+ def children
18
+ artist = regexp.match(@raw)[:artist]
19
+ [ArtistsNode.new(artist)]
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ require_relative 'base_node'
2
+
3
+ module TrackParser
4
+ class NameNode < BaseNode
5
+
6
+ def initialize(name)
7
+ super(:name, name)
8
+ end
9
+
10
+ def name
11
+ @raw.strip
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,40 @@
1
+ require_relative 'base_node'
2
+ require_relative 'artists_node'
3
+ require_relative 'name_node'
4
+
5
+ module TrackParser
6
+ class RemixNode < BaseNode
7
+
8
+ VERSIONS_REGEXP = ["remix", "mix", "vocal", "dub", "rework", "edit", "version", "extended", "club", "original"].join("|")
9
+
10
+ def initialize(remix)
11
+ raw = remix.gsub(/(\(|\))/, "") # remove parantheses
12
+ super(:remix, raw)
13
+ end
14
+
15
+ def children
16
+ if has_remix_name?
17
+ nodes = @raw.split(/(?:'|´)s/)
18
+ [ArtistsNode.new(nodes[0]), NameNode.new(nodes[1])]
19
+ else
20
+ [ArtistsNode.new(remixer), NameNode.new(remix_version)]
21
+ end
22
+ end
23
+
24
+ def has_remix_name?
25
+ @raw.include?("'s") || @raw.include?("´s")
26
+ end
27
+
28
+ def remixer
29
+ without_version.strip
30
+ end
31
+
32
+ def remix_version(remix = @raw)
33
+ remix.scan(/(#{VERSIONS_REGEXP})\b/i).flatten.join(" ")
34
+ end
35
+
36
+ def without_version(part = @raw)
37
+ part.gsub(remix_version, "")
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,49 @@
1
+ require_relative 'base_node'
2
+ require_relative 'artists_node'
3
+ require_relative 'trackname_node'
4
+ require_relative 'remix_node'
5
+
6
+ module TrackParser
7
+ class TrackNode < BaseNode
8
+
9
+ def initialize(track)
10
+ raw = replace_parentheses(track)
11
+ super(:track, raw)
12
+ end
13
+
14
+ def children
15
+ if track_sections.size == 1
16
+ raise UnparseableTrack.new("Don't know how to parse a track without \"-\". Track was:#{@raw}")
17
+ else
18
+ nodes = track_sections[2..-1].map do |track_section|
19
+ parts = FilterPipeline.filter(track_section).first
20
+ FilterNodesMapping.to_nodes(parts)
21
+ end
22
+ [ArtistsNode.new(track_sections[0]), TracknameNode.new(track_sections[1])] + nodes.flatten
23
+ end
24
+ end
25
+
26
+ def replace_parentheses(text)
27
+ if text.is_a? String
28
+ text.gsub("[","(").gsub("]",")")
29
+ else
30
+ text[:name] = replace_parentheses(text[:name])
31
+ text
32
+ end
33
+ end
34
+
35
+ def track_sections
36
+ if @raw.is_a? String
37
+ split_sections(@raw)
38
+ else
39
+ [@raw[:artists]] + split_sections(@raw[:name])
40
+ end
41
+ end
42
+
43
+ def split_sections(text)
44
+ text.split(" - ").map(&:strip)
45
+ end
46
+ end
47
+
48
+ class UnparseableTrack < StandardError; end
49
+ end
@@ -0,0 +1,20 @@
1
+ require_relative 'base_node'
2
+ require_relative 'name_node'
3
+ require_relative 'remix_node'
4
+ require_relative 'featuring_node'
5
+ require_relative '../filter_pipeline'
6
+ require_relative '../filters/filter_nodes_mapping'
7
+
8
+ module TrackParser
9
+ class TracknameNode < BaseNode
10
+
11
+ def initialize(trackname)
12
+ super(:trackname, trackname)
13
+ end
14
+
15
+ def children
16
+ parts, remaining_text = FilterPipeline.filter(@raw)
17
+ [NameNode.new(remaining_text)] + FilterNodesMapping.to_nodes(parts)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ require_relative "nodes/track_node"
2
+ require_relative "processor"
3
+
4
+ module TrackParser
5
+ class Parser
6
+
7
+ def self.do(track)
8
+ self.new(track).parse
9
+ end
10
+
11
+ def initialize(track)
12
+ @track = TrackNode.new(track)
13
+ end
14
+
15
+ def parse
16
+ Processor.new.process(@track)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,53 @@
1
+ require "ast"
2
+ require_relative "track"
3
+
4
+ module TrackParser
5
+ class Processor < AST::Processor
6
+
7
+ def initialize
8
+ @track = Track.new
9
+ end
10
+
11
+ def on_track(node)
12
+ hash = process_all(node).reduce({}) { |mem, h| mem.merge(h) }
13
+ @track.add_artists(hash[:artists])
14
+ @track
15
+ end
16
+
17
+ def on_trackname(node)
18
+ hash = process_all(node).reduce({}) { |mem, h| mem.merge(h) }
19
+ @track.add_name(hash[:name])
20
+ {}
21
+ end
22
+
23
+ def on_artists(node)
24
+ artists = process_all(node)
25
+ { artists: artists }
26
+ end
27
+
28
+ def on_artist(node)
29
+ node.name
30
+ end
31
+
32
+ def on_name(node)
33
+ { name: node.name }
34
+ end
35
+
36
+ def on_remix(node)
37
+ hash = process_all(node).reduce({}) { |mem, h| mem.merge(h) }
38
+ @track.add_remixer(hash[:artists])
39
+ @track.add_remix_name(hash[:name])
40
+ {}
41
+ end
42
+
43
+ def on_featuring(node)
44
+ artists = process_all(node).first
45
+ @track.add_featuring(artists[:artists])
46
+ {}
47
+ end
48
+
49
+ def on_empty(node)
50
+ {}
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,49 @@
1
+ module TrackParser
2
+ class Track
3
+
4
+ attr_accessor :artists, :name, :remixer, :remix_name, :featuring
5
+
6
+ def initialize(hash = {})
7
+ @artists = hash[:artists]
8
+ @name = hash[:name]
9
+ @remixer = hash[:remixer]
10
+ @remix_name = hash[:remix_name]
11
+ @featuring = hash[:featuring]
12
+ end
13
+
14
+ def add_artists(artists)
15
+ @artists = artists
16
+ end
17
+
18
+ def add_remixer(remixer)
19
+ return if remixer.nil?
20
+ if @remixer.nil?
21
+ @remixer = remixer
22
+ else
23
+ @remixer.concat(remixer)
24
+ end
25
+ end
26
+
27
+ def add_remix_name(remix_name)
28
+ return if remix_name.nil?
29
+ if @remix_name.nil?
30
+ @remix_name = remix_name
31
+ else
32
+ @remix_name += " " + remix_name
33
+ end
34
+ end
35
+
36
+ def add_name(name)
37
+ @name = name
38
+ end
39
+
40
+ def add_featuring(featured_artists)
41
+ @featuring = featured_artists
42
+ end
43
+
44
+ def to_s
45
+ "artists='#{@artists}' name='#{@name}' remixer='#{@remixer}' remix_name='#{@remix_name}' featuring='#{featuring}'"
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module TrackParser
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,96 @@
1
+ describe TrackParser::Parser do
2
+
3
+ tracks = {
4
+ "SIS - Orgsa" =>
5
+ { artists: ["SIS"], name: "Orgsa", remixer: nil, remix_name: nil},
6
+ "Roy Davis Jr - About Love (Pezzner Remix)" =>
7
+ { artists: ["Roy Davis Jr"], name: "About Love", remixer: ["Pezzner"], remix_name: "Remix" },
8
+ "Julien Perez & Octavio Camino - Parada Maya" =>
9
+ { artists: ["Julien Perez", "Octavio Camino"], name: "Parada Maya", remixer: nil, remix_name: nil},
10
+ "Kollektiv Turmstrasse - Ordinary (Lake People's Circle Motive Remix)" =>
11
+ { artists: ["Kollektiv Turmstrasse"], name: "Ordinary", remixer: ["Lake People"], remix_name: "Circle Motive Remix" },
12
+ "Derek Marin - We've Been Expecting You - Hreno´s Deep Pockets Dub" =>
13
+ { artists: ["Derek Marin"], name: "We've Been Expecting You", remixer: ["Hreno"], remix_name: "Deep Pockets Dub" },
14
+ "Umek & Uto Karem - Crossing the Lines - Original Mix" =>
15
+ { artists: ["Umek", "Uto Karem"], name: "Crossing the Lines", remixer: nil, remix_name: "Original Mix" },
16
+ "Noir & Fraser Owen - &U - Mendo and Danny Serrano Remix" =>
17
+ { artists: ["Noir", "Fraser Owen"], name: "&U", remixer: ["Mendo", "Danny Serrano"], remix_name: "Remix"},
18
+ "Plastikman - Spastik - Dubfire Rework" =>
19
+ { artists: ["Plastikman"], name: "Spastik", remixer: ["Dubfire"], remix_name: "Rework" },
20
+ "Alex Under - El Encuentro - Richie Hawtin Edit" =>
21
+ { artists: ['Alex Under'], name: 'El Encuentro', remixer: ["Richie Hawtin"], remix_name: "Edit" },
22
+ "Gorge - Erotic Soul feat. The Writers Poet - Original Mix" =>
23
+ { artists: ["Gorge"], name: "Erotic Soul", featuring: ["The Writers Poet"], remixer: nil, remix_name: "Original Mix"},
24
+ "John Talabot & Pional - Destiny (Feat. Pional)" =>
25
+ { artists: ["John Talabot", "Pional"], name: "Destiny", featuring: ["Pional"], remixer: nil, remix_name: nil},
26
+ "Ornette - Crazy - Nôze Remix - Extended Club Version" =>
27
+ { artists: ["Ornette"], name: "Crazy", remixer: ["Nôze"], remix_name: "Remix Extended Club Version" },
28
+ "2 Guys in Venice & Spiller & Digitalism - Encore - Spiller & 2 Guys In Venice Remix" =>
29
+ { artists: ["2 Guys in Venice", "Spiller", "Digitalism"], name: "Encore", remixer: ["Spiller", "2 Guys In Venice"], remix_name: "Remix" },
30
+ "Subb-an - Take You Back (ft. Beckford)" =>
31
+ { artists: ["Subb-an"], name: "Take You Back", featuring: ["Beckford"] },
32
+ "Aki Bergen & Pezzner & Terry Grant - Tarareando - Vocal Mix" =>
33
+ { artists: ["Aki Bergen", "Pezzner", "Terry Grant"], name: "Tarareando", remixer: nil, remix_name: "Vocal Mix" },
34
+ "Jay Haze & Laila Tov - I Wait For You - Original" =>
35
+ { artists: ["Jay Haze", "Laila Tov"], name: "I Wait For You", remixer: nil, remix_name: "Original"},
36
+ "DJ T. - City Life - feat. Cari Golden [Maceo Plex Remix]" =>
37
+ { artists: ["DJ T."], name: "City Life", remixer: ["Maceo Plex"], remix_name: "Remix", featuring: ["Cari Golden"]},
38
+ "Fritz Kalkbrenner - Right in the Dark - Henrik Schwarz Remix - Chopstick & Johnjon Edit" =>
39
+ { artists: ["Fritz Kalkbrenner"], name: "Right in the Dark", remixer: ["Henrik Schwarz", "Chopstick", "Johnjon"], remix_name: "Remix Edit"}
40
+ }
41
+
42
+ tracks_structured = [
43
+ {track: { artists: ["Sailor & I"], name: "Tough Love - Aril Brikha Remix" }, result:
44
+ { artists: ["Sailor & I"], name: "Tough Love", remixer: ["Aril Brikha"], remix_name: "Remix"}}
45
+ ]
46
+
47
+ let(:parsed_track) { TrackParser::Parser.do(track) }
48
+
49
+ tracks.keys.each do |track|
50
+ context "#{track}" do
51
+ let(:track) { track }
52
+
53
+ it "returns the artist correctly" do
54
+ expect(parsed_track.artists).to eq(tracks[track][:artists])
55
+ end
56
+
57
+ it "returns the track name correctly" do
58
+ expect(parsed_track.name).to eq(tracks[track][:name])
59
+ end
60
+
61
+ it "returns the remixer correctly" do
62
+ expect(parsed_track.remixer).to eq(tracks[track][:remixer])
63
+ end
64
+
65
+ it "returns the remix name correctly" do
66
+ expect(parsed_track.remix_name).to eq(tracks[track][:remix_name])
67
+ end
68
+
69
+ it "returns the featured artists correctly" do
70
+ expect(parsed_track.featuring).to eq(tracks[track][:featuring])
71
+ end
72
+ end
73
+ end
74
+
75
+ context "invalid track" do
76
+ let(:track) { "Invalid Track" }
77
+
78
+ it "throws an exception when the track doesn't have \"-\"" do
79
+ expect{TrackParser::Parser.do(track)}.to raise_error(TrackParser::UnparseableTrack)
80
+ end
81
+ end
82
+
83
+ context "Hash as input" do
84
+ let(:track) { tracks_structured.first[:track] }
85
+ let(:result) { tracks_structured.first[:result]}
86
+
87
+ it "returns all the correct info" do
88
+ expect(parsed_track.artists).to eq(result[:artists])
89
+ expect(parsed_track.name).to eq(result[:name])
90
+ expect(parsed_track.remixer).to eq(result[:remixer])
91
+ expect(parsed_track.remix_name).to eq(result[:remix_name])
92
+ expect(parsed_track.featuring).to eq(result[:featuring])
93
+ end
94
+ end
95
+
96
+ end
@@ -0,0 +1,11 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'track_parser'
5
+
6
+ RSpec.configure do |config|
7
+
8
+ config.order = :random
9
+
10
+ Kernel.srand config.seed
11
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'track_parser/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "track_parser"
8
+ spec.version = TrackParser::VERSION
9
+ spec.authors = ["Alexandre Quintino"]
10
+ spec.email = ["amsquintino@gmail.com"]
11
+ spec.summary = %q{Tries to parse the name of a track (eg. ArtistA - ABC (ArtistB remix)) and extract metadata from it (eg. artists = ArtistA, track-name = ABC, remixer = ArtistB)}
12
+ spec.description = %q{Tries to parse the name of a track (eg. ArtistA - ABC (ArtistB remix)) and extract metadata from it (eg. artists = ArtistA, track-name = ABC, remixer = ArtistB)}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "pry"
25
+ spec.add_runtime_dependency "ast"
26
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: track_parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Alexandre Quintino
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: ast
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Tries to parse the name of a track (eg. ArtistA - ABC (ArtistB remix))
84
+ and extract metadata from it (eg. artists = ArtistA, track-name = ABC, remixer =
85
+ ArtistB)
86
+ email:
87
+ - amsquintino@gmail.com
88
+ executables: []
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - ".gitignore"
93
+ - ".rspec"
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - lib/track_parser.rb
99
+ - lib/track_parser/filter_pipeline.rb
100
+ - lib/track_parser/filtered_parts.rb
101
+ - lib/track_parser/filters/featuring_filter.rb
102
+ - lib/track_parser/filters/filter_nodes_mapping.rb
103
+ - lib/track_parser/filters/remix_filter.rb
104
+ - lib/track_parser/nodes/artist_node.rb
105
+ - lib/track_parser/nodes/artists_node.rb
106
+ - lib/track_parser/nodes/base_node.rb
107
+ - lib/track_parser/nodes/empty_node.rb
108
+ - lib/track_parser/nodes/featuring_node.rb
109
+ - lib/track_parser/nodes/name_node.rb
110
+ - lib/track_parser/nodes/remix_node.rb
111
+ - lib/track_parser/nodes/track_node.rb
112
+ - lib/track_parser/nodes/trackname_node.rb
113
+ - lib/track_parser/parser.rb
114
+ - lib/track_parser/processor.rb
115
+ - lib/track_parser/track.rb
116
+ - lib/track_parser/version.rb
117
+ - spec/parser_spec.rb
118
+ - spec/spec_helper.rb
119
+ - track_parser.gemspec
120
+ homepage: ''
121
+ licenses:
122
+ - MIT
123
+ metadata: {}
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubyforge_project:
140
+ rubygems_version: 2.4.5
141
+ signing_key:
142
+ specification_version: 4
143
+ summary: Tries to parse the name of a track (eg. ArtistA - ABC (ArtistB remix)) and
144
+ extract metadata from it (eg. artists = ArtistA, track-name = ABC, remixer = ArtistB)
145
+ test_files:
146
+ - spec/parser_spec.rb
147
+ - spec/spec_helper.rb