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,598 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "nokogiri"
|
4
|
+
require_relative "../common/exceptions"
|
5
|
+
require_relative "forum_thread"
|
6
|
+
require_relative "page_revision"
|
7
|
+
require_relative "page_source"
|
8
|
+
require_relative "page_votes"
|
9
|
+
require_relative "../util/requestutil"
|
10
|
+
require_relative "../util/parser/user"
|
11
|
+
require_relative "../util/parser/odate"
|
12
|
+
|
13
|
+
module Wikidotrb
|
14
|
+
module Module
|
15
|
+
DEFAULT_MODULE_BODY = [
|
16
|
+
"fullname", # ページのフルネーム(str)
|
17
|
+
"category", # カテゴリ(str)
|
18
|
+
"name", # ページ名(str)
|
19
|
+
"title", # タイトル(str)
|
20
|
+
"created_at", # 作成日時(odate element)
|
21
|
+
"created_by_linked", # 作成者(user element)
|
22
|
+
"updated_at", # 更新日時(odate element)
|
23
|
+
"updated_by_linked", # 更新者(user element)
|
24
|
+
"commented_at", # コメント日時(odate element)
|
25
|
+
"commented_by_linked", # コメントしたユーザ(user element)
|
26
|
+
"parent_fullname", # 親ページのフルネーム(str)
|
27
|
+
"comments", # コメント数(int)
|
28
|
+
"size", # サイズ(int)
|
29
|
+
"children", # 子ページ数(int)
|
30
|
+
"rating_votes", # 投票数(int)
|
31
|
+
"rating", # レーティング(int or float)
|
32
|
+
"rating_percent", # 5つ星レーティング(%)
|
33
|
+
"revisions", # リビジョン数(int)
|
34
|
+
"tags", # タグのリスト(list of str)
|
35
|
+
"_tags" # 隠しタグのリスト(list of str)
|
36
|
+
].freeze
|
37
|
+
|
38
|
+
class SearchPagesQuery
|
39
|
+
attr_accessor :pagetype, :category, :tags, :parent, :link_to, :created_at, :updated_at,
|
40
|
+
:created_by, :rating, :votes, :name, :fullname, :range, :order,
|
41
|
+
:offset, :limit, :perPage, :separate, :wrapper
|
42
|
+
|
43
|
+
def initialize(pagetype: "*", category: "*", tags: nil, parent: nil, link_to: nil, created_at: nil, updated_at: nil,
|
44
|
+
created_by: nil, rating: nil, votes: nil, name: nil, fullname: nil, range: nil, order: "created_at desc",
|
45
|
+
offset: 0, limit: nil, perPage: 250, separate: "no", wrapper: "no")
|
46
|
+
@pagetype = pagetype
|
47
|
+
@category = category
|
48
|
+
@tags = tags
|
49
|
+
@parent = parent
|
50
|
+
@link_to = link_to
|
51
|
+
@created_at = created_at
|
52
|
+
@updated_at = updated_at
|
53
|
+
@created_by = created_by
|
54
|
+
@rating = rating
|
55
|
+
@votes = votes
|
56
|
+
@name = name
|
57
|
+
@fullname = fullname
|
58
|
+
@range = range
|
59
|
+
@order = order
|
60
|
+
@offset = offset
|
61
|
+
@limit = limit
|
62
|
+
@perPage = perPage
|
63
|
+
@separate = separate
|
64
|
+
@wrapper = wrapper
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_h
|
68
|
+
res = instance_variables.to_h { |var| [var.to_s.delete("@"), instance_variable_get(var)] }
|
69
|
+
res.compact!
|
70
|
+
res["tags"] = res["tags"].join(" ") if res["tags"].is_a?(Array)
|
71
|
+
res
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class PageCollection < Array
|
76
|
+
attr_accessor :site
|
77
|
+
|
78
|
+
def initialize(site: nil, pages: [])
|
79
|
+
super(pages)
|
80
|
+
@site = site || pages.first&.site
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.parse(site, html_body)
|
84
|
+
pages = []
|
85
|
+
|
86
|
+
html_body.css("div.page").each do |page_element|
|
87
|
+
page_params = {}
|
88
|
+
|
89
|
+
# レーティング方式を判定
|
90
|
+
is_5star_rating = !page_element.css("span.rating span.page-rate-list-pages-start").empty?
|
91
|
+
|
92
|
+
# 各値を取得
|
93
|
+
page_element.css("span.set").each do |set_element|
|
94
|
+
key = set_element.css("span.name").text.strip
|
95
|
+
value_element = set_element.css("span.value")
|
96
|
+
|
97
|
+
value = if value_element.empty?
|
98
|
+
nil
|
99
|
+
elsif %w[created_at updated_at commented_at].include?(key)
|
100
|
+
odate_element = value_element.css("span.odate")
|
101
|
+
odate_element.empty? ? nil : Wikidotrb::Util::Parser::ODateParser.parse(odate_element)
|
102
|
+
elsif %w[created_by_linked updated_by_linked commented_by_linked].include?(key)
|
103
|
+
printuser_element = value_element.css("span.printuser")
|
104
|
+
if printuser_element.empty?
|
105
|
+
nil
|
106
|
+
else
|
107
|
+
Wikidotrb::Util::Parser::UserParser.parse(site.client,
|
108
|
+
printuser_element)
|
109
|
+
end
|
110
|
+
elsif %w[tags _tags].include?(key)
|
111
|
+
value_element.text.split
|
112
|
+
elsif %w[rating_votes comments size revisions].include?(key)
|
113
|
+
value_element.text.strip.to_i
|
114
|
+
elsif key == "rating"
|
115
|
+
is_5star_rating ? value_element.text.strip.to_f : value_element.text.strip.to_i
|
116
|
+
elsif key == "rating_percent"
|
117
|
+
is_5star_rating ? value_element.text.strip.to_f / 100 : nil
|
118
|
+
else
|
119
|
+
value_element.text.strip
|
120
|
+
end
|
121
|
+
|
122
|
+
# keyを変換
|
123
|
+
key = key.gsub("_linked", "") if key.include?("_linked")
|
124
|
+
key = "#{key}_count" if %w[comments children revisions].include?(key)
|
125
|
+
key = "votes_count" if key == "rating_votes"
|
126
|
+
|
127
|
+
page_params[key.to_sym] = value
|
128
|
+
end
|
129
|
+
|
130
|
+
# タグのリストを統合
|
131
|
+
page_params[:tags] ||= []
|
132
|
+
page_params[:tags] += page_params.delete(:_tags) || []
|
133
|
+
|
134
|
+
# ページオブジェクトを作成
|
135
|
+
pages << Page.new(site: site, **page_params)
|
136
|
+
end
|
137
|
+
|
138
|
+
new(site: site, pages: pages)
|
139
|
+
end
|
140
|
+
|
141
|
+
def self.search_pages(site, query = SearchPagesQuery.new)
|
142
|
+
# クエリの初期化
|
143
|
+
query_dict = query.to_h
|
144
|
+
query_dict["moduleName"] = "list/ListPagesModule"
|
145
|
+
query_dict["module_body"] = %(
|
146
|
+
[[div class="page"]]
|
147
|
+
#{DEFAULT_MODULE_BODY.map do |key|
|
148
|
+
%(
|
149
|
+
[[span class="set #{key}"]]
|
150
|
+
[[span class="name"]]#{key}[[/span]]
|
151
|
+
[[span class="value"]]%%#{key}%%[[/span]]
|
152
|
+
[[/span]]
|
153
|
+
)
|
154
|
+
end.join("\n")}
|
155
|
+
[[/div]]
|
156
|
+
)
|
157
|
+
|
158
|
+
begin
|
159
|
+
# 初回リクエスト
|
160
|
+
response_data = site.amc_request(bodies: [query_dict])[0]
|
161
|
+
rescue Wikidotrb::Common::Exceptions::WikidotStatusCodeException => e
|
162
|
+
raise Wikidotrb::Common::Exceptions::ForbiddenException, "Failed to get pages, target site may be private" if e.status_code == "not_ok"
|
163
|
+
|
164
|
+
raise e
|
165
|
+
end
|
166
|
+
|
167
|
+
body = response_data["body"]
|
168
|
+
first_page_html_body = Nokogiri::HTML(body)
|
169
|
+
|
170
|
+
total = 1
|
171
|
+
html_bodies = [first_page_html_body]
|
172
|
+
|
173
|
+
# pagerの存在を確認
|
174
|
+
pager_element = first_page_html_body.css("div.pager")
|
175
|
+
unless pager_element.empty?
|
176
|
+
# 最大ページ数を取得
|
177
|
+
total = pager_element.css("span.target")[-2].css("a").text.to_i
|
178
|
+
end
|
179
|
+
|
180
|
+
# 複数ページが存在する場合はリクエストを繰り返す
|
181
|
+
if total > 1
|
182
|
+
request_bodies = []
|
183
|
+
(1...total).each do |i|
|
184
|
+
_query_dict = query_dict.dup
|
185
|
+
_query_dict["offset"] = i * query.perPage
|
186
|
+
request_bodies << _query_dict
|
187
|
+
end
|
188
|
+
|
189
|
+
responses = site.amc_request(bodies: request_bodies)
|
190
|
+
html_bodies.concat(responses.map { |response| Nokogiri::HTML(response["body"]) })
|
191
|
+
end
|
192
|
+
|
193
|
+
# 全てのHTMLボディをパースしてページコレクションを作成
|
194
|
+
pages = html_bodies.flat_map { |html_body| parse(site, html_body) }
|
195
|
+
new(site: site, pages: pages)
|
196
|
+
end
|
197
|
+
|
198
|
+
# メソッドを定義する部分の修正
|
199
|
+
def get_page_sources
|
200
|
+
PageCollection.acquire_page_sources(@site, self)
|
201
|
+
end
|
202
|
+
|
203
|
+
def get_page_ids
|
204
|
+
PageCollection.acquire_page_ids(@site, self)
|
205
|
+
end
|
206
|
+
|
207
|
+
def get_page_revisions
|
208
|
+
PageCollection.acquire_page_revisions(@site, self)
|
209
|
+
end
|
210
|
+
|
211
|
+
def get_page_votes
|
212
|
+
PageCollection.acquire_page_votes(@site, self)
|
213
|
+
end
|
214
|
+
|
215
|
+
def get_page_discuss
|
216
|
+
PageCollection.acquire_page_discuss(@site, self)
|
217
|
+
end
|
218
|
+
|
219
|
+
def self.acquire_page_sources(site, pages)
|
220
|
+
return pages if pages.empty?
|
221
|
+
|
222
|
+
responses = site.amc_request(
|
223
|
+
bodies: pages.map { |page| { "moduleName" => "viewsource/ViewSourceModule", "page_id" => page.id } }
|
224
|
+
)
|
225
|
+
|
226
|
+
pages.each_with_index do |page, index|
|
227
|
+
body = responses[index]["body"]
|
228
|
+
source = Nokogiri::HTML(body).at_css("div.page-source").text.strip
|
229
|
+
page.source = PageSource.new(page: page, wiki_text: source)
|
230
|
+
end
|
231
|
+
|
232
|
+
pages
|
233
|
+
end
|
234
|
+
|
235
|
+
def self.acquire_page_ids(site, pages)
|
236
|
+
target_pages = pages.reject(&:is_id_acquired?)
|
237
|
+
return pages if target_pages.empty?
|
238
|
+
|
239
|
+
responses = Wikidotrb::Util::RequestUtil.request(
|
240
|
+
client: site.client,
|
241
|
+
method: "GET",
|
242
|
+
urls: target_pages.map { |page| "#{page.get_url}/norender/true/noredirect/true" }
|
243
|
+
)
|
244
|
+
|
245
|
+
responses.each_with_index do |response, index|
|
246
|
+
source = response.body.to_s # Convert to string if necessary
|
247
|
+
|
248
|
+
id_match = source.match(/WIKIREQUEST\.info\.pageId = (\d+);/)
|
249
|
+
unless id_match
|
250
|
+
raise Wikidotrb::Common::Exceptions::UnexpectedException,
|
251
|
+
"Cannot find page id: #{target_pages[index].fullname}"
|
252
|
+
end
|
253
|
+
|
254
|
+
target_pages[index].id = id_match[1].to_i
|
255
|
+
end
|
256
|
+
|
257
|
+
pages
|
258
|
+
end
|
259
|
+
|
260
|
+
def self.acquire_page_revisions(site, pages)
|
261
|
+
return pages if pages.empty?
|
262
|
+
|
263
|
+
responses = site.amc_request(
|
264
|
+
bodies: pages.map do |page|
|
265
|
+
{
|
266
|
+
"moduleName" => "history/PageRevisionListModule",
|
267
|
+
"page_id" => page.id,
|
268
|
+
"options" => { "all" => true },
|
269
|
+
"perpage" => 100_000_000 # pagerを使わずに全て取得
|
270
|
+
}
|
271
|
+
end
|
272
|
+
)
|
273
|
+
|
274
|
+
responses.each_with_index do |response, index|
|
275
|
+
body = response["body"]
|
276
|
+
revs = []
|
277
|
+
body_html = Nokogiri::HTML(body)
|
278
|
+
|
279
|
+
body_html.css("table.page-history > tr[id^=revision-row-]").each do |rev_element|
|
280
|
+
rev_id = rev_element["id"].gsub("revision-row-", "").to_i
|
281
|
+
|
282
|
+
tds = rev_element.css("td")
|
283
|
+
rev_no = tds[0].text.strip.gsub(".", "").to_i
|
284
|
+
created_by = Wikidotrb::Util::Parser::UserParser.parse(site.client, tds[4].css("span.printuser").first)
|
285
|
+
created_at = Wikidotrb::Util::Parser::ODateParser.parse(tds[5].css("span.odate").first)
|
286
|
+
comment = tds[6].text.strip
|
287
|
+
revs << PageRevision.new(
|
288
|
+
page: pages[index],
|
289
|
+
id: rev_id,
|
290
|
+
rev_no: rev_no,
|
291
|
+
created_by: created_by,
|
292
|
+
created_at: created_at,
|
293
|
+
comment: comment
|
294
|
+
)
|
295
|
+
end
|
296
|
+
pages[index].revisions = revs
|
297
|
+
end
|
298
|
+
|
299
|
+
pages
|
300
|
+
end
|
301
|
+
|
302
|
+
def self.acquire_page_votes(site, pages)
|
303
|
+
return pages if pages.empty?
|
304
|
+
|
305
|
+
responses = site.amc_request(
|
306
|
+
bodies: pages.map { |page| { "moduleName" => "pagerate/WhoRatedPageModule", "pageId" => page.id } }
|
307
|
+
)
|
308
|
+
|
309
|
+
responses.each_with_index do |response, index|
|
310
|
+
body = response["body"]
|
311
|
+
html = Nokogiri::HTML(body)
|
312
|
+
user_elems = html.css("span.printuser")
|
313
|
+
value_elems = html.css('span[style^="color"]')
|
314
|
+
|
315
|
+
if user_elems.size != value_elems.size
|
316
|
+
raise Wikidotrb::Common::Exceptions::UnexpectedException,
|
317
|
+
"User and value count mismatch"
|
318
|
+
end
|
319
|
+
|
320
|
+
users = user_elems.map { |user_elem| Wikidotrb::Util::Parser::UserParser.parse(site.client, user_elem) }
|
321
|
+
values = value_elems.map do |value_elem|
|
322
|
+
value = value_elem.text.strip
|
323
|
+
if value == "+"
|
324
|
+
1
|
325
|
+
elsif value == "-"
|
326
|
+
-1
|
327
|
+
else
|
328
|
+
value.to_i
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
votes = users.zip(values).map { |user, vote| PageVote.new(page: pages[index], user: user, value: vote) }
|
333
|
+
pages[index].votes = PageVoteCollection.new(page: pages[index], votes: votes)
|
334
|
+
end
|
335
|
+
|
336
|
+
pages
|
337
|
+
end
|
338
|
+
|
339
|
+
def self.acquire_page_discuss(site, pages)
|
340
|
+
target_pages = pages.reject(&:is_discuss_acquired?)
|
341
|
+
return pages if target_pages.empty?
|
342
|
+
|
343
|
+
responses = site.amc_request(
|
344
|
+
bodies: target_pages.map do |page|
|
345
|
+
{
|
346
|
+
"action" => "ForumAction",
|
347
|
+
"event" => "createPageDiscussionThread",
|
348
|
+
"page_id" => page.id,
|
349
|
+
"moduleName" => "Empty"
|
350
|
+
}
|
351
|
+
end
|
352
|
+
)
|
353
|
+
|
354
|
+
target_pages.each_with_index do |page, index|
|
355
|
+
page.discuss = ForumThread.new(site, responses[index]["thread_id"], page: page)
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
class Page
|
361
|
+
attr_accessor :site, :fullname, :name, :category, :title, :children_count,
|
362
|
+
:comments_count, :size, :rating, :votes_count, :rating_percent,
|
363
|
+
:revisions_count, :parent_fullname, :tags, :created_by, :created_at,
|
364
|
+
:updated_by, :updated_at, :commented_by, :commented_at, :_id,
|
365
|
+
:_source, :_revisions, :_votes, :_discuss
|
366
|
+
|
367
|
+
def initialize(site:, fullname:, name: "", category: "", title: "", children_count: 0, comments_count: 0, size: 0, rating: 0,
|
368
|
+
votes_count: 0, rating_percent: 0, revisions_count: 0, parent_fullname: "", tags: [], created_by: nil, created_at: nil,
|
369
|
+
updated_by: nil, updated_at: nil, commented_by: nil, commented_at: nil, _id: nil, _source: nil, _revisions: nil,
|
370
|
+
_votes: nil, _discuss: nil)
|
371
|
+
@site = site
|
372
|
+
@fullname = fullname
|
373
|
+
@name = name
|
374
|
+
@category = category
|
375
|
+
@title = title
|
376
|
+
@children_count = children_count
|
377
|
+
@comments_count = comments_count
|
378
|
+
@size = size
|
379
|
+
@rating = rating
|
380
|
+
@votes_count = votes_count
|
381
|
+
@rating_percent = rating_percent
|
382
|
+
@revisions_count = revisions_count
|
383
|
+
@parent_fullname = parent_fullname
|
384
|
+
@tags = tags
|
385
|
+
@created_by = created_by
|
386
|
+
@created_at = created_at
|
387
|
+
@updated_by = updated_by
|
388
|
+
@updated_at = updated_at
|
389
|
+
@commented_by = commented_by
|
390
|
+
@commented_at = commented_at
|
391
|
+
@_id = _id
|
392
|
+
@_source = _source
|
393
|
+
@_revisions = _revisions
|
394
|
+
@_votes = _votes
|
395
|
+
@_discuss = _discuss
|
396
|
+
end
|
397
|
+
|
398
|
+
def discuss
|
399
|
+
PageCollection.new(site: @site, pages: [self]).get_page_discuss if @_discuss.nil?
|
400
|
+
@_discuss.update
|
401
|
+
@_discuss
|
402
|
+
end
|
403
|
+
|
404
|
+
def discuss=(value)
|
405
|
+
@_discuss = value
|
406
|
+
end
|
407
|
+
|
408
|
+
def is_discuss_acquired?
|
409
|
+
!@_discuss.nil?
|
410
|
+
end
|
411
|
+
|
412
|
+
def get_url
|
413
|
+
"#{@site.get_url}/#{@fullname}"
|
414
|
+
end
|
415
|
+
|
416
|
+
def id
|
417
|
+
PageCollection.new(site: @site, pages: [self]).get_page_ids if @_id.nil?
|
418
|
+
@_id
|
419
|
+
end
|
420
|
+
|
421
|
+
def id=(value)
|
422
|
+
@_id = value
|
423
|
+
end
|
424
|
+
|
425
|
+
def is_id_acquired?
|
426
|
+
!@_id.nil?
|
427
|
+
end
|
428
|
+
|
429
|
+
def source
|
430
|
+
PageCollection.new(site: @site, pages: [self]).get_page_sources if @_source.nil?
|
431
|
+
@_source
|
432
|
+
end
|
433
|
+
|
434
|
+
def source=(value)
|
435
|
+
@_source = value
|
436
|
+
end
|
437
|
+
|
438
|
+
def revisions
|
439
|
+
PageCollection.new(site: @site, pages: [self]).get_page_revisions if @_revisions.nil?
|
440
|
+
PageRevisionCollection.new(page: self, revisions: @_revisions)
|
441
|
+
end
|
442
|
+
|
443
|
+
def revisions=(value)
|
444
|
+
@_revisions = value
|
445
|
+
end
|
446
|
+
|
447
|
+
def latest_revision
|
448
|
+
# revision_countとrev_noが一致するものを取得
|
449
|
+
@revisions.each do |revision|
|
450
|
+
return revision if revision.rev_no == @revisions_count
|
451
|
+
end
|
452
|
+
|
453
|
+
raise NotFoundException, "Cannot find latest revision"
|
454
|
+
end
|
455
|
+
|
456
|
+
def votes
|
457
|
+
PageCollection.new(site: @site, pages: [self]).get_page_votes if @_votes.nil?
|
458
|
+
@_votes
|
459
|
+
end
|
460
|
+
|
461
|
+
def votes=(value)
|
462
|
+
@_votes = value
|
463
|
+
end
|
464
|
+
|
465
|
+
def destroy
|
466
|
+
@site.client.login_check
|
467
|
+
@site.amc_request(bodies: [
|
468
|
+
{
|
469
|
+
action: "WikiPageAction",
|
470
|
+
event: "deletePage",
|
471
|
+
page_id: id,
|
472
|
+
moduleName: "Empty"
|
473
|
+
}
|
474
|
+
])
|
475
|
+
end
|
476
|
+
|
477
|
+
def get_metas
|
478
|
+
response_data = @site.amc_request(bodies: [{ pageId: id, moduleName: "edit/EditMetaModule" }])[0]
|
479
|
+
body = response_data["body"]
|
480
|
+
|
481
|
+
metas = {}
|
482
|
+
body.scan(/<meta name="([^"]+)" content="([^"]+)"/) do |meta|
|
483
|
+
metas[meta[0]] = meta[1]
|
484
|
+
end
|
485
|
+
|
486
|
+
metas
|
487
|
+
end
|
488
|
+
|
489
|
+
def set_meta(name, value)
|
490
|
+
@site.client.login_check
|
491
|
+
@site.amc_request(bodies: [
|
492
|
+
{
|
493
|
+
metaName: name,
|
494
|
+
metaContent: value,
|
495
|
+
action: "WikiPageAction",
|
496
|
+
event: "saveMetaTag",
|
497
|
+
pageId: id,
|
498
|
+
moduleName: "edit/EditMetaModule"
|
499
|
+
}
|
500
|
+
])
|
501
|
+
end
|
502
|
+
|
503
|
+
def delete_meta(name)
|
504
|
+
@site.client.login_check
|
505
|
+
@site.amc_request(bodies: [
|
506
|
+
{
|
507
|
+
metaName: name,
|
508
|
+
action: "WikiPageAction",
|
509
|
+
event: "deleteMetaTag",
|
510
|
+
pageId: id,
|
511
|
+
moduleName: "edit/EditMetaModule"
|
512
|
+
}
|
513
|
+
])
|
514
|
+
end
|
515
|
+
|
516
|
+
def self.create_or_edit(site:, fullname:, page_id: nil, title: "", source: "", comment: "", force_edit: false, raise_on_exists: false)
|
517
|
+
site.client.login_check
|
518
|
+
|
519
|
+
page_lock_request_body = {
|
520
|
+
mode: "page",
|
521
|
+
wiki_page: fullname,
|
522
|
+
moduleName: "edit/PageEditModule"
|
523
|
+
}
|
524
|
+
page_lock_request_body[:force_lock] = "yes" if force_edit
|
525
|
+
|
526
|
+
# `site.amc_request` returns a Hash, no need to call `.json`
|
527
|
+
page_lock_response_data = site.amc_request(bodies: [page_lock_request_body])[0]
|
528
|
+
|
529
|
+
raise Wikidotrb::Common::Exceptions::TargetErrorException, "Page #{fullname} is locked or other locks exist" if page_lock_response_data["locked"] || page_lock_response_data["other_locks"]
|
530
|
+
|
531
|
+
is_exist = page_lock_response_data.key?("page_revision_id")
|
532
|
+
|
533
|
+
raise Wikidotrb::Common::Exceptions::TargetExistsException, "Page #{fullname} already exists" if raise_on_exists && is_exist
|
534
|
+
|
535
|
+
raise ArgumentError, "page_id must be specified when editing existing page" if is_exist && page_id.nil?
|
536
|
+
|
537
|
+
lock_id = page_lock_response_data["lock_id"]
|
538
|
+
lock_secret = page_lock_response_data["lock_secret"]
|
539
|
+
page_revision_id = page_lock_response_data["page_revision_id"]
|
540
|
+
|
541
|
+
edit_request_body = {
|
542
|
+
action: "WikiPageAction",
|
543
|
+
event: "savePage",
|
544
|
+
moduleName: "Empty",
|
545
|
+
mode: "page",
|
546
|
+
lock_id: lock_id,
|
547
|
+
lock_secret: lock_secret,
|
548
|
+
revision_id: page_revision_id || "",
|
549
|
+
wiki_page: fullname,
|
550
|
+
page_id: page_id || "",
|
551
|
+
title: title,
|
552
|
+
source: source,
|
553
|
+
comments: comment
|
554
|
+
}
|
555
|
+
response_data = site.amc_request(bodies: [edit_request_body])[0]
|
556
|
+
|
557
|
+
unless response_data["status"] == "ok"
|
558
|
+
raise WikidotStatusCodeException,
|
559
|
+
"Failed to create or edit page: #{fullname}"
|
560
|
+
end
|
561
|
+
|
562
|
+
res = PageCollection.search_pages(site, Wikidotrb::Module::SearchPagesQuery.new(fullname: fullname))
|
563
|
+
raise NotFoundException, "Page creation failed: #{fullname}" if res.empty?
|
564
|
+
|
565
|
+
res[0]
|
566
|
+
end
|
567
|
+
|
568
|
+
def edit(title: nil, source: nil, comment: nil, force_edit: false)
|
569
|
+
title ||= @title
|
570
|
+
source ||= @source.wiki_text
|
571
|
+
comment ||= ""
|
572
|
+
|
573
|
+
Page.create_or_edit(
|
574
|
+
site: @site,
|
575
|
+
fullname: @fullname,
|
576
|
+
page_id: id,
|
577
|
+
title: title,
|
578
|
+
source: source,
|
579
|
+
comment: comment,
|
580
|
+
force_edit: force_edit
|
581
|
+
)
|
582
|
+
end
|
583
|
+
|
584
|
+
def set_tags(tags)
|
585
|
+
@site.client.login_check
|
586
|
+
@site.amc_request(bodies: [
|
587
|
+
{
|
588
|
+
tags: tags.join(" "),
|
589
|
+
action: "WikiPageAction",
|
590
|
+
event: "saveTags",
|
591
|
+
pageId: id,
|
592
|
+
moduleName: "Empty"
|
593
|
+
}
|
594
|
+
])
|
595
|
+
end
|
596
|
+
end
|
597
|
+
end
|
598
|
+
end
|