wikidotrb 3.0.7.pre.6
Sign up to get free protection for your applications and to get access to all the features.
- 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,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "nokogiri"
|
4
|
+
require "date"
|
5
|
+
require_relative "page_source"
|
6
|
+
|
7
|
+
module Wikidotrb
|
8
|
+
module Module
|
9
|
+
class PageRevisionCollection < Array
|
10
|
+
attr_accessor :page
|
11
|
+
|
12
|
+
# 初期化メソッド
|
13
|
+
# @param page [Page] ページオブジェクト
|
14
|
+
# @param revisions [Array<PageRevision>] リビジョンのリスト
|
15
|
+
def initialize(page: nil, revisions: [])
|
16
|
+
super(revisions)
|
17
|
+
@page = page || revisions.first.page
|
18
|
+
end
|
19
|
+
|
20
|
+
# ソースを取得して設定する
|
21
|
+
# @param page [Page] ページオブジェクト
|
22
|
+
# @param revisions [Array<PageRevision>] リビジョンのリスト
|
23
|
+
# @return [Array<PageRevision>] 更新されたリビジョンのリスト
|
24
|
+
def self.acquire_sources(page:, revisions:)
|
25
|
+
target_revisions = revisions.reject(&:source_acquired?)
|
26
|
+
|
27
|
+
return revisions if target_revisions.empty?
|
28
|
+
|
29
|
+
responses = page.site.amc_request(
|
30
|
+
bodies: target_revisions.map do |revision|
|
31
|
+
{ "moduleName" => "history/PageSourceModule", "revision_id" => revision.id }
|
32
|
+
end
|
33
|
+
)
|
34
|
+
|
35
|
+
responses.each_with_index do |response, index|
|
36
|
+
body = response["body"]
|
37
|
+
body_html = Nokogiri::HTML(body)
|
38
|
+
target_revisions[index].source = PageSource.new(
|
39
|
+
page: page,
|
40
|
+
wiki_text: body_html.at_css("div.page-source").text.strip
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
revisions
|
45
|
+
end
|
46
|
+
|
47
|
+
# HTMLを取得して設定する
|
48
|
+
# @param page [Page] ページオブジェクト
|
49
|
+
# @param revisions [Array<PageRevision>] リビジョンのリスト
|
50
|
+
# @return [Array<PageRevision>] 更新されたリビジョンのリスト
|
51
|
+
def self.acquire_htmls(page:, revisions:)
|
52
|
+
target_revisions = revisions.reject(&:html_acquired?)
|
53
|
+
|
54
|
+
return revisions if target_revisions.empty?
|
55
|
+
|
56
|
+
responses = page.site.amc_request(
|
57
|
+
bodies: target_revisions.map do |revision|
|
58
|
+
{ "moduleName" => "history/PageVersionModule", "revision_id" => revision.id }
|
59
|
+
end
|
60
|
+
)
|
61
|
+
|
62
|
+
responses.each_with_index do |response, index|
|
63
|
+
body = response["body"]
|
64
|
+
# HTMLソースの抽出
|
65
|
+
source = body.split(
|
66
|
+
"onclick=\"document.getElementById('page-version-info').style.display='none'\">",
|
67
|
+
2
|
68
|
+
)[1].split("</a>\n\t</div>\n\n\n\n", 2)[1]
|
69
|
+
target_revisions[index].html = source
|
70
|
+
end
|
71
|
+
|
72
|
+
revisions
|
73
|
+
end
|
74
|
+
|
75
|
+
# ソースをリビジョンに取得する
|
76
|
+
def get_sources
|
77
|
+
PageRevisionCollection.acquire_sources(page: @page, revisions: self)
|
78
|
+
end
|
79
|
+
|
80
|
+
# HTMLをリビジョンに取得する
|
81
|
+
def get_htmls
|
82
|
+
PageRevisionCollection.acquire_htmls(page: @page, revisions: self)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class PageRevision
|
87
|
+
attr_accessor :page, :id, :rev_no, :created_by, :created_at, :comment, :source, :html
|
88
|
+
|
89
|
+
# 初期化メソッド
|
90
|
+
# @param page [Page] ページオブジェクト
|
91
|
+
# @param id [Integer] リビジョンID
|
92
|
+
# @param rev_no [Integer] リビジョン番号
|
93
|
+
# @param created_by [AbstractUser] 作成者
|
94
|
+
# @param created_at [DateTime] 作成日時
|
95
|
+
# @param comment [String] コメント
|
96
|
+
# @param source [PageSource, nil] ページソース
|
97
|
+
# @param html [String, nil] HTMLソース
|
98
|
+
def initialize(page:, id:, rev_no:, created_by:, created_at:, comment:, source: nil, html: nil)
|
99
|
+
@page = page
|
100
|
+
@id = id
|
101
|
+
@rev_no = rev_no
|
102
|
+
@created_by = created_by
|
103
|
+
@created_at = created_at
|
104
|
+
@comment = comment
|
105
|
+
@source = source
|
106
|
+
@html = html
|
107
|
+
end
|
108
|
+
|
109
|
+
# ソースの取得状況を確認する
|
110
|
+
# @return [Boolean] ソースが取得済みかどうか
|
111
|
+
def source_acquired?
|
112
|
+
!@source.nil?
|
113
|
+
end
|
114
|
+
|
115
|
+
# HTMLの取得状況を確認する
|
116
|
+
# @return [Boolean] HTMLが取得済みかどうか
|
117
|
+
def html_acquired?
|
118
|
+
!@html.nil?
|
119
|
+
end
|
120
|
+
|
121
|
+
# ソースのゲッターメソッド
|
122
|
+
# ソースが取得されていなければ取得する
|
123
|
+
# @return [PageSource] ソースオブジェクト
|
124
|
+
def source
|
125
|
+
PageRevisionCollection.new(page: @page, revisions: [self]).get_sources unless source_acquired?
|
126
|
+
@source
|
127
|
+
end
|
128
|
+
|
129
|
+
# ソースのセッターメソッド
|
130
|
+
|
131
|
+
# HTMLのゲッターメソッド
|
132
|
+
# HTMLが取得されていなければ取得する
|
133
|
+
# @return [String] HTMLソース
|
134
|
+
def html
|
135
|
+
PageRevisionCollection.new(page: @page, revisions: [self]).get_htmls unless html_acquired?
|
136
|
+
@html
|
137
|
+
end
|
138
|
+
|
139
|
+
# HTMLのセッターメソッド
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wikidotrb
|
4
|
+
module Module
|
5
|
+
class PageSource
|
6
|
+
attr_accessor :page, :wiki_text
|
7
|
+
|
8
|
+
# 初期化メソッド
|
9
|
+
# @param page [Page] ページオブジェクト
|
10
|
+
# @param wiki_text [String] ページのWikiテキスト
|
11
|
+
def initialize(page:, wiki_text:)
|
12
|
+
@page = page
|
13
|
+
@wiki_text = wiki_text
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wikidotrb
|
4
|
+
module Module
|
5
|
+
class PageVoteCollection < Array
|
6
|
+
attr_accessor :page
|
7
|
+
|
8
|
+
# 初期化メソッド
|
9
|
+
# @param page [Page] ページオブジェクト
|
10
|
+
# @param votes [Array<PageVote>] 投票オブジェクトのリスト
|
11
|
+
def initialize(page:, votes: [])
|
12
|
+
super(votes)
|
13
|
+
@page = page
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class PageVote
|
18
|
+
attr_accessor :page, :user, :value
|
19
|
+
|
20
|
+
# 初期化メソッド
|
21
|
+
# @param page [Page] ページオブジェクト
|
22
|
+
# @param user [AbstractUser] ユーザーオブジェクト
|
23
|
+
# @param value [Integer] 投票の値
|
24
|
+
def initialize(page:, user:, value:)
|
25
|
+
@page = page
|
26
|
+
@user = user
|
27
|
+
@value = value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "httpx"
|
4
|
+
require "nokogiri"
|
5
|
+
require "date"
|
6
|
+
require_relative "client"
|
7
|
+
require_relative "user"
|
8
|
+
require_relative "../common/exceptions"
|
9
|
+
require_relative "../common/decorators"
|
10
|
+
require_relative "../util/parser/odate"
|
11
|
+
require_relative "../util/parser/user"
|
12
|
+
|
13
|
+
module Wikidotrb
|
14
|
+
module Module
|
15
|
+
class PrivateMessageCollection < Array
|
16
|
+
extend Wikidotrb::Common::Decorators
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"#{self.class.name}(#{size} messages)"
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.from_ids(client:, message_ids:)
|
23
|
+
bodies = message_ids.map do |message_id|
|
24
|
+
{ item: message_id, moduleName: "dashboard/messages/DMViewMessageModule" }
|
25
|
+
end
|
26
|
+
|
27
|
+
responses = client.amc_client.request(bodies: bodies, return_exceptions: true)
|
28
|
+
|
29
|
+
messages = []
|
30
|
+
|
31
|
+
responses.each_with_index do |response, index|
|
32
|
+
if response.is_a?(Wikidotrb::Common::Exceptions::WikidotStatusCodeException) && response.status_code == ("no_message")
|
33
|
+
raise Wikidotrb::Common::Exceptions::ForbiddenException.new(
|
34
|
+
"Failed to get message: #{message_ids[index]}"
|
35
|
+
), response
|
36
|
+
end
|
37
|
+
|
38
|
+
raise response if response.is_a?(Exception)
|
39
|
+
|
40
|
+
html = Nokogiri::HTML(response["body"])
|
41
|
+
sender, recipient = html.css("div.pmessage div.header span.printuser")
|
42
|
+
messages << PrivateMessage.new(
|
43
|
+
client: client,
|
44
|
+
id: message_ids[index],
|
45
|
+
sender: Wikidotrb::Util::Parser::UserParser.parse(client, sender),
|
46
|
+
recipient: Wikidotrb::Util::Parser::UserParser.parse(client, recipient),
|
47
|
+
subject: html.css("div.pmessage div.header span.subject").text.strip,
|
48
|
+
body: html.css("div.pmessage div.body").text.strip,
|
49
|
+
created_at: Wikidotrb::Util::Parser::ODateParser.parse(html.css("div.header span.odate"))
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
new(messages)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self._acquire(client:, module_name:)
|
57
|
+
response = client.amc_client.request(bodies: [{ moduleName: module_name }])[0]
|
58
|
+
|
59
|
+
html = Nokogiri::HTML(response["body"])
|
60
|
+
pager = html.css("div.pager span.target")
|
61
|
+
max_page = pager.length > 2 ? pager[-2].text.to_i : 1
|
62
|
+
|
63
|
+
responses = if max_page > 1
|
64
|
+
bodies = (1..max_page).map { |page| { page: page, moduleName: module_name } }
|
65
|
+
client.amc_client.request(bodies: bodies, return_exceptions: false)
|
66
|
+
else
|
67
|
+
[response]
|
68
|
+
end
|
69
|
+
|
70
|
+
message_ids = []
|
71
|
+
responses.each do |res|
|
72
|
+
html = Nokogiri::HTML(res["body"])
|
73
|
+
message_ids += html.css("tr.message").map { |tr| tr["data-href"].split("/").last.to_i }
|
74
|
+
end
|
75
|
+
|
76
|
+
from_ids(client: client, message_ids: message_ids)
|
77
|
+
end
|
78
|
+
|
79
|
+
# メソッドが定義された後にデコレータを適用
|
80
|
+
login_required :from_ids, :_acquire
|
81
|
+
end
|
82
|
+
|
83
|
+
class PrivateMessageInbox < PrivateMessageCollection
|
84
|
+
def self.from_ids(client:, message_ids:)
|
85
|
+
new(super)
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.acquire(client:)
|
89
|
+
new(_acquire(client: client, module_name: "dashboard/messages/DMInboxModule"))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class PrivateMessageSentBox < PrivateMessageCollection
|
94
|
+
def self.from_ids(client:, message_ids:)
|
95
|
+
new(super)
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.acquire(client:)
|
99
|
+
new(_acquire(client: client, module_name: "dashboard/messages/DMSentModule"))
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class PrivateMessage
|
104
|
+
attr_reader :client, :id, :sender, :recipient, :subject, :body, :created_at
|
105
|
+
|
106
|
+
def initialize(client:, id:, sender:, recipient:, subject:, body:, created_at:)
|
107
|
+
@client = client
|
108
|
+
@id = id
|
109
|
+
@sender = sender
|
110
|
+
@recipient = recipient
|
111
|
+
@subject = subject
|
112
|
+
@body = body
|
113
|
+
@created_at = created_at
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_s
|
117
|
+
"PrivateMessage(id=#{id}, sender=#{sender}, recipient=#{recipient}, subject=#{subject})"
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.from_id(client:, message_id:)
|
121
|
+
PrivateMessageCollection.from_ids(client: client, message_ids: [message_id]).first
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.send_message(client:, recipient:, subject:, body:)
|
125
|
+
client.amc_client.request(
|
126
|
+
bodies: [{
|
127
|
+
source: body,
|
128
|
+
subject: subject,
|
129
|
+
to_user_id: recipient.id,
|
130
|
+
action: "DashboardMessageAction",
|
131
|
+
event: "send",
|
132
|
+
moduleName: "Empty"
|
133
|
+
}]
|
134
|
+
)
|
135
|
+
end
|
136
|
+
|
137
|
+
# メソッド定義後にデコレータを適用
|
138
|
+
extend Wikidotrb::Common::Decorators
|
139
|
+
login_required :send_message
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "httpx"
|
4
|
+
require_relative "forum"
|
5
|
+
require_relative "page"
|
6
|
+
require_relative "site_application"
|
7
|
+
require_relative "../common/exceptions"
|
8
|
+
require_relative "../common/decorators"
|
9
|
+
|
10
|
+
module Wikidotrb
|
11
|
+
module Module
|
12
|
+
class SitePagesMethods
|
13
|
+
def initialize(site)
|
14
|
+
@site = site
|
15
|
+
end
|
16
|
+
|
17
|
+
# ページを検索する
|
18
|
+
# @param kwargs [Hash] 検索クエリのパラメータ
|
19
|
+
# @return [PageCollection] ページのコレクション
|
20
|
+
def search(**kwargs)
|
21
|
+
query = SearchPagesQuery.new(**kwargs)
|
22
|
+
PageCollection.search_pages(@site, query)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class SitePageMethods
|
27
|
+
def initialize(site)
|
28
|
+
@site = site
|
29
|
+
end
|
30
|
+
|
31
|
+
# フルネームからページを取得する
|
32
|
+
# @param fullname [String] ページのフルネーム
|
33
|
+
# @param raise_when_not_found [Boolean] ページが見つからない場合に例外を発生させるかどうか
|
34
|
+
# @return [Page, nil] ページオブジェクト、もしくはnil
|
35
|
+
def get(fullname, raise_when_not_found: true)
|
36
|
+
res = PageCollection.search_pages(@site, Wikidotrb::Module::SearchPagesQuery.new(fullname: fullname))
|
37
|
+
|
38
|
+
if res.empty?
|
39
|
+
raise Wikidotrb::Common::Exceptions::NotFoundException, "Page is not found: #{fullname}" if raise_when_not_found
|
40
|
+
|
41
|
+
return nil
|
42
|
+
end
|
43
|
+
|
44
|
+
res.first
|
45
|
+
end
|
46
|
+
|
47
|
+
# ページを作成する
|
48
|
+
# @param fullname [String] ページのフルネーム
|
49
|
+
# @param title [String] ページのタイトル
|
50
|
+
# @param source [String] ページのソース
|
51
|
+
# @param comment [String] コメント
|
52
|
+
# @param force_edit [Boolean] ページが存在する場合に上書きするかどうか
|
53
|
+
# @return [Page] 作成されたページオブジェクト
|
54
|
+
def create(fullname:, title: "", source: "", comment: "", force_edit: false)
|
55
|
+
Page.create_or_edit(
|
56
|
+
site: @site,
|
57
|
+
fullname: fullname,
|
58
|
+
title: title,
|
59
|
+
source: source,
|
60
|
+
comment: comment,
|
61
|
+
force_edit: force_edit,
|
62
|
+
raise_on_exists: true
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class Site
|
68
|
+
attr_reader :client, :id, :title, :unix_name, :domain, :ssl_supported, :pages, :page
|
69
|
+
|
70
|
+
extend Wikidotrb::Common::Decorators
|
71
|
+
|
72
|
+
def initialize(client:, id:, title:, unix_name:, domain:, ssl_supported:)
|
73
|
+
@client = client
|
74
|
+
@id = id
|
75
|
+
@title = title
|
76
|
+
@unix_name = unix_name
|
77
|
+
@domain = domain
|
78
|
+
@ssl_supported = ssl_supported
|
79
|
+
|
80
|
+
@pages = SitePagesMethods.new(self)
|
81
|
+
@page = SitePageMethods.new(self)
|
82
|
+
@forum = Forum.new(site: self)
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_s
|
86
|
+
"Site(id=#{id}, title=#{title}, unix_name=#{unix_name})"
|
87
|
+
end
|
88
|
+
|
89
|
+
# UNIX名からサイトオブジェクトを取得する
|
90
|
+
# @param client [Client] クライアント
|
91
|
+
# @param unix_name [String] サイトのUNIX名
|
92
|
+
# @return [Site] サイトオブジェクト
|
93
|
+
def self.from_unix_name(client:, unix_name:)
|
94
|
+
url = "http://#{unix_name}.wikidot.com"
|
95
|
+
timeout = { connect: client.amc_client.config.request_timeout }
|
96
|
+
response = HTTPX.with(timeout: timeout).get(url)
|
97
|
+
|
98
|
+
# リダイレクトの対応
|
99
|
+
while response.status >= 300 && response.status < 400
|
100
|
+
url = response.headers["location"]
|
101
|
+
response = HTTPX.with(timeout: timeout).get(url)
|
102
|
+
end
|
103
|
+
|
104
|
+
# サイトが存在しない場合
|
105
|
+
raise Wikidotrb::Common::Exceptions::NotFoundException, "Site is not found: #{unix_name}.wikidot.com" if response.status == 404
|
106
|
+
|
107
|
+
# サイトが存在する場合
|
108
|
+
source = response.body.to_s
|
109
|
+
|
110
|
+
# id : WIKIREQUEST.info.siteId = xxxx;
|
111
|
+
id_match = source.match(/WIKIREQUEST\.info\.siteId = (\d+);/)
|
112
|
+
raise Wikidotrb::Common::Exceptions::UnexpectedException, "Cannot find site id: #{unix_name}.wikidot.com" if id_match.nil?
|
113
|
+
|
114
|
+
site_id = id_match[1].to_i
|
115
|
+
|
116
|
+
# title : titleタグ
|
117
|
+
title_match = source.match(%r{<title>(.*?)</title>})
|
118
|
+
raise Wikidotrb::Common::Exceptions::UnexpectedException, "Cannot find site title: #{unix_name}.wikidot.com" if title_match.nil?
|
119
|
+
|
120
|
+
title = title_match[1]
|
121
|
+
|
122
|
+
# unix_name : WIKIREQUEST.info.siteUnixName = "xxxx";
|
123
|
+
unix_name_match = source.match(/WIKIREQUEST\.info\.siteUnixName = "(.*?)";/)
|
124
|
+
if unix_name_match.nil?
|
125
|
+
raise Wikidotrb::Common::Exceptions::UnexpectedException,
|
126
|
+
"Cannot find site unix_name: #{unix_name}.wikidot.com"
|
127
|
+
end
|
128
|
+
|
129
|
+
unix_name = unix_name_match[1]
|
130
|
+
|
131
|
+
# domain : WIKIREQUEST.info.domain = "xxxx";
|
132
|
+
domain_match = source.match(/WIKIREQUEST\.info\.domain = "(.*?)";/)
|
133
|
+
raise Wikidotrb::Common::Exceptions::UnexpectedException, "Cannot find site domain: #{unix_name}.wikidot.com" if domain_match.nil?
|
134
|
+
|
135
|
+
domain = domain_match[1]
|
136
|
+
|
137
|
+
# SSL対応チェック
|
138
|
+
ssl_supported = response.uri.to_s.start_with?("https")
|
139
|
+
|
140
|
+
new(
|
141
|
+
client: client,
|
142
|
+
id: site_id,
|
143
|
+
title: title,
|
144
|
+
unix_name: unix_name,
|
145
|
+
domain: domain,
|
146
|
+
ssl_supported: ssl_supported
|
147
|
+
)
|
148
|
+
end
|
149
|
+
|
150
|
+
# このサイトに対してAMCリクエストを実行する
|
151
|
+
# @param bodies [Array<Hash>] リクエストボディのリスト
|
152
|
+
# @param return_exceptions [Boolean] 例外を返すかどうか
|
153
|
+
def amc_request(bodies:, return_exceptions: false)
|
154
|
+
client.amc_client.request(
|
155
|
+
bodies: bodies,
|
156
|
+
return_exceptions: return_exceptions,
|
157
|
+
site_name: unix_name,
|
158
|
+
site_ssl_supported: ssl_supported
|
159
|
+
)
|
160
|
+
end
|
161
|
+
|
162
|
+
# サイトへの未処理の参加申請を取得する
|
163
|
+
# @return [Array<SiteApplication>] 未処理の申請リスト
|
164
|
+
def get_applications
|
165
|
+
SiteApplication.acquire_all(site: self)
|
166
|
+
end
|
167
|
+
|
168
|
+
# ユーザーをサイトに招待する
|
169
|
+
# @param user [User] 招待するユーザー
|
170
|
+
# @param text [String] 招待文
|
171
|
+
def invite_user(user:, text:)
|
172
|
+
amc_request(
|
173
|
+
bodies: [{
|
174
|
+
action: "ManageSiteMembershipAction",
|
175
|
+
event: "inviteMember",
|
176
|
+
user_id: user.id,
|
177
|
+
text: text,
|
178
|
+
moduleName: "Empty"
|
179
|
+
}]
|
180
|
+
)
|
181
|
+
rescue Wikidotrb::Common::Exceptions::WikidotStatusCodeException => e
|
182
|
+
case e.status_code
|
183
|
+
when "already_invited"
|
184
|
+
raise Wikidotrb::Common::Exceptions::TargetErrorException.new(
|
185
|
+
"User is already invited to #{unix_name}: #{user.name}"
|
186
|
+
), e
|
187
|
+
when "already_member"
|
188
|
+
raise Wikidotrb::Common::Exceptions::TargetErrorException.new(
|
189
|
+
"User is already a member of #{unix_name}: #{user.name}"
|
190
|
+
), e
|
191
|
+
else
|
192
|
+
raise e
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
# サイトのURLを取得する
|
197
|
+
# @return [String] サイトのURL
|
198
|
+
def get_url
|
199
|
+
"http#{ssl_supported ? "s" : ""}://#{domain}"
|
200
|
+
end
|
201
|
+
|
202
|
+
# `invite_user`にデコレータを適用
|
203
|
+
login_required :invite_user
|
204
|
+
login_required :get_applications
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "nokogiri"
|
4
|
+
require_relative "site"
|
5
|
+
require_relative "user"
|
6
|
+
require_relative "../common/exceptions"
|
7
|
+
require_relative "../util/parser/odate"
|
8
|
+
require_relative "../util/parser/user"
|
9
|
+
|
10
|
+
module Wikidotrb
|
11
|
+
module Module
|
12
|
+
class SiteApplication
|
13
|
+
attr_reader :site, :user, :text
|
14
|
+
|
15
|
+
def initialize(site:, user:, text:)
|
16
|
+
@site = site
|
17
|
+
@user = user
|
18
|
+
@text = text
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"SiteApplication(user=#{user}, site=#{site}, text=#{text})"
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.acquire_all(site:)
|
26
|
+
# サイトへの未処理の申請を取得する
|
27
|
+
# @param site [Site] サイト
|
28
|
+
# @return [Array<SiteApplication>] 申請のリスト
|
29
|
+
response = site.amc_request(
|
30
|
+
bodies: [{ moduleName: "managesite/ManageSiteMembersApplicationsModule" }]
|
31
|
+
).first
|
32
|
+
|
33
|
+
body = response["body"]
|
34
|
+
|
35
|
+
raise Wikidotrb::Common::Exceptions::ForbiddenException, "You are not allowed to access this page" if body.include?("WIKIDOT.page.listeners.loginClick(event)")
|
36
|
+
|
37
|
+
html = Nokogiri::HTML(response["body"])
|
38
|
+
|
39
|
+
applications = []
|
40
|
+
|
41
|
+
user_elements = html.css("h3 span.printuser")
|
42
|
+
text_wrapper_elements = html.css("table")
|
43
|
+
|
44
|
+
if user_elements.length != text_wrapper_elements.length
|
45
|
+
raise Wikidotrb::Common::Exceptions::UnexpectedException,
|
46
|
+
"Length of user_elements and text_wrapper_elements are different"
|
47
|
+
end
|
48
|
+
|
49
|
+
user_elements.each_with_index do |user_element, i|
|
50
|
+
text_wrapper_element = text_wrapper_elements[i]
|
51
|
+
|
52
|
+
user = Wikidotrb::Util::Parser::UserParser.user(site.client, user_element)
|
53
|
+
text = text_wrapper_element.css("td")[1].text.strip
|
54
|
+
|
55
|
+
applications << SiteApplication.new(site: site, user: user, text: text)
|
56
|
+
end
|
57
|
+
|
58
|
+
applications
|
59
|
+
end
|
60
|
+
|
61
|
+
def _process(action)
|
62
|
+
# 申請を処理する
|
63
|
+
# @param action [String] 処理の種類 ('accept' または 'decline')
|
64
|
+
raise ArgumentError, "Invalid action: #{action}" unless %w[accept decline].include?(action)
|
65
|
+
|
66
|
+
begin
|
67
|
+
site.amc_request(
|
68
|
+
bodies: [{
|
69
|
+
action: "ManageSiteMembershipAction",
|
70
|
+
event: "acceptApplication",
|
71
|
+
user_id: user.id,
|
72
|
+
text: "your application has been #{action}ed",
|
73
|
+
type: action,
|
74
|
+
moduleName: "Empty"
|
75
|
+
}]
|
76
|
+
)
|
77
|
+
rescue Wikidotrb::Common::Exceptions::WikidotStatusCodeException => e
|
78
|
+
raise e unless e.status_code == "no_application"
|
79
|
+
|
80
|
+
raise Wikidotrb::Common::Exceptions::NotFoundException.new(
|
81
|
+
"Application not found: #{user}"
|
82
|
+
), e
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# 申請を承認する
|
87
|
+
def accept
|
88
|
+
_process("accept")
|
89
|
+
end
|
90
|
+
|
91
|
+
# 申請を拒否する
|
92
|
+
def decline
|
93
|
+
_process("decline")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|