· 6 years ago · Aug 13, 2019, 10:24 PM
1package pine;
2
3import java.time.Year;
4import java.util.Arrays;
5import java.util.Calendar;
6import java.util.Date;
7import java.util.HashSet;
8import java.util.Map;
9import java.util.Map.Entry;
10import java.util.NavigableMap;
11import java.util.Random;
12import java.util.Set;
13import java.util.TreeMap;
14
15import javax.crypto.KeyGenerator;
16import javax.crypto.SecretKey;
17
18/**
19 * Generates the String text necessary to create variable range outputs.
20 */
21public class PineKeygen {
22
23 /** Default time zone. */
24 private static final String defaultTZ = "America/New_York";
25
26 /**
27 * Key: Integer order of the key<br>
28 * Value: The key
29 */
30 private static NavigableMap<Integer, String> trialKeys = new TreeMap<>((k1, k2) -> {
31 return Integer.compare(k1, k2);
32 });
33
34 /**
35 * Key: Integer order of the key<br>
36 * Value: The key
37 */
38 private static NavigableMap<Integer, String> subKeys = new TreeMap<>((k1, k2) -> {
39 return Integer.compare(k1, k2);
40 });
41
42 /** Calendar. */
43 private static Calendar calendar = Calendar.getInstance();
44
45 /**
46 * @param args Syntax: validVarName:String numMembers:int everyXWeeks:int timeZone:String endHour:int
47 * endMinute:int
48 * <p>
49 * <i>validVarName</i> will have a boolean <tt>true</tt> or <tt>false</tt> if the tested key is
50 * currently valid. A valid key is <tt>true</tt> only if the time stamp associated with that
51 * key (if it exists) has not yet expired for a trial, or it is an active subscription key
52 * (required).
53 * <p>
54 * <i>numMembers</i> is an integer that designates the total number of active member keys to
55 * generate (required)
56 * <p>
57 * <i>everyXDays</i> is an integer that designates how often a key is generated, in days.
58 * <b>7</b> designates that 1 key will be generated every 7 days starting at 23:59 on the first
59 * Sunday of the year (required).
60 * <p>
61 * <i>timeZone</i> optional argument, example = GMT+5
62 * <p>
63 * <i>endHour</i> optional argument, example = 23
64 * <p>
65 * <i>endMinute</i> optional argument, example = 59
66 * <p>
67 */
68 public static void main(String[] args) {
69 try {
70 if (args.length < 3) {
71 throw new IllegalArgumentException("Invalid argument count.");
72 }
73
74 String varName = args[0];
75 varName = varName.equals("validTrial") || varName.equals("validSub") ? varName + "1" : varName;
76 int dayRate = Integer.valueOf(args[2]);
77
78 Set<String> bytes = new HashSet<>();
79
80 KeyGenerator keygen = KeyGenerator.getInstance("AES");
81 keygen.init(128);
82
83 int maxL = 0;
84 SecretKey sKey;
85 byte[] enc;
86
87 for (int i = 0; i < 365; i += dayRate) {
88 sKey = keygen.generateKey();
89 enc = sKey.getEncoded();
90
91 String s = Arrays.toString(enc).replace(", ", "").replace("-", "");
92 s = s.substring(1, s.length() - 1);
93
94 while (bytes.contains(s)) {
95 sKey = keygen.generateKey();
96 enc = sKey.getEncoded();
97
98 s = Arrays.toString(enc).replace(", ", "").replace("-", "");
99 s = s.substring(1, s.length() - 1);
100 }
101
102 trialKeys.put(i, s);
103 bytes.add(s);
104
105 maxL = Math.max(maxL, s.length());
106 }
107
108 int numSubs = Integer.valueOf(args[1]);
109
110 for (int i = 0; i < numSubs; i++) {
111 sKey = keygen.generateKey();
112 enc = sKey.getEncoded();
113
114 String s = Arrays.toString(enc).replace(", ", "").replace("-", "");
115 s = s.substring(1, s.length() - 1);
116
117 while (bytes.contains(s)) {
118 sKey = keygen.generateKey();
119 enc = sKey.getEncoded();
120
121 s = Arrays.toString(enc).replace(", ", "").replace("-", "");
122 s = s.substring(1, s.length() - 1);
123 }
124
125 subKeys.put(i, s);
126 bytes.add(s);
127
128 maxL = Math.max(maxL, s.length());
129 }
130
131 for (Entry<Integer, String> e : trialKeys.entrySet()) {
132 String key = e.getValue();
133
134 while (key.length() < maxL) {
135 key = "0" + key;
136 }
137
138 trialKeys.put(e.getKey(), key);
139 }
140
141 for (Entry<Integer, String> e : subKeys.entrySet()) {
142 String key = e.getValue();
143
144 while (key.length() < maxL) {
145 key = "0" + key;
146 }
147
148 subKeys.put(e.getKey(), key);
149 }
150
151 String timezone = "default";
152 int hour = 23;
153 int minute = 59;
154
155 if (args.length > 3) {
156 try {
157 hour = Integer.valueOf(args[3]);
158 } catch (NumberFormatException e) {
159 timezone = args[3];
160 }
161
162 if (args.length > 4) {
163 if (timezone.equals("default")) {
164 minute = Integer.valueOf(args[4]);
165 } else {
166 hour = Integer.valueOf(args[4]);
167 }
168
169 if (args.length > 5) {
170 minute = Integer.valueOf(args[5]);
171 }
172 }
173 }
174
175 timezone = timezone.equals("default") ? defaultTZ : timezone;
176 timezone = timezone.trim().replaceAll(" ", "");
177 hour = Math.max(0, Math.min(23, hour));
178 minute = Math.max(0, Math.min(59, minute));
179
180 StringBuilder sb = new StringBuilder("\n\nkey = input(\"\", title=\"Key\")\n\n")
181 .append("t = timenow\n\n")
182 .append("validTrial").append(" = ");
183
184 StringBuilder sb2 = new StringBuilder("// Trial Keys\n\n");
185
186 setFirstSunday(Year.now().getValue());
187
188 calendar.add(Calendar.DATE, -dayRate);
189
190 int pYear = calendar.get(Calendar.YEAR);
191 int pMonth = calendar.get(Calendar.MONTH) + 1;
192 int pDay = calendar.get(Calendar.DAY_OF_MONTH);
193
194 calendar.add(Calendar.DATE, dayRate);
195
196 // for trading view, add + 1 to the month,
197
198 for (Entry<Integer, String> e : trialKeys.entrySet()) {
199 String key = e.getValue();
200
201 int year = calendar.get(Calendar.YEAR);
202 int month = calendar.get(Calendar.MONTH) + 1;
203 int day = calendar.get(Calendar.DAY_OF_MONTH);
204
205 calendar.add(Calendar.DATE, dayRate);
206
207 sb.append("(key == \"").append(key).append("\" and ")
208 .append("t > ").append(timestamp(timezone, pYear, pMonth, pDay, hour, minute))
209 .append(" and t <= ").append(timestamp(timezone, year, month, day, hour, minute))
210 .append(") or ");
211
212 sb2.append("// ").append(key).append(": ").append(
213 formatYearMonthDay(pYear, pMonth, pDay, hour, minute)).append(" ---> ")
214 .append(formatYearMonthDay(year, month, day, hour, minute)).append("\n");
215
216 pYear = year;
217 pMonth = month;
218 pDay = day;
219 }
220
221 String out = sb.toString();
222
223 sb = new StringBuilder(out.substring(0, out.length() - 4))
224 .append("\n\nvalidSub = ");
225
226 for (Entry<Integer, String> e : subKeys.entrySet()) {
227 String key = e.getValue();
228 sb.append("key == \"").append(key).append("\" or ");
229 }
230
231 out = sb.toString();
232
233 sb = new StringBuilder(out.substring(0, out.length() - 4))
234 .append("\n\n").append(varName).append(" = ").append("validTrial or validSub")
235 .append("\n\n").append(sb2.toString())
236 .append("\n\n// Subscription Keys\n\n");
237
238 for (Entry<Integer, String> e : subKeys.entrySet()) {
239 sb.append("// ").append(e.getValue()).append("\n");
240 }
241
242 System.out.println(sb.toString());
243
244 } catch (Exception e) {
245 System.out
246 .println("\nSyntax: expiredVarName:String everyXDays:int timeZone:String endHour:int endMinute:int\n\n"
247 +
248 "validVarName = A boolean true or false if the tested key " +
249 "is currently valid. A valid key is true only if the time stamp " +
250 "associated with that key (if it exists) has not yet expired for a trial, " +
251 "or it is an active subscription key(required)\n\n" +
252 "numMembers = an integer that designates the number of active members subscription " +
253 "keys to generate (required) \n\n" +
254 "everyXDays = an integer that designates how often a key is " +
255 "generated, in days. 7 designates that 1 key will be generated every 7 days starting " +
256 "at endHour:endMinute on the first Sunday of the year (required)\n\n" +
257 "timeZone = Designates the timezone, example = GMT+5 or America/New_York (optional)\n\n" +
258 "endHour = Designates the end hour, example = 23 (optional)\n\n" +
259 "endMinute = Designates the end minute, example = 59 (optional)\n\n" +
260 "Full Example\n\n> valid 20 14 12 0\n\n will generate a 20 member subscription keys, " +
261 "and a trial key every 14 days starting on Sunday at 12:00 PM America/New_York\n");
262
263 e.printStackTrace();
264 }
265 }
266
267 static void setFirstSunday(int year) {
268 setFirstDayOfWeek(year, Calendar.JANUARY, Calendar.SUNDAY);
269 }
270
271 static void setFirstDayOfWeek(int year, int dayofWeek) {
272 setFirstDayOfWeek(year, Calendar.JANUARY, dayofWeek);
273 }
274
275 static void setFirstDayOfWeek(int year, int month, int dayofweek) {
276 calendar.set(Calendar.MONTH, month);
277 calendar.set(Calendar.YEAR, year);
278
279 int dom = 1;
280 calendar.set(Calendar.DAY_OF_MONTH, dom);
281
282 while (calendar.get(Calendar.DAY_OF_WEEK) != dayofweek) {
283 calendar.set(Calendar.DAY_OF_MONTH, ++dom);
284 }
285 }
286
287 static String timestamp(String tz, int year, int month, int dayofmonth, int hour, int minute) {
288 return new StringBuilder("timestamp(\"")
289 .append(tz).append("\", ")
290 .append(year).append(", ")
291 .append(month).append(", ")
292 .append(dayofmonth).append(", ")
293 .append(hour).append(", ")
294 .append(minute)
295 .append(")").toString();
296
297 }
298
299 static String formatYearMonthDay(int year, int month, int day, int hour, int minute) {
300 String m = (month < 10 ? "0" : "") + String.valueOf(month);
301 String d = (day < 10 ? "0" : "") + String.valueOf(day);
302 String h = (hour < 10 ? "0" : "") + String.valueOf(hour);
303 String min = (minute < 10 ? "0" : "") + String.valueOf(minute);
304
305 return new StringBuilder().append(year).append("-").append(m).append("-").append(d).append("-")
306 .append(h).append(":").append(min)
307 .toString();
308
309 }
310}