initial rebuild from v1

This commit is contained in:
2021-04-22 22:31:23 +02:00
commit cc8cf4954d
152 changed files with 11559 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
//= link_tree ../images
//= link_directory ../stylesheets .css

0
app/assets/images/.keep Normal file
View File

View File

@@ -0,0 +1,19 @@
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
* vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*= require_tree .
*= require_self
*/
body {
background-color: rgb(21, 32, 43);
}

View File

@@ -0,0 +1,3 @@
// Place all the styles related to the home controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: https://sass-lang.com/

View File

@@ -0,0 +1,4 @@
module ApplicationCable
class Channel < ActionCable::Channel::Base
end
end

View File

@@ -0,0 +1,4 @@
module ApplicationCable
class Connection < ActionCable::Connection::Base
end
end

View File

@@ -0,0 +1,12 @@
class ApplicationController < ActionController::Base
around_action :switch_locale
def switch_locale(&action)
locale = I18n.default_locale
I18n.with_locale(locale, &action)
end
def new_session_path(_scope)
new_user_session_path
end
end

View File

View File

@@ -0,0 +1,4 @@
class HomeController < ApplicationController
def index
end
end

View File

@@ -0,0 +1,24 @@
# frozen_string_literal: true
# Controller: Callback
#
# Description: Callback method for Bnet
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
skip_before_action :verify_authenticity_token, only: :bnet
def bnet
@user = User.from_omniauth(request.env['omniauth.auth'])
if @user.persisted?
sign_in_and_redirect @user, event: :authentication
set_flash_message(:notice, :success, kind: 'Bnet') if is_navigational_format?
else
session['devise.bnet_data'] = request.env['omniauth.auth'].except(:extra)
redirect_to new_user_registration_url
end
end
def failure
redirect_to root_path
end
end

View File

@@ -0,0 +1,2 @@
module ApplicationHelper
end

View File

@@ -0,0 +1,2 @@
module HomeHelper
end

View File

@@ -0,0 +1,2 @@
module WelcomeHelper
end

View File

@@ -0,0 +1,6 @@
// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the `bin/rails generate channel` command.
import { createConsumer } from "@rails/actioncable"
export default createConsumer()

View File

@@ -0,0 +1,5 @@
// Load all the channels within this directory and all subdirectories.
// Channel files must be named *_channel.js.
const channels = require.context('.', true, /_channel\.js$/)
channels.keys().forEach(channels)

View File

@@ -0,0 +1,23 @@
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
import "bootstrap"
import "../stylesheets/application"
import "@fortawesome/fontawesome-free/css/all"
document.addEventListener("turbolinks:load", () => {
$('[data-toggle="tooltip"]').tooltip()
$('[data-toggle="popover"]').popover()
})
Rails.start()
Turbolinks.start()
ActiveStorage.start()

View File

@@ -0,0 +1 @@
@import "~bootstrap/scss/bootstrap";

View File

@@ -0,0 +1,7 @@
class ApplicationJob < ActiveJob::Base
# Automatically retry jobs that encountered a deadlock
# retry_on ActiveRecord::Deadlocked
# Most jobs are safe to ignore if the underlying records are no longer available
# discard_on ActiveJob::DeserializationError
end

View File

@@ -0,0 +1,4 @@
class ApplicationMailer < ActionMailer::Base
default from: 'from@example.com'
layout 'mailer'
end

View File

@@ -0,0 +1,3 @@
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end

View File

36
app/models/user.rb Normal file
View File

@@ -0,0 +1,36 @@
# frozen_string_literal: true
# Model: User
#
# Description: Define an application user. the only authentication mecanism
# is omniauthable with the BattleNet API
class User < ApplicationRecord
devise :rememberable, :omniauthable, omniauth_providers: [:bnet]
has_many :wow_characters, dependent: :destroy
validates :battletag, presence: true, uniqueness: true
def self.from_omniauth(auth)
user = User.where(provider: auth.provider, uid: auth.uid).first_or_initialize
user.provider = auth.provider
user.uid = auth.uid
user.battletag = auth.info.battletag
user.token_expires = auth.credentials.expires
user.token_expire_at = Time.at(auth.credentials.expires_at).utc
user.token = auth.credentials.token
user.save
user
end
def self.new_with_session(params, session)
super.tap do |user|
if (data = session['devise.bnet_data']) && session['devise.bnet_data']['extra']['raw_info']
user.email = data['email'] if user.email.blank?
end
end
end
end

View File

@@ -0,0 +1,14 @@
class WowCharacter < ApplicationRecord
extend Mobility
translates :translated_faction, :translated_gender
belongs_to :user
belongs_to :wow_realm
belongs_to :wow_class
belongs_to :wow_race
belongs_to :wow_character_title, optional: true
has_one :wow_character_medium, dependent: :nullify
validates :name, presence: true
validates :character_id, presence: true, uniqueness: true
end

View File

@@ -0,0 +1,3 @@
class WowCharacterMedium < ApplicationRecord
belongs_to :wow_character
end

View File

@@ -0,0 +1,9 @@
class WowCharacterTitle < ApplicationRecord
extend Mobility
translates :name, :male_name, :female_name
has_many :wow_characters, dependent: :nullify
validates :name, presence: true
validates :title_id, presence: true, uniqueness: true
end

9
app/models/wow_class.rb Normal file
View File

@@ -0,0 +1,9 @@
class WowClass < ApplicationRecord
extend Mobility
translates :name, :power_type, :male_name, :female_name
has_many :wow_characters, dependent: :nullify
validates :name, presence: true
validates :class_id, presence: true, uniqueness: true
end

9
app/models/wow_race.rb Normal file
View File

@@ -0,0 +1,9 @@
class WowRace < ApplicationRecord
extend Mobility
translates :name, :translated_faction, :male_name, :female_name
has_many :wow_characters, dependent: :nullify
validates :name, presence: true
validates :race_id, presence: true, uniqueness: true
end

10
app/models/wow_realm.rb Normal file
View File

@@ -0,0 +1,10 @@
class WowRealm < ApplicationRecord
extend Mobility
translates :name, :category, :realm_type
has_many :wow_characters, dependent: :nullify
validates :name, presence: true
validates :slug, presence: true
validates :realm_id, presence: true, uniqueness: true
end

View File

@@ -0,0 +1,2 @@
<h1>Home#index</h1>
<p>Find me in app/views/home/index.html.erb</p>

View File

@@ -0,0 +1,25 @@
<nav class="navbar fixed-top navbar-dark navbar-expand-lg bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="#">Northwhale 2</a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="nav navbar-nav flex-row ml-md-auto d-none d-md-flex">
<li class="nav-item">
<% if user_signed_in? %>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Menu
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li>Bnet: <%= current_user.battletag %></li>
<li><hr class="dropdown-divider"></li>
<li><%= link_to '<i class="fas fa-sign-out-alt"></i>'.html_safe, destroy_user_session_path, method: :delete %></li>
</ul>
</li>
<% else %>
<%= link_to 'Sign in with <i class="fab fa-battle-net"></i>'.html_safe, user_bnet_omniauth_authorize_path, method: :post, class: "btn btn-primary" %>
<% end %>
</li>
</ul>
</div>
</div>
</nav>

View File

@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<title>Northwhale2</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= render 'layouts/navbar' %>
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
<%= yield %>
</body>
</html>

View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
/* Email styles need to be inline */
</style>
</head>
<body>
<%= yield %>
</body>
</html>

View File

@@ -0,0 +1 @@
<%= yield %>

View File

@@ -0,0 +1,21 @@
class WowCharacterDetailWorker
include Sidekiq::Worker
def perform(wow_character_id)
return unless (wow_character = WowCharacter.where(character_id: wow_character_id).first)
RBattlenet.authenticate(client_id: ENV['BLIZZARD_API_CLIENT_ID'], client_secret: ENV['BLIZZARD_API_CLIENT_SECRET'])
RBattlenet.set_options(locale: 'en_GB')
result = RBattlenet::Wow::Character.find({ name: wow_character.name.downcase, realm: wow_character.wow_realm.slug })
return unless result.status_code == 200
wow_character.achievements_points = result.achievement_points
wow_character.last_login_timestamp = Time.at(result.last_login_timestamp.to_s[0..-4].to_i).utc
wow_character.average_item_level = result.average_item_level
wow_character.equipped_item_level = result.equipped_item_level
wow_character.wow_character_title = WowCharacterTitle.where(title_id: result.active_title.id).first if result.active_title
wow_character.save
end
end

View File

@@ -0,0 +1,35 @@
class WowCharacterMediaWorker
include Sidekiq::Worker
def perform(wow_character_id)
return unless (wow_character = WowCharacter.where(character_id: wow_character_id).first)
RBattlenet.authenticate(client_id: ENV['BLIZZARD_API_CLIENT_ID'], client_secret: ENV['BLIZZARD_API_CLIENT_SECRET'])
RBattlenet.set_options(locale: 'en_GB')
result = RBattlenet::Wow::Character::Media.find({ name: wow_character.name.downcase, realm: wow_character.wow_realm.slug })
return unless result.status_code == 200
return unless (wow_character_media = wow_character.wow_character_medium || WowCharacterMedium.new)
wow_character_media.wow_character = wow_character
wow_character_media.href = result._links.self.href
return unless result.assets
result.assets.each do |asset|
case asset['key']
when 'avatar'
wow_character_media.avatar = asset['value']
when 'inset'
wow_character_media.inset = asset['value']
when 'main'
wow_character_media.main = asset['value']
when 'main-raw'
wow_character_media.main_raw = asset['value']
end
end
wow_character_media.save
end
end

View File

@@ -0,0 +1,37 @@
class WowCharacterTitleDetailWorker
include Sidekiq::Worker
def perform(title_id)
locales = [
['en-us', 'en_US'],
['es-mx', 'es_MX'],
['pt-br', 'pt_BR'],
['de-de', 'de_DE'],
['en-gb', 'en_GB'],
['es-es', 'es_ES'],
['fr-fr', 'fr_FR'],
['it', 'it_IT'],
['ru-ru', 'ru_RU'],
['ko', 'ko_KR'],
['zh-tw', 'zh_TW'],
['zh-cn', 'zh_CN']
]
return unless (title = WowCharacterTitle.where(title_id: title_id).first)
RBattlenet.set_options(locale: 'all')
result = RBattlenet::Wow::Title.find(title_id)
return unless result.status_code == 200
# Localisation data
locales.each do |locale|
Mobility.with_locale(locale[0]) do
title.male_name = result.gender_name.male[locale[1]]
title.female_name = result.gender_name.female[locale[1]]
end
end
title.save
end
end

View File

@@ -0,0 +1,42 @@
class WowCharacterTitlesWorker
include Sidekiq::Worker
def perform
locales = [
['en-us', 'en_US'],
['es-mx', 'es_MX'],
['pt-br', 'pt_BR'],
['de-de', 'de_DE'],
['en-gb', 'en_GB'],
['es-es', 'es_ES'],
['fr-fr', 'fr_FR'],
['it', 'it_IT'],
['ru-ru', 'ru_RU'],
['ko', 'ko_KR'],
['zh-tw', 'zh_TW'],
['zh-cn', 'zh_CN']
]
RBattlenet.authenticate(client_id: ENV['BLIZZARD_API_CLIENT_ID'], client_secret: ENV['BLIZZARD_API_CLIENT_SECRET'])
RBattlenet.set_options(locale: 'all')
result = RBattlenet::Wow::Title.all
return unless result.status_code == 200
result.titles.each do |title|
wow_title = WowCharacterTitle.where(title_id: title.id).first_or_initialize
wow_title.title_id = title.id
wow_title.href = title.key.href
# Localisation data
locales.each do |locale|
Mobility.with_locale(locale[0]) { wow_title.name = title.name[locale[1]] }
end
wow_title.save
WowCharacterTitleDetailWorker.perform_async(wow_title.title_id) if wow_title.persisted?
end
end
end

View File

@@ -0,0 +1,60 @@
class WowCharactersWorker
include Sidekiq::Worker
def perform(user_id)
locales = [
['en-us', 'en_US'],
['es-mx', 'es_MX'],
['pt-br', 'pt_BR'],
['de-de', 'de_DE'],
['en-gb', 'en_GB'],
['es-es', 'es_ES'],
['fr-fr', 'fr_FR'],
['it', 'it_IT'],
['ru-ru', 'ru_RU'],
['ko', 'ko_KR'],
['zh-tw', 'zh_TW'],
['zh-cn', 'zh_CN']
]
# Update the WoW character list
return unless (user = User.find(user_id))
RBattlenet.set_options(locale: 'all')
result = RBattlenet::Wow::Profile::User.find(user.token)
return unless result.status_code == 200
result.wow_accounts.each do |account|
account.characters.each do |character|
wow_char = user.wow_characters.where(character_id: character.id).first_or_initialize
wow_char.name = character.name
wow_char.gender = character.gender.type
wow_char.faction = character.faction.type
wow_char.href = character.character.href
wow_char.level = character.level
wow_char.wow_realm = WowRealm.where(realm_id: character.realm.id).first
wow_char.wow_class = WowClass.where(class_id: character.playable_class.id).first
wow_char.wow_race = WowRace.where(race_id: character.playable_race.id).first
wow_char.user = user
wow_char.account_id = account.id
wow_char.character_id = character.id
locales.each do |locale|
Mobility.with_locale(locale[0]) do
wow_char.translated_faction = character.faction.name[locale[1]]
wow_char.translated_gender = character.gender.name[locale[1]]
end
end
wow_char.save
if wow_char.persisted?
WowCharacterMediaWorker.perform_async(wow_char.character_id)
WowCharacterDetailWorker.perform_async(wow_char.character_id)
end
end
end
end
end

View File

@@ -0,0 +1,38 @@
class WowClassDetailWorker
include Sidekiq::Worker
def perform(class_id)
locales = [
['en-us', 'en_US'],
['es-mx', 'es_MX'],
['pt-br', 'pt_BR'],
['de-de', 'de_DE'],
['en-gb', 'en_GB'],
['es-es', 'es_ES'],
['fr-fr', 'fr_FR'],
['it', 'it_IT'],
['ru-ru', 'ru_RU'],
['ko', 'ko_KR'],
['zh-tw', 'zh_TW'],
['zh-cn', 'zh_CN']
]
return unless (wow_class = WowClass.where(class_id: class_id).first)
RBattlenet.set_options(locale: 'all')
result = RBattlenet::Wow::PlayableClass.find(class_id)
return unless result.status_code == 200
# Localisation data
locales.each do |locale|
Mobility.with_locale(locale[0]) do
wow_class.power_type = result.power_type.name[locale[1]]
wow_class.male_name = result.gender_name.male[locale[1]]
wow_class.female_name = result.gender_name.female[locale[1]]
end
end
wow_class.save
end
end

View File

@@ -0,0 +1,42 @@
class WowClassesWorker
include Sidekiq::Worker
def perform
locales = [
['en-us', 'en_US'],
['es-mx', 'es_MX'],
['pt-br', 'pt_BR'],
['de-de', 'de_DE'],
['en-gb', 'en_GB'],
['es-es', 'es_ES'],
['fr-fr', 'fr_FR'],
['it', 'it_IT'],
['ru-ru', 'ru_RU'],
['ko', 'ko_KR'],
['zh-tw', 'zh_TW'],
['zh-cn', 'zh_CN']
]
RBattlenet.authenticate(client_id: ENV['BLIZZARD_API_CLIENT_ID'], client_secret: ENV['BLIZZARD_API_CLIENT_SECRET'])
RBattlenet.set_options(locale: 'all')
result = RBattlenet::Wow::PlayableClass.all
return unless result.status_code == 200
result.classes.each do |playable_class|
wow_class = WowClass.where(class_id: playable_class.id).first_or_initialize
wow_class.class_id = playable_class.id
wow_class.href = playable_class.key.href
# Localisation data
locales.each do |locale|
Mobility.with_locale(locale[0]) { wow_class.name = playable_class.name[locale[1]] }
end
wow_class.save
WowClassDetailWorker.perform_async(wow_class.class_id) if wow_class.persisted?
end
end
end

View File

@@ -0,0 +1,42 @@
class WowRaceDetailWorker
include Sidekiq::Worker
def perform(race_id)
locales = [
['en-us', 'en_US'],
['es-mx', 'es_MX'],
['pt-br', 'pt_BR'],
['de-de', 'de_DE'],
['en-gb', 'en_GB'],
['es-es', 'es_ES'],
['fr-fr', 'fr_FR'],
['it', 'it_IT'],
['ru-ru', 'ru_RU'],
['ko', 'ko_KR'],
['zh-tw', 'zh_TW'],
['zh-cn', 'zh_CN']
]
return unless (race = WowRace.where(race_id: race_id).first)
RBattlenet.set_options(locale: 'all')
result = RBattlenet::Wow::PlayableRace.find(race_id)
return unless result.status_code == 200
race.faction = result.faction.type
race.is_selectable = result.is_selectable
race.is_allied_race = result.is_allied_race
# Localisation data
locales.each do |locale|
Mobility.with_locale(locale[0]) do
race.translated_faction = result.faction.name[locale[1]]
race.male_name = result.gender_name.male[locale[1]]
race.female_name = result.gender_name.female[locale[1]]
end
end
race.save
end
end

View File

@@ -0,0 +1,43 @@
class WowRacesWorker
include Sidekiq::Worker
def perform
locales = [
['en-us', 'en_US'],
['es-mx', 'es_MX'],
['pt-br', 'pt_BR'],
['de-de', 'de_DE'],
['en-gb', 'en_GB'],
['es-es', 'es_ES'],
['fr-fr', 'fr_FR'],
['it', 'it_IT'],
['ru-ru', 'ru_RU'],
['ko', 'ko_KR'],
['zh-tw', 'zh_TW'],
['zh-cn', 'zh_CN']
]
RBattlenet.authenticate(client_id: ENV['BLIZZARD_API_CLIENT_ID'], client_secret: ENV['BLIZZARD_API_CLIENT_SECRET'])
RBattlenet.set_options(locale: 'all')
result = RBattlenet::Wow::PlayableRace.all
return unless result.status_code == 200
result.races.each do |playable_race|
wow_race = WowRace.where(race_id: playable_race.id).first_or_initialize
# Global data
wow_race.race_id = playable_race.id
wow_race.href = playable_race.key.href
# Localisation data
locales.each do |locale|
Mobility.with_locale(locale[0]) { wow_race.name = playable_race.name[locale[1]] }
end
wow_race.save
WowRaceDetailWorker.perform_async(wow_race.race_id) if wow_race.persisted?
end
end
end

View File

@@ -0,0 +1,41 @@
class WowRealmDetailWorker
include Sidekiq::Worker
def perform(realm_id)
locales = [
['en-us', 'en_US'],
['es-mx', 'es_MX'],
['pt-br', 'pt_BR'],
['de-de', 'de_DE'],
['en-gb', 'en_GB'],
['es-es', 'es_ES'],
['fr-fr', 'fr_FR'],
['it', 'it_IT'],
['ru-ru', 'ru_RU'],
['ko', 'ko_KR'],
['zh-tw', 'zh_TW'],
['zh-cn', 'zh_CN']
]
return unless (realm = WowRealm.where(realm_id: realm_id).first)
RBattlenet.set_options(locale: 'all')
result = RBattlenet::Wow::Realm.find(realm_id)
return unless result.status_code == 200
realm.locale = result.locale
realm.timezone = result.timezone
realm.is_tournament = result.is_tournament
# Localisation data
locales.each do |locale|
Mobility.with_locale(locale[0]) do
realm.realm_type = result.type.name[locale[1]]
realm.category = result.category[locale[1]]
end
end
realm.save
end
end

View File

@@ -0,0 +1,43 @@
class WowRealmsWorker
include Sidekiq::Worker
def perform
locales = [
['en-us', 'en_US'],
['es-mx', 'es_MX'],
['pt-br', 'pt_BR'],
['de-de', 'de_DE'],
['en-gb', 'en_GB'],
['es-es', 'es_ES'],
['fr-fr', 'fr_FR'],
['it', 'it_IT'],
['ru-ru', 'ru_RU'],
['ko', 'ko_KR'],
['zh-tw', 'zh_TW'],
['zh-cn', 'zh_CN']
]
RBattlenet.authenticate(client_id: ENV['BLIZZARD_API_CLIENT_ID'], client_secret: ENV['BLIZZARD_API_CLIENT_SECRET'])
RBattlenet.set_options(locale: 'all')
result = RBattlenet::Wow::Realm.all
return unless result.status_code == 200
result.realms.each do |realm|
wow_realm = WowRealm.where(realm_id: realm.id).first_or_initialize
wow_realm.realm_id = realm.id
wow_realm.slug = realm.slug
wow_realm.href = realm.key.href
# Localisation data
locales.each do |locale|
Mobility.with_locale(locale[0]) { wow_realm.name = realm.name[locale[1]] }
end
wow_realm.save
WowRealmDetailWorker.perform_async(wow_realm.realm_id) if wow_realm.persisted?
end
end
end