Models: Message, WikiPage, Game (typed structs instead of raw hashes) Repositories: MessageBoard, OnlineUsers, WikiClient, CatalogClient bbs.rb uses attribute access (page.title, game.play_path, …) throughout Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
43 lines
862 B
Ruby
43 lines
862 B
Ruby
# frozen_string_literal: true
|
|
|
|
require 'csv'
|
|
require 'time'
|
|
require 'fileutils'
|
|
require_relative '../model/message'
|
|
|
|
class MessageBoard
|
|
def initialize(path)
|
|
@path = path
|
|
@messages = []
|
|
@mu = Mutex.new
|
|
load_csv
|
|
end
|
|
|
|
def append(username, text)
|
|
msg = Message.new(Time.now.strftime('%m-%d %H:%M'), username, text)
|
|
@mu.synchronize do
|
|
@messages << msg
|
|
FileUtils.mkdir_p(File.dirname(@path))
|
|
CSV.open(@path, 'a') { |csv| csv << [msg.timestamp, msg.username, msg.text] }
|
|
end
|
|
msg
|
|
end
|
|
|
|
def last(n = 30)
|
|
@mu.synchronize { @messages.last(n) }
|
|
end
|
|
|
|
def count
|
|
@mu.synchronize { @messages.size }
|
|
end
|
|
|
|
private
|
|
|
|
def load_csv
|
|
return unless File.exist?(@path)
|
|
CSV.foreach(@path) { |row| @messages << Message.new(*row) }
|
|
rescue => e
|
|
warn "MessageBoard load error: #{e}"
|
|
end
|
|
end
|