Fix for Imgur NSFW wall
This commit is contained in:
parent
3f913fef1d
commit
b762abec97
|
@ -49,6 +49,10 @@
|
|||
[url=https://www.sex.com/pin/38152484-she-likes-it-rough/]Test[/url]
|
||||
|
||||
[url=https://www.sex.com/pin/57537179-cock-slapping-hungry-tongue/]Test[/url]
|
||||
|
||||
[url=https://imgur.com/gallery/ILsb94I]Imgur gallery[/url]
|
||||
|
||||
[url=https://imgur.com/CIKv6sA]Imgur image[/url]
|
||||
*/
|
||||
|
||||
import * as _ from 'lodash';
|
||||
|
@ -57,6 +61,7 @@
|
|||
import { EventBus, EventBusEvent } from './event-bus';
|
||||
import {domain} from '../bbcode/core';
|
||||
import {ImagePreviewMutator} from './image-preview-mutator';
|
||||
import {ImageUrlMutator} from './image-url-mutator';
|
||||
import {Point, screen, WebviewTag} from 'electron';
|
||||
import Timer = NodeJS.Timer;
|
||||
|
||||
|
@ -76,13 +81,15 @@
|
|||
protected visible = false;
|
||||
protected url: string | null = 'about:blank';
|
||||
protected parent: ImagePreview;
|
||||
protected debug: boolean;
|
||||
|
||||
abstract show(url: string): void;
|
||||
abstract show(url: string): Promise<void>;
|
||||
abstract hide(): void;
|
||||
abstract match(domainName: string): boolean;
|
||||
|
||||
constructor(parent: ImagePreview) {
|
||||
this.parent = parent;
|
||||
this.debug = parent.debug;
|
||||
}
|
||||
|
||||
isVisible(): boolean {
|
||||
|
@ -92,6 +99,10 @@
|
|||
getUrl(): string | null {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
setDebug(debug: boolean): void {
|
||||
this.debug = debug;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -102,7 +113,7 @@
|
|||
}
|
||||
|
||||
|
||||
show(url: string): void {
|
||||
async show(url: string): Promise<void> {
|
||||
this.visible = true;
|
||||
this.url = url;
|
||||
}
|
||||
|
@ -119,6 +130,9 @@
|
|||
|
||||
protected allowCachedUrl = true;
|
||||
|
||||
protected urlMutator = new ImageUrlMutator(this.parent.debug);
|
||||
|
||||
|
||||
hide(): void {
|
||||
const wasVisible = this.visible;
|
||||
|
||||
|
@ -139,20 +153,27 @@
|
|||
}
|
||||
|
||||
|
||||
show(url: string): void {
|
||||
setDebug(debug: boolean): void {
|
||||
this.debug = debug;
|
||||
|
||||
this.urlMutator.setDebug(debug);
|
||||
}
|
||||
|
||||
|
||||
async show(url: string): Promise<void> {
|
||||
const webview = this.parent.getWebview();
|
||||
|
||||
try {
|
||||
if ((this.allowCachedUrl) && ((webview.getURL() === url) || (url === this.lastExternalUrl))) {
|
||||
if (this.parent.debug)
|
||||
if (this.debug)
|
||||
console.log('ImagePreview: exec re-show mutator');
|
||||
|
||||
webview.executeJavaScript(this.parent.jsMutator.getReShowMutator());
|
||||
} else {
|
||||
if (this.parent.debug)
|
||||
if (this.debug)
|
||||
console.log('ImagePreview: must load; skip re-show because urls don\'t match', this.url, webview.getURL());
|
||||
|
||||
webview.loadURL(url);
|
||||
webview.loadURL(await this.urlMutator.resolve(url));
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
|
@ -520,6 +541,8 @@
|
|||
this.debug = !this.debug;
|
||||
|
||||
this.jsMutator.setDebug(this.debug);
|
||||
this.localPreviewHelper.setDebug(this.debug);
|
||||
this.externalPreviewHelper.setDebug(this.debug);
|
||||
|
||||
if (this.debug) {
|
||||
const webview = this.getWebview();
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
import * as _ from 'lodash';
|
||||
import Axios from 'axios';
|
||||
|
||||
export type UrlSolverCallback = (url: string, match: RegExpMatchArray) => Promise<string>;
|
||||
|
||||
export interface UrlSolver {
|
||||
matcher: RegExp;
|
||||
solver: UrlSolverCallback;
|
||||
}
|
||||
|
||||
|
||||
export class ImageUrlMutator {
|
||||
|
||||
private solvers: UrlSolver[] = [];
|
||||
|
||||
private static IMGUR_CLIENT_ID = 'd60e27140a73b2e';
|
||||
|
||||
private debug: boolean;
|
||||
|
||||
|
||||
constructor(debug: boolean) {
|
||||
this.debug = debug;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
protected init(): void {
|
||||
this.add(
|
||||
/^https?:\/\/imgur.com\/gallery\/([a-zA-Z0-9]+)/,
|
||||
async(url: string, match: RegExpMatchArray): Promise<string> => {
|
||||
// Imgur Gallery
|
||||
const galleryId = match[1];
|
||||
|
||||
try {
|
||||
const result = await Axios.get(
|
||||
`https://api.imgur.com/3/gallery/${galleryId}/images`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Client-ID ${ImageUrlMutator.IMGUR_CLIENT_ID}`
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const imageUrl = _.get(result, 'data.data.0.link', null);
|
||||
|
||||
if (!imageUrl) {
|
||||
return url;
|
||||
}
|
||||
|
||||
const imageCount = _.get(result, 'data.data.length', 1);
|
||||
|
||||
if (this.debug)
|
||||
console.log('Imgur gallery', url, imageUrl, imageCount);
|
||||
|
||||
return `${imageUrl}?flist_gallery_image_count=${imageCount}`;
|
||||
|
||||
} catch (err) {
|
||||
console.error('Imgur Gallery Failure', url, err);
|
||||
return url;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// must be AFTER gallery test
|
||||
this.add(
|
||||
/^https?:\/\/imgur.com\/([a-zA-Z0-9]+)/,
|
||||
async(url: string, match: RegExpMatchArray): Promise<string> => {
|
||||
// Single Imgur Image
|
||||
const imageId = match[1];
|
||||
|
||||
try {
|
||||
const result = await Axios.get(
|
||||
`https://api.imgur.com/3/image/${imageId}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Client-ID ${ImageUrlMutator.IMGUR_CLIENT_ID}`
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const imageUrl = _.get(result, 'data.data.link', url);
|
||||
|
||||
if (this.debug)
|
||||
console.log('Imgur image', url, imageUrl);
|
||||
|
||||
return imageUrl as string;
|
||||
} catch (err) {
|
||||
console.error('Imgur Image Failure', url, err);
|
||||
return url;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
setDebug(debug: boolean): void {
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
|
||||
protected add(matcher: RegExp, solver: UrlSolverCallback): void {
|
||||
this.solvers.push({matcher, solver});
|
||||
}
|
||||
|
||||
|
||||
async resolve(url: string): Promise<string> {
|
||||
const match = _.find(this.solvers, (s: UrlSolver) => url.match(s.matcher)) as (UrlSolver | undefined);
|
||||
|
||||
if (!match) {
|
||||
return url;
|
||||
}
|
||||
|
||||
return match.solver(url, url.match(match.matcher) as RegExpMatchArray);
|
||||
}
|
||||
}
|
||||
|
|
@ -99,6 +99,25 @@
|
|||
const webContents = electron.remote.getCurrentWebContents();
|
||||
const parent = electron.remote.getCurrentWindow().webContents;
|
||||
|
||||
// Allow requests to imgur.com
|
||||
const session = electron.remote.session;
|
||||
|
||||
/* tslint:disable:no-unsafe-any no-any no-unnecessary-type-assertion */
|
||||
session!.defaultSession!.webRequest!.onBeforeSendHeaders(
|
||||
{
|
||||
urls: [
|
||||
'https?://(api|i).imgur.com/*'
|
||||
]
|
||||
},
|
||||
(details: any, callback: any) => {
|
||||
details.requestHeaders['Origin'] = null;
|
||||
details.headers['Origin'] = null;
|
||||
|
||||
callback({requestHeaders: details.requestHeaders});
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
log.info('About to load keytar');
|
||||
|
||||
/* tslint:disable: no-any no-unsafe-any */ //because this is hacky
|
||||
|
|
|
@ -9,7 +9,7 @@ export enum TagId {
|
|||
Gender = 3,
|
||||
Build = 13,
|
||||
FurryPreference = 29,
|
||||
BdsmRole = 15,
|
||||
SubDomRole = 15,
|
||||
Position = 41,
|
||||
BodyType = 51,
|
||||
ApparentAge = 64,
|
||||
|
@ -29,6 +29,14 @@ export enum Gender {
|
|||
Shemale = 141
|
||||
}
|
||||
|
||||
export enum SubDomRole {
|
||||
AlwaysSubmissive = 7,
|
||||
UsuallySubmissive = 8,
|
||||
Switch = 9,
|
||||
UsuallyDominant = 10,
|
||||
AlwaysDominant = 11
|
||||
}
|
||||
|
||||
export enum Orientation {
|
||||
Straight = 4,
|
||||
Gay = 5,
|
||||
|
@ -73,6 +81,8 @@ enum Kink {
|
|||
Ageplay = 196,
|
||||
UnderageCharacters = 207,
|
||||
|
||||
RoleReversal = 408,
|
||||
|
||||
AnthroCharacters = 587,
|
||||
Humans = 609,
|
||||
|
||||
|
@ -189,7 +199,7 @@ const fchatGenderMap: FchatGenderMap = {
|
|||
Shemale: Gender.Shemale,
|
||||
Herm: Gender.Herm,
|
||||
'Male-Herm': Gender.MaleHerm,
|
||||
'Cunt-boy': Gender.Cuntboy,
|
||||
'Cunt-Boy': Gender.Cuntboy,
|
||||
Transgender: Gender.Transgender
|
||||
};
|
||||
|
||||
|
@ -285,6 +295,7 @@ export class CharacterAnalysis {
|
|||
readonly species: Species | null;
|
||||
readonly furryPreference: FurryPreference | null;
|
||||
readonly age: number | null;
|
||||
readonly subDomRole: SubDomRole | null;
|
||||
|
||||
readonly isAnthro: boolean | null;
|
||||
readonly isHuman: boolean | null;
|
||||
|
@ -297,6 +308,7 @@ export class CharacterAnalysis {
|
|||
this.orientation = Matcher.getTagValueList(TagId.Orientation, c);
|
||||
this.species = Matcher.species(c);
|
||||
this.furryPreference = Matcher.getTagValueList(TagId.FurryPreference, c);
|
||||
this.subDomRole = Matcher.getTagValueList(TagId.SubDomRole, c);
|
||||
|
||||
const ageTag = Matcher.getTagValue(TagId.Age, c);
|
||||
|
||||
|
@ -360,7 +372,8 @@ export class Matcher {
|
|||
[TagId.Gender]: this.resolveGenderScore(),
|
||||
[TagId.Age]: this.resolveAgeScore(),
|
||||
[TagId.FurryPreference]: this.resolveFurryPairingsScore(),
|
||||
[TagId.Species]: this.resolveSpeciesScore()
|
||||
[TagId.Species]: this.resolveSpeciesScore(),
|
||||
[TagId.SubDomRole]: this.resolveSubDomScore()
|
||||
},
|
||||
|
||||
info: {
|
||||
|
@ -610,7 +623,6 @@ export class Matcher {
|
|||
|
||||
private resolveGenderScore(): Score {
|
||||
const you = this.you;
|
||||
|
||||
const theirGender = this.theirAnalysis.gender;
|
||||
|
||||
if (theirGender === null)
|
||||
|
@ -625,6 +637,72 @@ export class Matcher {
|
|||
return new Score(Scoring.NEUTRAL);
|
||||
}
|
||||
|
||||
|
||||
private resolveSubDomScore(): Score {
|
||||
const you = this.you;
|
||||
const yourSubDomRole = this.yourAnalysis.subDomRole;
|
||||
const theirSubDomRole = this.theirAnalysis.subDomRole;
|
||||
const yourRoleReversalPreference = Matcher.getKinkPreference(you, Kink.RoleReversal);
|
||||
|
||||
if ((!yourSubDomRole) || (!theirSubDomRole))
|
||||
return new Score(Scoring.NEUTRAL);
|
||||
|
||||
if ((yourSubDomRole === SubDomRole.AlwaysDominant) || (yourSubDomRole === SubDomRole.UsuallyDominant)) {
|
||||
if (theirSubDomRole === SubDomRole.Switch)
|
||||
return new Score(Scoring.WEAK_MATCH, `Likes <span>switches</span>`);
|
||||
|
||||
if ((theirSubDomRole === SubDomRole.AlwaysSubmissive) || (theirSubDomRole === SubDomRole.UsuallySubmissive))
|
||||
return new Score(Scoring.MATCH, `Loves <span>submissives</span>`);
|
||||
|
||||
if (yourRoleReversalPreference === KinkPreference.Favorite)
|
||||
return new Score(Scoring.MATCH, `Loves <span>role reversal</span>`);
|
||||
|
||||
if (yourRoleReversalPreference === KinkPreference.Yes)
|
||||
return new Score(Scoring.MATCH, `Likes <span>role reversal</span>`);
|
||||
|
||||
if ((yourSubDomRole === SubDomRole.AlwaysDominant) && (theirSubDomRole === SubDomRole.AlwaysDominant))
|
||||
return new Score(Scoring.MISMATCH, 'No <span>dominants</span>');
|
||||
|
||||
return new Score(Scoring.WEAK_MISMATCH, 'Hesitant on <span>dominants</span>');
|
||||
} else if ((yourSubDomRole === SubDomRole.AlwaysSubmissive) || (yourSubDomRole === SubDomRole.UsuallySubmissive)) {
|
||||
if (theirSubDomRole === SubDomRole.Switch)
|
||||
return new Score(Scoring.WEAK_MATCH, `Likes <span>switches</span>`);
|
||||
|
||||
if ((theirSubDomRole === SubDomRole.AlwaysDominant) || (theirSubDomRole === SubDomRole.UsuallyDominant))
|
||||
return new Score(Scoring.MATCH, `Loves <span>dominants</span>`);
|
||||
|
||||
if (yourRoleReversalPreference === KinkPreference.Favorite)
|
||||
return new Score(Scoring.MATCH, `Loves <span>role reversal</span>`);
|
||||
|
||||
if (yourRoleReversalPreference === KinkPreference.Yes)
|
||||
return new Score(Scoring.MATCH, `Likes <span>role reversal</span>`);
|
||||
|
||||
if ((yourSubDomRole === SubDomRole.AlwaysSubmissive) && (theirSubDomRole === SubDomRole.AlwaysSubmissive))
|
||||
return new Score(Scoring.MISMATCH, 'No <span>submissives</span>');
|
||||
|
||||
return new Score(Scoring.WEAK_MISMATCH, 'Hesitant on <span>submissives</span>');
|
||||
}
|
||||
|
||||
// You must be a switch
|
||||
if (theirSubDomRole === SubDomRole.Switch)
|
||||
return new Score(Scoring.MATCH, `Loves <span>switches</span>`);
|
||||
|
||||
// if (yourRoleReversalPreference === KinkPreference.Favorite)
|
||||
// return new Score(Scoring.MATCH, `Loves <span>role reversal</span>`);
|
||||
//
|
||||
// if (yourRoleReversalPreference === KinkPreference.Yes)
|
||||
// return new Score(Scoring.MATCH, `Likes <span>role reversal</span>`);
|
||||
|
||||
if ((theirSubDomRole === SubDomRole.AlwaysDominant) || (theirSubDomRole === SubDomRole.UsuallyDominant))
|
||||
return new Score(Scoring.MATCH, `Loves <span>dominants</span>`);
|
||||
|
||||
if ((theirSubDomRole === SubDomRole.AlwaysSubmissive) || (theirSubDomRole === SubDomRole.UsuallySubmissive))
|
||||
return new Score(Scoring.MATCH, `Loves <span>submissives</span>`);
|
||||
|
||||
return new Score(Scoring.NEUTRAL);
|
||||
}
|
||||
|
||||
|
||||
static getTagValue(tagId: number, c: Character): CharacterInfotag | undefined {
|
||||
return c.infotags[tagId];
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
|
|||
* Kinks are auto-compared when viewing character profile
|
||||
* Custom kink explanations can be expanded inline
|
||||
* Custom kinks are highlighted
|
||||
* Gender, anthro/human preference, age, and sexual preference are highlighted if compatible or incompatible
|
||||
* Gender, anthro/human preference, age, sexual preference, and sub/dom preference are highlighted if compatible or incompatible
|
||||
* Guestbook, friend, and group counts are visible on tabs
|
||||
* Character images are expanded inline
|
||||
* Cleaner presentation for the side bar details (age, etc.), sorted in most relevant order
|
||||
|
@ -43,7 +43,7 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
|
|||
* Search filters can be reset
|
||||
* General
|
||||
* Character profiles, guestbooks, friend lists, and image lists are cached for faster access.
|
||||
* Open conversation dialog for typing in a character name
|
||||
* Conversation dialog can be opened by typing in a character name
|
||||
|
||||
|
||||
## How to Set Up Ads
|
||||
|
@ -76,6 +76,8 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
|
|||
* Configuration dialog for the player to change match weighs, preview settings, etc.
|
||||
* Conversation bot API
|
||||
* Character comparison should consider D/s preference
|
||||
* Fix collapsible details on character view
|
||||
* Filter unmatching ads is not channel specific -- it's either on everywhere or nowhere
|
||||
|
||||
|
||||
# F-List Exported
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
|
||||
|
||||
theirInterestIsRelevant(id: number): boolean {
|
||||
return ((id === TagId.FurryPreference) || (id === TagId.Orientation));
|
||||
return ((id === TagId.FurryPreference) || (id === TagId.Orientation) || (id === TagId.SubDomRole));
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue