initial version
it supports bi-direcitonal text, after manually filling the database :)master
commit
5ae481ccf2
@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
matritch-registration.yaml
|
||||||
|
*.db
|
@ -0,0 +1,117 @@
|
|||||||
|
const mx = require('matrix-appservice-bridge');
|
||||||
|
const tmi = require('tmi.js');
|
||||||
|
|
||||||
|
// has to be defined here because of scope
|
||||||
|
let bridge;
|
||||||
|
let tmiListener;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Matrix part
|
||||||
|
async function matrixEventHandler(request, context) {
|
||||||
|
const event = request.getData();
|
||||||
|
|
||||||
|
if(event.type === 'm.room.message') {
|
||||||
|
const message = event.content.body;
|
||||||
|
const remoteUsers = await bridge.getUserStore().getRemoteUsersFromMatrixId(event.sender);
|
||||||
|
// use the first user, multipe user mappings are unsupported
|
||||||
|
const remoteUser = remoteUsers[0];
|
||||||
|
const tmiUsername = remoteUser.id;
|
||||||
|
const tmiPassword = remoteUser.data.password;
|
||||||
|
|
||||||
|
const remoteRooms = await bridge.getRoomStore().getLinkedRemoteRooms(event.room_id);
|
||||||
|
remoteRooms.forEach(remoteRoom => {
|
||||||
|
const tmiClient = new tmi.Client({
|
||||||
|
connection: {
|
||||||
|
secure: true,
|
||||||
|
},
|
||||||
|
identity: {
|
||||||
|
username: tmiUsername,
|
||||||
|
password: tmiPassword
|
||||||
|
},
|
||||||
|
channels: [
|
||||||
|
remoteRoom.roomId
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// connect to tmi, send message and disconnect
|
||||||
|
tmiClient.connect();
|
||||||
|
tmiClient.on('connected', () => {
|
||||||
|
tmiClient.say(remoteRoom.roomId, message);
|
||||||
|
tmiClient.disconnect();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
new mx.Cli({
|
||||||
|
registrationPath: 'matritch-registration.yaml',
|
||||||
|
generateRegistration: (reg, callback) => {
|
||||||
|
reg.setId(mx.AppServiceRegistration.generateToken());
|
||||||
|
reg.setHomeserverToken(mx.AppServiceRegistration.generateToken());
|
||||||
|
reg.setAppServiceToken(mx.AppServiceRegistration.generateToken());
|
||||||
|
reg.setSenderLocalpart('_matritch');
|
||||||
|
reg.addRegexPattern('users', '@_matritch_.*', true);
|
||||||
|
callback(reg);
|
||||||
|
},
|
||||||
|
run: async (port, config) => {
|
||||||
|
bridge = new mx.Bridge({
|
||||||
|
homeserverUrl: process.env.HOMESEVER || 'http://localhost:8008',
|
||||||
|
domain: process.env.DOMAIN || 'localhost',
|
||||||
|
registration: 'matritch-registration.yaml',
|
||||||
|
controller: {
|
||||||
|
onUserQuery: queriedUser => {
|
||||||
|
// auto-provision users with no additonal data
|
||||||
|
console.log(JSON.stringify(queriedUser))
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
onEvent: matrixEventHandler
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log('Matrix-side listening on port %s', port);
|
||||||
|
|
||||||
|
await bridge.run(port, config);
|
||||||
|
connectTmiListener();
|
||||||
|
}
|
||||||
|
}).run();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Twitch part
|
||||||
|
const localpartPrefix = bridge.opts.registration.namespaces.users[0].regex.slice(0, -2);
|
||||||
|
const domain = bridge.opts.domain;
|
||||||
|
|
||||||
|
|
||||||
|
async function tmiEventHandler(target, context, message, self) {
|
||||||
|
const remoteUsers = await bridge.getUserStore().getRemoteUser(context.username)
|
||||||
|
if(remoteUsers) {
|
||||||
|
// ignore messages from briged users
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const matrixRooms = await bridge.getRoomStore().getLinkedMatrixRooms(target);
|
||||||
|
matrixRooms.forEach(matrixRoom => {
|
||||||
|
const intent = bridge.getIntent(localpartPrefix+context.username+':'+domain);
|
||||||
|
intent.sendText(matrixRoom.roomId, message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
async function connectTmiListener() {
|
||||||
|
const remoteRooms = await bridge.getRoomStore().select({
|
||||||
|
matrix_id: {$exists: true},
|
||||||
|
remote_id: {$exists: true}
|
||||||
|
});
|
||||||
|
const channels = remoteRooms.map(remoteRoom => {
|
||||||
|
return remoteRoom.remote_id;
|
||||||
|
});
|
||||||
|
|
||||||
|
const tmiAnonymousOptions = {
|
||||||
|
connection: {
|
||||||
|
secure: true,
|
||||||
|
reconnect: true
|
||||||
|
},
|
||||||
|
channels: channels
|
||||||
|
};
|
||||||
|
tmiListener = new tmi.Client(tmiAnonymousOptions);
|
||||||
|
tmiListener.on('message', tmiEventHandler);
|
||||||
|
tmiListener.connect();
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "matritch",
|
||||||
|
"version": "0.0",
|
||||||
|
"description": "a matrix-twitch bridge",
|
||||||
|
"main": "index.js",
|
||||||
|
"repository": "https://gitea.lubiland.de/lub/matritch",
|
||||||
|
"author": "lub <git@lubiland.de>",
|
||||||
|
"license": "GPL-3.0-or-later",
|
||||||
|
"dependencies": {
|
||||||
|
"matrix-appservice-bridge": "^1.11.1",
|
||||||
|
"tmi.js": "^1.5.0"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue