<commit_before>package com.github.bjoernpetersen.jmusicbot;

import com.github.bjoernpetersen.jmusicbot.Plugin.State;
import com.github.bjoernpetersen.jmusicbot.config.Config;
import com.github.bjoernpetersen.jmusicbot.playback.Player;
import com.github.bjoernpetersen.jmusicbot.playback.QueueChangeListener;
import com.github.bjoernpetersen.jmusicbot.playback.QueueEntry;
import com.github.bjoernpetersen.jmusicbot.playback.SongEntry;
import com.github.bjoernpetersen.jmusicbot.provider.Provider;
import com.github.bjoernpetersen.jmusicbot.provider.ProviderManager;
import com.github.bjoernpetersen.jmusicbot.provider.Suggester;
import com.github.bjoernpetersen.jmusicbot.user.UserManager;
import com.github.zafarkhaja.semver.ParseException;
import com.github.zafarkhaja.semver.Version;
import com.google.common.annotations.VisibleForTesting;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.StringJoiner;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

@Nonnull
public final class MusicBot implements Loggable, Closeable {

  private static final int PORT = 42945;
  private static final String GROUP_ADDRESS = "172.16.31.10";

  private final Config config;
  private final Player player;
  private final PlaybackFactoryManager playbackFactoryManager;
  private final ProviderManager providerManager;
  private final UserManager userManager;
  private final Closeable restApi;
  private final Closeable broadcaster;
  private final Set<AdminPlugin> adminPlugins;

  private MusicBot(@Nonnull Config config, @Nonnull InitStateWriter initStateWriter,
      @Nonnull PlaybackFactoryManager playbackFactoryManager,
      @Nonnull ProviderManager providerManager, @Nullable Suggester defaultSuggester,
      @Nonnull UserManager userManager, @Nonnull ApiInitializer apiInitializer,
      @Nonnull BroadcasterInitializer broadcasterInitializer,
      @Nonnull Set<AdminPlugin> adminPlugins)
      throws InitializationException {
    this.config = config;
    this.playbackFactoryManager = playbackFactoryManager;
    this.providerManager = providerManager;
    this.userManager = userManager;

    List<Closeable> initialized = new ArrayList<>();
    initialized.add(playbackFactoryManager);
    initialized.add(providerManager);
    initialized.add(userManager);

    if (defaultSuggester != null
        && providerManager.getWrapper(defaultSuggester).getState() != State.ACTIVE) {
      initStateWriter.warning("Default suggester is not active.");
      defaultSuggester = null;
    }

    try {
      checkSanity(providerManager);
    } catch (InitializationException e) {
      closeAll(e, initialized);
      throw e;
    }

    Consumer<SongEntry> songPlayedNotifier = songEntry -> {
      Song song = songEntry.getSong();
      Provider provider = song.getProvider();
      for (Suggester suggester : providerManager.getSuggesters(provider)) {
        suggester.notifyPlayed(songEntry);
      }
    };

    try {
      this.player = new Player(songPlayedNotifier, defaultSuggester);
      initialized.add(this.player);
    } catch (RuntimeException e) {
      closeAll(e, initialized);
      throw new InitializationException("Exception during player init", e);
    }
    this.player.getQueue().addListener(new QueueChangeListener() {
      @Override
      public void onAdd(@Nonnull QueueEntry entry) {
        Song song = entry.getSong();
        Provider provider = song.getProvider();
        for (Suggester suggester : providerManager.getSuggesters(provider)) {
          suggester.removeSuggestion(song);
        }
      }

      @Override
      public void onRemove(@Nonnull QueueEntry entry) {
      }

      @Override
      public void onMove(@Nonnull QueueEntry entry, int fromIndex, int toIndex) {
      }
    });

    try {
      this.restApi = apiInitializer.initialize(this, PORT);
      initialized.add(this.restApi);
    } catch (InitializationException e) {
      closeAll(e, initialized);
      throw new InitializationException("Exception during REST init", e);
    }

    try {
      this.broadcaster = broadcasterInitializer.initialize(
          PORT,
          GROUP_ADDRESS,
          PORT + ";1.0"
      );
      initialized.add(this.broadcaster);
    } catch (InitializationException e) {
      closeAll(e, initialized);
      throw new InitializationException("Exception during broadcaster init", e);
    }

    this.adminPlugins = adminPlugins;
    try {
      for (AdminPlugin plugin : adminPlugins) {
        plugin.initialize(initStateWriter, this);
        initialized.add(plugin);
      }
    } catch (InitializationException e) {
      closeAll(e, initialized);
      throw new InitializationException("Exception during admin plugin init", e);
    }
  }

  private void checkSanity(@Nonnull ProviderManager providerManager)
      throws InitializationException {
    if (providerManager.getProviders().count() == 0) {
      throw new InitializationException("There are no active providers. This setup is useless.");
    }
  }

  private void closeAll(Exception cause, List<Closeable> toClose) {
    for (Closeable closeable : toClose) {<commit_msg>Add broadcast ID to UDP message<commit_after>package com.github.bjoernpetersen.jmusicbot;

import com.github.bjoernpetersen.jmusicbot.Plugin.State;
import com.github.bjoernpetersen.jmusicbot.config.Config;
import com.github.bjoernpetersen.jmusicbot.playback.Player;
import com.github.bjoernpetersen.jmusicbot.playback.QueueChangeListener;
import com.github.bjoernpetersen.jmusicbot.playback.QueueEntry;
import com.github.bjoernpetersen.jmusicbot.playback.SongEntry;
import com.github.bjoernpetersen.jmusicbot.provider.Provider;
import com.github.bjoernpetersen.jmusicbot.provider.ProviderManager;
import com.github.bjoernpetersen.jmusicbot.provider.Suggester;
import com.github.bjoernpetersen.jmusicbot.user.UserManager;
import com.github.zafarkhaja.semver.ParseException;
import com.github.zafarkhaja.semver.Version;
import com.google.common.annotations.VisibleForTesting;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.StringJoiner;
import java.util.function.Consumer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

@Nonnull
public final class MusicBot implements Loggable, Closeable {

  private static final String BROADCAST_ID = "MusicBot";
  private static final int PORT = 42945;
  private static final String GROUP_ADDRESS = "172.16.31.10";

  private final Config config;
  private final Player player;
  private final PlaybackFactoryManager playbackFactoryManager;
  private final ProviderManager providerManager;
  private final UserManager userManager;
  private final Closeable restApi;
  private final Closeable broadcaster;
  private final Set<AdminPlugin> adminPlugins;

  private MusicBot(@Nonnull Config config, @Nonnull InitStateWriter initStateWriter,
      @Nonnull PlaybackFactoryManager playbackFactoryManager,
      @Nonnull ProviderManager providerManager, @Nullable Suggester defaultSuggester,
      @Nonnull UserManager userManager, @Nonnull ApiInitializer apiInitializer,
      @Nonnull BroadcasterInitializer broadcasterInitializer,
      @Nonnull Set<AdminPlugin> adminPlugins)
      throws InitializationException {
    this.config = config;
    this.playbackFactoryManager = playbackFactoryManager;
    this.providerManager = providerManager;
    this.userManager = userManager;

    List<Closeable> initialized = new ArrayList<>();
    initialized.add(playbackFactoryManager);
    initialized.add(providerManager);
    initialized.add(userManager);

    if (defaultSuggester != null
        && providerManager.getWrapper(defaultSuggester).getState() != State.ACTIVE) {
      initStateWriter.warning("Default suggester is not active.");
      defaultSuggester = null;
    }

    try {
      checkSanity(providerManager);
    } catch (InitializationException e) {
      closeAll(e, initialized);
      throw e;
    }

    Consumer<SongEntry> songPlayedNotifier = songEntry -> {
      Song song = songEntry.getSong();
      Provider provider = song.getProvider();
      for (Suggester suggester : providerManager.getSuggesters(provider)) {
        suggester.notifyPlayed(songEntry);
      }
    };

    try {
      this.player = new Player(songPlayedNotifier, defaultSuggester);
      initialized.add(this.player);
    } catch (RuntimeException e) {
      closeAll(e, initialized);
      throw new InitializationException("Exception during player init", e);
    }
    this.player.getQueue().addListener(new QueueChangeListener() {
      @Override
      public void onAdd(@Nonnull QueueEntry entry) {
        Song song = entry.getSong();
        Provider provider = song.getProvider();
        for (Suggester suggester : providerManager.getSuggesters(provider)) {
          suggester.removeSuggestion(song);
        }
      }

      @Override
      public void onRemove(@Nonnull QueueEntry entry) {
      }

      @Override
      public void onMove(@Nonnull QueueEntry entry, int fromIndex, int toIndex) {
      }
    });

    try {
      this.restApi = apiInitializer.initialize(this, PORT);
      initialized.add(this.restApi);
    } catch (InitializationException e) {
      closeAll(e, initialized);
      throw new InitializationException("Exception during REST init", e);
    }

    try {
      this.broadcaster = broadcasterInitializer.initialize(
          PORT,
          GROUP_ADDRESS,
          BROADCAST_ID + ';' + PORT + ';' + getVersion().toString()
      );
      initialized.add(this.broadcaster);
    } catch (InitializationException e) {
      closeAll(e, initialized);
      throw new InitializationException("Exception during broadcaster init", e);
    }

    this.adminPlugins = adminPlugins;
    try {
      for (AdminPlugin plugin : adminPlugins) {
        plugin.initialize(initStateWriter, this);
        initialized.add(plugin);
      }
    } catch (InitializationException e) {
      closeAll(e, initialized);
      throw new InitializationException("Exception during admin plugin init", e);
    }
  }

  private void checkSanity(@Nonnull ProviderManager providerManager)
      throws InitializationException {
    if (providerManager.getProviders().count() == 0) {
      throw new InitializationException("There are no active providers. This setup is useless.");
    }
  }

  private void closeAll(Exception cause, List<Closeable> toClose) {
    for (Closeable closeable : toClose) {
{'fraction_non_alphanumeric': 0.09005216436350325, 'fraction_numerical': 0.002928525670357829, 'mean_word_length': 3.9605083976395825, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '677644', 'n_tokens_mistral': 3167, 'n_tokens_neox': 3037, 'n_words': 680}