Add automatic creation of vote message with random movies
When a !nextwp event is created the bot will fetch random movies and create a message that people can vote on
This commit is contained in:
parent
2c5bf1272e
commit
2707f7d73b
@ -1,4 +1,5 @@
|
|||||||
import dotenv from "dotenv"
|
import dotenv from "dotenv"
|
||||||
|
import { AddListingProviderRequestToJSON } from "./jellyfin"
|
||||||
dotenv.config()
|
dotenv.config()
|
||||||
|
|
||||||
interface options {
|
interface options {
|
||||||
@ -22,6 +23,7 @@ export interface Config {
|
|||||||
workaround_token: string
|
workaround_token: string
|
||||||
watcher_role: string
|
watcher_role: string
|
||||||
jf_admin_role: string
|
jf_admin_role: string
|
||||||
|
announcement_channel_id: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const config: Config = {
|
export const config: Config = {
|
||||||
@ -53,6 +55,7 @@ export const config: Config = {
|
|||||||
jellyfin_url: process.env.JELLYFIN_URL ?? "",
|
jellyfin_url: process.env.JELLYFIN_URL ?? "",
|
||||||
workaround_token: process.env.TOKEN ?? "",
|
workaround_token: process.env.TOKEN ?? "",
|
||||||
watcher_role: process.env.WATCHER_ROLE ?? "",
|
watcher_role: process.env.WATCHER_ROLE ?? "",
|
||||||
jf_admin_role: process.env.ADMIN_ROLE ?? ""
|
jf_admin_role: process.env.ADMIN_ROLE ?? "",
|
||||||
|
announcement_channel_id: process.env.CHANNEL_ID ?? ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
44
server/events/guildScheduledEventCreate.ts
Normal file
44
server/events/guildScheduledEventCreate.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { BaseFetchOptions, ChannelType, GuildBasedChannel, GuildChannelResolvable, GuildMember, GuildScheduledEvent, GuildScheduledEventStatus, Message, TextChannel, messageLink } from "discord.js";
|
||||||
|
import { v4 as uuid } from "uuid";
|
||||||
|
import { jellyfinHandler } from "../..";
|
||||||
|
import { getGuildSpecificTriggerRoleId } from "../helper/roleFilter";
|
||||||
|
import { logger } from "../logger";
|
||||||
|
import { config } from "../configuration";
|
||||||
|
|
||||||
|
|
||||||
|
export const name = 'guildScheduledEventCreate'
|
||||||
|
|
||||||
|
const emotes = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣", "🔟"]
|
||||||
|
|
||||||
|
export async function execute(event: GuildScheduledEvent) {
|
||||||
|
const requestId = uuid()
|
||||||
|
logger.debug(`New event created: ${JSON.stringify(event, null, 2)}`, { guildId: event.guildId, requestId })
|
||||||
|
|
||||||
|
if (event.name.toLowerCase().includes("!nextwp")) {
|
||||||
|
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)
|
||||||
|
|
||||||
|
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 })
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const channel: TextChannel = <TextChannel>(await event.guild?.channels.fetch())?.filter(channel => channel!.id === config.bot.announcement_channel_id).map((value, _) => value)[0] //todo: needs to be done less sketchy
|
||||||
|
logger.debug(`Found channel ${JSON.stringify(channel, null, 2)}`)
|
||||||
|
|
||||||
|
let message = "Es gibt eine neue Abstimmung für die nächste Watchparty! Stimme hierunter für den nächsten Film ab!\n"
|
||||||
|
|
||||||
|
for (let i = 0; i < movies.length; i++) {
|
||||||
|
message = message.concat(emotes[i]).concat(": ").concat(movies[i].name!).concat("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
const sentMessage: Message<true> = await (await channel.fetch()).send(message)
|
||||||
|
|
||||||
|
for (let i = 0; i < movies.length; i++) {
|
||||||
|
sentMessage.react(emotes[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -9,8 +9,8 @@ export const name = 'guildScheduledEventUpdate'
|
|||||||
|
|
||||||
export async function execute(oldEvent: GuildScheduledEvent, newEvent: GuildScheduledEvent) {
|
export async function execute(oldEvent: GuildScheduledEvent, newEvent: GuildScheduledEvent) {
|
||||||
try {
|
try {
|
||||||
logger.info(JSON.stringify(newEvent, null, 2))
|
|
||||||
const requestId = uuid()
|
const requestId = uuid()
|
||||||
|
logger.debug(`Got scheduledEvent update. New Event: ${JSON.stringify(newEvent, null, 2)}`,{guildId: newEvent.guildId, requestId})
|
||||||
|
|
||||||
if (newEvent.description?.toLowerCase().includes("!wp") && [GuildScheduledEventStatus.Active, GuildScheduledEventStatus.Completed].includes(newEvent.status)) {
|
if (newEvent.description?.toLowerCase().includes("!wp") && [GuildScheduledEventStatus.Active, GuildScheduledEventStatus.Completed].includes(newEvent.status)) {
|
||||||
const roles = getGuildSpecificTriggerRoleId(newEvent.guildId).map((key, value)=> value)
|
const roles = getGuildSpecificTriggerRoleId(newEvent.guildId).map((key, value)=> value)
|
||||||
@ -37,6 +37,7 @@ export async function execute(oldEvent: GuildScheduledEvent, newEvent: GuildSche
|
|||||||
logger.error(error)
|
logger.error(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createJFUsers(members: GuildMember[], movieName: string, requestId?: string) {
|
async function createJFUsers(members: GuildMember[], movieName: string, requestId?: string) {
|
||||||
logger.info(`Creating users for: \n ${JSON.stringify(members, null, 2)}`)
|
logger.info(`Creating users for: \n ${JSON.stringify(members, null, 2)}`)
|
||||||
members.forEach(member => {
|
members.forEach(member => {
|
||||||
|
@ -2,8 +2,8 @@ import { GuildMember } from "discord.js";
|
|||||||
import { Config } from "../configuration";
|
import { Config } from "../configuration";
|
||||||
import { Maybe, PermissionLevel } from "../interfaces";
|
import { Maybe, PermissionLevel } from "../interfaces";
|
||||||
import { logger } from "../logger";
|
import { logger } from "../logger";
|
||||||
import { CreateUserByNameOperationRequest, DeleteUserRequest, SystemApi, UpdateUserPasswordOperationRequest, UpdateUserPolicyOperationRequest, UserApi } from "./apis";
|
import { CreateUserByNameOperationRequest, DeleteUserRequest, GetItemsRequest, GetMovieRemoteSearchResultsOperationRequest, ItemLookupApi, ItemsApi, LibraryApi, SystemApi, UpdateUserPasswordOperationRequest, UpdateUserPolicyOperationRequest, UserApi } from "./apis";
|
||||||
import { UpdateUserPasswordRequest } from "./models";
|
import { BaseItemDto, UpdateUserPasswordRequest } from "./models";
|
||||||
import { UserDto } from "./models/UserDto";
|
import { UserDto } from "./models/UserDto";
|
||||||
import { Configuration, ConfigurationParameters } from "./runtime";
|
import { Configuration, ConfigurationParameters } from "./runtime";
|
||||||
|
|
||||||
@ -12,6 +12,7 @@ export class JellyfinHandler {
|
|||||||
|
|
||||||
private userApi: UserApi
|
private userApi: UserApi
|
||||||
private systemApi: SystemApi
|
private systemApi: SystemApi
|
||||||
|
private moviesApi: ItemsApi
|
||||||
private token: string
|
private token: string
|
||||||
private authHeader: { headers: { 'X-Emby-Authorization': string } }
|
private authHeader: { headers: { 'X-Emby-Authorization': string } }
|
||||||
private config: Config
|
private config: Config
|
||||||
@ -24,7 +25,7 @@ export class JellyfinHandler {
|
|||||||
}
|
}
|
||||||
return this.serverName
|
return this.serverName
|
||||||
}
|
}
|
||||||
constructor(_config: Config, _userApi?: UserApi, _systemApi?: SystemApi) {
|
constructor(_config: Config, _userApi?: UserApi, _systemApi?: SystemApi, _itemsApi?: ItemsApi) {
|
||||||
this.config = _config
|
this.config = _config
|
||||||
this.token = this.config.bot.jellfin_token
|
this.token = this.config.bot.jellfin_token
|
||||||
this.authHeader = {
|
this.authHeader = {
|
||||||
@ -40,8 +41,14 @@ export class JellyfinHandler {
|
|||||||
basePath: this.config.bot.jellyfin_url,
|
basePath: this.config.bot.jellyfin_url,
|
||||||
headers: this.authHeader.headers
|
headers: this.authHeader.headers
|
||||||
}
|
}
|
||||||
|
const libraryApiConfigurationParams: ConfigurationParameters = {
|
||||||
|
basePath: this.config.bot.jellyfin_url,
|
||||||
|
headers: this.authHeader.headers
|
||||||
|
}
|
||||||
|
|
||||||
this.userApi = _userApi ?? new UserApi(new Configuration(userApiConfigurationParams))
|
this.userApi = _userApi ?? new UserApi(new Configuration(userApiConfigurationParams))
|
||||||
this.systemApi = _systemApi ?? new SystemApi(new Configuration(systemApiConfigurationParams))
|
this.systemApi = _systemApi ?? new SystemApi(new Configuration(systemApiConfigurationParams))
|
||||||
|
this.moviesApi = _itemsApi ?? new ItemsApi(new Configuration(libraryApiConfigurationParams))
|
||||||
logger.info(`Initialized Jellyfin handler`, { requestId: 'Init' })
|
logger.info(`Initialized Jellyfin handler`, { requestId: 'Init' })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,6 +229,37 @@ export class JellyfinHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getAllMovies(guildId: string, requestId: string): Promise<BaseItemDto[]> {
|
||||||
|
logger.info("requesting all movies from jellyfin", { guildId: guildId, requestId })
|
||||||
|
|
||||||
|
const liloJfUser = await this.getUser(<GuildMember>{ guild: { id: guildId }, displayName: "lilo" }, requestId)
|
||||||
|
|
||||||
|
const searchParams: GetItemsRequest = {
|
||||||
|
userId: liloJfUser?.id,
|
||||||
|
parentId: "f137a2dd21bbc1b99aa5c0f6bf02a805" // 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 })
|
||||||
|
logger.info(`Found ${movies?.length} movies in total`, { guildId: guildId, requestId })
|
||||||
|
return movies ?? []
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getRandomMovies(count: number, guildId: string, requestId: string): Promise<BaseItemDto[]> {
|
||||||
|
logger.info(`${count} random movies requested.`, { guildId: guildId, requestId })
|
||||||
|
const allMovies = await this.getAllMovies(guildId, requestId)
|
||||||
|
if (count >= allMovies.length) {
|
||||||
|
logger.info(`${count} random movies requested but found only ${allMovies.length}. Returning all Movies.`)
|
||||||
|
return allMovies
|
||||||
|
}
|
||||||
|
const movies: BaseItemDto[] = []
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
const index = Math.random() * allMovies.length
|
||||||
|
movies.push(...allMovies.splice(index, 1)) // maybe out of bounds? ?
|
||||||
|
}
|
||||||
|
|
||||||
|
return movies
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
export enum UserUpsertResult { enabled, created }
|
export enum UserUpsertResult { enabled, created }
|
||||||
|
Loading…
Reference in New Issue
Block a user