Skip to content

Commit

Permalink
Merge pull request #2 from Massolari/feat/send-gallery
Browse files Browse the repository at this point in the history
Send gallery pictures/gifs
  • Loading branch information
Massolari authored Feb 29, 2024
2 parents 11f6ab1 + 150050a commit 5ef1098
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 117 deletions.
1 change: 1 addition & 0 deletions gleam.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
name = "reddit_to_telegram"
version = "1.0.0"
gleam = ">= 0.32.0"

# Fill out these fields if you intend to generate HTML documentation or publish
# your project to the Hex package manager.
Expand Down
122 changes: 64 additions & 58 deletions src/reddit.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import app_data.{type AppData}
import gleam/bit_array
import gleam/bytes_builder
import gleam/bool
import gleam/dict
import gleam/dynamic
import gleam/hackney
import gleam/http
Expand All @@ -20,7 +21,7 @@ pub type Post {
title: String,
text: String,
score: Int,
media: Result(Media, Nil),
media: List(Media),
external_url: Result(String, Nil),
)
}
Expand Down Expand Up @@ -120,7 +121,7 @@ fn get_threads(
<> subreddit
<> "/"
<> sort_string
<> "?limit=10",
<> "?limit=20",
)
|> result.map_error(fn(_) { "Error creating threads request" }),
)
Expand Down Expand Up @@ -161,17 +162,18 @@ fn post_decoder() -> dynamic.Decoder(Post) {
)
}

fn media_decoder() -> dynamic.Decoder(Result(Media, Nil)) {
fn media_decoder() -> dynamic.Decoder(List(Media)) {
dynamic.any([
fn(dynamic) {
is_video_decoder(dynamic)
|> result.map(Ok)
|> result.map(list.prepend([], _))
},
fn(dynamic) {
url_decoder()(dynamic)
|> result.map(Ok)
|> result.map(list.prepend([], _))
},
fn(_) { Ok(Error(Nil)) },
fn(dynamic) { media_metadata_decoder()(dynamic) },
fn(_) { Ok([]) },
])
}

Expand Down Expand Up @@ -213,58 +215,62 @@ fn url_decoder() -> dynamic.Decoder(Media) {
})
}

// TODO: It's not possible for Telegram to show images from reddit, so we need to
// download them and send them as files.
//
// fn media_metadata_decoder() -> dynamic.Decoder(Media) {
// dynamic.field(named: "media_metadata", of: fn(dynamic_media_metadata) {
// dynamic.dict(of: dynamic.string, to: dynamic.dynamic)(dynamic_media_metadata,
// )
// |> result.try(fn(dict_dynamic) {
// dict_dynamic
// |> dict.values
// // TODO: handle multiple images
// |> list.first
// // List(DecodeError)
// |> result.map_error(fn(_) { [] })
// |> result.try(metadata_decoder())
// })
// })
// }
//
// fn metadata_decoder() -> dynamic.Decoder(Media) {
// fn(dynamic_metadata) {
// dynamic.field(named: "e", of: fn(dynamic_e) {
// dynamic.string(dynamic_e)
// |> result.try(fn(e) {
// case e {
// "Image" -> {
// dynamic.field(
// named: "s",
// of: dynamic.field(named: "u", of: fn(dynamic_url) {
// dynamic.string(dynamic_url)
// |> result.map(fn(url) { Media(url, Image) })
// }),
// )(dynamic_metadata)
// }
// "AnimatedImage" -> {
// dynamic.field(
// named: "s",
// of: dynamic.field(named: "gif", of: fn(dynamic_url) {
// dynamic.string(dynamic_url)
// |> result.map(fn(url) { Media(url, Gif) })
// }),
// )(dynamic_metadata)
// }
// _ -> {
// io.println("Unknown media type: " <> e)
// Error([])
// }
// }
// })
// })(dynamic_metadata)
// }
// }
fn media_metadata_decoder() -> dynamic.Decoder(List(Media)) {
dynamic.field(named: "media_metadata", of: fn(dynamic_media_metadata) {
use dict_dynamic <- result.try(
dynamic_media_metadata
|> dynamic.dict(of: dynamic.string, to: dynamic.dynamic)
|> result.map(dict.values),
)

use acc, dynamic <- list.try_fold(dict_dynamic, [])

dynamic
|> metadata_decoder()
|> result.map_error(fn(_) { [] })
|> result.map(fn(media) { list.prepend(acc, media) })
})
}

fn metadata_decoder() -> dynamic.Decoder(Media) {
fn(dynamic_metadata) {
dynamic.field(named: "e", of: fn(dynamic_e) {
dynamic.string(dynamic_e)
|> result.try(fn(e) {
case e {
"Image" -> {
dynamic.field(
named: "s",
of: dynamic.field(named: "u", of: fn(dynamic_url) {
dynamic.string(dynamic_url)
|> result.map(fn(url) {
case url {
"https://preview.redd.it/" <> path ->
Media("https://i.redd.it/" <> path, Image)
_ -> Media(url, Image)
}
})
}),
)(dynamic_metadata)
}
"AnimatedImage" -> {
dynamic.field(
named: "s",
of: dynamic.field(named: "gif", of: fn(dynamic_url) {
dynamic.string(dynamic_url)
|> result.map(fn(url) { Media(url, Gif) })
}),
)(dynamic_metadata)
}
_ -> {
io.println("Unknown media type: " <> e)
Error([])
}
}
})
})(dynamic_metadata)
}
}

fn media_from_url(url: String) -> Result(Media, dynamic.DecodeErrors) {
use <- bool.guard(when: is_url_image(url), return: Ok(Media(url, Image)))
Expand Down
18 changes: 6 additions & 12 deletions src/reddit_to_telegram.gleam
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import gleam/io
import gleam/list
import gleam/result
import gleam/function
import gleam/pair
import gleam/string
import gleam/int
Expand Down Expand Up @@ -85,25 +84,20 @@ fn start(
|> filter_low_score(10)

io.println(
"Sending messages to telegram channel "
<> bridge.telegram_channel
<> "...",
"Sending messages to telegram channel " <> bridge.telegram_channel <> "...",
)
let #(inserted, errors) =
filtered_posts
|> telegram.send_messages(data, bridge.telegram_channel)
|> list.partition(with: result.is_ok)
|> pair.map_first(list.filter_map(_, function.identity))
|> pair.map_second(fn(error) {
error
|> list.map(result.unwrap_error(_, ""))
})
|> pair.map_first(result.values)
|> pair.map_second(list.map(_, result.unwrap_error(_, "")))

io.println(
inserted
|> list.length
|> int.to_string
<> " messages sent",
|> list.length
|> int.to_string
<> " messages sent",
)

let _ = database.add_messages(database, inserted, bridge.telegram_channel)
Expand Down
Loading

0 comments on commit 5ef1098

Please sign in to comment.