diff --git a/Gemfile b/Gemfile index 1ebc6f4..0a2099d 100644 --- a/Gemfile +++ b/Gemfile @@ -5,3 +5,7 @@ source "https://rubygems.org" # gem "rails" gem "sequel", "~> 5.72" + +gem "websocket", "~> 1.2" + +gem "websocket-eventmachine-server", "~> 1.0" diff --git a/Gemfile.lock b/Gemfile.lock index ab0303d..b569531 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,14 +2,25 @@ GEM remote: https://rubygems.org/ specs: bigdecimal (3.1.4) + eventmachine (1.2.7) sequel (5.72.0) bigdecimal + websocket (1.2.10) + websocket-eventmachine-base (1.2.0) + eventmachine (~> 1.0) + websocket (~> 1.0) + websocket-native (~> 1.0) + websocket-eventmachine-server (1.0.1) + websocket-eventmachine-base (~> 1.0) + websocket-native (1.0.0) PLATFORMS x86_64-linux DEPENDENCIES sequel (~> 5.72) + websocket (~> 1.2) + websocket-eventmachine-server (~> 1.0) BUNDLED WITH 2.4.10 diff --git a/LICENSE b/LICENSE index 16fa760..e4fb36b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ PixelRidge Business Exclusive General Public Use License for Software Executables (PixelRidge-BEGPULSE) -## Version 1.2 +## Version 1.3 ### Preamble @@ -20,7 +20,7 @@ Subject to the terms and conditions of this License, Licensor hereby grants you ### 3. Attribution -You must provide proper attribution to the Licensor by including a plain-view backlink to the Licensor's website. This backlink must be easily visible to all users and not hidden under any circumstances. +You must provide attribution to the Licensor by including a plain-view URI (or link) to the Licensor's website. This link must be easily visible to all users and not hidden under any circumstances. It should be noted that this should only apply in the event that it can. In the event a public link is impossible due to the nature of the usage of the Software, it's expected that attribution be given in a way such that the attribution complies with the Open Source Initiative standards for Open Source Attribution. ### 4. Business Use @@ -36,11 +36,11 @@ The Software is provided "AS-IS," without any warranty of any kind, either expre ### 7. Updates and Versioning -PixelRidge Softworks may or may not provide updates to the Software in the future. There is no obligation to provide updates or support for the Software. The latest version of this License shall always be considered the governing terms. PixelRidge Softworks will provide reasonable notice in the event of a license change. +PixelRidge Softworks may or may not provide updates to the Software in the future. There is no obligation to provide updates or support for the Software. The latest version of this License shall always be considered the governing terms. PixelRidge Softworks will provide reasonable notice in the event of a license change. Notice shall be provided via email. Due to spam laws, we cannot just email you. You may opt into our specialized mailing list for licensing on our website. ### 8. Source Code Availability -Any modifications to the Software must remain open-source and source-available in their entirety. +Any modifications to the Software must remain open-source and source-available in their entirety unless another agreement with the Licensor is formed. ### 9. Compliance Monitoring @@ -68,4 +68,4 @@ This License shall be governed by the laws of Alberta, Canada. ### 15. Miscellaneous -This License constitutes the entire agreement between you and PixelRidge Softworks concerning the Software. It may only be modified in writing, signed by both parties. +This License constitutes the entire agreement between you and PixelRidge Softworks concerning the Software. diff --git a/bin/start_repoquest_server.rb b/bin/start_repoquest_server.rb index e69de29..527c539 100644 --- a/bin/start_repoquest_server.rb +++ b/bin/start_repoquest_server.rb @@ -0,0 +1,28 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require_relative '../lib/repoquest_server' +require_relative '../lib/database/repoquest_db_connector' + +# Initialize database connector and run migrations +db_connector = RepoQuestDBConnector.new +db_connector.run_migrations + +# Initialize the RepoQuest server +port = 8080 +server = RepoQuest::Server.new(port, db_connector) + +# Signal handling for graceful shutdown +Signal.trap('INT') do + puts 'Received SIGINT. Shutting down...' + EM.stop +end + +Signal.trap('TERM') do + puts 'Received SIGTERM. Shutting down...' + EM.stop +end + +# Start the server +puts "Starting RepoQuest server on port #{port}..." +server.start diff --git a/config/repoquest_database.yml b/config/repoquest_database.yml deleted file mode 100644 index e69de29..0000000 diff --git a/lib/database/migrations/001_create_players.rb b/lib/database/migrations/001_create_players.rb new file mode 100644 index 0000000..9f59a41 --- /dev/null +++ b/lib/database/migrations/001_create_players.rb @@ -0,0 +1,14 @@ +# lib/database/migrations/001_create_players.rb +Sequel.migration do + change do + create_table :players do + primary_key :player_number + String :player_id, unique: true + String :username + Integer :player_level + Integer :times_gained_xp + DateTime :created_at + DateTime :updated_at + end + end +end diff --git a/lib/database/migrations/001_create_users_and_xp_gain_tables.rb b/lib/database/migrations/001_create_users_and_xp_gain_tables.rb deleted file mode 100644 index d1cbe68..0000000 --- a/lib/database/migrations/001_create_users_and_xp_gain_tables.rb +++ /dev/null @@ -1,26 +0,0 @@ -# db/migrations/001_create_users_and_xp_gain_tables.rb -Sequel.migration do - up do - create_table(:users) do - primary_key :id - String :user_id, unique: true - String :username - Integer :current_level - Integer :total_xp - end - - create_table(:xp_gain) do - primary_key :id - String :commit_id - Integer :xp_gained - DateTime :time_of_gain - Integer :total_gains - foreign_key :user_id, :users - end - end - - down do - drop_table(:xp_gain) - drop_table(:users) - end -end diff --git a/lib/database/migrations/002_create_repos.rb b/lib/database/migrations/002_create_repos.rb new file mode 100644 index 0000000..b64a24b --- /dev/null +++ b/lib/database/migrations/002_create_repos.rb @@ -0,0 +1,12 @@ +# lib/database/migrations/002_create_repos.rb +Sequel.migration do + change do + create_table :repos do + primary_key :repo_id + String :repo_name + String :repo_link + DateTime :created_at + DateTime :updated_at + end + end +end diff --git a/lib/database/models/player.rb b/lib/database/models/player.rb new file mode 100644 index 0000000..782604d --- /dev/null +++ b/lib/database/models/player.rb @@ -0,0 +1,7 @@ +# lib/database/models/player.rb +require 'sequel' + +class Player < Sequel::Model + set_primary_key :player_number + plugin :timestamps, update_on_create: true +end diff --git a/lib/database/models/repo.rb b/lib/database/models/repo.rb new file mode 100644 index 0000000..c52720e --- /dev/null +++ b/lib/database/models/repo.rb @@ -0,0 +1,7 @@ +# lib/database/models/repo.rb +require 'sequel' + +class Repo < Sequel::Model + set_primary_key :repo_id + plugin :timestamps, update_on_create: true +end diff --git a/lib/database/repoquest_db_connector.rb b/lib/database/repoquest_db_connector.rb index 744c75a..6b4f072 100644 --- a/lib/database/repoquest_db_connector.rb +++ b/lib/database/repoquest_db_connector.rb @@ -1,13 +1,23 @@ -# lib/database/repoquest_db_connector.rb require 'sequel' +require 'fileutils' class RepoQuestDBConnector - def initialize(db_file = 'sqlite://repoquest.db') - @db = Sequel.connect(db_file) + def initialize(db_file = 'repoquest.db') + db_path = File.join(Dir.pwd, db_file) + + # Check if SQLite file exists, if not, create it + FileUtils.touch(db_path) unless File.exist?(db_path) + + @db = Sequel.connect("sqlite://#{db_path}") + rescue Sequel::Error => e + puts "Database connection failed: #{e.message}" + exit 1 end - def run_migrations + def run_migrations(migration_path = 'lib/database/migrations/') Sequel.extension :migration - Sequel::Migrator.run(@db, 'db/migrations/') + Sequel::Migrator.run(@db, migration_path) + rescue Sequel::Error => e + puts "Migration failed: #{e.message}" end end diff --git a/lib/repoquest_server.rb b/lib/repoquest_server.rb index e69de29..542432d 100644 --- a/lib/repoquest_server.rb +++ b/lib/repoquest_server.rb @@ -0,0 +1,70 @@ +require 'websocket-eventmachine-server' +require 'sequel' +require 'json' +require_relative 'database/models/player' +require_relative 'database/models/repo' + +module RepoQuest + class Server + def initialize(port, db_connector) + @port = port + @db_connector = db_connector + @db = @db_connector.db # Assuming you have a method in db_connector that returns the Sequel database object + end + + def start + EM.run do + WebSocket::EventMachine::Server.start(host: '0.0.0.0', port: @port) do |ws| + ws.onopen do + puts 'Client connected' + end + + ws.onmessage do |msg| + Fiber.new do + handle_message(msg, ws) + end.resume + end + + ws.onclose do + puts 'Client disconnected' + end + end + end + end + + private + + def handle_message(message, _ws) + parsed_data = JSON.parse(message) + user_id = parsed_data['user_id'] + xp_gained = parsed_data['xp_gained'] + repo_pushed_to = parsed_data['repo_pushed_to'] + + if user_id && xp_gained && repo_pushed_to + update_player_info(user_id, xp_gained) + update_repo_info(repo_pushed_to) + else + puts 'Invalid data received.' + end + rescue JSON::ParserError => e + puts "Error parsing JSON: #{e.message}" + end + + def update_player_info(user_id, xp_gained) + player = Player.where(player_id: user_id).first + if player + player.update(player_level: player.player_level + xp_gained, + times_gained_xp: player.times_gained_xp + 1) + else + puts "Player with ID #{user_id} not found." + end + end + + def update_repo_info(repo_pushed_to) + repo = Repo.where(repo_link: repo_pushed_to).first + return if repo + + Repo.create(repo_link: repo_pushed_to) + end + end +end diff --git a/lib/websocket/repoquest_frame_parser.rb b/lib/websocket/repoquest_frame_parser.rb deleted file mode 100644 index e69de29..0000000 diff --git a/lib/websocket/repoquest_handshake.rb b/lib/websocket/repoquest_handshake.rb deleted file mode 100644 index e69de29..0000000