pervert-monkey 1.0.10 → 1.0.12

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.
Files changed (58) hide show
  1. package/README.md +22 -11
  2. package/dist/core/pervertmonkey.core.es.d.ts +31 -19
  3. package/dist/core/pervertmonkey.core.es.js +752 -120
  4. package/dist/core/pervertmonkey.core.es.js.map +1 -1
  5. package/dist/core/pervertmonkey.core.umd.js +752 -120
  6. package/dist/core/pervertmonkey.core.umd.js.map +1 -1
  7. package/dist/userscripts/3hentai.user.js +19 -26
  8. package/dist/userscripts/camgirlfinder.user.js +2 -2
  9. package/dist/userscripts/camwhores.user.js +12 -16
  10. package/dist/userscripts/e-hentai.user.js +3 -4
  11. package/dist/userscripts/ebalka.user.js +6 -11
  12. package/dist/userscripts/eporner.user.js +11 -16
  13. package/dist/userscripts/erome.user.js +2 -2
  14. package/dist/userscripts/eroprofile.user.js +2 -2
  15. package/dist/userscripts/javhdporn.user.js +2 -2
  16. package/dist/userscripts/missav.user.js +2 -2
  17. package/dist/userscripts/motherless.user.js +19 -40
  18. package/dist/userscripts/namethatporn.user.js +5 -4
  19. package/dist/userscripts/nhentai.user.js +3 -3
  20. package/dist/userscripts/obmenvsem.user.js +18 -4
  21. package/dist/userscripts/pornhub.user.js +9 -12
  22. package/dist/userscripts/spankbang.user.js +6 -38
  23. package/dist/userscripts/thisvid.user.js +20 -22
  24. package/dist/userscripts/xhamster.user.js +20 -16
  25. package/dist/userscripts/xvideos.user.js +7 -12
  26. package/package.json +2 -1
  27. package/src/core/data-handler/data-manager.ts +4 -4
  28. package/src/core/infinite-scroll/index.ts +9 -9
  29. package/src/core/jabroni-config/index.ts +3 -2
  30. package/src/core/jabroni-config/jabroni-gui-controller.ts +60 -0
  31. package/src/core/parsers/thumb-data-parser.ts +36 -13
  32. package/src/core/parsers/thumb-img-parser.ts +49 -46
  33. package/src/core/rules/index.ts +12 -39
  34. package/src/userscripts/index.ts +1 -1
  35. package/src/userscripts/scripts/3hentai.ts +21 -25
  36. package/src/userscripts/scripts/camgirlfinder.ts +1 -1
  37. package/src/userscripts/scripts/camwhores.ts +10 -18
  38. package/src/userscripts/scripts/e-hentai.ts +1 -2
  39. package/src/userscripts/scripts/ebalka.ts +7 -12
  40. package/src/userscripts/scripts/eporner.ts +10 -16
  41. package/src/userscripts/scripts/erome.ts +1 -1
  42. package/src/userscripts/scripts/eroprofile.ts +1 -1
  43. package/src/userscripts/scripts/javhdporn.ts +1 -1
  44. package/src/userscripts/scripts/missav.ts +1 -1
  45. package/src/userscripts/scripts/motherless.ts +19 -49
  46. package/src/userscripts/scripts/namethatporn.ts +7 -6
  47. package/src/userscripts/scripts/nhentai.ts +2 -2
  48. package/src/userscripts/scripts/obmenvsem.ts +19 -4
  49. package/src/userscripts/scripts/pornhub.ts +10 -14
  50. package/src/userscripts/scripts/spankbang.ts +2 -38
  51. package/src/userscripts/scripts/thisvid.ts +26 -26
  52. package/src/userscripts/scripts/xhamster.ts +20 -23
  53. package/src/userscripts/scripts/xvideos.ts +8 -13
  54. package/src/utils/dom/index.ts +10 -0
  55. package/src/utils/events/on-hover.ts +17 -25
  56. package/src/utils/events/tick.ts +1 -3
  57. package/src/utils/observers/index.ts +8 -4
  58. package/src/utils/parsers/time-parser.ts +2 -2
@@ -6,20 +6,21 @@ import {
6
6
  } from '../../utils';
7
7
  import { DataManager, type DataSelectorFn } from '../data-handler';
8
8
  import { InfiniteScroller, type OffsetGenerator } from '../infinite-scroll';
9
- import { DefaultScheme, type SchemeOptions, StoreStateDefault } from '../jabroni-config';
9
+ import {
10
+ DefaultScheme,
11
+ JabronioGuiController,
12
+ type SchemeOptions,
13
+ StoreStateDefault,
14
+ } from '../jabroni-config';
10
15
  import {
11
16
  getPaginationStrategy,
12
17
  type PaginationStrategy,
13
18
  ThumbDataParser,
14
19
  ThumbImgParser,
15
- ThumbsParser
20
+ ThumbsParser,
16
21
  } from '../parsers';
17
22
 
18
23
  export class Rules {
19
- public getThumbUrl(thumb: HTMLElement | HTMLAnchorElement) {
20
- return ((thumb.querySelector('a[href]') || thumb) as HTMLAnchorElement).href;
21
- }
22
-
23
24
  public thumb: Parameters<typeof ThumbDataParser.create>[0] = {};
24
25
  public thumbDataParser: ThumbDataParser;
25
26
 
@@ -73,6 +74,7 @@ export class Rules {
73
74
  public schemeOptions: SchemeOptions = [];
74
75
  public store: JabronioStore;
75
76
  public gui: JabronioGUI;
77
+ public inputController: JabronioGuiController;
76
78
 
77
79
  private createStore() {
78
80
  const config = { ...StoreStateDefault, ...this.storeOptions };
@@ -117,35 +119,6 @@ export class Rules {
117
119
  return window.self !== window.top;
118
120
  }
119
121
 
120
- private setupStoreListeners() {
121
- const eventsMap = {
122
- 'sort by duration': {
123
- action: (direction: boolean) => this.dataManager.sortBy('duration', direction),
124
- },
125
- };
126
-
127
- let lastEvent: undefined | string;
128
- let direction = true;
129
-
130
- this.store.eventSubject.subscribe((event) => {
131
- if (event === lastEvent) {
132
- direction = !direction;
133
- } else {
134
- lastEvent = event;
135
- direction = true;
136
- }
137
-
138
- if (event in eventsMap) {
139
- const ev = eventsMap[event as keyof typeof eventsMap];
140
- ev?.action(direction);
141
- }
142
- });
143
-
144
- this.store.stateSubject.subscribe((a) => {
145
- this.dataManager.applyFilters(a as { [key: string]: boolean });
146
- });
147
- }
148
-
149
122
  private mutationObservers: MutationObserver[] = [];
150
123
 
151
124
  public resetOnPaginationOrContainerDeath = true;
@@ -171,8 +144,6 @@ export class Rules {
171
144
  public onResetCallback?: () => void;
172
145
 
173
146
  private reset() {
174
- // console.log('\nRESET\n');
175
-
176
147
  this.mutationObservers.forEach((o) => {
177
148
  o.disconnect();
178
149
  });
@@ -181,7 +152,9 @@ export class Rules {
181
152
  this.paginationStrategy = getPaginationStrategy(this.paginationStrategyOptions);
182
153
 
183
154
  this.dataManager = new DataManager(this, this.dataHomogenity);
184
- this.setupStoreListeners();
155
+
156
+ this.inputController.dispose();
157
+ this.inputController = new JabronioGuiController(this.store, this.dataManager);
185
158
 
186
159
  this.resetInfiniteScroller();
187
160
 
@@ -209,8 +182,8 @@ export class Rules {
209
182
  this.gui = this.createGui();
210
183
 
211
184
  this.dataManager = new DataManager(this, this.dataHomogenity);
185
+ this.inputController = new JabronioGuiController(this.store, this.dataManager);
212
186
 
213
187
  this.reset();
214
- // console.log('data', this.dataManager.data.values().toArray());
215
188
  }
216
189
  }
@@ -1 +1 @@
1
- import './scripts/pornhub';
1
+ import './scripts/eporner'
@@ -4,7 +4,7 @@ import { circularShift, OnHover, Tick } from '../../utils';
4
4
 
5
5
  export const meta: MonkeyUserScript = {
6
6
  name: '3Hentai PervertMonkey',
7
- version: '1.0.2',
7
+ version: '1.0.4',
8
8
  description: 'Infinite scroll [optional], Filter by Title',
9
9
  match: 'https://*.3hentai.net/*',
10
10
  };
@@ -12,12 +12,12 @@ export const meta: MonkeyUserScript = {
12
12
  const rules = new Rules({
13
13
  containerSelectorLast: '.listing-container',
14
14
  thumbs: {
15
- selector: '.doujin-col'
15
+ selector: '.doujin-col',
16
16
  },
17
17
  thumb: {
18
18
  selectors: {
19
19
  title: '.title',
20
- }
20
+ },
21
21
  },
22
22
  thumbImg: {
23
23
  strategy: 'auto',
@@ -30,30 +30,26 @@ const rules = new Rules({
30
30
 
31
31
  function animatePreview() {
32
32
  const tick = new Tick(500, false);
33
- const end = 999;
33
+ const end = 9999;
34
34
 
35
35
  function rotate(src: string) {
36
- return src.replace(/(\d+)(?=t\.jpg$)/,
37
- (_, n) => `${circularShift(parseInt(n), end)}`);
36
+ return src.replace(/(\d+)(?=t\.jpg$)/, (_, n) => `${circularShift(parseInt(n), end)}`);
38
37
  }
39
38
 
40
- OnHover.create(
41
- document.body,
42
- (e) => e instanceof HTMLImageElement && e.src.endsWith('.jpg'),
43
- (e) => {
44
- const t = e as HTMLImageElement;
45
- const origin = t.src;
46
- t.src = t.src.replace(/\w+\.\w+$/, '1t.jpg');
47
- t.onerror = (_) => tick.stop();
48
- tick.start(
49
- () => {
50
- t.src = rotate(t.src);
51
- },
52
- () => {
53
- t.src = origin;
54
- },
55
- );
56
- },
57
- (_) => tick.stop()
58
- );
39
+ OnHover.create(document.body, '.doujin-col', (e) => {
40
+ const img = e.querySelector('img') as HTMLImageElement;
41
+ const origin = img.src;
42
+ img.src = img.src.replace(/\w+\.\w+$/, '1t.jpg');
43
+ img.onerror = (_) => tick.stop();
44
+ tick.start(
45
+ () => {
46
+ img.src = rotate(img.src);
47
+ },
48
+ () => {
49
+ img.src = origin;
50
+ },
51
+ );
52
+
53
+ return () => tick.stop();
54
+ });
59
55
  }
@@ -2,7 +2,7 @@ import type { MonkeyUserScript } from 'vite-plugin-monkey';
2
2
 
3
3
  export const meta: MonkeyUserScript = {
4
4
  name: 'CamGirlFinder PervertMonkey',
5
- version: '1.6.0',
5
+ version: '1.6.2',
6
6
  description:
7
7
  'Adds model links for CamWhores, webcamrecordings, recu.me, camvideos, privat-zapisi',
8
8
  match: ['https://camgirlfinder.net/*'],
@@ -17,7 +17,7 @@ import {
17
17
 
18
18
  export const meta: MonkeyUserScript = {
19
19
  name: 'CamWhores PervertMonkey',
20
- version: '3.0.4',
20
+ version: '3.0.6',
21
21
  description:
22
22
  'Infinite scroll [optional]. Filter by Title, Duration and Private/Public. Mass friend request button. Download button',
23
23
  match: ['https://*.camwhores.tv', 'https://*.camwhores.*/*'],
@@ -48,7 +48,7 @@ const rules = new Rules({
48
48
  },
49
49
  thumbs: {
50
50
  selector:
51
- '.list-videos .item, .playlist .item, .list-playlists > div > .item, .item:has(.title)'
51
+ '.list-videos .item, .playlist .item, .list-playlists > div > .item, .item:has(.title)',
52
52
  },
53
53
  thumb: {
54
54
  strategy: 'auto-select',
@@ -58,7 +58,6 @@ const rules = new Rules({
58
58
  },
59
59
  thumbImg: {
60
60
  selector: 'data-original',
61
- strategy: 'auto',
62
61
  },
63
62
  gropeStrategy: 'all-in-all',
64
63
  customDataSelectorFns: [
@@ -109,28 +108,21 @@ function animatePreview(container: HTMLElement) {
109
108
 
110
109
  OnHover.create(
111
110
  container,
112
- (target) =>
113
- target.tagName === 'IMG' &&
114
- target.classList.contains('thumb') &&
115
- !!target.getAttribute('src') &&
116
- !/data:image|avatar/.test(target.getAttribute('src') as string),
117
- (_target) => {
118
- const target = _target as HTMLImageElement;
119
- const origin = target.src;
120
- const count = parseInt(target.getAttribute('data-cnt') as string) || 5;
111
+ '.list-videos .item, .playlist .item, .list-playlists > div > .item, .item:has(.title)',
112
+ (e) => {
113
+ const img = e.querySelector('img') as HTMLImageElement;
114
+ const origin = img.src;
115
+ const count = parseInt(img.getAttribute('data-cnt') as string) || 5;
121
116
  tick.start(
122
117
  () => {
123
- target.src = rotateImg(target.src, count);
118
+ img.src = rotateImg(img.src, count);
124
119
  },
125
120
  () => {
126
- target.src = origin;
121
+ img.src = origin;
127
122
  },
128
123
  );
129
- return {
130
- leaveTarget: target.closest('.item') as HTMLElement,
131
- };
124
+ return () => tick.stop();
132
125
  },
133
- () => tick.stop(),
134
126
  );
135
127
  }
136
128
 
@@ -4,7 +4,7 @@ import { fetchHtml } from '../../utils';
4
4
 
5
5
  export const meta: MonkeyUserScript = {
6
6
  name: 'E-Hentai PervertMonkey',
7
- version: '1.0.0',
7
+ version: '1.0.2',
8
8
  description: 'Infinite scroll [optional], Filter by Title',
9
9
  match: ['https://*.e-hentai.org/*'],
10
10
  };
@@ -18,7 +18,6 @@ const rules = new Rules({
18
18
  },
19
19
  thumbImg: {
20
20
  selector: 'data-lazy-load',
21
- strategy: 'auto',
22
21
  },
23
22
  containerSelectorLast: '.itg.gld',
24
23
  paginationStrategyOptions: createPaginationStrategyOptions(),
@@ -4,7 +4,7 @@ import { exterminateVideo, OnHover, parseHtml } from '../../utils';
4
4
 
5
5
  export const meta: MonkeyUserScript = {
6
6
  name: 'Ebalka PervertMonkey',
7
- version: '3.0.1',
7
+ version: '3.0.3',
8
8
  description: 'Infinite scroll [optional], Filter by Title and Duration',
9
9
  match: [
10
10
  'https://b.ebalka.zip/*',
@@ -21,13 +21,13 @@ const rules = new Rules({
21
21
  paginationSelector: '.pagination:not([id *= member])',
22
22
  },
23
23
  thumbs: {
24
- selector: '.card_video'
24
+ selector: '.card_video',
25
25
  },
26
26
  thumb: {
27
27
  selectors: {
28
28
  title: '.card__title',
29
29
  duration: '.card__spot > span:last-child',
30
- }
30
+ },
31
31
  },
32
32
  animatePreview,
33
33
  schemeOptions: ['Text Filter', 'Badge', 'Duration Filter', 'Advanced'],
@@ -50,13 +50,8 @@ function animatePreview(container: HTMLElement) {
50
50
  };
51
51
  }
52
52
 
53
- OnHover.create(
54
- container,
55
- (target) => target.tagName === 'IMG',
56
- (target) => {
57
- const thumb = target.closest('.card') as HTMLElement;
58
- const onOverCallback = animateThumb(thumb);
59
- return { leaveTarget: thumb, onOverCallback };
60
- },
61
- );
53
+ OnHover.create(container, '.card_video', (target) => {
54
+ const thumb = target.closest('.card') as HTMLElement;
55
+ return animateThumb(thumb);
56
+ });
62
57
  }
@@ -5,7 +5,7 @@ import { OnHover } from '../../utils';
5
5
 
6
6
  export const meta: MonkeyUserScript = {
7
7
  name: 'Eporner PervertMonkey',
8
- version: '2.0.2',
8
+ version: '2.0.4',
9
9
  description: 'Infinite scroll [optional], Filter by Title, Duration and HD',
10
10
  match: ['https://*.eporner.com/*', 'https://*.eporner.*/*'],
11
11
  };
@@ -16,6 +16,7 @@ const rules = new Rules({
16
16
  paginationStrategyOptions: {
17
17
  paginationSelector: '.numlist2',
18
18
  },
19
+ thumbs: { selector: 'div[id^=vf][data-id]' },
19
20
  thumb: {
20
21
  selectors: {
21
22
  quality: { type: 'number', selector: '[title="Quality"]' },
@@ -25,11 +26,8 @@ const rules = new Rules({
25
26
  },
26
27
  },
27
28
  thumbImg: {
28
- strategy: 'auto'
29
- // getImgDataAttrDelete: 'auto',
30
- },
31
- thumbs: {
32
- selector: 'div[id^=vf][data-id]',
29
+ strategy: 'auto',
30
+ remove: 'auto',
33
31
  },
34
32
  containerSelectorLast: '#vidresults',
35
33
  customDataSelectorFns: [
@@ -82,14 +80,10 @@ const rules = new Rules({
82
80
  });
83
81
 
84
82
  function animatePreview(doc: HTMLElement) {
85
- OnHover.create(
86
- doc,
87
- (e) => e instanceof HTMLImageElement,
88
- (e) => {
89
- const target = e as HTMLImageElement;
90
- const thumb = target.closest('[data-id]');
91
- const id = thumb?.getAttribute('data-id');
92
- show_video_prev(id);
93
- },
94
- );
83
+ OnHover.create(doc, 'div[id^=vf][data-id]', (e) => {
84
+ const target = e as HTMLImageElement;
85
+ const thumb = target.closest('[data-id]');
86
+ const id = thumb?.getAttribute('data-id');
87
+ show_video_prev(id);
88
+ });
95
89
  }
@@ -4,7 +4,7 @@ import { Rules } from '../../core';
4
4
 
5
5
  export const meta: MonkeyUserScript = {
6
6
  name: 'Erome PervertMonkey',
7
- version: '5.0.1',
7
+ version: '5.0.3',
8
8
  description: 'Infinite scroll [optional], Filter by Title and Video/Photo albums',
9
9
  match: ['*://*.erome.com/*'],
10
10
  };
@@ -3,7 +3,7 @@ import { Rules } from '../../core';
3
3
 
4
4
  export const meta: MonkeyUserScript = {
5
5
  name: 'Eroprofile PervertMonkey',
6
- version: '2.0.1',
6
+ version: '2.0.3',
7
7
  description: 'Infinite scroll [optional], Filter by Title and Duration',
8
8
  match: ['https://*.eroprofile.com/*'],
9
9
  };
@@ -3,7 +3,7 @@ import { Rules } from '../../core';
3
3
 
4
4
  export const meta: MonkeyUserScript = {
5
5
  name: 'Javhdporn PervertMonkey',
6
- version: '3.0.1',
6
+ version: '3.0.3',
7
7
  description: 'Infinite scroll [optional], Filter by Title and Duration',
8
8
  match: [
9
9
  "https://*.javhdporn.net/*",
@@ -3,7 +3,7 @@ import { Rules } from '../../core';
3
3
 
4
4
  export const meta: MonkeyUserScript = {
5
5
  name: 'Missav PervertMonkey',
6
- version: '3.0.1',
6
+ version: '3.0.3',
7
7
  description: 'Infinite scroll [optional], Filter by Title and Duration',
8
8
  match: [
9
9
  'https://*.missav123.com/*',
@@ -5,10 +5,10 @@ import { fetchWith, OnHover, replaceElementTag, Tick } from '../../utils';
5
5
 
6
6
  export const meta: MonkeyUserScript = {
7
7
  name: 'Motherless PervertMonkey',
8
- version: '5.0.2',
8
+ version: '5.0.4',
9
9
  description: 'Infinite scroll [optional], Filter by Title and Duration',
10
10
  match: ['https://motherless.com/*'],
11
- grant: ['GM_addElement', 'GM_addStyle', 'unsafeWindow']
11
+ grant: ['GM_addElement', 'GM_addStyle', 'unsafeWindow'],
12
12
  };
13
13
 
14
14
  (unsafeWindow as any).__is_premium = true;
@@ -22,7 +22,7 @@ const rules = new Rules({
22
22
  uploader: '.uploader',
23
23
  title: '.title',
24
24
  duration: '.size',
25
- }
25
+ },
26
26
  },
27
27
  thumbImg: { strategy: 'auto' },
28
28
  paginationStrategyOptions: {
@@ -34,28 +34,15 @@ const rules = new Rules({
34
34
  });
35
35
 
36
36
  function animatePreview(_: HTMLElement) {
37
- const ANIMATION_INTERVAL = 500;
38
- const tick = new Tick(ANIMATION_INTERVAL);
39
- let currentOverlay: HTMLElement | null = null;
40
-
41
- function onLeave(target: HTMLElement) {
42
- tick.stop();
43
-
44
- const img = target.querySelector('img.static') as HTMLElement;
45
- img.classList.remove('animating');
46
-
47
- if (currentOverlay) {
48
- currentOverlay.style.display = 'none';
49
- }
50
- }
37
+ const tick = new Tick(500);
51
38
 
52
39
  function onOver(target: HTMLElement) {
53
40
  $('.video').off();
54
- const container = target.closest('.desktop-thumb.video') as HTMLElement;
41
+ const container = target.querySelector('.desktop-thumb.video') as HTMLElement;
55
42
  const img = container.querySelector('img.static') as HTMLImageElement;
56
43
  const stripSrc = img.getAttribute('data-strip-src');
57
44
 
58
- img.classList.add('animating');
45
+ container.classList.toggle('animating');
59
46
 
60
47
  let overlay = img.nextElementSibling as HTMLElement;
61
48
  if (!overlay || overlay.tagName !== 'DIV') {
@@ -64,54 +51,37 @@ function animatePreview(_: HTMLElement) {
64
51
  'style',
65
52
  'z-index: 8; position: absolute; top: 0; left: 0; pointer-events: none;',
66
53
  );
67
- img.parentNode?.insertBefore(overlay, img.nextSibling);
54
+ img.after(overlay);
68
55
  }
69
56
 
70
- currentOverlay = overlay;
71
57
  overlay.style.display = 'block';
72
58
 
73
59
  let j = 0;
74
- const containerHeight = container.offsetHeight;
60
+ const containerHeight = container.offsetHeight + 20;
61
+ const w = img.offsetWidth;
62
+ const h = img.offsetHeight;
63
+ const widthRatio = Math.floor((1000.303 * w) / 100);
64
+ const heightRatio = Math.floor((228.6666 * h) / 100);
65
+ const verticalOffset = (containerHeight - h) / 2;
75
66
 
76
67
  tick.start(() => {
77
- const w = img.offsetWidth;
78
- const h = img.offsetHeight;
79
-
80
- const widthRatio = Math.floor((1000.303 * w) / 100);
81
- const heightRatio = Math.floor((228.6666 * h) / 100);
82
-
83
- const verticalOffset = (containerHeight - h) / 2;
84
-
85
68
  Object.assign(overlay.style, {
86
69
  width: `${w}px`,
87
70
  height: `${containerHeight}px`,
88
71
  backgroundImage: `url('${stripSrc}')`,
89
72
  backgroundSize: `${widthRatio}px ${heightRatio}px`,
90
73
  backgroundPosition: `-${(j++ * w) % widthRatio}px ${verticalOffset}px`,
91
- backgroundRepeat: 'no-repeat',
92
74
  });
93
75
  });
94
76
 
95
- const onOverCallback = () => onLeave(container);
96
- return { onOverCallback, leaveTarget: container };
77
+ return () => {
78
+ tick.stop();
79
+ container.classList.toggle('animating');
80
+ overlay.style.display = 'none';
81
+ };
97
82
  }
98
83
 
99
- OnHover.create(
100
- document.body,
101
- (e) => {
102
- const container = e.closest('.desktop-thumb.video') as HTMLElement;
103
- if (!container) return false;
104
-
105
- const img = container.querySelector('img.static') as HTMLImageElement;
106
- if (!img) return false;
107
-
108
- const stripSrc = img.getAttribute('data-strip-src');
109
- if (!stripSrc || img.classList.contains('animating')) return false;
110
-
111
- return true;
112
- },
113
- onOver,
114
- );
84
+ OnHover.create(document.body, '.thumb-container, .mobile-thumb', onOver);
115
85
  }
116
86
 
117
87
  //====================================================================================================
@@ -4,7 +4,7 @@ import { Rules } from '../../core';
4
4
 
5
5
  export const meta: MonkeyUserScript = {
6
6
  name: 'NameThatPorn PervertMonkey',
7
- version: '3.0.1',
7
+ version: '3.0.3',
8
8
  description: 'Infinite scroll [optional], Filter by Title and Un/Solved',
9
9
  match: ['https://namethatporn.com/*'],
10
10
  };
@@ -20,12 +20,14 @@ const rules = new Rules({
20
20
  type: 'boolean',
21
21
  selector: '.item_solved, .nsw_r_slvd',
22
22
  },
23
- }
23
+ },
24
24
  },
25
25
  thumbImg: {
26
- strategy: 'auto',
27
- selector: (img: HTMLImageElement) =>
28
- img.getAttribute('data-dyn')?.concat('.webp') || (img.getAttribute('src') as string),
26
+ selector: (img: HTMLImageElement) => {
27
+ return (
28
+ img.getAttribute('data-dyn')?.concat('.webp') || (img.getAttribute('src') as string)
29
+ );
30
+ },
29
31
  },
30
32
  paginationStrategyOptions: {
31
33
  paginationSelector: '#smi_wrp, #nsw_p',
@@ -55,7 +57,6 @@ const rules = new Rules({
55
57
  ],
56
58
  });
57
59
 
58
- // some monkeypatching here...
59
60
  unsafeWindow.confirm = () => true;
60
61
 
61
62
  function handleKeys(event: KeyboardEvent) {
@@ -4,7 +4,7 @@ import { parseHtml } from '../../utils';
4
4
 
5
5
  export const meta: MonkeyUserScript = {
6
6
  name: 'NHentai PervertMonkey',
7
- version: '4.0.1',
7
+ version: '4.0.3',
8
8
  description: 'Infinite scroll [optional], Filter by Title',
9
9
  match: ['https://*.nhentai.net/*', 'https://*.nhentai.*/*'],
10
10
  };
@@ -21,7 +21,7 @@ const nhentaiRules = new Rules({
21
21
  },
22
22
  thumbImg: {
23
23
  strategy: 'auto',
24
- shouldDelete: 'auto'
24
+ remove: 'auto'
25
25
  },
26
26
  containerSelectorLast: '.index-container, .container',
27
27
  customDataSelectorFns: ['filterInclude', 'filterExclude'],
@@ -1,16 +1,18 @@
1
1
  import type { MonkeyUserScript } from 'vite-plugin-monkey';
2
- import { GM_addStyle } from '$';
2
+ import { GM_addElement, GM_addStyle } from '$';
3
3
  import { Rules } from '../../core';
4
4
  import { fetchHtml, parseUrl } from '../../utils';
5
5
 
6
6
  export const meta: MonkeyUserScript = {
7
7
  name: 'Obmensvem PervertMonkey',
8
- version: '1.0.1',
8
+ version: '1.0.3',
9
9
  description: 'Infinite scroll [optional], Filter by Title and Duration',
10
10
  match: ['https://*.obmenvsem.com/*', 'https://*.obmenvsem.*/*'],
11
+ grant: ['GM_addStyle', 'GM_addElement', 'unsafeWindow'],
11
12
  };
12
13
 
13
14
  const IS_USER_FILES = location.pathname.startsWith('/user_files');
15
+ const IS_VIDEO_PAGE = /info.php\?id=\d+$/.test(location.href);
14
16
  const SEARCH_PARAM = IS_USER_FILES ? 'start' : 'page';
15
17
 
16
18
  function setup() {
@@ -20,7 +22,21 @@ function setup() {
20
22
  ...document.querySelectorAll('.item:has(> a.block[href *= info] > img)'),
21
23
  );
22
24
  document.querySelector('.c2')?.after(container);
23
- GM_addStyle('a.block[href *= info] > img:first-child { height: 240px; }');
25
+
26
+ if (!IS_VIDEO_PAGE) {
27
+ GM_addStyle('a.block[href *= info] > img:first-child { height: 240px; }');
28
+ }
29
+
30
+ if (IS_VIDEO_PAGE) {
31
+ const vidh = document.querySelector('a[href*=mp4]') as HTMLAnchorElement;
32
+ vidh?.after(
33
+ GM_addElement('video', {
34
+ src: vidh.href,
35
+ controls: true,
36
+ width: vidh.parentElement?.offsetWidth,
37
+ }),
38
+ );
39
+ }
24
40
  }
25
41
 
26
42
  setup();
@@ -43,7 +59,6 @@ const rules = new Rules({
43
59
  thumbs: { selector: '.item:has(> a.block[href *= info] > img)' },
44
60
  thumb: { strategy: 'auto-text' },
45
61
  thumbImg: {
46
- strategy: 'auto',
47
62
  selector: (img) => {
48
63
  const url = (img.closest('a') as HTMLAnchorElement).href;
49
64
  fetchHtml(url).then((dom) => {