From d98819445fd386677bb33df33c2ef88ab9e4bb69 Mon Sep 17 00:00:00 2001 From: Andrzej Stepien Date: Thu, 17 Aug 2023 00:26:54 +0200 Subject: [PATCH] refactor database functions so that: - db prop is passed down from top layer (to make testing easier, and for memory efficiency) - functions are organised into separate, themed files - for readability - tests now pass down a test database, and update it accordingly --- checkAndPublish.mjs | 20 +- data/animal-names.csv | 700 ++++++++++++++++++++++++++ data/database | Bin 44208128 -> 44208128 bytes data/database-testing | Bin 39145472 -> 44208128 bytes data/scripts/db.mjs | 14 - data/scripts/deleteMisspelled.mjs | 4 +- data/scripts/flagDerivatives.mjs | 4 +- data/scripts/flagScientific.mjs | 4 +- data/scripts/importIPAs.mjs | 2 +- data/scripts/importWiktionaryData.mjs | 2 +- database-calls/DELETEFunctions.mjs | 20 + database-calls/EXISTSFunctions.mjs | 26 + database-calls/GETFunctions.mjs | 67 +++ database-calls/INSERTFunctions.mjs | 21 + database-calls/db.mjs | 153 +++--- database-calls/getNewPrompt.mjs | 31 -- database-calls/insertPublished.mjs | 57 --- index.mjs | 5 +- logger.mjs | 2 +- social-interaction/Note.mjs | 7 +- social-interaction/handleMention.mjs | 24 +- start.mjs | 6 +- test/Note.test.mjs | 3 +- test/handleMentions.test.mjs | 33 +- 24 files changed, 969 insertions(+), 236 deletions(-) create mode 100644 data/animal-names.csv delete mode 100644 data/scripts/db.mjs create mode 100644 database-calls/DELETEFunctions.mjs create mode 100644 database-calls/EXISTSFunctions.mjs create mode 100644 database-calls/GETFunctions.mjs create mode 100644 database-calls/INSERTFunctions.mjs delete mode 100644 database-calls/getNewPrompt.mjs delete mode 100644 database-calls/insertPublished.mjs diff --git a/checkAndPublish.mjs b/checkAndPublish.mjs index a507891..18d42b8 100644 --- a/checkAndPublish.mjs +++ b/checkAndPublish.mjs @@ -1,17 +1,17 @@ -import getNewPrompt from "./database-calls/getNewPrompt.mjs" import createNote from "./firefish-calls/createNote.mjs" import makeText from "./makeText.mjs" -import insertPublished from "./database-calls/insertPublished.mjs" +import insertPublished from "./database-calls/INSERTFunctions.mjs" import logger from "./logger.mjs" -import {deleteFromBuffer, todaysPromptAlreadyPublished, tableIsNotEmpty, getPromptFromBuffer} from "./database-calls/db.mjs" +import { deleteFromBuffer } from "./database-calls/DELETEFunctions.mjs" +import { todaysPromptAlreadyPublished, tableIsNotEmpty } from "./database-calls/EXISTSFunctions.mjs" +import { getPromptFromBuffer, getNewPrompt } from "./database-calls/GETFunctions.mjs" - -export default async function checkAndPublish () { +export default async function checkAndPublish (db) { logger.trace("checkAndPublish called") - logger.trace(todaysPromptAlreadyPublished()) - if(!await todaysPromptAlreadyPublished()){ + logger.trace(todaysPromptAlreadyPublished(db)) + if(!await todaysPromptAlreadyPublished(db)){ try { - const prompt = await tableIsNotEmpty('buffer') ? await getPromptFromBuffer() : await getNewPrompt() + const prompt = await tableIsNotEmpty(db,'buffer') ? await getPromptFromBuffer(db) : await getNewPrompt(db) logger.trace({prompt:prompt},"prompt acquired successfully!") try { const text = makeText(prompt) @@ -19,9 +19,9 @@ export default async function checkAndPublish () { const note = await createNote(text) logger.trace("createNote successful!") try { - let response = await deleteFromBuffer(prompt.word) + let response = await deleteFromBuffer(db,prompt.word) if(response===0){logger.error("deleteFromBuffer failed! Are you trying to delete a word that isn't there?")} - response = await insertPublished(note, prompt.word) + response = await insertPublished(db,note, prompt.word) logger.trace("insertPublished successful!") } catch (error) { logger.error(error, 'insertPublished failed!') diff --git a/data/animal-names.csv b/data/animal-names.csv new file mode 100644 index 0000000..a0648ae --- /dev/null +++ b/data/animal-names.csv @@ -0,0 +1,700 @@ +id,name +1,Aardvark +2,Abyssinian +3,Adelie Penguin +4,Affenpinscher +5,Afghan Hound +6,African Bush Elephant +7,African Civet +8,African Clawed Frog +9,African Forest Elephant +10,African Palm Civet +11,African Penguin +12,African Tree Toad +13,African Wild Dog +14,Ainu Dog +15,Airedale Terrier +16,Akbash +17,Akita +18,Alaskan Malamute +19,Albatross +20,Aldabra Giant Tortoise +21,Alligator +22,Alpaca +23,Alpine Dachsbracke +24,Amazon River Dolphin (Pink Dolphin) +25,American Alsatian +26,American Bulldog +27,American Cocker Spaniel +28,American Coonhound +29,American Eskimo Dog +30,American Foxhound +31,American Pit Bull Terrier +32,American Staffordshire Terrier +33,American Water Spaniel +34,Amur Leopard +35,Anatolian Shepherd Dog +36,Anchovies +37,Angelfish +38,Ant +39,Anteater +40,Antelope +41,Appenzeller Dog +42,Arapaima +43,Arctic Fox +44,Arctic Hare +45,Arctic Wolf +46,Armadillo +47,Asian Elephant +48,Asian Giant Hornet +49,Asian Palm Civet +50,Asiatic Black Bear +51,Aurochs +52,Australian Cattle Dog +53,Australian Kelpie Dog +54,Australian Mist +55,Australian Shepherd +56,Australian Terrier +57,Avocet +58,Axolotl +59,Aye Aye +60,Baboon +61,Bactrian Camel +62,Badger +63,Baiji +64,Balinese +65,Banded Palm Civet +66,Bandicoot +67,Barb +68,Barn Owl +69,Barnacle +70,Barracuda +71,Barramundi Fish +72,Basenji Dog +73,Basking Shark +74,Basset Fauve de Bretagne +75,Basset Hound +76,Bat +77,Bavarian Mountain Hound +78,Beagle +79,Bear +80,Bearded Collie +81,Bearded Dragon +82,Beaver +83,Bedlington Terrier +84,Beetle +85,Beluga Sturgeon +86,Bengal Tiger +87,Bernese Mountain Dog +88,Bichir +89,Bichon Frise +90,Biewer Terrier +91,Binturong +92,Bird +93,Birds Of Paradise +94,Birman +95,Bison +96,Black Marlin +97,Black Rhinoceros +98,Black Russian Terrier +99,Black Widow Spider +100,Blobfish +101,Bloodhound +102,Blue Jay +103,Blue Lacy Dog +104,Blue Whale +105,Bluetick Coonhound +106,Bobcat +107,Bolognese Dog +108,Bombay +109,Bongo +110,Bonito Fish +111,Bonobo +112,Booby +113,Border Collie +114,Border Terrier +115,Bornean Orang-utan +116,Borneo Elephant +117,Boston Terrier: Complete Pet Guide +118,Bottlenose Dolphin +119,Bowfin +120,Bowhead Whale +121,Boxer Dog +122,Boykin Spaniel +123,Brazilian Terrier +124,British Timber +125,Brown Bear +126,Budgerigar +127,Buffalo +128,Bull Shark +129,Bull Terrier +130,Bulldog +131,Bullfrog +132,Bullmastiff +133,Bumblebee +134,Burmese +135,Burrowing Frog +136,Butterfly +137,Butterfly Fish +138,Caiman +139,Caiman Lizard +140,Cairn Terrier +141,Camel +142,Camel Spider +143,Canaan Dog +144,Canadian Eskimo Dog +145,Capybara +146,Caracal +147,Carolina Dog +148,Carp +149,Cassowary +150,Cat +151,Caterpillar +152,Catfish +153,Cavalier King Charles Spaniel +154,Centipede +155,Cesky Fousek +156,Chameleon +157,Chamois +158,Cheetah +159,Chesapeake Bay Retriever +160,Chicken +161,Chihuahua +162,Chimaera +163,Chimpanzee +164,Chinchilla +165,Chinese Crested Dog +166,Chinook +167,Chinstrap Penguin +168,Chipmunk +169,Chow Chow +170,Cichlid +171,Clouded Leopard +172,Clownfish +173,Clumber Spaniel +174,Coati +175,Cockatoo +176,Cockroach +177,Coelacanth +178,Collared Peccary +179,Collie +180,Colossal Squid +181,Common Buzzard +182,Common Frog +183,Common Loon +184,Common Toad +185,Cooper’s Hawk +186,Coral +187,Cotton-top Tamarin +188,Cougar +189,Cow +190,Coyote +191,Crab +192,Crab-Eating Macaque +193,Crane +194,Crested Penguin +195,Crocodile +196,Cross River Gorilla +197,Curly Coated Retriever +198,Cuscus +199,Cuttlefish +200,Dachshund +201,Dalmatian +202,Darwin’s Frog +203,Deer +204,Desert Tortoise +205,Deutsche Bracke +206,Dhole +207,Dingo +208,Discus +209,Doberman Pinscher +210,Dodo +211,Dog +212,Dogo Argentino +213,Dogue De Bordeaux +214,Dolphin +215,Donkey +216,Dormouse +217,Dragonfish +218,Dragonfly +219,Drever +220,Drum Fish +221,Duck +222,Dugong +223,Dunker +224,Dusky Dolphin +225,Dwarf Crocodile +226,Eagle +227,Earwig +228,Eastern Gorilla +229,Eastern Lowland Gorilla +230,Echidna +231,Edible Frog +232,Eel +233,Egyptian Mau +234,Electric Eel +235,Elephant +236,Elephant Seal +237,Elephant Shrew +238,Emperor Penguin +239,Emperor Tamarin +240,Emu +241,English Cocker Spaniel +242,English Shepherd +243,English Springer Spaniel +244,Entlebucher Mountain Dog +245,Epagneul Pont Audemer +246,Ermine +247,Eskimo Dog +248,Estrela Mountain Dog +249,Falcon +250,False Killer Whale +251,Fangtooth +252,Fennec Fox +253,Ferret +254,Field Spaniel +255,Fin Whale +256,Finnish Spitz +257,Fire-Bellied Toad +258,Fish +259,Fishing Cat +260,Flamingo +261,Flat Coat Retriever +262,Flounder +263,Fluke Fish (summer flounder) +264,Fly +265,Flying Squirrel +266,Fossa +267,Fox +268,Fox Terrier +269,French Bulldog +270,Frigatebird +271,Frilled Lizard +272,Frilled Shark +273,Frog +274,Fur Seal +275,Galapagos Penguin +276,Galapagos Tortoise +277,Gar +278,Gecko +279,Gentoo Penguin +280,Geoffroys Tamarin +281,Gerbil +282,German Pinscher +283,German Shepherd Guide +284,Gharial +285,Giant African Land Snail +286,Giant Clam +287,Giant Panda Bear +288,Giant Schnauzer +289,Gibbon +290,Gila Monster +291,Giraffe +292,Glass Lizard +293,Glow Worm +294,Goat +295,Goblin Shark +296,Golden Lion Tamarin +297,Golden Masked Owl +298,Golden Oriole +299,Golden Retriever Complete Pet Guide +300,Golden-Crowned Flying Fox +301,Goose +302,Gopher +303,Gorilla +304,Grasshopper +305,Great Dane +306,Great Pyrenees +307,Great White Shark +308,Greater Swiss Mountain Dog +309,Green Anole +310,Green Bee-Eater +311,Greenland Dog +312,Grey Mouse Lemur +313,Grey Reef Shark +314,Grey Seal +315,Greyhound +316,Grizzly Bear +317,Grouse +318,Guinea Fowl +319,Guinea Pig +320,Guppy +321,Hagfish +322,Hammerhead Shark +323,Hamster +324,Hare +325,Harpy Eagle +326,Harrier +327,Havanese +328,Hawaiian Crow +329,Hedgehog +330,Hercules Beetle +331,Hermit Crab +332,Heron +333,Herring +334,Highland Cattle +335,Himalayan +336,Hippopotamus +337,Honey Badger +338,Honey Bee +339,Hoopoe +340,Horn Shark +341,Hornbill +342,Horned Frog +343,Horse +344,Horseshoe Crab +345,Howler Monkey +346,Human +347,Humboldt Penguin +348,Hummingbird +349,Humpback Whale +350,Hyena +351,Ibis +352,Ibizan Hound +353,Iguana +354,Immortal Jellyfish +355,Impala +356,Indian Elephant +357,Indian Palm Squirrel +358,Indian Rhinoceros +359,Indian Star Tortoise +360,Indochinese Tiger +361,Indri +362,Insects +363,Irish Setter Complete Pet Guide +364,Irish WolfHound +365,Italian Greyhound +366,Jack Russel +367,Jackal +368,Jaguar +369,Japanese Chin +370,Japanese Macaque +371,Javan Rhinoceros +372,Javanese +373,Jellyfish +374,Jerboa +375,Kakapo +376,Kangaroo +377,Keel-Billed Toucan +378,Keeshond +379,Killer Whale +380,King Cobra +381,King Crab +382,King Penguin +383,Kingfisher +384,Kiwi +385,Koala +386,Komodo Dragon +387,Krill +388,Kudu +389,Labradoodle +390,Labrador Retriever +391,Ladybug +392,Lamprey +393,Leaf-Tailed Gecko +394,Lemming +395,Lemur +396,Leopard +397,Leopard Cat +398,Leopard Seal +399,Leopard Tortoise +400,Liger +401,Lion +402,Lionfish +403,Little Penguin +404,Lizard +405,Llama +406,Lobster +407,Long-Eared Owl +408,Lungfish +409,Lynx +410,Macaroni Penguin +411,Macaw +412,Magellanic Penguin +413,Magpie +414,Maine Coon +415,Malayan Civet +416,Malayan Tiger +417,Maltese +418,Mammals +419,Manatee +420,Mandrill +421,Maned Wolf +422,Manta Ray +423,Marine Toad +424,Markhor +425,Marmot +426,Marsh Frog +427,Masked Palm Civet +428,Mastiff +429,Mayfly +430,Meerkat +431,Megalodon +432,Mexican Free-Tailed Bat +433,Milkfish +434,Millipede +435,Mink +436,Minke Whale +437,Mole +438,Molly +439,Monarch Butterfly +440,Mongoose +441,Mongrel +442,Monitor Lizard +443,Monkey +444,Monkfish +445,Monte Iberia Eleuth +446,Moorhen +447,Moose +448,Moray Eel +449,Moth +450,Mountain Gorilla +451,Mountain Lion +452,Mouse +453,Mule +454,Muskrat +455,Narwhal +456,Neanderthal +457,Neapolitan Mastiff +458,Newfoundland +459,Newt +460,Nightingale +461,Norfolk Terrier +462,North American Black Bear +463,Northern Inuit Dog +464,Norwegian Forest +465,Numbat +466,Nurse Shark +467,Ocelot +468,Octopus +469,Okapi +470,Old English Sheepdog +471,Olm +472,Opossum +473,Orang-utan +474,Ostrich +475,Otter +476,Oyster +477,Paddlefish +478,Pademelon +479,Pangolin +480,Panther +481,Parrot +482,Patas Monkey +483,Peacock +484,Pekingese +485,Pelican +486,Penguin +487,Pere Davids Deer +488,Peregrine Falcon +489,Persian +490,Petit Basset Griffon Vendéen +491,Pheasant +492,Pied Tamarin +493,Pig +494,Pika +495,Pike Fish +496,Pink Fairy Armadillo +497,Piranha +498,Platypus +499,Pointer +500,Poison Dart Frog +501,Polar Bear +502,Pond Skater +503,Poodle +504,Pool Frog +505,Porcupine +506,Porpoise +507,Possum +508,Prawn +509,Proboscis Monkey +510,Pufferfish +511,Puffin +512,Pug +513,Puma +514,Purple Emperor Butterfly +515,Puss Moth +516,Pygmy Hippopotamus +517,Pygmy Marmoset +518,Quail +519,Quetzal +520,Quokka +521,Quoll +522,Rabbit +523,Raccoon +524,Raccoon Dog +525,Radiated Tortoise +526,Ragdoll +527,Rat +528,Rattlesnake +529,Red Finch +530,Red Fox +531,Red Knee Tarantula +532,Red Panda +533,Red Wolf +534,Red-handed Tamarin +535,Reindeer +536,Rhinoceros +537,River Turtle +538,Robin +539,Rock Hyrax +540,Rockfish +541,Rockhopper Penguin +542,Roseate Spoonbill +543,Rottweiler +544,Royal Penguin +545,Russian Blue +546,Saarloos Wolfdog +547,Saber-Toothed Tiger +548,Sable +549,Saiga +550,Saint Bernard +551,Salamander +552,Salmon +553,Samoyed +554,Sand Lizard +555,Saola +556,Sardines +557,Sawfish +558,Scimitar-horned Oryx +559,Scorpion +560,Scorpion Fish +561,Sea Dragon +562,Sea Lion +563,Sea Otter +564,Sea Slug +565,Sea Squirt +566,Sea Turtle +567,Sea Urchin +568,Seahorse +569,Seal +570,Serval +571,Shark +572,Sheep +573,Shiba Inu +574,Shih Tzu +575,Shrimp +576,Siamese +577,Siamese Fighting Fish +578,Siberian +579,Siberian Husky +580,Siberian Tiger +581,Silver Dollar +582,Skate Fish +583,Skunk +584,Sloth +585,Slow Worm +586,Snail +587,Snake +588,Snapping Turtle +589,Snowshoe +590,Snowy Owl +591,Somali +592,South China Tiger +593,Spadefoot Toad +594,Sparrow +595,Spectacled Bear +596,Sperm Whale +597,Spider Monkey +598,Spiny Dogfish +599,Spixs Macaw +600,Sponge +601,Squid +602,Squirrel +603,Squirrel Monkey +604,Sri Lankan Elephant +605,Staffordshire Bull Terrier +606,Stag Beetle +607,Starfish +608,Steller’s Sea Cow +609,Stick Insect +610,Stingray +611,Stoat +612,Striped Rocket Frog +613,Sturgeon +614,Sucker Fish +615,Sugar Glider +616,Sumatran Elephant +617,Sumatran Orang-utan +618,Sumatran Rhinoceros +619,Sumatran Tiger +620,Sun Bear +621,Swai Fish +622,Swan +623,Swedish Vallhund +624,Tamaskan +625,Tang +626,Tapanuli Orang-utan +627,Tapir +628,Tarpon +629,Tarsier +630,Tasmanian Devil +631,Tawny Owl +632,Teddy Roosevelt Terrier +633,Termite +634,Tetra +635,Thorny Devil +636,Tibetan Mastiff +637,Tiffany +638,Tiger +639,Tiger Salamander +640,Tiger Shark +641,Tortoise +642,Toucan +643,Tree Frog +644,Tropicbird +645,Tuatara +646,Turkey +647,Turkish Angora +648,Uakari +649,Uguisu +650,Umbrellabird +651,Utonagan +652,Vampire Bat +653,Vampire Squid +654,Vaquita +655,Vervet Monkey +656,Vulture +657,Wallaby +658,Walleye Fish +659,Walrus +660,Wandering Albatross +661,Warthog +662,Wasp +663,Water Buffalo +664,Water Dragon +665,Water Vole +666,Weasel +667,Welsh Corgi: The Complete Pet Guide +668,West Highland Terrier +669,Western Gorilla +670,Western Lowland Gorilla +671,Whale Shark +672,Whippet +673,White Rhinoceros +674,White Tiger +675,White-Faced Capuchin +676,Wild Boar +677,Wildebeest +678,Wolf +679,Wolf Eel +680,Wolf Spider +681,Wolffish +682,Wolverine +683,Wombat +684,Woodlouse +685,Woodpecker +686,Woolly Mammoth +687,Woolly Monkey +688,Wrasse +689,Wyoming Toad +690,X-Ray Tetra +691,Xerus +692,Yak +693,Yellow-Eyed Penguin +694,Yorkshire Terrier +695,Zebra +696,Zebra Shark +697,Zebu +698,Zonkey +699,Zorse \ No newline at end of file diff --git a/data/database b/data/database index deb206a2094450bd42b51244bedbc63c56925a69..9f731ec05ebf2367b0e6829b3a11632c77f3f50f 100644 GIT binary patch delta 3045 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 diff --git a/data/database-testing b/data/database-testing index 03fbdd269932e47828142e8e539a8d863fc4aa03..cac76370af722e946ed9a2e02fea30f8c1d2a22e 100644 GIT binary patch delta 120750 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 delta 23951 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 { - return db - .select("word") - .from("dictionary") -} diff --git a/data/scripts/deleteMisspelled.mjs b/data/scripts/deleteMisspelled.mjs index b0d958f..6dac7d5 100644 --- a/data/scripts/deleteMisspelled.mjs +++ b/data/scripts/deleteMisspelled.mjs @@ -1,6 +1,6 @@ -import {db, getWords} from './db.mjs' +import { db } from '../../database-calls/db.mjs' import { isMisspelled } from 'spellchecker' - +import { getWords } from '../../database-calls/GETFunctions.mjs' const words = await getWords(db) diff --git a/data/scripts/flagDerivatives.mjs b/data/scripts/flagDerivatives.mjs index f164daa..73ce0e9 100644 --- a/data/scripts/flagDerivatives.mjs +++ b/data/scripts/flagDerivatives.mjs @@ -1,4 +1,6 @@ -import { db, getWords } from './db.mjs' +import { db } from '../../database-calls/db.mjs' +import { getWords } from '../../database-calls/GETFunctions.mjs' + //const words = getWords(db) const allDefinitionsAreFormOf = (meanings) => { diff --git a/data/scripts/flagScientific.mjs b/data/scripts/flagScientific.mjs index 44263ea..6792cfb 100644 --- a/data/scripts/flagScientific.mjs +++ b/data/scripts/flagScientific.mjs @@ -1,4 +1,6 @@ -import { db, getWords } from './db.mjs' +import { db } from '../../database-calls/db.mjs' +import { getWords } from '../../database-calls/GETFunctions.mjs' + const words = await getWords(db) const allDefinitionsAreScientific = (meanings) => { diff --git a/data/scripts/importIPAs.mjs b/data/scripts/importIPAs.mjs index f3572be..f5f8a9d 100644 --- a/data/scripts/importIPAs.mjs +++ b/data/scripts/importIPAs.mjs @@ -1,4 +1,4 @@ -import {db} from './db.mjs' +import { db } from '../../database-calls/db.mjs' import fs from 'fs' const IPAs = JSON.parse(fs.readFileSync('../IPAs_en_UK.json')).en_UK[0] diff --git a/data/scripts/importWiktionaryData.mjs b/data/scripts/importWiktionaryData.mjs index de89ce4..a550892 100644 --- a/data/scripts/importWiktionaryData.mjs +++ b/data/scripts/importWiktionaryData.mjs @@ -1,4 +1,4 @@ -import {db} from './db.mjs' +import { db } from '../../database-calls/db.mjs' import fs from 'fs' const wiktionary = JSON.parse(fs.readFileSync('../processing/wiktionary-p3.json')) diff --git a/database-calls/DELETEFunctions.mjs b/database-calls/DELETEFunctions.mjs new file mode 100644 index 0000000..4a87ce9 --- /dev/null +++ b/database-calls/DELETEFunctions.mjs @@ -0,0 +1,20 @@ +import logger from "../logger.mjs" + +export const deleteFromTable = async (db,table,word) => { + logger.trace(`deleteFromBuffer called for word ${word}!`) + return db(table) + .where('word', word) + .del() +} + + + +export const deleteFromBuffer = async (db,word) => { + logger.trace(`deleteFromBuffer called for word ${word}!`) + return deleteFromTable(db,'buffer',word) + } + +export const deleteFromPublished = async (db,word) => { + logger.trace(`delteFromPublished called for word ${word}`) + return deleteFromTable(db,'published',word) +} \ No newline at end of file diff --git a/database-calls/EXISTSFunctions.mjs b/database-calls/EXISTSFunctions.mjs new file mode 100644 index 0000000..2a1c57f --- /dev/null +++ b/database-calls/EXISTSFunctions.mjs @@ -0,0 +1,26 @@ +import { isoDate } from "../utilities.mjs" +export const valueExistsInColumn = async (db, table, column, value) => { + + const number = await db(table) + .count('* as count') + .where(column, value) + return number[0].count > 0 +} + +export const wordExistsInDictionary = async (db, word) => { + return valueExistsInColumn(db,'dictionary','word',word) +} + +export const todaysPromptAlreadyPublished = async (db) => { + return valueExistsInColumn(db,'published', 'date', isoDate()) +} + +export const wordIsAlreadyInBuffer = async (db, word) => { + return valueExistsInColumn(db,'buffer', 'word', word) +} + +export const tableIsNotEmpty = async (db, table) => { + const number = await db(table) + .count('* as count') + return number[0].count > 0 +} \ No newline at end of file diff --git a/database-calls/GETFunctions.mjs b/database-calls/GETFunctions.mjs new file mode 100644 index 0000000..f7b25ab --- /dev/null +++ b/database-calls/GETFunctions.mjs @@ -0,0 +1,67 @@ +import config from '../config.mjs' +import {blocklist} from './db.mjs' +import logger from "../logger.mjs" +export const getAcceptablePrompts = async (db,word) => { + logger.trace("getAcceptablePrompt called") + return db('dictionary') + .select('*') + .where({ + derivative: 0, + scientific: 0, + }) + .modify(queryBuilder=>{ + if(word){queryBuilder.andWhere('word',word)} + }) + .andWhere('count', '<', config.maxCount) + .andWhere('count', '>', config.minCount) + .andWhere('word', 'not in', blocklist) + .whereRaw('length(word) > 3') + .whereNotNull('pronunciation') + .orderByRaw('count desc') + } + + export const getWords = async (db) => { + logger.trace("getWords called") + return db + .select("word") + .from("dictionary") + .catch(error => { throw error }) + } + + export async function getNewPrompt(db) { + logger.trace("getNewPrompt called") + + const getBiasedRng = (min, max, bias, influence) => { + const random = Math.random() * (max - min) + min + const mix = Math.random() * influence + return random * (1 - mix) + bias * mix + } + + const randomEntry = (array) => { + const random = getBiasedRng(0, 1, config.rarityBias, 1) + const mix = Math.random() + return array[ + parseInt( + array.length * random + ) + ] + } + + return randomEntry(await getAcceptablePrompts(db)) +} + +export const getPromptFromBuffer = async (db) => { + logger.trace("getting prompt from buffer") + const oldestWordInBuffer = await db('buffer').select('word').orderBy('timestamp', 'asc').limit(1) + const word = oldestWordInBuffer[0].word + if(!word){throw new Error("Requested oldest word in buffer but got an empty array! Is buffer empty?")} + const prompt = await getAcceptablePrompts(word) + if(prompt.length===0){throw new Error("Prompt from buffer is not acceptable! Has it already been published? Have the acceptability criteria changed?")} + return prompt[0] +} + +export const getDatePublished = async (db,word) => { + return db('published') + .select('date') + .where('word',word) +} \ No newline at end of file diff --git a/database-calls/INSERTFunctions.mjs b/database-calls/INSERTFunctions.mjs new file mode 100644 index 0000000..595a703 --- /dev/null +++ b/database-calls/INSERTFunctions.mjs @@ -0,0 +1,21 @@ +import { isoDate } from "../utilities.mjs" +import logger from "../logger.mjs" +import { sampleRes } from "./db.mjs" + +export async function insertPublished(db, res, word) { + logger.trace("insertPublished called") + return db('published') + .insert({ + id: res.createdNote.id, + word, + date: isoDate(sampleRes.createdNote.createdAt) + }) +} + +export const insertIntoBuffer = async (db,word,timestamp) => { + return db('buffer') + .insert({ + word:word, + timestamp:timestamp + }) +} \ No newline at end of file diff --git a/database-calls/db.mjs b/database-calls/db.mjs index 175285a..7f530a6 100644 --- a/database-calls/db.mjs +++ b/database-calls/db.mjs @@ -1,108 +1,87 @@ import Knex from 'knex' -import logger from '../logger.mjs' -import { isoDate } from "../utilities.mjs" -import config from "../config.mjs" + export const db = Knex({ client: 'sqlite3', // or 'better-sqlite3' connection: { - //filename: "data/database" + filename: "data/database" + }, + useNullAsDefault: true +}) + +export const testDb = Knex({ + client: 'sqlite3', // or 'better-sqlite3' + connection: { filename: "data/database-testing" }, useNullAsDefault: true }) +export const sampleRes = { + createdNote: { + id: '9i8urek4jtzhmtuh', + createdAt: '2023-08-10T15:02:35.380Z', + userId: '9i5z5o9zy11l3skl', + user: { + id: '9i5z5o9zy11l3skl', + name: null, + username: 'micro365', + host: null, + avatarUrl: 'https://localhost:3000/files/thumbnail-4e0e8b82-df72-48f7-8100-b7515173da9d', + avatarBlurhash: 'ySPjGct7xu%M-;xu-;%MRjWBoffQofWB~qRjRjayRjfQM{M{t7ofWBt7ayfQ~qj[WBj[M{WBof?bofayfQM{WBfQt7xuofWBofofM{', + avatarColor: null, + isLocked: false, + speakAsCat: true, + emojis: [], + onlineStatus: 'active', + driveCapacityOverrideMb: null + }, + text: "Today's #micro365 prompt is:\n" + + '# $[x2 $[font.serif **marmalade**]]\n' + + '/mˈɑːmɐlˌe‍ɪd/\n' + + '**noun**:\n' + + '- A kind of jam made with citrus fruit, distinguished by being made slightly bitter by the addition of the peel and by partial caramelisation during manufacture. Most commonly made with Seville oranges, and usually qualified by the name of the fruit when made with other types of fruit.\n' + + '- A kind of jam made with citrus fruit, distinguished by being made slightly bitter by the addition of the peel and by partial caramelisation during manufacture. Most commonly made with Seville oranges, and usually qualified by the name of the fruit when made with other types of fruit. Ellipsis of orange marmalade.\n' + + '- quince jam\n' + + '**verb**:\n' + + '- To spread marmalade on.\n' + + '#writing #microfiction #vss #marmalade', + cw: null, + visibility: 'public', + renoteCount: 0, + repliesCount: 0, + reactions: {}, + reactionEmojis: [], + emojis: [], + tags: ['micro365', 'writing', 'microfiction', 'vss', 'marmalade'], + fileIds: [], + files: [], + replyId: null, + renoteId: null + } +} -const blocklist = db.union([ + +export const blocklist = db.union([ db('bad_words').select('word'), db('medical_dictionary').select('word'), db('published').select('word') ]) -export const getAcceptablePrompts = async (word) => { - logger.trace("getAcceptablePrompt called") - return db('dictionary') - .select('*') - .where({ - derivative: 0, - scientific: 0, - }) - .modify(queryBuilder=>{ - if(word){queryBuilder.andWhere('word',word)} - }) - .andWhere('count', '<', config.maxCount) - .andWhere('count', '>', config.minCount) - .andWhere('word', 'not in', blocklist) - .whereRaw('length(word) > 3') - .whereNotNull('pronunciation') - .orderByRaw('count desc') -} - - -export const getWords = async () => { - logger.trace("getWords called") - return db - .select("word") - .from("dictionary") - .catch(error => { throw error }) -} - -export const insertIntoBuffer = async (word,timestamp) => { - return db('buffer') - .insert({ - word:word, - timestamp:timestamp - }) -} -export const valueExistsInColumn = async (table, column, value) => { - - const number = await db(table) - .count('* as count') - .where(column, value) - return number[0].count > 0 -} - -export const wordExistsInDictionary = async (word) => { - return valueExistsInColumn('dictionary','word',word) -} - -export const todaysPromptAlreadyPublished = async () => { - return valueExistsInColumn('published', 'date', isoDate()) -} - -export const wordIsAlreadyInBuffer = async (word) => { - return valueExistsInColumn('buffer', 'word', word) -} - -export const tableIsNotEmpty = async (table) => { - const number = await db(table) - .count('* as count') - return number[0].count > 0 -} - -export const getPromptFromBuffer = async () => { - logger.trace("getting prompt from buffer") - const oldestWordInBuffer = await db('buffer').select('word').orderBy('timestamp', 'asc').limit(1) - const word = oldestWordInBuffer[0].word - if(!word){throw new Error("Requested oldest word in buffer but got an empty array! Is buffer empty?")} - const prompt = await getAcceptablePrompts(word) - if(prompt.length===0){throw new Error("Prompt from buffer is not acceptable! Has it already been published? Have the acceptability criteria changed?")} - return prompt[0] -} - -export const deleteFromBuffer = async (word) => { - logger.trace(`deleteFromBuffer called for word ${word}!`) - return db('buffer') - .where('word', word) - .del() -} -export const getDatePublished = async (word) => { - return db('published') - .select('date') - .where('word',word) -} + + + + + + + + + + + + diff --git a/database-calls/getNewPrompt.mjs b/database-calls/getNewPrompt.mjs deleted file mode 100644 index f020ef5..0000000 --- a/database-calls/getNewPrompt.mjs +++ /dev/null @@ -1,31 +0,0 @@ -import logger from "../logger.mjs" -import { getAcceptablePrompts } from "./db.mjs" -import config from "../config.mjs" - -export default async function getNewPrompt() { - logger.trace("getNewPrompt called") - - const getBiasedRng = (min, max, bias, influence) => { - const random = Math.random() * (max - min) + min - const mix = Math.random() * influence - return random * (1 - mix) + bias * mix - } - - const randomEntry = (array) => { - const random = getBiasedRng(0, 1, config.rarityBias, 1) - const mix = Math.random() - return array[ - parseInt( - array.length * random - ) - ] - } - - return randomEntry(await getAcceptablePrompts()) -} - - - - - - diff --git a/database-calls/insertPublished.mjs b/database-calls/insertPublished.mjs deleted file mode 100644 index 7317067..0000000 --- a/database-calls/insertPublished.mjs +++ /dev/null @@ -1,57 +0,0 @@ -import { db } from "./db.mjs" -import { isoDate } from "../utilities.mjs" -import logger from "../logger.mjs" -const sampleRes = { - createdNote: { - id: '9i8urek4jtzhmtuh', - createdAt: '2023-08-10T15:02:35.380Z', - userId: '9i5z5o9zy11l3skl', - user: { - id: '9i5z5o9zy11l3skl', - name: null, - username: 'micro365', - host: null, - avatarUrl: 'https://localhost:3000/files/thumbnail-4e0e8b82-df72-48f7-8100-b7515173da9d', - avatarBlurhash: 'ySPjGct7xu%M-;xu-;%MRjWBoffQofWB~qRjRjayRjfQM{M{t7ofWBt7ayfQ~qj[WBj[M{WBof?bofayfQM{WBfQt7xuofWBofofM{', - avatarColor: null, - isLocked: false, - speakAsCat: true, - emojis: [], - onlineStatus: 'active', - driveCapacityOverrideMb: null - }, - text: "Today's #micro365 prompt is:\n" + - '# $[x2 $[font.serif **marmalade**]]\n' + - '/mˈɑːmɐlˌe‍ɪd/\n' + - '**noun**:\n' + - '- A kind of jam made with citrus fruit, distinguished by being made slightly bitter by the addition of the peel and by partial caramelisation during manufacture. Most commonly made with Seville oranges, and usually qualified by the name of the fruit when made with other types of fruit.\n' + - '- A kind of jam made with citrus fruit, distinguished by being made slightly bitter by the addition of the peel and by partial caramelisation during manufacture. Most commonly made with Seville oranges, and usually qualified by the name of the fruit when made with other types of fruit. Ellipsis of orange marmalade.\n' + - '- quince jam\n' + - '**verb**:\n' + - '- To spread marmalade on.\n' + - '#writing #microfiction #vss #marmalade', - cw: null, - visibility: 'public', - renoteCount: 0, - repliesCount: 0, - reactions: {}, - reactionEmojis: [], - emojis: [], - tags: ['micro365', 'writing', 'microfiction', 'vss', 'marmalade'], - fileIds: [], - files: [], - replyId: null, - renoteId: null - } -} - -export default async function insertPublished(res, word) { - logger.trace("insertPublished called") - return db('published') - .insert({ - id: res.createdNote.id, - word, - date: isoDate(sampleRes.createdNote.createdAt) - }) -} -//console.log(await insertPublished(sampleRes,'marmalade')) \ No newline at end of file diff --git a/index.mjs b/index.mjs index a71cd96..d2854c2 100644 --- a/index.mjs +++ b/index.mjs @@ -4,6 +4,7 @@ import logger from "./logger.mjs"; import pinoHTTP from 'pino-http' import start from "./start.mjs"; import handleMention from "./social-interaction/handleMention.mjs"; +import { db } from "./database-calls/db.mjs"; const app = express() const port = 4000 app.use(bodyParser.json()) @@ -15,7 +16,7 @@ app.use( app.post('/api', async (req,res) => { logger.info({body:req.body.body},"webhook received!") res.sendStatus(200) - const result = await handleMention(req.body.body) + const result = await handleMention(db,req.body.body) logger.info(`handleMention returned ${result.code}`) }) @@ -39,4 +40,4 @@ process.on('uncaughtException', (err) => { process.exit(1); }); -start() \ No newline at end of file +start(db) \ No newline at end of file diff --git a/logger.mjs b/logger.mjs index 3c1b596..274931c 100644 --- a/logger.mjs +++ b/logger.mjs @@ -16,7 +16,7 @@ const __dirname = path.dirname(__filename); // }) export default pino( { - level: 'trace', + level: 'error', formatters: { level: (label) => { return { level: label.toUpperCase() }; diff --git a/social-interaction/Note.mjs b/social-interaction/Note.mjs index 50c1779..2968efc 100644 --- a/social-interaction/Note.mjs +++ b/social-interaction/Note.mjs @@ -1,5 +1,5 @@ import logger from "../logger.mjs" -import { wordExistsInDictionary } from "../database-calls/db.mjs" +import { wordExistsInDictionary } from "../database-calls/EXISTSFunctions.mjs" const sampleNote = { "id": "9id213fllx9y189f", "createdAt": "2023-08-13T13:37:09.537Z", @@ -78,9 +78,10 @@ const sampleNote = { } export default class { - constructor(raw){ + constructor(db,raw){ this.raw = raw logger.trace({id:raw.id},"new note constructed!") + this.db = db } #handle = /@[a-z,A-Z,0-9]* /g @@ -106,7 +107,7 @@ get isSingleWord() { } get isRealWord(){ - return wordExistsInDictionary(this.cleanText) + return wordExistsInDictionary(this.db,this.cleanText) } get author(){ diff --git a/social-interaction/handleMention.mjs b/social-interaction/handleMention.mjs index c699963..65a7e84 100644 --- a/social-interaction/handleMention.mjs +++ b/social-interaction/handleMention.mjs @@ -2,10 +2,12 @@ import logger from "../logger.mjs" import { timestamp } from "../utilities.mjs" import Note from "./Note.mjs" import createNote from "../firefish-calls/createNote.mjs" -import { getDatePublished, wordIsAlreadyInBuffer, getAcceptablePrompts, valueExistsInColumn, insertIntoBuffer } from "../database-calls/db.mjs" - -export default async function handleMentions(body) { - const note = new Note(body.note) +import { insertIntoBuffer } from "../database-calls/INSERTFunctions.mjs" +import { getDatePublished } from "../database-calls/GETFunctions.mjs" +import { valueExistsInColumn, wordIsAlreadyInBuffer } from "../database-calls/EXISTSFunctions.mjs" +import { getAcceptablePrompts } from "../database-calls/GETFunctions.mjs" +export default async function handleMentions(db,body) { + const note = new Note(db,body.note) if(!note.hasCW){ createNote("Please put your prompt suggestions behind a CW. No spoilers!") return {code: "NOCW"} @@ -15,7 +17,7 @@ export default async function handleMentions(body) { return { code: "NOTONEWORD" } } const word = note.cleanText - if (await valueExistsInColumn('bad_words', 'word', word)) { + if (await valueExistsInColumn(db, 'bad_words', 'word', word)) { createNote("That word is on my blocklist.",note.id) return { code: "BLOCKLIST" } } @@ -24,20 +26,20 @@ export default async function handleMentions(body) { createNote(`I'm afraid I can't do that, ${note.author}. That's not a 'real' word, at least as far as I'm aware! Have you checked the spelling?`,note.id) return { code: "NOTREAL" } } - if (await wordIsAlreadyInBuffer(word)) { + if (await wordIsAlreadyInBuffer(db,word)) { createNote(`Believe it or not, somebody has already suggested that! Watch this space!`,note.id) return { code: "INBUFFER" } } - let unacceptable = await getAcceptablePrompts(word) + let unacceptable = await getAcceptablePrompts(db,word) unacceptable = unacceptable.length===0 if (unacceptable) { - if (await valueExistsInColumn('medical_dictionary', 'word', word)) { + if (await valueExistsInColumn(db,'medical_dictionary', 'word', word)) { createNote("I'm afraid I can't use any word that appears in my medical dictionary. I know this delivers some false positives, but it was the only way.",note.id) return { code: "MEDICAL" } } - if(await valueExistsInColumn('published','word',word)){ - let datePublished = await getDatePublished(word) + if(await valueExistsInColumn(db,'published','word',word)){ + let datePublished = await getDatePublished(db,word) datePublished = datePublished[0].date createNote(`I already used that prompt on ${datePublished}, actually!`,note.id) return {code: "PUBLISHED"} @@ -45,7 +47,7 @@ export default async function handleMentions(body) { createNote(`I'm afraid I can't do that, ${note.author}. The word you've suggested is either too quirky or not quirky enough. Them's the breaks.`,note.id) return { code: "RARITY" } } else { - await insertIntoBuffer(word,timestamp()) + await insertIntoBuffer(db,word,timestamp()) await createNote(`OK!`,note.id) return { code: "OK" } } diff --git a/start.mjs b/start.mjs index 8c6a3ed..00142f0 100644 --- a/start.mjs +++ b/start.mjs @@ -2,11 +2,11 @@ import cron from 'node-cron' import logger from './logger.mjs'; import checkAndPublish from './checkAndPublish.mjs'; -export default function start(){ +export default function start(db){ logger.trace("start() called") - checkAndPublish() + checkAndPublish(db) cron.schedule('* * * * *', () => { - checkAndPublish() + checkAndPublish(db) logger.trace('one-minute cron call'); }); } \ No newline at end of file diff --git a/test/Note.test.mjs b/test/Note.test.mjs index b842b67..7070389 100644 --- a/test/Note.test.mjs +++ b/test/Note.test.mjs @@ -1,4 +1,5 @@ import Note from "../social-interaction/Note.mjs"; +import { testDb as db } from "../database-calls/db.mjs"; import { expect } from "chai"; const sampleNote = { "id": "9id213fllx9y189f", @@ -76,7 +77,7 @@ const sampleNote = { "renoteId": null } } -const N1 = new Note(sampleNote) +const N1 = new Note(db,sampleNote) describe("Testing Note getters", function () { it("1. .text returns a string", function (done) { expect(N1.text).to.be.a("string") diff --git a/test/handleMentions.test.mjs b/test/handleMentions.test.mjs index dc36e56..fb26c75 100644 --- a/test/handleMentions.test.mjs +++ b/test/handleMentions.test.mjs @@ -1,5 +1,10 @@ import handleMentions from "../social-interaction/handleMention.mjs"; +import { testDb as db } from "../database-calls/db.mjs"; import { expect } from "chai"; +import {insertPublished, insertIntoBuffer }from "../database-calls/INSERTFunctions.mjs"; +import { sampleRes } from "../database-calls/db.mjs"; +import { deleteFromPublished, deleteFromBuffer } from "../database-calls/DELETEFunctions.mjs"; +import { timestamp } from "../utilities.mjs"; const sampleBody = { note: { "id": "9id213fllx9y189f", @@ -84,62 +89,70 @@ describe("Testing handleMentions responses", async function(){ it("1. handleMentions() returns code MEDICAL when text = '@micro365 hysterectomy'", async function(){ sampleBody.note.text = "@micro365 hysterectomy" - const result = await handleMentions(sampleBody) + const result = await handleMentions(db,sampleBody) expect(result.code).to.equal("MEDICAL") //done() }) it("2. handleMentions() returns code BLOCKLIST when text = '@micro365 knockers'", async function(){ sampleBody.note.text = "@micro365 knockers" - const result = await handleMentions(sampleBody) + const result = await handleMentions(db,sampleBody) expect(result.code).to.equal("BLOCKLIST") //done() }) it("3. handleMentions() returns code RARITY when text = '@micro365 the'", async function(){ sampleBody.note.text = "@micro365 the" - const result = await handleMentions(sampleBody) + const result = await handleMentions(db,sampleBody) expect(result.code).to.equal("RARITY") //done() }) it("4. handleMentions() returns code INBUFFER when text = '@micro365 incapacity'", async function(){ sampleBody.note.text = "@micro365 incapacity" - const result = await handleMentions(sampleBody) + await deleteFromBuffer(db,'incapacity') + await insertIntoBuffer(db, 'incapacity',timestamp()) + const result = await handleMentions(db,sampleBody) + await deleteFromBuffer(db,'incapacity') expect(result.code).to.equal("INBUFFER") //done() }) it("5. handleMentions() returns code NOTREAL when text = '@micro365 embiggensly'", async function(){ sampleBody.note.text = "@micro365 embiggensly" - const result = await handleMentions(sampleBody) + const result = await handleMentions(db,sampleBody) expect(result.code).to.equal("NOTREAL") //done() }) it("5.1 handleMentions() returns code NOTREAL when text = '@micro365 uydwgqi'", async function(){ sampleBody.note.text = "@micro365 uydwgqi" - const result = await handleMentions(sampleBody) + const result = await handleMentions(db,sampleBody) expect(result.code).to.equal("NOTREAL") //done() }) it("6. handleMentions() returns code NOTONEWORD when text = '@micro365 apple banana'", async function(){ sampleBody.note.text = "@micro365 apple apple" - const result = await handleMentions(sampleBody) + const result = await handleMentions(db,sampleBody) expect(result.code).to.equal("NOTONEWORD") //done() }) it("7. handleMentions() returns code OK when text = '@micro365 howler'", async function(){ sampleBody.note.text = "@micro365 howler" - const result = await handleMentions(sampleBody) + + const result = await handleMentions(db,sampleBody) + expect(result.code).to.equal("OK") //done() }) it("8. handleMentions() returns code PUBLISHED when text = '@micro365 nudism'", async function(){ sampleBody.note.text = "@micro365 nudism" - const result = await handleMentions(sampleBody) + await deleteFromPublished(db,'nudism') + await insertPublished(db,sampleRes,'nudism') + const result = await handleMentions(db,sampleBody) + await deleteFromPublished(db,'nudism') expect(result.code).to.equal("PUBLISHED") //done() }) it("9. handleMentions() returns code NOCW when cw = ''", async function(){ sampleBody.note.cw = "" - const result = await handleMentions(sampleBody) + const result = await handleMentions(db,sampleBody) expect(result.code).to.equal("NOCW") //done() })