41 Commits

Author SHA1 Message Date
36d1306180 remove test build 2023-06-24 02:13:05 +02:00
69bde313b5 test with latest
All checks were successful
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Successful in 6s
2023-06-24 02:10:26 +02:00
7af3d87048 use new var in build
All checks were successful
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Successful in 6s
2023-06-24 02:09:03 +02:00
73741230b1 adjust env method
All checks were successful
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Successful in 7s
2023-06-24 02:08:26 +02:00
4f6d4f646a adjust echo script
All checks were successful
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Successful in 6s
2023-06-24 02:07:19 +02:00
6169649261 add new step
All checks were successful
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Successful in 6s
2023-06-24 02:06:10 +02:00
0560c4620c adjust awk script
All checks were successful
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Successful in 6s
2023-06-24 02:05:01 +02:00
be3ee5e493 echo version
All checks were successful
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Successful in 6s
2023-06-24 02:02:42 +02:00
251e6ae3d6 add test build script
Some checks failed
Build a docker image for node-jellyfin-role-bot / build-docker-image (push) Failing after 9s
2023-06-24 02:00:56 +02:00
2edd0312dc Merge branch 'master' into feat/cicd 2023-06-24 02:00:28 +02:00
f2b5ee502f remove unnecessary scripts
All checks were successful
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Successful in 10s
2023-06-14 22:35:59 +02:00
749e1c89ab clean up ci yaml 2023-06-14 22:35:51 +02:00
0d5799796a go back to normal docker commands
All checks were successful
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Successful in 15s
2023-06-14 22:33:15 +02:00
b7986d276b fix env access
All checks were successful
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Successful in 24s
2023-06-14 22:31:34 +02:00
8540381834 use bash explicitly
All checks were successful
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Successful in 8s
2023-06-14 22:29:55 +02:00
7e67d1fed9 adjust scripts
All checks were successful
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Successful in 8s
2023-06-14 22:28:29 +02:00
0cb19ba8f1 use bash scripts for docker stage
All checks were successful
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Successful in 11s
2023-06-14 22:27:18 +02:00
5dcf766593 dockerbuild and dockerpush scripts 2023-06-14 22:27:05 +02:00
808bdd033e string it
All checks were successful
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Successful in 9s
2023-06-14 22:20:06 +02:00
33f031d333 simplify push
All checks were successful
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Successful in 9s
2023-06-14 22:14:46 +02:00
40d9523e21 doing it manually 2023-06-14 22:14:19 +02:00
26e74a62c1 add branch 2023-06-14 21:54:22 +02:00
c0f91aad79 add secrets to 'on' 2023-06-14 21:42:16 +02:00
79ffde5f34 check env step
Some checks failed
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Failing after 23s
2023-06-14 21:30:23 +02:00
911b9e4884 adjust pipeline to be personalized
Some checks failed
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Failing after 17s
2023-06-14 21:27:16 +02:00
31a9e0eb28 adjust url
Some checks failed
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Failing after 22s
2023-06-14 19:44:50 +02:00
bcf788293e hardcoded docker tags
Some checks failed
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Failing after 28s
2023-06-14 19:27:28 +02:00
934b6dfead remove custom script
Some checks failed
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Failing after 15s
2023-06-14 19:21:22 +02:00
cd0c8c0017 latest tag by default
Some checks failed
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Failing after 15s
2023-06-14 19:18:46 +02:00
83f803d0e7 remove metadata action
Some checks failed
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Failing after 20s
2023-06-14 19:16:23 +02:00
2cb652aee6 add metadata and registry push
Some checks failed
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Failing after 9s
2023-06-14 19:11:05 +02:00
034d14eb15 use a container with docker
All checks were successful
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Successful in 2m3s
2023-06-14 18:59:07 +02:00
c8bfc47ddf add docker login
Some checks failed
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Failing after 14s
2023-06-13 23:47:22 +02:00
b67982ed38 ls
Some checks failed
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Failing after 9s
2023-06-13 23:29:29 +02:00
e3144fc402 add checkout option 2023-06-13 23:29:03 +02:00
1970f4b0cb adjust docker build stage
Some checks failed
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Failing after 34s
2023-06-13 23:24:56 +02:00
8ac4f568a0 add on push
Some checks failed
Build a docker image for node-jellyfin-role-ot / build-docker-image (push) Failing after 41s
2023-06-13 21:51:26 +02:00
09f4efc96c change os 2023-06-13 21:50:21 +02:00
6e0c3b8ef6 add gitea cicd 2023-06-13 21:49:04 +02:00
8ee36f7510 add woodpecker integration 2023-06-13 20:31:33 +02:00
1593e126eb add docker build files 2023-06-13 20:31:19 +02:00
25 changed files with 936 additions and 944 deletions

View File

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

View File

@ -11,6 +11,7 @@ env:
jobs:
build-docker-image:
runs-on: ubuntu-latest
#if: gitea.ref == 'refs/heads/master'
container: catthehacker/ubuntu:act-latest
permissions:
contents: read
@ -21,8 +22,6 @@ jobs:
- 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" -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
run: docker build -t "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" .
- name: Push Container
run: docker push --all-tags "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"

View File

@ -5,8 +5,8 @@ import { JellyfinHandler } from "./server/jellyfin/handler"
import { attachedImages } from "./server/assets/attachments"
const requestId = 'startup'
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 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)

View File

@ -13,22 +13,22 @@ export default new Command({
options: [{
name: "typ",
type: ApplicationCommandOptionType.String,
description: "Was für ein announcement?",
choices: [{ name: "initial", value: "initial" }, { name: "votepls", value: "votepls" }, { name: "cancel", value: "cancel" }],
description:"Was für ein announcement?",
choices: [{name: "initial", value:"initial"},{name: "votepls", value:"votepls"},{name: "cancel", value:"cancel"}],
required: true
}],
run: async (interaction: RunOptions) => {
const command = interaction.interaction
const requestId = uuid()
if (!command.guildId) {
logger.error("COMMAND DOES NOT HAVE A GUILD ID; CANCELLING!!!", { requestId })
if(!command.guildId) {
logger.error("COMMAND DOES NOT HAVE A GUILD ID; CANCELLING!!!", {requestId})
return
}
const guildId = command.guildId
const announcementType = command.options.data.find(option => option.name.includes("typ"))
logger.info(`Got command for announcing ${announcementType?.value}!`, { guildId, requestId })
if (!announcementType) {
if(!announcementType) {
logger.error("Did not get an announcement type!", { guildId, requestId })
return
}
@ -40,7 +40,7 @@ export default new Command({
logger.info(`User ${command.member.displayName} seems to be admin`)
}
if ((<string>announcementType.value).includes("initial")) {
if((<string>announcementType.value).includes("initial")) {
sendInitialAnnouncement(guildId, requestId)
command.followUp("Ist rausgeschickt!")
} else {
@ -56,7 +56,7 @@ function isAdmin(member: GuildMember): boolean {
async function sendInitialAnnouncement(guildId: string, requestId: string): Promise<void> {
logger.info("Sending initial announcement")
const announcementChannel: Maybe<TextChannel> = client.getAnnouncementChannelForGuild(guildId)
if (!announcementChannel) {
if(!announcementChannel) {
logger.error("Could not find announcement channel. Aborting", { guildId, requestId })
return
}
@ -96,7 +96,7 @@ export async function manageAnnouncementRoles(guild: Guild, reaction: MessageRea
const allUsers = (await guild.members.fetch())
const usersWhoHaveRole: GuildMember[] = allUsers
.filter(member => member.roles.cache
.filter(member=> member.roles.cache
.find(role => role.id === config.bot.announcement_role) !== undefined)
.map(member => member)
@ -105,15 +105,15 @@ export async function manageAnnouncementRoles(guild: Guild, reaction: MessageRea
const usersWhoDontHaveRole: GuildMember[] = allUsers
.filter(member => member.roles.cache
.find(role => role.id === config.bot.announcement_role) === undefined)
.find(role=> role.id === config.bot.announcement_role) === undefined)
.map(member => member)
const usersWhoNeedRole: GuildMember[] = usersWhoDontHaveRole
.filter(userWhoNeeds => usersWhoWantRole.map(wanter => wanter.id).includes(userWhoNeeds.id))
logger.debug(`Theses users will get the role removed: ${JSON.stringify(usersWhoNeedRoleRevoked)}`, { guildId, requestId })
logger.debug(`Theses users will get the role added: ${JSON.stringify(usersWhoNeedRole)}`, { guildId, requestId })
logger.debug(`Theses users will get the role removed: ${JSON.stringify(usersWhoNeedRoleRevoked)}`, {guildId, requestId})
logger.debug(`Theses users will get the role added: ${JSON.stringify(usersWhoNeedRole)}`, {guildId, requestId})
usersWhoNeedRoleRevoked.forEach(user => user.roles.remove(announcementRole))
usersWhoNeedRole.forEach(user => user.roles.add(announcementRole))

View File

@ -20,7 +20,7 @@ export async function execute(event: GuildScheduledEvent) {
if (event.description.includes("!wp")) {
logger.info("Got manual create event of watchparty event!", { guildId, requestId })
if (event.description.includes("!private")) {
if(event.description.includes("!private")) {
logger.info("Event description contains \"!private\". Won't announce.", { guildId, requestId })
return
}

View File

@ -28,14 +28,14 @@ export async function execute(event: GuildScheduledEvent) {
logger.debug(`Movies: ${JSON.stringify(movies)}`, { guildId: event.guildId, requestId })
const announcementChannel: Maybe<TextChannel> = client.getAnnouncementChannelForGuild(event.guildId)
if (!announcementChannel) {
if(!announcementChannel) {
logger.error("Could not find announcement channel. Aborting", { guildId: event.guildId, requestId })
return
}
logger.debug(`Found channel ${JSON.stringify(announcementChannel, null, 2)}`, { guildId: event.guildId, requestId })
if (!event.scheduledStartAt) {
logger.info("EVENT DOES NOT HAVE STARTDATE; CANCELLING", { guildId: event.guildId, requestId })
if(!event.scheduledStartAt) {
logger.info("EVENT DOES NOT HAVE STARTDATE; CANCELLING", {guildId: event.guildId, requestId})
return
}
let message = `[Abstimmung] für https://discord.com/events/${event.guildId}/${event.id}\n<@&${config.bot.announcement_role}> Es gibt eine neue Abstimmung für die nächste Watchparty ${createDateStringFromEvent(event, event.guildId, requestId)}! Stimme hierunter für den nächsten Film ab!\n`
@ -46,7 +46,7 @@ export async function execute(event: GuildScheduledEvent) {
message = message.concat(NONE_OF_THAT).concat(": Wenn dir nichts davon gefällt.")
const options: MessageCreateOptions = {
allowedMentions: { parse: ["roles"] },
allowedMentions: { parse: ["roles"]},
content: message,
}

View File

@ -27,7 +27,7 @@ export async function execute(oldEvent: GuildScheduledEvent, newEvent: GuildSche
const wpAnnouncements = (await announcementChannel.messages.fetch()).filter(message => !message.cleanContent.includes("[initial]"))
const announcementsWithoutEvent = filterAnnouncementsByPendingWPs(wpAnnouncements, events)
logger.info(`Deleting ${announcementsWithoutEvent.length} announcements.`, { guildId, requestId })
logger.info(`Deleting ${announcementsWithoutEvent.length} announcements.`, {guildId, requestId})
announcementsWithoutEvent.forEach(message => message.delete())
}
} catch (error) {
@ -44,7 +44,7 @@ function filterAnnouncementsByPendingWPs(messages: Collection<string, Message<tr
foundEventForMessage = true
}
}
if (!foundEventForMessage) {
if(!foundEventForMessage){
filteredMessages.push(message)
}
}

View File

@ -12,7 +12,7 @@ export async function execute(oldState: VoiceState, newState: VoiceState) {
try {
logger.info(JSON.stringify(newState, null, 2))
//ignore events like mute/unmute
if (newState.channel?.id === oldState.channel?.id) {
if(newState.channel?.id === oldState.channel?.id) {
logger.info("Not handling VoiceState event because channelid of old and new was the same (i.e. mute/unmute event)")
return
}
@ -21,25 +21,25 @@ export async function execute(oldState: VoiceState, newState: VoiceState) {
.filter((key) => key.description?.toLowerCase().includes("!wp") && key.isActive())
.map((key) => key)
const scheduledEventUsers = (await Promise.all(scheduledEvents.map(event => event.fetchSubscribers({ withMember: true }))))
const scheduledEventUsers = (await Promise.all(scheduledEvents.map(event => event.fetchSubscribers({withMember: true}))))
//Dont handle users, that are already subscribed to the event. We only want to handle unsubscribed users here
let userFound = false;
scheduledEventUsers.forEach(collection => {
collection.each(key => {
logger.info(JSON.stringify(key, null, 2))
if (key.member.user.id === newState.member?.user.id)
if(key.member.user.id === newState.member?.user.id)
userFound = true;
})
})
if (userFound) {
if(userFound) {
logger.info(`Not handling VoiceState event because user was already subscribed and got an account from there. User: ${JSON.stringify(newState.member, null, 2)}`)
return
}
if (scheduledEvents.find(event => event.channelId === newState.channelId)) {
if (newState.member) {
if(newState.member){
logger.info("YO! Da ist jemand dem Channel mit dem Event beigetreten, ich kümmer mich mal um nen Account!")
const result = await jellyfinHandler.upsertUser(newState.member, "TEMPORARY", uuid())
if (result === UserUpsertResult.created) {
@ -53,7 +53,7 @@ export async function execute(oldState: VoiceState, newState: VoiceState) {
} else {
logger.info("VoiceState channelId was not the id of any channel with events")
}
} catch (error) {
}catch(error){
logger.error(error)
}
}

View File

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

View File

@ -64,7 +64,7 @@ export class JellyfinHandler {
logger.debug(JSON.stringify(req), { requestId, guildId })
const createResult = await this.userApi.createUserByName(req)
if (createResult) {
if (createResult.policy) {
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}"!`)
@ -74,8 +74,8 @@ export class JellyfinHandler {
}
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 })
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
@ -273,7 +273,7 @@ export class JellyfinHandler {
let movieCount = 0
let movieNames: string[]
do {
movieNames = (await this.getRandomMovies(count, guildId, requestId)).filter(movie => movie.name && movie.name.length > 0).map(movie => <string>movie.name)
movieNames = (await this.getRandomMovies(count, guildId, requestId)).filter(movie => movie.name && movie.name.length > 0).map(movie => <string> movie.name)
movieCount = movieNames.length
} while (movieCount < count)
return movieNames

View File

@ -29,7 +29,7 @@ export interface ConfigurationParameters {
}
export class Configuration {
constructor(private configuration: ConfigurationParameters = {}) { }
constructor(private configuration: ConfigurationParameters = {}) {}
set config(configuration: Configuration) {
this.configuration = configuration;
@ -393,7 +393,7 @@ export interface ResponseTransformer<T> {
}
export class JSONApiResponse<T> {
constructor(public raw: Response, private transformer: ResponseTransformer<T> = (jsonValue: any) => jsonValue) { }
constructor(public raw: Response, private transformer: ResponseTransformer<T> = (jsonValue: any) => jsonValue) {}
async value(): Promise<T> {
return this.transformer(await this.raw.json());
@ -401,7 +401,7 @@ export class JSONApiResponse<T> {
}
export class VoidApiResponse {
constructor(public raw: Response) { }
constructor(public raw: Response) {}
async value(): Promise<void> {
return undefined;
@ -409,7 +409,7 @@ export class VoidApiResponse {
}
export class BlobApiResponse {
constructor(public raw: Response) { }
constructor(public raw: Response) {}
async value(): Promise<Blob> {
return await this.raw.blob();
@ -417,7 +417,7 @@ export class BlobApiResponse {
}
export class TextApiResponse {
constructor(public raw: Response) { }
constructor(public raw: Response) {}
async value(): Promise<string> {
return await this.raw.text();

View File

@ -130,7 +130,7 @@ export class ExtendedClient extends Client {
for (const guild of guilds.values()) {
logger.info("Starting background task for announcement role", { guildId: guild.id })
const textChannel: Maybe<TextChannel> = this.getAnnouncementChannelForGuild(guild.id)
if (!textChannel) {
if(!textChannel) {
logger.error("Could not find announcement channel. Aborting", { guildId: guild.id })
return
}
@ -174,7 +174,7 @@ export class ExtendedClient extends Client {
}
private async startPollCloseBackgroundTasks() {
for (const guild of this.guilds.cache) {
for(const guild of this.guilds.cache) {
this.pollCloseBackgroundTasks.set(guild[1].id, schedule("0 * * * * *", () => checkForPollsToClose(guild[1])))
}
}