-
Notifications
You must be signed in to change notification settings - Fork 0
/
message_util.clj
182 lines (157 loc) · 8.83 KB
/
message_util.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
;
; Copyright © 2020 Peter Monks
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; SPDX-License-Identifier: Apache-2.0
;
(ns discljord-utils.message-util
(:require [clojure.tools.logging :as log]
[discljord.messaging :as dm]
[discljord.formatting :as df]
[discljord-utils.util :as u]))
(defn- check-response-and-throw
[response]
(if (instance? java.lang.Throwable response)
(throw (ex-info (str "Discord API error: " (.getMessage ^java.lang.Throwable response))
(into {} (ex-data response))
response))
response))
(defn create-message!
"A version of discljord.message/create-message! that throws errors."
[discord-message-channel channel-id & args]
(log/debug "Sending message to Discord channel" (str channel-id " with args:") args)
(check-response-and-throw @(apply dm/create-message! discord-message-channel channel-id args)))
(defn edit-message!
"A version of discljord.message/edit-message! that throws errors."
[discord-message-channel channel-id message-id & args]
(log/debug "Editing message" message-id "in Discord channel" (str channel-id " with args:") args)
(check-response-and-throw @(apply dm/edit-message! discord-message-channel channel-id message-id args)))
(defn delete-message!
"A version of discljord.message/delete-message! that throws errors."
[discord-message-channel channel-id message-id]
(log/debug "Deleting message-id" message-id)
(check-response-and-throw @(dm/delete-message! discord-message-channel channel-id message-id)))
(defn create-reaction!
"A version of discljord.message/create-reaction! that throws errors."
[discord-message-channel channel-id message-id reaction]
(log/debug "Adding reaction" reaction "to message-id" message-id)
(check-response-and-throw @(dm/create-reaction! discord-message-channel channel-id message-id reaction)))
(defn create-dm!
"A version of discljord.message/create-dm! that throws errors."
[discord-message-channel user-id]
(log/debug "Creating DM channel with user-id" user-id)
(check-response-and-throw @(dm/create-dm! discord-message-channel user-id)))
(defn get-channel!
"A version of discljord.message/get-channel! that throws errors."
[discord-message-channel channel-id]
(log/debug "Obtaining channel information for channel" channel-id)
(check-response-and-throw @(dm/get-channel! discord-message-channel channel-id)))
(defn send-dm!
"Convenience method that creates a DM channel to the specified user and sends the given message to them."
[discord-message-channel user-id message]
(let [dm-channel (create-dm! discord-message-channel user-id)
channel-id (:id dm-channel)]
(create-message! discord-message-channel channel-id :content message)))
(defn bulk-overwrite-guild-application-commands!
"A version of discljord.message/bulk-overwrite-guild-application-commands! that throws errors."
[discord-message-channel application-id guild-id application-commands]
(check-response-and-throw @(dm/bulk-overwrite-guild-application-commands! discord-message-channel
application-id
guild-id
application-commands)))
(defn create-interaction-response!
"A version of discljord.message/create-interaction-response! that throws errors."
[discord-message-channel interaction-id interaction-token response-type & args]
(check-response-and-throw @(apply dm/create-interaction-response! discord-message-channel
interaction-id
interaction-token
response-type ; https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-response-object-interaction-callback-type
args)))
(defn delete-original-interaction-response!
"A version of discljord.message/delete-original-interaction-response! that throws errors."
[discord-message-channel application-id interaction-token & args]
(check-response-and-throw @(apply dm/delete-original-interaction-response! discord-message-channel
application-id
interaction-token
args)))
(defn direct-message?
"Was the given event sent via a Direct Message?"
[event-data]
(not (:guild-id event-data))) ; Direct messages don't have a :guild-id in their event data
(defn bot-message?
"Was the given event generated by a bot?"
[event-data]
(:bot (:author event-data)))
(defn human-message?
"Was the given event generated by a human?"
[event-data]
(not (bot-message? event-data)))
(defn nick-or-user-name
"Convenience method that returns the nickname, or (if there isn't one) username, of the author of the given message."
[event-data]
(if-let [name (:nick (:member event-data))]
name
(:username (:author event-data))))
(defn channel-link
"Convenience method that creates a link to the given channel-id, for embedding in message bodies"
[channel-id]
(when channel-id
(df/mention-channel channel-id)))
(defn user-link
"Convenience method that creates a link to the given user-id, for embedding in message bodies"
[user-id]
(when user-id
(df/mention-user user-id)))
(defn message-url
"Convenience method that creates a URL to a specific message"
[guild-id channel-id message-id]
(when (and guild-id channel-id message-id)
(str "https://discord.com/channels/" guild-id "/" channel-id "/" message-id)))
(defmulti timestamp-tag
"Convenience method that creates a Discord 'dynamic timestamp' tag for the provided date value and (optional) Discord format specifier (a character; one of \\d \\f \\t \\D \\F \\R \\T - see https://www.reddit.com/r/discordapp/comments/ohmxrc/new_inline_dynamic_timestamps_that_anyone_can_type/ for examples)."
(fn [i & _] (class i)))
(defmethod timestamp-tag Long
([i] (timestamp-tag i nil))
([i format] (str "<t:" i (when format (str ":" format)) ">")))
(defmethod timestamp-tag java.time.Instant
([^java.time.Instant i] (timestamp-tag i nil))
([^java.time.Instant i format] (timestamp-tag (.getEpochSecond i) format)))
(defmethod timestamp-tag java.util.Date
([^java.util.Date i] (timestamp-tag i nil))
([^java.util.Date i format] (timestamp-tag (long (/ (.getTime i) 1000)) format)))
(defmethod timestamp-tag java.time.ZonedDateTime
([^java.time.ZonedDateTime i] (timestamp-tag i nil))
([^java.time.ZonedDateTime i format] (timestamp-tag (.toEpochSecond i) format)))
(defn md-escape
"Escapes the given string for Discord's dialect of markdown, optionally specifying whether the string will appear within a code fence or not (in which case the rules are different)."
([s] (md-escape s false))
([s code-fence?]
(let [replacements (concat [["\\" "\\\\"] ; Replacements from https://daringfireball.net/projects/markdown/syntax#backslash, with Discord additions (strike and spoiler)
["`" "\\`"]]
(when-not code-fence? [["*" "\\*"]
["_" "\\_"]
["{" "\\{"]
["}" "\\}"]
["[" "\\["]
["]" "\\]"]
["(" "\\("]
[")" "\\)"]
["#" "\\#"]
["+" "\\+"]
["-" "\\-"]
["." "\\."]
["!" "\\!"]
["~" "\\~"]
["|" "\\|"]]))]
(u/replace-all s replacements))))