このコミットが含まれているのは:
@@ -31,7 +31,7 @@ class MaterialVersionRecorder < VersionRecorder
|
||||
{ url: @record.url,
|
||||
parent: @record.parent,
|
||||
tag: @record.tag,
|
||||
tag_name: @record.tag&.name,
|
||||
tag_name: @record.tag&.name('ja'),
|
||||
tag_category: @record.tag&.category,
|
||||
source_kind: @record.source_kind,
|
||||
source_uri: @record.source_uri,
|
||||
|
||||
@@ -66,7 +66,7 @@ class PostBulkCreator
|
||||
PostCreatePreflight.new(
|
||||
attributes: attributes,
|
||||
thumbnail: thumbnail_for(index, attributes),
|
||||
host: @host).run
|
||||
host: @host).run(locale)
|
||||
if preflight[:existing_post_id].present?
|
||||
return {
|
||||
status: 'skipped',
|
||||
|
||||
@@ -12,8 +12,8 @@ class PostCreatePlan
|
||||
direct_tag_specs, tag_sections = parse_direct_tag_specs(locale)
|
||||
default_tag_specs = build_default_tag_specs(locale, direct_tag_specs)
|
||||
snapshot_tag_specs = merge_tag_specs(direct_tag_specs + default_tag_specs)
|
||||
preload_existing_tags_by_name!(snapshot_tag_specs.map { _1[:name] })
|
||||
validate_new_tag_specs!(snapshot_tag_specs)
|
||||
preload_existing_tags_by_name!(locale, snapshot_tag_specs.map { _1[:name] })
|
||||
validate_new_tag_specs!(locale, snapshot_tag_specs)
|
||||
post_tag_specs = expand_parent_tag_specs(locale, snapshot_tag_specs)
|
||||
video_ms = normalise_video_ms(snapshot_tag_specs)
|
||||
validate_video_sections!(video_ms, tag_sections)
|
||||
@@ -49,7 +49,9 @@ class PostCreatePlan
|
||||
tag_names.each do |raw_name|
|
||||
tag_name, category, sections = parse_raw_tag_name(locale, raw_name)
|
||||
existing_tag = existing_tags_by_name(locale)[tag_name]
|
||||
raise Tag::DeprecatedTagNormalisationError, [existing_tag.name] if existing_tag&.deprecated?
|
||||
if existing_tag&.deprecated?
|
||||
raise Tag::DeprecatedTagNormalisationError, [existing_tag.name(locale.language_code)]
|
||||
end
|
||||
|
||||
direct_tag_specs << {
|
||||
name: tag_name,
|
||||
@@ -106,17 +108,18 @@ class PostCreatePlan
|
||||
default_tag_specs
|
||||
end
|
||||
|
||||
def validate_new_tag_specs! specs
|
||||
def validate_new_tag_specs! locale, specs
|
||||
Array(specs).each do |spec|
|
||||
next if existing_tags_by_name.key?(spec[:name])
|
||||
next if existing_tags_by_name(locale).key?(spec[:name])
|
||||
|
||||
validate_new_tag_spec!(spec)
|
||||
validate_new_tag_spec!(locale, spec)
|
||||
end
|
||||
end
|
||||
|
||||
def validate_new_tag_spec! spec
|
||||
tag_name = TagName.new(name: spec[:name])
|
||||
tag = Tag.new(category: spec[:category], tag_name:)
|
||||
def validate_new_tag_spec! locale, spec
|
||||
tag_name = TagName.new(name: spec[:name], language_code: locale.language_code,
|
||||
script_code: locale.script_code, primary_flg: true)
|
||||
tag = Tag.new(category: spec[:category])
|
||||
return if tag_name.valid? && tag.valid?
|
||||
|
||||
post = Post.new
|
||||
@@ -139,7 +142,7 @@ class PostCreatePlan
|
||||
Tag.expand_parent_tags(existing_snapshot_tags)
|
||||
.reject(&:deprecated?)
|
||||
.map { |tag|
|
||||
{ name: tag.name,
|
||||
{ name: tag.name(locale.language_code),
|
||||
category: tag.category.to_sym }
|
||||
}
|
||||
merge_tag_specs(snapshot_tag_specs + expanded_parent_specs)
|
||||
@@ -161,7 +164,9 @@ class PostCreatePlan
|
||||
def existing_tags_by_name locale
|
||||
@existing_tags_by_name ||= begin
|
||||
names = tag_names.map { canonical_tag_name_without_sections(locale, _1) }.uniq
|
||||
Tag.joins(:tag_name).where(tag_names: { name: names }).index_by(&:name)
|
||||
TagName.where(language_code: locale.language_code, primary_flg: true, name: names)
|
||||
.includes(:tag)
|
||||
.each_with_object({ }) { |tag_name, tags| tags[tag_name.name] = tag_name.tag }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -171,9 +176,11 @@ class PostCreatePlan
|
||||
return if missing_names.empty?
|
||||
|
||||
existing_tags_by_name(locale).merge!(
|
||||
Tag.joins(:tag_name)
|
||||
.where(tag_names: { name: missing_names })
|
||||
.index_by(&:name))
|
||||
TagName.where(language_code: locale.language_code,
|
||||
primary_flg: true,
|
||||
name: missing_names)
|
||||
.includes(:tag)
|
||||
.each_with_object({ }) { |tag_name, tags| tags[tag_name.name] = tag_name.tag })
|
||||
end
|
||||
|
||||
def canonical_tag_name_without_sections locale, raw_name
|
||||
@@ -266,8 +273,8 @@ class PostCreatePlan
|
||||
tag_name = TagName.find_by(language_code: locale.language_code, name:)
|
||||
return name if !(tag_name) || tag_name.primary?
|
||||
|
||||
TagName.find_by!(language_code: locale.language_code,
|
||||
tag_id: tag_name.tag_id,
|
||||
primary_flg: true).name
|
||||
TagName.find_by(language_code: locale.language_code,
|
||||
tag_id: tag_name.tag_id,
|
||||
primary_flg: true)&.name || name
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,7 +15,7 @@ class PostCreatePreflight
|
||||
@host = host
|
||||
end
|
||||
|
||||
def run
|
||||
def run locale
|
||||
preview = PostImportPreviewer.new.preview_rows(
|
||||
rows: [preview_row],
|
||||
fetch_metadata: false).first
|
||||
@@ -53,7 +53,7 @@ class PostCreatePreflight
|
||||
original_created_from: preview[:attributes]['original_created_from'],
|
||||
original_created_before: preview[:attributes]['original_created_before'],
|
||||
duration: preview[:attributes]['duration'],
|
||||
video_ms: preview[:attributes]['video_ms'] }).build!
|
||||
video_ms: preview[:attributes]['video_ms'] }).build!(locale)
|
||||
|
||||
{
|
||||
url: plan[:url],
|
||||
|
||||
@@ -24,7 +24,10 @@ class PostCreator
|
||||
snapshot_tags = planned_snapshot_tags(locale)
|
||||
post_tags = planned_post_tags(locale)
|
||||
sections = planned_sections(locale)
|
||||
TagVersioning.record_tag_snapshots!(snapshot_tags, created_by_user: @actor)
|
||||
TagVersioning.record_tag_snapshots!(
|
||||
snapshot_tags,
|
||||
created_by_user: @actor,
|
||||
language_code: locale.language_code)
|
||||
post.video_ms = planned_video_ms(locale)
|
||||
post.save!
|
||||
sync_post_tags!(post, post_tags, sections)
|
||||
@@ -70,7 +73,8 @@ class PostCreator
|
||||
tag_sections: materialise_sections(
|
||||
@attributes[:tag_sections] || { },
|
||||
snapshot_tags,
|
||||
post_tags),
|
||||
post_tags,
|
||||
locale),
|
||||
normalised_parent_post_ids: @attributes[:normalised_parent_post_ids] || [],
|
||||
video_ms: @attributes[:video_ms] }
|
||||
else
|
||||
@@ -81,15 +85,16 @@ class PostCreator
|
||||
|
||||
def build_materialised_plan locale
|
||||
plan = PostCreatePlan.new(attributes: @attributes).build!(locale)
|
||||
snapshot_tags = materialise_tags(plan[:snapshot_tag_specs] || [])
|
||||
post_tags = materialise_tags(plan[:post_tag_specs] || [])
|
||||
snapshot_tags = materialise_tags(locale, plan[:snapshot_tag_specs] || [])
|
||||
post_tags = materialise_tags(locale, plan[:post_tag_specs] || [])
|
||||
{
|
||||
snapshot_tags: snapshot_tags,
|
||||
post_tags: post_tags,
|
||||
tag_sections: materialise_sections(
|
||||
plan[:tag_sections] || { },
|
||||
snapshot_tags,
|
||||
post_tags),
|
||||
post_tags,
|
||||
locale),
|
||||
normalised_parent_post_ids: plan[:normalised_parent_post_ids] || [],
|
||||
video_ms: plan[:video_ms] }
|
||||
end
|
||||
@@ -106,10 +111,10 @@ class PostCreator
|
||||
end.values
|
||||
end
|
||||
|
||||
def materialise_sections sections_by_name, snapshot_tags, post_tags
|
||||
tags_by_name = post_tags.index_by(&:name)
|
||||
def materialise_sections sections_by_name, snapshot_tags, post_tags, locale = Locale.nipponese
|
||||
tags_by_name = post_tags.index_by { _1.name(locale.language_code) }
|
||||
snapshot_tags.each do |tag|
|
||||
tags_by_name[tag.name] ||= tag
|
||||
tags_by_name[tag.name(locale.language_code)] ||= tag
|
||||
end
|
||||
|
||||
sections_by_name.each_with_object({ }) do |(tag_name, ranges), sections|
|
||||
|
||||
@@ -16,7 +16,7 @@ class PostImportPreviewer
|
||||
THUMBNAIL_FETCH_WARNING = 'サムネールを取得できませんでした.'.freeze
|
||||
METADATA_FETCH_WARNING = '自動取得に失敗しました.'.freeze
|
||||
|
||||
def preview_rows rows:, fetch_metadata: true, metadata_cache: { }
|
||||
def preview_rows locale, rows:, fetch_metadata: true, metadata_cache: { }
|
||||
prepared_rows = rows.map { prepare_row(_1) }
|
||||
url_counts = prepared_rows.filter_map { _1[:normal_url] }.tally
|
||||
existing_posts =
|
||||
@@ -36,7 +36,7 @@ class PostImportPreviewer
|
||||
existing_posts,
|
||||
url_counts)
|
||||
prepared_rows.map { |row|
|
||||
preview_row(row,
|
||||
preview_row(locale, row,
|
||||
fetch_metadata:,
|
||||
metadata_cache:,
|
||||
existing_posts:,
|
||||
@@ -59,7 +59,7 @@ class PostImportPreviewer
|
||||
source.merge(url_text: url, normal_url:, url_error: validate_url_safety(normal_url))
|
||||
end
|
||||
|
||||
def preview_row row,
|
||||
def preview_row locale, row,
|
||||
fetch_metadata:,
|
||||
metadata_cache:,
|
||||
existing_posts:,
|
||||
@@ -124,7 +124,8 @@ class PostImportPreviewer
|
||||
|
||||
attributes['url'] = url
|
||||
validate_basic_data(attributes, validation_errors)
|
||||
validate_preview_tags(merged_tags(tag_sources, provenance['tags']),
|
||||
validate_preview_tags(locale,
|
||||
merged_tags(tag_sources, provenance['tags']),
|
||||
validation_errors,
|
||||
known_tags)
|
||||
validate_parents(attributes['parent_post_ids'], validation_errors, existing_parent_ids)
|
||||
@@ -362,11 +363,9 @@ class PostImportPreviewer
|
||||
}.compact.uniq
|
||||
return { } if names.empty?
|
||||
|
||||
Tag.joins(:tag_name)
|
||||
.where(tag_names: { name: names })
|
||||
.includes(:tag_name)
|
||||
.to_a
|
||||
.index_by(&:name)
|
||||
TagName.where(language_code: 'ja', primary_flg: true, name: names)
|
||||
.includes(:tag)
|
||||
.each_with_object({ }) { |tag_name, tags| tags[tag_name.name] = tag_name.tag }
|
||||
end
|
||||
|
||||
def preload_parent_ids prepared_rows
|
||||
@@ -437,19 +436,21 @@ class PostImportPreviewer
|
||||
sources['automatic'].to_s
|
||||
end
|
||||
|
||||
def preview_tag_names raw
|
||||
def preview_tag_names locale, raw
|
||||
names = raw.to_s.split
|
||||
return [] if names.empty?
|
||||
if names.any? { _1.downcase.start_with?('nico:') }
|
||||
return []
|
||||
end
|
||||
|
||||
names.map { |name| TagName.canonicalise(name.sub(/\[.*\]\z/, '')).first }
|
||||
names.map { |name|
|
||||
TagName.canonicalise(locale, name.sub(/\[.*\]\z/, '')).first
|
||||
}
|
||||
rescue Tag::SectionLiteralParseError
|
||||
[]
|
||||
end
|
||||
|
||||
def validate_preview_tags raw, errors, known_tags
|
||||
def validate_preview_tags locale, raw, errors, known_tags
|
||||
names = raw.to_s.split
|
||||
return if names.empty?
|
||||
if names.any? { _1.downcase.start_with?('nico:') }
|
||||
@@ -457,7 +458,9 @@ class PostImportPreviewer
|
||||
return
|
||||
end
|
||||
|
||||
parsed = names.map { |name| TagName.canonicalise(name.sub(/\[.*\]\z/, '')).first }
|
||||
parsed = names.map { |name|
|
||||
TagName.canonicalise(locale, name.sub(/\[.*\]\z/, '')).first
|
||||
}
|
||||
existing = parsed.filter_map { known_tags[_1] }
|
||||
deprecated = existing.select(&:deprecated?).map(&:name)
|
||||
errors[:tags] = ["廃止済みタグがあります: #{ deprecated.join(' ') }"] if deprecated.present?
|
||||
|
||||
@@ -47,9 +47,9 @@ class PostMetadataFetcher
|
||||
|
||||
existing_tags =
|
||||
Tag
|
||||
.joins(:tag_name)
|
||||
.where(tag_names: { name: names })
|
||||
.index_by(&:name)
|
||||
.joins(:tag_names)
|
||||
.where(tag_names: { language_code: 'ja', primary_flg: true, name: names })
|
||||
.index_by { _1.name('ja') }
|
||||
|
||||
names.map { |name|
|
||||
tag = existing_tags[name]
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
class TagVersionRecorder < VersionRecorder
|
||||
def self.record! tag:, event_type:, created_by_user:
|
||||
new(tag:, event_type:, created_by_user:).record!
|
||||
def self.record! tag:, event_type:, created_by_user:, language_code: 'ja'
|
||||
new(tag:, event_type:, created_by_user:, language_code:).record!
|
||||
end
|
||||
|
||||
def initialize tag:, event_type:, created_by_user:
|
||||
def initialize tag:, event_type:, created_by_user:, language_code:
|
||||
super(record: tag, event_type:, created_by_user:)
|
||||
@language_code = language_code
|
||||
end
|
||||
|
||||
private
|
||||
@@ -14,10 +15,10 @@ class TagVersionRecorder < VersionRecorder
|
||||
def record_key = :tag
|
||||
|
||||
def snapshot_attributes
|
||||
{ name: @record.name,
|
||||
{ name: @record.name(@language_code),
|
||||
category: @record.category,
|
||||
deprecated_at: @record.deprecated_at,
|
||||
aliases: @record.snapshot_aliases.join(' '),
|
||||
aliases: @record.snapshot_aliases(@language_code).join(' '),
|
||||
parent_tag_ids: @record.snapshot_parent_tag_ids.join(' ') }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
class TagVersioning
|
||||
def self.record! tag, event_type:, created_by_user:
|
||||
TagVersionRecorder.record!(tag:, event_type:, created_by_user:)
|
||||
def self.record! tag, event_type:, created_by_user:, language_code: 'ja'
|
||||
TagVersionRecorder.record!(tag:, event_type:, created_by_user:, language_code:)
|
||||
end
|
||||
|
||||
def self.ensure_snapshot! tag, created_by_user:
|
||||
def self.ensure_snapshot! tag, created_by_user:, language_code: 'ja'
|
||||
return if tag.tag_versions.exists?
|
||||
|
||||
TagVersionRecorder.record!(tag:, event_type: :create, created_by_user:)
|
||||
TagVersionRecorder.record!(tag:, event_type: :create, created_by_user:, language_code:)
|
||||
end
|
||||
|
||||
def self.record_tag_snapshot! tag, created_by_user:
|
||||
def self.record_tag_snapshot! tag, created_by_user:, language_code: 'ja'
|
||||
event_type = tag.tag_versions.exists? ? :update : :create
|
||||
record!(tag, event_type:, created_by_user:)
|
||||
record!(tag, event_type:, created_by_user:, language_code:)
|
||||
end
|
||||
|
||||
def self.record_tag_snapshots! tags, created_by_user:
|
||||
def self.record_tag_snapshots! tags, created_by_user:, language_code: 'ja'
|
||||
tags.each do |tag|
|
||||
record_tag_snapshot!(tag, created_by_user:)
|
||||
record_tag_snapshot!(tag, created_by_user:, language_code:)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -41,7 +41,7 @@ class TheatrePostSelector
|
||||
def weighted_candidates
|
||||
@weighted_candidates ||= begin
|
||||
penalties = tag_penalties
|
||||
posts = eligible_posts.includes(tags: :tag_name).to_a
|
||||
posts = eligible_posts.includes(tags: :tag_names).to_a
|
||||
|
||||
posts.map do |post|
|
||||
post_tags = post.tags.to_a
|
||||
@@ -82,7 +82,7 @@ class TheatrePostSelector
|
||||
def tag_penalty_json
|
||||
return [] if tag_penalties.empty?
|
||||
|
||||
tags = Tag.where(id: tag_penalties.keys).includes(:tag_name).index_by(&:id)
|
||||
tags = Tag.where(id: tag_penalties.keys).includes(:tag_names).index_by(&:id)
|
||||
|
||||
tag_penalties
|
||||
.map { |tag_id, penalty|
|
||||
@@ -113,7 +113,7 @@ class TheatrePostSelector
|
||||
|
||||
def light_tag_json tag
|
||||
{ id: tag.id,
|
||||
name: tag.name,
|
||||
name: tag.name('ja'),
|
||||
category: tag.category }
|
||||
end
|
||||
end
|
||||
|
||||
新しいイシューから参照
ユーザーをブロックする