Compare commits

..

No commits in common. "master" and "0.0.1" have entirely different histories.

12 changed files with 268 additions and 248 deletions

View file

@ -1,55 +0,0 @@
name: build
on:
push:
branches:
- master
jobs:
release:
runs-on: docker
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Define next tag
uses: https://github.com/paulhatch/semantic-version@v5.0.2
id: version
with:
tag_prefix: ""
major_pattern: "(MAJOR)"
minor_pattern: "(MINOR)"
change_path: .
version_format: "${major}.${minor}.${patch}"
- name: Create tag
run: |
git config --global user.name "${GITHUB_ACTOR}"
git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com"
git tag "${{ steps.version.outputs.version }}" -m "[forgejo-action-tag]"
git push origin --tags
docker:
runs-on: host
needs:
- release
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
registry: git.h2-invent.com
username: ${{ secrets.FORGEJO_ACTION_PACKAGE_RW_USER }}
password: ${{ secrets.FORGEJO_ACTION_PACKAGE_RW_KEY }}
- name: Build and push Image
uses: docker/build-push-action@v6
with:
push: true
tags: git.h2-invent.com/meetling/matrix-bot:${{ needs.release.outputs.version }}

78
.github/workflows/pipeline-release.yml vendored Normal file
View file

@ -0,0 +1,78 @@
name: Create Release
env:
GITHUB_TOKEN: ${{ secrets.token }}
on:
push:
branches:
- main
- master
jobs:
artifact:
uses: h2-invent/jitsi-admin-matrix-bot/.github/workflows/task-artifact.yml@master
create_release:
needs:
- artifact
runs-on: ubuntu-latest
outputs:
create_release_output: ${{ steps.version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: paulhatch/semantic-version@v5.0.2
id: version
with:
tag_prefix: ""
major_pattern: "(MAJOR)"
minor_pattern: "(MINOR)"
change_path: .
version_format: "${major}.${minor}.${patch}"
- uses: actions/download-artifact@v3
with:
name: artifact_${{github.run_number}}
- run: unzip -qq artifact_${{github.run_number}}.zip -d artifact
- name: Archive Release for application
uses: thedoctor0/zip-release@0.7.1
with:
type: 'zip'
filename: 'application.zip'
exclusions: '*.git* *.github*'
directory: artifact
- name: Create new Release with semantic-version tag
uses: ncipollo/release-action@v1
id: create_release
with:
draft: false
prerelease: false
name: Release ${{ steps.version.outputs.version }}
tag: ${{ steps.version.outputs.version }}
artifacts: artifact/application.zip
artifactContentType: application/zip
bodyFile: RELEASE_NOTE.md
upload_dockerhub_main:
needs:
- create_release
uses: h2-invent/jitsi-admin-matrix-bot/.github/workflows/task-upload-docker-hub.yml@master
with:
reponame: 'h2invent/jitsi-admin-matrix-bot'
dockerfile_path: './Dockerfile'
directory: '.'
version: h2invent/jitsi-admin-matrix-bot:latest,h2invent/jitsi-admin-matrix-bot:${{ needs.create_release.outputs.create_release_output }}
secrets:
dockerhub_password: ${{ secrets.DOCKERHUB_TOKEN }}
dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }}

28
.github/workflows/task-artifact.yml vendored Normal file
View file

@ -0,0 +1,28 @@
name: Build Artifacts
on: workflow_call
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install NPM Packages
uses: actions/setup-node@v3
with:
node-version: ${{ vars.NODE_VERSION }}
- name: Install Node modules
run: npm install
- uses: montudor/action-zip@v1
with:
args: zip -qq -r artifact_${{github.run_number}}.zip .
- name: Upload articats
uses: actions/upload-artifact@v3
with:
name: artifact_${{github.run_number}}
path: artifact_${{github.run_number}}.zip

View file

@ -0,0 +1,70 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.
name: Publish Docker image
on:
workflow_call:
inputs:
reponame:
description: 'the image name of the docker hub image'
default: 'h2invent/jitsi-admin-main'
required: true
type: string
directory:
description: 'the dir of the Dockerfile image'
default: '.'
required: true
type: string
dockerfile_path:
description: 'the name of the Dockerfile image'
default: './Dockerfile'
required: true
type: string
version:
description: 'the version/tag of the Dockerfile image'
required: true
type: string
secrets:
dockerhub_username:
required: true
dockerhub_password:
required: true
jobs:
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
steps:
- name: Get current Username
id: date
run: echo "${{ secrets.dockerhub_password }}"
- name: Check out the repo
uses: actions/checkout@v4
- name: Log in to Docker Hub
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
with:
username: ${{ secrets.dockerhub_username }}
password: ${{ secrets.dockerhub_password }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ inputs.reponame }}
- name: Build and push Docker image
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
with:
context: ${{ inputs.directory }}
file: ${{ inputs.dockerfile_path }}
push: true
tags: ${{ inputs.reponame }}:${{ inputs.version }}

142
README.md
View file

@ -1,85 +1,65 @@
# Matrix Meetling Bot ## Matrix Jitsi-admin Bot
Ein Bot zur Verwaltung von **Jitsi-Meetings** über eine **Matrix-Instanz**. Mit diesem Bot lassen sich Jitsi-Sitzungen direkt über Matrix steuern und verwalten - ideal für automatisierte Konferenzen und Raumverwaltung. Dies ist ein Bot, der für die Verwaltung von Jitsi-Meetings über Matrix erstellt wurde. Der Bot ermöglicht die Steuerung und Verwaltung von Meetings über eine Matrix-Instanz.
### Installation
#### Token erstellen
1. Klonen des Repositorys:
```
git clone https://de-h2-git01.h2.home/emanuel.holzmann/matrix-bot.git
```
2. Installation der benötigten Pakete:
```
npm install
```
3. Generieren des Tokens:
Führen Sie den folgenden Befehl aus und ersetzen Sie `username`, `passwort` und `https://matrixdomain.org` durch die entsprechenden Anmeldeinformationen:
```shell
MATRIX_USERNAME=username MATRIX_PASSWORD=passwort MATRIX_URL=https://matrixdomain.org node login.mjs
```
Der generierte Access-Token muss sicher aufbewahrt werden, da er der Schlüssel für den Docker-Container ist.
#### Container starten
1. Erneutes Checkout der Anwendung (optional, wenn bereits geklont):
```
git clone https://de-h2-git01.h2.home/emanuel.holzmann/matrix-bot.git
```
2. Wechseln in das Verzeichnis:
```
cd matrix-bot
```
3. Bauen der Anwendung und Starten des Containers mit `docker-compose`:
Führen Sie den folgenden Befehl aus und ersetzen Sie `tokenKommtHIerHer` durch den generierten Accesstoken aus Schritt 1, `https://matrixdomain.org` und `https://jitsi-admin-url.de` müssen durch reale URLs ersetzt werden:
```shell
MATRIX_TOKEN=tokenKommtHIerHer MATRIX_URL=https://matrixdomain.org JITSI_ADMIN_URL=https://jitsi-admin-url.de docker-compose up --build -d
```
4. Berechtigungen für das Volume festlegen:
```shell
chown -R 1000:1000 /var/lib/docker/volumes/matrix-bot_secret_data/
```
### Hinweise
Stellen Sie sicher, dass die Umgebungsvariablen korrekt gesetzt sind und die Zugangsdaten sicher behandelt werden. Der Bot ermöglicht die Verwaltung von Jitsi-Meetings über Matrix und kann entsprechend konfiguriert werden.
--- ---
## 🚀 Funktionen Bitte beachten Sie, dass die Pfadangaben, Token und URLs entsprechend Ihren tatsächlichen Konfigurationen und Anforderungen angepasst werden müssen.
- Starten und Verwalten von Jitsi-Meetings über Matrix
- Konfigurierbare Umgebungsvariablen
- Integration über Docker möglich
---
## 🛠️ Installation & Einrichtung
### 1. 🔑 Matrix-Zugangstoken generieren
Führe den folgenden Befehl aus, um einen Access-Token zu generieren. Ersetze `username`, `passwort` und die URL durch deine echten Zugangsdaten:
```bash
docker run --rm -it \
-e MATRIX_USERNAME=username \
-e MATRIX_PASSWORD=passwort \
-e MATRIX_URL=https://matrixdomain.org \
git.h2-invent.com/meetling/matrix-bot:2.2.7 \
node login.mjs
```
> 💡 **Hinweis:** Bewahre den generierten Token sicher auf - er wird zur Authentifizierung im Container verwendet.
---
## 🐳 Deployment mit Docker
### 1. 📂 Docker Compose Download
Falls noch nicht geschehen:
```bash
mkdir /opt/matrix-bot
cd /opt/matrix-bot
wget https://git.h2-invent.com/Meetling/matrix-bot/raw/branch/master/docker-compose.yml
```
### 2. ⚙️ Container starten
Baue das Docker-Image und starte den Container. Ersetze dabei:
- `tokenKommtHierHer`: den zuvor generierten Matrix Access-Token
- `https://matrixdomain.org`: deine Matrix-Instanz
- `https://jitsi-admin-url.de`: die Jitsi-Admin-URL
```bash
MATRIX_TOKEN=tokenKommtHierHer \
MATRIX_URL=https://matrixdomain.org \
JITSI_ADMIN_URL=https://jitsi-admin-url.de \
docker-compose up -d
```
### 3. 🔐 Berechtigungen setzen
Stelle sicher, dass das Docker-Volume korrekt gesetzt ist:
---
## ⚙️ Konfigurierbare Umgebungsvariablen
| Variable | Beschreibung | Beispielwert |
|----------------------|------------------------------------------------------------------|-----------------------------------|
| `MATRIX_URL` | URL der Matrix-Instanz | `https://matrix.org` |
| `MATRIX_TOKEN` | Der generierte Access-Token | _deinToken_ |
| `MATRIX_PASSWORD` | (Optional) Passwort des Matrix-Accounts | `geheimesPasswort` |
| `JITSI_ADMIN_URL` | URL zum Jitsi-Admin-Endpunkt | `https://jitsi-admin.de` |
| `MATRIX_DISPLAYNAME` | Anzeigename des Bots in Matrix | `"Raumassistent"` |
| `SHOW_WARNING_OF_MIM`| Gibt an, ob Warnungen angezeigt werden sollen (true/false) | `false` |
---
## 📌 Hinweise
- Stelle sicher, dass alle Zugangsdaten und Tokens **sicher gespeichert** und **nicht öffentlich geteilt** werden.
- Die in der README genannten URLs und Tokens dienen nur als **Beispiele** - bitte passe sie an deine Umgebung an.
- Der Bot bietet eine flexible Möglichkeit, Jitsi-Meetings über Matrix zu automatisieren.

View file

@ -11,8 +11,11 @@ Welcome to the inaugural release of our Matrix bot equipped with conference crea
- **!hilfe Command:** Use `!hilfe` to display a comprehensive list of available commands, providing users with quick access to the bot's functionalities. - **!hilfe Command:** Use `!hilfe` to display a comprehensive list of available commands, providing users with quick access to the bot's functionalities.
- **!jitsi Command:** Use `!jitsi` to Instantly initiate a new room in Jitsi if no room is specified in the current room description. This command streamlines the creation of conference rooms. - **!jitsi Command:** Use `!jitsi` to Instantly initiate a new room in Jitsi if no room is specified in the current room description. This command streamlines the creation of conference rooms.
- **!join Command:** Use `!join` to Generate a direct link enabling users to swiftly join ongoing conferences without hassle. - **!join Command:** Use `!join` to Generate a direct link enabling users to swiftly join ongoing conferences without hassle.
- **!version Command:** Use `!version` to Generate a string with the version of the Bot.
We're thrilled to launch this initial version of the Matrix bot, aiming to enhance user experience by simplifying conference creation and access within Matrix chat. We're thrilled to launch this initial version of the Matrix bot, aiming to enhance user experience by simplifying conference creation and access within Matrix chat.
Thank you for using our bot! We welcome your feedback to continue improving its functionality. Thank you for using our bot! We welcome your feedback to continue improving its functionality.
---
Feel free to adjust the details and add any additional information or features specific to your bot's functionality.

View file

@ -1,6 +1,5 @@
import {md5} from "js-md5"; import {md5} from "js-md5";
import {BOT_VERSION, JITSI_ADMIN_URL, SHOW_WARNING_OF_MIM} from "./config.mjs"; import {JITSI_ADMIN_URL} from "./config.mjs";
import gitRepoInfo from 'git-repo-info';
export class conferenceUtils { export class conferenceUtils {
client; client;
@ -10,13 +9,15 @@ export class conferenceUtils {
} }
async createConference(roomId) { async createConference(roomId) {
var roomDescription = await this.getRoomTopic(roomId) var roomDescription = await this.client.getRoomStateEvent(roomId, 'm.room.topic');
const escapedBaseUrl = JITSI_ADMIN_URL.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); roomDescription = roomDescription.topic;
const regex = new RegExp(escapedBaseUrl + '[^\\s\\n]+'); const escapedBaseUrl = JITSI_ADMIN_URL.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const match = roomDescription.match(regex);
if (match) { const regex = new RegExp(escapedBaseUrl + '[^\\s\\n]+');
return match[0]; const match = roomDescription.match(regex);
} if (match) {
return match[0];
}
var hash = md5(roomId); var hash = md5(roomId);
return JITSI_ADMIN_URL + '/m/' + hash; return JITSI_ADMIN_URL + '/m/' + hash;
@ -29,26 +30,15 @@ export class conferenceUtils {
async sendJoinConference(roomId) { async sendJoinConference(roomId) {
var url = await this.createConference(roomId); var url = await this.createConference(roomId);
await this.client.sendHtmlText(roomId, '<a href ="' + url + '">Hier der Konferenz beitreten</a> '); await this.client.sendHtmlText(roomId, '<div role="button" tabindex="0" class="mx_AccessibleButton mx_MemberList_invite"><a href ="' + url + '">Hier der Konferenz beitreten</a></div> ');
}
async inviteAll(roomId) {
var url = await this.createConference(roomId);
var text = '@room <h2>Diese Konferenz startet gerade</h2><br><a href="'+url+'">➡Jetzt dieser Konfernz beitreten</a>'
await this.client.sendHtmlText(roomId, text);
} }
async changeRoomName(roomId) { async changeRoomName(roomId) {
var roomDescription = await this.getRoomTopic(roomId) var roomDescription = await this.client.getRoomStateEvent(roomId, 'm.room.topic');
roomDescription = roomDescription.topic;
var conferenceUrl = await this.createConference(roomId); var conferenceUrl = await this.createConference(roomId);
if (!roomDescription.includes(conferenceUrl)) { if (!roomDescription.includes(conferenceUrl)) {
try { await this.client.sendStateEvent(roomId, 'm.room.topic', '', {'topic': roomDescription + "\n\r" + conferenceUrl})
await this.client.sendStateEvent(roomId, 'm.room.topic', '', {'topic': roomDescription + "\n\r" + conferenceUrl})
}catch (e) {
await this.client.sendText(roomId, 'Der Bot benötigt die Berechtigung "Moderator" um das Raumthema ändern zu dürfen.');
}
} }
} }
@ -57,42 +47,8 @@ export class conferenceUtils {
roomId, roomId,
'Neue Konferenz erstellen: !jitsi\n\r' + 'Neue Konferenz erstellen: !jitsi\n\r' +
'Direkt der Konferenz beitreten: !join\n\r' + 'Direkt der Konferenz beitreten: !join\n\r' +
'Konferenz für alle starten: !starten\n\r'+
'Diese Hilfeseite anzeigen: !hilfe\n\r' 'Diese Hilfeseite anzeigen: !hilfe\n\r'
); );
} }
async getRoomTopic(roomId){
var roomDescription = '';
try {
roomDescription = await this.client.getRoomStateEvent(roomId, 'm.room.topic');
roomDescription = roomDescription.topic;
}catch (e) {
}
return roomDescription;
}
async getVersion(roomId) {
const repoInfo = gitRepoInfo();
this.client.sendText(roomId, 'Version: '+BOT_VERSION);
}
async sendWelcome(roomId) {
var text= '<h2>Hallo, ich bin der Raumassistent.</h2><br> Ein Teammitglied hat mich in diesen Raum eingeladen.<br><br>';
if (SHOW_WARNING_OF_MIM){
text += '⚠️ Kleiner Disclaimer zu Beginn: Ich kann <b>alle Nachrichten</b> in diesem Chat mitlesen. Nicht nur Nachrichten an mich.<br><br>'
}
text +='<b>Hier sind einige Dinge, die ich tun kann:</b><br><br>' +
'<ul>'+
'<li>📹️ Ich kann Videokonfernzen in diesem Raumn erstellen und verwalten</li>'+
'<li>✍️ Sie können mit mir chatten wie mit einem normalen Teilnehmenden.</li>' +
'<li>✅ Um auf alle meine Funktionen zugreifen zu können machen Sie mich bitte zu einem MODERATOR.</li>' +
'<li>❓️ Alle weiteren Informationen erhalten sie durch tippen von "!hilfe"</li>'
+'</ul>';
this.client.sendHtmlText(roomId, text);
}
} }

View file

@ -3,6 +3,4 @@ export var MATRIX_URL=process.env.MATRIX_URL || "https://matrix.org";
export var JITSI_ADMIN_URL =process.env.JITSI_ADMIN_URL || 'https://jitsi-admin.de'; export var JITSI_ADMIN_URL =process.env.JITSI_ADMIN_URL || 'https://jitsi-admin.de';
export var MATRIX_USERNAME =process.env.MATRIX_USERNAME || 'h2inventbot'; export var MATRIX_USERNAME =process.env.MATRIX_USERNAME || 'h2inventbot';
export var MATRIX_PASSWORD =process.env.MATRIX_PASSWORD || 'xxxxxxxx'; export var MATRIX_PASSWORD =process.env.MATRIX_PASSWORD || 'xxxxxxxx';
export var MATRIX_DISPLAYNAME =process.env.MATRIX_DISPLAYNAME || 'Raumassistent'; export var MATRIX_DISPLAYNAME =process.env.MATRIX_DISPLAYNAME || 'Raumassistent';
export var BOT_VERSION =process.env.BOT_VERSION || '<version-addhere>';
export var SHOW_WARNING_OF_MIM =process.env.SHOW_WARNING_OF_MIM || false;

View file

@ -1,6 +1,8 @@
version: '3.7'
services: services:
matrix-bot: matrix-bot:
image: git.h2-invent.com/meetling/matrix-bot:2.2.7 build: .
environment: environment:
MATRIX_URL: ${MATRIX_URL} MATRIX_URL: ${MATRIX_URL}
MATRIX_TOKEN: ${MATRIX_TOKEN} MATRIX_TOKEN: ${MATRIX_TOKEN}

View file

@ -1,15 +1,7 @@
import { import {AutojoinRoomsMixin, MatrixClient, RustSdkCryptoStorageProvider, SimpleFsStorageProvider} from "matrix-bot-sdk";
AutojoinRoomsMixin,
MatrixClient,
RustSdkCryptoStorageProvider,
SimpleFsStorageProvider,
LogService,
LogLevel
} from "matrix-bot-sdk";
import {MATRIX_DISPLAYNAME, MATRIX_TOKEN, MATRIX_URL} from './config.mjs' import {MATRIX_DISPLAYNAME, MATRIX_TOKEN, MATRIX_URL} from './config.mjs'
import {conferenceUtils} from './confernceUtils.mjs' import {conferenceUtils} from './confernceUtils.mjs'
const cryptoProvider = new RustSdkCryptoStorageProvider("./crypto-storage/"); const cryptoProvider = new RustSdkCryptoStorageProvider("./crypto-storage/");
// LogService.muteModule("Metrics"); // LogService.muteModule("Metrics");
@ -36,20 +28,11 @@ AutojoinRoomsMixin.setupOnClient(client);
// Before we start the bot, register our command handler // Before we start the bot, register our command handler
client.on("room.message", handleCommand); client.on("room.message", handleCommand);
client.on("room.join", handlemembership);
// Now that everything is set up, start the bot. This will start the sync loop and run until killed. // Now that everything is set up, start the bot. This will start the sync loop and run until killed.
client.start().then(() => console.log("Bot started!")); client.start().then(() => console.log("Bot started!"));
client.setDisplayName(MATRIX_DISPLAYNAME) client.setDisplayName(MATRIX_DISPLAYNAME)
client.getWhoAmI().then(userInfo => {
console.log("Logged in as User:", userInfo.user_id);
console.log("Logged in with the device ID:", userInfo.device_id);
}).catch(err => {
console.error("Error verifying session:", err);
});
const conferenceUtil = new conferenceUtils(client); const conferenceUtil = new conferenceUtils(client);
// This is the command handler we registered a few lines up // This is the command handler we registered a few lines up
async function handleCommand(roomId, event) { async function handleCommand(roomId, event) {
// Don't handle unhelpful events (ones that aren't text messages, are redacted, or sent by us) // Don't handle unhelpful events (ones that aren't text messages, are redacted, or sent by us)
@ -57,28 +40,15 @@ async function handleCommand(roomId, event) {
if (event['sender'] === await client.getUserId()) return; if (event['sender'] === await client.getUserId()) return;
// Check to ensure that the `!hello` command is being run // Check to ensure that the `!hello` command is being run
let body = event['content']['body']; const body = event['content']['body'];
body = body.toLowerCase(); if (body?.startsWith("!jitsi")){
if (body?.startsWith("!jitsi")) { await conferenceUtil.sendMessageWithUrl(roomId);
conferenceUtil.sendMessageWithUrl(roomId); await conferenceUtil.changeRoomName(roomId);
conferenceUtil.changeRoomName(roomId);
} }
if (body?.startsWith("!join")){
if (body?.startsWith("!join")) { await conferenceUtil.sendJoinConference(roomId);
conferenceUtil.sendJoinConference(roomId);
} }
if (body?.startsWith("!hilfe")){
if (body?.startsWith("!hilfe")) {
conferenceUtil.sendHelp(roomId) conferenceUtil.sendHelp(roomId)
} }
if (body?.startsWith("!starten")) {
conferenceUtil.inviteAll(roomId)
}
if (body?.startsWith("!version")) {
conferenceUtil.getVersion(roomId)
}
} }
async function handlemembership(roomId, event) {
conferenceUtil.sendWelcome(roomId)
}

9
package-lock.json generated
View file

@ -9,7 +9,6 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"git-repo-info": "^2.1.1",
"js-md5": "^0.8.3", "js-md5": "^0.8.3",
"matrix-bot-sdk": "^0.7.0" "matrix-bot-sdk": "^0.7.0"
}, },
@ -746,14 +745,6 @@
"assert-plus": "^1.0.0" "assert-plus": "^1.0.0"
} }
}, },
"node_modules/git-repo-info": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/git-repo-info/-/git-repo-info-2.1.1.tgz",
"integrity": "sha512-8aCohiDo4jwjOwma4FmYFd3i97urZulL8XL24nIPxuE+GZnfsAyy/g2Shqx6OjUiFKUXZM+Yy+KHnOmmA3FVcg==",
"engines": {
"node": ">= 4.0"
}
},
"node_modules/glob-to-regexp": { "node_modules/glob-to-regexp": {
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",

View file

@ -9,7 +9,6 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"git-repo-info": "^2.1.1",
"js-md5": "^0.8.3", "js-md5": "^0.8.3",
"matrix-bot-sdk": "^0.7.0" "matrix-bot-sdk": "^0.7.0"
}, },