forked from huggle/huggle
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProcessing.vb
1679 lines (1329 loc) · 75.3 KB
/
Processing.vb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
'This is a source code or part of Huggle project
'This file contains code for edit actions
'Copyright (C) 2011 Huggle team
'This program is free software: you can redistribute it and/or modify
'it under the terms of the GNU General Public License as published by
'the Free Software Foundation, either version 3 of the License, or
'(at your option) any later version.
'This program is distributed in the hope that it will be useful,
'but WITHOUT ANY WARRANTY; without even the implied warranty of
'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
'GNU General Public License for more details.
Imports System.Text.RegularExpressions
Imports System.Web.HttpUtility
Module Processing
Private RcLineRegex As New Regex _
("type=""([^""]*)"" ns=""[^""]*"" title=""([^""]*)"" pageid=""[^""]*"" " _
& "revid=""([^""]*)"" old_revid=""([^""]*)"" rcid=""([^""]*)"" user=""([^""]*)""( bot="""")?( anon=" _
& """"")?( new="""")?( minor="""")? oldlen=""([^""]*)"" newlen=""([^""]*)"" times" _
& "tamp=""([^""]*)""( comment=""([^""]*)"")? />", RegexOptions.Compiled)
Sub ProcessEdit(ByVal Edit As Edit)
If Edit Is Nothing Then
ErrorLog("ProcessEdit")
Exit Sub
End If
If Edit.Time = Date.MinValue Then Edit.Time = Date.SpecifyKind(Date.UtcNow, DateTimeKind.Utc)
If Edit.Oldid Is Nothing Then Edit.Oldid = "prev"
If Edit.Bot Then Edit.User.Bot = True
'Auto summaries
If (Config.PageBlankedPattern IsNot Nothing AndAlso Config.PageBlankedPattern.IsMatch(Edit.Summary)) _
OrElse Edit.Size = 0 Then Edit.Type = EditType.Blanked
If Config.PageRedirectedPattern IsNot Nothing AndAlso Config.PageRedirectedPattern.IsMatch(Edit.Summary) _
Then Edit.Type = EditType.Redirect
If (Config.PageReplacedPattern IsNot Nothing AndAlso Config.PageReplacedPattern.IsMatch(Edit.Summary)) _
OrElse (Edit.Size >= 0 AndAlso Edit.Size <= 200 AndAlso Edit.Change <= -200) _
Then Edit.Type = EditType.ReplacedWith
'Enable
If MainForm IsNot Nothing Then
MainForm.BrowserOpen.Enabled = True
MainForm.BrowserOpenB.Enabled = True
End If
'Assisted summaries
If Config.Summary <> "" AndAlso Edit.Summary.EndsWith(Config.Summary) Then Edit.Assisted = True
For Each Item As String In Config.AssistedSummaries
If Edit.Summary.Contains(Item) Then
Edit.Assisted = True
Exit For
End If
Next Item
If Edit.User IsNot Nothing AndAlso Edit.Page IsNot Nothing Then
If Edit.NewPage Then
Edit.Page.FirstEdit = Edit
Edit.Prev = NullEdit
End If
'Reverts
If Edit.User.Level < UserLevel.Warning Then
For Each Item As Regex In Config.RevertPatterns
If Item.IsMatch(TrimSummary(Edit.Summary)) Then
Edit.Type = EditType.Revert
If Edit.Page.Level = PageLevel.None Then Edit.Page.Level = PageLevel.Watch
If Edit.Prev IsNot Nothing AndAlso Edit.Prev.User IsNot Nothing _
AndAlso Edit.Prev.User IsNot Edit.User AndAlso Edit.Prev.User.Level = UserLevel.None _
Then Edit.Prev.User.Level = UserLevel.Reverted
Exit For
End If
Next Item
End If
If ( Edit.Summary = Config.UndoSummary & " " & Config.Summary ) Then Edit.Type = EditType.Revert
'Reverted users
If (Edit.Type = EditType.Revert AndAlso Edit.Summary.ToLower.Contains("[[special:contributions/")) Then
Dim Username As String = Edit.Summary.Substring(Edit.Summary.ToLower.IndexOf _
("[[special:contributions/") + 24)
If (Username.Contains("]]") OrElse Username.Contains("|")) Then
If (Username.Contains("]]")) Then Username = Username.Substring(0, Username.IndexOf("]]"))
If (Username.Contains("|")) Then Username = Username.Substring(0, Username.IndexOf("|"))
Username = HtmlDecode(Username)
Dim RevertedUser As User = GetUser(Username)
If ((RevertedUser IsNot Edit.User) AndAlso RevertedUser.Level = UserLevel.None) Then
RevertedUser.Level = UserLevel.Reverted
End If
End If
End If
'Reverted edits
If (Edit.Next IsNot Nothing AndAlso Edit.Next.Type = EditType.Revert AndAlso Edit.User.Level = UserLevel.None) Then Edit.User.Level = UserLevel.Reverted
'Warnings / block notifications
If Edit.Page.Space Is Space.UserTalk AndAlso Not Edit.Page.IsSubpage Then
Dim SummaryLevel As UserLevel = GetUserLevelFromSummary(Edit)
If SummaryLevel >= UserLevel.Warning AndAlso Not Edit.Page.Owner.Ignored _
AndAlso Edit.Time.AddHours(Config.WarningAge) > Date.UtcNow Then
Edit.Type = EditType.Warning
Edit.WarningLevel = SummaryLevel
If Edit.User.WarnTime < Edit.Time Then Edit.User.WarnTime = Edit.Time
If Edit.Page.Owner.Level < SummaryLevel AndAlso SummaryLevel < UserLevel.Warn4im _
Then Edit.Page.Owner.Level = SummaryLevel
ElseIf SummaryLevel = UserLevel.Notification Then
Edit.Type = EditType.Notification
If Edit.Page.Owner.Level < SummaryLevel AndAlso Not Edit.Page.Owner.Ignored _
Then Edit.Page.Owner.Level = SummaryLevel
End If
End If
'AIV/UAA reports
If (Edit.Page.Name = Config.AIVLocation OrElse Edit.Page.Name = Config.UAALocation) Then
If (Edit.Summary.Contains("User-reported") AndAlso Not (Edit.Summary.Contains(" rm ") OrElse Edit.Summary.Contains("remove"))) Then
Edit.Type = EditType.Report
If Edit.Summary.Contains("User-reported - ") _
OrElse Edit.Summary.Contains("User-reported */ ") Then
Dim Summary As String = ""
If Edit.Summary.Contains("User-reported - ") _
Then Summary = Edit.Summary.Substring(Edit.Summary.IndexOf("User-reported - ") + 16)
If Edit.Summary.Contains("User-reported */ ") _
Then Summary = Edit.Summary.Substring(Edit.Summary.IndexOf("User-reported */ ") + 17)
If Summary.ToLower.StartsWith("[[special:contributions/") Then
Summary = Summary.Substring(22)
If Summary.Contains("|") Then Summary = Summary.Substring(0, Summary.IndexOf("|"))
If Summary.Contains("]") Then Summary = Summary.Substring(0, Summary.IndexOf("]"))
Summary = HtmlDecode(Summary)
Dim ReportedUser As User = GetUser(Summary)
If Not ReportedUser.Ignored Then
If Edit.Page.Name = Config.AIVLocation AndAlso ReportedUser.Level < UserLevel.ReportedAIV _
Then ReportedUser.Level = UserLevel.ReportedAIV
If Edit.Page.Name = Config.UAALocation AndAlso ReportedUser.Level < UserLevel.ReportedUAA _
Then ReportedUser.Level = UserLevel.ReportedUAA
End If
Else
If Summary.EndsWith(" reported") _
Then Summary = Summary.Substring(0, Summary.IndexOf(" reported"))
Dim ReportedUser As User = GetUser(Summary)
If ReportedUser IsNot Nothing AndAlso ReportedUser.Anonymous AndAlso _
ReportedUser.Level < UserLevel.ReportedUAA AndAlso Not ReportedUser.Ignored Then
If Edit.Page.Name = Config.AIVLocation Then ReportedUser.Level = UserLevel.ReportedAIV _
Else ReportedUser.Level = UserLevel.ReportedUAA
End If
End If
End If
End If
If Edit.Summary.ToLower.StartsWith("reporting [[special:contributions/") _
OrElse Edit.Summary.ToLower.StartsWith("extending report for ") Then
Dim Summary As String = Edit.Summary.Substring(34)
If Summary.Contains("|") Then Summary = Summary.Substring(0, Summary.IndexOf("|"))
If Summary.Contains("]") Then Summary = Summary.Substring(0, Summary.IndexOf("]"))
Summary = HtmlDecode(Summary)
Dim ReportedUser As User = GetUser(Summary)
If ReportedUser.Level < UserLevel.ReportedAIV AndAlso Not ReportedUser.Ignored Then _
ReportedUser.Level = UserLevel.ReportedAIV
Edit.Type = EditType.Report
ElseIf Edit.Summary.ToLower.StartsWith("reporting ") AndAlso Edit.Summary.Length > 10 Then
Dim ReportedUser As User = GetUser(Edit.Summary.Substring(10))
If ReportedUser.Level < UserLevel.ReportedAIV AndAlso Not ReportedUser.Ignored Then _
ReportedUser.Level = UserLevel.ReportedAIV
Edit.Type = EditType.Report
End If
If Edit.Summary.ToLower.StartsWith("added report") _
OrElse Edit.Summary.ToLower.StartsWith("reporting") Then Edit.Type = EditType.Report
End If
'Bot AIV reports
If Edit.Page.Name = Config.AIVBotLocation Then
If Edit.Summary.ToLower.StartsWith("automatically reporting") _
AndAlso Edit.Summary.Contains(". (bot)") Then
'ClueBot
Dim UserName As String = Edit.Summary.Substring(Edit.Summary.IndexOf("/") + 1)
If UserName.Contains("/") Then UserName = UserName.Substring(UserName.IndexOf("/") + 1)
UserName = UserName.Substring(0, UserName.IndexOf(". (bot)")).Replace("[", "").Replace("]", "")
UserName = HtmlDecode(UserName)
Dim ReportedUser As User = GetUser(UserName)
If ReportedUser.Level < UserLevel.ReportedAIV AndAlso Not ReportedUser.Ignored _
Then ReportedUser.Level = UserLevel.ReportedAIV
Edit.Type = EditType.Report
ElseIf Edit.Summary.ToLower.StartsWith("bot - reporting apparent vandalism by ") Then
'VoaBot II
Dim UserName As String = Edit.Summary.Substring(45)
If UserName.Contains("|") Then UserName = UserName.Substring(UserName.IndexOf("|") + 6)
If UserName.Contains("]]") Then UserName = UserName.Substring(0, UserName.IndexOf("]]"))
Dim ReportedUser As User = GetUser(UserName)
If ReportedUser.Level < UserLevel.ReportedAIV AndAlso Not ReportedUser.Ignored _
Then ReportedUser.Level = UserLevel.ReportedAIV
Edit.Type = EditType.Report
End If
End If
'Bot UAA reports
If Edit.Page.Name = Config.UAABotLocation Then
If Edit.Summary.ToLower.StartsWith("reporting [[special:contributions/") _
OrElse Edit.Summary.ToLower.StartsWith("extending report for ") Then
Dim UserName As String = Edit.Summary.Substring(34)
If UserName.Contains("|") Then UserName = UserName.Substring(0, UserName.IndexOf("|"))
If UserName.Contains("]") Then UserName = UserName.Substring(0, UserName.IndexOf("]"))
UserName = HtmlDecode(UserName)
Dim ReportedUser As User = GetUser(UserName)
If ReportedUser.Level < UserLevel.ReportedUAA AndAlso Not ReportedUser.Ignored Then _
ReportedUser.Level = UserLevel.ReportedUAA
Edit.Type = EditType.Report
End If
End If
'Tagging
If IsTagFromSummary(Edit) AndAlso Edit.Type = EditType.None Then Edit.Type = EditType.Tag
End If
If Edit.Id IsNot Nothing AndAlso Not Edit.All.ContainsKey(Edit.Id) Then Edit.All.Add(Edit.Id, Edit)
Edit.Processed = True
End Sub
Sub ProcessNewEdit(ByVal Edit As Edit)
If Edit.User Is Nothing OrElse Edit.Page Is Nothing OrElse MainForm Is Nothing Then Exit Sub
Dim Redraw As Boolean
'Update edit properties
If Edit.Page.LastEdit IsNot Nothing Then
Edit.Prev = Edit.Page.LastEdit
Edit.Prev.Next = Edit
If Edit.Prev.Size >= 0 AndAlso Edit.Change <> 0 Then Edit.Size = Edit.Prev.Size + Edit.Change
If Edit.Change <> 0 AndAlso Edit.Size >= 0 Then Edit.Prev.Size = Edit.Size - Edit.Change
End If
If Edit.User Is Nothing Then
Edit.User = Edit.Page.LastEdit.User
End If
If Edit.User.LastEdit IsNot Nothing Then
Edit.PrevByUser = Edit.User.LastEdit
Edit.PrevByUser.NextByUser = Edit
End If
Edit.Page.Exists = True
Edit.Page.Text = Nothing
Edit.Page.SpeedyCriterion = Nothing
Edit.Page.LastEdit = Edit
Edit.User.LastEdit = Edit
If CustomReverts.ContainsKey(Edit.Page) Then
If Edit.User.IsMe AndAlso Edit.Summary = CustomReverts(Edit.Page) Then Edit.Type = EditType.Revert
CustomReverts.Remove(Edit.Page)
End If
'Update statistics and edit counts
Stats.Update(Edit)
Edit.User.SessionEditCount += 1
If Edit.User.EditCount > -1 Then Edit.User.EditCount += 1
'Add edit to the all lists
For Each Queue As Queue In Queue.All.Values
If Queue.MatchesFilter(Edit) Then
If Queue.RevisionRegex IsNot Nothing AndAlso Queue.DiffMode = DiffMode.All Then
If Edit.DiffCacheState = Edit.CacheState.Uncached Then
Edit.DiffCacheState = Huggle.Edit.CacheState.Caching
Dim NewRequest As New DiffRequest
NewRequest.Edit = Edit
NewRequest.Start()
End If
Else
Queue.AddEdit(Edit)
If Queue Is CurrentQueue Then
'Keep user's viewing position when adding new items, if not looking at the top of the queue
If (Queue.SortOrder = QueueSortOrder.Time And (MainForm.QueueScroll.Value) < MainForm.QueueScroll.Maximum And MainForm.QueueScroll.Value > 1) Then MainForm.QueueScroll.Value += 1
Redraw = True
End If
End If
End If
Next Queue
'Issue warnings
Dim i As Integer = 0
Dim Break As Integer = 0
While i < PendingWarnings.Count
If PendingWarnings(i).Page Is Edit.Page Then
If Edit.User.IsMe Then
Dim Last As Edit = PendingWarnings(i).User.TalkPage.LastEdit
If Last IsNot Nothing AndAlso Last.Time.AddSeconds(Config.MinWarningWait) > Date.UtcNow Then
'Do nothing if there is a very recent warning to try to compensate for
'stupid broken tools that warn for other people's reverts *cough* vandalproof *cough*
Log(Msg("warn-fail", PendingWarnings(i).User.Name) & ": " & Msg("warn-recent", _
CStr(Config.MinWarningWait)))
Else
Dim NewWarningRequest As New WarningRequest
NewWarningRequest.Edit = PendingWarnings(i)
NewWarningRequest.Start()
End If
End If
PendingWarnings.RemoveAt(i)
Else
i += 1
End If
End While
'Refresh undo information
For Each Item As Command In Undo
If Item.Edit IsNot Nothing AndAlso Item.Edit.Page Is Edit.Page Then
MainForm.RemoveFromUndoList(Item)
Exit For
End If
Next Item
'Remove in-progress log entries
Dim j As Integer = 0
Break = 0
While j < MainForm.Status.Items.Count And Break < Misc.GlExcess
If TypeOf MainForm.Status.Items(j).Tag Is Page AndAlso CType(MainForm.Status.Items(j).Tag, Page) _
Is Edit.Page Then MainForm.Status.Items.RemoveAt(j) Else j += 1
Break = Break + 1
End While
If Edit.User.IsMe Then
'Log user's edits
If Edit.Summary = "" Then Log("Edited '" & Edit.Page.Name & "': (no summary)", Edit) _
Else Log("Edited '" & Edit.Page.Name & "': " & TrimSummary(Edit.Summary), Edit)
'Add undo information
Dim NewCommand As New Command
NewCommand.Edit = Edit
Select Case Edit.Type
Case EditType.Warning
NewCommand.Type = CommandType.Warning
NewCommand.Description = "Warn " & Edit.Page.Name.Substring(10)
Case EditType.Revert
NewCommand.Type = CommandType.Revert
NewCommand.Description = "Revert on " & Edit.Page.Name
Case EditType.Report
NewCommand.Type = CommandType.Report
NewCommand.Description = "Report " & TrimSummary(Edit.Summary).Substring(10)
Case Else
NewCommand.Type = CommandType.Edit
NewCommand.Description = "Edit " & Edit.Page.Name
End Select
If MainForm IsNot Nothing Then MainForm.AddToUndoList(NewCommand)
End If
'Check for new messages
If Edit.Page Is User.Me.TalkPage AndAlso Not Edit.Bot Then
MainForm.SystemMessages.Enabled = Not Edit.User.IsMe
If MainForm.SystemMessages.Enabled AndAlso Config.TrayIcon Then MainForm.TrayIcon.ShowBalloonTip(10000)
End If
'Warnings
If Edit.Page.Space Is Space.UserTalk AndAlso Not Edit.Page.IsSubpage Then
Dim PageOwner As User = GetUser(Edit.Page.Name.Substring(10))
Dim WarningLevel As UserLevel = GetUserLevelFromSummary(Edit)
If PageOwner IsNot Nothing Then
If Edit.User.IsMe AndAlso PageOwner.WarningsCurrent AndAlso WarningLevel >= UserLevel.Warning Then
'Add our own warnings straight to the list
Dim NewWarning As New Warning
NewWarning.Level = WarningLevel
NewWarning.Time = Edit.Time
NewWarning.Type = "huggle"
NewWarning.User = User.Me
If PageOwner.Warnings Is Nothing Then PageOwner.Warnings = New List(Of Warning)
PageOwner.Warnings.Add(NewWarning)
PageOwner.Warnings.Sort(AddressOf SortWarningsByDate)
Else
'Even if we can get the level of others, we can rarely even guess at the type
PageOwner.WarningsCurrent = False
End If
'Refresh any open user info form
For Each Item As Form In Application.OpenForms
Dim uif As UserInfoForm = TryCast(Item, UserInfoForm)
If uif IsNot Nothing AndAlso uif.User Is PageOwner Then uif.RefreshWarnings()
Next Item
End If
End If
'Get edit counts for non-whitelisted registered users, in batches, and whitelist if appropriate
If Config.AutoWhitelist AndAlso Not Edit.User.Anonymous AndAlso Not Edit.User.Ignored _
AndAlso Not Edit.User.EditCount > 0 Then
NextCount.Add(Edit.User)
'If the list has more than "CountBatchSize" entrys then...
If NextCount.Count >= Config.CountBatchSize Then
Dim NewCountRequest As New CountRequest
NewCountRequest.Users.AddRange(NextCount)
NewCountRequest.Start()
NextCount.Clear()
End If
End If
'Preload diffs
If CurrentQueue IsNot Nothing AndAlso CurrentQueue.DiffMode = DiffMode.Preload _
AndAlso DiffRequest.PreloadCount < Config.Preloads + 1 Then
For k As Integer = 0 To Math.Min(CurrentQueue.Edits.Count, Config.Preloads) - 1
If CurrentQueue.Edits(k).DiffCacheState = Edit.CacheState.Uncached Then
CurrentQueue.Edits(k).DiffCacheState = Huggle.Edit.CacheState.Caching
Dim NewRequest As New DiffRequest
NewRequest.Edit = CurrentQueue.Edits(k)
NewRequest.Start()
DiffRequest.PreloadCount += 1
If DiffRequest.PreloadCount >= Config.Preloads Then Exit For
End If
Next k
End If
'Refresh the interface
If MainForm IsNot Nothing AndAlso MainForm.Visible Then
If CurrentEdit IsNot Nothing AndAlso CurrentPage IsNot Nothing AndAlso CurrentUser IsNot Nothing AndAlso _
(Edit.Page Is CurrentPage OrElse Edit.User Is CurrentUser OrElse Edit.Page Is CurrentUser.TalkPage) Then
MainForm.DrawHistory()
MainForm.DrawContribs()
End If
If Config.ShowQueue AndAlso Redraw Then MainForm.DrawQueues()
For Each Item As TabPage In MainForm.Tabs.TabPages
Dim ThisTab As BrowserTab = CType(Item.Controls(0), BrowserTab)
If ThisTab.Edit IsNot Nothing Then
If ThisTab.Edit.Page Is Edit.Page AndAlso ThisTab.ShowNewEdits Then
'Show new edits to page
DisplayEdit(Edit, False, ThisTab, Not Edit.User.IsMe)
If ThisTab Is CurrentTab Then
MainForm.RevertB.Enabled = False
MainForm.RevertWarnB.Enabled = False
MainForm.Reverting = False
MainForm.RevertTimer.Stop()
MainForm.RevertTimer.Interval = 3000
MainForm.RevertTimer.Start()
Else
ThisTab.Highlight = True
End If
ElseIf ThisTab.Edit.User Is Edit.User AndAlso ThisTab.ShowNewContribs Then
'Show new contribs by user
DisplayEdit(Edit, False, ThisTab)
If ThisTab Is CurrentTab Then
MainForm.RevertB.Enabled = False
MainForm.RevertWarnB.Enabled = False
MainForm.RevertTimer.Start()
Else
ThisTab.Highlight = True
End If
End If
End If
Next Item
End If
End Sub
Sub UserDeleteRequest(ByVal Page As Page)
If Page Is Nothing Then Exit Sub
If Config.Rights.Contains("delete") Then
Dim NewDeleteForm As New DeleteForm
NewDeleteForm.Page = Page
NewDeleteForm.Reason.Text = Config.SpeedySummary.Replace("$1", "[[WP:SD#G7|requested by page creator]]")
NewDeleteForm.ShowDialog()
Else
Dim NewTagRequest As New TagRequest
NewTagRequest.Page = Page
NewTagRequest.Tag = "{{db-g7}}"
NewTagRequest.Summary = Config.SpeedySummary.Replace("$1", "[[WP:SD#G7|requested by page creator]]")
NewTagRequest.Start()
End If
End Sub
Function DoRevert(ByVal Edit As Edit, Optional ByVal Summary As String = Nothing, _
Optional ByVal Rollback As Boolean = True, Optional ByVal Undoing As Boolean = False, _
Optional ByVal CurrentOnly As Boolean = False) As Boolean
If Edit Is Nothing OrElse Edit.Page Is Nothing OrElse Edit.User Is Nothing Then Return False
Dim LastEditor As User
If Edit.Page.LastEdit IsNot Nothing Then LastEditor = Edit.Page.LastEdit.User Else LastEditor = Nothing
'Confirm self-reversion
If Config.ConfirmSelfRevert AndAlso Not Undoing AndAlso Edit.User.IsMe _
AndAlso (Edit.Page.FirstEdit Is Nothing OrElse Edit.Id <> Edit.Page.FirstEdit.Id) _
AndAlso MessageBox.Show(Msg("revert-confirm-self"), "Huggle", MessageBoxButtons.YesNo, _
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) = DialogResult.No Then Return False
'Confirm reversion of whitelisted user
If Config.ConfirmIgnored AndAlso Edit.User.Ignored AndAlso Not Edit.User.IsMe AndAlso _
MessageBox.Show(Msg("revert-confirm-ignored", Edit.User.Name), "Huggle", MessageBoxButtons.YesNo, _
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) = DialogResult.No Then Return False
'Confirm reversion of multiple edits
If Config.ConfirmMultiple AndAlso Edit.Prev IsNot Nothing AndAlso Edit.User Is Edit.Prev.User _
AndAlso MessageBox.Show(Msg("revert-confirm-multiple", Edit.User.Name), "Huggle", _
MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.No Then Return False
If Not Undoing AndAlso Edit.User.Level = UserLevel.None Then Edit.User.Level = UserLevel.Reverted
If Not Undoing AndAlso Edit.Page.Level = PageLevel.None Then Edit.Page.Level = PageLevel.Watch
'If reverting first edit to user talk page, blank it
If Edit.Page.FirstEdit IsNot Nothing AndAlso Edit.Id = Edit.Page.FirstEdit.Id _
AndAlso Edit.Page.Space Is Space.UserTalk Then
Dim NewRequest As New EditRequest
NewRequest.Text = ""
NewRequest.Page = Edit.Page
NewRequest.Minor = Config.Minor("revert")
NewRequest.Watch = Config.Watch("revert")
If Undoing Then NewRequest.Summary = Config.UndoSummary Else NewRequest.Summary = _
"Revert edit by [[Special:Contributions/" & Config.Username & "|" & Config.Username & "]]"
NewRequest.Start()
Return False
End If
'If reverting first edit to page, offer to tag for speedy deletion
If Edit.Page.FirstEdit IsNot Nothing AndAlso Edit.Id = Edit.Page.FirstEdit.Id Then
If Not Config.Speedy Then
MessageBox.Show(Msg("revert-error-first"))
Return False
End If
Dim Prompt As String = Msg("revert-only") & " "
If Config.Rights.Contains("delete") _
Then Prompt &= Msg("revert-delete-instead") Else Prompt &= Msg("revert-speedy-instead")
If MessageBox.Show(Prompt, "Huggle", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes _
Then UserDeleteRequest(Edit.Page)
Return False
End If
'If reverting page creator, offer to tag for speedy deletion
If Edit.Page.FirstEdit IsNot Nothing AndAlso Config.Speedy AndAlso Edit.User Is Edit.Page.FirstEdit.User Then
Dim Prompt As String = Msg("revert-creator", Edit.User.Name) & " "
If Config.Rights.Contains("delete") _
Then Prompt &= Msg("revert-delete-instead") Else Prompt &= Msg("revert-speedy-instead")
Select Case MessageBox.Show(Prompt, "Huggle", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)
Case DialogResult.Yes
UserDeleteRequest(Edit.Page)
Return False
Case DialogResult.Cancel
Return False
End Select
End If
'Confirm revert to revision by a warned user
If Config.ConfirmWarned AndAlso Not Undoing AndAlso Edit.Prev IsNot Nothing AndAlso Edit.Prev.User IsNot Nothing _
AndAlso Edit.Prev.User IsNot Edit.User AndAlso Edit.Prev.User.Level >= UserLevel.Warn1 AndAlso _
MessageBox.Show(Msg("revert-confirm-warned", Edit.User.Name), "Huggle", MessageBoxButtons.YesNo, _
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) = DialogResult.No Then Return False
'Confirm revert to revision by anonymous user in same /16 block as user being reverted
If Config.ConfirmRange AndAlso Not Undoing AndAlso Edit.Prev IsNot Nothing AndAlso Edit.Prev.User IsNot Nothing _
AndAlso Edit.Prev.User.Anonymous AndAlso Edit.User.Anonymous AndAlso Edit.Prev.User IsNot Edit.User AndAlso _
Edit.Prev.User.Range = Edit.User.Range AndAlso MessageBox.Show(Msg("revert-confirm-range", _
Edit.User.Name, Edit.Prev.User.Name), "Huggle", MessageBoxButtons.YesNo, MessageBoxIcon.Question, _
MessageBoxDefaultButton.Button2) = DialogResult.No Then Return False
'Confirm revert of ignored page
If Config.ConfirmPage AndAlso Not Undoing AndAlso Config.IgnoredPages.Contains(Edit.Page.Name) AndAlso _
MessageBox.Show(Msg("revert-confirm-page", Edit.Page.Name), "Huggle", MessageBoxButtons.YesNo, _
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) = DialogResult.No Then Return False
If Not Edit.User.Ignored AndAlso Not Edit.User.IsMe AndAlso Not Edit.User.RecentContribsRetrieved Then
Edit.User.RecentContribsRetrieved = True
Dim NewRequest As New ContribsRequest
NewRequest.BlockSize = 10
NewRequest.User = Edit.User
NewRequest.Start()
End If
'Use rollback if possible
If Rollback AndAlso Config.Rights.Contains("rollback") AndAlso Config.UseRollback AndAlso Not Undoing _
AndAlso (Edit Is Edit.Page.LastEdit) AndAlso (Edit.RollbackToken IsNot Nothing) _
AndAlso Not (CurrentOnly AndAlso (Edit.Prev Is Nothing OrElse Edit.User Is Edit.Prev.User)) Then
If Edit Is CurrentEdit Then MainForm.StartRevert()
Dim NewRequest As New RollbackRequest
NewRequest.Edit = Edit
NewRequest.Summary = Summary
NewRequest.Start()
Return True
End If
'Revert all edits by the last editor of the page, if possible
If Edit Is Edit.Page.LastEdit AndAlso Not Undoing _
AndAlso Not (CurrentOnly AndAlso (Edit.Prev Is Nothing OrElse Edit.User Is Edit.Prev.User)) Then
If Edit Is CurrentEdit Then MainForm.StartRevert()
Dim NewRequest As New FakeRollbackRequest
NewRequest.Page = Edit.Page
NewRequest.ExcludeUser = Edit.User
NewRequest.LastUser = LastEditor
NewRequest.Summary = Summary
NewRequest.Start()
Return True
End If
'Confirm revert to another revision by the same user
If Not Undoing AndAlso Edit.Prev IsNot Nothing AndAlso Edit.Prev.User Is Edit.User _
AndAlso Config.ConfirmSame AndAlso Edit.User IsNot User.Me AndAlso _
MessageBox.Show(Msg("revert-confirm-same", Edit.User.Name), "Huggle", MessageBoxButtons.YesNo, _
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) = DialogResult.No Then Return False
If Edit Is CurrentEdit Then MainForm.StartRevert()
If CurrentOnly AndAlso Edit IsNot Edit.Page.LastEdit Then
'Use 'undo' with single edit if necessary
Dim NewRequest As New UndoRequest
NewRequest.Edit = Edit
NewRequest.Summary = Summary
NewRequest.Start()
Return True
Else
'Plain old reversion
Dim NewRequest As New RevertRequest
NewRequest.Edit = Edit.Prev
NewRequest.LastUser = LastEditor
NewRequest.Summary = Summary
NewRequest.Start()
Return True
End If
End Function
Sub ProcessBlock(ByVal BlockObject As Object)
Dim Block As Block = CType(BlockObject, Block)
If Block IsNot Nothing AndAlso Block.User IsNot Nothing Then
Stats.Update(Block)
If Block.User.BlocksCurrent Then
If Block.User.Blocks Is Nothing Then Block.User.Blocks = New List(Of Block)
Block.User.Blocks.Insert(0, Block)
End If
If Block.Action = "block" Then
If Not Block.User.Ignored Then Block.User.Level = UserLevel.Blocked
Else
Block.User.Level = UserLevel.None
End If
'Refresh any open user info form
For Each Item As Form In Application.OpenForms
Dim uif As UserInfoForm = TryCast(Item, UserInfoForm)
If uif IsNot Nothing AndAlso uif.User Is Block.User Then
uif.RefreshBlocks()
End If
Next Item
End If
End Sub
Sub ProcessDelete(ByVal DeleteObject As Object)
Dim Delete As Delete = CType(DeleteObject, Delete)
If Delete IsNot Nothing AndAlso Delete.Page IsNot Nothing Then
Stats.Update(Delete)
Delete.Page.Exists = False
If Delete.Page.DeletesCurrent Then
If Delete.Page.Deletes Is Nothing Then Delete.Page.Deletes = New List(Of Delete)
Delete.Page.Deletes.Insert(0, Delete)
End If
'Remove page's edits from user contribs and queues
For Each Edit As Edit In Delete.Page.Edits
Edit.Deleted = True
If Edit.PrevByUser IsNot Nothing Then Edit.PrevByUser.NextByUser = Edit.NextByUser
If Edit.NextByUser IsNot Nothing Then Edit.NextByUser.PrevByUser = Edit.PrevByUser
For Each Item As Queue In Queue.All.Values
Item.RemoveEdit(Edit)
Next Item
Next Edit
'Refresh any browser tab in which a revision to the page is being viewed
If MainForm IsNot Nothing Then
For Each Item As TabPage In MainForm.Tabs.TabPages
Dim Tab As BrowserTab = CType(Item.Controls(0), BrowserTab)
If Tab.ShowNewEdits AndAlso Tab.Edit IsNot Nothing _
AndAlso Tab.Edit.Page Is Delete.Page Then DisplayEdit(Tab.Edit, False, Tab)
Next Item
End If
End If
End Sub
Sub ProcessRestore(ByVal DeleteObject As Object)
Dim Restore As Delete = CType(DeleteObject, Delete)
If Restore IsNot Nothing AndAlso Restore.Page IsNot Nothing Then
If Restore.Page.DeletesCurrent Then
If Restore.Page.Deletes Is Nothing Then Restore.Page.Deletes = New List(Of Delete)
Restore.Page.Deletes.Insert(0, Restore)
End If
End If
End Sub
Sub ProcessPageMove(ByVal PageMoveObject As Object)
On Error Resume Next
Dim PageMove As PageMove = CType(PageMoveObject, PageMove)
GetPage(PageMove.Source).MovedTo(PageMove.Destination)
'Page move leaves a redirect behind
Dim RedirectEdit As New Edit
RedirectEdit.Type = EditType.Redirect
RedirectEdit.User = PageMove.User
RedirectEdit.Prev = NullEdit
GetPage(PageMove.Source).FirstEdit = RedirectEdit
GetPage(PageMove.Source).LastEdit = RedirectEdit
End Sub
Sub ProcessProtection(ByVal ProtectionObject As Object)
On Error Resume Next
Dim Protection As Protection = CType(ProtectionObject, Protection)
If Protection IsNot Nothing AndAlso Protection.Page IsNot Nothing Then
Stats.Update(Protection)
Dim ThisPage As Page = Protection.Page
If Protection.Page.ProtectionsCurrent Then
If Protection.Page.Protections Is Nothing _
Then Protection.Page.Protections = New List(Of Protection)
Protection.Page.Protections.Insert(0, Protection)
End If
ThisPage.EditLevel = Protection.EditLevel
ThisPage.MoveLevel = Protection.MoveLevel
End If
End Sub
Sub ProcessUpload(ByVal UploadObject As Object)
End Sub
Sub ProcessDiff(ByVal Edit As Edit, ByVal DiffText As String, ByVal Tab As BrowserTab)
Debug.WriteLine("Diff")
If Not Edit.Multiple Then
If DiffText.Contains("<span class=""mw-rollback-link"">") Then
Dim Rollbacktoken As String = DiffText.Substring(DiffText.IndexOf("<span class=""mw-rollback-link"">"))
Edit.RollbackToken = UrlDecode(FindString(Rollbacktoken, "<a href=""", "&token=", """"))
Else
Edit.RollbackToken = Nothing
End If
If Edit.Id = "next" OrElse Edit.Id = "cur" AndAlso DiffText.Contains("<div id=""mw-diff-ntitle1"">") Then
Edit.Id = FindString(DiffText, "<div id=""mw-diff-ntitle1""><strong><a", "oldid=", "'")
End If
If Edit.Id <> "cur" AndAlso Edit.All.ContainsKey(Edit.Id) Then Edit = Edit.All(Edit.Id)
If Edit.Oldid = "prev" AndAlso DiffText.Contains("<div id=""mw-diff-otitle1"">") Then
Edit.Oldid = FindString(DiffText, "<div id=""mw-diff-otitle1""><strong><a", "oldid=", "'")
End If
If Edit.User Is Nothing AndAlso DiffText.Contains("<div id=""mw-diff-ntitle2"">") Then
Dim Username As String = FindString(DiffText, "<div id=""mw-diff-ntitle2"">", ">", "<")
Username = HtmlDecode(Username.Replace(" (page does not exist)", ""))
Edit.User = GetUser(Username)
End If
If Edit.Prev Is Nothing Then
Edit.Prev = New Edit
Edit.Prev.Page = Edit.Page
Edit.Prev.Next = Edit
Edit.Prev.Id = Edit.Oldid
Edit.Prev.Oldid = "prev"
End If
If Edit.Time = Date.MinValue AndAlso DiffText.Contains("<div id=""mw-diff-ntitle1"">") Then
Dim Time As String = FindString(DiffText, "<div id=""mw-diff-ntitle1"">", "</div>")
If Time.Contains("Revision as of ") Then
Time = FindString(Time, "Revision as of ")
If Date.TryParse(Time, Edit.Time) _
Then Edit.Time = Date.SpecifyKind(CDate(Time), DateTimeKind.Local).ToUniversalTime
ElseIf Time.Contains("Current revision") Then
Time = FindString(Time, "Current revision</a> (", ")")
If Date.TryParse(Time, Edit.Time) _
Then Edit.Time = Date.SpecifyKind(CDate(Time), DateTimeKind.Local).ToUniversalTime
End If
End If
If Edit.Prev.Time = Date.MinValue AndAlso DiffText.Contains("<div id=""mw-diff-otitle1"">") Then
Dim Time As String = FindString(DiffText, "<div id=""mw-diff-otitle1"">", "<a href=", ">", "<")
Time = Time.Substring(Time.IndexOf(":") - 2)
If Date.TryParse(Time, Edit.Prev.Time) _
Then Edit.Prev.Time = Date.SpecifyKind(CDate(Time), DateTimeKind.Local).ToUniversalTime
End If
If Edit.Prev.User Is Nothing AndAlso DiffText.Contains("<div id=""mw-diff-otitle2"">") Then
Dim Username As String = HtmlDecode(FindString(DiffText, "<div id=""mw-diff-otitle2"">", ">", "</a>"))
Edit.Prev.User = GetUser(Username)
End If
If Edit.Prev.Summary Is Nothing Then
If DiffText.Contains("<div id=""mw-diff-otitle3"">") Then
Dim Summary As String = FindString(DiffText, "<div id=""mw-diff-otitle3"">")
If Summary.Contains("<div id=""mw-diff-ntitle3"">") Then _
Summary = Summary.Substring(0, Summary.IndexOf("<div id=""mw-diff-ntitle3"">"))
If Summary.Contains("<span class=""comment"">") Then
If Summary.Contains("</span></div>") Then 'without revision deletion links
Summary = FindString(Summary, "<span class=""comment"">", "</span></div>")
ElseIf Summary.Contains("</span> ") Then 'with revision deletion links
Summary = FindString(Summary, "<span class=""comment"">", "</span> ")
Else
Summary = ""
End If
Summary = HtmlToWikiText(Summary)
Edit.Prev.Summary = Summary
Else
Edit.Prev.Summary = ""
End If
Else
Edit.Prev.Summary = ""
End If
End If
If Config.PageCreatedPattern IsNot Nothing AndAlso Config.PageCreatedPattern.IsMatch(Edit.Prev.Summary) _
AndAlso Edit.Prev.Prev Is Nothing Then
Edit.Prev.NewPage = True
Edit.Prev.Prev = NullEdit
Edit.Page.FirstEdit = Edit.Prev
End If
If DiffText.Contains("<div id=""mw-diff-ntitle4""> </div>") Then Edit.Page.LastEdit = Edit
If Not Edit.Prev.Processed Then ProcessEdit(Edit.Prev)
Edit.ChangedContent = GetChangesFromDiff(DiffText)
'Queues that have a revision content filter will now know whether they can add this revision
For Each Queue As Queue In Queue.All.Values
If Queue.RevisionRegex IsNot Nothing AndAlso Queue.MatchesFilter(Edit) _
AndAlso Queue.MatchesContentFilter(Edit) Then Queue.AddEdit(Edit)
Next Queue
End If
Edit.Diff = DiffText
Edit.DiffCacheState = Edit.CacheState.Cached
If Tab.Edit IsNot Nothing AndAlso (Tab.Edit Is Edit OrElse (Tab.Edit.Next Is Edit AndAlso HidingEdit)) _
Then DisplayEdit(Edit, False, Tab, (Edit.User IsNot Nothing AndAlso Not Edit.User.IsMe))
End Sub
'Converts an HTML diff into a string containing LF-separated list of changes on 'new' side of diff
Function GetChangesFromDiff(ByVal Text As String) As String
Dim Changes As String = "", Pos As Integer = 0, TextPart As String
Dim Current As Integer = 0
Pos = Text.IndexOf("<td class=""diff-addedline"">")
While Pos > -1 And Current < Misc.GlExcess
TextPart = Text.Substring(Pos)
Current = Current + 1
Dim Line As String = FindString(TextPart, "<td class=""diff-addedline"">", "</td>")
If Line.Contains("<span class=""diffchange") Then
While Line.Contains("<span class=""diffchange")
Dim Change As String = FindString(Line, "<span class=""diffchange", ">", "</span>")
Changes &= HtmlDecode(StripHTML(Change)) & LF
Line = Line.Substring(Line.IndexOf("<span class=""diffchange") + 1)
End While
ElseIf Line.Length > 0 Then
'No 'diffchange' spans and nothing on the other side => the whole line was added
Dim RowStart As String = Text.Substring(Text.Substring(0, Pos).LastIndexOf("<tr>"))
RowStart = RowStart.Substring(0, RowStart.IndexOf("<td class=""diff-addedline"">"))
If RowStart.Contains("<td colspan=""2""> </td>") Then Changes &= HtmlDecode(StripHTML(Line)) & LF
End If
Pos = Text.IndexOf("<td class=""diff-addedline"">", Pos + 1)
End While
Return Changes
End Function
Sub ProcessHistory(ByVal Result As String, ByVal Page As Page)
On Error Resume Next
If Result Is Nothing Then Return
Dim History As MatchCollection = New Regex("<rev revid=""([^""]+)"" parentid=""([^""]+)"" user=""([^""]+)"" (anon="""" )" & _
"?timestamp=""([^""]+)""( comment=""([^""]+)"")?(>([^<]*)</)?", RegexOptions.Compiled).Matches(Result)
If History.Count = 0 Then
If Page.LastEdit Is Nothing Then Page.LastEdit = NullEdit
Exit Sub
End If
Dim NextEdit As Edit = Nothing
For i As Integer = 0 To History.Count - 1
Dim Edit As Edit
Dim Diff As String = History(i).Groups(1).Value
If Edit.All.ContainsKey(Diff) Then Edit = Edit.All(Diff) Else Edit = New Edit
Edit.Id = Diff
If Edit.Oldid Is Nothing Then Edit.Oldid = "prev"
Edit.Page = Page
If History(i).Groups(8).Value <> "" Then Edit.Text = HtmlDecode(History(i).Groups(9).Value)
Edit.User = GetUser(HtmlDecode(History(i).Groups(3).Value))
If Edit.Summary Is Nothing Then Edit.Summary = HtmlDecode(History(i).Groups(7).Value)
If Edit.Time = Date.MinValue Then Edit.Time = CDate(History(i).Groups(5).Value)
If Page.LastEdit Is Nothing Then
Page.LastEdit = Edit
ElseIf NextEdit IsNot Nothing Then
Edit.Next = NextEdit
Edit.Next.Oldid = Edit.Id
NextEdit.Prev = Edit
End If
NextEdit = Edit
ProcessEdit(Edit)