wikidotrb 3.0.7.pre.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +77 -0
- data/CHANGELOG.md +52 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/Rakefile +12 -0
- data/_config.yml +4 -0
- data/lib/wikidotrb/common/decorators.rb +81 -0
- data/lib/wikidotrb/common/exceptions.rb +88 -0
- data/lib/wikidotrb/common/logger.rb +25 -0
- data/lib/wikidotrb/connector/ajax.rb +192 -0
- data/lib/wikidotrb/connector/api.rb +20 -0
- data/lib/wikidotrb/module/auth.rb +76 -0
- data/lib/wikidotrb/module/client.rb +146 -0
- data/lib/wikidotrb/module/forum.rb +92 -0
- data/lib/wikidotrb/module/forum_category.rb +197 -0
- data/lib/wikidotrb/module/forum_group.rb +109 -0
- data/lib/wikidotrb/module/forum_post.rb +223 -0
- data/lib/wikidotrb/module/forum_thread.rb +346 -0
- data/lib/wikidotrb/module/page.rb +598 -0
- data/lib/wikidotrb/module/page_revision.rb +142 -0
- data/lib/wikidotrb/module/page_source.rb +17 -0
- data/lib/wikidotrb/module/page_votes.rb +31 -0
- data/lib/wikidotrb/module/private_message.rb +142 -0
- data/lib/wikidotrb/module/site.rb +207 -0
- data/lib/wikidotrb/module/site_application.rb +97 -0
- data/lib/wikidotrb/module/user.rb +119 -0
- data/lib/wikidotrb/util/parser/odate.rb +47 -0
- data/lib/wikidotrb/util/parser/user.rb +105 -0
- data/lib/wikidotrb/util/quick_module.rb +61 -0
- data/lib/wikidotrb/util/requestutil.rb +51 -0
- data/lib/wikidotrb/util/stringutil.rb +39 -0
- data/lib/wikidotrb/util/table/char_table.rb +477 -0
- data/lib/wikidotrb/version.rb +5 -0
- data/lib/wikidotrb.rb +41 -0
- data/sig/wikidotrb.rbs +4 -0
- metadata +197 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wikidotrb
|
4
|
+
module Connector
|
5
|
+
# APIキーのオブジェクト
|
6
|
+
class APIKeys
|
7
|
+
# 読み取り専用の属性
|
8
|
+
attr_reader :ro_key, :rw_key
|
9
|
+
|
10
|
+
# 初期化
|
11
|
+
# @param ro_key [String] Read Only Key
|
12
|
+
# @param rw_key [String] Read-Write Key
|
13
|
+
def initialize(ro_key:, rw_key:)
|
14
|
+
@ro_key = ro_key
|
15
|
+
@rw_key = rw_key
|
16
|
+
freeze
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "httpx"
|
4
|
+
require "uri"
|
5
|
+
require "json"
|
6
|
+
require_relative "../common/exceptions"
|
7
|
+
|
8
|
+
module Wikidotrb
|
9
|
+
module Module
|
10
|
+
class HTTPAuthentication
|
11
|
+
# ユーザー名とパスワードでログインする
|
12
|
+
# @param client [Client] クライアント
|
13
|
+
# @param username [String] ユーザー名
|
14
|
+
# @param password [String] パスワード
|
15
|
+
# @raise [SessionCreateException] セッション作成に失敗した場合
|
16
|
+
def self.login(client, username, password)
|
17
|
+
url = "https://www.wikidot.com/default--flow/login__LoginPopupScreen"
|
18
|
+
|
19
|
+
# ログインリクエストのデータを作成
|
20
|
+
request_data = {
|
21
|
+
"login" => username,
|
22
|
+
"password" => password,
|
23
|
+
"action" => "Login2Action",
|
24
|
+
"event" => "login"
|
25
|
+
}
|
26
|
+
|
27
|
+
response = HTTPX.post(
|
28
|
+
url,
|
29
|
+
headers: client.amc_client.header.get_header,
|
30
|
+
form: request_data,
|
31
|
+
timeout: { operation: 20 }
|
32
|
+
)
|
33
|
+
|
34
|
+
# ステータスコードのチェック
|
35
|
+
unless response.status == 200
|
36
|
+
raise Wikidotrb::Common::Exceptions::SessionCreateException,
|
37
|
+
"Login attempt is failed due to HTTP status code: #{response.status}"
|
38
|
+
end
|
39
|
+
|
40
|
+
# レスポンスボディのチェック
|
41
|
+
if response.body.to_s.include?("The login and password do not match")
|
42
|
+
raise Wikidotrb::Common::Exceptions::SessionCreateException,
|
43
|
+
"Login attempt is failed due to invalid username or password"
|
44
|
+
end
|
45
|
+
|
46
|
+
# クッキーのチェックとパース
|
47
|
+
set_cookie_header = response.headers["set-cookie"]
|
48
|
+
|
49
|
+
# `set-cookie` が存在しない、または `nil` の場合にエラーを発生
|
50
|
+
raise Wikidotrb::Common::Exceptions::SessionCreateException, "Login attempt is failed due to invalid cookies" if set_cookie_header.nil? || set_cookie_header.empty?
|
51
|
+
|
52
|
+
# セッションクッキーを取得
|
53
|
+
session_cookie = set_cookie_header.match(/WIKIDOT_SESSION_ID=([^;]+)/)
|
54
|
+
|
55
|
+
raise Wikidotrb::Common::Exceptions::SessionCreateException, "Login attempt is failed due to invalid cookies" unless session_cookie
|
56
|
+
|
57
|
+
# セッションクッキーの設定
|
58
|
+
client.amc_client.header.set_cookie("WIKIDOT_SESSION_ID", session_cookie[1])
|
59
|
+
end
|
60
|
+
|
61
|
+
# ログアウトする
|
62
|
+
# @param client [Client] クライアント
|
63
|
+
def self.logout(client)
|
64
|
+
begin
|
65
|
+
client.amc_client.request(
|
66
|
+
[{ "action" => "Login2Action", "event" => "logout", "moduleName" => "Empty" }]
|
67
|
+
)
|
68
|
+
rescue StandardError
|
69
|
+
# 例外を無視してログアウト処理を続ける
|
70
|
+
end
|
71
|
+
|
72
|
+
client.amc_client.header.delete_cookie("WIKIDOT_SESSION_ID")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../common/logger"
|
4
|
+
require_relative "../common/exceptions"
|
5
|
+
require_relative "../connector/ajax"
|
6
|
+
require_relative "auth"
|
7
|
+
require_relative "private_message"
|
8
|
+
require_relative "site"
|
9
|
+
require_relative "user"
|
10
|
+
|
11
|
+
module Wikidotrb
|
12
|
+
module Module
|
13
|
+
class ClientUserMethods
|
14
|
+
attr_reader :client
|
15
|
+
|
16
|
+
def initialize(client)
|
17
|
+
@client = client
|
18
|
+
end
|
19
|
+
|
20
|
+
# ユーザー名からユーザーオブジェクトを取得する
|
21
|
+
# @param name [String] ユーザー名
|
22
|
+
# @param raise_when_not_found [Boolean] ユーザーが見つからない場合に例外を送出するか
|
23
|
+
# @return [User] ユーザーオブジェクト
|
24
|
+
def get(name, raise_when_not_found: false)
|
25
|
+
Wikidotrb::Module::User.from_name(@client, name, raise_when_not_found)
|
26
|
+
end
|
27
|
+
|
28
|
+
# ユーザー名からユーザーオブジェクトを取得する
|
29
|
+
# @param names [Array<String>] ユーザー名のリスト
|
30
|
+
# @param raise_when_not_found [Boolean] ユーザーが見つからない場合に例外を送出するか
|
31
|
+
# @return [Array<User>] ユーザーオブジェクトのリスト
|
32
|
+
def get_bulk(names, raise_when_not_found: false)
|
33
|
+
Wikidotrb::Module::UserCollection.from_names(@client, names, raise_when_not_found)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class ClientPrivateMessageMethods
|
38
|
+
attr_reader :client
|
39
|
+
|
40
|
+
def initialize(client)
|
41
|
+
@client = client
|
42
|
+
end
|
43
|
+
|
44
|
+
# メッセージを送信する
|
45
|
+
# @param recipient [User] 受信者
|
46
|
+
# @param subject [String] 件名
|
47
|
+
# @param body [String] 本文
|
48
|
+
def send_message(recipient, subject, body)
|
49
|
+
Wikidotrb::Module::PrivateMessage.send_message(
|
50
|
+
client: @client, recipient: recipient, subject: subject, body: body
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
# 受信箱を取得する
|
55
|
+
# @return [PrivateMessageInbox] 受信箱
|
56
|
+
def get_inbox
|
57
|
+
Wikidotrb::Module::PrivateMessageInbox.acquire(client: @client)
|
58
|
+
end
|
59
|
+
|
60
|
+
# 送信箱を取得する
|
61
|
+
# @return [PrivateMessageSentBox] 送信箱
|
62
|
+
def get_sentbox
|
63
|
+
Wikidotrb::Module::PrivateMessageSentBox.acquire(client: @client)
|
64
|
+
end
|
65
|
+
|
66
|
+
# メッセージを取得する
|
67
|
+
# @param message_ids [Array<Integer>] メッセージIDのリスト
|
68
|
+
# @return [PrivateMessageCollection] メッセージのリスト
|
69
|
+
def get_messages(message_ids)
|
70
|
+
Wikidotrb::Module::PrivateMessageCollection.from_ids(client: @client, message_ids: message_ids)
|
71
|
+
end
|
72
|
+
|
73
|
+
# メッセージを取得する
|
74
|
+
# @param message_id [Integer] メッセージID
|
75
|
+
# @return [PrivateMessage] メッセージ
|
76
|
+
def get_message(message_id)
|
77
|
+
Wikidotrb::Module::PrivateMessage.from_id(client: @client, message_id: message_id)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class ClientSiteMethods
|
82
|
+
attr_reader :client
|
83
|
+
|
84
|
+
def initialize(client)
|
85
|
+
@client = client
|
86
|
+
end
|
87
|
+
|
88
|
+
# UNIX名からサイトオブジェクトを取得する
|
89
|
+
# @param unix_name [String] サイトのUNIX名
|
90
|
+
# @return [Site] サイトオブジェクト
|
91
|
+
def get(unix_name)
|
92
|
+
Wikidotrb::Module::Site.from_unix_name(client: client, unix_name: unix_name)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class Client
|
97
|
+
attr_accessor :amc_client, :is_logged_in, :username
|
98
|
+
attr_reader :user, :private_message, :site
|
99
|
+
|
100
|
+
# 基幹クライアント
|
101
|
+
def initialize(username: nil, password: nil, amc_config: nil, logging_level: "WARN")
|
102
|
+
# 最初にロギングレベルを決定する
|
103
|
+
Wikidotrb::Common::Logger.level = logging_level
|
104
|
+
|
105
|
+
# AMCClientを初期化
|
106
|
+
@amc_client = Wikidotrb::Connector::AjaxModuleConnectorClient.new(site_name: "www", config: amc_config)
|
107
|
+
|
108
|
+
# セッション関連変数の初期化
|
109
|
+
@is_logged_in = false
|
110
|
+
@username = nil
|
111
|
+
|
112
|
+
# usernameとpasswordが指定されていればログインする
|
113
|
+
if username && password
|
114
|
+
Wikidotrb::Module::HTTPAuthentication.login(self, username, password)
|
115
|
+
@is_logged_in = true
|
116
|
+
@username = username
|
117
|
+
end
|
118
|
+
|
119
|
+
# メソッドの定義
|
120
|
+
@user = ClientUserMethods.new(self)
|
121
|
+
@private_message = ClientPrivateMessageMethods.new(self)
|
122
|
+
@site = ClientSiteMethods.new(self)
|
123
|
+
end
|
124
|
+
|
125
|
+
# デストラクタ
|
126
|
+
def finalize
|
127
|
+
return unless @is_logged_in
|
128
|
+
|
129
|
+
Wikidotrb::Module::HTTPAuthentication.logout(self)
|
130
|
+
@is_logged_in = false
|
131
|
+
@username = nil
|
132
|
+
end
|
133
|
+
|
134
|
+
def to_s
|
135
|
+
"Client(username=#{@username}, is_logged_in=#{@is_logged_in})"
|
136
|
+
end
|
137
|
+
|
138
|
+
# ログインチェック
|
139
|
+
def login_check
|
140
|
+
raise Wikidotrb::Common::Exceptions::LoginRequiredException, "Login is required to execute this function" unless @is_logged_in
|
141
|
+
|
142
|
+
nil
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "forum_category"
|
4
|
+
require_relative "forum_group"
|
5
|
+
require_relative "forum_thread"
|
6
|
+
|
7
|
+
module Wikidotrb
|
8
|
+
module Module
|
9
|
+
class ForumCategoryMethods
|
10
|
+
# 初期化メソッド
|
11
|
+
# @param forum [Forum] フォーラムオブジェクト
|
12
|
+
def initialize(forum)
|
13
|
+
@forum = forum
|
14
|
+
end
|
15
|
+
|
16
|
+
# カテゴリをIDから取得
|
17
|
+
# @param id [Integer] カテゴリID
|
18
|
+
# @return [ForumCategory] 更新されたカテゴリ
|
19
|
+
def get(id)
|
20
|
+
category = ForumCategory.new(
|
21
|
+
site: @forum.site,
|
22
|
+
id: id,
|
23
|
+
forum: @forum
|
24
|
+
)
|
25
|
+
category.update
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class ForumThreadMethods
|
30
|
+
# 初期化メソッド
|
31
|
+
# @param forum [Forum] フォーラムオブジェクト
|
32
|
+
def initialize(forum)
|
33
|
+
@forum = forum
|
34
|
+
end
|
35
|
+
|
36
|
+
# スレッドをIDから取得
|
37
|
+
# @param id [Integer] スレッドID
|
38
|
+
# @return [ForumThread] 更新されたスレッド
|
39
|
+
def get(id)
|
40
|
+
thread = ForumThread.new(
|
41
|
+
site: @forum.site,
|
42
|
+
id: id,
|
43
|
+
forum: @forum
|
44
|
+
)
|
45
|
+
thread.update
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Forum
|
50
|
+
attr_accessor :site, :_groups, :_categories
|
51
|
+
|
52
|
+
# 初期化メソッド
|
53
|
+
# @param site [Site] サイトオブジェクト
|
54
|
+
def initialize(site:)
|
55
|
+
@site = site
|
56
|
+
@name = "Forum"
|
57
|
+
@_groups = nil
|
58
|
+
@_categories = nil
|
59
|
+
@category = ForumCategoryMethods.new(self)
|
60
|
+
@thread = ForumThreadMethods.new(self)
|
61
|
+
end
|
62
|
+
|
63
|
+
# カテゴリメソッドオブジェクトを取得
|
64
|
+
# @return [ForumCategoryMethods] カテゴリメソッド
|
65
|
+
attr_reader :category
|
66
|
+
|
67
|
+
# スレッドメソッドオブジェクトを取得
|
68
|
+
# @return [ForumThreadMethods] スレッドメソッド
|
69
|
+
attr_reader :thread
|
70
|
+
|
71
|
+
# フォーラムのURLを取得
|
72
|
+
# @return [String] フォーラムのURL
|
73
|
+
def get_url
|
74
|
+
"#{@site.get_url}/forum/start"
|
75
|
+
end
|
76
|
+
|
77
|
+
# グループのプロパティ
|
78
|
+
# @return [ForumGroupCollection] グループコレクション
|
79
|
+
def groups
|
80
|
+
ForumGroupCollection.get_groups(site: @site, forum: self) if @_groups.nil?
|
81
|
+
@_groups
|
82
|
+
end
|
83
|
+
|
84
|
+
# カテゴリのプロパティ
|
85
|
+
# @return [ForumCategoryCollection] カテゴリコレクション
|
86
|
+
def categories
|
87
|
+
ForumCategoryCollection.get_categories(site: @site, forum: self) if @_categories.nil?
|
88
|
+
@_categories
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "nokogiri"
|
4
|
+
require "date"
|
5
|
+
require_relative "forum_thread"
|
6
|
+
|
7
|
+
module Wikidotrb
|
8
|
+
module Module
|
9
|
+
class ForumCategoryCollection < Array
|
10
|
+
attr_accessor :forum
|
11
|
+
|
12
|
+
# 初期化メソッド
|
13
|
+
# @param forum [Forum] フォーラムオブジェクト
|
14
|
+
# @param categories [Array<ForumCategory>] カテゴリーのリスト
|
15
|
+
def initialize(forum:, categories: [])
|
16
|
+
super(categories)
|
17
|
+
@forum = forum
|
18
|
+
end
|
19
|
+
|
20
|
+
# サイトとフォーラムからカテゴリを取得
|
21
|
+
# @param site [Site] サイトオブジェクト
|
22
|
+
# @param forum [Forum] フォーラムオブジェクト
|
23
|
+
def self.get_categories(site:, forum:)
|
24
|
+
categories = []
|
25
|
+
|
26
|
+
forum.groups.each do |group|
|
27
|
+
categories.concat(group.categories)
|
28
|
+
end
|
29
|
+
|
30
|
+
forum._categories = ForumCategoryCollection.new(forum: forum, categories: categories)
|
31
|
+
end
|
32
|
+
|
33
|
+
# IDまたはタイトルからカテゴリを検索
|
34
|
+
# @param id [Integer] カテゴリID
|
35
|
+
# @param title [String] カテゴリのタイトル
|
36
|
+
# @return [ForumCategory, nil] 一致するカテゴリ
|
37
|
+
def find(id: nil, title: nil)
|
38
|
+
find do |category|
|
39
|
+
(id.nil? || category.id == id) && (title.nil? || category.title == title)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# カテゴリ情報を取得して更新する
|
44
|
+
# @param forum [Forum] フォーラムオブジェクト
|
45
|
+
# @param categories [Array<ForumCategory>] カテゴリーのリスト
|
46
|
+
# @return [Array<ForumCategory>] 更新されたカテゴリのリスト
|
47
|
+
def self.acquire_update(forum:, categories:)
|
48
|
+
return categories if categories.empty?
|
49
|
+
|
50
|
+
responses = forum.site.amc_request(
|
51
|
+
bodies: categories.map { |category| { "c" => category.id, "moduleName" => "forum/ForumViewCategoryModule" } }
|
52
|
+
)
|
53
|
+
|
54
|
+
responses.each_with_index do |response, index|
|
55
|
+
category = categories[index]
|
56
|
+
html = Nokogiri::HTML(response.body.to_s)
|
57
|
+
statistics = html.at_css("div.statistics").text
|
58
|
+
description = html.at_css("div.description-block").text.strip
|
59
|
+
info = html.at_css("div.forum-breadcrumbs").text.match(%r{([ \S]*) / ([ \S]*)})
|
60
|
+
counts = statistics.scan(/\d+/).map(&:to_i)
|
61
|
+
|
62
|
+
category.last = nil if category.posts_counts != counts[1]
|
63
|
+
category.description = description.match(/[ \S]*$/)[0]
|
64
|
+
category.threads_counts, category.posts_counts = counts
|
65
|
+
category.group = category.forum.groups.find(info[1])
|
66
|
+
category.title = info[2]
|
67
|
+
pager_no = html.at_css("span.pager-no")
|
68
|
+
category.pagerno = pager_no.nil? ? 1 : pager_no.text.match(/of (\d+)/)[1].to_i
|
69
|
+
end
|
70
|
+
|
71
|
+
categories
|
72
|
+
end
|
73
|
+
|
74
|
+
# カテゴリ情報を更新
|
75
|
+
def update
|
76
|
+
ForumCategoryCollection.acquire_update(forum: @forum, categories: self)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class ForumCategory
|
81
|
+
attr_accessor :site, :id, :forum, :title, :description, :group, :threads_counts, :posts_counts, :pagerno
|
82
|
+
attr_reader :last
|
83
|
+
|
84
|
+
def initialize(site:, id:, forum:, title: nil, description: nil, group: nil, threads_counts: nil,
|
85
|
+
posts_counts: nil, pagerno: nil, last_thread_id: nil, last_post_id: nil)
|
86
|
+
@site = site
|
87
|
+
@id = id
|
88
|
+
@forum = forum
|
89
|
+
@title = title
|
90
|
+
@description = description
|
91
|
+
@group = group
|
92
|
+
@threads_counts = threads_counts
|
93
|
+
@posts_counts = posts_counts
|
94
|
+
@pagerno = pagerno
|
95
|
+
@_last_thread_id = last_thread_id
|
96
|
+
@_last_post_id = last_post_id
|
97
|
+
@_last = nil
|
98
|
+
end
|
99
|
+
|
100
|
+
# カテゴリのURLを取得
|
101
|
+
def get_url
|
102
|
+
"#{@site.get_url}/forum/c-#{@id}"
|
103
|
+
end
|
104
|
+
|
105
|
+
# カテゴリを更新
|
106
|
+
def update
|
107
|
+
ForumCategoryCollection.new(forum: @forum, categories: [self]).update.first
|
108
|
+
end
|
109
|
+
|
110
|
+
# 最後の投稿を取得
|
111
|
+
def last
|
112
|
+
@_last = @forum.thread.get(@_last_thread_id).get(@_last_post_id) if @_last_thread_id && @_last_post_id && @_last.nil?
|
113
|
+
@_last
|
114
|
+
end
|
115
|
+
|
116
|
+
# 最後の投稿を設定
|
117
|
+
def last=(value)
|
118
|
+
@_last = value
|
119
|
+
end
|
120
|
+
|
121
|
+
# スレッドのコレクションを取得する
|
122
|
+
# @return [ForumThreadCollection] スレッドオブジェクトのコレクション
|
123
|
+
def threads
|
124
|
+
client = @site.client
|
125
|
+
update
|
126
|
+
responses = @site.amc_request(
|
127
|
+
bodies: (1..@pagerno).map { |no| { "p" => no, "c" => @id, "moduleName" => "forum/ForumViewCategoryModule" } }
|
128
|
+
)
|
129
|
+
|
130
|
+
threads = []
|
131
|
+
|
132
|
+
responses.each do |response|
|
133
|
+
html = Nokogiri::HTML(response.body.to_s)
|
134
|
+
html.css("table.table tr.head~tr").each do |info|
|
135
|
+
title = info.at_css("div.title a")
|
136
|
+
thread_id = title["href"].match(/t-(\d+)/)[1].to_i
|
137
|
+
description = info.at_css("div.description").text.strip
|
138
|
+
user = info.at_css("span.printuser")
|
139
|
+
odate = info.at_css("span.odate")
|
140
|
+
posts_count = info.at_css("td.posts").text.to_i
|
141
|
+
last_id = info.at_css("td.last>a")
|
142
|
+
post_id = last_id.nil? ? nil : last_id["href"].match(/post-(\d+)/)[1].to_i
|
143
|
+
|
144
|
+
thread = ForumThread.new(
|
145
|
+
site: @site,
|
146
|
+
id: thread_id,
|
147
|
+
forum: @forum,
|
148
|
+
title: title.text.strip,
|
149
|
+
description: description,
|
150
|
+
created_by: user_parser(client, user),
|
151
|
+
created_at: odate_parser(odate),
|
152
|
+
posts_counts: posts_count,
|
153
|
+
_last_post_id: post_id
|
154
|
+
)
|
155
|
+
|
156
|
+
threads << thread
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
ForumThreadCollection.new(forum: @forum, threads: threads)
|
161
|
+
end
|
162
|
+
|
163
|
+
# 新しいスレッドを作成
|
164
|
+
def new_thread(title:, source:, description: "")
|
165
|
+
client = @site.client
|
166
|
+
client.login_check
|
167
|
+
|
168
|
+
response = @site.amc_request(
|
169
|
+
bodies: [
|
170
|
+
{
|
171
|
+
"category_id" => @id,
|
172
|
+
"title" => title,
|
173
|
+
"description" => description,
|
174
|
+
"source" => source,
|
175
|
+
"action" => "ForumAction",
|
176
|
+
"event" => "newThread"
|
177
|
+
}
|
178
|
+
]
|
179
|
+
).first
|
180
|
+
|
181
|
+
body = JSON.parse(response.body.to_s)
|
182
|
+
|
183
|
+
ForumThread.new(
|
184
|
+
site: @site,
|
185
|
+
id: body["threadId"].to_i,
|
186
|
+
forum: @forum,
|
187
|
+
category: self,
|
188
|
+
title: title,
|
189
|
+
description: description,
|
190
|
+
created_by: client.user.get(client.username),
|
191
|
+
created_at: DateTime.parse(body["CURRENT_TIMESTAMP"]),
|
192
|
+
posts_counts: 1
|
193
|
+
)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "nokogiri"
|
4
|
+
require "json"
|
5
|
+
require_relative "forum_category"
|
6
|
+
|
7
|
+
module Wikidotrb
|
8
|
+
module Module
|
9
|
+
class ForumGroupCollection < Array
|
10
|
+
attr_accessor :forum
|
11
|
+
|
12
|
+
# 初期化メソッド
|
13
|
+
# @param forum [Forum] フォーラムオブジェクト
|
14
|
+
# @param groups [Array<ForumGroup>] グループのリスト
|
15
|
+
def initialize(forum:, groups: [])
|
16
|
+
super(groups)
|
17
|
+
@forum = forum
|
18
|
+
end
|
19
|
+
|
20
|
+
# サイトとフォーラムからグループを取得
|
21
|
+
# @param site [Site] サイトオブジェクト
|
22
|
+
# @param forum [Forum] フォーラムオブジェクト
|
23
|
+
def self.get_groups(site:, forum:)
|
24
|
+
groups = []
|
25
|
+
|
26
|
+
response = site.amc_request(bodies: [{ "moduleName" => "forum/ForumStartModule", "hidden" => "true" }]).first
|
27
|
+
body = JSON.parse(response.body)["body"]
|
28
|
+
html = Nokogiri::HTML(body)
|
29
|
+
|
30
|
+
html.css("div.forum-group").each do |group_info|
|
31
|
+
group = ForumGroup.new(
|
32
|
+
site: site,
|
33
|
+
forum: forum,
|
34
|
+
title: group_info.at_css("div.title").text.strip,
|
35
|
+
description: group_info.at_css("div.description").text.strip
|
36
|
+
)
|
37
|
+
|
38
|
+
categories = []
|
39
|
+
|
40
|
+
group_info.css("table tr.head~tr").each do |info|
|
41
|
+
name = info.at_css("td.name")
|
42
|
+
thread_count = info.at_css("td.threads").text.strip.to_i
|
43
|
+
post_count = info.at_css("td.posts").text.strip.to_i
|
44
|
+
last_id = info.at_css("td.last>a")
|
45
|
+
if last_id.nil?
|
46
|
+
thread_id = nil
|
47
|
+
post_id = nil
|
48
|
+
else
|
49
|
+
thread_id, post_id = last_id["href"].match(/t-(\d+).+post-(\d+)/).captures.map(&:to_i)
|
50
|
+
end
|
51
|
+
|
52
|
+
category = ForumCategory.new(
|
53
|
+
site: site,
|
54
|
+
id: name.at_css("a")["href"].match(/c-(\d+)/)[1].to_i,
|
55
|
+
description: name.at_css("div.description").text.strip,
|
56
|
+
forum: forum,
|
57
|
+
title: name.at_css("a").text.strip,
|
58
|
+
group: group,
|
59
|
+
threads_counts: thread_count,
|
60
|
+
posts_counts: post_count,
|
61
|
+
last_thread_id: thread_id,
|
62
|
+
last_post_id: post_id
|
63
|
+
)
|
64
|
+
|
65
|
+
categories << category
|
66
|
+
end
|
67
|
+
|
68
|
+
group.categories = ForumCategoryCollection.new(forum: forum, categories: categories)
|
69
|
+
|
70
|
+
groups << group
|
71
|
+
end
|
72
|
+
|
73
|
+
forum._groups = ForumGroupCollection.new(forum: forum, groups: groups)
|
74
|
+
end
|
75
|
+
|
76
|
+
# グループをタイトルと説明から検索
|
77
|
+
# @param title [String] グループのタイトル
|
78
|
+
# @param description [String] グループの説明
|
79
|
+
# @return [ForumGroup, nil] 見つかったグループ
|
80
|
+
def find(title: nil, description: nil)
|
81
|
+
find do |group|
|
82
|
+
(title.nil? || group.title == title) && (description.nil? || group.description == description)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# 条件に一致するすべてのグループを検索
|
87
|
+
# @param title [String] グループのタイトル
|
88
|
+
# @param description [String] グループの説明
|
89
|
+
# @return [Array<ForumGroup>] 見つかったグループのリスト
|
90
|
+
def findall(title: nil, description: nil)
|
91
|
+
select do |group|
|
92
|
+
(title.nil? || group.title == title) && (description.nil? || group.description == description)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class ForumGroup
|
98
|
+
attr_accessor :site, :forum, :title, :description, :categories
|
99
|
+
|
100
|
+
def initialize(site:, forum:, title:, description:, categories: nil)
|
101
|
+
@site = site
|
102
|
+
@forum = forum
|
103
|
+
@title = title
|
104
|
+
@description = description
|
105
|
+
@categories = categories || ForumCategoryCollection.new(forum: forum)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|