Skip to content

Commit

Permalink
Merge pull request #49 from hspsh/libre-alternatives
Browse files Browse the repository at this point in the history
Add a plugin which rewrites Twitter links to nitter.net links
  • Loading branch information
LiquidLemon authored May 18, 2022
2 parents cca7176 + 25638cf commit 894abf5
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 4 deletions.
10 changes: 10 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,14 @@ module.exports = {
'plugins': [
'@typescript-eslint'
],
'rules': {
'@typescript-eslint/no-unused-vars': [
'warn',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
},
],
}
};
85 changes: 85 additions & 0 deletions lib/plugins/libreLinks/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { Message } from 'discord.js'
import { MessageHandler, Plugin } from '../pluginManager'

// https://stackoverflow.com/a/3809435/18140793
const URL_REGEX =
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/g

const getUrls = (str: string): string[] => {
const matches = Array.from(str.matchAll(URL_REGEX))
const urls = matches.map((x) => x[0])
return urls
}

const isUnsignedInt = (num: string): boolean => {
for (const char of num) {
if (!(char >= '0' && char <= '9')) {
return false
}
}

return true
}

const getNitterLink = (link: string): string | undefined => {
const url = new URL(link)

if (url.host != 'twitter.com') {
return
}

const [_, ...pathSegments] = url.pathname.split('/')
const isProfile = pathSegments.length == 1
const isStatus =
pathSegments.length == 3 &&
pathSegments[1] == 'status' &&
isUnsignedInt(pathSegments[2])

if (!isProfile && !isStatus) {
return
}

url.search = ''
url.host = 'nitter.net'
url.protocol = 'https'

return url.toString()
}

const replaceUrls = (urls: string[]): string[] => {
const replaced: string[] = []

urls.forEach((url) => {
const transformed = getNitterLink(url)
if (transformed !== undefined) {
replaced.push(transformed)
}
})

return replaced
}

const messageHandlers: MessageHandler[] = [
{
predicate: async (_: Message) => true,
action: async (msg: Message): Promise<void> => {
const urls = getUrls(msg.content)
const replaced = replaceUrls(urls)

if (replaced.length == 0) {
return
}

const response = replaced.join('\n')
await msg.channel.send(response)
},
},
]

const LibreLinksPlugin: Plugin = {
name: 'libre-links',
messageHandlers,
commands: [],
}

export default LibreLinksPlugin
12 changes: 9 additions & 3 deletions lib/plugins/pluginManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import config from '../config'

import whoisPlugin from './whois/plugin'
import { JudgementPluginFactory } from './rel/plugin'
import LibreLinksPlugin from './libreLinks/plugin'

export type Command = {
name: string
description: string
handle: (interaction: CommandInteraction) => Promise<void>
}

// TODO(LiquidLemon): replace with simple middleware to prevent work duplication
export type MessageHandler = {
predicate: (message: Message) => Promise<boolean>
action: (message: Message) => Promise<void>
Expand Down Expand Up @@ -87,12 +89,17 @@ export default class PluginManager {
}

public async handleMessage(interaction: Message): Promise<void> {
if (interaction.author.id == interaction.client.user?.id) {
return
}

const logContext = {
messageContent: interaction.content,
user: `${interaction.author.username}#${interaction.author.discriminator}`,
userId: interaction.author.id,
}

// TODO(LiquidLemon): simplify this monstrosity
const messageHandler = (
await Promise.all(
this.plugins
Expand All @@ -111,10 +118,8 @@ export default class PluginManager {
return
}

logger.info('Handling message.', logContext)

try {
logger.info('Handling message.', logContext)
logger.debug('Handling message.', logContext)
await messageHandler(interaction)
} catch (error) {
logger.error(
Expand All @@ -131,6 +136,7 @@ export default class PluginManager {
await JudgementPluginFactory.createPlugin(
config.env.REL_DB_PATH || './sqlite.db'
),
LibreLinksPlugin,
])
}
}
7 changes: 6 additions & 1 deletion lib/plugins/whois/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { CommandInteraction, GuildMember, Message, TextChannel } from 'discord.js'
import {
CommandInteraction,
GuildMember,
Message,
TextChannel,
} from 'discord.js'

import { Plugin, Command, MessageHandler } from '../pluginManager'
import api from './api'
Expand Down

0 comments on commit 894abf5

Please sign in to comment.