File size: 3,936 Bytes
3b6afc0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
const express = require('express');
const router = express.Router();
const { MeiliSearch } = require('meilisearch');
const { Message } = require('../../models/Message');
const { Conversation, getConvosQueried } = require('../../models/Conversation');
const { reduceHits } = require('../../lib/utils/reduceHits');
const { cleanUpPrimaryKeyValue } = require('../../lib/utils/misc');
const requireJwtAuth = require('../../middleware/requireJwtAuth');

const cache = new Map();

router.get('/sync', async function (req, res) {
  await Message.syncWithMeili();
  await Conversation.syncWithMeili();
  res.send('synced');
});

router.get('/', requireJwtAuth, async function (req, res) {
  try {
    let user = req.user.id;
    user = user ?? null;
    const { q } = req.query;
    const pageNumber = req.query.pageNumber || 1;
    const key = `${user || ''}${q}`;

    if (cache.has(key)) {
      console.log('cache hit', key);
      const cached = cache.get(key);
      const { pages, pageSize, messages } = cached;
      res
        .status(200)
        .send({ conversations: cached[pageNumber], pages, pageNumber, pageSize, messages });
      return;
    } else {
      cache.clear();
    }

    // const message = await Message.meiliSearch(q);
    const messages = (
      await Message.meiliSearch(
        q,
        {
          attributesToHighlight: ['text'],
          highlightPreTag: '**',
          highlightPostTag: '**',
        },
        true,
      )
    ).hits.map((message) => {
      const { _formatted, ...rest } = message;
      return {
        ...rest,
        searchResult: true,
        text: _formatted.text,
      };
    });
    const titles = (await Conversation.meiliSearch(q)).hits;
    const sortedHits = reduceHits(messages, titles);
    // debugging:
    // console.log('user:', user, 'message hits:', messages.length, 'convo hits:', titles.length);
    // console.log('sorted hits:', sortedHits.length);
    const result = await getConvosQueried(user, sortedHits, pageNumber);

    const activeMessages = [];
    for (let i = 0; i < messages.length; i++) {
      let message = messages[i];
      if (message.conversationId.includes('--')) {
        message.conversationId = cleanUpPrimaryKeyValue(message.conversationId);
      }
      if (result.convoMap[message.conversationId] && !message.error) {
        const convo = result.convoMap[message.conversationId];
        const { title, chatGptLabel, model } = convo;
        message = { ...message, ...{ title, chatGptLabel, model } };
        activeMessages.push(message);
      }
    }
    result.messages = activeMessages;
    if (result.cache) {
      result.cache.messages = activeMessages;
      cache.set(key, result.cache);
      delete result.cache;
    }
    delete result.convoMap;
    // for debugging
    // console.log(result, messages.length);
    res.status(200).send(result);
  } catch (error) {
    console.log(error);
    res.status(500).send({ message: 'Error searching' });
  }
});

router.get('/clear', async function (req, res) {
  await Message.resetIndex();
  res.send('cleared');
});

router.get('/test', async function (req, res) {
  const { q } = req.query;
  const messages = (
    await Message.meiliSearch(q, { attributesToHighlight: ['text'] }, true)
  ).hits.map((message) => {
    const { _formatted, ...rest } = message;
    return { ...rest, searchResult: true, text: _formatted.text };
  });
  res.send(messages);
});

router.get('/enable', async function (req, res) {
  let result = false;
  try {
    const client = new MeiliSearch({
      host: process.env.MEILI_HOST,
      apiKey: process.env.MEILI_MASTER_KEY,
    });

    const { status } = await client.health();
    // console.log(`Meilisearch: ${status}`);
    result = status === 'available' && !!process.env.SEARCH;
    return res.send(result);
  } catch (error) {
    // console.error(error);
    return res.send(false);
  }
});

module.exports = router;