32 Commits

Author SHA1 Message Date
0d3c62c6ad Merge pull request 'feat/formatting' (#53) from feat/formatting into master
Reviewed-on: #53
2023-06-24 22:55:42 +02:00
5816db48e6 Merge branch 'master' into feat/formatting
All checks were successful
Compile the repository / compile (pull_request) Successful in 1m16s
Run unit tests / test (pull_request) Successful in 1m33s
2023-06-24 21:55:51 +02:00
66f843b399 format more files
All checks were successful
Compile the repository / compile (pull_request) Successful in 1m12s
2023-06-24 21:09:56 +02:00
d82a7cffd2 same config for all
All checks were successful
Compile the repository / compile (pull_request) Successful in 6s
2023-06-24 21:07:41 +02:00
8a06a661fa adjust some files to new formatting
All checks were successful
Compile the repository / compile (pull_request) Successful in 1m28s
2023-06-24 21:05:43 +02:00
4084f675cd change to tab indents 2023-06-24 21:05:33 +02:00
3bd26a9d6c Merge pull request 'feat/testing' (#52) from feat/testing into master
Reviewed-on: #52
2023-06-24 20:59:39 +02:00
e7b21fa658 apply editorconfig to ts files
All checks were successful
Compile the repository / compile (pull_request) Successful in 1m7s
2023-06-24 20:58:41 +02:00
2d32f9b680 format many files 2023-06-24 20:56:58 +02:00
5503aa8713 add editorconfig 2023-06-24 20:56:22 +02:00
25bb676fda readd compile
All checks were successful
Compile the repository / compile (pull_request) Successful in 10s
Run unit tests / test (pull_request) Successful in 8s
2023-06-24 20:37:59 +02:00
9f5abb8a90 Merge branch 'master' into feat/testing 2023-06-24 20:37:08 +02:00
0e67252976 Merge pull request 'use bash magic to get an env var from the package.json' (#51) from feat/build-versioned-image into master
Reviewed-on: #51
2023-06-24 20:35:23 +02:00
37b798818c handle timezone correctly in docker build
All checks were successful
Run unit tests / test (pull_request) Successful in 1m53s
Compile the repository / compile (pull_request) Successful in 1m10s
2023-06-24 20:31:37 +02:00
af414d0bad rename human facing name for test job
All checks were successful
Compile the repository / compile (pull_request) Successful in 7s
Run unit tests / test (pull_request) Successful in 7s
2023-06-24 20:17:04 +02:00
c32434a7eb rename test job
All checks were successful
Compile the repository / compile (pull_request) Successful in 9s
Compile the repository / test (pull_request) Successful in 9s
2023-06-24 20:16:03 +02:00
c133570d8c update other workflows to use staged builds
All checks were successful
Compile the repository / compile (pull_request) Successful in 8s
2023-06-24 20:11:39 +02:00
65cdee36e9 update testcase
All checks were successful
Compile the repository / compile (pull_request) Successful in 1m58s
2023-06-24 20:09:52 +02:00
6b0e84669a update dockerfile to support test stage 2023-06-24 20:09:09 +02:00
dd72f8e165 add automatic jest test in docker build to workflows 2023-06-24 20:09:00 +02:00
a6f19ccd2b add date test (WIP) 2023-06-24 19:56:49 +02:00
c39f9c6ee1 add first passing test 2023-06-24 19:56:30 +02:00
f41194ba71 add base jest setup 2023-06-24 19:11:12 +02:00
fa49dc0f76 use bash magic to get an env var from the package.json
All checks were successful
Compile the repository / compile (pull_request) Successful in 7s
this is shamelessly stolen from work
2023-06-24 02:14:53 +02:00
e52e845851 1.1.3
All checks were successful
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Successful in 1m59s
2023-06-23 23:46:52 +02:00
61544feaba Fix stupid timezone issues 2023-06-23 23:46:11 +02:00
1966640239 Merge branch 'master' of ssh://gitea.brudi.xyz:222/kenobi/jellyfin-discord-bot 2023-06-23 21:24:32 +02:00
fa9998e92c Unallow transcoding per default for new users 2023-06-23 21:23:54 +02:00
c1a449bafe 1.1.2
All checks were successful
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Successful in 1m50s
2023-06-23 19:46:20 +02:00
d5d82043f0 temporarily remove second tag on docker build 2023-06-23 19:46:06 +02:00
51ebf2e939 1.1.1
All checks were successful
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Successful in 12s
2023-06-23 19:44:58 +02:00
f314b2f355 maybe fix a docker build typo 2023-06-23 19:44:44 +02:00
32 changed files with 1561 additions and 1402 deletions

7
.editorconfig Normal file
View File

@ -0,0 +1,7 @@
root = true
[*]
indent_style = tab
tab_width = 4
[*.ts]
indent_style = tab
tab_width = 4

View File

@ -14,4 +14,4 @@ jobs:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Build Container - name: Build Container
run: docker build . run: docker build --target compile .

View File

@ -11,7 +11,6 @@ env:
jobs: jobs:
build-docker-image: build-docker-image:
runs-on: ubuntu-latest runs-on: ubuntu-latest
#if: gitea.ref == 'refs/heads/master'
container: catthehacker/ubuntu:act-latest container: catthehacker/ubuntu:act-latest
permissions: permissions:
contents: read contents: read
@ -22,6 +21,8 @@ jobs:
- name: Log in to the Container registry - name: Log in to the Container registry
run: docker login -u ${{ env.USER }} -p ${{ secrets.TOKEN }} ${{ env.REGISTRY }} run: docker login -u ${{ env.USER }} -p ${{ secrets.TOKEN }} ${{ env.REGISTRY }}
- name: Build Container - name: Build Container
run: docker build -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ node -p "require('./package.json').version" }}". run: docker build --target compile -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}" .
env:
version: $(cat package.json | awk 'match($0, /version/) {print $2}' | sed 's/[\",]//g') # extracts the version number from the package.json with bash magic
- name: Push Container - name: Push Container
run: docker push --all-tags "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}" run: docker push --all-tags "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"

View File

@ -0,0 +1,18 @@
name: Run unit tests
on: [pull_request]
env:
REGISTRY: gitea.brudi.xyz
IMAGE_NAME: ${{ gitea.repository }}
USER: ${{ gitea.actor }}
jobs:
test:
runs-on: ubuntu-latest
container: catthehacker/ubuntu:act-latest
permissions:
contents: read
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Run Tests
run: docker build --target test .

View File

@ -1,11 +1,21 @@
FROM node:alpine as Build FROM node:alpine as files
ENV NODE_ENV=production ENV TZ="Europe/Berlin"
WORKDIR /app WORKDIR /app
COPY [ "package-lock.json", "package.json", "index.ts", "tsconfig.json", "./" ] COPY [ "package-lock.json", "package.json", "index.ts", "tsconfig.json", "./" ]
COPY server ./server COPY server ./server
FROM files as proddependencies
ENV NODE_ENV=production
RUN npm ci --omit=dev RUN npm ci --omit=dev
FROM proddependencies as compile
RUN npm run build RUN npm run build
CMD ["npm","run","start"] CMD ["npm","run","start"]
FROM files as dependencies
RUN npm ci
FROM dependencies as test
COPY jest.config.js .
COPY tests ./tests
RUN npm run test

18
jest.config.js Normal file
View File

@ -0,0 +1,18 @@
module.exports = {
'roots': [
'<rootDir>/tests',
'<rootDir>/server'
],
'transform': {
'^.+\\.tsx?$': 'ts-jest'
},
'testRegex': '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
'moduleFileExtensions': [
'ts',
'tsx',
'js',
'jsx',
'json',
'node'
],
};

46
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "node-jellyfin-discord-bot", "name": "node-jellyfin-discord-bot",
"version": "1.1.0", "version": "1.1.3",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "node-jellyfin-discord-bot", "name": "node-jellyfin-discord-bot",
"version": "1.1.0", "version": "1.1.3",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@discordjs/rest": "^1.7.0", "@discordjs/rest": "^1.7.0",
@ -17,6 +17,7 @@
"@types/uuid": "^9.0.1", "@types/uuid": "^9.0.1",
"axios": "^1.3.5", "axios": "^1.3.5",
"date-fns": "^2.29.3", "date-fns": "^2.29.3",
"date-fns-tz": "^2.0.0",
"discord-api-types": "^0.37.38", "discord-api-types": "^0.37.38",
"discord.js": "^14.9.0", "discord.js": "^14.9.0",
"dotenv": "^16.0.3", "dotenv": "^16.0.3",
@ -29,12 +30,13 @@
"winston": "^3.8.2" "winston": "^3.8.2"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.5.0", "@types/jest": "^29.5.2",
"@typescript-eslint/eslint-plugin": "^5.58.0", "@typescript-eslint/eslint-plugin": "^5.58.0",
"@typescript-eslint/parser": "^5.58.0", "@typescript-eslint/parser": "^5.58.0",
"eslint": "^8.38.0", "eslint": "^8.38.0",
"jest": "^29.5.0", "jest": "^29.5.0",
"jest-cli": "^29.5.0", "jest-cli": "^29.5.0",
"mockdate": "^3.0.5",
"nodemon": "^2.0.22", "nodemon": "^2.0.22",
"rimraf": "^5.0.0", "rimraf": "^5.0.0",
"ts-jest": "^29.1.0" "ts-jest": "^29.1.0"
@ -1567,9 +1569,9 @@
} }
}, },
"node_modules/@types/jest": { "node_modules/@types/jest": {
"version": "29.5.0", "version": "29.5.2",
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.0.tgz", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.2.tgz",
"integrity": "sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg==", "integrity": "sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"expect": "^29.0.0", "expect": "^29.0.0",
@ -2626,6 +2628,14 @@
"url": "https://opencollective.com/date-fns" "url": "https://opencollective.com/date-fns"
} }
}, },
"node_modules/date-fns-tz": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-2.0.0.tgz",
"integrity": "sha512-OAtcLdB9vxSXTWHdT8b398ARImVwQMyjfYGkKD2zaGpHseG2UPHbHjXELReErZFxWdSLph3c2zOaaTyHfOhERQ==",
"peerDependencies": {
"date-fns": ">=2.0.0"
}
},
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@ -4980,6 +4990,12 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/mockdate": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/mockdate/-/mockdate-3.0.5.tgz",
"integrity": "sha512-iniQP4rj1FhBdBYS/+eQv7j1tadJ9lJtdzgOpvsOHng/GbcDh2Fhdeq+ZRldrPYdXvCyfFUmFeEwEGXZB5I/AQ==",
"dev": true
},
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@ -8130,9 +8146,9 @@
} }
}, },
"@types/jest": { "@types/jest": {
"version": "29.5.0", "version": "29.5.2",
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.0.tgz", "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.2.tgz",
"integrity": "sha512-3Emr5VOl/aoBwnWcH/EFQvlSAmjV+XtV9GGu5mwdYew5vhQh0IUZx/60x0TzHDu09Bi7HMx10t/namdJw5QIcg==", "integrity": "sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg==",
"dev": true, "dev": true,
"requires": { "requires": {
"expect": "^29.0.0", "expect": "^29.0.0",
@ -8905,6 +8921,12 @@
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
"integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==" "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA=="
}, },
"date-fns-tz": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-2.0.0.tgz",
"integrity": "sha512-OAtcLdB9vxSXTWHdT8b398ARImVwQMyjfYGkKD2zaGpHseG2UPHbHjXELReErZFxWdSLph3c2zOaaTyHfOhERQ==",
"requires": {}
},
"debug": { "debug": {
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@ -10705,6 +10727,12 @@
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
}, },
"mockdate": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/mockdate/-/mockdate-3.0.5.tgz",
"integrity": "sha512-iniQP4rj1FhBdBYS/+eQv7j1tadJ9lJtdzgOpvsOHng/GbcDh2Fhdeq+ZRldrPYdXvCyfFUmFeEwEGXZB5I/AQ==",
"dev": true
},
"ms": { "ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",

View File

@ -1,6 +1,6 @@
{ {
"name": "node-jellyfin-discord-bot", "name": "node-jellyfin-discord-bot",
"version": "1.1.0", "version": "1.1.3",
"description": "A discord bot to sync jellyfin accounts with discord roles", "description": "A discord bot to sync jellyfin accounts with discord roles",
"main": "index.js", "main": "index.js",
"license": "MIT", "license": "MIT",
@ -13,6 +13,7 @@
"@types/uuid": "^9.0.1", "@types/uuid": "^9.0.1",
"axios": "^1.3.5", "axios": "^1.3.5",
"date-fns": "^2.29.3", "date-fns": "^2.29.3",
"date-fns-tz": "^2.0.0",
"discord-api-types": "^0.37.38", "discord-api-types": "^0.37.38",
"discord.js": "^14.9.0", "discord.js": "^14.9.0",
"dotenv": "^16.0.3", "dotenv": "^16.0.3",
@ -32,15 +33,18 @@
"debuggable": "node build/index.js --inspect-brk", "debuggable": "node build/index.js --inspect-brk",
"monitor": "nodemon build/index.js", "monitor": "nodemon build/index.js",
"lint": "eslint . --ext .ts", "lint": "eslint . --ext .ts",
"lint-fix": "eslint . --ext .ts --fix" "lint-fix": "eslint . --ext .ts --fix",
"test": "jest",
"test-watch": "jest --watch"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.5.0", "@types/jest": "^29.5.2",
"@typescript-eslint/eslint-plugin": "^5.58.0", "@typescript-eslint/eslint-plugin": "^5.58.0",
"@typescript-eslint/parser": "^5.58.0", "@typescript-eslint/parser": "^5.58.0",
"eslint": "^8.38.0", "eslint": "^8.38.0",
"jest": "^29.5.0", "jest": "^29.5.0",
"jest-cli": "^29.5.0", "jest-cli": "^29.5.0",
"mockdate": "^3.0.5",
"nodemon": "^2.0.22", "nodemon": "^2.0.22",
"rimraf": "^5.0.0", "rimraf": "^5.0.0",
"ts-jest": "^29.1.0" "ts-jest": "^29.1.0"

View File

@ -1,6 +1,8 @@
import { format } from "date-fns"; import { format, isToday, toDate } from "date-fns";
import { utcToZonedTime } from "date-fns-tz"
import { GuildScheduledEvent } from "discord.js"; import { GuildScheduledEvent } from "discord.js";
import { logger } from "../logger"; import { logger } from "../logger";
import de from "date-fns/locale/de";
export function createDateStringFromEvent(event: GuildScheduledEvent, requestId: string, guildId?: string): string { export function createDateStringFromEvent(event: GuildScheduledEvent, requestId: string, guildId?: string): string {
if (!event.scheduledStartAt) { if (!event.scheduledStartAt) {
@ -8,9 +10,14 @@ export function createDateStringFromEvent(event: GuildScheduledEvent, requestId:
return `"habe keinen Startzeitpunkt ermitteln können"` return `"habe keinen Startzeitpunkt ermitteln können"`
} }
const date = format(event.scheduledStartAt, "dd.MM") const timeZone = 'Europe/Berlin'
const time = format(event.scheduledStartAt, "HH:mm") const zonedDateTime = utcToZonedTime(event.scheduledStartAt, timeZone)
const time = format(zonedDateTime, "HH:mm", { locale: de })
if (isToday(zonedDateTime)) {
return `heute um ${time}`
}
const date = format(zonedDateTime, "eeee dd.MM", { locale: de })
return `am ${date} um ${time}` return `am ${date} um ${time}`
} }

View File

@ -2,7 +2,7 @@ import { GuildMember } from "discord.js";
import { JellyfinConfig, Maybe, PermissionLevel } from "../interfaces"; import { JellyfinConfig, Maybe, PermissionLevel } from "../interfaces";
import { logger } from "../logger"; import { logger } from "../logger";
import { CreateUserByNameOperationRequest, DeleteUserRequest, GetItemsRequest, ItemsApi, SystemApi, UpdateUserPasswordOperationRequest, UpdateUserPolicyOperationRequest, UserApi } from "./apis"; import { CreateUserByNameOperationRequest, DeleteUserRequest, GetItemsRequest, ItemsApi, SystemApi, UpdateUserPasswordOperationRequest, UpdateUserPolicyOperationRequest, UserApi } from "./apis";
import { BaseItemDto, UpdateUserPasswordRequest } from "./models"; import { BaseItemDto, UpdateUserPasswordRequest, UpdateUserPolicyRequest } from "./models";
import { UserDto } from "./models/UserDto"; import { UserDto } from "./models/UserDto";
import { Configuration, ConfigurationParameters } from "./runtime"; import { Configuration, ConfigurationParameters } from "./runtime";
@ -52,24 +52,46 @@ export class JellyfinHandler {
return (Math.random() * 10000 + 10000).toFixed(0) return (Math.random() * 10000 + 10000).toFixed(0)
} }
public async createUserAccountForDiscordUser(discordUser: GuildMember, level: PermissionLevel, guildId?: string, requestId?: string): Promise<UserDto> { public async createUserAccountForDiscordUser(discordUser: GuildMember, level: PermissionLevel, requestId: string, guildId?: string): Promise<UserDto> {
const newUserName = this.generateJFUserName(discordUser, level) const newUserName = this.generateJFUserName(discordUser, level)
logger.info(`New Username for ${discordUser.displayName}: ${newUserName}`, { guildId, requestId }) logger.info(`New Username for ${discordUser.displayName}: ${newUserName}`, { guildId, requestId })
const req: CreateUserByNameOperationRequest = { const req: CreateUserByNameOperationRequest = {
createUserByNameRequest: { createUserByNameRequest: {
name: newUserName, name: newUserName,
password: this.generatePasswordForUser(), password: this.generatePasswordForUser()
} }
} }
logger.debug(JSON.stringify(req), { requestId, guildId }) logger.debug(JSON.stringify(req), { requestId, guildId })
const createResult = await this.userApi.createUserByName(req) const createResult = await this.userApi.createUserByName(req)
if (createResult) { if (createResult) {
if (createResult.policy) {
this.setUserPermissions(createResult, requestId, guildId)
}
(await discordUser.createDM()).send(`Ich hab dir mal nen Account angelegt :)\nDein Username ist ${createResult.name}, dein Password ist "${req.createUserByNameRequest.password}"!`) (await discordUser.createDM()).send(`Ich hab dir mal nen Account angelegt :)\nDein Username ist ${createResult.name}, dein Password ist "${req.createUserByNameRequest.password}"!`)
return createResult return createResult
} }
else throw new Error('Could not create User in Jellyfin') else throw new Error('Could not create User in Jellyfin')
} }
public async setUserPermissions(user: UserDto, requestId: string, guildId?: string) {
if (!user.policy || !user.id) {
logger.error(`Cannot update user policy. User ${user.name} has no policy to modify`, { guildId, requestId })
return
}
user.policy.enableVideoPlaybackTranscoding = false
const operation: UpdateUserPolicyRequest = {
...user.policy,
enableVideoPlaybackTranscoding: false
}
const request: UpdateUserPolicyOperationRequest = {
userId: user.id,
updateUserPolicyRequest: operation
}
this.userApi.updateUserPolicy(request)
}
public async isUserAlreadyPresent(discordUser: GuildMember, requestId?: string): Promise<boolean> { public async isUserAlreadyPresent(discordUser: GuildMember, requestId?: string): Promise<boolean> {
const jfuser = await this.getUser(discordUser, requestId) const jfuser = await this.getUser(discordUser, requestId)
logger.debug(`Presence for DiscordUser ${discordUser.id}:${jfuser !== undefined}`, { guildId: discordUser.guild.id, requestId }) logger.debug(`Presence for DiscordUser ${discordUser.id}:${jfuser !== undefined}`, { guildId: discordUser.guild.id, requestId })

View File

@ -0,0 +1,16 @@
import { GuildScheduledEvent } from "discord.js"
import { createDateStringFromEvent } from "../../server/helper/dateHelper"
import MockDate from 'mockdate'
beforeAll(() => {
MockDate.set('01-01-2023')
})
function getTestDate(date: string): GuildScheduledEvent {
return <GuildScheduledEvent>{ scheduledStartAt: new Date(date) }
}
test('createDateStringFromEvent - correct formatting', () => {
expect(createDateStringFromEvent(getTestDate('01-01-2023 12:30'), "")).toEqual('heute um 12:30')
expect(createDateStringFromEvent(getTestDate('01-02-2023 12:30'), "")).toEqual('am Montag 02.01 um 12:30')
expect(createDateStringFromEvent(getTestDate('01-03-2023 12:30'), "")).toEqual('am Dienstag 03.01 um 12:30')
})

View File

@ -0,0 +1,28 @@
import { Collection, GuildMember, Role } from "discord.js"
import { filterRolesFromMemberUpdate } from "../../server/helper/roleFilter"
function buildFakeRole(id: string, name: string): Role {
return <Role>{ id, name }
}
test('filterRolesFromMemberUpdate', () => {
const oldMemberRoles: Collection<string, Role> = new Collection<string, Role>()
oldMemberRoles.set('1', buildFakeRole('01', 'Role01'))
oldMemberRoles.set('2', buildFakeRole('02', 'Role02'))
const newMemberRoles: Collection<string, Role> = new Collection<string, Role>()
newMemberRoles.set('1', buildFakeRole('01', 'Role01'))
newMemberRoles.set('2', buildFakeRole('02', 'Role02'))
newMemberRoles.set('3', buildFakeRole('03', 'Role03'))
const oldMember: GuildMember = <GuildMember>{ roles: { cache: oldMemberRoles }, guild: { id: "guildid" } }
const newMember: GuildMember = <GuildMember>{ roles: { cache: newMemberRoles }, guild: { id: "guildid" } }
const output = filterRolesFromMemberUpdate(oldMember, newMember)
const expectedAddedRoles: Collection<string, Role> = new Collection<string, Role>()
expectedAddedRoles.set('3', buildFakeRole('03', 'Role03'))
const expectedRemovedRoles: Collection<string, Role> = new Collection<string, Role>()
expect(output.addedRoles).toEqual(expectedAddedRoles)
expect(output.removedRoles).toEqual(expectedRemovedRoles)
})