package com.torrenttunes.server.db; import static com.torrenttunes.client.db.Tables.SETTINGS; import static com.torrenttunes.server.db.Tables.*; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.NoSuchFileException; import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.NoSuchElementException; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.codehaus.jackson.JsonNode; import org.javalite.activejdbc.DBException; import org.javalite.activejdbc.Model; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.frostwire.jlibtorrent.TorrentHandle; import com.frostwire.jlibtorrent.TorrentInfo; import com.musicbrainz.mp3.tagger.Tools.Artist.Tag; import com.musicbrainz.mp3.tagger.Tools.CoverArt; import com.musicbrainz.mp3.tagger.Tools.Song.MusicBrainzRecordingQuery; import com.torrenttunes.client.LibtorrentEngine; import com.torrenttunes.server.DataSources; import com.torrenttunes.server.db.Tables.ReleaseGroup; import com.torrenttunes.server.db.Tables.Song; import com.torrenttunes.server.tools.Tools; public class Actions { static final Logger log = LoggerFactory.getLogger(Actions.class); public static void saveTorrentToDB(File torrentFile, String infoHash) { try { log.info("Saving " + torrentFile.getName() + " to the DB"); // First get the MBID from the filename String mbid = torrentFile.getName().split("_sha2")[0].split("mbid-")[1]; // Save the song Song song = SONG.create("torrent_path", torrentFile.getAbsolutePath(), "info_hash", infoHash, "mbid", mbid); Boolean success = song.saveIt(); } catch(DBException e) { if (e.getMessage().contains("MySQLIntegrityConstraintViolationException")) { log.error("Not adding " + torrentFile.getName() + ", Song was already in the DB"); } else { e.printStackTrace(); } } catch(ArrayIndexOutOfBoundsException e2) { log.error("Filename was too long"); } } public static void updateSongInfo(JsonNode json) { // Get the variables String songMbid = json.get("recordingMBID").asText(); String title = json.get("recording").asText(); String artist = json.get("artist").asText(); String artistMbid = json.get("artistMBID").asText(); Long durationMS = json.get("duration").asLong(); String ipHash = json.get("uploader_ip_hash").asText(); log.info("Updating song info for song: " + title + " , mbid: " + songMbid); // Find it by the MBID Tools.dbInit(); Song song = SONG.findFirst("mbid = ?", songMbid); song.set("title", title, "duration_ms", durationMS, "uploader_ip_hash", ipHash).saveIt(); Tools.dbClose(); log.info("New song: " + title + " updated"); createArtist(artist, artistMbid); createSongReleaseGroups(json, songMbid, artistMbid); } private static void createSongReleaseGroups(JsonNode json, String songMbid, String artistMbid) { // Loop over every album found, necessary for release_groups and tracks int i = 0; JsonNode releaseGroupInfos = json.get("releaseGroupInfos"); while (releaseGroupInfos.has(i)) { JsonNode cReleaseGroupInfo = releaseGroupInfos.get(i++); String albumMbid = cReleaseGroupInfo.get("mbid").asText(); Integer discNo = cReleaseGroupInfo.get("discNo").asInt(); Integer trackNo = cReleaseGroupInfo.get("trackNo").asInt(); String primaryType = cReleaseGroupInfo.get("primaryType").asText(); JsonNode secondaryTypesJson = cReleaseGroupInfo.get("secondaryTypes"); String secondaryTypes = null; if (secondaryTypesJson.isArray()) { secondaryTypes = ""; int j = 0; while (secondaryTypesJson.has(j)) { secondaryTypes += secondaryTypesJson.get(j++).asText(); } } log.info("secondary types = " + secondaryTypes); createReleaseGroups(artistMbid, albumMbid, primaryType, secondaryTypes); // Now that both the song and release_group are made, add the song_release_group // row that links them together try { Tools.dbInit(); SONG_RELEASE_GROUP.createIt("song_mbid", songMbid, "release_group_mbid", albumMbid, "disc_number", discNo, "track_number", trackNo); log.info("Song release group:" + songMbid, " created"); } catch(DBException e) { log.error("That song release group row already exists"); } finally { Tools.dbClose(); } } } private static void createReleaseGroups(String artistMbid, String albumMbid, String primaryType, String secondaryTypes) { Tools.dbInit(); ReleaseGroup releaseRow = RELEASE_GROUP.findFirst("mbid = ?" , albumMbid); Tools.dbClose(); // If the album doesn't exist, create the row if (releaseRow == null) { log.info("new album"); // Fetch some links and images from musicbrainz com.musicbrainz.mp3.tagger.Tools.ReleaseGroup mbInfo = com.musicbrainz.mp3.tagger.Tools.ReleaseGroup.fetchReleaseGroup(albumMbid); // Fetch the coverart String coverArtURL = null, coverArtLargeThumbnail = null, coverArtSmallThumbnail = null; try { CoverArt coverArt = CoverArt.fetchCoverArt(albumMbid); coverArtURL = coverArt.getImageURL(); coverArtLargeThumbnail = coverArt.getLargeThumbnailURL(); coverArtSmallThumbnail = coverArt.getSmallThumbnailURL(); } catch(NoSuchElementException e) { e.printStackTrace(); } Tools.dbInit(); releaseRow = RELEASE_GROUP.createIt("mbid", albumMbid, "title", mbInfo.getTitle(), "artist_mbid", artistMbid, "year", mbInfo.getYear(), "wikipedia_link", mbInfo.getWikipedia(), "allmusic_link", mbInfo.getAllMusic(), "official_homepage", mbInfo.getOfficialHomepage(), "lyrics", mbInfo.getLyrics(), "album_coverart_url", coverArtURL, "album_coverart_thumbnail_large", coverArtLargeThumbnail, "album_coverart_thumbnail_small", coverArtSmallThumbnail, "primary_type", primaryType, "secondary_types", secondaryTypes); Tools.dbClose(); log.info("New album: " + mbInfo.getTitle() + " created"); } } private static void createArtist(String artist, String artistMbid) { // First, check to see if the album or artist need to be created: Tools.dbInit(); Artist artistRow = ARTIST.findFirst("mbid = ?", artistMbid); Tools.dbClose(); if (artistRow == null) { log.info("new artist"); // Fetch some links and images from musicbrainz com.musicbrainz.mp3.tagger.Tools.Artist mbInfo = com.musicbrainz.mp3.tagger.Tools.Artist.fetchArtist(artistMbid); // Fetch the images String imageURL = null; if (mbInfo.getWikipedia() != null) { try { imageURL = Tools.getImageFromWikipedia(mbInfo.getWikipedia()); log.info("found wikipedia image"); } catch(NullPointerException e) { e.printStackTrace(); } } // Fetch and create the tags // Check to see if there are any tagInfos for that artist in the db, or any from musicBrainz Tools.dbInit(); artistRow = ARTIST.createIt("mbid", artistMbid, "name", artist, "image_url", imageURL, "wikipedia_link", mbInfo.getWikipedia(), "allmusic_link", mbInfo.getAllMusic(), "official_homepage", mbInfo.getOfficialHomepage(), "imdb", mbInfo.getIMDB(), "lyrics", mbInfo.getLyrics(), "youtube", mbInfo.getYoutube(), "soundcloud", mbInfo.getSoundCloud(), "lastfm", mbInfo.getLastFM()); createTags(artistMbid, mbInfo); Tools.dbClose(); log.info("New artist: " + artist + " created"); } } private static void createTags(String artistMbid, com.musicbrainz.mp3.tagger.Tools.Artist mbInfo) { TagInfo ti = TAG_INFO.findFirst("artist_mbid = ?", artistMbid); // Delete all of that artists tag infos if they do exist if (ti != null) { TAG_INFO.delete("artist_mbid = ?", artistMbid); } if (mbInfo.getTags() != null) { for (Tag mbInfoTag : mbInfo.getTags()) { com.torrenttunes.server.db.Tables.Tag tagRow = TAG.findFirst("name = ?", mbInfoTag.getName()); // if that tag doesn't exist, create it if (tagRow == null) { tagRow = TAG.createIt("name", mbInfoTag.getName()); } // create the tag_info ti = TAG_INFO.createIt("artist_mbid", artistMbid, "count", mbInfoTag.getCount(), "tag_id", tagRow.getInteger("id")); log.info("Added tag " + mbInfoTag.getName() + " for artist " + artistMbid); } } } public static void refetchTags() { List<Artist> artists = ARTIST.findAll(); for (Artist cArtist : artists) { String artistMbid = cArtist.getString("mbid"); // Fetch some links and images from musicbrainz com.musicbrainz.mp3.tagger.Tools.Artist mbInfo = com.musicbrainz.mp3.tagger.Tools.Artist.fetchArtist(artistMbid); createTags(artistMbid, mbInfo); } } public static void refetchAlbumArt() { List<ReleaseGroup> albums = RELEASE_GROUP.findAll(); for (ReleaseGroup cAlbum : albums) { String albumMbid = cAlbum.getString("mbid"); String albumTitle = cAlbum.getString("title"); if (cAlbum.getString("album_coverart_url") == null) { log.info("no cover art found, refetching for album: " + albumTitle + " , mbid: " + albumMbid); // Fetch the coverart String coverArtURL = null, coverArtLargeThumbnail = null, coverArtSmallThumbnail = null; try { CoverArt coverArt = CoverArt.fetchCoverArt(albumMbid); coverArtURL = coverArt.getImageURL(); coverArtLargeThumbnail = coverArt.getLargeThumbnailURL(); coverArtSmallThumbnail = coverArt.getSmallThumbnailURL(); } catch(NoSuchElementException e) { e.printStackTrace(); continue; } RELEASE_GROUP.update( // Updates "album_coverart_url = ?, album_coverart_thumbnail_large = ?, album_coverart_thumbnail_small = ?", // Conditions "mbid = ?", coverArtURL, coverArtLargeThumbnail, coverArtSmallThumbnail, albumMbid); } } } public static void addToPlayCount(String infoHash) { // SONG.update("plays = plays + ?", "info_hash = ?", 1, infoHash); Song s = SONG.findFirst("info_hash = ?", infoHash); s.set("plays", s.getInteger("plays") + 1); s.saveIt(); } public static void addToTimeoutCount(String infoHash) { // SONG.update("plays = plays + ?", "info_hash = ?", 1, infoHash); Song s = SONG.findFirst("info_hash = ?", infoHash); s.set("timeouts", s.getInteger("timeouts") + 1); s.saveIt(); } public static void updateSeeders(String infoHash, String seeders) { Song song = SONG.findFirst("info_hash = ?", infoHash); song.set("seeders", seeders); song.saveIt(); } public static void removeArtist(String artistMBID) { // First delete/remove it from the libtorrent session // First find everything that needs to be deleted, in the DB // Set<String> songMbids = new HashSet<String>(); // List<SongView> svs = SONG_VIEW.find("artist_mbid = ?", artistMBID); // // for (SongView sv : svs) { // songMbids.add(sv.getString("song_mbid")); // } // SONG_VIEW.dele // get release groups List<ReleaseGroup> rgs = RELEASE_GROUP.find("artist_mbid = ?", artistMBID); // Get songs Set<SongReleaseGroup> srgs = new HashSet<>(); for (ReleaseGroup rg : rgs) { List<SongReleaseGroup> srg = SONG_RELEASE_GROUP.find("release_group_mbid = ?", rg.getString("mbid")); srgs.addAll(srg); } for (ReleaseGroup rg : rgs) { SONG_RELEASE_GROUP.delete("release_group_mbid = ?", rg.getString("mbid")); } // Delete from songs to artist for (SongReleaseGroup srg : srgs) { log.info(srg.toString()); Song song = SONG.findFirst("mbid = ?", srg.getString("song_mbid")); if (song != null) { log.info(song.toString()); log.info("path name: " + song.getString("torrent_path")); // Delete the torrent file from the server: File torrentFile = new File(song.getString("torrent_path")); if (torrentFile.exists()) torrentFile.delete(); SONG.delete("mbid = ?", srg.getString("song_mbid")); } } RELEASE_GROUP.delete("artist_mbid = ?", artistMBID); TAG_INFO.delete("artist_mbid = ?", artistMBID); ARTIST.delete("mbid = ?", artistMBID); com.torrenttunes.client.tools.Tools.dbInit(); com.torrenttunes.client.db.Actions.removeArtist(artistMBID); com.torrenttunes.client.tools.Tools.dbClose(); } public static void removeSong(String songMBID) { // Remove the song release groups SONG_RELEASE_GROUP.delete("song_mbid = ?", songMBID); Song song = SONG.findFirst("mbid = ?", songMBID); // Delete the torrent file from the server: File torrentFile = new File(song.getString("torrent_path")); if (torrentFile.exists()) torrentFile.delete(); SONG.delete("mbid = ?", songMBID); com.torrenttunes.client.tools.Tools.dbInit(); com.torrenttunes.client.db.Actions.removeSong(songMBID); com.torrenttunes.client.tools.Tools.dbClose(); } public static void saveTorrentFileToDB(File f) { try { // infoHash = Torrent.load(f).getHexInfoHash().toLowerCase(); byte[] fileBytes = java.nio.file.Files.readAllBytes(Paths.get(f.getAbsolutePath())); TorrentInfo ti = TorrentInfo.bdecode(fileBytes); String infoHash = ti.getInfoHash().toHex().toLowerCase(); Tools.dbInit(); Actions.saveTorrentToDB(f, infoHash); Tools.dbClose(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static File createArtistDiscographyZipFile(String artistMbid) { // Get the artist songs List<SongViewGrouped> songs = SONG_VIEW_GROUPED.find("artist_mbid = ?", artistMbid). orderBy("torrent_path"); String zipFileName = songs.get(0).getString("artist") + "_torrents_discography.ZIP"; log.info("Wrote a discography file for artist_mbid: " + artistMbid); return createZipOfSongs(songs, zipFileName); } public static File createAlbumZipFile(String albumMbid) { // Get the artist songs List<SongView> songs = SONG_VIEW.find("release_group_mbid = ?", albumMbid). orderBy("torrent_path"); String zipFileName = songs.get(0).getString("album") + "_torrents.ZIP"; log.info("Wrote a Zip file for album mbid: " + albumMbid); return createZipOfSongs(songs, zipFileName); } public static <T extends Model> File createZipOfSongs(List<T> songs, String zipFileName) { try { File zipFile = new File(DataSources.TORRENTS_DIR() + "/" + zipFileName); ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(zipFile)); for (Model song : songs) { try { File torrentFile = new File(song.getString("torrent_path")); ZipEntry e = new ZipEntry(torrentFile.getName()); zout.putNextEntry(e); byte[] torrentBytes = java.nio.file.Files.readAllBytes(Paths.get(torrentFile.getAbsolutePath())); zout.write(torrentBytes, 0, torrentBytes.length); zout.closeEntry(); } catch(NoSuchFileException e) { log.error("Couldn't find torrent file, skipping: " + song.getString("torrent_path")); } } zout.close(); return zipFile; } catch (IOException e1) { e1.printStackTrace(); } return null; } public static String getSongMagnetLink(String songMbid) { Song song = SONG.findFirst("mbid = ?", songMbid); String infoHash = song.getString("info_hash"); TorrentHandle th = LibtorrentEngine.INSTANCE.getInfoHashToTorrentMap().get(infoHash); return th.makeMagnetUri(); } public static void refetchTitles() { // Go through the artist, album, and song tables, refetching all the titles Tools.dbInit(); List<Artist> artists = ARTIST.find("name like ?", "%�%"); for (Artist artist : artists) { String mbid = artist.getString("mbid"); String name = com.musicbrainz.mp3.tagger.Tools.Artist.fetchArtist(mbid).getName(); artist.update("name = ?", "mbid = ?", name, mbid); log.info("Updated artist name in DB: " + name); } List<ReleaseGroup> rgs = RELEASE_GROUP.find("title like ?", "%�%"); for (ReleaseGroup rg : rgs) { String mbid = rg.getString("mbid"); String title = com.musicbrainz.mp3.tagger.Tools.ReleaseGroup.fetchReleaseGroup(mbid).getTitle(); rg.update("title = ?", "mbid = ?", title, mbid); log.info("Updated release group title in DB: " + title); } List<Song> songs = SONG.find("title like ?", "%�%"); for (Song song : songs) { String mbid = song.getString("mbid"); String title = com.musicbrainz.mp3.tagger.Tools.SongMBID.fetchSong(mbid).getRecording(); song.set("title", title).saveIt(); log.info("Updated song title in DB: " + title); } Tools.dbClose(); } }