Compare commits
9 Commits
5b99c843b4
...
v1.0.0
Author | SHA1 | Date | |
---|---|---|---|
f78e4c3e3e | |||
a1e1fca650 | |||
2fae61fc1f | |||
71ffc6ba50 | |||
8caf80f54e | |||
1ccb1a7cae | |||
d22e38efbf | |||
68662e72ad | |||
251756c622 |
23
.gitea/workflows/docker-build.yaml
Normal file
23
.gitea/workflows/docker-build.yaml
Normal file
@ -0,0 +1,23 @@
|
||||
name: Build a docker image for node-jellyfin-role-bot
|
||||
run-name: ${{ gitea.actor }} is building an image
|
||||
on: [push]
|
||||
env:
|
||||
REGISTRY: gitea.brudi.xyz
|
||||
IMAGE_NAME: ${{ gitea.repository }}
|
||||
USER: ${{ gitea.actor }}
|
||||
jobs:
|
||||
build-docker-image:
|
||||
runs-on: ubuntu-latest
|
||||
container: catthehacker/ubuntu:act-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Log in to the Container registry
|
||||
run: docker login -u ${{ env.USER }} -p ${{ secrets.TOKEN }} ${{ env.REGISTRY }}
|
||||
- name: Build Container
|
||||
run: docker build -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" .
|
||||
- name: Push Container
|
||||
run: docker push "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest"
|
11
Dockerfile
Normal file
11
Dockerfile
Normal file
@ -0,0 +1,11 @@
|
||||
FROM node:alpine as Build
|
||||
ENV NODE_ENV=production
|
||||
WORKDIR /app
|
||||
|
||||
COPY [ "package-lock.json", "package.json", "index.ts", "tsconfig.json", "./" ]
|
||||
COPY server ./server
|
||||
|
||||
RUN npm ci --omit=dev
|
||||
|
||||
RUN npm run build
|
||||
CMD ["npm","run","start"]
|
3
index.ts
3
index.ts
@ -5,7 +5,8 @@ import { JellyfinHandler } from "./server/jellyfin/handler"
|
||||
import { attachedImages } from "./server/assets/attachments"
|
||||
const requestId = 'startup'
|
||||
|
||||
export const jellyfinHandler = new JellyfinHandler(config)
|
||||
export const jellyfinHandler = new JellyfinHandler({jellyfinToken: config.bot.workaround_token, jellyfinUrl: config.bot.jellyfin_url, movieCollectionId: config.bot.jf_collection_id, collectionUser: config.bot.jf_user})
|
||||
export const yavinJellyfinHandler = new JellyfinHandler({jellyfinToken: config.bot.yavin_jellyfin_token, jellyfinUrl: config.bot.yavin_jellyfin_url, movieCollectionId: config.bot.yavin_collection_id, collectionUser: config.bot.yavin_jellyfin_collection_user})
|
||||
|
||||
export const client = new ExtendedClient(jellyfinHandler)
|
||||
|
||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "node-jellyfin-discord-bot",
|
||||
"version": "0.0.1",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "node-jellyfin-discord-bot",
|
||||
"version": "0.0.1",
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@discordjs/rest": "^1.7.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-jellyfin-discord-bot",
|
||||
"version": "0.0.1",
|
||||
"version": "1.0.0",
|
||||
"description": "A discord bot to sync jellyfin accounts with discord roles",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
|
@ -67,7 +67,7 @@ async function sendInitialAnnouncement(guildId: string, requestId: string): Prom
|
||||
|
||||
const body = `[initial] Hey! @everyone! Hier ist der Watchparty Bot vom Hartzarett.
|
||||
|
||||
Wir machen in Zukunft regelmäßig Watchparties! Falls du mitmachen möchtest, reagiere einfach auf diesen Post mit 🎫, dann bekommst du automatisch eine Rolle zugewiesen und wirst benachrichtigt sobald es in der Zukunft weitere Watchparties und Filme zum abstimmen gibt.
|
||||
Wir machen in Zukunft regelmäßig Watchparties in denen wir zusammen Filme gucken! Falls du mitmachen möchtest, reagiere einfach auf diesen Post mit 🎫, dann bekommst du automatisch eine Rolle zugewiesen und wirst benachrichtigt sobald es in der Zukunft weitere Watchparties und Filme zum abstimmen gibt.
|
||||
|
||||
Für eine Erklärung wie das alles funktioniert mach einfach /mitgucken für eine lange Erklärung am Stück oder /guides wenn du auswählen möchtest wozu du Infos bekommst.`
|
||||
|
||||
|
@ -25,6 +25,11 @@ export interface Config {
|
||||
announcement_role: string
|
||||
announcement_channel_id: string
|
||||
jf_collection_id: string
|
||||
jf_user: string
|
||||
yavin_collection_id: string
|
||||
yavin_jellyfin_url: string
|
||||
yavin_jellyfin_token: string
|
||||
yavin_jellyfin_collection_user: string
|
||||
}
|
||||
}
|
||||
export const config: Config = {
|
||||
@ -59,6 +64,11 @@ export const config: Config = {
|
||||
jf_admin_role: process.env.ADMIN_ROLE ?? "",
|
||||
announcement_role: process.env.WATCHPARTY_ANNOUNCEMENT_ROLE ?? "",
|
||||
announcement_channel_id: process.env.CHANNEL_ID ?? "",
|
||||
jf_collection_id: process.env.JELLYFIN_COLLECTION_ID ?? ""
|
||||
jf_collection_id: process.env.JELLYFIN_COLLECTION_ID ?? "",
|
||||
yavin_collection_id: process.env.YAVIN_COLLECTION_ID ?? "",
|
||||
yavin_jellyfin_url: process.env.YAVIN_JELLYFIN_URL ?? "",
|
||||
yavin_jellyfin_token: process.env.YAVIN_TOKEN ?? "",
|
||||
yavin_jellyfin_collection_user: process.env.YAVIN_COLLECTION_USER ?? "",
|
||||
jf_user: process.env.JELLYFIN_USER ?? ""
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ export async function execute(oldMember: GuildMember, newMember: GuildMember) {
|
||||
try {
|
||||
const requestId = uuid()
|
||||
const changedRoles: ChangedRoles = filterRolesFromMemberUpdate(oldMember, newMember)
|
||||
const triggerRoleIds: Collection<string, PermissionLevel> = getGuildSpecificTriggerRoleId(oldMember.guild.id)
|
||||
const triggerRoleIds: Collection<string, PermissionLevel> = getGuildSpecificTriggerRoleId()
|
||||
|
||||
triggerRoleIds.forEach((level, key) => {
|
||||
const addedRoleMatches = changedRoles.addedRoles.find(aRole => aRole.id === key)
|
||||
|
@ -3,11 +3,11 @@ import toDate from "date-fns/fp/toDate";
|
||||
import { GuildScheduledEvent, Message, MessageCreateOptions, TextChannel } from "discord.js";
|
||||
import { ScheduledTask, schedule } from "node-cron";
|
||||
import { v4 as uuid } from "uuid";
|
||||
import { client, jellyfinHandler } from "../..";
|
||||
import { client, yavinJellyfinHandler } from "../..";
|
||||
import { closePoll } from "../commands/closepoll";
|
||||
import { config } from "../configuration";
|
||||
import { logger } from "../logger";
|
||||
import { Maybe } from "../interfaces";
|
||||
import { logger } from "../logger";
|
||||
|
||||
|
||||
export const name = 'guildScheduledEventCreate'
|
||||
@ -24,7 +24,7 @@ export async function execute(event: GuildScheduledEvent) {
|
||||
logger.info("Event was a placeholder event to start a new watchparty and voting. Creating vote!", { guildId: event.guildId, requestId })
|
||||
logger.debug("Renaming event", { guildId: event.guildId, requestId })
|
||||
event.edit({ name: "Watchparty - Voting offen" })
|
||||
const movies = await jellyfinHandler.getRandomMovies(5, event.guildId, requestId)
|
||||
const movies = await yavinJellyfinHandler.getRandomMovies(5, event.guildId, requestId)
|
||||
|
||||
logger.info(`Got ${movies.length} random movies. Creating voting`, { guildId: event.guildId, requestId })
|
||||
logger.debug(`Movies: ${JSON.stringify(movies.map(movie => movie.name))}`, { guildId: event.guildId, requestId })
|
||||
|
@ -32,4 +32,10 @@ export interface ChangedRoles {
|
||||
addedRoles: Collection<string, Role>
|
||||
removedRoles: Collection<string, Role>
|
||||
}
|
||||
export interface JellyfinConfig {
|
||||
jellyfinUrl: string,
|
||||
jellyfinToken: string,
|
||||
movieCollectionId: string,
|
||||
collectionUser: string
|
||||
}
|
||||
export type PermissionLevel = "VIEWER" | "ADMIN" | "TEMPORARY"
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { GuildMember } from "discord.js";
|
||||
import { Config } from "../configuration";
|
||||
import { Maybe, PermissionLevel } from "../interfaces";
|
||||
import { JellyfinConfig, Maybe, PermissionLevel } from "../interfaces";
|
||||
import { logger } from "../logger";
|
||||
import { CreateUserByNameOperationRequest, DeleteUserRequest, GetItemsRequest, ItemsApi, SystemApi, UpdateUserPasswordOperationRequest, UpdateUserPolicyOperationRequest, UserApi } from "./apis";
|
||||
import { BaseItemDto, UpdateUserPasswordRequest } from "./models";
|
||||
@ -15,34 +14,27 @@ export class JellyfinHandler {
|
||||
private moviesApi: ItemsApi
|
||||
private token: string
|
||||
private authHeader: { headers: { 'X-Emby-Authorization': string } }
|
||||
private config: Config
|
||||
private config: JellyfinConfig
|
||||
private serverName = "";
|
||||
|
||||
public async ServerName(): Promise<string> {
|
||||
if (this.serverName === "") {
|
||||
const info = await this.systemApi.getSystemInfo(this.authHeader)
|
||||
this.serverName = info.serverName ?? this.config.bot.jellyfin_url
|
||||
}
|
||||
return this.serverName
|
||||
}
|
||||
constructor(_config: Config, _userApi?: UserApi, _systemApi?: SystemApi, _itemsApi?: ItemsApi) {
|
||||
constructor(_config: JellyfinConfig, _userApi?: UserApi, _systemApi?: SystemApi, _itemsApi?: ItemsApi) {
|
||||
this.config = _config
|
||||
this.token = this.config.bot.jellfin_token
|
||||
this.token = this.config.jellyfinToken
|
||||
this.authHeader = {
|
||||
headers: {
|
||||
"X-Emby-Authorization": this.config.bot.workaround_token
|
||||
"X-Emby-Authorization": this.config.jellyfinToken
|
||||
}
|
||||
}
|
||||
const userApiConfigurationParams: ConfigurationParameters = {
|
||||
basePath: this.config.bot.jellyfin_url,
|
||||
basePath: this.config.jellyfinUrl,
|
||||
headers: this.authHeader.headers
|
||||
}
|
||||
const systemApiConfigurationParams: ConfigurationParameters = {
|
||||
basePath: this.config.bot.jellyfin_url,
|
||||
basePath: this.config.jellyfinUrl,
|
||||
headers: this.authHeader.headers
|
||||
}
|
||||
const libraryApiConfigurationParams: ConfigurationParameters = {
|
||||
basePath: this.config.bot.jellyfin_url,
|
||||
basePath: this.config.jellyfinUrl,
|
||||
headers: this.authHeader.headers
|
||||
}
|
||||
|
||||
@ -228,11 +220,9 @@ export class JellyfinHandler {
|
||||
public async getAllMovies(guildId: string, requestId: string): Promise<BaseItemDto[]> {
|
||||
logger.info("requesting all movies from jellyfin", { guildId, requestId })
|
||||
|
||||
const liloJfUser = await this.getUser(<GuildMember>{ guild: { id: guildId }, displayName: "lilo" }, requestId)
|
||||
|
||||
const searchParams: GetItemsRequest = {
|
||||
userId: liloJfUser?.id,
|
||||
parentId: this.config.bot.jf_collection_id // collection ID for all movies
|
||||
userId: this.config.collectionUser,
|
||||
parentId: this.config.movieCollectionId // collection ID for all movies
|
||||
}
|
||||
const movies = (await (this.moviesApi.getItems(searchParams))).items?.filter(item => !item.isFolder)
|
||||
// logger.debug(JSON.stringify(movies, null, 2), { guildId: guildId, requestId })
|
||||
|
@ -33,7 +33,6 @@ export class ExtendedClient extends Client {
|
||||
Promise.all(promises).then(() => {
|
||||
this.login(config.bot.token)
|
||||
})
|
||||
logger.info(`Connected with ${await this.jellyfin.ServerName()}`)
|
||||
}
|
||||
private async importFile(filepath: string): Promise<any> {
|
||||
logger.debug(`Importing ${filepath}`)
|
||||
|
Reference in New Issue
Block a user