diff --git a/CHANGELOG.md b/CHANGELOG.md index ec78bee..2004621 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Canary +* Added high-quality portrait check to Profile Helper +* Added option for disabling high-quality portraits +* Added cleaner `[quote][/quote]` style for profiles +* Fixed Redgifs previews (again) + ## 1.26.0 * High-quality portraits * Override the default 100x100px portrait with a high-resolution image @@ -18,7 +24,7 @@ * High-quality portraits are only visible to other F-Chat Rising users; users on other clients will see your regular portrait. * If your image is not a square, [you're gonna have a bad time](https://www.youtube.com/watch?v=6Ls5j5iz2eA). * [YiffBot 4000](https://www.f-list.net/c/YiffBot%204000) integration -* Fix "select/unselect all" behavior in Post Ads (credit: [@FatCatClient](https://github.com/FatCatClient)) +* Fixed "select/unselect all" behavior in Post Ads (credit: [@FatCatClient](https://github.com/FatCatClient)) * Extended emoji support (credit: [@FatCatClient](https://github.com/FatCatClient)) ## 1.25.1 diff --git a/bbcode/EIconSelector.vue b/bbcode/EIconSelector.vue index e81dad8..d232769 100644 --- a/bbcode/EIconSelector.vue +++ b/bbcode/EIconSelector.vue @@ -151,8 +151,8 @@ export default class EIconSelector extends CustomDialog { case 'symbols': return ['loveslove', 'pimpdcash', 'pls stop', 'paw2', 'gender-female', 'gender-male', 'gendershemale', 'gender-cuntboy', 'gender-mherm', - 'gender-transgender', 'usflag', 'europeflag', 'lgbt', 'transflag', 'sunnyuhsuperlove', 'discovered', 'thbun', - 'goldcoin1', 'star', 'full moon', 'sunshine', 'pinetree', 'carrots1', 'smashletter', 'chemicalscience', 'ghostbuster', + 'gender-transgender', 'usflag', 'europeflag', 'lgbt', 'transflag', 'sunnyuhsuperlove', 'discovered', + 'goldcoin1', 'star', 'full moon', 'sunshine', 'pinetree', 'carrots1', 'smashletter', 'ghostbuster', 'cuckquean', 'goldendicegmgolddicegif', 'pentagramo', 'sexsymbol', 'idnd1', 'instagram', 'twitterlogo', 'snapchaticon', 'tiktok', 'twitchlogo', 'discord', 'uber', 'google', 'nvidia', 'playstation', 'suitclubs', 'suitdiamonds', 'suithearts', 'suitspades', 'chainscuffs', @@ -164,11 +164,11 @@ export default class EIconSelector extends CustomDialog { case 'bubbles': return ['takemetohornyjail', 'notcashmoney', 'lickme', 'iacs', 'imahugeslut', 'fuckyouasshole', 'bubblecute', 'pat my head', 'chorse', 'knotslutbubble', 'toofuckinghot', 'pbmr', 'imabimbo', 'dicefuck', 'ciaig', 'horseslut', 'fatdick', 'tomboypussy', - 'breakthesubs', 'fuckingnya', 'iltclion', 'suckfuckobey', 'shemale', 'breedmaster', 'imastepfordwife', 'prier ahegao', + 'breakthesubs', 'fuckingnya', 'iltclion', 'suckfuckobey', 'shemale', 'breedmaster', 'imastepfordwife', 'ahegaoalert2', 'buttslutbb', 'notgayoranything', 'onlyfans', 'horsecockneed', 'crimes', 'breed143', 'nagagross', 'willrim', 'muskslut', '4lewdbubble', 'shimathatlewd', 'hypnosiss', 'imahypnoslut', 'sheepsass2', 'imahugeslut', 'notahealslut', 'ratedmilf', 'ratedstud', 'ratedslut', '5lewdbubble', 'xarcuminme', 'xarcumonme', 'choke me', 'iamgoingtopunchyou', 'snapmychoker', - 'rude1', 'fuckbun', 'iamindanger', 'fuckingelves', 'sluttery', 'helpicantstopsuckingcocks', 'talkpooltoy', 'thatskindahot', 'ygod', + 'rude1', 'fuckbun', 'iamindanger', 'elves', 'sluttery', 'helpicantstopsuckingcocks', 'talkpooltoy', 'thatskindahot', 'ygod', 'simpbait', 'eyesuphere', 'fuckpiggy', 'peggable2', 'sydeanothere', 'nothingcan', 'pawslut', 'stupidboys', 'corpsestare-', 'dinnersex', 'plappening', 'fallout-standby', 'inbagg', 'request denied', 'goodboy0', 'goodending', 'milky2', 'howbadcanibe', 'gwanna', 'spitinmouth', 'bathwater']; @@ -178,15 +178,15 @@ export default class EIconSelector extends CustomDialog { 'rorobutt2', 'fingerlick', 'lapgrind', 'jackthighs', 'a condom', 'wolf abs', 'musclefuck2', 'verobutt3', 'bumsqueeze', 'realahegao4', 'influencerhater', 'assfucker', 'gagged2', 'ballsack3', 'fingerblast3', 'sloppy01', 'sybian', 'floppyhorsecock', 'blackshem1', 'fingersucc', 'vullylick', 'fingersucc', 'cmontakeit', 'jessi flash', 'poju-butt', - 'cheegrope2', 'patr1', 'ahega01 2', 'handjob1nuke', 'harmanfingers', 'hermione1', '2buttw1', 'dropsqueeze', + 'cheegrope2', 'patr1', 'ahega01 2', 'handjob1nuke', 'harmanfingers', '2buttw1', 'dropsqueeze', 'lixlove', 'bbctitjob6', 'appreciativetease', 'bimbowhisper', 'subj3', 'salivashare', 'ballsworship3', 'wolfsknot2', 'gaykiss', - 'slurpkiss', 'absbulge', 'cockiss', 'horsedick11', 'knot1', 'g4ebulge', 'blackadamrough', 'knotdog', 'flaunt', 'cummiefj', 'lovetosuck', + 'slurpkiss', 'absbulge', 'cockiss', 'horsedick11', 'knotknotknot', 'g4ebulge', 'blackadamrough', 'knotdog', 'flaunt', 'cummiefj', 'lovetosuck', 'worship', 'hopelessly in love', 'knotts', 'cockloveeee', 'donglove', 'knotjob2', 'cummz', 'every drop', 'edgyoops', 'orccummies2', 'oralcreampie100px', 'horseoral9a', 'swallowit', 'realahegao4', 'gayicon2', 'slut4', 'hossspurties2', 'cumringgag', 'jillbimbogiffell2']; case 'memes': - return ['guncock', 'michaelguns', 'watchbadass', 'gonnabang', 'flirting101', 'monkeymeme', 'monkeymeme2', 'horsenoises', + return ['guncock', 'michaelguns', 'watchbadass', 'gonnabang', 'flirting101', 'monkeymeme', 'monkeymeme2', 'loudnoises', 'nyancat', 'gayb', 'fortasshole', 'dickletsign', 'sausageface', 'siren0', 'apologize to god', 'jabbalick', 'zeldawink', 'whatislove', 'surprisemothafucka', 'females', 'thanksihateit', 'hell is this', 'confused travolta', 'no words', 'coffindance', 'homelander', 'thatsapenis', 'pennyhee', 'kermitbusiness', 'goodbye', 'rickle', 'shiamagic', 'oag', ]; diff --git a/chat/CharacterSearch.vue b/chat/CharacterSearch.vue index e9da69f..de6f5fc 100644 --- a/chat/CharacterSearch.vue +++ b/chat/CharacterSearch.vue @@ -52,6 +52,7 @@ +
No luck? Try AI play with YiffBot 4000
@@ -94,7 +95,6 @@ profile: CharacterCacheRecord | null; } - function sort(resultX: SearchResult, resultY: SearchResult): number { const x = resultX.character; const y = resultY.character; @@ -185,6 +185,29 @@ // tslint:disable-next-line no-any scoreWatcher: ((event: any) => void) | null = null; + isYiffBot4000Online(): boolean { + return core.characters.get('YiffBot 4000').status !== 'offline'; + } + + showYiffBot4000(): void { + const character = core.characters.get('YiffBot 4000'); + + if (character.status === 'offline') { + return; + } + + const conversation = core.conversations.getPrivate(character); + + conversation.show(); + this.hide(); + + const last = _.last(conversation.messages); + + if (!last || last.time.getTime() < Date.now() - 1000 * 60 * 30) { + conversation.enteredText = 'Hello!'; + conversation.send(); + } + } @Hook('created') async created(): Promise { @@ -695,5 +718,24 @@ .search-spinner { // float: right; } + + .search-yiffbot-suggestion .btn { + padding-left: 5px; + padding-right: 5px; + margin-top: 1em; + margin-bottom: 0; + padding-top: 0; + padding-bottom: 0; + background-color: var(--secondary); + + &:hover { + background-color: var(--blue); + } + + span { + color: var(--yellow); + font-weight: bold; + } + } } diff --git a/chat/SettingsView.vue b/chat/SettingsView.vue index cb72884..c3c98d1 100644 --- a/chat/SettingsView.vue +++ b/chat/SettingsView.vue @@ -212,6 +212,13 @@ Show character portrait with each message + +
+ +
@@ -383,6 +390,7 @@ risingShowPortraitNearInput!: boolean; risingShowPortraitInMessage!: boolean; + risingShowHighQualityPortraits!: boolean; risingFilter!: SmartFilterSettings = {} as any; @@ -427,6 +435,7 @@ this.risingColorblindMode = settings.risingColorblindMode; this.risingShowPortraitNearInput = settings.risingShowPortraitNearInput; this.risingShowPortraitInMessage = settings.risingShowPortraitInMessage; + this.risingShowHighQualityPortraits = settings.risingShowHighQualityPortraits; this.risingFilter = settings.risingFilter; } @@ -490,6 +499,7 @@ risingShowUnreadOfflineCount: this.risingShowUnreadOfflineCount, risingShowPortraitNearInput: this.risingShowPortraitNearInput, risingShowPortraitInMessage: this.risingShowPortraitInMessage, + risingShowHighQualityPortraits: this.risingShowHighQualityPortraits, risingColorblindMode: this.risingColorblindMode, risingFilter: { diff --git a/chat/common.ts b/chat/common.ts index 0471c89..6fb3a41 100644 --- a/chat/common.ts +++ b/chat/common.ts @@ -63,6 +63,7 @@ export class Settings implements ISettings { risingColorblindMode = false; risingShowPortraitNearInput = true; risingShowPortraitInMessage = true; + risingShowHighQualityPortraits = true; risingFilter = { hideAds: false, diff --git a/chat/interfaces.ts b/chat/interfaces.ts index f79f9af..64d99b7 100644 --- a/chat/interfaces.ts +++ b/chat/interfaces.ts @@ -237,6 +237,7 @@ export namespace Settings { readonly risingColorblindMode: boolean; readonly risingShowPortraitNearInput: boolean; readonly risingShowPortraitInMessage: boolean; + readonly risingShowHighQualityPortraits: boolean; readonly risingFilter: SmartFilterSettings; } diff --git a/electron/blocker/blocker.ts b/electron/blocker/blocker.ts index ce20a42..d1ab188 100644 --- a/electron/blocker/blocker.ts +++ b/electron/blocker/blocker.ts @@ -5,6 +5,7 @@ import path from 'path'; import fs from 'fs'; import * as _ from 'lodash'; import * as electron from 'electron'; +import { NetworkFilter } from '@cliqz/adblocker'; export class BlockerIntegration { protected static readonly adBlockerLists = [ @@ -53,13 +54,17 @@ export class BlockerIntegration { log.debug('adblock.session.created'); + blocker.update({ + newNetworkFilters: [ + NetworkFilter.parse('@@||redgifs.com')!, + ] + }); + blocker.enableBlockingInSession(session); - // blocker.enableBlockingInSession(electron.session.defaultSession); log.debug('adblock.enabled'); BlockerIntegration.configureBlocker(blocker, session); - // BlockerIntegration.configureBlocker(blocker, electron.session.defaultSession); log.debug('adblock.session.attached'); diff --git a/learn/profile-cache.ts b/learn/profile-cache.ts index 48bf84d..d1dca9f 100644 --- a/learn/profile-cache.ts +++ b/learn/profile-cache.ts @@ -72,7 +72,7 @@ export class ProfileCache extends AsyncCache { } - async get(name: string, skipStore: boolean = false, fromChannel?: string): Promise { + async get(name: string, skipStore: boolean = false, _fromChannel?: string): Promise { const key = AsyncCache.nameKey(name); if (key in this.cache) { @@ -149,7 +149,7 @@ export class ProfileCache extends AsyncCache { } } - isSafeImageURL(url: string): boolean { + static isSafeRisingPortraitURL(url: string): boolean { if (url.match(/^https?:\/\/static\.f-list\.net\//i)) { return true; } @@ -177,14 +177,26 @@ export class ProfileCache extends AsyncCache { return false; } - updateOverrides(c: ComplexCharacter): void { - const match = c.character.description.match(/\[url=(.*?)]\s*?Rising\s*?Portrait\s*?\[\/url]/i); + static detectRisingPortraitURL(description: string): string | null { + if (!core.state.settings.risingShowHighQualityPortraits) { + return null; + } + + const match = description.match(/\[url=(.*?)]\s*?Rising\s*?Portrait\s*?\[\/url]/i); if (match && match[1]) { - const avatarUrl = match[1].trim(); + return match[1].trim(); + } - if (!this.isSafeImageURL(avatarUrl)) { - log.info('portrait.hq.invalid.domain', { name: c.character.name, url: avatarUrl }); + return null; + } + + updateOverrides(c: ComplexCharacter): void { + const avatarUrl = ProfileCache.detectRisingPortraitURL(c.character.description); + + if (avatarUrl) { + if (!ProfileCache.isSafeRisingPortraitURL(avatarUrl)) { + log.info('portrait.hq.invalid.domain', { name, url: avatarUrl }); return; } @@ -199,7 +211,6 @@ export class ProfileCache extends AsyncCache { } } - async register(c: ComplexCharacter, skipStore: boolean = false): Promise { const k = AsyncCache.nameKey(c.character.name); const match = ProfileCache.match(c); diff --git a/learn/recommend/profile-recommendation.ts b/learn/recommend/profile-recommendation.ts index 9062775..26c8539 100644 --- a/learn/recommend/profile-recommendation.ts +++ b/learn/recommend/profile-recommendation.ts @@ -4,6 +4,7 @@ import Axios from 'axios'; import { CharacterAnalysis, Matcher } from '../matcher'; import { FurryPreference, Kink, mammalSpecies, Species } from '../matcher-types'; import { characterImage } from '../../chat/common'; +import { ProfileCache } from '../profile-cache'; export enum ProfileRecommendationLevel { INFO = 'info', @@ -39,6 +40,7 @@ export class ProfileRecommendationAnalyzer { this.recommendations = []; await this.checkPortrait(); + await this.checkHqPortrait(); this.checkMissingProperties(); this.checkSpeciesPreferences(); @@ -53,15 +55,25 @@ export class ProfileRecommendationAnalyzer { } protected async checkPortrait(): Promise { - const profileUrl = characterImage(this.profile.character.name); + const portraitUrl = characterImage(this.profile.character.name); - const result = await Axios.head(profileUrl); + const result = await Axios.head(portraitUrl); if (_.trim(result.headers['etag'] || '', '"').trim().toLowerCase() === '639d154d-16c3') { this.add(`ADD_AVATAR`, ProfileRecommendationLevel.CRITICAL, 'Add an avatar portrait', 'Profiles with an avatar portrait stand out in chats.', 'https://wiki.f-list.net/Guide:_Character_Profiles#Avatar'); } } + protected async checkHqPortrait(): Promise { + const profileUrl = ProfileCache.detectRisingPortraitURL(this.profile.character.description); + + if (!profileUrl) { + this.add(`ADD_HQ_AVATAR`, ProfileRecommendationLevel.CRITICAL, 'Add a high-quality portrait', 'Profiles with a high-quality portraits stand out in chats with other F-Chat Rising players.', 'https://github.com/hearmeneigh/fchat-rising/wiki/High%E2%80%90Quality-Portraits'); + } else if (!ProfileCache.isSafeRisingPortraitURL(profileUrl)) { + this.add(`ADD_HQ_AVATAR_SAFE_DOMAIN`, ProfileRecommendationLevel.CRITICAL, 'Unsupported high-quality portrait URL', 'High-quality portraits can only point to f-list.net, freeimages.host, e621.net, iili.io, imgur.com, or redgifs.com domains.', 'https://github.com/hearmeneigh/fchat-rising/wiki/High%E2%80%90Quality-Portraits'); + } + } + protected checkImages(): void { if (!this.profile.character.image_count) { this.add(`ADD_IMAGE`, ProfileRecommendationLevel.CRITICAL, 'Add a profile image', 'Profiles with images are more attractive to other players.', 'https://wiki.f-list.net/Guide:_Character_Profiles#Images'); diff --git a/site/character_page/character_page.vue b/site/character_page/character_page.vue index 7ebf793..87d9d4d 100644 --- a/site/character_page/character_page.vue +++ b/site/character_page/character_page.vue @@ -39,7 +39,7 @@
-
+
@@ -934,4 +934,23 @@ background: var(--headerBackgroundMaskColor) !important; } + .character-description .bbcode { + white-space: pre-line !important; + + blockquote { + margin: 0; + background-color: var(--characterImageWrapperBg); + padding: 1em; + border-radius: 3px; + + .quoteHeader { + border-bottom: 1px solid; + text-transform: uppercase; + font-weight: bold; + font-size: 80%; + opacity: 0.7; + } + } + } +