Skip to content

Commit

Permalink
cache youtube channel titles to cut down on number of requests
Browse files Browse the repository at this point in the history
  • Loading branch information
travv0 committed Apr 5, 2024
1 parent d7cd91e commit 9e77bab
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 48 deletions.
8 changes: 4 additions & 4 deletions Commands.fs
Original file line number Diff line number Diff line change
Expand Up @@ -514,12 +514,12 @@ type Commands() =
do! ctx.TriggerTypingAsync()

if
Option.isNone (getDb ()).YoutubeChannel
Option.isNone (getDb ()).YoutubeUpdatesChannel
&& ctx.Guild.SystemChannel <> null
then
updateDb
{ (getDb ()) with
YoutubeChannel = Some ctx.Guild.SystemChannel.Id }
YoutubeUpdatesChannel = Some ctx.Guild.SystemChannel.Id }

match! Youtube.getYoutubeChannelId channel with
| None ->
Expand Down Expand Up @@ -599,7 +599,7 @@ type Commands() =

updateDb
{ (getDb ()) with
YoutubeChannel = Some channel.Id }
YoutubeUpdatesChannel = Some channel.Id }

ctx.RespondChunked(
$"Set YouTube updates channel to **#%s{channel.Name}**"
Expand All @@ -612,7 +612,7 @@ type Commands() =
task {
do! ctx.TriggerTypingAsync()

match (getDb ()).YoutubeChannel with
match (getDb ()).YoutubeUpdatesChannel with
| None -> ctx.RespondChunked("No YouTube updates channel set")
| Some channelId ->
let channel = ctx.Guild.GetChannel channelId
Expand Down
3 changes: 2 additions & 1 deletion Data.fs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ let mutable private db =
AutoReplies = Map.empty
AutoReplyRates = Map.empty
LastResponse = None
YoutubeChannel = None
YoutubeUpdatesChannel = None
YoutubeChannels = Set.empty
YoutubeChannelTitles = Map.empty
LastYoutubeFetch = Map.empty
SeenCommunityPosts = Set.empty }

Expand Down
2 changes: 1 addition & 1 deletion Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module Core =
let rand = Random()

let rec postYoutubeUpdates (dis: DiscordClient) =
match (getDb ()).YoutubeChannel with
match (getDb ()).YoutubeUpdatesChannel with
| Some channel ->
let updates = Youtube.getYoutubeUpdates ()
let communityUpdates = Youtube.getCommunityUpdates ()
Expand Down
9 changes: 7 additions & 2 deletions Types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ type Db =
AutoReplies: Map<uint64, string>
AutoReplyRates: Map<uint64, decimal>
LastResponse: string option
YoutubeChannel: uint64 option
YoutubeUpdatesChannel: uint64 option
YoutubeChannels: Set<string>
YoutubeChannelTitles: Map<string, string>
LastYoutubeFetch: Map<string, DateTime>
SeenCommunityPosts: Set<string> }

Expand Down Expand Up @@ -41,10 +42,14 @@ type Db =
|> List.map (fun (k, v) -> uint64 k, v)
|> Map.ofList
LastResponse = Decode.string |> get.Optional.Field "LastResponse"
YoutubeChannel =
YoutubeUpdatesChannel =
Decode.string
|> get.Optional.Field "YoutubeChannel"
|> Option.map uint64
YoutubeChannelTitles =
Decode.dict Decode.string
|> get.Optional.Field "YoutubeChannelTitles"
|> Option.defaultValue Map.empty
YoutubeChannels =
Decode.list Decode.string
|> get.Optional.Field "YoutubeChannels"
Expand Down
106 changes: 66 additions & 40 deletions Youtube.fs
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,35 @@ let getYoutubeChannelId (channel: string) =

let getChannelTitleByChannelId (channelId: string) =
task {
let searchRequest =
ChannelsResource.ListRequest(
youtubeService,
Repeatable([| "brandingSettings" |]),
Id = Repeatable([| channelId |]),
MaxResults = 1L
)

let! response = searchRequest.ExecuteAsync()

return
match response.Items with
| null -> None
| items when items.Count > 0 ->
Some items.[0].BrandingSettings.Channel.Title
| _ -> None
match Map.tryFind channelId (getDb ()).YoutubeChannelTitles with
| Some title -> return Some title
| None ->
let searchRequest =
ChannelsResource.ListRequest(
youtubeService,
Repeatable([| "brandingSettings" |]),
Id = Repeatable([| channelId |]),
MaxResults = 1L
)

let! response = searchRequest.ExecuteAsync()

return
match response.Items with
| null -> None
| items when items.Count > 0 ->
let title = items[0].BrandingSettings.Channel.Title

updateDb
{ (getDb ()) with
YoutubeChannelTitles =
Map.add
channelId
title
(getDb ()).YoutubeChannelTitles }

Some title
| _ -> None
}

let getYoutubeUpdates () : string option list =
Expand Down Expand Up @@ -202,27 +215,40 @@ type ChannelList =

let getCommunityUpdates () : string list =
[ for channelId in (getDb ()).YoutubeChannels do
let channelTitle = match (getChannelTitleByChannelId channelId).Result with
| Some title -> title
| None -> channelId
let communityApiUrl = $"https://yt.lemnoslife.com/channels?part=community,snippet&id=%s{channelId}"
let response = Http.RequestString(communityApiUrl)

match response |> Decode.fromString ChannelList.Decoder with
| Ok channelList ->
for channel in channelList.items do
for post in channel.Community do
if not (Set.contains post.id (getDb ()).SeenCommunityPosts) then
yield
$"**{channelTitle}** has a new community post: \n"
+ (post.contentText |> List.map (fun x -> x.text) |> String.concat "")
+ $"\n\nSee full post at https://www.youtube.com/post/%s{post.id}"

let postIds = channel.Community |> List.map (fun x -> x.id)
updateDb
{ (getDb ()) with
SeenCommunityPosts = Set.union (getDb ()).SeenCommunityPosts (Set.ofList postIds )}
| Error error ->
yield
$"Error decoding community post for channel {channelId}: {error}"
]
let channelTitle =
match (getChannelTitleByChannelId channelId).Result with
| Some title -> title
| None -> channelId

let communityApiUrl =
$"https://yt.lemnoslife.com/channels?part=community,snippet&id=%s{channelId}"

let response = Http.RequestString(communityApiUrl)

match response |> Decode.fromString ChannelList.Decoder with
| Ok channelList ->
for channel in channelList.items do
for post in channel.Community do
if
not (
Set.contains post.id (getDb ()).SeenCommunityPosts
)
then
yield
$"**{channelTitle}** has a new community post: \n"
+ (post.contentText
|> List.map (fun x -> x.text)
|> String.concat "")
+ $"\n\nSee full post at https://www.youtube.com/post/%s{post.id}"

let postIds = channel.Community |> List.map (fun x -> x.id)

updateDb
{ (getDb ()) with
SeenCommunityPosts =
Set.union
(getDb ()).SeenCommunityPosts
(Set.ofList postIds) }
| Error error ->
yield
$"Error decoding community post for channel {channelId}: {error}" ]

0 comments on commit 9e77bab

Please sign in to comment.