/ support / ebsSupport / model.mjs
model.mjs
  1  import { $ } from "bun"
  2  import { Database } from "bun:sqlite"
  3  import * as fs from "node:fs/promises"
  4  
  5  // Production Queries
  6  const allQuestions = `select * from questions where channel_id != 157284360;`
  7  ,     allPurchases = `select * from purchases where channel_id != 157284360;`
  8  ,       allConfigs = `select * from configs   where channel_id != 157284360;`
  9  ,      allSessions = `select * from sessions  where channel_id != 157284360 order by open desc;`
 10  
 11  export function ProductionDB () {
 12    let productionDB = new Database("askebs.sql")
 13    
 14    const allQueries = new Map([
 15      ["configs", allConfigs],
 16      ["sessions", allSessions],
 17      ["purchases", allPurchases],
 18      ["questions", allQuestions],
 19    ])
 20  
 21    return {
 22      async getLatest() {
 23        productionDB.close()
 24        await fs.rm(    "askebs.sql", { force: true })
 25        await fs.rm("askebs.sql-wal", { force: true })
 26        await fs.rm("askebs.sql-shm", { force: true })
 27        const { stdout } =  await $`litestream restore "${process.env.LITESTREAM_PATH}"`
 28        productionDB = new Database("askebs.sql")
 29      },
 30      getAll(table) {
 31       const prepared = productionDB.query(allQueries.get(table))
 32       ,         data = prepared.all()  
 33  
 34        return data
 35      }
 36    }
 37  }
 38  
 39  // Support Queries
 40  const getVersion = `select version from support_version where id = 1;`
 41  ,     setVersion = `update support_version set version = $version where id = 1;`
 42  
 43  const makeLeadsTable = `\
 44  create table if not exists leads (
 45    channelId integer primary key,
 46    userName varchar(25),
 47    name text,
 48    content text,
 49    followers integer,
 50    averageViewers real,
 51    averageSampleLength real,
 52    averageBitsPerSample real,
 53    averageQuestionsPerMinute real,
 54    averageMessagesPerMinute real,
 55    averageChattersPerMinute real,
 56    email text,
 57    socials text,
 58    status integer
 59  );`
 60  
 61  const makeSamplesTable = `\
 62  create table if not exists samples (
 63    sampleId integer primary key,
 64    channelId integer,
 65    userName varchar(25),
 66    topic text,
 67    title text,
 68    duration integer,
 69    bits integer,
 70    messages integer,
 71    questions integer,
 72    chatters integer,
 73    averageViewers real
 74  );`
 75  
 76  const makeVODTable = `\
 77  create table if not exists vods (
 78    sessionId text primary key,
 79    userName varchar(25),
 80    vodLink text
 81  );
 82  `
 83  const getAllVODs = `select * from vods;`
 84  const insertVOD = `insert into vods values ($sessionId, $userName, $vodLink)`
 85  
 86  const updateLeadField = (field) => `update leads set ${field} = $value where channelId = $channelId;`
 87  
 88  const addStartColumnToSampleTable = `alter table samples add column start text;`
 89  
 90  const insertSample = `\
 91  insert into samples (channelId, userName, topic, title, duration, bits, messages, questions, chatters, averageViewers, start)
 92  values ($channelId, $userName, $topic, $title, $duration, $bits, $messages, $questions, $chatters, $averageViewers, $start);`
 93  
 94  const addWeekdayColumnToLeadTable = `alter table leads add column weekdays text;`
 95  const addActiveViewerPercentageToLeadTable = `alter table leads add column activeViewerPercentage real;`
 96  
 97  const insertLead = `\
 98  insert into leads
 99  values ($channelId, $userName, $name, $content, $followers,
100          $averageViewers, $averageSampleLength, $averageBitsPerSample,
101          $averageQuestionsPerMinute, $averageMessagesPerMinute, $averageChattersPerMinute,
102          $email, $socials, $status, $weekdays, $activeViewerPercentage);`
103  
104  const getAllSamplesForChannel = `select * from samples where userName = $userName;`
105  const getAllChannelsInLeads =  `select userName from leads;`
106  
107  export function SupportDB (path) {
108    const supportDB = new Database(path)
109  
110    const SupportVersionUpgrades = [
111      // v1 -> v2
112      (supportDB) => {
113        supportDB.query(makeLeadsTable).run()
114        supportDB.query(makeSamplesTable).run()
115        supportDB.query(setVersion).run({ $version: 2 })
116      },
117      // v2 -> v3
118      (supportDB) => {
119        supportDB.query(makeVODTable).run()
120        supportDB.query(setVersion).run({ $version: 3 })
121      },
122      // v3 -> v4
123      (supportDB) => {
124        supportDB.query(addStartColumnToSampleTable).run()
125        supportDB.query(setVersion).run({ $version: 4 })
126      },
127      // v4 -> v5
128      (supportDB) => {
129        supportDB.query(addWeekdayColumnToLeadTable).run()
130        supportDB.query(setVersion).run({ $version: 5 })
131      },
132      // v5 -> v6
133      (supportDB) => {
134        supportDB.query(addActiveViewerPercentageToLeadTable).run()
135        supportDB.query(setVersion).run({ $version: 6 })
136      },
137    ]
138  
139    const mutableLeadFields = new Set(["name", "content", "followers", "email", "status"])
140    
141    return {
142      getUserPasswordHash(user) {
143        const query = supportDB.query(`select password from users where username = $username;`)
144        return query.get({ $username: user })
145      },
146      upgradeIfNeeded() {
147        const versionQuery = supportDB.query(getVersion)
148        let { version } = versionQuery.get()
149  
150        for (let v = version-1; v < SupportVersionUpgrades.length; v++) {
151          SupportVersionUpgrades[v](supportDB)
152        }
153      },
154      getVersion() {
155        const versionQuery = supportDB.query(getVersion)
156        let { version } = versionQuery.get()
157  
158        return version
159      },
160      addSample(sample) {
161        const preparedSample = {
162          $channelId: sample.channelId,
163          $userName: sample.userName,
164          $topic: sample.topic,
165          $title: sample.title,
166          $duration: sample.duration,
167          $bits: sample.bits,
168          $messages: sample.messages,
169          $questions: sample.questions,
170          $chatters: sample.chatters,
171          $averageViewers: sample.averageViewers,
172          $start: sample.start,
173        }
174  
175        const sampleQuery = supportDB.query(insertSample)
176        sampleQuery.run(preparedSample)
177      },
178      addLead(lead) {
179        console.log(lead)
180        try {
181          const query = supportDB.query(insertLead)
182          query.run(lead)
183        } catch(e) {
184          console.log(e)
185        }
186      },
187      getAllLeads() {
188        const query = supportDB.query(`select * from leads;`)
189        return query.all() 
190      },
191      getSamples() {
192        const samplesQuery = supportDB.query(`select * from samples;`)
193        return samplesQuery.all()
194      },
195      getAllContentCategories() {
196        const contentQuery = supportDB.query(`select distinct content from leads;`)
197        return contentQuery.all().map(r => r.content)
198      },
199      updateLeadField(channelId, field, value) {
200        if (mutableLeadFields.has(field)) {
201          const fieldQuery = supportDB.query(updateLeadField(field))
202          fieldQuery.run({ $channelId: channelId, $value: value })
203        }
204      },
205      getVODs() { return supportDB.query(getAllVODs).all() },
206      addVOD({sessionId, userName, vodLink}) {
207        const insertVODQuery = supportDB.query(insertVOD)
208        return insertVODQuery.run({
209          $sessionId: sessionId,
210          $userName: userName,
211          $vodLink: vodLink,
212        })
213      },
214      getAllSamplesByChannel(userName) {
215        const query = supportDB.query(getAllSamplesForChannel)
216        return query.all({ $userName: userName })
217      },
218      getAllLeadChannels() {
219        const query = supportDB.query(getAllChannelsInLeads)
220        return query.all().map(r => r.userName)
221      }
222    }
223  }