Giter VIP home page Giter VIP logo

trojanerbot's People

Contributors

dependabot[bot] avatar networkexception avatar trojanerhd avatar

Watchers

 avatar  avatar

trojanerbot's Issues

Send live message when streamer is live while subscribing

Currently, only if the streamer had no subscriptions before (meaning, they don't exist in the settings.json), a message gets sent when subscribing while the streamer is live. This should be changed to always send a message when subscribing to somebody who is live right now

Enable more than 100 streams to be fetched

Currently, thanks to the Twitch API, only the first 20 streamers are returned in every request. This can be changed to 100 by specifying a first field. If there are more than 100, the remaining streamers have to be obtained by separate requests with an after field in the request using so-called pagnation

Send embed in command reply

Currently, the bot - for whatever reason - sends the response See embed and a separate embed message. This can be improved to only send the embed in the response

Unexpected token c in JSON at position 0

Randomly occurs after some time when starting the bot (in this case it took a few hours/days)

Probably some error handling is required in general

FetchError: invalid json response body at https://api.twitch.tv/helix/streams?user_login=<username>&user_login=<other username>&… reason: Unexpected token c in JSON at position 0
    at /home/trojaner/Code/Web/TrojanerBot/node_modules/node-fetch/lib/index.js:272:32
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:93:5) {
  type: 'invalid-json'
}

/home/trojaner/Code/Web/TrojanerBot/node_modules/node-fetch/lib/index.js:272
                                return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json'));
                                                           ^
FetchError: invalid json response body at https://api.twitch.tv/helix/games? reason: Unexpected token c in JSON at position 0
    at /home/trojaner/Code/Web/TrojanerBot/node_modules/node-fetch/lib/index.js:272:32
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:93:5) {
  type: 'invalid-json'
}

Improve quote links

Features:

  • Opt-out entirely
    • Disable as server maintainer
    • Disable as user (if not disabled on server)
  • The user should be able to remove the quote reply
  • Add support for images
    • Keep in mind that it's also possible to send multiple images in one message

Change .find() to .some() wherever applicable

When I started writing this bot, I didn't know that Array.prototype.some() exists and used a workaround:

const found: T | undefined = array.find((elem: T): boolean => elem === something);
if (!found) console.log(false);
else console.log(true);

this can be changed to

const found: boolean = array.some((elem: T): boolean => elem === something);
console.log(found);

(In this case even to console.log(array.some((elem: T): boolean => elem === something));)

Slash command permissions throw error

Discord changed in an update that bot tokens can't change command permissions so now the following steps are required to automatically set permissions:

  1. Make a local redirect server (e. g. using express)
    • Validate redirect server by adding http://localhost:<PORT> to https://discord.com/developers/applications/<CLIENT_ID>/oauth2/general
  2. Let a server admin / owner authenticate via https://discord.com/oauth2/authorize?client_id=<CLIENT_ID>&scope=applications.commands.permissions.update&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A<PORT>
  3. Store Bearer token of authentication
  4. Make PUT request to Discord endpoint /applications/<APPLICATION_ID>/guilds/<GUILD_ID>/commands/<COMMAND_ID>/permissions for each command with payload permissions: {id: string, type: 1 | 2 | 3, permission: boolean}[] (See https://discord.com/developers/docs/interactions/application-commands#edit-application-command-permissions for more information, specifically https://discord.com/developers/docs/interactions/application-commands#application-command-permissions-object-application-command-permissions-structure for permission array)
    • <APPLICATION_ID> can be globally received via DiscordClient._client.application?.id

Only send live notifications if stream has not been restarted

Currently, the bot sends a notification every time the stream has been restarted (after five minutes of being live). It would be appropriate to add a flag last-live or abuse the started-at tag to store the time the streamer was last live. If that time is less than 10 minutes ago e. g. and the streamer goes live again, don't send a message again and instead start maintaining the old live messages again.

/settings command for bot management

Followup to PR #67: If the bot will be used in multiple servers, it would be better if the admins of that server could configure the bot's settings directly through a /settings command instead of the settings being sprayed into multiple / commands as it is in the current implementation of that PR.

Setting would be:

  • Set permitted roles
  • Live channel
    • Set people for the live channel
    • Set the name of the live channel
    • Enable / disable feature altogether
  • Roles channel
    • Add/edit/remove roles
    • Enable / disable feature altogether
  • Talking channel
    • Enable / disable feature altogether
  • Set emotes to use for /to command

Bot randomly crashes

Error: WebSocket was closed before the connection was established
    at WebSocket.close (/home/trojaner/Code/Web/TrojanerBot/node_modules/ws/lib/websocket.j
s:285:14)
    at WebSocketShard.destroy (/home/trojaner/Code/Web/TrojanerBot/node_modules/discord.js/
src/client/websocket/WebSocketShard.js:728:27)
    at Timeout.<anonymous> (/home/trojaner/Code/Web/TrojanerBot/node_modules/discord.js/src
/client/websocket/WebSocketShard.js:522:12)
    at listOnTimeout (node:internal/timers:559:17)
    at processTimers (node:internal/timers:502:7)
Emitted 'error' event on WebSocket instance at: 
    at emitErrorAndClose (/home/trojaner/Code/Web/TrojanerBot/node_modules/ws/lib/websocket
.js:984:13)
    at processTicksAndRejections (node:internal/process/task_queues:83:21)

Possibly bumping the discord.js version might fix that?

Add update information

In the future, the bot should work with GitHub releases and warn the user when it is out of date with instructions to update. The ideal approach for development would be to slowly migrate each update with breaking changes that require migrations - as we see it in the following lines right now, for example:

// If some keys do not exist in the new settings read from file, set these settings back to the already stored value (before the read)
if (
Object.keys(Settings._settings).some(
(key: string): boolean => !(key in newSettings)
)
) {
// Every key that exists in the new settings is being iterated over
for (const untypedSetting of Object.keys(newSettings)) {
// Type the setting key to be a valid key for the SettingsJSON array
const setting: keyof SettingsJSON =
untypedSetting as keyof SettingsJSON;
// Store every found setting from the new settings into the local settings
// @ts-ignore
Settings._settings[setting] = newSettings[setting] as any;
}
changed = true;
}
// Backwards compatibility: This is a hard-coded checker to see if every streamer has a sent boolean because there was a version where it was not there
for (const i of [
...Settings._settings['streamer-subscriptions'].entries(),
]
.filter(
(channelWithIndex: [number, Channel]): boolean =>
channelWithIndex[1].sent === undefined
)
.map(
(channelWithIndex: [number, Channel]): number => channelWithIndex[0]
)) {
Settings._settings['streamer-subscriptions'][i].sent = false;
changed = true;
}
// Backwards compatibility: If users added streamers with invalid characters in previous versions of the bot, they get deleted
if (
Settings._settings['streamer-subscriptions'].some(
(channel: Channel): boolean =>
!channel.streamer.match(DMManager.validNameRegex)
)
) {
Settings._settings['streamer-subscriptions'] = Settings._settings[
'streamer-subscriptions'
].filter(
(channel: Channel): boolean =>
!!channel.streamer.match(DMManager.validNameRegex)
);
changed = true;
}
if (changed) Settings.saveSettings();

When redeploying commands while not having authorized to update command permissions, the bot crashes

Problem

When using /deploy or typing !deploy (with permissions), the error Uncaught Error Error: listen EADDRINUSE: address already in use :::3000 is thrown.

Reason

Because a redeployment creates a new instance of Authentication, a new express app is created that tries to listen to the same port as the previous one

Solution

Make server static and check if it has a value when creating a new Authentication instance. If so, don't listen to the same port again.

Workarounds

  • Restart the bot if it crashes, it won't crash again until you redeploy again
  • Authorize before redeployment

express-port setting keeps reappearing even though it is optional

Problem

Upon deleting the setting express-port in settings.json, the bot automatically overwrites the settings and adds the setting back

Reason

if (
Object.keys(Settings._settings).find(
(key: string): boolean => !(key in newSettings)
)
) {
for (const untypedSetting of Object.keys(newSettings)) {
const setting: keyof SettingsJSON =
untypedSetting as keyof SettingsJSON;
//TODO: Understand what is going on here and document code
//@ts-ignore
Settings._settings[setting] = newSettings[setting] as any;
}
changed = true;
}

This code checks if the new settings do not include a key of the old settings, takes all of the values that the new settings changed but reapplies the old settings

Workaround

Set the express port to a non-positive value (like 0)

Use more embeds

Followup to PR #67: Currently, commands like /roles list display a very raw and ugly output. Change that into embeds

Better permissions

The current permissions rely on hard coded role names (Moderator and Owner).
It would be better for the bot owner to change that (Linked to #4)

Create README

  • General description
    • Use cases
    • Limitations
    • Features
  • Installation instructions
    • .env
  • Deployment & Contribution instructions

Implement a proper logger

While the settings already uses a flag logging for the log level, it is only used for logging initial information about whether the current bot's configuration is valid. However, I also want to use a logger in my code. That means, I want to be able to log anything anywhere under the condition that logging is set to at least level X.

Talking channel creation broken

Expected behavior:
Upon joining the channel “Talking”, a second channel gets generated and so forth.

Actual behavior
Upon joining the channel “Talking”, nothing happens at all.

Internal Server Error

Response: Internal Server Error
    at RequestHandler.execute (/home/trojaner/Code/Web/TrojanerBot/node_modules/discord.js/src/rest/RequestHandler.js:161:15)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:94:5)
    at async RequestHandler.push (/home/trojaner/Code/Web/TrojanerBot/node_modules/discord.js/src/rest/RequestHandler.js:39:14)
    at async MessageManager._fetchMany (/home/trojaner/Code/Web/TrojanerBot/node_modules/discord.js/src/managers/MessageManager.js:140:18) {
  code: 500,
  method: 'get',
  path: '/channels/630883093129199656/messages'
}

and

HTTPError [AbortError]: The user aborted a request.
    at RequestHandler.execute (/home/trojaner/Code/Web/TrojanerBot/node_modules/discord.js/src/rest/RequestHandler.js:93:15)
    at processTicksAndRejections (node:internal/process/task_queues:94:5)
    at async RequestHandler.push (/home/trojaner/Code/Web/TrojanerBot/node_modules/discord.js/src/rest/RequestHandler.js:39:14)
    at async MessageManager._fetchMany (/home/trojaner/Code/Web/TrojanerBot/node_modules/discord.js/src/managers/MessageManager.js:140:18) {
  code: 500,
  method: 'get',
  path: '/channels/630883093129199656/messages'
}

occur sometimes.
Probably messages that are trying to be fetched and are getting deleted in the process(?)

Include yarn.lock in repository

The yarn.lock contains information with what version of the package the code works, hence it's important. Should be added to the repository

Bot randomly crashes

node:events:505
      throw er; // Unhandled 'error' event
      ^

Error: connect ETIMEDOUT XXX.XXX.XXX.XXX:443
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1187:16)
Emitted 'error' event on ClientRequest instance at:
    at TLSSocket.socketErrorListener (node:_http_client:454:9)
    at TLSSocket.emit (node:events:527:28)
    at emitErrorNT (node:internal/streams/destroy:157:8)
    at emitErrorCloseNT (node:internal/streams/destroy:122:3)
    at processTicksAndRejections (node:internal/process/task_queues:83:21) {
  errno: -110,
  code: 'ETIMEDOUT',
  syscall: 'connect',
  address: 'XXX.XXX.XXX.XXX',
  port: 443
}

(IP replaced with XXX.XXX.XXX.XXX)

#live feature broken, removal of feature considered?

The functionality for the #live channel is broken. It displays a wrong refresh time and also doesn't show anything (sometimes?).

On that note, there should be an evaluation of the necessity of having this feature. Maybe just get rid of it?

redirect_uri gets automatically set to the first entry of the application, no need to include it in auth url

console.log(
`Warning: To update the command's permissions, please authenticate the application at https://discord.com/oauth2/authorize?client_id=${DiscordClient._client.application?.id}&scope=applications.commands.permissions.update&response_type=code&redirect_uri=<redirect_uri>`
);

Here, the redirect_uri=<redirect_uri> can be omitted

Get rid of help command

Help command is useless since discord has built-in descriptions and listings of slash commands

Centralize JSON files

Currently you have to create some JSON files scattered across the repository. It would be appropriate to centralize those JSON files e. g. in a folder or by merging them in total to one file

(Linked with #3)

Bot crashes: channel.isText is not a function

/home/trojaner/Code/Web/TrojanerBot/node_modules/discord.js/src/client/actions/InteractionCreate.js:48
        if (channel && !channel.isText()) return;
                                ^

TypeError: channel.isText is not a function
    at InteractionCreateAction.handle (/home/trojaner/Code/Web/TrojanerBot/node_modules/discord.js/src/client/actions/InteractionCreate.js:48:33)
    at Object.module.exports [as INTERACTION_CREATE] (/home/trojaner/Code/Web/TrojanerBot/node_modules/discord.js/src/client/websocket/handlers/INTERACTION_CREATE.js:4:36)
    at WebSocketManager.handlePacket (/home/trojaner/Code/Web/TrojanerBot/node_modules/discord.js/src/client/websocket/WebSocketManager.js:346:31)
    at WebSocketShard.onPacket (/home/trojaner/Code/Web/TrojanerBot/node_modules/discord.js/src/client/websocket/WebSocketShard.js:482:22)
    at WebSocketShard.onMessage (/home/trojaner/Code/Web/TrojanerBot/node_modules/discord.js/src/client/websocket/WebSocketShard.js:317:10)
    at callListener (/home/trojaner/Code/Web/TrojanerBot/node_modules/ws/lib/event-target.js:290:14)
    at WebSocket.onMessage (/home/trojaner/Code/Web/TrojanerBot/node_modules/ws/lib/event-target.js:209:9)
    at WebSocket.emit (node:events:513:28)
    at Receiver.receiverOnMessage (/home/trojaner/Code/Web/TrojanerBot/node_modules/ws/lib/websocket.js:1180:20)
    at Receiver.emit (node:events:513:28)

Configs for each server

Currently, settings.json and .env is for all servers at once, they won't get distinguished. Meaning, you can't show different streamers in different servers for example

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.