spam.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. # Copyright (C) 2018 Tom Li <tomli at tomli.me>.
  2. #
  3. # To the extent possible under law, I, Tom Li, has waived all copyright
  4. # and related or neighboring rights to this work. You may copy, modify,
  5. # distribute and perform the work, for all purposes.
  6. #
  7. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  8. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  9. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  10. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  11. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  12. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  13. # THE SOFTWARE.
  14. import sys
  15. from pprint import pprint
  16. def parse(dat):
  17. struct = []
  18. state = "STATE_INITIAL"
  19. ptr = [struct]
  20. key_buf = []
  21. val_buf = []
  22. last_type = ""
  23. dat = dat.replace("return {", "{")
  24. for i in dat:
  25. if i.isspace() and (not "STR" in state):
  26. continue
  27. previous_state = state
  28. if i == "{":
  29. state = "STATE_BEGIN_DICT"
  30. elif i == "}":
  31. state = "STATE_END_DICT"
  32. elif i == "[":
  33. state = "STATE_BEGIN_KEY"
  34. elif i == "]":
  35. state = "STATE_END_KEY"
  36. elif i == "\"":
  37. if state not in ["STATE_BEGIN_STR", "STATE_STR"]:
  38. state = "STATE_BEGIN_STR"
  39. elif state in ["STATE_BEGIN_STR", "STATE_STR"]:
  40. state = "STATE_END_STR"
  41. elif i == "=":
  42. if state not in ["STATE_BEGIN_STR", "STATE_STR"]:
  43. state = "STATE_ASSIGNMENT"
  44. elif i == ";":
  45. if previous_state == "STATE_VAL":
  46. state = "STATE_END_VAL"
  47. state = "STATE_END_ENTRY"
  48. else:
  49. if state == "STATE_BEGIN_KEY":
  50. state = "STATE_VAL"
  51. elif state == "STATE_BEGIN_STR":
  52. state = "STATE_STR"
  53. elif state == "STATE_ASSIGNMENT":
  54. state = "STATE_VAL"
  55. if previous_state == "STATE_BEGIN_STR":
  56. state = "STATE_STR"
  57. #print("char: %s \t state: %s" % (i, state))
  58. #print("previous ptr: ", end="")
  59. #pprint(ptr)
  60. if state == "STATE_BEGIN_DICT":
  61. dic = {}
  62. if ptr[-1] == None:
  63. #print(last_type)
  64. if last_type == "key":
  65. ptr[-2][key_buf[0]] = dic
  66. elif last_type == "val":
  67. ptr[-2][val_buf] = dic
  68. else:
  69. assert(False)
  70. ptr.pop()
  71. else:
  72. ptr[-1].append(dic)
  73. ptr.append(dic)
  74. if state == "STATE_BEGIN_KEY":
  75. last_type = "key"
  76. key_buf.clear()
  77. ptr.append(key_buf)
  78. if state == "STATE_BEGIN_STR":
  79. if previous_state != "STATE_BEGIN_KEY":
  80. last_type = "val"
  81. val_buf.clear()
  82. ptr.append(val_buf)
  83. if state in ["STATE_VAL", "STATE_STR"]:
  84. if previous_state == "STATE_ASSIGNMENT":
  85. ptr.append(val_buf)
  86. ptr[-1] += i
  87. if state in ["STATE_END_DICT"]:
  88. ptr.pop()
  89. if state in ["STATE_END_KEY", "STATE_END_ENTRY"]:
  90. if previous_state == "STATE_END_DICT":
  91. continue
  92. if previous_state == "STATE_VAL":
  93. if ("".join(ptr[-1])) == "false":
  94. ptr[-1].clear()
  95. ptr[-1].append(False)
  96. elif ("".join(ptr[-1])) == "true":
  97. ptr[-1].clear()
  98. ptr[-1].append(True)
  99. else:
  100. val = eval("".join(ptr[-1]))
  101. ptr[-1].clear()
  102. ptr[-1].append(val)
  103. else:
  104. assert(previous_state in ["STATE_END_STR"])
  105. string = "".join(ptr[-1])
  106. ptr[-1].clear()
  107. ptr[-1].append(string)
  108. if isinstance(ptr[-2], dict):
  109. ptr[-2][ptr[-1][0]] = None
  110. elif isinstance(ptr[-2], type(None)):
  111. #print("key 0 is", tuple(ptr[-3].keys())[0])
  112. #print("key_buf is", key_buf)
  113. #print("val_buf is", val_buf)
  114. ptr[-3]["".join(key_buf)] = ptr[-1][0]
  115. ptr.pop()
  116. ptr.pop()
  117. else:
  118. assert(False)
  119. val_buf.clear()
  120. if state == "STATE_ASSIGNMENT":
  121. ptr[-1] = ptr[-2][ptr[-1][0]]
  122. #print("struct: ", end="")
  123. #pprint(struct)
  124. #print("new ptr: ", end="")
  125. #pprint(ptr)
  126. #print()
  127. assert(len(struct) == 1)
  128. return struct[0]
  129. for arg in sys.argv[1:]:
  130. score = 0
  131. f = open(arg, "r")
  132. dat = f.read()
  133. f.close()
  134. try:
  135. roster = parse(dat)
  136. except AssertionError as e:
  137. print("============ INTERNAL ERROR ============", file=sys.stderr)
  138. print("The program fails to parse \"%s\", please" % arg, file=sys.stderr)
  139. print("submit a bug report, with your file attached.", file=sys.stderr)
  140. print("============ INTERNAL ERROR ============", file=sys.stderr)
  141. raise e
  142. server = []
  143. none_subscription = 0
  144. for s in tuple(roster.keys()):
  145. if not isinstance(s, str):
  146. continue
  147. if "@" not in s:
  148. continue
  149. server.append(s.split("@")[1])
  150. if roster[s]["subscription"] == "none":
  151. none_subscription += 1
  152. if len(server) >= 50:
  153. score += 1
  154. if len(set(server)) >= 20:
  155. score += 1
  156. if "pending" in roster and len(roster["pending"]) > 20:
  157. score += 1
  158. if len(server) > 0 and (none_subscription / len(server)) >= 0.55:
  159. score += 2
  160. if score >= 3:
  161. print(arg, score)