Skip to content

Commit a39afc3

Browse files
committed
migrate to cloudflare workers
1 parent 047aeaf commit a39afc3

File tree

16 files changed

+213
-96
lines changed

16 files changed

+213
-96
lines changed

.dev.vars

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
S_TOKEN = "2DE97130-0F07-4BB8-9A55-B45C75A98EC1"
2+
TG_TOKEN = "300777612:AAGeXAgHXehSNPj9G9GD8FjzOnOX5zuc4qM"

.gitignore

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
1-
/target
2-
/classes
3-
/checkouts
4-
profiles.clj
5-
pom.xml
6-
pom.xml.asc
7-
*.jar
8-
*.class
9-
/.lein-*
10-
/.nrepl-port
11-
.hgignore
12-
.hg/
1+
*.js
2+
*.out
3+
*.cmi
4+
*.cmo
5+
_build/
6+
.DS_Store
7+

.ocamlformat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
profile = ocamlformat

.travis.yml

Lines changed: 0 additions & 11 deletions
This file was deleted.

Dockerfile

Lines changed: 0 additions & 21 deletions
This file was deleted.

app/dune

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
(executable
2+
(name main)
3+
(libraries core js_of_ocaml yojson)
4+
(modes js)
5+
(preprocess
6+
(pps js_of_ocaml-ppx)))

app/main.ml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
open Js_of_ocaml
2+
3+
module Utils = struct
4+
module U = Js_of_ocaml.Js.Unsafe
5+
module StringMap = Map.Make (String)
6+
7+
let entries_to_string_map entries =
8+
U.global ##. Array##from entries
9+
|> Js.to_array
10+
|> Array.fold_left
11+
(fun a e ->
12+
let k = e##at 0 in
13+
let v = e##at 1 in
14+
if Js.typeof k = Js.string "string" then
15+
StringMap.add (Js.to_string k) (Js.to_string v) a
16+
else a )
17+
StringMap.empty
18+
19+
let make_response (body : string) =
20+
U.new_obj U.global ##. Response [|U.inject body|]
21+
22+
let post (url : string) (body : string) =
23+
U.global##fetch (U.inject url)
24+
(U.obj
25+
[| ("method", U.inject "post")
26+
; ("body", U.inject body)
27+
; ("headers", U.obj [|("content-type", U.inject "application/json")|])
28+
|] )
29+
30+
let get_entries obj = U.global ##. Object##entries obj
31+
32+
let log_error e = U.global##.console##error e
33+
end
34+
35+
(* application/json *)
36+
let fetch req env =
37+
req##text##then_ (fun body ->
38+
match
39+
Core.handle
40+
{ env= Utils.entries_to_string_map (Utils.get_entries env)
41+
; headers= Utils.entries_to_string_map req##.headers
42+
; body= Js.to_string body }
43+
with
44+
| Some cmd ->
45+
let promise = Utils.post cmd.url cmd.body in
46+
(promise##catch (fun e -> Utils.log_error e))##then_ (fun _ ->
47+
Utils.make_response "" )
48+
| None ->
49+
Utils.make_response "" )
50+
51+
let () = Js.export "fetch" fetch

dune-project

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(lang dune 3.2)

project.clj

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/core.ml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
module J = Yojson.Safe
2+
module U = Yojson.Safe.Util
3+
4+
module StringMap = struct
5+
include Map.Make (String)
6+
7+
let pp _ ppf m =
8+
Format.fprintf ppf "{" ;
9+
iter (fun k v -> Format.fprintf ppf "\"%s\": \"%s\"; " k v) m ;
10+
Format.fprintf ppf "}"
11+
end
12+
13+
type http_msg_props =
14+
{env: string StringMap.t; headers: string StringMap.t; body: string}
15+
[@@deriving show]
16+
17+
type http_cmd_props = {url: string; body: string} [@@deriving show]
18+
19+
let handle' ({body; env; _} : http_msg_props) =
20+
match J.from_string body |> U.member "message" with
21+
| `Null ->
22+
None
23+
| message ->
24+
if U.keys message |> List.mem "new_chat_member" then
25+
let url =
26+
Printf.sprintf "https://api.telegram.org/bot%s/deleteMessage"
27+
(StringMap.find "TG_TOKEN" env)
28+
in
29+
Some
30+
{ url
31+
; body=
32+
`Assoc
33+
[ ("chat_id", message |> U.member "chat" |> U.member "id")
34+
; ("message_id", message |> U.member "message_id") ]
35+
|> Yojson.Safe.to_string }
36+
else None
37+
38+
let handle'' ({env; headers; _} as msg) =
39+
let hst = StringMap.find_opt "x-telegram-bot-api-secret-token" headers in
40+
let st = StringMap.find_opt "S_TOKEN" env in
41+
match (st, hst) with
42+
| Some st, Some hst when st = hst ->
43+
handle' msg
44+
| _ ->
45+
None
46+
47+
let handle (msg : http_msg_props) : http_cmd_props option =
48+
print_endline @@ "LOG:MSG: " ^ show_http_msg_props msg ^ "\n" ;
49+
let result = handle'' msg in
50+
Option.iter
51+
(fun x -> print_endline @@ "LOG:CMD: " ^ show_http_cmd_props x ^ "\n")
52+
result ;
53+
result

src/delete_message_bot/core.clj

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/dune

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
(library
2+
(name core)
3+
(libraries js_of_ocaml yojson)
4+
(preprocess
5+
(pps ppx_deriving.show js_of_ocaml-ppx)))

test/delete_message_bot/core_test.clj

Lines changed: 0 additions & 7 deletions
This file was deleted.

test/dune

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
(tests
2+
(names test)
3+
(libraries core alcotest js_of_ocaml yojson)
4+
(preprocess
5+
(pps js_of_ocaml-ppx)))

test/test.ml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
open Alcotest
2+
open Core
3+
module M = Core.StringMap
4+
5+
let make_tests ?headers rules =
6+
let make_msg body =
7+
let open Core in
8+
{ env=
9+
StringMap.singleton "S_TOKEN" "token" |> StringMap.add "TG_TOKEN" "123"
10+
; headers=
11+
Option.value headers
12+
~default:
13+
(StringMap.singleton "x-telegram-bot-api-secret-token" "token")
14+
; body }
15+
in
16+
List.map
17+
(fun (expected, input) ->
18+
let expected =
19+
expected
20+
|> Option.map (fun x ->
21+
{url= "https://api.telegram.org/bot123/deleteMessage"; body= x} )
22+
in
23+
test_case "test" `Quick (fun _ ->
24+
let cmd_fmt =
25+
Fmt.record
26+
[ Fmt.field "url" (fun x -> x.url) Fmt.string
27+
; Fmt.field "body" (fun x -> x.body) Fmt.string ]
28+
in
29+
check
30+
(option (of_pp cmd_fmt))
31+
"" expected
32+
(Core.handle (make_msg input)) ) )
33+
rules
34+
35+
let samples =
36+
[ (None, {|{}|})
37+
; ( None
38+
, {|{"update_id":569999999,"message":{"message_id":4699,"from":{"id":249999999,"is_bot":false,"first_name":"JohnDoe","username":"johndoe","language_code":"en"},"chat":{"id":249999999,"first_name":"JohnDoe","username":"johndoe","type":"private"},"date":1699999999,"text":"hello"}}|}
39+
)
40+
; ( Some {|{"chat_id":-1001000000000,"message_id":12000}|}
41+
, {|{"update_id":560000000,"message":{"message_id":12000,"from":{"id":240000000,"is_bot":false,"first_name":"Alex","username":"alex000","language_code":"en"},"chat":{"id":-1001000000000,"title":"GroupName","type":"supergroup"},"date":1600000000,"new_chat_participant":{"id":1300000000,"is_bot":true,"first_name":"Docker","username":"docker_bot"},"new_chat_member":{"id":1300000000,"is_bot":true,"first_name":"Docker","username":"docker_bot"},"new_chat_members":[{"id":1300000000,"is_bot":true,"first_name":"Docker","username":"docker_bot"}]}}|}
42+
) ]
43+
|> make_tests
44+
45+
let auth_base =
46+
[ (None, {|{}|})
47+
; ( None
48+
, {|{"update_id":569999999,"message":{"message_id":4699,"from":{"id":249999999,"is_bot":false,"first_name":"JohnDoe","username":"johndoe","language_code":"en"},"chat":{"id":249999999,"first_name":"JohnDoe","username":"johndoe","type":"private"},"date":1699999999,"text":"hello"}}|}
49+
)
50+
; ( None
51+
, {|{"update_id":560000000,"message":{"message_id":12000,"from":{"id":240000000,"is_bot":false,"first_name":"Alex","username":"alex000","language_code":"en"},"chat":{"id":-1001000000000,"title":"GroupName","type":"supergroup"},"date":1600000000,"new_chat_participant":{"id":1300000000,"is_bot":true,"first_name":"Docker","username":"docker_bot"},"new_chat_member":{"id":1300000000,"is_bot":true,"first_name":"Docker","username":"docker_bot"},"new_chat_members":[{"id":1300000000,"is_bot":true,"first_name":"Docker","username":"docker_bot"}]}}|}
52+
)
53+
; ( None
54+
, {|{"update_id":560000000,"message":{"message_id":12000,"from":{"id":240000000,"is_bot":false,"first_name":"Alex","username":"alex000","language_code":"en"},"chat":{"id":-1001000000000,"title":"GroupName","type":"supergroup"},"date":1600000000,"new_chat_participant":{"id":1300000000,"is_bot":true,"first_name":"Docker","username":"docker_bot"},"new_chat_member":{"id":1300000000,"is_bot":true,"first_name":"Docker","username":"docker_bot"},"new_chat_members":[{"id":1300000000,"is_bot":true,"first_name":"Docker","username":"docker_bot"}]}}|}
55+
) ]
56+
57+
let auth = auth_base |> make_tests ~headers:M.empty
58+
59+
let auth2 =
60+
auth_base
61+
|> make_tests
62+
~headers:(M.singleton "x-telegram-bot-api-secret-token" "token2")
63+
64+
let () =
65+
run "tests" [("message parse", samples); ("auth", auth); ("auth2", auth2)]

wrangler.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name = "delete-messages-bot"
2+
type = "javascript"
3+
route = ''
4+
zone_id = ''
5+
usage_model = 'bundled'
6+
compatibility_flags = []
7+
workers_dev = true
8+
compatibility_date = "2022-12-27"
9+
node_compat = true
10+
11+
[build]
12+
watch_dir = "app"
13+
command = "dune build --profile=release"
14+
upload.dir = "_build/default/app"
15+
upload.main = "main.bc.js"
16+
upload.format = "modules"
17+
upload.rules = [{ type = "ESModule", globs = ["**/*.js"] }]

0 commit comments

Comments
 (0)