Skip to content

Commit

Permalink
Issue DevChatter#35 Curate the Live Channels Display on Hompage
Browse files Browse the repository at this point in the history
Changes made to show live channels sorted by view count, also displaying time online. Modified the Feeling Lucky button to display a random live channel.
  • Loading branch information
CodeItQuick committed Apr 28, 2019
1 parent a38d0fb commit a0c672a
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 38 deletions.
1 change: 1 addition & 0 deletions src/DevChatter.DevStreams.Core/Data/ICrudRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public interface ICrudRepository
Task<List<T>> GetAll<T>();
Task<List<T>> GetAll<T>(string filter, object args);
Task<List<T>> GetAll<T>(string filter, string orderBy, object args);
Task<List<Channel>> GetAllChannelInfo();
Task<int> Update<T>(T model) where T : DataEntity;
Task<int> Delete<T>(int id) where T : DataEntity;
Task<int> Delete<T>(T model) where T : DataEntity;
Expand Down
7 changes: 6 additions & 1 deletion src/DevChatter.DevStreams.Core/Twitch/ChannelLiveState.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
namespace DevChatter.DevStreams.Core.Twitch
using System;

namespace DevChatter.DevStreams.Core.Twitch
{
public class ChannelLiveState
{
public string TwitchId { get; set; }
public bool IsLive { get; set; }
public DateTime startedAt { get; set; }
public int viewerCount { get; set; }

}
}
26 changes: 26 additions & 0 deletions src/DevChatter.DevStreams.Core/Twitch/TwitchResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,30 @@ public class StreamResult
public List<StreamResultData> Data { get; set; }
public Pagination Pagination { get; set; }
}
public class ChannelResultData
{
public int _total { get; set; }
public List<ChannelResult> follows { get; set; }
}

public class ChannelResult
{
public DateTime created_at { get; set; }
public bool notifications { get; set; }
public ChannelFollowResult channel { get; set; }
}

public class ChannelFollowResult
{
public int _id { get; set; }
public DateTime created_at { get; set; }
public string display_name { get; set; }
public int followers { get; set; }
public string game { get; set; }
public string logo { get; set; }
public DateTime updated_at { get; set; }
public string url { get; set; }
public string video_banner { get; set; }
public int views { get; set; }
}
}
30 changes: 30 additions & 0 deletions src/DevChatter.DevStreams.Infra.Dapper/DapperCrudRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,36 @@ public async Task<List<T>> GetAll<T>(string filter, string orderBy, object args)
}
}

/// <summary>
/// Returns all the channel data for a channel object.
/// </summary>
/// <returns>All Channel Info in a List<Channel> Object </Channel></returns>
public async Task<List<Channel>> GetAllChannelInfo()
{
string sql = "SELECT * FROM Channels;";
string sql2 = "SELECT * FROM TwitchChannels;";

string combinedSQL = sql + sql2;

using (IDbConnection connection = new SqlConnection(_dbSettings.DefaultConnection))
{
var dbQuery = await connection.QueryMultipleAsync(combinedSQL);
List<Channel> channels = dbQuery.Read<Channel>().ToList();
var twitchChannels = dbQuery.Read<TwitchChannel>();

foreach (var channel in channels)
{
if (twitchChannels.Where(x => x?.ChannelId == channel?.Id).Any())
{
channel.Twitch = twitchChannels.Where(x => x?.ChannelId == channel?.Id).First();
}
}

return channels;
}

}

public async Task<int> Update<T>(T model) where T : DataEntity
{
using (IDbConnection connection = new SqlConnection(_dbSettings.DefaultConnection))
Expand Down
53 changes: 30 additions & 23 deletions src/DevChatter.DevStreams.Infra.Twitch/TwitchStreamService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using DevChatter.DevStreams.Core.Model;

namespace DevChatter.DevStreams.Infra.Twitch
{
Expand All @@ -19,11 +20,20 @@ public TwitchStreamService(IOptions<TwitchSettings> twitchSettings)
_twitchSettings = twitchSettings.Value;
}

/// <summary>
/// Returns the subset of the channels which are currently live on Twitch.
/// </summary>
/// <param name="channelNames">Names of the Channels to check for live status.</param>
/// <returns>The names of the subset of channels that are currently live.</returns>


public async Task<ChannelLiveState> IsLive(string twitchId)
{
// TODO: Have this just check cache or do a refresh based on getting *all* data.

var url = $"{_twitchSettings.BaseApiUrl}/streams?user_id={twitchId}";
var jsonResult = await Get(url);

var result = JsonConvert.DeserializeObject<StreamResult>(jsonResult);

return new ChannelLiveState{TwitchId = twitchId, IsLive = result.Data.Any()};
}

public async Task<List<ChannelLiveState>> GetChannelLiveStates(List<string> twitchIds)
{
if (!twitchIds.Any())
Expand All @@ -37,27 +47,24 @@ public async Task<List<ChannelLiveState>> GetChannelLiveStates(List<string> twit

var result = JsonConvert.DeserializeObject<StreamResult>(jsonResult);

var liveChannels = result.Data.Where(x => x.Type == "live").ToList();
var liveChannels = result.Data.ToList();

return twitchIds
.Select(twitchId => new ChannelLiveState
{
TwitchId = twitchId,
IsLive = liveChannels.Any(x => x.User_id == twitchId)
})
.ToList();
}
var returnStat = new List<ChannelLiveState>();

public async Task<ChannelLiveState> IsLive(string twitchId)
{
// TODO: Have this just check cache or do a refresh based on getting *all* data.

var url = $"{_twitchSettings.BaseApiUrl}/streams?user_id={twitchId}";
var jsonResult = await Get(url);

var result = JsonConvert.DeserializeObject<StreamResult>(jsonResult);
if (twitchIds.Any())
{
returnStat = twitchIds
.Select(twitchId => new ChannelLiveState
{
TwitchId = twitchId,
IsLive = liveChannels.Any(x => x.User_id == twitchId),
startedAt = result.Data.Where(x => x.User_id == twitchId).Select(x => x.Started_at.ToUniversalTime()).DefaultIfEmpty().First(),
viewerCount = result.Data.Where(x => x.User_id == twitchId).Select(x => x.Viewer_count).DefaultIfEmpty().First()

return new ChannelLiveState{TwitchId = twitchId, IsLive = result.Data.Any()};
})
.ToList();
}
return returnStat;
}

// TODO: Extract to composed dependency
Expand Down
37 changes: 32 additions & 5 deletions src/DevChatter.DevStreams.Web/Controllers/IsLiveController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System;

namespace DevChatter.DevStreams.Web.Controllers
{
Expand All @@ -26,20 +27,46 @@ public IsLiveController(ICrudRepository crudRepository,


/// <summary>
/// Get all live streams.
/// Get all live streams info.
/// </summary>
/// <returns></returns>
/// <returns>TwitchName, isLive = True, started_At, View Count</returns>
[HttpGet]
public async Task<IActionResult> Get()
{
List<TwitchChannel> channels = await _crudRepository.GetAll<TwitchChannel>();
List<string> twitchIds = channels.Select(x => x.TwitchId).ToList();
var liveTwitchIds = (await _twitchService.GetChannelLiveStates(twitchIds))
var liveTwitchData = (await _twitchService.GetChannelLiveStates(twitchIds));

var sortedLiveData = liveTwitchData.OrderByDescending(o => o.viewerCount).ToList();

var liveTwitchIds = sortedLiveData
.Where(x => x.IsLive)
.Select(x => x.TwitchId)
.ToList();
var liveChannelNames = channels.Where(c => liveTwitchIds.Contains(c.TwitchId)).Select(c => c.TwitchName);
return Ok(liveChannelNames);

var liveChannelSorted = sortedLiveData
.OrderByDescending(x => x.viewerCount)
.Select(x => channels.Where(y => y.TwitchId == x.TwitchId).Where(v => x.IsLive).Select(z => z.TwitchName))
.Where(x => x.Any())
.ToList();

var timeDifference = sortedLiveData
.Where(x => liveTwitchIds.Contains(x.TwitchId))
.Select(x => (DateTime.UtcNow - x.startedAt.ToUniversalTime()));

var viewerCount = sortedLiveData
.Where(x => liveTwitchIds.Contains(x.TwitchId))
.Select(x => x.viewerCount)
.ToList();

var responseObject = new
{
Channel = liveChannelSorted,
viewCount = viewerCount,
timeOnline = timeDifference
};

return Ok(responseObject);
}

[HttpGet, Route("{twitchId}")]
Expand Down
9 changes: 6 additions & 3 deletions src/DevChatter.DevStreams.Web/Pages/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
<div class="col-md-3">
<h2>Live Now</h2> @*TODO: Show channels that are live right now.*@
<ul>
<li v-for="liveChannel in liveChannels">
{{liveChannel}}
</li>
<li v-for="liveChannel, index in liveChannels.channel.slice(0, 10)">
{{liveChannel[0]}}
views: {{ liveChannels.viewCount[index] }}
Online: {{ liveChannels.timeOnline[index] }}

</li>
</ul>
</div>
<div class="col-md-5">
Expand Down
19 changes: 13 additions & 6 deletions src/DevChatter.DevStreams.Web/Pages/Index.cshtml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,26 @@ public async Task<IActionResult> OnGetAsync()

public async Task<IActionResult> OnGetLuckyAsync()
{
List<Channel> channels = await _repo.GetAll<Channel>();
List<Channel> channels = await _repo.GetAllChannelInfo();

List<string> twitchIds = channels.Select(x => x?.Twitch?.TwitchId)
.Where(x => !string.IsNullOrWhiteSpace(x))
.ToList();
var liveChannelIds = (await _twitchService.GetChannelLiveStates(twitchIds))

var liveTwitchId = (await _twitchService.GetChannelLiveStates(twitchIds))
.Where(x => x.IsLive)
.Select(x => x.TwitchId)
.ToList();
var result = new Result();
.ToList().PickOneRandomElement();

var liveChannel = channels
.Where(x => x?.Twitch?.TwitchId == liveTwitchId)
.Select(x => x?.Name);

var result = new Result(); ;

if (liveChannelIds.Any())
if (liveChannel.Any())
{
result.ChannelName = liveChannelIds.PickOneRandomElement();
result.ChannelName = liveChannel.First();
}
else
{
Expand Down

0 comments on commit a0c672a

Please sign in to comment.