Exemple #1
0
        private void ScanForSpeakerInfo(SubscriptionInfo subscriptionInfo, string recordingsFolder, bool restricted, int progressFrom, int progressTo)
        {
            ILookup <string, DirectoryInfoBase> directories = _fileSystem.DirectoryInfo.FromDirectoryName(recordingsFolder)
                                                              .GetDirectories("*", SearchOption.AllDirectories)
                                                              .ToLookup(d => d.Name);

            using (IDbConnection db = _dbConnectionFactory.Open())
                using (IDbTransaction transaction = db.OpenTransaction())
                {
                    List <DbSpeaker> speakers = db.Select <DbSpeaker>();
                    for (int index = 0; index < speakers.Count; index++)
                    {
                        DbSpeaker speaker = speakers[index];

                        string fullName = speaker.ToSpeaker().FullName;
                        if (directories.Contains(fullName))
                        {
                            FileInfoBase photo = directories[fullName]
                                                 .SelectMany(d => d.GetFiles("*.jpg"))
                                                 .OrderByDescending(f => f.Length)
                                                 .FirstOrDefault();

                            if (photo != null)
                            {
                                speaker.PhotoPath = photo.FullName;
                                db.Update(speaker);
                            }

                            FileInfoBase markdownFile = directories[fullName]
                                                        .SelectMany(d => d.GetFiles("*.md"))
                                                        .OrderByDescending(f => f.Length)
                                                        .FirstOrDefault();

                            if (markdownFile != null)
                            {
                                string markdownText = _fileSystem.File.ReadAllText(markdownFile.FullName);
                                speaker.Description = new Markdown().Transform(markdownText);
                            }

                            if (markdownFile != null || photo != null)
                            {
                                db.Update(speaker);
                            }
                        }

                        PublishProgress(subscriptionInfo, (progressTo - progressFrom) * (index / speakers.Count));
                    }

                    transaction.Commit();
                }
        }
Exemple #2
0
        private void RebuildFromFolder(SubscriptionInfo subscriptionInfo, string folderPath, bool restricted, int startPercent = 0, int endPercent = 100)
        {
            if (folderPath == null)
            {
                throw new ArgumentNullException(nameof(folderPath));
            }

            using (IDbConnection db = _dbConnectionFactory.Open())
            {
                DirectoryInfoBase directoryInfo = _fileSystem.DirectoryInfo.FromDirectoryName(folderPath);
                FileInfoBase[]    files         = directoryInfo.GetFiles("*.mp3", SearchOption.AllDirectories);

                int index = 0;
                foreach (IGrouping <string, FileInfoBase> albumFiles in files.GroupBy(f => f.DirectoryName))
                {
                    using (IDbTransaction transaction = db.OpenTransaction())
                    {
                        _logger.Debug("Fetching album");
                        DbAlbum album = db.Single <DbAlbum>(a => a.Path == albumFiles.Key);

                        foreach (FileInfoBase file in albumFiles)
                        {
                            int progress =
                                (int)Math.Round((index + 1) / (double)files.Length * (endPercent - startPercent)) +
                                startPercent;
                            PublishProgress(subscriptionInfo, progress);
                            _logger.DebugFormat("Processing file {0}", file.FullName);
                            DbRecording recording;

                            bool saveTagFile = false;

                            _logger.Debug("Reading tag file");
                            using (File tagFile = File.Create(_fileAbstractionFactory(file.FullName, true)))
                            {
                                string recordingId = tagFile.GetCustomField(SoundWordsRecordingIdField);
                                if (recordingId != null)
                                {
                                    _logger.Debug("Fetching recording");
                                    recording = db.Single <DbRecording>(r => r.Uid == recordingId) ?? new DbRecording {
                                        Uid = recordingId
                                    };
                                }
                                else
                                {
                                    recording = new DbRecording {
                                        Uid = Guid.NewGuid().ToString("N")
                                    };
                                    saveTagFile = true;
                                    tagFile.SetCustomField(SoundWordsRecordingIdField, recording.Uid);
                                }

                                if (album == null)
                                {
                                    string uid = tagFile.GetCustomField(SoundWordsAlbumIdField) ?? Guid.NewGuid().ToString("N");

                                    album = new DbAlbum
                                    {
                                        Uid        = uid,
                                        Name       = (tagFile.Tag.Album ?? "Ukjent").Trim(),
                                        Path       = albumFiles.Key,
                                        Restricted = restricted
                                    };
                                }

                                UpdateAttachments(albumFiles.Key, album);

                                if (album.Id != 0)
                                {
                                    _logger.Debug("Saving album");
                                    db.Update(album);
                                }
                                else
                                {
                                    _logger.Debug("Creating album");
                                    album.Id = db.Insert(album, true);
                                }

                                if (tagFile.GetCustomField(SoundWordsAlbumIdField) != album.Uid)
                                {
                                    tagFile.SetCustomField(SoundWordsAlbumIdField, album.Uid);
                                    saveTagFile = true;
                                }

                                recording.AlbumId    = album.Id;
                                recording.Title      = (tagFile.Tag.Title ?? "Ukjent").Trim();
                                recording.Track      = (ushort)tagFile.Tag.Track;
                                recording.Comment    = tagFile.Tag.Comment;
                                recording.Year       = tagFile.Tag.Year != 0 ? (ushort?)tagFile.Tag.Year : null;
                                recording.Path       = file.FullName;
                                recording.Restricted = restricted;

                                if (recording.Id == 0)
                                {
                                    _logger.DebugFormat("Creating recording: {0}", recording.Dump());
                                    recording.Id = db.Insert(recording, true);
                                }
                                else
                                {
                                    _logger.DebugFormat("Saving recording: {0}", recording.Dump());
                                    db.Update(recording);
                                }

                                db.Delete <DbRecordingSpeaker>(rs => rs.RecordingId == recording.Id);

                                foreach (string performer in tagFile.Tag.Performers)
                                {
                                    _logger.DebugFormat($"Creating speaker {performer}");
                                    NameInfo  nameInfo = performer.ToNameInfo();
                                    DbSpeaker speaker  = db.Single <DbSpeaker>(s =>
                                                                               s.FirstName == nameInfo.FirstName && s.LastName == nameInfo.LastName);

                                    if (speaker == null)
                                    {
                                        speaker = new DbSpeaker
                                        {
                                            Uid       = Guid.NewGuid().ToString("N"),
                                            FirstName = nameInfo.FirstName,
                                            LastName  = nameInfo.LastName
                                        };

                                        speaker.Id = db.Insert(speaker, true);
                                    }

                                    if (!db.Exists <DbRecordingSpeaker>(rs =>
                                                                        rs.RecordingId == recording.Id && rs.SpeakerId == speaker.Id))
                                    {
                                        db.Insert(new DbRecordingSpeaker
                                        {
                                            RecordingId = recording.Id,
                                            SpeakerId   = speaker.Id
                                        });
                                    }
                                }

                                if (saveTagFile)
                                {
                                    _logger.Debug("Writing ID tag data");
                                    tagFile.Save();
                                }
                            }

                            index++;
                        }

                        _logger.Info("Committing transaction");
                        transaction.Commit();
                    }
                }
            }
        }
        //public object Get(Details details)
        //{
        //    Models.Recording recording = _recordingRepository.GetById(details.Id);
        //    if (recording.Restricted && !UserSession.IsAuthenticated)
        //        return HttpResult.Redirect("/Login".AddQueryParam("redirect", Request.AbsoluteUri));

        //    return new DetailsResponse {Recording = recording};
        //}

        //public object Get(Delete delete)
        //{
        //    Models.Recording recording = _recordingRepository.GetById(delete.Id);
        //    if (recording.Restricted && !UserSession.IsAuthenticated) return HttpResult.Redirect("/Login".AddQueryParam("redirect", Request.AbsoluteUri));


        //    return new DeleteResponse {Recording = recording};
        //}

        //[Authenticate]
        //[RequiredRole(RoleNames.Admin)]
        //public object Post(Delete delete)
        //{
        //    _recordingRepository.Delete(delete.Id);

        //    return this.Redirect("/Recording");
        //}

        public object Get(SpeakerDetails speaker)
        {
            if (speaker.EscapedFragment == null && !Request.RawUrl.IsNormalizedUrl())
            {
                return(this.RedirectPermanently(Request.RawUrl.ToNormalizedUrl()));
            }

            if (speaker.EscapedFragment != null && speaker.EscapedFragment.StartsWith("/"))
            {
                speaker.Album = speaker.EscapedFragment.Substring(1);
            }

            var includeRestricted = UserSession.IsAuthenticated;

            NameInfo nameInfo = speaker.Name.ToNameInfo();

            using (IDbConnection db = _dbConnectionFactory.Open())
            {
                DbSpeaker dbSpeaker = db.Single <DbSpeaker>(s => s.FirstName == nameInfo.FirstName && s.LastName == nameInfo.LastName && !s.Deleted);
                if (dbSpeaker == null)
                {
                    throw HttpError.NotFound("Speaker not found");
                }

                SqlExpression <DbRecording> albumIdQuery =
                    db.From <DbRecording>()
                    .Join <DbRecordingSpeaker>((recording, recordingSpeaker) => recording.Id == recordingSpeaker.RecordingId)
                    .Where <DbRecording, DbRecordingSpeaker>((recording, recordingSpeaker) => !recording.Deleted && recordingSpeaker.SpeakerId == dbSpeaker.Id)
                    .SelectDistinct(rs => rs.AlbumId);

                SqlExpression <DbSpeaker> query = db.From <DbSpeaker>()
                                                  .Join <DbRecordingSpeaker>((sp, recordingSpeaker) => sp.Id == recordingSpeaker.SpeakerId)
                                                  .Join <DbRecordingSpeaker, DbRecording>((recordingSpeaker, recording) => recordingSpeaker.RecordingId == recording.Id)
                                                  .Join <DbRecording, DbAlbum>((recording, album) => recording.AlbumId == album.Id)
                                                  .Where <DbSpeaker, DbAlbum>((sp, album) => !sp.Deleted && !album.Deleted && Sql.In(album.Id, albumIdQuery))
                                                  .OrderBy <DbAlbum>(a => a.Name)
                                                  .ThenBy <DbRecording>(r => r.Track);

                if (!includeRestricted)
                {
                    query.And <DbAlbum>(a => !a.Restricted);
                }

                List <Tuple <DbSpeaker, DbRecordingSpeaker, DbRecording, DbAlbum> > recordings = db.SelectMulti <DbSpeaker, DbRecordingSpeaker, DbRecording, DbAlbum>(query);

                Dictionary <long, DbAlbum> albums = recordings.DistinctBy(r => r.Item4.Id).Select(r => r.Item4).ToDictionary(a => a.Id);

                ILookup <long, Tuple <DbSpeaker, DbRecordingSpeaker, DbRecording, DbAlbum> > albumLookup = recordings.ToLookup(r => r.Item4.Id);
                ILookup <long, Tuple <DbSpeaker, DbRecordingSpeaker, DbRecording, DbAlbum> > speakers    = recordings.ToLookup(r => r.Item3.Id);

                List <AlbumInfo> albumInfos =
                    (from g in albumLookup
                     let album = albums[g.Key]
                                 select new AlbumInfo
                {
                    Uid = album.Uid,
                    Name = album.Name,
                    Description = album.Description,
                    AlbumSpeakers = GetSpeakers(g),
                    HasAlbumArt = album.AlbumArtPath != null,
                    Recordings = g.DistinctBy(r => r.Item3.Id)
                                 .OrderBy(r => r.Item3.Track)
                                 .Select(r => new RecordingInfo
                    {
                        Uid = r.Item3.Uid,
                        Title = r.Item3.Title,
                        Track = r.Item3.Track,
                        Year = r.Item3.Year,
                        Comment = r.Item3.Comment,
                        Speakers = speakers[r.Item3.Id]
                                   .DistinctBy(rs => rs.Item1.Id)
                                   .Select(rs => rs.Item1.ToSpeakerInfo())
                                   .ToList()
                    }).ToList(),
                    Attachments = album.AttachmentPaths
                                  .Select((attachment, index) => new AttachmentInfo
                    {
                        Name =
                            _fileSystem.Path.GetFileName(attachment),
                        Index = index
                    }).ToList()
                }).ToList();

                return(new SpeakerDetailsResponse
                {
                    Uid = dbSpeaker.Uid,
                    Speaker = speaker.Name,
                    Albums = albumInfos.ToList(),
                    Speakers = _recordingRepository.GetSpeakers(includeRestricted).Select(s => s.ToSpeakerInfo(sp => sp.FullName == speaker.Name)).ToList(),
                    SelectedAlbum = albumInfos.FirstOrDefault(a => a.Name == (speaker.Album ?? speaker.EscapedFragment)),
                    HasPhoto = dbSpeaker.PhotoPath != null,
                    Description = dbSpeaker.Description
                });
            }
        }
Exemple #4
0
        public object Any(SpeakerFeedRequest speakerFeedRequest)
        {
            bool       includeRestricted = UserSession.IsAuthenticated;
            const int  limit             = 50;
            XNamespace itunes            = "http://www.itunes.com/dtds/podcast-1.0.dtd";
            XNamespace atom    = "http://www.w3.org/2005/Atom";
            string     siteUrl = Request.GetApplicationUrl();

            string       logoUrl   = $"{siteUrl}/content/images/podcast_logo.png";
            const string subscribe = @"<h4>Abonner i iTunes</h4>
<ol>
	<li>Start iTunes</li>
	<li>Klikk Fil - Abonner på podcast (File - Subscribe to Podcast). (Trykk Alt-F for å få frem menyen i Windows.)
	<li>Lim inn lenken til denne siden, og klikk OK</li>
</ol>";

            using (IDbConnection db = _dbConnectionFactory.Open())
            {
                DbSpeaker speaker = null;
                if (speakerFeedRequest.Speaker != null)
                {
                    NameInfo nameInfo = speakerFeedRequest.Speaker?.ToNameInfo();
                    speaker = db.Single <DbSpeaker>(s => s.FirstName == nameInfo.FirstName && s.LastName == nameInfo.LastName && !s.Deleted);
                }

                string description = string.Empty;

                SqlExpression <DbSpeaker> query = db.From <DbSpeaker>()
                                                  .Join <DbRecordingSpeaker>((sp, recordingSpeaker) => sp.Id == recordingSpeaker.SpeakerId)
                                                  .Join <DbRecordingSpeaker, DbRecording>((recordingSpeaker, recording) =>
                                                                                          recordingSpeaker.RecordingId == recording.Id)
                                                  .Join <DbRecording, DbAlbum>((recording, album) => recording.AlbumId == album.Id)
                                                  .Where <DbRecording, DbSpeaker>((recording, sp) => !recording.Deleted && !sp.Deleted)
                                                  .Take(limit);
                if (speaker != null)
                {
                    query.And <DbSpeaker>(s => s.Id == speaker.Id);
                }
                else
                {
                    query.OrderByDescending <DbRecording>(r => r.CreatedOn);
                }

                if (!includeRestricted)
                {
                    query.And <DbRecording>(r => r.Restricted == false);
                }

                List <Tuple <DbSpeaker, DbRecordingSpeaker, DbRecording, DbAlbum> > speakerInfo =
                    db.SelectMulti <DbSpeaker, DbRecordingSpeaker, DbRecording, DbAlbum>(query);

                ILookup <long, Tuple <DbSpeaker, DbRecordingSpeaker, DbRecording, DbAlbum> > recordingLookup = speakerInfo.ToLookup(s => s.Item3.Id);

                Dictionary <long, DbAlbum> albums = speakerInfo.DistinctBy(r => r.Item4.Id).Select(r => r.Item4).ToDictionary(a => a.Id);

                IEnumerable <XElement> items =
                    from recording in speakerInfo.DistinctBy(r => r.Item3.Id).Select(r => r.Item3.ToRecording())
                    let album = albums[recording.AlbumId]
                                let speakerName = recordingLookup[recording.Id]
                                                  .Select(s => s.Item1).DistinctBy(s => s.Id)
                                                  .Select(s => s.ToSpeaker().FullName)
                                                  .ToSeparatedString('/')
                                                  let trackDescription =
                        $"{recording.Comment}{(recording.Year != null ? " ({0})".Fmt(recording.Year) : string.Empty)}".PadRight(1, '-')
                        let tagInfo = GetTag(recording)
                                      let fileInfo = _fileSystem.FileInfo.FromFileName(recording.Path)
                                                     let titleSuffix =
                            tagInfo.Tag.TrackCount > 1
                            ? " ({0}/{1})".Fmt(tagInfo.Tag.Track, tagInfo.Tag.TrackCount)
                            : string.Empty
                            let url =
                                $"{siteUrl}/Recording/Stream/{recording.Uid:N}/{fileInfo.Name.UrlEncode20()}"
                                let guid =
                                    $"{siteUrl}/Recording/Stream/{recording.Uid:N}{(speakerFeedRequest.Speaker == null ? "/top50" : string.Empty)}"
                                    select new XElement("item",
                                                        new XElement("title",
                                                                     $"{album.Name}: {recording.Title}{titleSuffix}"
                                                                     ),
                                                        new XElement(itunes + "author", speakerName
                                                                     ),
                                                        new XElement(itunes + "subtitle",
                                                                     $"{(speakerFeedRequest.Speaker == null ? $"{speakerName}: " : string.Empty)}{album.Name}"
                                                                     ),
                                                        new XElement(itunes + "summary", new XCData(trackDescription)
                                                                     ),
                                                        new XElement("description",
                                                                     $"{trackDescription}{Environment.NewLine}{subscribe}"
                                                                     ),
                                                        new XElement(itunes + "image",
                                                                     new XAttribute("href",
                                                                                    logoUrl)
                                                                     ),
                                                        new XElement("enclosure",
                                                                     new XAttribute("url", url),
                                                                     new XAttribute("length", fileInfo.Length),
                                                                     new XAttribute("type", "audio/mpeg")
                                                                     ),
                                                        new XElement("guid", guid
                                                                     ),
                                                        new XElement("pubDate", recording.CreatedOn.ToString("r")
                                                                     ),
                                                        new XElement(itunes + "duration", tagInfo.Properties.Duration.ToString(@"hh\:mm\:ss")
                                                                     ),
                                                        new XElement(itunes + "explicit", "no"
                                                                     )
                                                        );

                string title = speakerFeedRequest.Speaker ?? $"Siste {limit}";

                string link = speakerFeedRequest.Speaker != null
                                  ? $"{siteUrl}/Recording/Speaker/{speakerFeedRequest.Speaker.UrlEncode20()}"
                                  : siteUrl;

                string selfUrl = $"{siteUrl}{Request.RawUrl}";

                List <XElement> categories = new List <XElement>();
                for (int i = 0; i < Configuration.PodcastCategories.Count; i++)
                {
                    categories.Add(new XElement(itunes + "category",
                                                new XAttribute("text", Configuration.PodcastCategories[i]),
                                                new XElement(itunes + "category",
                                                             new XAttribute("text", Configuration.PodcastSubcategories[i])
                                                             )
                                                ));
                }

                XElement element =
                    new XElement("rss",
                                 new XAttribute(XNamespace.Xmlns + "itunes", "http://www.itunes.com/dtds/podcast-1.0.dtd"),
                                 new XAttribute(XNamespace.Xmlns + "atom", "http://www.w3.org/2005/Atom"),
                                 new XAttribute("version", "2.0"),
                                 new XElement("channel",
                                              new XElement(atom + "link",
                                                           new XAttribute("href", selfUrl),
                                                           new XAttribute("rel", "self"),
                                                           new XAttribute("type", "application/rss+xml"),
                                                           new XAttribute(XNamespace.Xmlns + "atom", atom)
                                                           ),
                                              new XElement("title", $"{Configuration.SiteName}: {title}"
                                                           ),
                                              new XElement("link", link
                                                           ),
                                              new XElement("language", "no"
                                                           ),
                                              new XElement("copyright", Configuration.CompanyName
                                                           ),
                                              new XElement(itunes + "subtitle", Configuration.Slogan,
                                                           new XAttribute(XNamespace.Xmlns + "itunes", itunes)
                                                           ),
                                              new XElement(itunes + "author", speakerFeedRequest.Speaker ?? Configuration.CompanyName
                                                           ),
                                              new XElement(itunes + "summary",
                                                           new XCData(WebUtility.HtmlDecode(Configuration.MetaDescription))
                                                           ),
                                              new XElement("description", description
                                                           ),
                                              new XElement(itunes + "owner",
                                                           new XElement(itunes + "name", Configuration.CompanyName
                                                                        ),
                                                           new XElement(itunes + "email", Configuration.CompanyEmail
                                                                        )
                                                           ),
                                              new XElement(itunes + "image",
                                                           new XAttribute("href", logoUrl)
                                                           ),
                                              categories,
                                              new XElement(itunes + "explicit", "no"
                                                           ),
                                              items
                                              )
                                 );

                string podcastFeed = $@"<?xml version=""1.0"" encoding=""UTF-8""?>{Environment.NewLine}{element}";
                return(new HttpResult(podcastFeed, "application/rss+xml"));
            }
        }