Follow the leader with help from a server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

437 lines
9.0KB

  1. // NGnius 2020-02-12
  2. package main
  3. import (
  4. "crypto/rand"
  5. "crypto/sha512"
  6. "encoding/binary"
  7. "encoding/json"
  8. "math/big"
  9. "strconv"
  10. // test
  11. //"fmt"
  12. )
  13. var (
  14. randomizeTokens bool
  15. )
  16. type Jsonable interface {
  17. Json() ([]byte, error)
  18. JsonPretty() ([]byte, error)
  19. Unjson([]byte) error
  20. JsonObject() (interface{}, error)
  21. }
  22. type Rower interface {
  23. Intake() []interface{}
  24. Output() []interface{}
  25. }
  26. type Board struct {
  27. ID int64
  28. Name string
  29. Description string
  30. }
  31. func LoadBoard(id int64) *Board {
  32. b := &Board{ID: id}
  33. loadErr := b.Load()
  34. if loadErr != nil {
  35. return nil
  36. }
  37. return b
  38. }
  39. func (b *Board) Load() error {
  40. return db.QueryRow(queryStrings[queryType][7], b.ID).Scan(b.Intake()...)
  41. }
  42. func (b *Board) Commit() error {
  43. tx, _ := db.Begin()
  44. statement, _ := tx.Prepare(queryStrings[queryType][8])
  45. _, err := statement.Exec(b.Output()...)
  46. if err != nil {
  47. tx.Rollback()
  48. return err
  49. }
  50. return tx.Commit()
  51. }
  52. func (b *Board) Entries() ([]*Entry, error) {
  53. var entries []*Entry
  54. rows, err := db.Query(queryStrings[queryType][9], b.ID)
  55. if err != nil {
  56. return entries, err
  57. }
  58. count := 0
  59. for rows.Next() {
  60. entries = append(entries, &Entry{})
  61. scanErr := rows.Scan(entries[count].Intake()...)
  62. if scanErr != nil {
  63. return entries, scanErr
  64. }
  65. count++
  66. }
  67. return entries, nil
  68. }
  69. func (b *Board) SomeEntries(start, end int64) ([]*Entry, error) {
  70. var entries []*Entry
  71. rows, err := db.Query(queryStrings[queryType][10], b.ID, start, end)
  72. if err != nil {
  73. return entries, err
  74. }
  75. count := 0
  76. for rows.Next() {
  77. entries = append(entries, &Entry{})
  78. scanErr := rows.Scan(entries[count].Intake()...)
  79. if scanErr != nil {
  80. return entries, scanErr
  81. }
  82. count++
  83. }
  84. return entries, nil
  85. }
  86. func (b *Board) Url() string {
  87. return "/board?id=" + strconv.Itoa(int(b.ID))
  88. }
  89. // implementation of Jsonable
  90. func (b *Board) Json() ([]byte, error) {
  91. var data []byte
  92. jsonObj, err := b.JsonObject()
  93. if err != nil {
  94. return data, err
  95. }
  96. return json.Marshal(jsonObj)
  97. }
  98. func (b *Board) JsonPretty() ([]byte, error) {
  99. var data []byte
  100. jsonObj, err := b.JsonObject()
  101. if err != nil {
  102. return data, err
  103. }
  104. return json.MarshalIndent(jsonObj, "", " ")
  105. }
  106. func (b *Board) JsonObject() (interface{}, error) {
  107. jsonObj := BoardJSON{ID: b.ID, Name: b.Name, Description: b.Description, Url: b.Url()}
  108. return jsonObj, nil
  109. }
  110. // implementation of Rower
  111. func (b *Board) Intake() []interface{} {
  112. return []interface{}{&b.ID, &b.Name, &b.Description}
  113. }
  114. func (b *Board) Output() []interface{} {
  115. return []interface{}{b.ID, b.Name, b.Description}
  116. }
  117. type Player struct {
  118. ID int64
  119. Name string
  120. }
  121. func LoadPlayer(id int64) *Player {
  122. p := &Player{ID: id}
  123. loadErr := p.Load()
  124. if loadErr != nil {
  125. return nil
  126. }
  127. return p
  128. }
  129. func (p *Player) Load() error {
  130. return db.QueryRow(queryStrings[queryType][11], p.ID).Scan(p.Intake()...)
  131. }
  132. func (p *Player) Commit() error {
  133. tx, _ := db.Begin()
  134. statement, _ := tx.Prepare(queryStrings[queryType][12])
  135. _, err := statement.Exec(p.Output()...)
  136. if err != nil {
  137. tx.Rollback()
  138. return err
  139. }
  140. return tx.Commit()
  141. }
  142. func (p *Player) Entries() ([]*Entry, error) {
  143. var entries []*Entry
  144. rows, err := db.Query(queryStrings[queryType][13], p.ID)
  145. if err != nil {
  146. return entries, err
  147. }
  148. count := 0
  149. for rows.Next() {
  150. entries = append(entries, &Entry{})
  151. scanErr := rows.Scan(entries[count].Intake()...)
  152. if scanErr != nil {
  153. return entries, scanErr
  154. }
  155. count++
  156. }
  157. return entries, nil
  158. }
  159. func (p *Player) SomeEntries(limit int64) ([]*Entry, error) {
  160. var entries []*Entry
  161. rows, err := db.Query(queryStrings[queryType][14], p.ID, limit)
  162. if err != nil {
  163. return entries, err
  164. }
  165. count := 0
  166. for rows.Next() {
  167. entries = append(entries, &Entry{})
  168. scanErr := rows.Scan(entries[count].Intake()...)
  169. if scanErr != nil {
  170. return entries, scanErr
  171. }
  172. count++
  173. }
  174. return entries, nil
  175. }
  176. func (p *Player) Url() string {
  177. return "/player?id=" + strconv.Itoa(int(p.ID))
  178. }
  179. // implementation of Jsonable
  180. func (p *Player) Json() ([]byte, error) {
  181. var data []byte
  182. jsonObj, err := p.JsonObject()
  183. if err != nil {
  184. return data, err
  185. }
  186. return json.Marshal(jsonObj)
  187. }
  188. func (p *Player) JsonPretty() ([]byte, error) {
  189. var data []byte
  190. jsonObj, err := p.JsonObject()
  191. if err != nil {
  192. return data, err
  193. }
  194. return json.MarshalIndent(jsonObj, "", " ")
  195. }
  196. func (p *Player) JsonObject() (interface{}, error) {
  197. jsonObj := PlayerJSON{ID: p.ID, Name: p.Name, Url: p.Url()}
  198. return jsonObj, nil
  199. }
  200. // implementation of Rower
  201. func (p *Player) Intake() []interface{} {
  202. return []interface{}{&p.ID, &p.Name}
  203. }
  204. func (p *Player) Output() []interface{} {
  205. return []interface{}{p.ID, p.Name}
  206. }
  207. type Entry struct {
  208. ID int64
  209. Rank int64
  210. Score int64
  211. Player int64
  212. Board int64
  213. Time int64 // Created time (seconds since Unix epoch)
  214. Metadata []byte
  215. }
  216. func LoadEntry(id int64) *Entry {
  217. e := &Entry{ID: id}
  218. loadErr := e.Load()
  219. if loadErr != nil {
  220. return nil
  221. }
  222. return e
  223. }
  224. func (e *Entry) Load() error {
  225. return db.QueryRow(queryStrings[queryType][15], e.ID).Scan(e.Intake()...)
  226. }
  227. func (e *Entry) Commit() error {
  228. tx, _ := db.Begin()
  229. statement, _ := tx.Prepare(queryStrings[queryType][16])
  230. _, err := statement.Exec(e.Output()...)
  231. if err != nil {
  232. tx.Rollback()
  233. return err
  234. }
  235. return tx.Commit()
  236. }
  237. // implementation of Jsonable
  238. func (e *Entry) Json() ([]byte, error) {
  239. var data []byte
  240. jsonObj, err := e.JsonObject()
  241. if err != nil {
  242. return data, err
  243. }
  244. return json.Marshal(jsonObj)
  245. }
  246. func (e *Entry) JsonPretty() ([]byte, error) {
  247. var data []byte
  248. jsonObj, err := e.JsonObject()
  249. if err != nil {
  250. return data, err
  251. }
  252. return json.MarshalIndent(jsonObj, "", " ")
  253. }
  254. func (e *Entry) JsonObject() (interface{}, error) {
  255. jsonObj := EntryJSON{ID: e.ID, Rank: e.Rank, Score: e.Score, PlayerID: e.Player, BoardID: e.Board}
  256. ePlayer := &Player{ID: e.Player}
  257. err := ePlayer.Load()
  258. if err != nil {
  259. return jsonObj, err
  260. }
  261. jsonObj.PlayerName = ePlayer.Name
  262. jsonObj.PlayerURL = ePlayer.Url()
  263. eBoard := &Board{ID: e.Board}
  264. err = eBoard.Load()
  265. if err != nil {
  266. return jsonObj, err
  267. }
  268. jsonObj.BoardName = eBoard.Name
  269. jsonObj.BoardURL = eBoard.Url()
  270. return jsonObj, nil
  271. }
  272. // implementation of Rower
  273. func (e *Entry) Intake() []interface{} {
  274. return []interface{}{&e.ID, &e.Rank, &e.Score, &e.Player, &e.Board, &e.Time, &e.Metadata}
  275. }
  276. func (e *Entry) Output() []interface{} {
  277. return []interface{}{e.ID, e.Rank, e.Score, e.Player, e.Board, e.Time, e.Metadata}
  278. }
  279. type Key struct {
  280. ID int64
  281. Token string
  282. Player int64
  283. Time int64 // Created time (seconds since Unix epoch)
  284. Metadata []byte
  285. }
  286. func LoadKey(id int64) *Key {
  287. k := &Key{ID: id}
  288. loadErr := k.Load()
  289. if loadErr != nil {
  290. return nil
  291. }
  292. return k
  293. }
  294. func (k *Key) Load() error {
  295. return db.QueryRow(queryStrings[queryType][17], k.ID).Scan(k.Intake()...)
  296. }
  297. func (k *Key) Commit() error {
  298. tx, _ := db.Begin()
  299. statement, _ := tx.Prepare(queryStrings[queryType][18])
  300. _, err := statement.Exec(k.Output()...)
  301. if err != nil {
  302. tx.Rollback()
  303. return err
  304. }
  305. return tx.Commit()
  306. }
  307. func (k *Key) IsEnabled() bool {
  308. return (k.Metadata[0] & 0b00000001) == 0
  309. }
  310. func (k *Key) Disable() {
  311. k.Metadata[0] = k.Metadata[0] | 0b00000001
  312. }
  313. func (k *Key) IsSuperuser() bool {
  314. return (k.Metadata[0] & 0b00000100) == 0
  315. }
  316. func (k *Key) Promote() {
  317. k.Metadata[0] = k.Metadata[0] | 0b00000100
  318. }
  319. func (k *Key) IsMultiuser() bool {
  320. return (k.Metadata[0] & 0b00010000) == 0
  321. }
  322. func (k *Key) Develop() {
  323. k.Metadata[0] = k.Metadata[0] | 0b00010000
  324. }
  325. func (k *Key) GenerateToken() error {
  326. buf_int64 := make([]byte, 10) // 8 bytes = 64 bits
  327. input := []byte{}
  328. if randomizeTokens {
  329. max := big.NewInt(2 ^ 16 - 1)
  330. for i := 0; i < 512; i++ {
  331. // generate randomness
  332. num, _ := rand.Int(rand.Reader, max)
  333. input = append(input, num.Bytes()...)
  334. }
  335. }
  336. binary.PutVarint(buf_int64, k.ID)
  337. input = append(input, buf_int64[0:8]...)
  338. binary.PutVarint(buf_int64, k.Player)
  339. input = append(input, buf_int64[0:8]...)
  340. binary.PutVarint(buf_int64, k.Time)
  341. input = append(input, buf_int64[0:8]...)
  342. bToken := sha512.Sum512(input)
  343. //k.Token = string(bToken)
  344. k.Token = ""
  345. for _, b := range bToken {
  346. tmp_b := b & 0b01111111 // Valid 7-bit ASCII values only
  347. for !((tmp_b > 47 && tmp_b < 58) || (tmp_b > 64 && tmp_b < 91) || (tmp_b > 96 && tmp_b < 123)) {
  348. tmp_b = sha512.Sum512([]byte{tmp_b})[1]
  349. tmp_b = tmp_b & 0b01111111
  350. }
  351. k.Token += string(tmp_b)
  352. }
  353. return nil
  354. }
  355. // Implementation of Jsonable
  356. func (k *Key) Json() ([]byte, error) {
  357. var data []byte
  358. jsonObj, err := k.JsonObject()
  359. if err != nil {
  360. return data, err
  361. }
  362. return json.Marshal(jsonObj)
  363. }
  364. func (k *Key) JsonPretty() ([]byte, error) {
  365. var data []byte
  366. jsonObj, err := k.JsonObject()
  367. if err != nil {
  368. return data, err
  369. }
  370. return json.MarshalIndent(jsonObj, "", " ")
  371. }
  372. func (k *Key) JsonObject() (interface{}, error) {
  373. jsonObj := KeyJSON{Token: k.Token, PlayerID: k.Player}
  374. return jsonObj, nil
  375. }
  376. // Implementation of Rower
  377. func (k *Key) Intake() []interface{} {
  378. return []interface{}{&k.ID, &k.Token, &k.Player, &k.Time, &k.Metadata}
  379. }
  380. func (k *Key) Output() []interface{} {
  381. return []interface{}{k.ID, k.Token, k.Player, k.Time, k.Metadata}
  382. }