Add data ingestion endpoints (#195)
* Update schema.rb * Add endpoints for importing game data This lets privileged users import canonical data for characters, weapons and summons directly from the game
This commit is contained in:
parent
28a6b1894e
commit
7880ac76cc
3 changed files with 122 additions and 4 deletions
|
|
@ -27,6 +27,8 @@ module Api
|
||||||
6 => 5
|
6 => 5
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
|
before_action :ensure_admin_role, only: %i[weapons summons characters]
|
||||||
|
|
||||||
##
|
##
|
||||||
# Processes an import request.
|
# Processes an import request.
|
||||||
#
|
#
|
||||||
|
|
@ -49,9 +51,9 @@ module Api
|
||||||
end
|
end
|
||||||
|
|
||||||
unless raw_params['deck'].is_a?(Hash) &&
|
unless raw_params['deck'].is_a?(Hash) &&
|
||||||
raw_params['deck'].key?('pc') &&
|
raw_params['deck'].key?('pc') &&
|
||||||
raw_params['deck'].key?('npc')
|
raw_params['deck'].key?('npc')
|
||||||
Rails.logger.error "[IMPORT] Deck data incomplete or missing."
|
Rails.logger.error '[IMPORT] Deck data incomplete or missing.'
|
||||||
return render json: { error: 'Invalid deck data' }, status: :unprocessable_content
|
return render json: { error: 'Invalid deck data' }, status: :unprocessable_content
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -68,8 +70,111 @@ module Api
|
||||||
render json: { error: e.message }, status: :unprocessable_content
|
render json: { error: e.message }, status: :unprocessable_content
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def weapons
|
||||||
|
Rails.logger.info '[IMPORT] Checking weapon gamedata input...'
|
||||||
|
|
||||||
|
body = parse_request_body
|
||||||
|
return unless body
|
||||||
|
|
||||||
|
weapon = Weapon.find_by(granblue_id: body['id'])
|
||||||
|
unless weapon
|
||||||
|
Rails.logger.error "[IMPORT] Weapon not found with ID: #{body['id']}"
|
||||||
|
return render json: { error: 'Weapon not found' }, status: :not_found
|
||||||
|
end
|
||||||
|
|
||||||
|
lang = params[:lang]
|
||||||
|
unless %w[en jp].include?(lang)
|
||||||
|
Rails.logger.error "[IMPORT] Invalid language: #{lang}"
|
||||||
|
return render json: { error: 'Invalid language' }, status: :unprocessable_content
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
weapon.update!(
|
||||||
|
"game_raw_#{lang}" => body.to_json
|
||||||
|
)
|
||||||
|
render json: { message: 'Weapon gamedata updated successfully' }, status: :ok
|
||||||
|
rescue StandardError => e
|
||||||
|
Rails.logger.error "[IMPORT] Failed to update weapon gamedata: #{e.message}"
|
||||||
|
render json: { error: e.message }, status: :unprocessable_content
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def summons
|
||||||
|
Rails.logger.info '[IMPORT] Checking summon gamedata input...'
|
||||||
|
|
||||||
|
body = parse_request_body
|
||||||
|
return unless body
|
||||||
|
|
||||||
|
summon = Summon.find_by(granblue_id: body['id'])
|
||||||
|
unless summon
|
||||||
|
Rails.logger.error "[IMPORT] Summon not found with ID: #{body['id']}"
|
||||||
|
return render json: { error: 'Summon not found' }, status: :not_found
|
||||||
|
end
|
||||||
|
|
||||||
|
lang = params[:lang]
|
||||||
|
unless %w[en jp].include?(lang)
|
||||||
|
Rails.logger.error "[IMPORT] Invalid language: #{lang}"
|
||||||
|
return render json: { error: 'Invalid language' }, status: :unprocessable_content
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
summon.update!(
|
||||||
|
"game_raw_#{lang}" => body.to_json
|
||||||
|
)
|
||||||
|
render json: { message: 'Summon gamedata updated successfully' }, status: :ok
|
||||||
|
rescue StandardError => e
|
||||||
|
Rails.logger.error "[IMPORT] Failed to update summon gamedata: #{e.message}"
|
||||||
|
render json: { error: e.message }, status: :unprocessable_content
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Updates character gamedata from JSON blob.
|
||||||
|
#
|
||||||
|
# @return [void] Renders JSON response with success or error message.
|
||||||
|
def characters
|
||||||
|
Rails.logger.info '[IMPORT] Checking character gamedata input...'
|
||||||
|
|
||||||
|
body = parse_request_body
|
||||||
|
return unless body
|
||||||
|
|
||||||
|
character = Character.find_by(granblue_id: body['id'])
|
||||||
|
unless character
|
||||||
|
Rails.logger.error "[IMPORT] Character not found with ID: #{body['id']}"
|
||||||
|
return render json: { error: 'Character not found' }, status: :not_found
|
||||||
|
end
|
||||||
|
|
||||||
|
lang = params[:lang]
|
||||||
|
unless %w[en jp].include?(lang)
|
||||||
|
Rails.logger.error "[IMPORT] Invalid language: #{lang}"
|
||||||
|
return render json: { error: 'Invalid language' }, status: :unprocessable_content
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
character.update!(
|
||||||
|
"game_raw_#{lang}" => body.to_json
|
||||||
|
)
|
||||||
|
render json: { message: 'Character gamedata updated successfully' }, status: :ok
|
||||||
|
rescue StandardError => e
|
||||||
|
Rails.logger.error "[IMPORT] Failed to update character gamedata: #{e.message}"
|
||||||
|
render json: { error: e.message }, status: :unprocessable_content
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
##
|
||||||
|
# Ensures the current user has admin role (role 9).
|
||||||
|
# Renders an error if the user is not an admin.
|
||||||
|
#
|
||||||
|
# @return [void]
|
||||||
|
def ensure_admin_role
|
||||||
|
return if current_user&.role == 9
|
||||||
|
|
||||||
|
Rails.logger.error "[IMPORT] Unauthorized access attempt by user #{current_user&.id}"
|
||||||
|
render json: { error: 'Unauthorized' }, status: :unauthorized
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Reads and parses the raw JSON request body.
|
# Reads and parses the raw JSON request body.
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ Rails.application.routes.draw do
|
||||||
get 'version', to: 'api#version'
|
get 'version', to: 'api#version'
|
||||||
|
|
||||||
post 'import', to: 'import#create'
|
post 'import', to: 'import#create'
|
||||||
|
post 'import/weapons', to: 'import#weapons'
|
||||||
|
post 'import/summons', to: 'import#summons'
|
||||||
|
post 'import/characters', to: 'import#characters'
|
||||||
|
|
||||||
get 'users/info/:id', to: 'users#info'
|
get 'users/info/:id', to: 'users#info'
|
||||||
|
|
||||||
|
|
|
||||||
12
db/schema.rb
12
db/schema.rb
|
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[8.0].define(version: 2025_02_18_025315) do
|
ActiveRecord::Schema[8.0].define(version: 2025_03_01_143956) do
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "btree_gin"
|
enable_extension "btree_gin"
|
||||||
enable_extension "pg_catalog.plpgsql"
|
enable_extension "pg_catalog.plpgsql"
|
||||||
|
|
@ -67,6 +67,9 @@ ActiveRecord::Schema[8.0].define(version: 2025_02_18_025315) do
|
||||||
t.string "kamigame", default: ""
|
t.string "kamigame", default: ""
|
||||||
t.string "nicknames_en", default: [], null: false, array: true
|
t.string "nicknames_en", default: [], null: false, array: true
|
||||||
t.string "nicknames_jp", default: [], null: false, array: true
|
t.string "nicknames_jp", default: [], null: false, array: true
|
||||||
|
t.text "wiki_raw"
|
||||||
|
t.text "game_raw_en"
|
||||||
|
t.text "game_raw_jp"
|
||||||
t.index ["granblue_id"], name: "index_characters_on_granblue_id"
|
t.index ["granblue_id"], name: "index_characters_on_granblue_id"
|
||||||
t.index ["name_en"], name: "index_characters_on_name_en", opclass: :gin_trgm_ops, using: :gin
|
t.index ["name_en"], name: "index_characters_on_name_en", opclass: :gin_trgm_ops, using: :gin
|
||||||
end
|
end
|
||||||
|
|
@ -420,6 +423,9 @@ ActiveRecord::Schema[8.0].define(version: 2025_02_18_025315) do
|
||||||
t.date "transcendence_date"
|
t.date "transcendence_date"
|
||||||
t.string "nicknames_en", default: [], null: false, array: true
|
t.string "nicknames_en", default: [], null: false, array: true
|
||||||
t.string "nicknames_jp", default: [], null: false, array: true
|
t.string "nicknames_jp", default: [], null: false, array: true
|
||||||
|
t.text "wiki_raw"
|
||||||
|
t.text "game_raw_en"
|
||||||
|
t.text "game_raw_jp"
|
||||||
t.index ["granblue_id"], name: "index_summons_on_granblue_id"
|
t.index ["granblue_id"], name: "index_summons_on_granblue_id"
|
||||||
t.index ["name_en"], name: "index_summons_on_name_en", opclass: :gin_trgm_ops, using: :gin
|
t.index ["name_en"], name: "index_summons_on_name_en", opclass: :gin_trgm_ops, using: :gin
|
||||||
end
|
end
|
||||||
|
|
@ -495,6 +501,10 @@ ActiveRecord::Schema[8.0].define(version: 2025_02_18_025315) do
|
||||||
t.date "transcendence_date"
|
t.date "transcendence_date"
|
||||||
t.string "recruits"
|
t.string "recruits"
|
||||||
t.integer "series"
|
t.integer "series"
|
||||||
|
t.integer "new_series"
|
||||||
|
t.text "wiki_raw"
|
||||||
|
t.text "game_raw_en"
|
||||||
|
t.text "game_raw_jp"
|
||||||
t.index ["granblue_id"], name: "index_weapons_on_granblue_id"
|
t.index ["granblue_id"], name: "index_weapons_on_granblue_id"
|
||||||
t.index ["name_en"], name: "index_weapons_on_name_en", opclass: :gin_trgm_ops, using: :gin
|
t.index ["name_en"], name: "index_weapons_on_name_en", opclass: :gin_trgm_ops, using: :gin
|
||||||
t.index ["recruits"], name: "index_weapons_on_recruits"
|
t.index ["recruits"], name: "index_weapons_on_recruits"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue