aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/commands/core/bridge.js
blob: 89ed2119078d1a5b1770085960b056517e5e1098 (plain)
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
129
130
131
132
133
/*
  Description: Rebroadcasts any `text` to all clients in a `channel` with `nick`
*/

import * as UAC from "../utility/UAC/_info";

// module support functions
const parseText = (text) => {
  // verifies user input is text
  if (typeof text !== "string") {
    return false;
  }

  let sanitizedText = text;

  // strip newlines from beginning and end
  sanitizedText = sanitizedText.replace(/^\s*\n|^\s+$|\n\s*$/g, "");
  // replace 3+ newlines with just 2 newlines
  sanitizedText = sanitizedText.replace(/\n{3,}/g, "\n\n");

  return sanitizedText;
};

// module main
export async function run(core, server, socket, data) {
  // check user input
  const text = parseText(data.text);

  if (!text) {
    // lets not send objects or empty text, yea?
    return server.police.frisk(socket.address, 13);
  }

  // check for spam
  const score = text.length / 83 / 4;
  if (server.police.frisk(socket.address, score)) {
    return server.reply(
      {
        cmd: "warn",
        text:
          "You are sending too much text. Wait a moment and try again.\nPress the up arrow key to restore your last message.",
      },
      socket
    );
  }

  // build chat payload
  const payload = {
    cmd: "chat",
    nick: data.nick,
    text,
    level: socket.level,
  };

  if (UAC.isAdmin(socket.level)) {
    payload.admin = true;
  } else if (UAC.isModerator(socket.level)) {
    payload.mod = true;
  }

  if (socket.trip) {
    payload.trip = socket.trip;
  }

  // broadcast to channel peers
  server.broadcast(payload, {channel: socket.channel});

  // stats are fun
  core.stats.increment("messages-sent");

  return true;
}

// module hook functions
export function initHooks(server) {
  server.registerHook("in", "chat", this.commandCheckIn.bind(this), 20);
  server.registerHook("in", "chat", this.finalCmdCheck.bind(this), 254);
}

// checks for miscellaneous '/' based commands
export function commandCheckIn(core, server, socket, payload) {
  if (typeof payload.text !== "string") {
    return false;
  }

  if (payload.text.startsWith("/myhash")) {
    server.reply(
      {
        cmd: "info",
        text: `Your hash: ${socket.hash}`,
      },
      socket
    );

    return false;
  }

  return payload;
}

export function finalCmdCheck(core, server, socket, payload) {
  if (typeof payload.text !== "string") {
    return false;
  }

  if (!payload.text.startsWith("/")) {
    return payload;
  }

  if (payload.text.startsWith("//")) {
    payload.text = payload.text.substr(1);

    return payload;
  }

  server.reply(
    {
      cmd: "warn",
      text: `Unknown command: ${payload.text}`,
    },
    socket
  );

  return false;
}

export const requiredData = ["text", "nick"];
export const info = {
  name: "chat",
  description: "Broadcasts passed `text` field to the calling users channel using `nick`",
  usage: `
    API: { cmd: 'chat', text: '<text to send>', nick: 'nick'} `,
};