### Manage Anime Downloads with AnimeDownloadManager Source: https://context7.com/aniyomiorg/aniyomi/llms.txt This controller demonstrates how to interact with the AnimeDownloadManager to start, pause, and monitor episode downloads. It includes methods for queue reordering, checking download status, and handling file deletion. ```kotlin import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadManager import eu.kanade.tachiyomi.data.download.anime.model.AnimeDownload import tachiyomi.domain.entries.anime.model.Anime import tachiyomi.domain.items.episode.model.Episode class DownloadController( private val downloadManager: AnimeDownloadManager ) { fun startDownloads() = downloadManager.startDownloads() fun pauseDownloads() = downloadManager.pauseDownloads() fun clearQueue() = downloadManager.clearQueue() val isRunning: Boolean get() = downloadManager.isRunning fun downloadEpisodes(anime: Anime, episodes: List) { downloadManager.downloadEpisodes(anime = anime, episodes = episodes, autoStart = true, alt = false) } fun downloadNow(episodeId: Long) { downloadManager.startDownloadNow(episodeId) } fun isDownloaded(episodeName: String, scanlator: String?, animeTitle: String, sourceId: Long): Boolean { return downloadManager.isEpisodeDownloaded(episodeName, scanlator, animeTitle, sourceId) } fun deleteEpisodes(episodes: List, anime: Anime, source: AnimeSource) { downloadManager.deleteEpisodes(episodes, anime, source) } fun observeDownloadStatus() { viewModelScope.launch { downloadManager.statusFlow().collect { download -> when (download.status) { AnimeDownload.State.DOWNLOADING -> updateProgress(download) AnimeDownload.State.DOWNLOADED -> markComplete(download) AnimeDownload.State.ERROR -> handleError(download) else -> {} } } } } } ``` -------------------------------- ### Create Library Backups with BackupCreator in Kotlin Source: https://context7.com/aniyomiorg/aniyomi/llms.txt This Kotlin code demonstrates how to create full and minimal backups of library data using the BackupCreator class. It allows specifying various backup options and generates a backup file at a given URI. The BackupCreator also provides a utility to get a standardized backup filename. ```kotlin import eu.kanade.tachiyomi.data.backup.create.BackupCreator import eu.kanade.tachiyomi.data.backup.create.BackupOptions import android.net.Uri class BackupController(context: Context) { private val backupCreator = BackupCreator(context, isAutoBackup = false) // Create full backup suspend fun createFullBackup(uri: Uri): String { val options = BackupOptions( libraryEntries = true, categories = true, chapters = true, tracking = true, history = true, appSettings = true, sourceSettings = true, privateSettings = false, extensions = true, extensionRepoSettings = true, customButton = true, readEntries = true // Include read/watched but not favorited ) return backupCreator.backup(uri, options) } // Create minimal backup (library only) suspend fun createLibraryBackup(uri: Uri): String { val options = BackupOptions( libraryEntries = true, categories = true, chapters = true, tracking = true, history = false, appSettings = false, sourceSettings = false, privateSettings = false, extensions = false, extensionRepoSettings = false, customButton = false, readEntries = false ) return backupCreator.backup(uri, options) } // Get backup filename fun getBackupFilename(): String { return BackupCreator.getFilename() // Returns: "app.aniyomi_2024-01-15_14-30.tachibk" } } ``` -------------------------------- ### Initialize Episode Domain Model Source: https://context7.com/aniyomiorg/aniyomi/llms.txt Demonstrates the creation of an Episode object, tracking playback progress, filler status, and metadata for specific anime episodes. ```kotlin import tachiyomi.domain.items.episode.model.Episode val episode = Episode( id = 1L, animeId = 1L, seen = false, bookmark = false, fillermark = false, lastSecondSeen = 0L, totalSeconds = 1440L, dateFetch = System.currentTimeMillis(), sourceOrder = 1L, url = "/episode/1", name = "Episode 1: The Beginning", dateUpload = System.currentTimeMillis(), episodeNumber = 1.0, scanlator = "SubGroup", summary = "Our hero begins their journey...", previewUrl = "https://example.com/preview1.jpg", lastModifiedAt = System.currentTimeMillis(), version = 1L ) ``` -------------------------------- ### Manage Anime Library with AnimeLibraryScreenModel Source: https://context7.com/aniyomiorg/aniyomi/llms.txt Demonstrates how to observe library state, perform search queries, manage selection modes, and execute batch operations like downloading or marking episodes as seen. ```kotlin import eu.kanade.tachiyomi.ui.library.anime.AnimeLibraryScreenModel import eu.kanade.presentation.entries.DownloadAction class LibraryUsageExample { private val screenModel: AnimeLibraryScreenModel fun observeLibrary() { screenModel.state.collect { state -> val isLoading = state.isLoading val categories = state.categories val hasFilters = state.hasActiveFilters val isSelectionMode = state.selectionMode val items = state.getAnimelibItemsByCategoryId(categoryId) val pageItems = state.getAnimelibItemsByPage(pageIndex) val count = state.getAnimeCountForCategory(category) } } fun search(query: String?) { screenModel.search(query) } fun toggleSelection(anime: LibraryAnime) { screenModel.toggleSelection(anime) } fun downloadSelected(action: DownloadAction) { screenModel.runDownloadActionSelection(action) } fun markSelectedAsSeen(seen: Boolean) { screenModel.markSeenSelection(seen) } suspend fun getNextUnseen(anime: Anime): Episode? { return screenModel.getNextUnseenEpisode(anime) } } ``` -------------------------------- ### Initialize Anime Domain Model Source: https://context7.com/aniyomiorg/aniyomi/llms.txt Demonstrates how to instantiate an Anime data class with metadata, sorting flags, and update strategies. This model serves as the primary entity for anime entries within the library. ```kotlin import tachiyomi.domain.entries.anime.model.Anime import eu.kanade.tachiyomi.animesource.model.AnimeUpdateStrategy import eu.kanade.tachiyomi.animesource.model.FetchType val anime = Anime( id = 1L, source = 123456789L, favorite = true, lastUpdate = System.currentTimeMillis(), nextUpdate = System.currentTimeMillis() + 86400000, fetchInterval = 7, dateAdded = System.currentTimeMillis(), viewerFlags = 0L, episodeFlags = Anime.EPISODE_SORT_DESC or Anime.EPISODE_SHOW_UNSEEN, coverLastModified = 0L, backgroundLastModified = 0L, url = "/anime/my-anime", title = "My Anime Title", artist = "Studio Name", author = "Director Name", description = "An exciting anime about...", genre = listOf("Action", "Adventure", "Fantasy"), status = 1L, thumbnailUrl = "https://example.com/cover.jpg", backgroundUrl = null, updateStrategy = AnimeUpdateStrategy.ALWAYS_UPDATE, initialized = true, lastModifiedAt = System.currentTimeMillis(), favoriteModifiedAt = System.currentTimeMillis(), version = 1L, fetchType = FetchType.Episodes, parentId = null, seasonFlags = 0L, seasonNumber = -1.0, seasonSourceOrder = 0L ) ``` -------------------------------- ### Manage Tracker Integrations Source: https://context7.com/aniyomiorg/aniyomi/llms.txt Demonstrates how to interact with the TrackerManager to access, observe, and manage external tracking services like MyAnimeList, AniList, Kitsu, and Simkl. ```kotlin import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.data.track.Tracker class TrackingController(private val trackerManager: TrackerManager) { val myAnimeList = trackerManager.myAnimeList val aniList = trackerManager.aniList val kitsu = trackerManager.kitsu val simkl = trackerManager.simkl fun getLoggedInTrackers(): List = trackerManager.loggedInTrackers() fun observeTrackerLogins() { viewModelScope.launch { trackerManager.loggedInTrackersFlow().collect { trackers -> updateAvailableTrackers(trackers) } } } fun getTracker(trackerId: Long): Tracker? = trackerManager.get(trackerId) companion object { const val ANILIST_ID = TrackerManager.ANILIST const val KITSU_ID = TrackerManager.KITSU const val SIMKL_ID = TrackerManager.SIMKL } } ``` -------------------------------- ### Initialize Manga Domain Model Source: https://context7.com/aniyomiorg/aniyomi/llms.txt Shows the instantiation of a Manga data class, which includes properties for reading progress, chapter filtering, and display preferences. ```kotlin import tachiyomi.domain.entries.manga.model.Manga import eu.kanade.tachiyomi.source.model.UpdateStrategy val manga = Manga( id = 1L, source = 987654321L, favorite = true, lastUpdate = System.currentTimeMillis(), nextUpdate = System.currentTimeMillis() + 86400000, fetchInterval = 7, dateAdded = System.currentTimeMillis(), viewerFlags = 0L, chapterFlags = Manga.CHAPTER_SORT_DESC or Manga.CHAPTER_SHOW_UNREAD, coverLastModified = 0L, url = "/manga/my-manga", title = "My Manga Title", artist = "Artist Name", author = "Author Name", description = "A captivating manga about...", genre = listOf("Romance", "Drama", "Slice of Life"), status = 2L, thumbnailUrl = "https://example.com/manga-cover.jpg", updateStrategy = UpdateStrategy.ALWAYS_UPDATE, initialized = true, lastModifiedAt = System.currentTimeMillis(), favoriteModifiedAt = System.currentTimeMillis(), version = 1L ) ``` -------------------------------- ### Implementing a Custom AnimeSource in Kotlin Source: https://context7.com/aniyomiorg/aniyomi/llms.txt This snippet demonstrates how to implement the AnimeSource interface. It covers the mandatory overrides for metadata, episodes, seasons, hosters, and video resolution retrieval. ```kotlin import eu.kanade.tachiyomi.animesource.AnimeSource import eu.kanade.tachiyomi.animesource.model.SAnime import eu.kanade.tachiyomi.animesource.model.SEpisode import eu.kanade.tachiyomi.animesource.model.Video import eu.kanade.tachiyomi.animesource.model.Hoster class MyAnimeSource : AnimeSource { override val id: Long = 1234567890L override val name: String = "My Anime Source" override val lang: String = "en" override suspend fun getAnimeDetails(anime: SAnime): SAnime { return anime.apply { title = "Fetched Title" description = "Updated description" genre = "Action, Adventure" status = SAnime.ONGOING thumbnail_url = "https://example.com/thumb.jpg" } } override suspend fun getEpisodeList(anime: SAnime): List { return listOf( SEpisode.create().apply { url = "/episode/1" name = "Episode 1" episode_number = 1f date_upload = System.currentTimeMillis() }, SEpisode.create().apply { url = "/episode/2" name = "Episode 2" episode_number = 2f } ) } override suspend fun getSeasonList(anime: SAnime): List { return listOf( SAnime.create().apply { url = "/anime/show/season-1" title = "Season 1" }, SAnime.create().apply { url = "/anime/show/season-2" title = "Season 2" } ) } override suspend fun getHosterList(episode: SEpisode): List { return listOf( Hoster("StreamServer1", "https://stream1.example.com/ep1"), Hoster("StreamServer2", "https://stream2.example.com/ep1") ) } override suspend fun getVideoList(hoster: Hoster): List