Скрипт для отправки лучших картинок из Reddit в Telegram

  1. config = {
  2.   "token": "123456789:ABCDEFGH", // токен бота
  3.   "peer": -1001111234567, // id канала или чатика
  4.   "items-in-top": 3, // сколько рассматривать картинок в топе сабреддита
  5.   "subreddits": [
  6.     // Список сабреддитов
  7.     "aww", "pics", "Art", "japanpics"
  8.   ]
  9. }
  10.  
  11. use "std"
  12. use "math"
  13. use "http"
  14. use "json"
  15. use "functional"
  16. use "files"
  17. use "jdbc"
  18.  
  19. // Telegram
  20. def toParams(obj) = reduce(obj, "", def(acc, k, v) = acc + k + "=" + v + "&")
  21. def createRawUrl(method, params, token = "") = "https://api.telegram.org/bot" + token + "/" + method + "?"+params+"access_token="+token
  22. def createUrl(method, params, token = "") = createRawUrl(method, toParams(params), token)
  23. def invokeJson(method, params, callback) = http(createUrl(method, params, config.token), combine(::jsondecode, callback))
  24. def invoke(method, params, callback) = http(createUrl(method, params, config.token), callback)
  25. def sendPhoto(chatId, url) {
  26.   invoke("sendPhoto", {
  27.     "chat_id": chatId,
  28.     "photo": url
  29.   }, def(r) {})
  30. }
  31.  
  32. // Reddit
  33. def fetchSubreddit(subreddit) {
  34.   url = "https://www.reddit.com/r/" + subreddit + "/.json"
  35.   data = sync(def(ret) = http(url, combine(::jsondecode, ret))).data
  36.   return stream(data.children)
  37.     .map(def(child) = child.data)
  38.     .limit(min(config["items-in-top"], data.dist))
  39.     .map(def(post) = {
  40.       "id": post.id,
  41.       "sub": subreddit,
  42.       "url": post.url,
  43.       "time": post.created_utc
  44.     })
  45.     .toArray()
  46. }
  47. def fetchAll(subreddits) =
  48.   stream(subreddits)
  49.     .flatMap(::fetchSubreddit)
  50.     .toArray()
  51.  
  52. // Database
  53. conn = getConnection("jdbc:sqlite:redditimages.db")
  54. st = conn.createStatement()
  55. st.executeUpdate(
  56.   "CREATE TABLE IF NOT EXISTS posts (
  57.    id          INTEGER PRIMARY KEY AUTOINCREMENT,
  58.    post_id     STRING NOT NULL,
  59.    subreddit   STRING NOT NULL,
  60.    url         STRING NOT NULL,
  61.    created_at  INTEGER NOT NULL,
  62.    sent_at     INTEGER NOT NULL
  63.  )")
  64. st.executeUpdate(
  65.   "CREATE UNIQUE INDEX IF NOT EXISTS reddit_post_idx ON posts (post_id, subreddit)")
  66. st.close()
  67.  
  68. stIsPostExists = conn.prepareStatement(
  69.   "SELECT COUNT(*) FROM posts
  70.   WHERE post_id = ? AND subreddit = ?")
  71. stAddPost = conn.prepareStatement(
  72.   "INSERT INTO posts(post_id, subreddit, url, created_at, sent_at)
  73.   VALUES(?, ?, ?, ?, ?)")
  74.  
  75. def isPostUnique(post) {
  76.   stIsPostExists.setString(1, post.id)
  77.   stIsPostExists.setString(2, post.sub)
  78.   rs = stIsPostExists.executeQuery()
  79.   return rs.getInt(1) == 0
  80. }
  81.  
  82. def addPost(post) {
  83.   stAddPost.setString(1, post.id)
  84.   stAddPost.setString(2, post.sub)
  85.   stAddPost.setString(3, post.url)
  86.   stAddPost.setLong(4, post.time)
  87.   stAddPost.setLong(5, time() / 1000)
  88.   stAddPost.executeUpdate()
  89. }
  90.  
  91.  
  92. stream(fetchAll(config.subreddits))
  93.   .filter(def(p) = reduce([".jpg", ".png"], false, def(acc, ext) = acc || indexOf(p.url, ext) > 0))
  94.   .filter(::isPostUnique)
  95.   .peek(def(p) = sendPhoto(config.peer, p.url))
  96.   .peek(::addPost)
  97.   .count()
  98.  
  99.  
  100. stIsPostExists.close()
  101. stAddPost.close()
  102. conn.close()
Скрипт отправляет в указанный телеграм канал или чат самые лучшие картинки из определённых сабреддитов. Для фильтрации повторов используется база данных sqlite.
Вешать на крон с интервалом по желанию (зависит от частоты появления картинок в сабреддитах и желаемой частоты отправки картинок, я повесил раз в три часа):
  1. 0 */3 * * *     /usr/local/bin/ownlang -f /var/www/ownlang/scripts/redditimages2telegram.own

Реклама

Мы в соцсетях

tw tg yt gt