cinch-bgg 0.0.2 → 0.0.3

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.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/cinch-bgg.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "cinch-bgg"
5
- s.version = "0.0.2"
5
+ s.version = "0.0.3"
6
6
  s.platform = Gem::Platform::RUBY
7
7
  s.authors = ["Caitlin Woodward"]
8
8
  s.email = ["caitlin@caitlinwoodward.me"]
@@ -10,8 +10,6 @@ Gem::Specification.new do |s|
10
10
  s.summary = %q{Gives Cinch IRC bots access to BoardGameGeek data}
11
11
  s.description = %q{Gives Cinch IRC bots access to BoardGameGeek data}
12
12
 
13
- s.rubyforge_project = "cinch-bgg"
14
-
15
13
  s.add_dependency("cinch", "~> 2.0")
16
14
  s.add_dependency("nokogiri", "~> 1.5.2")
17
15
 
@@ -7,25 +7,74 @@ module Cinch
7
7
  class Bgg
8
8
  include Cinch::Plugin
9
9
 
10
- match /bgg (.+)/i, method: :bgg
11
- match /bgguser (.+)/i, method: :bgguser
10
+ USERS_FILE = "users_list"
11
+ USERS_SUBDIR = "users"
12
+ GAMES_SUBDIR = "games"
13
+
14
+ match /bgg (.+)/i, method: :bgg
15
+ match /bggme/i, method: :bggself
16
+ match /bgguser (.+)/i, method: :bgguser
17
+ match /bgguser -u (.+)/i, method: :bggactualuser
18
+
19
+ match /link_bgg (.+)/i, method: :link_to_bgg
20
+
21
+ match /whohas (.+)/i, method: :who_has_game
22
+
23
+ def initialize(*args)
24
+ super
25
+
26
+ @data_dir = config[:data_dir]
27
+ @community = load_community
28
+ end
12
29
 
13
30
  def bgg(m, title)
14
- results = search_bgg(title)
15
- if results == "not found"
16
- m.reply "#{m.user.nick}: \"#{title}\" not found"
17
- elsif results == "too big"
18
- m.reply "#{m.user.nick}: \"#{title}\" was too broad of a search term"
19
- else
20
- game = results.sort{ |x, y| x.rank <=> y.rank }.first
31
+ game = search_bgg(m, title)
32
+ unless game.nil?
21
33
  m.reply "#{m.user.nick}: #{game.name} (#{game.year}) - #{game.rating} - Rank: #{game.game_rank} - Designer: #{game.designers.join(", ")} - Mechanics: #{game.mechanics.join(", ")} - " <<
22
34
  "http://boardgamegeek.com/boardgame/#{game.id}"
23
35
  end
24
36
  end
25
37
 
26
- def bgguser(m, name)
27
- user = search_for_user(name)
28
- m.reply "#{m.user.nick}: #{user.name} - Collection: #{user.collection.size} - Top 5: #{user.top_games.first(5).join(", ")} - http://boardgamegeek.com/user/#{user.name}"
38
+ def bgguser(m, nick)
39
+ unless nick.start_with?("-u ")
40
+ if self.in_community?(nick)
41
+ name = self.find_bgg_by_irc(nick)
42
+ user = search_for_user(name)
43
+ m.reply "#{user.name} - Collection: #{user.collection.size} - Top 5: #{user.top_games.first(5).join(", ")} - http://boardgamegeek.com/user/#{user.name}", true
44
+ else
45
+ m.reply "There's no \"#{nick}\" in the community. To link yourself and join the community, \"!link_bgg bgg_username\". To search by actual bgg username, \"!bgguser -u bgg_username\".", true
46
+ end
47
+ end
48
+ end
49
+
50
+ def bggself(m)
51
+ self.bgguser(m.user.nick)
52
+ end
53
+
54
+ def bggactualuser(m, nick)
55
+ user = search_for_user(nick)
56
+ m.reply "#{user.name} - Collection: #{user.collection.size} - Top 5: #{user.top_games.first(5).join(", ")} - http://boardgamegeek.com/user/#{user.name}", true
57
+ end
58
+
59
+ def link_to_bgg(m, username)
60
+ @community[m.user.nick] = username
61
+ File.open("#{@data_dir}#{USERS_FILE}", 'w') do |file|
62
+ @community.each do |irc_nick, bgg_name|
63
+ file.write("#{irc_nick},#{bgg_name}\n")
64
+ end
65
+ end
66
+ m.reply "You are now added to the community!", true
67
+ end
68
+
69
+ def who_has_game(m, title)
70
+ game = search_bgg(m, title)
71
+ unless game.nil?
72
+ community = @community.dup
73
+ community.each{ |irc, bgg| community[irc] = search_for_user(bgg, { :id => game.id, :use_cache => true }) }
74
+
75
+ community.keep_if{ |irc, user| user.collection.include? game.id.to_s }
76
+ m.reply "Owning \"#{game.name}\": #{community.keys.join(", ")}", true
77
+ end
29
78
  end
30
79
 
31
80
  #--------------------------------------------------------------------------------
@@ -33,43 +82,77 @@ module Cinch
33
82
  #--------------------------------------------------------------------------------
34
83
  protected
35
84
 
36
- def search_bgg(search_string)
85
+ def search_bgg(m, search_string)
37
86
  search_results_xml = Nokogiri::XML(open("http://boardgamegeek.com/xmlapi2/search?query=#{search_string.gsub(" ", "%20")}&type=boardgame&exact=1").read)
38
87
  if search_results_xml.css('items')[0]['total'] == "0"
39
88
  search_results_xml = Nokogiri::XML(open("http://boardgamegeek.com/xmlapi2/search?query=#{search_string.gsub(" ", "%20")}&type=boardgame").read)
40
89
  end
41
90
  search_results = search_results_xml.css('item').map { |i| i['id'].to_i }
42
91
 
43
- # this is dumb, find a better way
44
92
  if search_results.empty?
45
- response = "not found"
93
+ m.reply "\"#{search_string}\" not found", true
46
94
  elsif search_results.size > 50
47
- response = "too big"
95
+ m.reply "\"#{search_string}\" was too broad of a search term", true
48
96
  else
49
- response = search_results.map do |id|
97
+ results = search_results.map do |id|
50
98
  Game.new(id, get_info_for_game(id))
51
99
  end
100
+ response = results.sort{ |x, y| x.rank <=> y.rank }.first
52
101
  end
53
102
  response
54
103
  end
55
104
 
56
105
  def get_info_for_game(game_id)
57
- unless File.exists?("data/#{game_id}.xml")
58
- open("data/games/#{game_id}.xml", "wb") do |file|
106
+ unless File.exists?("#{@data_dir}#{GAMES_SUBDIR}/#{game_id}.xml")
107
+ open("#{@data_dir}#{GAMES_SUBDIR}/#{game_id}.xml", "wb") do |file|
59
108
  open("http://boardgamegeek.com/xmlapi2/thing?id=#{game_id}&stats=1") do |uri|
60
109
  file.write(uri.read)
61
110
  end
62
111
  end
63
112
  end
64
- Nokogiri::XML(File.open("data/games/#{game_id}.xml"))
113
+ Nokogiri::XML(File.open("#{@data_dir}#{GAMES_SUBDIR}/#{game_id}.xml"))
65
114
  end
66
115
 
67
- def search_for_user(name)
68
- user_xml = Nokogiri::XML(open("http://boardgamegeek.com/xmlapi2/user?name=#{name}&hot=1&top=1").read)
69
- collection_xml = Nokogiri::XML(open("http://boardgamegeek.com/xmlapi2/collection?username=#{name}&own=1").read)
116
+ def search_for_user(name, collection_options = {})
117
+ use_cache = collection_options[:use_cache] || false
118
+ game_id = collection_options[:id] || nil
119
+
120
+ search_game_id_str = (game_id.nil? ? "" : "&id=#{game_id}")
121
+ user_xml = Nokogiri::XML(open("http://boardgamegeek.com/xmlapi2/user?name=#{name}&hot=1&top=1#{search_game_id_str}").read)
122
+ collection_xml = get_collection_data_for_user(name, use_cache)
70
123
  User.new(name, user_xml, collection_xml)
71
124
  end
72
125
 
126
+ def get_collection_data_for_user(name, using_cache = false)
127
+ file_url = "#{@data_dir}#{USERS_SUBDIR}/#{name}.xml"
128
+ unless using_cache
129
+ open(file_url, "w") do |file|
130
+ open("http://boardgamegeek.com/xmlapi2/collection?username=#{name}&own=1&stats=1") do |uri|
131
+ file.write(uri.read)
132
+ end
133
+ end
134
+ end
135
+ Nokogiri::XML(File.open(file_url))
136
+ end
137
+
138
+ def load_community
139
+ users_file = File.open("#{@data_dir}#{USERS_FILE}")
140
+ users = {}
141
+ users_file.lines.each do |line|
142
+ nicks = line.gsub("\n", "").split(",")
143
+ users[nicks.first] = nicks.last
144
+ end
145
+ users
146
+ end
147
+
148
+ def find_bgg_by_irc(irc_nick)
149
+ @community[irc_nick]
150
+ end
151
+
152
+ def in_community?(irc_nick)
153
+ self.find_bgg_by_irc(irc_nick) != nil
154
+ end
155
+
73
156
  end
74
157
 
75
158
  class Game
@@ -77,7 +160,7 @@ module Cinch
77
160
 
78
161
  NOT_RANKED_RANK = 10001
79
162
 
80
- def initialize(id, xml)
163
+ def initialize(id, xml)
81
164
  self.id = id
82
165
  self.rating = xml.css('statistics ratings average')[0]['value'].to_f
83
166
  self.rank = xml.css('statistics ratings ranks rank')[0]["value"]
@@ -111,7 +194,12 @@ module Cinch
111
194
  self.hot_games = user_xml.css("hot item").map{ |g| g["name"] }
112
195
  self.collection = {}
113
196
  collection_xml.css("items item").each do |g|
114
- self.collection[g["objectid"]] = g.css("name")[0].content
197
+ self.collection[g["objectid"]] = {}
198
+ self.collection[g["objectid"]]["name"] = g.css("name")[0].content
199
+ self.collection[g["objectid"]]["for_trade"] = g.css("status fortrade")[0]
200
+ self.collection[g["objectid"]]["want"] = g.css("status want")[0]
201
+ self.collection[g["objectid"]]["plays"] = g.css("numplays")[0].content.to_i
202
+ self.collection[g["objectid"]]["ratings"] = g.css("stats")[0].css("rating")[0]['value']
115
203
  end
116
204
  end
117
205
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cinch-bgg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-16 00:00:00.000000000Z
12
+ date: 2012-10-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cinch
16
- requirement: &70356809562460 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '2.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70356809562460
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '2.0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: nokogiri
27
- requirement: &70356809561980 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ~>
@@ -32,7 +37,12 @@ dependencies:
32
37
  version: 1.5.2
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *70356809561980
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.5.2
36
46
  description: Gives Cinch IRC bots access to BoardGameGeek data
37
47
  email:
38
48
  - caitlin@caitlinwoodward.me
@@ -40,6 +50,7 @@ executables: []
40
50
  extensions: []
41
51
  extra_rdoc_files: []
42
52
  files:
53
+ - .gitignore
43
54
  - Gemfile
44
55
  - README.md
45
56
  - cinch-bgg.gemspec
@@ -63,8 +74,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
63
74
  - !ruby/object:Gem::Version
64
75
  version: '0'
65
76
  requirements: []
66
- rubyforge_project: cinch-bgg
67
- rubygems_version: 1.8.6
77
+ rubyforge_project:
78
+ rubygems_version: 1.8.24
68
79
  signing_key:
69
80
  specification_version: 3
70
81
  summary: Gives Cinch IRC bots access to BoardGameGeek data