Reconnect management for ad manager; Hide/show non-matching ads; throttle profile API queries
This commit is contained in:
parent
c8f0ffddd5
commit
727b3d5712
|
@ -19,7 +19,7 @@
|
|||
</div>
|
||||
<div v-else-if="results" class="results">
|
||||
<h4>{{l('characterSearch.results')}}</h4>
|
||||
<div v-for="character in results" :key="character.name" :class="'status-' + character.status">
|
||||
<div v-for="character in results" :key="character.name" class="search-result" :class="'status-' + character.status">
|
||||
<template v-if="character.status === 'looking'" v-once>
|
||||
<img :src="characterImage(character.name)" v-if="showAvatars"/>
|
||||
<user :character="character" :showStatus="true" :match="true"></user>
|
||||
|
@ -243,6 +243,9 @@
|
|||
.user-view {
|
||||
display: block;
|
||||
}
|
||||
& > .search-result {
|
||||
clear: both;
|
||||
}
|
||||
& > .status-looking {
|
||||
margin-bottom: 5px;
|
||||
min-height: 50px;
|
||||
|
|
|
@ -128,6 +128,11 @@
|
|||
if(this.connected) core.notifications.playSound('logout');
|
||||
this.connected = false;
|
||||
this.connecting = false;
|
||||
|
||||
if (!isReconnect) {
|
||||
core.conversations.channelConversations.forEach((chanConv) => chanConv.adManager.stop());
|
||||
}
|
||||
|
||||
document.title = l('title');
|
||||
});
|
||||
core.connection.onEvent('connecting', async() => {
|
||||
|
|
|
@ -55,6 +55,10 @@
|
|||
<a :class="isChannel(conversation) ? {active: conversation.mode == mode, disabled: conversation.channel.mode != 'both'} : undefined"
|
||||
class="nav-link" href="#" @click.prevent="setMode(mode)">{{l('channel.mode.' + mode)}}</a>
|
||||
</li>
|
||||
<li>
|
||||
<a @click.prevent="toggleNonMatchingAds()" :class="{active: showNonMatchingAds, disabled: !showNonMatchingAds}" v-show="(conversation.mode == 'both' || conversation.mode == 'ads')"
|
||||
class="nav-link" href="#">Non-Matching</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div style="z-index:5;position:absolute;left:0;right:0;max-height:60%;overflow:auto"
|
||||
|
@ -88,8 +92,8 @@
|
|||
|
||||
<a class="btn btn-sm btn-outline-primary renew-autoposts" @click="renewAutoPosting()">{{l('admgr.renew')}}</a>
|
||||
</div>
|
||||
<div class="border-top messages" :class="isChannel(conversation) ? 'messages-' + conversation.mode : undefined" ref="messages"
|
||||
@scroll="onMessagesScroll" style="flex:1;overflow:auto;margin-top:2px">
|
||||
<div class="border-top messages" :class="getMessageWrapperClasses()" ref="messages"
|
||||
@scroll="onMessagesScroll" style="flex:1;overflow:auto;margin-top:2px">
|
||||
<template v-for="message in messages">
|
||||
<message-view :message="message" :channel="isChannel(conversation) ? conversation.channel : undefined" :key="message.id"
|
||||
:classes="message == conversation.lastRead ? 'last-read' : ''">
|
||||
|
@ -209,6 +213,7 @@
|
|||
adAutoPostNextAd: string | null = null;
|
||||
isChannel = Conversation.isChannel;
|
||||
isPrivate = Conversation.isPrivate;
|
||||
showNonMatchingAds = true;
|
||||
|
||||
@Hook('mounted')
|
||||
mounted(): void {
|
||||
|
@ -389,6 +394,27 @@
|
|||
if(conv.channel.mode === 'both') conv.mode = mode;
|
||||
}
|
||||
|
||||
|
||||
toggleNonMatchingAds(): void {
|
||||
this.showNonMatchingAds = !this.showNonMatchingAds;
|
||||
}
|
||||
|
||||
|
||||
/* tslint:disable */
|
||||
getMessageWrapperClasses(): any {
|
||||
if (!this.isChannel(this.conversation)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const conv = <Conversation.ChannelConversation>this.conversation;
|
||||
const classes:any = {};
|
||||
|
||||
classes['messages-' + conv.mode] = true;
|
||||
classes['hide-non-matching'] = !this.showNonMatchingAds;
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
acceptReport(sfc: {callid: number}): void {
|
||||
core.connection.send('SFC', {action: 'confirm', callid: sfc.callid});
|
||||
}
|
||||
|
@ -682,6 +708,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
.messages.hide-non-matching .message.message-score {
|
||||
&.mismatch {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.message {
|
||||
&.message-event {
|
||||
font-size: 85%;
|
||||
|
|
|
@ -19,6 +19,31 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
/*
|
||||
[url=https://giphy.com/gifs/arianagrande-ariana-grande-thank-u-next-you-uldtLAK6tSOKP5PWw3]Test[/url]
|
||||
|
||||
[url=https://media1.tenor.com/images/097ee180965dd336f470b77d064f198f/tenor.gif?itemid=13664909]Test[/url]
|
||||
|
||||
[url=https://tenor.com/view/thank-unext-ariana-grande-thank-you-next-wink-winking-gif-13664909]Test[/url]
|
||||
|
||||
[url=https://www.sex.com/pin/58497794/]Test[/url]
|
||||
|
||||
[url=https://images.sex.com/images/pinporn/2019/09/10/620/21790701.gif]Test[/url]
|
||||
|
||||
[url=http://gfycatporn.com/deepthroat.php]Test[/url]
|
||||
|
||||
[url=https://imgur.com/LmEyXEM]Test[/url]
|
||||
|
||||
[url=https://static1.e621.net/data/6d/bf/6dbf0c369793dbb5a53d9814c17861eb.webm]Test[/url]
|
||||
|
||||
[url=https://www.youtube.com/watch?v=_52zdiltkRM]Test[/url]
|
||||
|
||||
[url=https://e621.net/post/show/1672753/2018-anthro-antlers-balls-bed-big_penis-black_hair]Test[/url]
|
||||
|
||||
[url=https://rule34.xxx/index.php?page=post&s=view&id=3213191]Test[/url]
|
||||
*/
|
||||
|
||||
|
||||
import * as _ from 'lodash';
|
||||
import {Component, Hook} from '@f-list/vue-ts';
|
||||
import Vue from 'vue';
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
import core from './core';
|
||||
import { Conversation } from './interfaces';
|
||||
import Timer = NodeJS.Timer;
|
||||
|
||||
import throat from 'throat';
|
||||
|
||||
const adManagerThroat = throat(1);
|
||||
|
||||
|
||||
export class AdManager {
|
||||
static readonly POSTING_PERIOD = 3 * 60 * 60 * 1000;
|
||||
static readonly START_VARIANCE = 3 * 60 * 1000;
|
||||
static readonly POST_VARIANCE = 8 * 60 * 1000;
|
||||
static readonly POST_DELAY = 1.5 * 60 * 1000;
|
||||
|
||||
static readonly POST_MANUAL_THRESHOLD = 5 * 1000; // don't post anything within 5 seconds of other posts
|
||||
|
||||
private conversation: Conversation;
|
||||
|
||||
private adIndex = 0;
|
||||
|
@ -24,6 +32,29 @@ export class AdManager {
|
|||
return this.active;
|
||||
}
|
||||
|
||||
|
||||
// tslint:disable-next-line
|
||||
private async delay(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
|
||||
// This makes sure there is a 5s delay between channel posts
|
||||
private async sendAdToChannel(msg: string, conv: Conversation.ChannelConversation): Promise<void> {
|
||||
await adManagerThroat(
|
||||
async() => {
|
||||
const delta = Date.now() - core.cache.getLastPost().getTime();
|
||||
|
||||
if ((delta > 0) && (delta < AdManager.POST_MANUAL_THRESHOLD)) {
|
||||
await this.delay(delta);
|
||||
}
|
||||
|
||||
await conv.sendAd(msg);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private async sendNextPost(): Promise<void> {
|
||||
const msg = this.getNextAd();
|
||||
|
||||
|
@ -34,7 +65,7 @@ export class AdManager {
|
|||
|
||||
const chanConv = (<Conversation.ChannelConversation>this.conversation);
|
||||
|
||||
await chanConv.sendAd(msg);
|
||||
await this.sendAdToChannel(msg, chanConv);
|
||||
|
||||
// post next ad every 12 - 22 minutes
|
||||
const nextInMs = Math.max(0, (chanConv.nextAd - Date.now())) +
|
||||
|
|
|
@ -339,6 +339,8 @@ class ChannelConversation extends Conversation implements Interfaces.ChannelConv
|
|||
if(isAd)
|
||||
this.nextAd = Date.now() + core.connection.vars.lfrp_flood * 1000;
|
||||
else this.clearText();
|
||||
|
||||
core.cache.timeLastPost();
|
||||
}
|
||||
|
||||
async sendAd(text: string): Promise<void> {
|
||||
|
|
|
@ -30,11 +30,22 @@ const parserSettings = {
|
|||
};
|
||||
|
||||
|
||||
import throat from 'throat';
|
||||
|
||||
// Throttle queries so that only two profile requests can run at any given time
|
||||
const characterDataThroat = throat(2);
|
||||
|
||||
|
||||
// tslint:disable-next-line: ban-ts-ignore
|
||||
// @ts-ignore
|
||||
async function characterData(name: string | undefined, id: number = -1, skipEvent: boolean = false): Promise<Character> {
|
||||
// console.log('CharacterDataquery', name);
|
||||
return characterDataThroat(async() => executeCharacterData(name, id, skipEvent));
|
||||
}
|
||||
|
||||
// tslint:disable-next-line: ban-ts-ignore
|
||||
// @ts-ignore
|
||||
async function executeCharacterData(name: string | undefined, id: number = -1, skipEvent: boolean = false): Promise<Character> {
|
||||
const data = await core.connection.queryApi<CharacterInfo & {
|
||||
badges: string[]
|
||||
customs_first: boolean
|
||||
|
|
|
@ -37,6 +37,16 @@ export class CacheManager {
|
|||
|
||||
protected profileStore?: IndexedStore;
|
||||
|
||||
protected lastPost: Date = new Date();
|
||||
|
||||
|
||||
timeLastPost(): void {
|
||||
this.lastPost = new Date();
|
||||
}
|
||||
|
||||
getLastPost(): Date {
|
||||
return this.lastPost;
|
||||
}
|
||||
|
||||
async queueForFetching(name: string, skipCacheCheck: boolean = false): Promise<void> {
|
||||
if (!skipCacheCheck) {
|
||||
|
@ -65,7 +75,8 @@ export class CacheManager {
|
|||
// console.log('AddProfileForFetching', name, this.queue.length);
|
||||
}
|
||||
|
||||
async fetchProfile(name: string): Promise<void> {
|
||||
|
||||
async fetchProfile(name: string): Promise<ComplexCharacter | null> {
|
||||
try {
|
||||
await methods.fieldsGet();
|
||||
|
||||
|
@ -74,8 +85,12 @@ export class CacheManager {
|
|||
const r = await this.profileCache.register(c);
|
||||
|
||||
this.updateAdScoringForProfile(c, r.matchScore);
|
||||
|
||||
return c;
|
||||
} catch (err) {
|
||||
console.error('Failed to fetch profile for cache', name, err);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
"sass-loader": "^7.1.0",
|
||||
"sortablejs": "^1.8.0-rc1",
|
||||
"style-loader": "^0.23.1",
|
||||
"throat": "^5.0.0",
|
||||
"ts-loader": "^5.3.1",
|
||||
"tslib": "^1.9.3",
|
||||
"tslint": "^5.12.0",
|
||||
|
|
|
@ -14,6 +14,7 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
|
|||
|
||||
* Ads view
|
||||
* Highlight ads from characters most interesting to you
|
||||
* Hide obviously unmatching ads
|
||||
* View characters' recent ads
|
||||
* Ad auto-posting
|
||||
* Manage channel ad settings via "Tab Settings"
|
||||
|
@ -34,6 +35,7 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
|
|||
* Cleaner presentation for the side bar details (age, etc.), sorted in most relevant order
|
||||
* Less informative side bar details (views, contact) are separated and shown in a less prominent way
|
||||
* Cleaner guestbook view
|
||||
* Profiles, images, guestbook posts, and groups are cached for faster view
|
||||
* Character Search
|
||||
* Search results are sorted based on match scores
|
||||
* Display match score in search results
|
||||
|
@ -59,13 +61,10 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
|
|||
* Split chat view
|
||||
* Improvements to log browsing
|
||||
* Fix broken BBCode, such as `[big]` in character profiles
|
||||
* Which channels my chart partner is on?
|
||||
* Reposition ad settings and toggle
|
||||
* Cache image list, guestbook pages
|
||||
* Save character status messages
|
||||
* Bug: Invalid Ticket
|
||||
* Bug: Posting on the same second
|
||||
* Bug: Images tab count is off
|
||||
* Logout cancels auto-ads
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -6178,6 +6178,11 @@ terser@^3.8.1:
|
|||
source-map "~0.6.1"
|
||||
source-map-support "~0.5.6"
|
||||
|
||||
throat@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b"
|
||||
integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==
|
||||
|
||||
throttleit@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf"
|
||||
|
|
Loading…
Reference in New Issue