2023-05-04 23:34:53 +02:00
import { GuildMember } from "discord.js" ;
2023-06-04 01:02:29 +02:00
import { CreateUserByNameOperationRequest , SystemApi , UpdateUserPasswordOperationRequest , UpdateUserPolicyOperationRequest , UserApi } from "./apis" ;
2023-05-04 23:34:53 +02:00
import { UserDto } from "./models/UserDto" ;
import { Configuration , ConfigurationParameters } from "./runtime" ;
2023-06-04 01:02:29 +02:00
import { CreateUserByNameRequest , UpdateUserEasyPasswordRequest , UpdateUserPasswordRequest , UpdateUserPolicyRequest } from "./models" ;
2023-05-04 23:34:53 +02:00
import { Config } from "../configuration" ;
import { logger } from "../logger" ;
import { Maybe } from "../interfaces" ;
2023-06-04 01:02:29 +02:00
import { v4 as uuid } from "uuid" ;
2023-04-16 02:04:08 +02:00
export class JellyfinHandler {
private userApi : UserApi
private systemApi : SystemApi
private token : string
2023-06-04 03:14:45 +02:00
private authHeader : { headers : { 'X-Emby-Authorization' : string } }
2023-04-16 02:04:08 +02:00
private config : Config
2023-04-18 23:46:26 +02:00
private serverName = "" ;
2023-04-16 02:04:08 +02:00
public async ServerName ( ) : Promise < string > {
if ( this . serverName === "" ) {
const info = await this . systemApi . getSystemInfo ( this . authHeader )
2023-05-04 23:34:53 +02:00
this . serverName = info . serverName ? ? this . config . bot . jellyfin_url
2023-04-16 02:04:08 +02:00
}
return this . serverName
}
constructor ( _config : Config , _userApi? : UserApi , _systemApi? : SystemApi ) {
this . config = _config
this . token = this . config . bot . jellfin_token
this . authHeader = {
headers : {
2023-06-04 03:14:45 +02:00
"X-Emby-Authorization" : this . config . bot . workaround_token
2023-04-16 02:04:08 +02:00
}
}
2023-06-03 22:06:23 +02:00
const userApiConfigurationParams : ConfigurationParameters = {
basePath : this.config.bot.jellyfin_url ,
headers : this.authHeader.headers
}
const systemApiConfigurationParams : ConfigurationParameters = {
basePath : this.config.bot.jellyfin_url ,
headers : this.authHeader.headers
}
this . userApi = _userApi ? ? new UserApi ( new Configuration ( userApiConfigurationParams ) )
this . systemApi = _systemApi ? ? new SystemApi ( new Configuration ( systemApiConfigurationParams ) )
2023-05-04 23:34:53 +02:00
logger . info ( ` Initialized Jellyfin handler ` , { requestId : 'Init' } )
2023-04-16 02:04:08 +02:00
}
2023-04-18 23:46:26 +02:00
private generateJFUserName ( discordUser : GuildMember ) : string {
return discordUser . displayName
2023-04-16 02:04:08 +02:00
}
public async addPermissionsToUserAccount ( jfUserAccount : UserDto , guildId : string , requestId : string ) : Promise < UserDto > {
throw new Error ( "Method not implemented." ) ;
}
2023-04-20 20:54:20 +02:00
2023-06-04 01:02:29 +02:00
private generatePasswordForUser ( ) : string {
return ( Math . random ( ) * 10000 + 10000 ) . toFixed ( 0 )
2023-04-20 20:54:20 +02:00
}
public async createUserAccountForDiscordUser ( discordUser : GuildMember , guildId? : string , requestId? : string ) : Promise < UserDto > {
2023-04-16 02:04:08 +02:00
const newUserName = this . generateJFUserName ( discordUser )
2023-04-18 23:46:26 +02:00
logger . info ( ` New Username for ${ discordUser . displayName } : ${ newUserName } ` , { guildId , requestId } )
2023-05-04 23:34:53 +02:00
const req : CreateUserByNameOperationRequest = {
createUserByNameRequest : {
name : newUserName ,
2023-06-04 01:02:29 +02:00
password : this.generatePasswordForUser ( ) ,
2023-05-04 23:34:53 +02:00
}
2023-04-20 20:54:20 +02:00
}
logger . debug ( JSON . stringify ( req ) )
2023-06-03 22:06:23 +02:00
const createResult = await this . userApi . createUserByName ( req )
2023-06-04 03:14:45 +02:00
if ( createResult ) {
( await discordUser . createDM ( ) ) . send ( ` Ich hab dir mal nen Account angelegt :) \ nDein Username ist ${ createResult . name } , dein Password ist " ${ req . createUserByNameRequest . password } "! ` )
2023-05-04 23:34:53 +02:00
return createResult
2023-04-20 20:54:20 +02:00
}
2023-06-04 01:02:29 +02:00
else throw new Error ( 'Could not create User in Jellyfin' )
2023-04-16 02:04:08 +02:00
}
2023-06-04 03:14:45 +02:00
2023-04-20 20:54:20 +02:00
public async isUserAlreadyPresent ( discordUser : GuildMember , requestId? : string ) : Promise < boolean > {
const jfuser = await this . getUser ( discordUser , requestId )
logger . debug ( ` Presence for DiscordUser ${ discordUser . id } : ${ jfuser !== undefined } ` )
return jfuser !== undefined
}
2023-06-04 03:14:45 +02:00
2023-04-18 23:46:26 +02:00
public async getCurrentUsers ( guildId : string , requestId? : string ) : Promise < UserDto [ ] > {
2023-04-16 02:04:08 +02:00
try {
2023-05-04 23:34:53 +02:00
logger . info ( ` Fetching current users from Jellyfin ` , { requestId , guildId } )
const result = await this . userApi . getUsers ( undefined , this . authHeader )
return result
2023-04-16 02:04:08 +02:00
} catch ( error ) {
logger . error ( ` Could not fetch current users from jellyfin ` , { guildId , requestId } )
}
return [ ]
}
2023-06-04 03:14:45 +02:00
2023-04-20 20:54:20 +02:00
public async getUser ( discordUser : GuildMember , requestId? : string ) : Promise < Maybe < UserDto > > {
2023-06-04 03:14:45 +02:00
logger . info ( ` Getting user for discord member ${ discordUser . displayName } ` , { requestId } )
2023-04-20 20:54:20 +02:00
const jfUsernameFromDiscordUsername = this . generateJFUserName ( discordUser )
const jfUsers = await this . getCurrentUsers ( discordUser . guild . id , requestId )
const foundUser = jfUsers . find ( x = > x . name === jfUsernameFromDiscordUsername )
return foundUser
}
2023-06-04 03:14:45 +02:00
2023-04-20 20:54:20 +02:00
public async removeUser ( newMember : GuildMember , requestId? : string ) {
2023-06-04 03:14:45 +02:00
logger . error ( ` Trying to remove user ${ newMember . displayName } , but method is not implemented ` , { requestId } )
2023-04-20 20:54:20 +02:00
const jfuser = await this . getUser ( newMember , requestId )
if ( jfuser ) {
2023-06-04 01:02:29 +02:00
await this . disableUser ( jfuser , newMember . guild . id , requestId )
}
}
public async resetUserPasswort ( member : GuildMember , requestId? : string ) {
2023-06-04 03:14:45 +02:00
logger . info ( ` Resetting password for user ${ member . displayName } ` , { requestId } )
2023-06-04 01:02:29 +02:00
const jfUser = await this . getUser ( member , requestId )
if ( jfUser && jfUser . id ) {
2023-06-04 03:14:45 +02:00
// const reset: UpdateUserPasswordRequest = {
// resetPassword: true
// }
// const shit: UpdateUserPasswordOperationRequest = {
// updateUserPasswordRequest: reset,
// userId: jfUser.id
// }
// logger.info(JSON.stringify(jfUser.policy, null, 2))
// logger.info("Resetting password", {requestId})
// await this.userApi.updateUserPassword(shit);
const password = this . generatePasswordForUser ( )
const passwordRequest : UpdateUserPasswordRequest = {
// resetPassword: true,
currentPw : "" ,
newPw : password
2023-06-04 01:02:29 +02:00
}
2023-06-04 03:14:45 +02:00
const passwordOperationRequest : UpdateUserPasswordOperationRequest = {
updateUserPasswordRequest : passwordRequest ,
2023-06-04 01:02:29 +02:00
userId : jfUser.id
}
2023-06-04 03:14:45 +02:00
logger . info ( "Setting new password" , { requestId } )
await this . userApi . updateUserPassword ( passwordOperationRequest ) ;
2023-06-04 01:02:29 +02:00
2023-06-04 03:14:45 +02:00
( await member . createDM ( ) ) . send ( ` Hier ist dein neues Passwort: ${ password } ` )
2023-06-04 01:02:29 +02:00
} else {
( await member . createDM ( ) ) . send ( "Ich konnte leider keinen User von dir auf Jellyfin finden. Bitte melde dich bei Markus oder Samantha!" )
2023-04-20 20:54:20 +02:00
}
2023-06-04 01:02:29 +02:00
2023-04-20 20:54:20 +02:00
}
2023-06-04 01:02:29 +02:00
public async disableUser ( user : UserDto , guildId? : string , requestId? : string ) : Promise < void > {
2023-04-20 20:54:20 +02:00
if ( user . id ) {
2023-06-04 03:14:45 +02:00
const jfUser = await this . getUser ( < GuildMember > { displayName : user.name , guild : { id : guildId } } , requestId )
2023-06-04 01:02:29 +02:00
logger . info ( ` Trying to disable user: ${ user . name } | ${ user . id } | ${ JSON . stringify ( jfUser , null , 2 ) } ` )
2023-05-04 23:34:53 +02:00
const r : UpdateUserPolicyOperationRequest = {
userId : user.id ? ? "" ,
updateUserPolicyRequest : {
2023-06-04 01:02:29 +02:00
. . . jfUser ? . policy ,
isDisabled : true ,
}
}
await this . userApi . updateUserPolicy ( r )
logger . info ( ` Succeeded with disabling user: ${ user . name } ` )
}
else {
logger . error ( ` Can not disable user ${ JSON . stringify ( user ) } , has no id?! ` , { requestId , guildId } )
}
}
2023-06-04 03:14:45 +02:00
2023-06-04 01:02:29 +02:00
public async enableUser ( user : UserDto , guildId : string , requestId? : string ) : Promise < void > {
if ( user . id ) {
2023-06-04 03:14:45 +02:00
const jfUser = await this . getUser ( < GuildMember > { displayName : user.name , guild : { id : guildId } } , requestId )
2023-06-04 01:02:29 +02:00
logger . info ( ` Trying to enable user: ${ user . name } | ${ user . id } | ${ JSON . stringify ( jfUser , null , 2 ) } ` )
const r : UpdateUserPolicyOperationRequest = {
userId : user.id ? ? "" ,
updateUserPolicyRequest : {
. . . jfUser ? . policy ,
isDisabled : false ,
2023-05-04 23:34:53 +02:00
}
2023-04-20 20:54:20 +02:00
}
2023-06-03 22:06:23 +02:00
await this . userApi . updateUserPolicy ( r )
2023-04-20 20:54:20 +02:00
logger . info ( ` Succeeded with enabling user: ${ user . name } ` )
}
else {
logger . error ( ` Can not enable user ${ JSON . stringify ( user ) } , has no id?! ` , { requestId , guildId } )
}
2023-04-18 23:46:26 +02:00
}
2023-04-20 20:54:20 +02:00
2023-04-18 23:46:26 +02:00
public async upsertUser ( newMember : GuildMember , level : string , requestId? : string ) {
2023-04-20 20:54:20 +02:00
logger . error ( ` Trying to upsert user ${ newMember . displayName } , with permissionLevel ${ level } ` )
const jfuser = await this . getUser ( newMember , requestId )
if ( jfuser ) {
2023-04-18 23:46:26 +02:00
logger . info ( ` User with name ${ newMember . displayName } is already present ` )
2023-06-04 01:02:29 +02:00
await this . enableUser ( jfuser , newMember . guild . id , requestId )
2023-04-20 20:54:20 +02:00
} else {
this . createUserAccountForDiscordUser ( newMember , newMember . guild . id , requestId )
2023-04-18 23:46:26 +02:00
}
}
2023-04-16 02:04:08 +02:00
}
2023-05-04 23:34:53 +02:00