diff --git a/Commands.fs b/Commands.fs index a553e63..6acc456 100644 --- a/Commands.fs +++ b/Commands.fs @@ -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 -> @@ -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}**" @@ -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 diff --git a/Data.fs b/Data.fs index 095b815..4ba349f 100644 --- a/Data.fs +++ b/Data.fs @@ -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 } diff --git a/Program.fs b/Program.fs index aa19906..30ff982 100644 --- a/Program.fs +++ b/Program.fs @@ -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 () diff --git a/Types.fs b/Types.fs index 1e605ff..45515cc 100644 --- a/Types.fs +++ b/Types.fs @@ -11,8 +11,9 @@ type Db = AutoReplies: Map AutoReplyRates: Map LastResponse: string option - YoutubeChannel: uint64 option + YoutubeUpdatesChannel: uint64 option YoutubeChannels: Set + YoutubeChannelTitles: Map LastYoutubeFetch: Map SeenCommunityPosts: Set } @@ -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" diff --git a/Youtube.fs b/Youtube.fs index c5762f6..1a0f2d3 100644 --- a/Youtube.fs +++ b/Youtube.fs @@ -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 = @@ -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}" ]