Skip to content

Commit

Permalink
First working lib version
Browse files Browse the repository at this point in the history
  • Loading branch information
MityaSaray committed May 19, 2019
1 parent 37cdaed commit 67db9e0
Show file tree
Hide file tree
Showing 11 changed files with 157 additions and 194 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@ tdlib_json_clojure_wrapper.iml
src/tdlib_json_clojure_wrapper/tg_connector/build
*.log
*.binlog
tg-db
config.json
tg-db
34 changes: 4 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,11 @@

A Clojure library designed to be a wrapper around tdlib json client using JNA.

Prerequisites are described in tdlib repository. Installation for Ubuntu is available in shellscript.
Also Leiningen.
Prerequisites are described in [tdlib](https://github.com/tdlib/td) repository.

There are installation instruction for your platform and general usage there https://github.com/tdlib/td
Also [Leiningen](https://leiningen.org/) .

You will need to create a config.json file in root directory.
**Working with library itself**

{
"@type": "setTdlibParameters",
"parameters": {
"api_id": your_api_id,
"api_hash": your_api_hash,
"application_version": "0.1",
"system_version": "Ubuntu 18.04",
"system_language_code": "en",
"device_model": "PC",
"database_directory": "tg-db"
}
}
Examples are provided in example.clj file

You will need to position build folder of tdlib inside
./src/tdlib_json_clojure_wrapper/tg_connector/build. You can look at tdlib_install.sh for example.
Or you can change path in TgClient path.

During first launch program will ask you phone and code in terminal.

Commands are
"lein deps" - to get dependencies.
"lein buildTg" - to build telegram client from source (may take a while).
"lein run" - to launch application.


Namespace tdlib-json-clojure-wrapper.tg-connector.core has prepared functions to communicate.
It also has "message-queue" channel that is filled with incoming messages.
6 changes: 1 addition & 5 deletions project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,4 @@
:dependencies [[org.clojure/clojure "1.10.0"]
[com.sun.jna/jna "3.0.9"]
[cheshire "5.8.1"]
[org.clojure/core.async "0.4.490"]]
:main tdlib-json-clojure-wrapper.core
:plugins [[lein-shell "0.5.0"]]
:aliases {"buildTg"
["shell" "./tdlib_install.sh"]})
[org.clojure/core.async "0.4.490"]])
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package tdlib_json_clojure_wrapper.tg_connector;
package tdlib_json_clojure_wrapper;

import com.sun.jna.Library;
import com.sun.jna.Native;
Expand All @@ -8,13 +8,13 @@ public class TgClient {
private static String pathToLib;
private static Pointer tgInstancePointer;
private static String errorMessage = "Tdlib client was null";
private TdLibrary client;

static {
pathToLib = System.getProperty("user.dir") + "/src/tdlib_json_clojure_wrapper/tg_connector/build/libtdjson.so";
public TgClient(String path) {
System.out.println(path);
pathToLib = path;
}

private TdLibrary client;

public void startClient() {
if (tgInstancePointer == null) {
client = TdLibrary.INSTANCE;
Expand All @@ -24,6 +24,7 @@ public void startClient() {
}

public void send(String message) {
System.out.println(message);
if (tgInstancePointer != null) {
client.td_json_client_send(tgInstancePointer, message);
} else {
Expand Down
122 changes: 109 additions & 13 deletions src/tdlib_json_clojure_wrapper/core.clj
Original file line number Diff line number Diff line change
@@ -1,14 +1,110 @@
(ns tdlib-json-clojure-wrapper.core
(:require [tdlib-json-clojure-wrapper.tg-connector.core :as conn]
[tdlib-json-clojure-wrapper.tg-connector.handlers :as handlers])
(:import (java.util.concurrent CountDownLatch))
(:gen-class))

(defn -main
"i start client connection and message handling"
[& args]
(let [signal (CountDownLatch. 1)]
(println "Disable autostart if you are encountering problems")
(conn/start-telegram)
(handlers/mq-handler)
(.await signal)))
(:require [cheshire.core :as che]
[clojure.core.async :as async])
(:import (tdlib_json_clojure_wrapper TgClient)))

(def client (atom nil))

(defn create-client [path-to-lib]
(TgClient. path-to-lib))

;; Telegram uses this format of keys
(def ttype (keyword "@type"))

(def telegram-ready-state (atom false))

(def message-queue (async/chan))

(defn jsonify [hash] (che/generate-string hash))

(defn json-parse [string]
(che/parse-string string))

(defn client-execute
([type] (. @client execute (jsonify {ttype type})))
;; if has some option to command
([type key command]
(. @client execute
(jsonify
{ttype type (keyword key) command}))))

(defn client-receive
"argument is timeout in seconds and it has to be double"
[]
(json-parse (. @client receive 0.3)))

(defn client-destroy []
(reset! telegram-ready-state false)
(. @client destroyClient)
(reset! client nil))

(defn client-send
([type]
(. @client send (jsonify {ttype type})))
;; if we want to log out there is slightly different behaviour
;; it does not just stop server, it clears our data from telegram and you will need to log in next time
([type logout] (. @client send (jsonify {ttype type}) logout))
([type key message]
(. @client send
(jsonify
{ttype type (keyword key) message}))))

(defn send-phone [phone-number]
(client-send "setAuthenticationPhoneNumber" "phone_number" phone-number))

(defn get-and-send-phone []
(println "Enter your phone number")
(let [phone (read-line)]
(send-phone phone)))

(defn send-auth-code [code]
(client-send "checkAuthenticationCode" "code" code))

(defn get-and-send-code []
(println "Enter your code")
(let [code (read-line)]
(send-auth-code code)))

(defn client-start [path-to-lib]
(reset! client (create-client path-to-lib))
(. @client startClient))

(defn init-reader-loop []
(async/go-loop []
(let [message
(try
(client-receive)
(catch Exception e (str "caught " (.getMessage e) "exception")))]
(if-not
(nil? message)
(async/>! message-queue message))
(recur))))

(defn start-service []
(reset! telegram-ready-state true)
(init-reader-loop))

(defn start-telegram [path-to-lib config]
(when-not (nil? path-to-lib)
(client-start path-to-lib)
(loop [message nil]
(let [state (get-in message ["authorization_state", "@type"])]
(if-not (= state "authorizationStateReady")
(cond
(= state "authorizationStateWaitTdlibParameters")
(do
(client-send ((keyword "@type") config) :parameters (:parameters config))
(recur (client-receive)))
(= state "authorizationStateWaitEncryptionKey")
(do
(client-send "checkDatabaseEncryptionKey")
(recur (client-receive)))
(= state "authorizationStateWaitPhoneNumber")
(do (get-and-send-phone)
(recur (client-receive)))
(= state "authorizationStateWaitCode")
(do (get-and-send-code)
(recur (client-receive)))
:else
(recur (client-receive)))
(start-service))))))
35 changes: 35 additions & 0 deletions src/tdlib_json_clojure_wrapper/example.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
(ns tdlib-json-clojure-wrapper.example
(:require [tdlib-json-clojure-wrapper.core :as c]
[clojure.core.async :as async]
[clojure.pprint :as pp])
(:import (java.util.concurrent CountDownLatch)))
(def config {(keyword "@type") "setTdlibParameters"
:parameters {:api_id "your application api",
:api_hash "your application hash"
:application_version "0.1"
:system_version "Ubuntu 18.04",
:system_language_code "en",
:device_model "PC",
:database_directory "tg-db"}})

(defn mq-handler
"Loops through all incoming messages and applies your logic"
[]
(async/go-loop []
(let [message (async/<! c/message-queue)]
(pp/pprint message))
(recur)))

(defn start-tg
"Start client connection and message handling"
[path-to-lib]
(let [signal (CountDownLatch. 1)]
(c/start-telegram path-to-lib config)
(mq-handler)
(.await signal)))

(defn get-auth-state [] (c/client-send "getAuthorizationState"))

(defn log-out
"logout is a very special case, its the only function that provides client-send with 2 arguments"
[] (c/client-send "logOut" true))
105 changes: 0 additions & 105 deletions src/tdlib_json_clojure_wrapper/tg_connector/core.clj

This file was deleted.

10 changes: 0 additions & 10 deletions src/tdlib_json_clojure_wrapper/tg_connector/handlers.clj

This file was deleted.

7 changes: 0 additions & 7 deletions src/tdlib_json_clojure_wrapper/tg_connector/requests.clj

This file was deleted.

16 changes: 0 additions & 16 deletions tdlib_install.sh

This file was deleted.

0 comments on commit 67db9e0

Please sign in to comment.