Skip to content

Commit

Permalink
post community posts of followed youtube channels
Browse files Browse the repository at this point in the history
  • Loading branch information
travv0 committed Apr 4, 2024
1 parent ac051d0 commit 5484fa1
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 9 deletions.
3 changes: 2 additions & 1 deletion Data.fs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ let mutable private db =
LastResponse = None
YoutubeChannel = None
YoutubeChannels = Set.empty
LastYoutubeFetch = Map.empty }
LastYoutubeFetch = Map.empty
SeenCommunityPosts = Set.empty }

try
match
Expand Down
17 changes: 15 additions & 2 deletions Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,15 @@ module Core =
match (getDb ()).YoutubeChannel with
| Some channel ->
let updates = Youtube.getYoutubeUpdates ()
let communityUpdates = Youtube.getCommunityUpdates ()

dis.Logger.LogInformation
$"Found %d{List.length updates} new Youtube updates"
if List.length communityUpdates > 0 then
dis.Logger.LogInformation
$"Found %d{List.length communityUpdates} new Youtube community updates"

if List.length updates > 0 then
dis.Logger.LogInformation
$"Found %d{List.length updates} new Youtube updates"

for update in updates do
match update with
Expand All @@ -32,6 +38,13 @@ module Core =
)
|> ignore
| None -> ()

for update in communityUpdates do
dis.SendMessageAsync(
dis.GetChannelAsync(uint64 channel).Result,
update
)
|> ignore
| None -> dis.Logger.LogInformation "No channel set for YouTube updates"

Thread.Sleep(1000 * 60)
Expand Down
10 changes: 8 additions & 2 deletions Types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ type Db =
LastResponse: string option
YoutubeChannel: uint64 option
YoutubeChannels: Set<string>
LastYoutubeFetch: Map<string, DateTime> }
LastYoutubeFetch: Map<string, DateTime>
SeenCommunityPosts: Set<string> }

static member Decoder =
Decode.object (fun get ->
Expand Down Expand Up @@ -52,7 +53,12 @@ type Db =
LastYoutubeFetch =
Decode.dict Decode.datetimeUtc
|> get.Optional.Field "LastYoutubeFetch"
|> Option.defaultValue Map.empty })
|> Option.defaultValue Map.empty
SeenCommunityPosts =
Decode.list Decode.string
|> get.Optional.Field "SeenCommunityPosts"
|> Option.defaultValue []
|> Set.ofList })


type Config =
Expand Down
73 changes: 69 additions & 4 deletions Youtube.fs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
module Youtube

open Google.Apis.Services
open Data
open Google.Apis.YouTube.v3
open FSharp.Data
open Google.Apis.Services
open Google.Apis.Util
open Google.Apis.YouTube.v3
open Google.Apis.YouTube.v3.Data
open System
open Thoth.Json.Net

let youtubeService =
let initializer = BaseClientService.Initializer()
Expand Down Expand Up @@ -48,7 +50,7 @@ let getYoutubeChannelId (channel: string) =
| _ -> None
}

let getYoutubeHandleByChannelId (channelId: string) =
let getChannelTitleByChannelId (channelId: string) =
task {
let searchRequest =
ChannelsResource.ListRequest(
Expand Down Expand Up @@ -99,7 +101,7 @@ let getYoutubeUpdates () : string option list =
| _ -> $"Unsupported resource type: %s{resourceId.Kind}"

let channelTitle =
match (getYoutubeHandleByChannelId channelId).Result with
match (getChannelTitleByChannelId channelId).Result with
| Some title -> title
| None -> channelId

Expand Down Expand Up @@ -161,3 +163,66 @@ let getYoutubeUpdates () : string option list =
+ $"https://www.youtube.com/watch?v=%s{item.ContentDetails.Upload.VideoId}"
)
| _ -> yield None ]

type ContentText =
{ text: string }

static member Decoder =
Decode.map
(fun text -> { text = text })
(Decode.field "text" Decode.string)

type Community =
{ id: string
contentText: ContentText list }

static member Decoder =
Decode.map2
(fun id contentText -> { id = id; contentText = contentText })
(Decode.field "id" Decode.string)
(Decode.field "contentText" (Decode.list ContentText.Decoder))

type Channel =
{ id: string
Community: Community list }

static member Decoder =
Decode.map2
(fun id community -> { id = id; Community = community })
(Decode.field "id" Decode.string)
(Decode.field "community" (Decode.list Community.Decoder))

type ChannelList =
{ items: Channel list }

static member Decoder =
Decode.map
(fun items -> { items = items })
(Decode.field "items" (Decode.list Channel.Decoder))

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")
+ $"\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 5484fa1

Please sign in to comment.