module Simple2ch
class Res
# @return [Fixnum] レス番号
attr_reader :res_num
# @return [String] 投稿者名
attr_reader :author
# @return [String] ID
attr_reader :author_id
# @return [Time] 書き込み日時
attr_reader :date
# @return [String] メール欄
attr_reader :mail
# @return [String] 内容
attr_reader :contents
# @attr_writer [Thre] thre スレッド
attr_writer :thre
KAKO_LOG_INFO = '過去ログ ★<><>[過去ログ]<>■ このスレッドは過去ログ倉庫に格納されています<>'
#
# @param [Fixnum] res_num レス番号
# @param [String] author 投稿者名
# @param [String] author_id ID
# @param [Time] date 書き込み日時
# @param [String] mail メール欄
# @param [String] contents 内容
def initialize(res_num, author: '', author_id: '', date: nil, mail: '', contents: '', thre: nil)
@res_num = res_num
@author = author
@author_id = author_id
@date = date
@mail = mail
@contents = contents
@thre = thre
end
# Datの1行から各項目を分離して、Resオブジェクトを返す
# @param [Fixnum] res_num レス番号
# @param [String] contents datのデータ1行
# @return [Res] 新規Resオブジェクト
# @raise [KakoLogException] 過去ログ情報をパースしようとした際に発生
def self.parse(res_num, contents, thre=nil)
unless contents.strip == KAKO_LOG_INFO
hash = parse_dat(contents)
hash[:thre] = thre if thre
return self.new(res_num, hash)
else
raise KakoLogException
end
end
# アンカーを抽出する 荒らしの場合は空配列を返す
# @return [Array] 昇順ソート済みアンカー、荒らしの場合は空配列
def anchors
arashi_removal_regex = /(?:\d{1,4}(?:\]*>)?(?:>|\[>,+-\]){1,2}){9}/
unless self.contents =~ arashi_removal_regex
splitter_regex = '[,、, ]'
digit_regex = '(?:\d|[0-9])+'
hyphen_regex = '[−ーー\-〜~〜]'
extracted = self.contents.scan />((?:#{digit_regex}(?:#{splitter_regex}|#{hyphen_regex})*)+)/
anchors = extracted.flatten.to_s.gsub(/[\"\[\]]/,'').split(/#{splitter_regex}/)
anchors.delete('')
anchors.map! do |a|
if a =~ /(#{digit_regex})#{hyphen_regex}(#{digit_regex})/
(Range.new parseInt($1), parseInt($2)).to_a
else
parseInt(a)
end
end
anchors.flatten.uniq.sort
else
[]
end
end
# 自レスへのアンカーが書き込まれているレス番号を返す
# @return [Array] レス番号
def received_anchors
thre = get_thre
received_anchors = thre.received_anchors
received_anchors.fetch(@res_num, [])
end
private
# スレッドを取得する
# @return [Thre] スレッド
def get_thre
if @thre
@thre
else
raise NoThreGivenException
end
end
# 全角数字をFixnumへ変換する
# @param [String] strnum 全角数字
# @return [Fixnum] 数字
def parseInt(strnum)
(Charwidth.normalize strnum).to_i
end
# Datの1行から各項目を分離して、Resオブジェクトを返すメソッドの実体
# @param [String] dat datのデータ1行
# @raise [DatParseException] Datのパースに失敗したときに発生
def self.parse_dat(dat)
split_date_and_id_regex = /(?