-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathget-names.clj
executable file
·99 lines (91 loc) · 3.79 KB
/
get-names.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
#!/usr/bin/env clj
(require '[clojure.string :as str]
'[clojure.set :as sets])
(import java.net.URL)
(def characters ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "_" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"])
(def possible-names (for [a characters b characters c characters] (str a b c)))
(defn send-usernames-request [request]
"Do a Playernames -> UUIDs request"
(loop []
(let
[conn (.. (new URL "https://api.mojang.com/profiles/minecraft") openConnection)]
(do
(. conn setRequestMethod "POST")
(. conn setRequestProperty "Content-Type" "application/json")
(. conn setDoOutput true)
(spit (. conn getOutputStream) request))
(if (not= 200 (int (. conn getResponseCode)))
(do
(println "Did not get a 200 response, sleeping for 15 seconds")
(Thread/sleep 15000)
(recur))
;(slurp (. conn getInputStream))
(set
(map
(fn [x] (second (re-find #"name\":\"(\S+?)\"" (str/lower-case x))))
(str/split
(let [resp (slurp (. conn getInputStream))]
(println "Response:" resp)
resp)
#"\},\{"))))
)))
(defn create-request-payload [names]
"Create the json payload accepted by the API given a vector of names"
(str "["
(reduce
(fn [a b] (str a ",\"" b "\""))
(str "\"" (first names) "\"")
(rest names)
)
"]"))
(defn get-all []
"Get all available-now or soon-available names"
(loop [available #{} remaining-names possible-names]
(if (empty? remaining-names)
available
(let [names (take 100 remaining-names)]
(let [response (send-usernames-request (create-request-payload names))
avail (sets/difference (set names) response)]
(println "Trying for names:" names)
(recur (sets/union available avail) (nthrest remaining-names 100)))))))
(defn send-at-time-request [name]
"Send a Username -> UUID at time request, returns true if name was in use 37 days ago"
(loop []
(let
[past-time (- (quot (System/currentTimeMillis) 1000) (* 60 60 24 37))
url (str "https://api.mojang.com/users/profiles/minecraft/" name "?at=" past-time)
conn (.. (new URL url) openConnection)
response (int (. conn getResponseCode))]
(cond
(= response 200) (do
(println "Setting" name "to soon-available")
true)
(= response 204) (do
(println "Setting" name "to available-now")
false)
:else (do
(println "Got an error (presumably Too Many Requests,) sleeping for 15 seconds")
(Thread/sleep 15000)
(recur))))))
(defn check-all []
"Check all names, returns two sets of available-now and soon-available"
(loop [remaining-names (into [] (reverse (sort (get-all))))
available-now []
soon-available []]
(if (empty? remaining-names)
[available-now soon-available]
(if (send-at-time-request (peek remaining-names))
(recur (pop remaining-names)
available-now
(conj soon-available (peek remaining-names)))
(recur (pop remaining-names)
(conj available-now (peek remaining-names))
soon-available)))))
(let [res (check-all)
available-now (first res)
soon-available (second res)]
(with-open [soon-writer (clojure.java.io/writer "./soon-available.txt")
now-writer (clojure.java.io/writer "./available-now.txt")]
(doall (for [name (sort soon-available)] (. soon-writer write (str name "\n"))))
(doall (for [name (sort available-now)] (. now-writer write (str name "\n"))))
))