duolingo_personal_data 0.1.0 → 0.2.0

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: 90f5ce55daf9c0dddbab10bd13f36d5344e9f9cc561d5e543fa196dd2a65e545
4
- data.tar.gz: 02f08b1c773a9fb5315f5353cef2389f41dc04644d89a5c55cba3f8cdc76d1ca
3
+ metadata.gz: f1b983dd563cc933d3a549d692b2e454cba4fd0413132d93761bc874a425af91
4
+ data.tar.gz: '0497cd092c7b84103da7c1b3f9a4293386cbf157f164d8c8a5d5f9063b6daebf'
5
5
  SHA512:
6
- metadata.gz: 90bce41f9fdaf3f3d8f514929fd66d870facefe07c965d42f9c2c8c55e38b426f28fb883075462d40fcc1703f00a9af21542f9557aeaca7e3deeff557300ab40
7
- data.tar.gz: cd9de28d5e5fb51e60b87663f3fc8e0fc597074b7b0f2734b342f12985ea9829285973908db8c27c16c37b68fdaa50d64973ec4dcc2f3ca972a80a23bfd5b20e
6
+ metadata.gz: b465b8f05db11c503afa124ac232e1075bf2a7485449a5066b045b11ca77a7755000e340543f62046f82f0ffbef7c3d6872682e35e594f680e352de26ff3ff8e
7
+ data.tar.gz: 981c6cacd459875817f8e3cd10dc86c9ea209afccd83c05e2a231b41dd51e9ae1143c609811f5c7948de1968c6911896357ce878630ccb6efe73451c3140fae4
data/.rubocop.yml CHANGED
@@ -1,19 +1,19 @@
1
1
  inherit_from: .rubocop_todo.yml
2
2
 
3
+ require:
4
+ - rubocop-rake
5
+
3
6
  AllCops:
4
7
  TargetRubyVersion: 2.6
5
8
  NewCops: enable
9
+ SuggestExtensions: false # RuboCop suggests extensions even if it's installed
10
+ DisabledByDefault: true
6
11
 
7
12
  Style/StringLiterals:
8
13
  Enabled: true
9
- EnforcedStyle: double_quotes
10
14
 
11
15
  Style/StringLiteralsInInterpolation:
12
16
  Enabled: true
13
- EnforcedStyle: double_quotes
14
-
15
- Layout/LineLength:
16
- Enabled: false
17
17
 
18
18
  Style/FrozenStringLiteralComment:
19
19
  Enabled: true
data/.rubocop_todo.yml CHANGED
@@ -1,50 +1,7 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2023-03-19 06:13:02 UTC using RuboCop version 1.10.0.
3
+ # on 2023-06-18 09:30:04 UTC using RuboCop version 1.48.1.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
-
9
- # Offense count: 2
10
- # Configuration parameters: IgnoredMethods, CountRepeatedAttributes.
11
- Metrics/AbcSize:
12
- Max: 34
13
-
14
- # Offense count: 1
15
- # Configuration parameters: CountComments, CountAsOne.
16
- Metrics/ClassLength:
17
- Max: 114
18
-
19
- # Offense count: 1
20
- # Configuration parameters: IgnoredMethods.
21
- Metrics/CyclomaticComplexity:
22
- Max: 11
23
-
24
- # Offense count: 2
25
- # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
26
- Metrics/MethodLength:
27
- Max: 18
28
-
29
- # Offense count: 1
30
- # Configuration parameters: IgnoredMethods.
31
- Metrics/PerceivedComplexity:
32
- Max: 11
33
-
34
- # Offense count: 12
35
- Style/Documentation:
36
- Exclude:
37
- - 'spec/**/*'
38
- - 'test/**/*'
39
- - 'lib/duolingo_personal_data/auth_data.rb'
40
- - 'lib/duolingo_personal_data/avatar_images.rb'
41
- - 'lib/duolingo_personal_data/blast_emails.rb'
42
- - 'lib/duolingo_personal_data/friends_follow.rb'
43
- - 'lib/duolingo_personal_data/inventory.rb'
44
- - 'lib/duolingo_personal_data/languages.rb'
45
- - 'lib/duolingo_personal_data/leaderboards.rb'
46
- - 'lib/duolingo_personal_data/notify_data.rb'
47
- - 'lib/duolingo_personal_data/profile.rb'
48
- - 'lib/duolingo_personal_data/stories.rb'
49
- - 'lib/duolingo_personal_data/story_completions.rb'
50
- - 'lib/duolingo_personal_data/teacher_privacy_settings.rb'
data/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ### Added
6
+
7
+ * Direcotry class (`DuolingoPersonalData::Direcotry`)
8
+
9
+ ### Changed, Removed, Fixed
10
+
11
+ * Changed to not delegate most Array and Hash methods
12
+ * Update RBS
13
+
14
+ ### Others
15
+
16
+ * Set RuboCop config to disable by default
17
+ * Lint with RuboCop
18
+
5
19
  ## [0.1.0] - 2023-03-19
6
20
 
7
21
  Initial release.
data/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- gem "rake", "~> 13.0"
6
- gem "rubocop", "~> 1.21"
7
- gem "test-unit", "~> 3.0"
5
+ gem 'rake', '~> 13.0'
6
+ gem 'rubocop', '~> 1.21'
7
+ gem 'test-unit', '~> 3.0'
data/Rakefile CHANGED
@@ -1,22 +1,24 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
3
 
4
4
  Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
5
+ t.libs << 'test'
6
+ t.libs << 'lib'
7
+ t.test_files = FileList['test/**/*_test.rb']
8
8
  end
9
9
 
10
- require "rubocop/rake_task"
10
+ require 'rubocop/rake_task'
11
11
 
12
12
  RuboCop::RakeTask.new
13
13
 
14
14
  task default: %i[test rubocop]
15
15
 
16
+ desc 'serve generated API documentation'
16
17
  task :serve do
17
- sh "ruby -run -e httpd doc"
18
+ sh 'ruby -run -e httpd doc'
18
19
  end
19
20
 
21
+ desc 'generate type signatures'
20
22
  task :sig do
21
- sh "typeprof lib/**/* > sig/duolingo_personal_data.rbs"
23
+ sh 'typeprof lib/**/* > sig/duolingo_personal_data.rbs'
22
24
  end
@@ -1,20 +1,20 @@
1
- require_relative "lib/duolingo_personal_data/version"
1
+ require_relative 'lib/duolingo_personal_data/version'
2
2
 
3
3
  Gem::Specification.new do |spec|
4
- spec.name = "duolingo_personal_data"
4
+ spec.name = 'duolingo_personal_data'
5
5
  spec.version = DuolingoPersonalData::VERSION
6
- spec.authors = ["gemmaro"]
7
- spec.email = ["gemmaro.dev@gmail.com"]
6
+ spec.authors = ['gemmaro']
7
+ spec.email = ['gemmaro.dev@gmail.com']
8
8
 
9
- spec.summary = "Library for Duolingo personal data."
10
- spec.description = "Duolingo Personal Data gem is for loading Duolingo Personal Data, which can be acquired at <https://drive-thru.duolingo.com/>."
11
- spec.homepage = "https://gitlab.com/gemmaro/ruby-duolingo-personal-data"
12
- spec.license = "Apache-2.0"
13
- spec.required_ruby_version = ">= 2.6.0"
9
+ spec.summary = 'Library for Duolingo personal data'
10
+ spec.description = 'Duolingo Personal Data gem is for loading Duolingo Personal Data, which can be acquired at https://drive-thru.duolingo.com/.'
11
+ spec.homepage = 'https://gitlab.com/gemmaro/ruby-duolingo-personal-data'
12
+ spec.license = 'Apache-2.0'
13
+ spec.required_ruby_version = '>= 2.6.0'
14
14
 
15
- spec.metadata["homepage_uri"] = spec.homepage
16
- spec.metadata["source_code_uri"] = spec.homepage
17
- spec.metadata["changelog_uri"] = "#{spec.homepage}/-/blob/main/CHANGELOG.md"
15
+ spec.metadata['homepage_uri'] = spec.homepage
16
+ spec.metadata['source_code_uri'] = spec.homepage
17
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/-/blob/main/CHANGELOG.md"
18
18
 
19
19
  spec.files = Dir.chdir(__dir__) do
20
20
  `git ls-files -z`.split("\x0").reject do |f|
@@ -22,5 +22,6 @@ Gem::Specification.new do |spec|
22
22
  end
23
23
  end
24
24
 
25
- spec.require_paths = ["lib"]
25
+ spec.require_paths = ['lib']
26
+ spec.metadata['rubygems_mfa_required'] = 'true'
26
27
  end
@@ -1,4 +1,4 @@
1
- require "csv"
1
+ require 'csv'
2
2
 
3
3
  module DuolingoPersonalData
4
4
  class AuthData
@@ -7,29 +7,29 @@ module DuolingoPersonalData
7
7
  end
8
8
 
9
9
  def user_account_name
10
- @user_account_name ||= value_from_property("User Account Name")
10
+ @user_account_name ||= value_from_property('User Account Name')
11
11
  end
12
12
 
13
13
  def email_address
14
- @email_address ||= value_from_property("Email Address")
14
+ @email_address ||= value_from_property('Email Address')
15
15
  end
16
16
 
17
17
  def last_update_timestamp
18
- @last_update_timestamp ||= value_from_property("Last Update Timestamp")
18
+ @last_update_timestamp ||= value_from_property('Last Update Timestamp')
19
19
  end
20
20
 
21
21
  def last_login_attempt_timestamp
22
- @last_login_attempt_timestamp ||= value_from_property("Last Login Attempt Timestamp")
22
+ @last_login_attempt_timestamp ||= value_from_property('Last Login Attempt Timestamp')
23
23
  end
24
24
 
25
25
  def last_authentication_key_refresh_timestamp
26
- @last_authentication_key_refresh_timestamp ||= value_from_property("Last Authentication Key Refresh Timestamp")
26
+ @last_authentication_key_refresh_timestamp ||= value_from_property('Last Authentication Key Refresh Timestamp')
27
27
  end
28
28
 
29
29
  private
30
30
 
31
31
  def value_from_property(property_name)
32
- table.find { |row| row["Property"] == property_name }["Value"]
32
+ table.find { |row| row['Property'] == property_name }['Value']
33
33
  end
34
34
 
35
35
  def table
@@ -1,6 +1,6 @@
1
- require "csv"
2
- require "uri"
3
- require "forwardable"
1
+ require 'csv'
2
+ require 'uri'
3
+ require 'forwardable'
4
4
 
5
5
  module DuolingoPersonalData
6
6
  class AvatarImages
@@ -9,12 +9,12 @@ module DuolingoPersonalData
9
9
  end
10
10
 
11
11
  extend Forwardable
12
- def_delegators :urls, *(Array.instance_methods - [:object_id])
12
+ def_delegators :urls, :to_a, :first, :size # TODO: Add more as needed
13
13
 
14
14
  private
15
15
 
16
16
  def urls
17
- @urls ||= table.map { |row| URI(row["URLs"]) }
17
+ @urls ||= table.map { |row| URI(row['URLs']) }
18
18
  end
19
19
 
20
20
  def table
@@ -1,5 +1,5 @@
1
- require "csv"
2
- require "time"
1
+ require 'csv'
2
+ require 'time'
3
3
 
4
4
  module DuolingoPersonalData
5
5
  class BlastEmails
@@ -8,60 +8,60 @@ module DuolingoPersonalData
8
8
  end
9
9
 
10
10
  def email_address
11
- @email_address ||= value_from_property("email_address")
11
+ @email_address ||= value_from_property('email_address')
12
12
  end
13
13
 
14
14
  def ui_language
15
- @ui_language ||= value_from_property("ui_language")
15
+ @ui_language ||= value_from_property('ui_language')
16
16
  end
17
17
 
18
18
  def learning_language
19
- @learning_language ||= value_from_property("learning_language")
19
+ @learning_language ||= value_from_property('learning_language')
20
20
  end
21
21
 
22
22
  def enabled
23
- @enabled ||= boolean_value_from_property("enabled")
23
+ @enabled ||= boolean_value_from_property('enabled')
24
24
  end
25
25
 
26
26
  def announcement
27
- @announcement ||= boolean_value_from_property("announcement")
27
+ @announcement ||= boolean_value_from_property('announcement')
28
28
  end
29
29
 
30
30
  def creation_datetime
31
- @creation_datetime ||= time_value_from_property("creation_datetime")
31
+ @creation_datetime ||= time_value_from_property('creation_datetime')
32
32
  end
33
33
 
34
34
  def last_session
35
- @last_session ||= time_value_from_property("last_session")
35
+ @last_session ||= time_value_from_property('last_session')
36
36
  end
37
37
 
38
38
  def trial_user
39
- @trial_user ||= boolean_value_from_property("trial_user")
39
+ @trial_user ||= boolean_value_from_property('trial_user')
40
40
  end
41
41
 
42
42
  def country
43
- @country ||= value_from_property("country")
43
+ @country ||= value_from_property('country')
44
44
  end
45
45
 
46
46
  def client
47
- @client ||= value_from_property("client")
47
+ @client ||= value_from_property('client')
48
48
  end
49
49
 
50
50
  def schools_role
51
- @schools_role ||= integer_value_from_property("schools_role")
51
+ @schools_role ||= integer_value_from_property('schools_role')
52
52
  end
53
53
 
54
54
  private
55
55
 
56
56
  def value_from_property(property_name)
57
- table.find { |row| row["property"] == property_name }["value"]
57
+ table.find { |row| row['property'] == property_name }['value']
58
58
  end
59
59
 
60
60
  def boolean_value_from_property(property_name)
61
61
  value = value_from_property(property_name)
62
62
  case value
63
- when "0" then false
64
- when "1" then true
63
+ when '0' then false
64
+ when '1' then true
65
65
  else
66
66
  raise Error, "cannot interpret #{value.inspect} as boolean"
67
67
  end
@@ -69,7 +69,7 @@ module DuolingoPersonalData
69
69
 
70
70
  def time_value_from_property(property_name)
71
71
  value = value_from_property(property_name)
72
- Time.strptime(value, "%Y-%m-%d %T")
72
+ Time.strptime(value, '%Y-%m-%d %T')
73
73
  end
74
74
 
75
75
  def integer_value_from_property(property_name)
@@ -0,0 +1,55 @@
1
+ module DuolingoPersonalData
2
+ class Directory
3
+ def initialize(path)
4
+ @path = path
5
+ end
6
+
7
+ def auth_data
8
+ @auth_data ||= AuthData.new(File.join(@path, 'auth_data.csv'))
9
+ end
10
+
11
+ def avatar_images
12
+ @avatar_images ||= AvatarImages.new(File.join(@path, 'avatar_images.csv'))
13
+ end
14
+
15
+ def blast_emails
16
+ @blast_emails ||= BlastEmails.new(File.join(@path, 'duolingo-blast-emails.csv'))
17
+ end
18
+
19
+ def notify_data
20
+ @notify_data ||= NotifyData.new(File.join(@path, 'duolingo-notify-data.csv'))
21
+ end
22
+
23
+ def friends_follow
24
+ @friends_follow ||= FriendsFollow.new(File.join(@path, 'friends-follow.csv'))
25
+ end
26
+
27
+ def inventory
28
+ @inventory ||= Inventory.new(File.join(@path, 'inventory.csv'))
29
+ end
30
+
31
+ def languages
32
+ @languages ||= Languages.new(File.join(@path, 'languages.csv'))
33
+ end
34
+
35
+ def leaderboards
36
+ @leaderboards ||= Leaderboards.new(File.join(@path, 'leaderboards.csv'))
37
+ end
38
+
39
+ def profile
40
+ @profile ||= Profile.new(File.join(@path, 'profile.csv'))
41
+ end
42
+
43
+ def stories
44
+ @stories ||= Stories.new(File.join(@path, 'stories.csv'))
45
+ end
46
+
47
+ def story_completions
48
+ @story_completions ||= StoryCompletions.new(File.join(@path, 'stories-story-completions.csv'))
49
+ end
50
+
51
+ def teacher_privacy_settings
52
+ @teacher_privacy_settings ||= TeacherPrivacySettings.new(File.join(@path, 'TeacherPrivacySettings.csv'))
53
+ end
54
+ end
55
+ end
@@ -5,23 +5,23 @@ module DuolingoPersonalData
5
5
  end
6
6
 
7
7
  def num_following
8
- @num_following ||= integer_value_from_property("num_following")
8
+ @num_following ||= integer_value_from_property('num_following')
9
9
  end
10
10
 
11
11
  def num_followers
12
- @num_followers ||= integer_value_from_property("num_followers")
12
+ @num_followers ||= integer_value_from_property('num_followers')
13
13
  end
14
14
 
15
15
  def num_blocking
16
- @num_blocking ||= integer_value_from_property("num_blocking")
16
+ @num_blocking ||= integer_value_from_property('num_blocking')
17
17
  end
18
18
 
19
19
  def num_blockers
20
- @num_blockers ||= integer_value_from_property("num_blockers")
20
+ @num_blockers ||= integer_value_from_property('num_blockers')
21
21
  end
22
22
 
23
23
  def timestamp_generated
24
- @timestamp_generated ||= timestamp_value_from_property("timestamp_generated")
24
+ @timestamp_generated ||= timestamp_value_from_property('timestamp_generated')
25
25
  end
26
26
 
27
27
  private
@@ -1,4 +1,4 @@
1
- require "forwardable"
1
+ require 'forwardable'
2
2
 
3
3
  module DuolingoPersonalData
4
4
  InventoryItem = Struct.new(:item_type, :purchase_datetime, :active, :price_in_virtual_currency, :wager_day,
@@ -10,32 +10,32 @@ module DuolingoPersonalData
10
10
  end
11
11
 
12
12
  extend Forwardable
13
- def_delegators :items, *(Array.instance_methods - [:object_id])
13
+ def_delegators :items, :to_a, :first, :size, :[] # TODO: Add more as needed
14
14
 
15
15
  private
16
16
 
17
17
  def items
18
18
  @items ||= table.map do |row|
19
- item = InventoryItem.new(item_type: row["item_type"],
20
- purchase_datetime: parse_datetime(row["purchase_datetime"]), active: parse_boolean(row["active"]), payment_processor: row["payment_processor"], product: row["product"])
21
- price = row["price_in_virtual_currency"]
19
+ item = InventoryItem.new(item_type: row['item_type'],
20
+ purchase_datetime: parse_datetime(row['purchase_datetime']), active: parse_boolean(row['active']), payment_processor: row['payment_processor'], product: row['product'])
21
+ price = row['price_in_virtual_currency']
22
22
  item.price_in_virtual_currency = Integer(price) if price
23
- day = row["wager_day"]
23
+ day = row['wager_day']
24
24
  item.wager_day = Integer(day) if day
25
- expiration = row["expected_expiration"]
25
+ expiration = row['expected_expiration']
26
26
  item.expected_expiration = parse_datetime(expiration) if expiration
27
27
  item
28
28
  end
29
29
  end
30
30
 
31
31
  def parse_datetime(str)
32
- Time.strptime(str, "%Y-%m-%d %T")
32
+ Time.strptime(str, '%Y-%m-%d %T')
33
33
  end
34
34
 
35
35
  def parse_boolean(str)
36
36
  case str
37
- when "false" then false
38
- when "true" then true
37
+ when 'false' then false
38
+ when 'true' then true
39
39
  else
40
40
  raise Error, "cannot parse #{str.inspect} as boolean"
41
41
  end
@@ -1,5 +1,5 @@
1
- require "forwardable"
2
- require "csv"
1
+ require 'forwardable'
2
+ require 'csv'
3
3
 
4
4
  module DuolingoPersonalData
5
5
  Language = Struct.new(:from_language, :points, :skill_learned, :total_lessons, :days_active, :last_active,
@@ -10,33 +10,33 @@ module DuolingoPersonalData
10
10
  end
11
11
 
12
12
  extend Forwardable
13
- def_delegators :languages, *(Hash.instance_methods - [:object_id])
13
+ def_delegators :languages, :to_h, :[] # TODO: Add more as needed
14
14
 
15
15
  private
16
16
 
17
17
  def languages
18
18
  @languages ||= CSV.read(@csv_path, headers: true).map do |row|
19
- language = Language.new(from_language: row["from_language"])
20
- points = row["points"]
19
+ language = Language.new(from_language: row['from_language'])
20
+ points = row['points']
21
21
  language.points = Integer(points) if points
22
- skills = row["skills_learned"]
22
+ skills = row['skills_learned']
23
23
  language.skill_learned = Integer(skills) if skills
24
- lessons = row["total_lessons"]
24
+ lessons = row['total_lessons']
25
25
  language.total_lessons = Integer(lessons) if lessons
26
- days = row["days_active"]
26
+ days = row['days_active']
27
27
  language.days_active = Integer(days) if days
28
- active = row["last_active"]
28
+ active = row['last_active']
29
29
  language.last_active = parse_datetime(active) if active
30
- proficiency = row["prior_proficiency"]
30
+ proficiency = row['prior_proficiency']
31
31
  language.prior_proficiency = Integer(proficiency) if proficiency
32
- subscribed = row["subscribed"]
32
+ subscribed = row['subscribed']
33
33
  language.subscribed = parse_datetime(subscribed) if subscribed
34
- { row["learning_language"] => language }
34
+ { row['learning_language'] => language }
35
35
  end.reduce(&:merge)
36
36
  end
37
37
 
38
38
  def parse_datetime(str)
39
- Time.strptime(str, "%Y-%m-%d %T")
39
+ Time.strptime(str, '%Y-%m-%d %T')
40
40
  end
41
41
  end
42
42
  end
@@ -1,5 +1,5 @@
1
- require "csv"
2
- require "forwardable"
1
+ require 'csv'
2
+ require 'forwardable'
3
3
 
4
4
  module DuolingoPersonalData
5
5
  LeaderboardsEntry = Struct.new(:timestamp, :tier, :score, keyword_init: true)
@@ -10,14 +10,14 @@ module DuolingoPersonalData
10
10
  end
11
11
 
12
12
  extend Forwardable
13
- def_delegators :leaderboards_entries, *(Array.instance_methods - [:object_id])
13
+ def_delegators :leaderboards_entries, :to_a, :first, :size, :[] # TODO: Add more as needed
14
14
 
15
15
  private
16
16
 
17
17
  def leaderboards_entries
18
18
  @leaderboards_entries ||= CSV.read(@csv_path, headers: true).map do |row|
19
- LeaderboardsEntry.new(timestamp: Time.strptime(row["timestamp"], "%FT%TZ"), tier: Integer(row["tier"]),
20
- score: Float(row["score"]))
19
+ LeaderboardsEntry.new(timestamp: Time.strptime(row['timestamp'], '%FT%TZ'), tier: Integer(row['tier']),
20
+ score: Float(row['score']))
21
21
  end
22
22
  end
23
23
  end
@@ -1,4 +1,4 @@
1
- require "json"
1
+ require 'json'
2
2
 
3
3
  module DuolingoPersonalData
4
4
  class NotifyData
@@ -7,17 +7,17 @@ module DuolingoPersonalData
7
7
  end
8
8
 
9
9
  def email
10
- @email ||= value_from_property("email")
10
+ @email ||= value_from_property('email')
11
11
  end
12
12
 
13
13
  def device_ids
14
- @device_ids ||= json_value_from_property("device_ids")
14
+ @device_ids ||= json_value_from_property('device_ids')
15
15
  end
16
16
 
17
17
  private
18
18
 
19
19
  def value_from_property(property_name)
20
- table.find { |row| row["property"] == property_name }["value"]
20
+ table.find { |row| row['property'] == property_name }['value']
21
21
  end
22
22
 
23
23
  def json_value_from_property(property_name)
@@ -1,4 +1,4 @@
1
- require "csv"
1
+ require 'csv'
2
2
 
3
3
  module DuolingoPersonalData
4
4
  class Profile
@@ -7,49 +7,49 @@ module DuolingoPersonalData
7
7
  end
8
8
 
9
9
  def username
10
- @username ||= value_from_property("username")
10
+ @username ||= value_from_property('username')
11
11
  end
12
12
 
13
13
  def email
14
- @email ||= value_from_property("email")
14
+ @email ||= value_from_property('email')
15
15
  end
16
16
 
17
17
  def fullname
18
- @fullname ||= value_from_property("fullname")
18
+ @fullname ||= value_from_property('fullname')
19
19
  end
20
20
 
21
21
  def joined_at
22
- @joined_at ||= datetime_value_from_property("joined_at")
22
+ @joined_at ||= datetime_value_from_property('joined_at')
23
23
  end
24
24
 
25
25
  def ui_language
26
- @ui_language ||= value_from_property("ui_language")
26
+ @ui_language ||= value_from_property('ui_language')
27
27
  end
28
28
 
29
29
  def learning_language
30
- @learning_language ||= value_from_property("learning_language")
30
+ @learning_language ||= value_from_property('learning_language')
31
31
  end
32
32
 
33
33
  def lingots
34
- @lingots ||= integer_value_from_property("lingots")
34
+ @lingots ||= integer_value_from_property('lingots')
35
35
  end
36
36
 
37
37
  def daily_goal
38
- @daily_goal ||= integer_value_from_property("daily_goal")
38
+ @daily_goal ||= integer_value_from_property('daily_goal')
39
39
  end
40
40
 
41
41
  def timezone
42
- @timezone ||= value_from_property("timezone")
42
+ @timezone ||= value_from_property('timezone')
43
43
  end
44
44
 
45
45
  def avatar_url
46
- @avatar_url ||= value_from_property("avatar_url")
46
+ @avatar_url ||= value_from_property('avatar_url')
47
47
  end
48
48
 
49
49
  private
50
50
 
51
51
  def value_from_property(property_name)
52
- table.find { |row| row["name"] == property_name }["value"]
52
+ table.find { |row| row['name'] == property_name }['value']
53
53
  end
54
54
 
55
55
  def integer_value_from_property(property_name)
@@ -57,7 +57,7 @@ module DuolingoPersonalData
57
57
  end
58
58
 
59
59
  def datetime_value_from_property(property_name)
60
- Time.strptime(value_from_property(property_name), "%F %T")
60
+ Time.strptime(value_from_property(property_name), '%F %T')
61
61
  end
62
62
 
63
63
  def table
@@ -5,11 +5,11 @@ module DuolingoPersonalData
5
5
  end
6
6
 
7
7
  def user_id
8
- @user_id ||= value_from_property("userId")
8
+ @user_id ||= value_from_property('userId')
9
9
  end
10
10
 
11
11
  def date_of_first_visit_to_stories
12
- @date_of_first_visit_to_stories ||= datetime_value_from_property("dateOfFirstVisitToStories")
12
+ @date_of_first_visit_to_stories ||= datetime_value_from_property('dateOfFirstVisitToStories')
13
13
  end
14
14
 
15
15
  private
@@ -19,7 +19,7 @@ module DuolingoPersonalData
19
19
  end
20
20
 
21
21
  def datetime_value_from_property(property_name)
22
- Time.strptime(value_from_property(property_name), "%F %T")
22
+ Time.strptime(value_from_property(property_name), '%F %T')
23
23
  end
24
24
 
25
25
  def table
@@ -1,4 +1,4 @@
1
- require "forwardable"
1
+ require 'forwardable'
2
2
 
3
3
  module DuolingoPersonalData
4
4
  StoryCompletion = Struct.new(:user_id, :story_id, :score, :time, keyword_init: true)
@@ -9,14 +9,14 @@ module DuolingoPersonalData
9
9
  end
10
10
 
11
11
  extend Forwardable
12
- def_delegators :completions, *(Array.instance_methods - [:object_id])
12
+ def_delegators :completions, :[] # TODO: Add more as needed
13
13
 
14
14
  private
15
15
 
16
16
  def completions
17
17
  @completions ||= CSV.read(@csv_path, headers: true).map do |row|
18
- StoryCompletion.new(user_id: row["userId"], story_id: row["storyId"], score: Integer(row["score"]),
19
- time: Time.strptime(row["time"], "%F %T"))
18
+ StoryCompletion.new(user_id: row['userId'], story_id: row['storyId'], score: Integer(row['score']),
19
+ time: Time.strptime(row['time'], '%F %T'))
20
20
  end
21
21
  end
22
22
  end
@@ -5,27 +5,27 @@ module DuolingoPersonalData
5
5
  end
6
6
 
7
7
  def disable_clubs
8
- @disable_clubs ||= boolean_value_from_property("disable_clubs")
8
+ @disable_clubs ||= boolean_value_from_property('disable_clubs')
9
9
  end
10
10
 
11
11
  def disable_discussions
12
- @disable_discussions ||= boolean_value_from_property("disable_discussions")
12
+ @disable_discussions ||= boolean_value_from_property('disable_discussions')
13
13
  end
14
14
 
15
15
  def disable_events
16
- @disable_events ||= boolean_value_from_property("disable_events")
16
+ @disable_events ||= boolean_value_from_property('disable_events')
17
17
  end
18
18
 
19
19
  def disable_stream
20
- @disable_stream ||= boolean_value_from_property("disable_stream")
20
+ @disable_stream ||= boolean_value_from_property('disable_stream')
21
21
  end
22
22
 
23
23
  def disable_immersion
24
- @disable_immersion ||= boolean_value_from_property("disable_immersion")
24
+ @disable_immersion ||= boolean_value_from_property('disable_immersion')
25
25
  end
26
26
 
27
27
  def disable_mature_words
28
- @disable_mature_words ||= boolean_value_from_property("disable_mature_words")
28
+ @disable_mature_words ||= boolean_value_from_property('disable_mature_words')
29
29
  end
30
30
 
31
31
  private
@@ -33,8 +33,8 @@ module DuolingoPersonalData
33
33
  def boolean_value_from_property(property_name)
34
34
  value = value_from_property(property_name)
35
35
  case value
36
- when "False" then false
37
- when "True" then true
36
+ when 'False' then false
37
+ when 'True' then true
38
38
  else
39
39
  raise Error, "cannot interpret #{value.inspect} as boolean"
40
40
  end
@@ -1,3 +1,3 @@
1
1
  module DuolingoPersonalData
2
- VERSION = "0.1.0".freeze
2
+ VERSION = '0.2.0'
3
3
  end
@@ -1,16 +1,17 @@
1
- require_relative "duolingo_personal_data/version"
2
- require_relative "duolingo_personal_data/auth_data"
3
- require_relative "duolingo_personal_data/avatar_images"
4
- require_relative "duolingo_personal_data/blast_emails"
5
- require_relative "duolingo_personal_data/notify_data"
6
- require_relative "duolingo_personal_data/friends_follow"
7
- require_relative "duolingo_personal_data/inventory"
8
- require_relative "duolingo_personal_data/languages"
9
- require_relative "duolingo_personal_data/leaderboards"
10
- require_relative "duolingo_personal_data/profile"
11
- require_relative "duolingo_personal_data/stories"
12
- require_relative "duolingo_personal_data/story_completions"
13
- require_relative "duolingo_personal_data/teacher_privacy_settings"
1
+ require_relative 'duolingo_personal_data/version'
2
+ require_relative 'duolingo_personal_data/auth_data'
3
+ require_relative 'duolingo_personal_data/avatar_images'
4
+ require_relative 'duolingo_personal_data/blast_emails'
5
+ require_relative 'duolingo_personal_data/notify_data'
6
+ require_relative 'duolingo_personal_data/friends_follow'
7
+ require_relative 'duolingo_personal_data/inventory'
8
+ require_relative 'duolingo_personal_data/languages'
9
+ require_relative 'duolingo_personal_data/leaderboards'
10
+ require_relative 'duolingo_personal_data/profile'
11
+ require_relative 'duolingo_personal_data/stories'
12
+ require_relative 'duolingo_personal_data/story_completions'
13
+ require_relative 'duolingo_personal_data/teacher_privacy_settings'
14
+ require_relative 'duolingo_personal_data/directory'
14
15
 
15
16
  module DuolingoPersonalData
16
17
  class Error < StandardError; end
data/manifest.scm CHANGED
@@ -1,3 +1,3 @@
1
1
  (use-modules (gnu packages ruby))
2
2
 
3
- (packages->manifest (list ruby-rubocop ruby))
3
+ (packages->manifest (list ruby-rubocop ruby-rubocop-rake ruby bundler))
@@ -5,7 +5,7 @@ module DuolingoPersonalData
5
5
  VERSION: String
6
6
 
7
7
  class AuthData
8
- @csv_path: untyped
8
+ @csv_path: String
9
9
  @user_account_name: String?
10
10
  @table: Array[Array[String?]]
11
11
  @email_address: String?
@@ -13,7 +13,7 @@ module DuolingoPersonalData
13
13
  @last_login_attempt_timestamp: String?
14
14
  @last_authentication_key_refresh_timestamp: String?
15
15
 
16
- def initialize: (untyped csv_path) -> void
16
+ def initialize: (String csv_path) -> void
17
17
  def user_account_name: -> String?
18
18
  def email_address: -> String?
19
19
  def last_update_timestamp: -> String?
@@ -27,11 +27,11 @@ module DuolingoPersonalData
27
27
 
28
28
  class AvatarImages
29
29
  extend Forwardable
30
- @csv_path: untyped
30
+ @csv_path: String
31
31
  @urls: Array[URI::Generic]
32
32
  @table: Array[Array[String?]]
33
33
 
34
- def initialize: (untyped csv_path) -> void
34
+ def initialize: (String csv_path) -> void
35
35
 
36
36
  private
37
37
  def urls: -> Array[URI::Generic]
@@ -39,7 +39,7 @@ module DuolingoPersonalData
39
39
  end
40
40
 
41
41
  class BlastEmails
42
- @csv_path: untyped
42
+ @csv_path: String
43
43
  @email_address: String?
44
44
  @table: Array[Array[String?]]
45
45
  @ui_language: String?
@@ -53,7 +53,7 @@ module DuolingoPersonalData
53
53
  @client: String?
54
54
  @schools_role: Integer
55
55
 
56
- def initialize: (untyped csv_path) -> void
56
+ def initialize: (String csv_path) -> void
57
57
  def email_address: -> String?
58
58
  def ui_language: -> String?
59
59
  def learning_language: -> String?
@@ -74,6 +74,36 @@ module DuolingoPersonalData
74
74
  def table: -> Array[Array[String?]]
75
75
  end
76
76
 
77
+ class Directory
78
+ @path: untyped
79
+ @auth_data: AuthData
80
+ @avatar_images: AvatarImages
81
+ @blast_emails: BlastEmails
82
+ @notify_data: untyped
83
+ @friends_follow: untyped
84
+ @inventory: untyped
85
+ @languages: untyped
86
+ @leaderboards: untyped
87
+ @profile: untyped
88
+ @stories: untyped
89
+ @story_completions: untyped
90
+ @teacher_privacy_settings: untyped
91
+
92
+ def initialize: (untyped path) -> void
93
+ def auth_data: -> AuthData
94
+ def avatar_images: -> AvatarImages
95
+ def blast_emails: -> BlastEmails
96
+ def notify_data: -> untyped
97
+ def friends_follow: -> untyped
98
+ def inventory: -> untyped
99
+ def languages: -> untyped
100
+ def leaderboards: -> untyped
101
+ def profile: -> untyped
102
+ def stories: -> untyped
103
+ def story_completions: -> untyped
104
+ def teacher_privacy_settings: -> untyped
105
+ end
106
+
77
107
  class FriendsFollow
78
108
  @csv_path: untyped
79
109
  @num_following: Integer
@@ -155,12 +185,12 @@ module DuolingoPersonalData
155
185
  class Leaderboards
156
186
  extend Forwardable
157
187
  @csv_path: untyped
158
- @entries: Array[LeaderboardsEntry]
188
+ @leaderboards_entries: Array[LeaderboardsEntry]
159
189
 
160
190
  def initialize: (untyped csv_path) -> void
161
191
 
162
192
  private
163
- def entries: -> Array[LeaderboardsEntry]
193
+ def leaderboards_entries: -> Array[LeaderboardsEntry]
164
194
  end
165
195
 
166
196
  class NotifyData
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duolingo_personal_data
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
  - gemmaro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-19 00:00:00.000000000 Z
11
+ date: 2023-06-18 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Duolingo Personal Data gem is for loading Duolingo Personal Data, which
14
- can be acquired at <https://drive-thru.duolingo.com/>.
14
+ can be acquired at https://drive-thru.duolingo.com/.
15
15
  email:
16
16
  - gemmaro.dev@gmail.com
17
17
  executables: []
@@ -42,6 +42,7 @@ files:
42
42
  - lib/duolingo_personal_data/auth_data.rb
43
43
  - lib/duolingo_personal_data/avatar_images.rb
44
44
  - lib/duolingo_personal_data/blast_emails.rb
45
+ - lib/duolingo_personal_data/directory.rb
45
46
  - lib/duolingo_personal_data/friends_follow.rb
46
47
  - lib/duolingo_personal_data/inventory.rb
47
48
  - lib/duolingo_personal_data/languages.rb
@@ -61,6 +62,7 @@ metadata:
61
62
  homepage_uri: https://gitlab.com/gemmaro/ruby-duolingo-personal-data
62
63
  source_code_uri: https://gitlab.com/gemmaro/ruby-duolingo-personal-data
63
64
  changelog_uri: https://gitlab.com/gemmaro/ruby-duolingo-personal-data/-/blob/main/CHANGELOG.md
65
+ rubygems_mfa_required: 'true'
64
66
  post_install_message:
65
67
  rdoc_options: []
66
68
  require_paths:
@@ -79,5 +81,5 @@ requirements: []
79
81
  rubygems_version: 3.1.6
80
82
  signing_key:
81
83
  specification_version: 4
82
- summary: Library for Duolingo personal data.
84
+ summary: Library for Duolingo personal data
83
85
  test_files: []