编译时的问题

时间:2019-05-25 19:20:43

标签: clojure

我不断收到以下错误,最有可能是显而易见的错误,但我对此并不陌生。任何帮助,将不胜感激。我很确定代码的这一部分有错误。

(b/defcomponent client {:bounce/deps #{config/value}}
  (log/info "Connecting to Discord")
  (let [token (get-in config/value [:discord :token])
        client (if token
                 (.. (ClientBuilder.)
                     (withToken token)
                     login)
                 (throw (Error. "Discord token not found, please set {:discord {:token \"...\"}} in `config/config.edn`.")))]

仔细检查我认为错误的位置,但是似乎无法弄清楚。

(ns snowball.discord
  (:require [clojure.string :as str]
            [clojure.core.async :as a]
            [bounce.system :as b]
            [taoensso.timbre :as log]
            [camel-snake-kebab.core :as csk]
            [snowball.config :as config]
            [snowball.util :as util])
  (:import [sx.blah.discord.api ClientBuilder]
           [sx.blah.discord.util.audio AudioPlayer]
           [sx.blah.discord.handle.audio IAudioReceiver]
           [sx.blah.discord.api.events IListener]))

(defn event->keyword [c]
  (-> (str c)
      (str/split #"\.")
      (last)
      (str/replace #"Event.*$" "")
      (csk/->kebab-case-keyword)))

(defmulti handle-event! (fn [c] (event->keyword c)))
(defmethod handle-event! :default [_] nil)

(declare client)

(defn ready? []
  (some-> client .isReady))

(defn poll-until-ready []
  (let [poll-ms (get-in config/value [:discord :poll-ms])]
    (log/info "Connected, waiting until ready")
    (util/poll-while poll-ms (complement ready?) #(log/info "Not ready, sleeping for" (str poll-ms "ms")))
    (log/info "Ready")))

(defn channels []
  (some-> client .getVoiceChannels seq))

(defn channel-users [channel]
  (some-> channel .getConnectedUsers seq))

(defn current-channel []
  (some-> client .getConnectedVoiceChannels seq first))

(defn ->name [entity]
  (some-> entity .getName))

(defn ->id [entity]
  (some-> entity .getLongID))

(defn leave! [channel]
  (when channel
    (log/info "Leaving" (->name channel))
    (.leave channel)))

(defn join! [channel]
  (when channel
    (log/info "Joining" (->name channel))
    (.join channel)))

(defn bot? [user]
  (some-> user .isBot))

(defn muted? [user]
  (when user
    (let [voice-state (first (.. user getVoiceStates values))]
      (or (.isMuted voice-state)
          (.isSelfMuted voice-state)
          (.isSuppressed voice-state)))))

(defn can-speak? [user]
  (not (or (bot? user) (muted? user))))

(defn has-speaking-users? [channel]
  (->> (channel-users channel)
       (filter can-speak?)
       (seq)
       (boolean)))

(defn default-guild []
  (some-> client .getGuilds seq first))

(defn guild-users []
  (some-> (default-guild) .getUsers))

(defn guild-text-channels []
  (some-> (default-guild) .getChannels))

(defn guild-voice-channels []
  (some-> (default-guild) .getVoiceChannels))

(defn move-user-to-voice-channel [user channel]
  (when (and user channel)
    (try
      (.moveToVoiceChannel user channel)
      (catch Exception e
        (log/warn "Tried to move a user to a voice channel that isn't connected to voice already")))))

(defn play! [audio]
  (when audio
    (when-let [guild (default-guild)]
      (doto (AudioPlayer/getAudioPlayerForGuild guild)
        (.clear)
        (.queue audio)))))

(defn send! [channel-id message]
  (when-let [channel (.getChannelByID (default-guild) channel-id)]
    (log/info "Sending message to" channel-id "-" message)
    (.sendMessage channel message)))

(defmethod handle-event! :reconnect-success [_]
  (log/info "Reconnection detected, leaving any existing voice channels to avoid weird state")
  (poll-until-ready)
  (when-let [channel (current-channel)]
    (leave! channel)))

(defn audio-manager []
  (some-> (default-guild) .getAudioManager))

(defrecord AudioEvent [audio user])

(defn subscribe-audio! [f]
  (let [sub! (atom nil)
        closed?! (atom false)
        sub-chan (a/go-loop []
                   (when-not @closed?!
                     (a/<! (a/timeout (get-in config/value [:discord :poll-ms])))
                     (if-let [am (audio-manager)]
                       (try
                         (let [sub (reify IAudioReceiver
                                     (receive [_ audio user _ _]
                                       (try
                                         (when-not (bot? user)
                                           (f (AudioEvent. audio user)))
                                         (catch Exception e
                                           (log/error "Caught error while passing audio event to subscription handler" e)))))]
                           (reset! sub! sub)
                           (log/info "Audio manager exists, subscribing to audio")
                           (.subscribeReceiver am sub))
                         (catch Exception e
                           (log/error "Caught error while setting up audio subscription" e)))
                       (recur))))]

    (fn []
      (when-let [sub @sub!]
        (reset! closed?! true)
        (a/close! sub-chan)
        (.unsubscribeReceiver (audio-manager) sub)))))

(b/defcomponent client {:bounce/deps #{config/value}}
  (log/info "Connecting to Discord")
  (let [token (get-in config/value [:discord :token])
        client (if token
                 (.. (ClientBuilder.)
                     (withToken token)
                     login)
                 (throw (Error. "Discord token not found, please set {:discord {:token \"...\"}} in `config/config.edn`.")))]

    (.registerListener
      (.getDispatcher client)
      (reify IListener
        (handle [_ event]
          (handle-event! event))))

    (with-redefs [client client]
      (poll-until-ready))

    (b/with-stop client
      (log/info "Shutting down Discord connection")
      (.logout client))))

(b/defcomponent audio-chan {:bounce/deps #{client}}
  (log/info "Starting audio channel from subscription")
  (let [audio-chan (a/chan (a/sliding-buffer 100))
        sub (subscribe-audio!
              (fn [event]
                (a/go
                  (a/put! audio-chan event))))]
    (b/with-stop audio-chan
      (log/info "Closing audio channel and unsubscribing")
      (sub)
      (a/close! audio-chan))))

以下是我遇到的错误

>     make
>     ./run.sh
>     19-05-25 19:05:45 localhost INFO [snowball.main:6] - Starting components...
>     19-05-25 19:05:47 localhost INFO [snowball.config:16] - Loading base config from config.base.edn and user config from
> config/config.edn
>     19-05-25 19:05:47 localhost INFO [snowball.discord:150] - Connecting to Discord
>     Exception in thread "main" java.lang.ClassCastException: class clojure.lang.Symbol cannot be cast to class java.lang.String
> (clojure.lang.Symbol is in unnamed module of loader 'app';
> java.lang.String is in module java.base of loader 'bootstrap')
>             at snowball.discord$eval12963$start_client__12964.invoke(discord.clj:152)
>             at clojure.lang.AFn.applyToHelper(AFn.java:152)
>             at clojure.lang.AFn.applyTo(AFn.java:144)
>             at clojure.core$apply.invokeStatic(core.clj:665)
>             at clojure.core$apply.invoke(core.clj:660)
>             at bounce.system$start_system$fn__479$fn__480.invoke(system.clj:68)
>             at bounce.system$start_system$fn__479$fn__480$fn__481.invoke(system.clj:71)
>             at clojure.lang.AFn.applyToHelper(AFn.java:152)
>             at clojure.lang.AFn.applyTo(AFn.java:144)
>             at clojure.core$apply.invokeStatic(core.clj:665)
>             at clojure.core$with_bindings_STAR_.invokeStatic(core.clj:1973)
>             at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1973)
>             at clojure.lang.RestFn.invoke(RestFn.java:425)
>             at bounce.system$start_system$fn__479$fn__480.invoke(system.clj:69)
>             at bounce.system$start_system.invokeStatic(system.clj:80)
>             at bounce.system$start_system.invoke(system.clj:59)
>             at bounce.system$start_BANG_.invokeStatic(system.clj:122)
>             at bounce.system$start_BANG_.invoke(system.clj:112)
>             at snowball.main$_main.invokeStatic(main.clj:13)
>             at snowball.main$_main.invoke(main.clj:5)
>             at clojure.lang.AFn.applyToHelper(AFn.java:152)
>             at clojure.lang.AFn.applyTo(AFn.java:144)
>             at clojure.lang.Var.applyTo(Var.java:705)
>             at clojure.core$apply.invokeStatic(core.clj:665)
>             at clojure.main$main_opt.invokeStatic(main.clj:491)
>             at clojure.main$main_opt.invoke(main.clj:487)
>             at clojure.main$main.invokeStatic(main.clj:598)
>             at clojure.main$main.doInvoke(main.clj:561)
>             at clojure.lang.RestFn.applyTo(RestFn.java:137)
>             at clojure.lang.Var.applyTo(Var.java:705)
>             at clojure.main.main(main.java:37)
>     Makefile:12: recipe for target 'run' failed
>     make: *** [run] Error 1

1 个答案:

答案 0 :(得分:0)

从此位:

>     19-05-25 19:05:47 localhost INFO [snowball.discord:150] - Connecting to Discord
>     Exception in thread "main" java.lang.ClassCastException: class clojure.lang.Symbol cannot be cast to class java.lang.String

第152行中的表达式(get-in config/value [:discord :token])似乎返回一个符号(clojure.lang.Symbol)而不是字符串,这导致在构建客户端时抛出ClassCastException课。

我猜这是怎么回事,您正在从外部文件或其他来源读取配置,并且您的令牌未正确引用,因此将其解析为符号(“变量名”)而不是字符串。