Better management of accidental parallel message posting

This commit is contained in:
Mr. Stallion 2020-04-19 12:59:49 -05:00
parent 58076f9ab8
commit f1fbe92dde
6 changed files with 86 additions and 27 deletions

View File

@ -9,6 +9,8 @@ import l from './localize';
import {CommandContext, isAction, isCommand, isWarn, parse as parseCommand} from './slash_commands';
import MessageType = Interfaces.Message.Type;
import {EventBus} from './preview/event-bus';
import throat from 'throat';
import Bluebird from 'bluebird';
function createMessage(this: any, type: MessageType, sender: Character, text: string, time?: Date): Message {
if(type === MessageType.Message && isAction(text)) {
@ -40,6 +42,8 @@ abstract class Conversation implements Interfaces.Conversation {
private lastSent = '';
adManager: AdManager;
protected static readonly conversationThroat = throat(1); // make sure user posting and ad posting won't get in each others' way
constructor(readonly key: string, public _isPinned: boolean) {
this.adManager = new AdManager(this);
}
@ -124,6 +128,19 @@ abstract class Conversation implements Interfaces.Conversation {
}
protected abstract doSend(): void | Promise<void>;
protected static readonly POST_DELAY = 1250;
protected static async testPostDelay(): Promise<void> {
const lastPostDelta = Date.now() - core.cache.getLastPost().getTime();
// console.log('Last Post Delta', lastPostDelta, ((lastPostDelta < Conversation.POST_DELAY) && (lastPostDelta > 0)));
if ((lastPostDelta < Conversation.POST_DELAY) && (lastPostDelta > 0)) {
await Bluebird.delay(Conversation.POST_DELAY - lastPostDelta);
}
}
}
class PrivateConversation extends Conversation implements Interfaces.PrivateConversation {
@ -200,11 +217,23 @@ class PrivateConversation extends Conversation implements Interfaces.PrivateConv
return;
}
core.connection.send('PRI', {recipient: this.name, message: this.enteredText});
const message = createMessage(MessageType.Message, core.characters.ownCharacter, this.enteredText);
this.safeAddMessage(message);
if(core.state.settings.logMessages) await core.logs.logMessage(this, message);
const messageText = this.enteredText;
this.clearText();
await Conversation.conversationThroat(
async() => {
await Conversation.testPostDelay();
core.connection.send('PRI', {recipient: this.name, message: messageText});
core.cache.markLastPostTime();
const message = createMessage(MessageType.Message, core.characters.ownCharacter, messageText);
this.safeAddMessage(message);
if(core.state.settings.logMessages) await core.logs.logMessage(this, message);
}
);
}
private setOwnTyping(status: Interfaces.TypingStatus): void {
@ -335,30 +364,52 @@ class ChannelConversation extends Conversation implements Interfaces.ChannelConv
return;
}
core.connection.send(isAd ? 'LRP' : 'MSG', {channel: this.channel.id, message: this.enteredText});
await this.addMessage(
createMessage(isAd ? MessageType.Ad : MessageType.Message, core.characters.ownCharacter, this.enteredText, new Date()));
if(isAd)
this.nextAd = Date.now() + core.connection.vars.lfrp_flood * 1000;
else this.clearText();
const message = this.enteredText;
core.cache.timeLastPost();
if (!isAd) {
this.clearText();
}
await Conversation.conversationThroat(
async() => {
await Conversation.testPostDelay();
core.connection.send(isAd ? 'LRP' : 'MSG', {channel: this.channel.id, message});
core.cache.markLastPostTime();
await this.addMessage(
createMessage(isAd ? MessageType.Ad : MessageType.Message, core.characters.ownCharacter, message, new Date())
);
if(isAd)
this.nextAd = Date.now() + core.connection.vars.lfrp_flood * 1000;
}
);
}
async sendAd(text: string): Promise<void> {
if (text.length < 1)
return;
core.connection.send('LRP', {channel: this.channel.id, message: text});
await Conversation.conversationThroat(
async() => {
await Conversation.testPostDelay();
await this.addMessage(
createMessage(MessageType.Ad, core.characters.ownCharacter, text, new Date())
core.connection.send('LRP', {channel: this.channel.id, message: text});
core.cache.markLastPostTime();
await this.addMessage(
createMessage(MessageType.Ad, core.characters.ownCharacter, text, new Date())
);
this.nextAd = Date.now() + core.connection.vars.lfrp_flood * 1000;
}
);
this.nextAd = Date.now() + core.connection.vars.lfrp_flood * 1000;
}
}
class ConsoleConversation extends Conversation {
readonly context = CommandContext.Console;
readonly name = l('chat.consoleTab');

View File

@ -40,7 +40,7 @@ export class CacheManager {
protected lastPost: Date = new Date();
timeLastPost(): void {
markLastPostTime(): void {
this.lastPost = new Date();
}

View File

@ -8,6 +8,7 @@
"@f-list/fork-ts-checker-webpack-plugin": "^3.1.1",
"@f-list/vue-ts": "^1.0.3",
"@fortawesome/fontawesome-free": "^5.9.0",
"@types/bluebird": "^3.5.30",
"@types/lodash": "^4.14.134",
"@types/node-fetch": "^2.5.5",
"@types/qs": "^6.9.1",
@ -45,6 +46,7 @@
},
"dependencies": {
"@cliqz/adblocker-electron": "^1.13.0",
"bluebird": "^3.7.2",
"jquery": "^3.4.1",
"keytar": "^5.4.0",
"node-fetch": "^2.6.0"

View File

@ -13,17 +13,18 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
### More Detailed Differences
* Ads view
* Channel Conversations
* Highlight ads from characters most interesting to you
* Hide clearly unmatched ads
* View characters' recent ads
* Ad auto-posting
* Ad Auto-Posting
* Manage channel ad settings via "Tab Settings"
* Automatically re-post ads every 11-18 minutes (randomized) for up to 180 minutes
* Rotate multiple ads on a single channel by entering multiple ads in "Ad Settings"
* Ad ratings
* Ad Ratings
* LFP ads are automatically rated (great/good/maybe/no) and matched against your profile
* Link previews
* Private Conversations
* View a characters' recent ads
* Link Previews
* Hover cursor over any `[url]` to see a preview of it
* Middle click any `[url]` to turn the preview into a sticky / interactive mode
* Link preview has an ad-blocker to minimize page load times and protect against unfriendly scripts
@ -45,8 +46,8 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
* Current search filters are listed in the search dialog
* Search filters can be reset
* Search results can be filtered by species
* Last 15 searches are stored and can be accessed from the 'Search' dialog
* Character status
* Last 15 searches are stored and can be accessed from the 'Character search' dialog
* Character Status Message
* Last 10 status messages are stored and can be accessed from the 'Set status' dialog
* General
* Character profiles, guestbooks, friend lists, and image lists are cached for faster access
@ -55,7 +56,7 @@ This repository contains a heavily customized version of the mainline F-Chat 3.0
* PM list shows characters' online status as a colored icon
* Technical Details for Nerds
* Upgraded to Electron 9.x
* Replaced `node-spellchecker` with the built-in spellchecker that ships with Electron 8
* Replaced `node-spellchecker` with the built-in spellchecker that ships with Electron 8+
* Multi-language support for spell checking (Windows only language is autodetected on MacOS)

View File

@ -51,7 +51,7 @@
true,
"array"
],
"await-promise": [true, "AxiosPromise"],
"await-promise": [true, "AxiosPromise", "Bluebird"],
"comment-format": false,
"completed-docs": false,
"curly": false,

View File

@ -153,6 +153,11 @@
dependencies:
defer-to-connect "^1.0.1"
"@types/bluebird@^3.5.30":
version "3.5.30"
resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.30.tgz#ee034a0eeea8b84ed868b1aa60d690b08a6cfbc5"
integrity sha512-8LhzvcjIoqoi1TghEkRMkbbmM+jhHnBokPGkJWjclMK+Ks0MxEBow3/p2/iFTZ+OIbJHQDSfpgdZEb+af3gfVw==
"@types/chrome@^0.0.103":
version "0.0.103"
resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.103.tgz#604f3d94ab4465cc8cde302c4916f4955eb7e8b6"
@ -844,7 +849,7 @@ block-stream@*:
dependencies:
inherits "~2.0.0"
bluebird@^3.1.1, bluebird@^3.5.0, bluebird@^3.5.5:
bluebird@^3.1.1, bluebird@^3.5.0, bluebird@^3.5.5, bluebird@^3.7.2:
version "3.7.2"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==