discourse_dev 0.0.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -0
  3. data/auth/app/views/fake_discourse_connect/form.html.erb +120 -0
  4. data/auth/plugin.rb +219 -0
  5. data/avatars/03F55412-DE8A-4F83-AAA6-D67EE5CE48DA-200w.jpeg +0 -0
  6. data/avatars/1C4EEDC2-FE9C-40B3-A2C9-A038873EE692-200w.jpeg +0 -0
  7. data/avatars/26CFEFB3-21C8-49FC-8C19-8E6A62B6D2E0-200w.jpeg +0 -0
  8. data/avatars/282A12CA-E0D7-4011-8BDD-1FAFAAB035F7-200w.jpeg +0 -0
  9. data/avatars/2DDDE973-40EC-4004-ABC0-73FD4CD6D042-200w.jpeg +0 -0
  10. data/avatars/344CFC24-61FB-426C-B3D1-CAD5BCBD3209-200w.jpeg +0 -0
  11. data/avatars/852EC6E1-347C-4187-9D42-DF264CCF17BF-200w.jpeg +0 -0
  12. data/avatars/A7299C8E-CEFC-47D9-939A-3C8CA0EA4D13-200w.jpeg +0 -0
  13. data/avatars/AEF44435-B547-4B84-A2AE-887DFAEE6DDF-200w.jpeg +0 -0
  14. data/avatars/B3CF5288-34B0-4A5E-9877-5965522529D6-200w.jpeg +0 -0
  15. data/avatars/BA0CB1F2-8C79-4376-B13B-DD5FB8772537-200w.jpeg +0 -0
  16. data/avatars/E0B4CAB3-F491-4322-BEF2-208B46748D4A-200w.jpeg +0 -0
  17. data/avatars/FBEBF655-4886-455A-A4A4-D62B77DD419B-200w.jpeg +0 -0
  18. data/config/dev.yml +38 -0
  19. data/config/locales/client.en.yml +6 -0
  20. data/{lib/faker/locales/en.yml → config/locales/faker.en.yml} +1 -1
  21. data/discourse_dev.gemspec +1 -0
  22. data/lib/discourse_dev.rb +49 -4
  23. data/lib/discourse_dev/category.rb +3 -3
  24. data/lib/discourse_dev/config.rb +101 -29
  25. data/lib/discourse_dev/group.rb +4 -5
  26. data/lib/discourse_dev/post.rb +64 -5
  27. data/lib/discourse_dev/record.rb +6 -1
  28. data/lib/discourse_dev/tag.rb +2 -2
  29. data/lib/discourse_dev/tasks/dev.rake +5 -1
  30. data/lib/discourse_dev/tasks/populate.rake +5 -0
  31. data/lib/discourse_dev/topic.rb +52 -10
  32. data/lib/discourse_dev/user.rb +58 -7
  33. data/lib/discourse_dev/version.rb +1 -1
  34. data/lib/faker/discourse_markdown.rb +96 -0
  35. metadata +36 -4
  36. data/lib/discourse_dev/config.yml +0 -4
@@ -6,33 +6,56 @@ require 'faker'
6
6
  module DiscourseDev
7
7
  class Topic < Record
8
8
 
9
- def initialize(count = DEFAULT_COUNT)
10
- super(::Topic, count)
9
+ def initialize
10
+ @settings = DiscourseDev.config.topic
11
+ super(::Topic, @settings[:count])
11
12
  end
12
13
 
13
14
  def data
15
+ max_views = 0
16
+
17
+ case Faker::Number.between(from: 0, to: 5)
18
+ when 0
19
+ max_views = 10
20
+ when 1
21
+ max_views = 100
22
+ when 2
23
+ max_views = SiteSetting.topic_views_heat_low
24
+ when 3
25
+ max_views = SiteSetting.topic_views_heat_medium
26
+ when 4
27
+ max_views = SiteSetting.topic_views_heat_high
28
+ when 5
29
+ max_views = SiteSetting.topic_views_heat_high + SiteSetting.topic_views_heat_medium
30
+ end
31
+
14
32
  {
15
33
  title: title[0, SiteSetting.max_topic_title_length],
16
- raw: Faker::Markdown.sandwich(sentences: 5),
34
+ raw: Faker::DiscourseMarkdown.sandwich(sentences: 5),
17
35
  category: @category.id,
36
+ created_at: Faker::Time.between(from: DiscourseDev.config.start_date, to: DateTime.now),
18
37
  tags: tags,
19
- topic_opts: { custom_fields: { dev_sample: true } },
38
+ topic_opts: {
39
+ import_mode: true,
40
+ views: Faker::Number.between(from: 1, to: max_views),
41
+ custom_fields: { dev_sample: true }
42
+ },
20
43
  skip_validations: true
21
44
  }
22
45
  end
23
46
 
24
47
  def title
25
- if index <= I18n.t("faker.discourse.topics").count
48
+ if index < I18n.t("faker.discourse.topics").count
26
49
  Faker::Discourse.unique.topic
27
50
  else
28
- Faker::Lorem.unique.sentence(word_count: 3, supplemental: true, random_words_to_add: 4).chomp(".")
51
+ Faker::Lorem.unique.sentence(word_count: 5, supplemental: true, random_words_to_add: 4).chomp(".")
29
52
  end
30
53
  end
31
54
 
32
55
  def tags
33
56
  @tags = []
34
57
 
35
- Faker::Number.between(from: 0, to: 3).times do
58
+ Faker::Number.between(from: @settings.dig(:tags, :min), to: @settings.dig(:tags, :max)).times do
36
59
  @tags << Faker::Discourse.tag
37
60
  end
38
61
 
@@ -41,14 +64,27 @@ module DiscourseDev
41
64
 
42
65
  def create!
43
66
  @category = Category.random
44
- post = PostCreator.new(user, data).create!
67
+ user = self.user
68
+ topic = Faker::DiscourseMarkdown.with_user(user.id) { data }
69
+ post = PostCreator.new(user, topic).create!
70
+
71
+ if override = @settings.dig(:replies, :overrides).find { |o| o[:title] == topic[:title] }
72
+ reply_count = override[:count]
73
+ else
74
+ reply_count = Faker::Number.between(from: @settings.dig(:replies, :min), to: @settings.dig(:replies, :max))
75
+ end
45
76
 
46
- Post.new(post.topic, Faker::Number.between(from: 0, to: 5)).populate!
77
+ Post.new(post.topic, reply_count).populate!
78
+ end
79
+
80
+ def populate!
81
+ super
82
+ delete_unwanted_sidekiq_jobs
47
83
  end
48
84
 
49
85
  def user
50
86
  return User.random if @category.groups.blank?
51
-
87
+
52
88
  group_ids = @category.groups.pluck(:id)
53
89
  user_ids = ::GroupUser.where(group_id: group_ids).pluck(:user_id)
54
90
  user_count = user_ids.count
@@ -60,5 +96,11 @@ module DiscourseDev
60
96
  category_definition_topic_ids = ::Category.pluck(:topic_id)
61
97
  ::Topic.where(archetype: :regular).where.not(id: category_definition_topic_ids).count
62
98
  end
99
+
100
+ def delete_unwanted_sidekiq_jobs
101
+ Sidekiq::ScheduledSet.new.each do |job|
102
+ job.delete if job.item["class"] == "Jobs::UserEmail"
103
+ end
104
+ end
63
105
  end
64
106
  end
@@ -6,16 +6,22 @@ require 'faker'
6
6
 
7
7
  module DiscourseDev
8
8
  class User < Record
9
+ attr_reader :images
9
10
 
10
- def initialize(count = DEFAULT_COUNT)
11
- super(::User, count)
11
+ def initialize
12
+ super(::User, DiscourseDev.config.user[:count])
13
+
14
+ # Using the stock avatar images from https://tinyfac.es
15
+ # Tiny Faces is a free crowd-sourced avatar gallery
16
+ @images = Dir[File.join(__dir__, '..', '..', 'avatars', '*.*')]
12
17
  end
13
18
 
14
19
  def data
15
20
  name = Faker::Name.unique.name
16
- email = Faker::Internet.unique.email(name: name)
17
- username = Faker::Internet.unique.username(specifier: name)[0, SiteSetting.max_username_length]
18
- username_lower = username.downcase
21
+ email = Faker::Internet.unique.email(name: name, domain: "faker.invalid")
22
+ username = Faker::Internet.unique.username(specifier: ::User.username_length)
23
+ username = UserNameSuggester.suggest(username)
24
+ username_lower = ::User.normalize_username(username)
19
25
 
20
26
  {
21
27
  name: name,
@@ -23,16 +29,18 @@ module DiscourseDev
23
29
  username: username,
24
30
  username_lower: username_lower,
25
31
  moderator: Faker::Boolean.boolean(true_ratio: 0.1),
26
- trust_level: Faker::Number.between(from: 1, to: 4)
32
+ trust_level: Faker::Number.between(from: 1, to: 4),
33
+ created_at: Faker::Time.between(from: DiscourseDev.config.start_date, to: DateTime.now),
27
34
  }
28
35
  end
29
36
 
30
37
  def create!
31
38
  super do |user|
32
39
  user.activate
40
+ set_random_avatar(user)
33
41
  Faker::Number.between(from: 0, to: 2).times do
34
42
  group = Group.random
35
-
43
+
36
44
  group.add(user)
37
45
  end
38
46
  end
@@ -41,5 +49,48 @@ module DiscourseDev
41
49
  def self.random
42
50
  super(::User)
43
51
  end
52
+
53
+ def set_random_avatar(user)
54
+ return if images.blank?
55
+ return unless Faker::Boolean.boolean
56
+
57
+ avatar_index = Faker::Number.between(from: 0, to: images.count - 1)
58
+ avatar_path = images[avatar_index]
59
+ create_avatar(user, avatar_path)
60
+ @images.delete_at(avatar_index)
61
+ end
62
+
63
+ def create_avatar(user, avatar_path)
64
+ tempfile = copy_to_tempfile(avatar_path)
65
+ filename = "avatar#{File.extname(avatar_path)}"
66
+ upload = UploadCreator.new(tempfile, filename, type: "avatar").create_for(user.id)
67
+
68
+ if upload.present? && upload.persisted?
69
+ user.create_user_avatar
70
+ user.user_avatar.update(custom_upload_id: upload.id)
71
+ user.update(uploaded_avatar_id: upload.id)
72
+ else
73
+ STDERR.puts "Failed to upload avatar for user #{user.username}: #{avatar_path}"
74
+ STDERR.puts upload.errors.inspect if upload
75
+ end
76
+ rescue
77
+ STDERR.puts "Failed to create avatar for user #{user.username}: #{avatar_path}"
78
+ ensure
79
+ tempfile.close! if tempfile
80
+ end
81
+
82
+ private
83
+
84
+ def copy_to_tempfile(source_path)
85
+ extension = File.extname(source_path)
86
+ tmp = Tempfile.new(['discourse-upload', extension])
87
+
88
+ File.open(source_path) do |source_stream|
89
+ IO.copy_stream(source_stream, tmp)
90
+ end
91
+
92
+ tmp.rewind
93
+ tmp
94
+ end
44
95
  end
45
96
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DiscourseDev
4
- VERSION = "0.0.5"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faker'
4
+ require 'net/http'
5
+ require 'json'
6
+
7
+ module Faker
8
+ class DiscourseMarkdown < Markdown
9
+ class << self
10
+ attr_writer(:user_id)
11
+
12
+ def user_id
13
+ @user_id || ::Discourse::SYSTEM_USER_ID
14
+ end
15
+
16
+ def with_user(user_id)
17
+ current_user_id = self.user_id
18
+ self.user_id = user_id
19
+ begin
20
+ yield
21
+ ensure
22
+ self.user_id = current_user_id
23
+ end
24
+ end
25
+
26
+ def image
27
+ image = next_image
28
+ image_file = load_image(image)
29
+
30
+ upload = ::UploadCreator.new(
31
+ image_file,
32
+ image[:filename],
33
+ origin: image[:url]
34
+ ).create_for(user_id)
35
+
36
+ ::UploadMarkdown.new(upload).to_markdown if upload.present? && upload.persisted?
37
+ rescue => e
38
+ STDERR.puts e
39
+ STDERR.puts e.backtrace.join("\n")
40
+ end
41
+
42
+ private
43
+
44
+ def next_image
45
+ if @images.blank?
46
+ if @stop_loading_images
47
+ @images = @all_images.dup
48
+ else
49
+ @next_page = (@next_page || 0) + 1
50
+ url = URI("https://picsum.photos/v2/list?page=#{@next_page}&limit=50")
51
+ response = Net::HTTP.get(url)
52
+ json = JSON.parse(response)
53
+
54
+ if json.blank?
55
+ @stop_loading_images = true
56
+ @images = @all_images.dup
57
+ else
58
+ @images = json.sort_by { |image| image["id"] }
59
+ @all_images = (@all_images || []).concat(@images)
60
+ end
61
+ end
62
+ end
63
+
64
+ image = @images.pop
65
+ { filename: "#{image['id']}.jpg", url: "#{image['download_url']}.jpg" }
66
+ end
67
+
68
+ def image_cache_dir
69
+ @image_cache_dir ||= ::File.join(Rails.root, "tmp", "discourse_dev", "images")
70
+ end
71
+
72
+ def load_image(image)
73
+ cache_path = ::File.join(image_cache_dir, image[:filename])
74
+
75
+ if !::File.exists?(cache_path)
76
+ FileUtils.mkdir_p(image_cache_dir)
77
+ temp_file = ::FileHelper.download(
78
+ image[:url],
79
+ max_file_size: [SiteSetting.max_image_size_kb.kilobytes, 10.megabytes].max,
80
+ tmp_file_name: "image",
81
+ follow_redirect: true
82
+ )
83
+ FileUtils.cp(temp_file, cache_path)
84
+ end
85
+
86
+ ::File.open(cache_path)
87
+ end
88
+
89
+ def available_methods
90
+ methods = super
91
+ methods << :image if ::DiscourseDev.config.post[:include_images]
92
+ methods
93
+ end
94
+ end
95
+ end
96
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: discourse_dev
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vinoth Kannan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-12 00:00:00.000000000 Z
11
+ date: 2021-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faker
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: 12.3.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-discourse
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'
55
69
  description: Rake helper tasks for Discourse developers
56
70
  email:
57
71
  - svkn.87@gmail.com
@@ -61,16 +75,34 @@ extra_rdoc_files: []
61
75
  files:
62
76
  - ".github/workflows/gem-push.yml"
63
77
  - ".gitignore"
78
+ - ".rubocop.yml"
64
79
  - Gemfile
65
80
  - LICENSE.txt
66
81
  - README.md
67
82
  - Rakefile
83
+ - auth/app/views/fake_discourse_connect/form.html.erb
84
+ - auth/plugin.rb
85
+ - avatars/03F55412-DE8A-4F83-AAA6-D67EE5CE48DA-200w.jpeg
86
+ - avatars/1C4EEDC2-FE9C-40B3-A2C9-A038873EE692-200w.jpeg
87
+ - avatars/26CFEFB3-21C8-49FC-8C19-8E6A62B6D2E0-200w.jpeg
88
+ - avatars/282A12CA-E0D7-4011-8BDD-1FAFAAB035F7-200w.jpeg
89
+ - avatars/2DDDE973-40EC-4004-ABC0-73FD4CD6D042-200w.jpeg
90
+ - avatars/344CFC24-61FB-426C-B3D1-CAD5BCBD3209-200w.jpeg
91
+ - avatars/852EC6E1-347C-4187-9D42-DF264CCF17BF-200w.jpeg
92
+ - avatars/A7299C8E-CEFC-47D9-939A-3C8CA0EA4D13-200w.jpeg
93
+ - avatars/AEF44435-B547-4B84-A2AE-887DFAEE6DDF-200w.jpeg
94
+ - avatars/B3CF5288-34B0-4A5E-9877-5965522529D6-200w.jpeg
95
+ - avatars/BA0CB1F2-8C79-4376-B13B-DD5FB8772537-200w.jpeg
96
+ - avatars/E0B4CAB3-F491-4322-BEF2-208B46748D4A-200w.jpeg
97
+ - avatars/FBEBF655-4886-455A-A4A4-D62B77DD419B-200w.jpeg
98
+ - config/dev.yml
99
+ - config/locales/client.en.yml
100
+ - config/locales/faker.en.yml
68
101
  - config/routes.rb
69
102
  - discourse_dev.gemspec
70
103
  - lib/discourse_dev.rb
71
104
  - lib/discourse_dev/category.rb
72
105
  - lib/discourse_dev/config.rb
73
- - lib/discourse_dev/config.yml
74
106
  - lib/discourse_dev/engine.rb
75
107
  - lib/discourse_dev/group.rb
76
108
  - lib/discourse_dev/post.rb
@@ -83,7 +115,7 @@ files:
83
115
  - lib/discourse_dev/user.rb
84
116
  - lib/discourse_dev/version.rb
85
117
  - lib/faker/discourse.rb
86
- - lib/faker/locales/en.yml
118
+ - lib/faker/discourse_markdown.rb
87
119
  homepage: https://github.com/discourse/discourse_dev
88
120
  licenses:
89
121
  - MIT
@@ -1,4 +0,0 @@
1
- site_settings:
2
- tagging_enabled: true
3
- verbose_discourse_connect_logging: true
4
- seed: 1