This should get us back on track (tested on ARCH Linux)
This commit is contained in:
@@ -0,0 +1,102 @@
|
|||||||
|
User: kA4pgXGnlGlc Password: vn0faZDx5Lcm7 EMail: 9mp7sfnc@1ph2yvtr1b2xnncmr0w.com Status: 200/200/200
|
||||||
|
User: vCUmADyvLUKa Password: iWigwJQpSBW EMail: p4vq1u2a1ug8e9e2an@8wygnw7jxwb.com Status: 200/200/200
|
||||||
|
User: sd8d7uFVJo4g Password: JBTKDO02A1 EMail: r4khrr9i03ufa8z@hskahrvd1opk.com Status: 200/200/200
|
||||||
|
User: jfGJl0q4ph3g Password: MeWkT4cIugef8BwT EMail: sdebmxksu4t8d@phlj4wb04x.com Status: 200/200/200
|
||||||
|
User: hy0UQkg6GI7d Password: o3GEk6FhweX8VHl3 EMail: 4ow63pj0@f9bjilxdsm2fjdmfm3.com Status: 200/200/200
|
||||||
|
User: ZqGdJ3P1Zr2B Password: 7o1Tgsf58b EMail: pxz6mzii1v6iqgrx@bnsuuifaiozkqu7.com Status: 200/200/200
|
||||||
|
User: Lrz5KoRzYZzr Password: OwVx72SVbMp EMail: eiw74mvidnm2@yrqryj7et4.com Status: 200/200/200
|
||||||
|
User: mnrzZNYSN3hJ Password: ZVbpLUOjoqmJs8 EMail: 36pw5peb@eke9if6at6bxwml.com Status: 200/200/200
|
||||||
|
User: 9P0BL1u5uux0 Password: XwmY3SHFCqY EMail: abmqvcczshocudkuy8p@k4ulpf.com Status: 200/200/200
|
||||||
|
User: Lvn8rCIzC1pq Password: LCML47Yr4b EMail: 8dqecj36yk1tzpxg0@5dd4i4.com Status: 200/200/200
|
||||||
|
User: MoXUVLw5kNH6 Password: S6CwVqsndbbNEKj EMail: qsosw2yiynd4qmwguod@d3bitpyvv1m0.com Status: 200/200/200
|
||||||
|
User: W8oxrUrNKwKt Password: 4KFFbCAf EMail: 0s3trskkw4oeh@cn07z6lkjzdo.com Status: 200/200/200
|
||||||
|
User: 0wWDtF4ppBs4 Password: zvtPsSiO EMail: 58zc88brt0wngabz6o15@s79ax6z8.com Status: 200/200/200
|
||||||
|
User: sNMbc9g8gLuk Password: VB60u9c0 EMail: tcb1azx1008@hffpja15iudf49o7.com Status: 200/200/200
|
||||||
|
User: Hzwa7I6UvQeb Password: qcelzyqS EMail: 7t4griziw3odfnuh@97mdgd.com Status: 200/200/200
|
||||||
|
User: WnbMKEZntgGV Password: oxjQe5TiUq EMail: uxqzbe5h0@7agbmkgyae81yk.com Status: 200/200/200
|
||||||
|
User: nzNSON8E2ykF Password: Rbr72ElWHoLU2MXM EMail: xaujh3bcd@kuafjdoc4z71m9u4.com Status: 200/200/200
|
||||||
|
User: ZknQFG8bpuAt Password: mr9olhajTYnC5kr EMail: bu4p8bf0frucym32oi2p@r57q8uh4.com Status: 200/200/200
|
||||||
|
User: sS2YxlM54IAX Password: ySvvd2zf3Jsl EMail: bdilg1qbyscks2nebg7x@f50624ip1rg.com Status: 200/200/200
|
||||||
|
User: 3mnNXYN9rweL Password: j2xl7irgoid2e EMail: 3mj4npt9ecty2wqsjtj@fdu83jgzv1qk.com Status: 200/200/200
|
||||||
|
User: 3UtR3Z8DJjp7 Password: LgdiT2Zm89f8 EMail: vhfbj95s7a8413se@q8e92k0.com Status: 200/200/200
|
||||||
|
User: a1p3HA4LAb9y Password: TDb2D6H14cpn5 EMail: 7ud47hmznszv04fycwb@99l1527cc3.com Status: 200/200/200
|
||||||
|
User: JWcQ9YlRHOSq Password: vPYGicQY2N EMail: g3516x9fao1gxd6@4vln10jhwoigol.com Status: 200/200/200
|
||||||
|
User: YDNQDENhYXW8 Password: xwFZ16xIw EMail: gp3gi5m6a1@3h2b6crbjyiphr7mb.com Status: 200/200/200
|
||||||
|
User: DewiiRMb52UG Password: t2352f3amoDds EMail: 1t55qx8v6zus@cpnhw2y.com Status: 200/200/200
|
||||||
|
User: BcY9hzOb03WY Password: z7Hh23yol EMail: pvod8xlbfklnr3bbfccm@db3wni7.com Status: 200/200/200
|
||||||
|
User: yQjBSi6X0r3A Password: OrLn5NIeJ9j EMail: tukud65ev@h1pwqx.com Status: 200/200/200
|
||||||
|
User: FOR3AwRQ1oyj Password: wwHwbeWwTgG EMail: nmnnvx9d@tgl6h8ejjq.com Status: 200/200/200
|
||||||
|
User: VZtLZC8w6o13 Password: y0nwMFj5m8vwdfGx EMail: yo5joji5ir4t@dxkch757cqq.com Status: 200/200/200
|
||||||
|
User: MA0uX9swvx4c Password: pC0IBT2M EMail: qdsgmz22jof@hnkh9nm.com Status: 200/200/200
|
||||||
|
User: g4wwo0GDMxPs Password: IVJmibfhCkBsqwE EMail: 3vey7yg1ssoikalenwv@quq55jrirp8yqm7.com Status: 200/200/200
|
||||||
|
User: YyRVMmP28O3M Password: 4fAQ5wgn5OO7k EMail: z8bgjyzgg58l8ho@9fvverrrcppthf9i.com Status: 200/200/200
|
||||||
|
User: 9sVQ9k5QBsZm Password: WnxMPWhtOxhlu8i EMail: wm1397etkq2isbcz49@1der7frkf6.com Status: 200/200/200
|
||||||
|
User: tTHNYUe9FtSQ Password: 2Lodw5gH6V2e EMail: pjzfepzy2p9b3gx@raamx09c.com Status: 200/200/200
|
||||||
|
User: qMG3llntqGSe Password: jTvFPbFAv EMail: 0qjw3dlmceuspkbt5q@jjqioski7qhfxpk.com Status: 200/200/200
|
||||||
|
User: gIm1SpnY5bDh Password: 3NXcKmnTpQ EMail: nkjfzkau02s@fy8dz2erk2m3g9nb.com Status: 200/200/200
|
||||||
|
User: x8HgFzchSbbI Password: jhYHISug3J9sglZ0 EMail: o1otlxma86a9vdx@ctuhy610s.com Status: 200/200/200
|
||||||
|
User: Wq06sturxPqA Password: N6lh2VFpO3p EMail: a39gkr0w@9ff2xpuoa142gla.com Status: 200/200/200
|
||||||
|
User: aPYUhA99BfWL Password: d9Tzfn1LjK4r2PlH EMail: 3lxeql5jco8@i3n4npbbiudwpugvy.com Status: 200/200/200
|
||||||
|
User: J3a6GMz58uCD Password: TQs3K4kkZfnFbse0 EMail: r0y9k6ktppidxm9xk@j58duae7ks8sql.com Status: 200/200/200
|
||||||
|
User: biaecW9XY28m Password: bvuX5LbTv7bo1tf EMail: uom71mt6y98@i3e3zs6.com Status: 200/200/200
|
||||||
|
User: WmQolC3lWfu8 Password: RK1geHYYR EMail: 2nmxwdju9@k3wb5qxwgo59rr77zy.com Status: 200/200/200
|
||||||
|
User: nV0unHBoG7Ml Password: QDrlaPXq2bf EMail: qkrux9uecfbctua07@nxs66un5b.com Status: 200/200/200
|
||||||
|
User: RZpejNe0Qgd7 Password: XNKPeLTPWH9A4JU EMail: l1pscpkq1q59@2i2jarr.com Status: 200/200/200
|
||||||
|
User: icl7pGnmrv51 Password: 8FdMLmDgF1yyz EMail: srg5fgsva5k5umww4e@l3jgcc0rkk7.com Status: 200/200/200
|
||||||
|
User: Vffv44oOjiBE Password: yoUOCVFVNuDk EMail: rw96795af1q@b14bua.com Status: 200/200/200
|
||||||
|
User: 07odLgCnmDEB Password: UElwdRmBb EMail: 257n3v2qolxs@x87d6rs9.com Status: 200/200/200
|
||||||
|
User: Dk0UztgZCK2u Password: 4UPhATToAdSfKr EMail: 08w2s1m1zpzayfs@7vul6ejmhzj0u4sy2.com Status: 200/200/200
|
||||||
|
User: ognE6KHaAanZ Password: iGG9Ht511sE EMail: 9x6hc50wc1mbnh@y07175.com Status: 200/200/200
|
||||||
|
User: wKYJKAJp5Diy Password: L3frymQ15G EMail: ari1z6xnq9c1d@s56463.com Status: 200/200/200
|
||||||
|
User: ONr7u1y7N9DE Password: RdGCNWWWdsiPYXB EMail: mwx5j4su@9qkv75.com Status: 200/200/200
|
||||||
|
User: 3m1WZh4dUN94 Password: AJoodDRjl EMail: 7ryuaq4owuvr@me11rn75ox0opfy4tur8.com Status: 200/200/200
|
||||||
|
User: ImebHnWQtP8x Password: A7reNlMfqCJ108l EMail: k8ksl5m30i9qsrfem9z@vzokus.com Status: 200/200/200
|
||||||
|
User: FWGcJXtooet1 Password: gFeJat67gySYIaD EMail: udirgc7my2l2@4a7yxwp3297ku.com Status: 200/200/200
|
||||||
|
User: IdefnRvrkN9j Password: sQy2l6SMrJDEjIL EMail: g3mo4iwlyfpl8u@vy8w3fhxjaie.com Status: 200/200/200
|
||||||
|
User: Pz10bthiXJjc Password: 5EBSMFFi EMail: vw16djmm41t8qb@6bkbdviwaud.com Status: 200/200/200
|
||||||
|
User: xf28kg0CbUho Password: unIn09mZiOBk46 EMail: 6ro2t8rrx3l9e@82u17xx16dabnx143cq.com Status: 200/200/200
|
||||||
|
User: Q2c4yMIRcq93 Password: pMfbjBe8dml4qFe EMail: 362mfi2hg3@h9670jzp3f99c.com Status: 200/200/200
|
||||||
|
User: Vwwb8dtPYegl Password: w9WbPyRRVnEj EMail: 114of4cz@74hdq0.com Status: 200/200/200
|
||||||
|
User: BaOZeLPzVvnE Password: LZfDyv4P2Bd6 EMail: 3nnx2b5brddzr45g@krl3f.com Status: 200/200/200
|
||||||
|
User: PovYyGEBMxrX Password: wtjIugW1X2A EMail: qwblu3lfjv@ebm78j8eknds.com Status: 200/200/200
|
||||||
|
User: jRwazeSoztYB Password: 4m7pVx5OJcuq EMail: ajocu2b95m1yjtq@up7fly.com Status: 200/200/200
|
||||||
|
User: 0fIjg38xZ1ok Password: qVAtcIfy2GIDHY EMail: iq5p76mqbp41qwj@8hn229uqy9t2e2lc7.com Status: 200/200/200
|
||||||
|
User: 8jMQz8vbhK4Y Password: T1uYnjVzHoG4MTsa EMail: fotosdwp@e97mp3zb.com Status: 200/200/200
|
||||||
|
User: 7JORzmCdROMt Password: 96X1fSjc EMail: 71qcee3bl0lom0l@qjkcg1awxzm0.com Status: 200/200/200
|
||||||
|
User: bU8zU1PT0SSp Password: uB4VX6CMOvoZE7 EMail: x08mhorx1ng38oq7z2@p2lxbp8lhgeruvc.com Status: 200/200/200
|
||||||
|
User: pBsSufDePj72 Password: IaYooHKIy EMail: fko423y9nixalm@qzali1.com Status: 200/200/200
|
||||||
|
User: tQc1NxvIoni9 Password: 0Zka1eZsxZ9d EMail: 0s90ii1qc103zqa@d76pr4k6rcw3ccwcx.com Status: 200/200/200
|
||||||
|
User: 77YAQl4vCGSX Password: iLcCgEspKBvIIz EMail: 0sgk3bxakc4vhr@7s37upc9rg0.com Status: 200/200/200
|
||||||
|
User: OVXREjs024iv Password: heR3gMV8Cs EMail: azzkygik@kyi0c65fn3py8ac1l7.com Status: 200/200/200
|
||||||
|
User: wGPCjTH9rlVM Password: 8n60h4XgXbpS EMail: qgszii17f@axpvw.com Status: 200/200/200
|
||||||
|
User: HdEl0uVSOrnw Password: 7tma6S1iwH EMail: yrh1haz6czem@0iyo58rtv1g1tui9f4n.com Status: 200/200/200
|
||||||
|
User: t0b1UIS02nsk Password: RjbM1xBalYBfYf EMail: a5oz4uwnhna66ow6n67@u7yle4frrr0uyfd.com Status: 200/200/200
|
||||||
|
User: 3l76YdsdaFrG Password: ofuEgEqrEec EMail: i4xpl1r76jopbqpxdwt@05tklhwl7k6.com Status: 200/200/200
|
||||||
|
User: xpzWpCR2JGR0 Password: moggVXrWIxd EMail: n10isime@4casoc6gbc90kwuq37a.com Status: 200/200/200
|
||||||
|
User: niTrlQSDb6AZ Password: TY3P7ufbKl EMail: rtuzqv38sqp@wi59t.com Status: 200/200/200
|
||||||
|
User: 9v4GEn0x0bLv Password: WAMHvFS4mRL EMail: it58ox5hkkfs4@e1pb8i0e634zw.com Status: 200/200/200
|
||||||
|
User: 59wENmcLi3bs Password: UrnGmwxZpRuDm EMail: k7vmu981k4j9q8@6j7j61.com Status: 200/200/200
|
||||||
|
User: yNrvA4XahWhV Password: fkE5vxxqxsA8TW6 EMail: 76j1p1bnpn10ke37q2j@v3sr6f22ee6intww.com Status: 200/200/200
|
||||||
|
User: lZ1hmmNrrbup Password: IhACwyRKWnKHeTb EMail: zjti056na439yd67o92@nur1r4.com Status: 200/200/200
|
||||||
|
User: y4TkrHUkSBHB Password: b9EgBnnT4G EMail: 9m96ptg0@97ld7r.com Status: 200/200/200
|
||||||
|
User: SqjFYOUthREH Password: Pm4fhhf3B EMail: 9ky10z5s@cairsmo2nuc7a.com Status: 200/200/200
|
||||||
|
User: MG9rk3eBgxpb Password: BKPyASG7QtzAkA5 EMail: op3ycqb3b0o710@cwu5ovcx5sbgo8d2p0j.com Status: 200/200/200
|
||||||
|
User: ins3dec9Yl7H Password: 2BcxiECub9 EMail: cy1uu6e8ec9a@x8p0jbkecmjge.com Status: 200/200/200
|
||||||
|
User: nprL5horsx0i Password: J6zIAqbEePfZB EMail: 341i04qs@thdnuozrzh52zu2nz.com Status: 200/200/200
|
||||||
|
User: uiScCjSn53K3 Password: S2xNCY0K6OCqp6 EMail: nab92vmecofi4m6ba2@47r5etpo1js6bla.com Status: 200/200/200
|
||||||
|
User: JjJJ52Bw30aX Password: 1PZsv7N8 EMail: pa78j33e@xv19cd374rjeakuywf.com Status: 200/200/200
|
||||||
|
User: 75pgPEfyMzXg Password: am0qaWkbdrWss9r EMail: nmudahit@9mmehg.com Status: 200/200/200
|
||||||
|
User: E00TomIphAY9 Password: Y8mzI5c4sM EMail: b942uv440rrp2y@td9mqx693fdmtule233a.com Status: 200/200/200
|
||||||
|
User: 2ELZOa8Z2c7g Password: KbCIil3IbWdK4 EMail: 22fyebt8@hiw9rn.com Status: 200/200/200
|
||||||
|
User: sFrFAO6OCJnM Password: E0y8MQkFeVJ EMail: hjn5pqxq65z11@7kxwpptdk6nrh3rcpqxx.com Status: 200/200/200
|
||||||
|
User: yG3vnZkaSGey Password: 5p7pVQ0qQJJtU EMail: i6sjnf0q70tu5q@4bnorlzit.com Status: 200/200/200
|
||||||
|
User: 8EbYQCfxn3vG Password: uO7RAwQ50nDUbj EMail: 33o0pscv6e@wrf7nq1hwjjs0mbt1n53.com Status: 200/200/200
|
||||||
|
User: NjsvRC5WxWvH Password: txyFZlkg4mNYP EMail: r6qlf0cs6c7@4qqhrcb9vfjze70po.com Status: 200/200/200
|
||||||
|
User: 6XIzAFYS4lP9 Password: Uo8VQlB28Jra4Je EMail: enq9k3fslpz@gx1rsq7n.com Status: 200/200/200
|
||||||
|
User: 2d85TSjxWi3G Password: 5la3U2YlO EMail: vn2ecrhlu547@54g56ukyavxwzd.com Status: 200/200/200
|
||||||
|
User: 9rLJjxJwbd6a Password: YwZurTVF0Uu EMail: 4zvjysdtngd3j@invvw42q3.com Status: 200/200/200
|
||||||
|
User: aIYfVQyL0DEA Password: Qfs7Vu0YTWPv EMail: wa0zi366bofjh1@zjdq1xhkpblvv1.com Status: 200/200/200
|
||||||
|
User: 1c8zDhMu1zWN Password: Aitm744xU1ADhJN EMail: z60ffdtlcbdkdxd35es@zeanes6qaii.com Status: 200/200/200
|
||||||
|
|
||||||
|
|
||||||
|
User: Wnioqs003kce Password: ErFPiexXpIr57NTl EMail: 1bq1mbx9yvub@q7t9dv.com Status: 200/200/200 // copspy
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
import asyncio
|
||||||
|
import datetime
|
||||||
|
import json
|
||||||
|
|
||||||
|
import websockets
|
||||||
|
from websockets.legacy.client import WebSocketClientProtocol
|
||||||
|
|
||||||
|
from core.dict_object import DictObject
|
||||||
|
|
||||||
|
|
||||||
|
# There is some calculation required. Best to kinda mess with it is to use the websocket on a dev pc and see the output, I believe it was JSON
|
||||||
|
# ws://<You-KNOW-THS>:8887 as basic chat communication. When u connect u have to identify (it sends "#auth") - Repky with the following message or get disconnected: "#auth 13r9Zh9qd10%§SD29#31+". After login u can use followin commands: "#timers" to get all timers(tara, gaunt, ...)
|
||||||
|
#
|
||||||
|
# "#all" sends complete towerdatabase, so just do it every 24h...
|
||||||
|
#
|
||||||
|
# You automaticly get tower updates: "#tower+ [data]" when planted and "#tower- [towerID]" when destroyed
|
||||||
|
# Also timers get been broadcasted: "#timer Tarasque killable" etc..."#timer Vizaresh spawn", "#timer Tarasque 30min", "#timer Tarasque 15min"
|
||||||
|
# like "#tower+ [{asddasdasdaqqd}]
|
||||||
|
|
||||||
|
class TimerObj:
|
||||||
|
name: str = ""
|
||||||
|
spawn: int = 0
|
||||||
|
mortal: int = 0
|
||||||
|
time: int = 0
|
||||||
|
spam: int = 0
|
||||||
|
|
||||||
|
def __init__(self, obj):
|
||||||
|
self.name = obj.name
|
||||||
|
self.spawn = obj.spawn
|
||||||
|
self.mortal = obj.mortal
|
||||||
|
self.time = obj.time
|
||||||
|
|
||||||
|
def nick(self):
|
||||||
|
return self.name.split()[0] if self.name != 'The Desert Rider' else 'Rider'
|
||||||
|
|
||||||
|
def update(self, obj):
|
||||||
|
self.spawn = obj.spawn
|
||||||
|
self.time = obj.time
|
||||||
|
self.mortal = obj.mortal
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.name} " \
|
||||||
|
f"\n\tspawn: {datetime.datetime.fromtimestamp(self.spawn, tz=datetime.timezone.utc).strftime('%H:%M:%S')}" \
|
||||||
|
f"\n\tmortal delta: {self.mortal}" \
|
||||||
|
f"\n\tmortal: {datetime.datetime.fromtimestamp(self.time, tz=datetime.timezone.utc).strftime('%H:%M:%S')}" \
|
||||||
|
f"\n\tImmortal: {self.alive_immortal()}" \
|
||||||
|
f"\n\tMortal killable: {self.alive_mortal()}" \
|
||||||
|
f"\n\t{self.name} - {self.spawn} - {self.mortal} - {self.time} - {self.spam} - {self.getTime()}"
|
||||||
|
|
||||||
|
def alive_immortal(self, spam=False) -> bool:
|
||||||
|
if spam:
|
||||||
|
return self.spam < self.spawn < self.time and self.time > self.getTime()
|
||||||
|
return self.time > self.getTime()
|
||||||
|
|
||||||
|
def alive_mortal(self, spam=False) -> bool:
|
||||||
|
if spam:
|
||||||
|
return self.spam < self.time < (self.getTime()) and (self.time + 60) > self.getTime()
|
||||||
|
return self.time < self.getTime()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def getTime(cls) -> int:
|
||||||
|
return int(datetime.datetime.now().timestamp())
|
||||||
|
|
||||||
|
def get_respawn_timer(self):
|
||||||
|
if self.name in ["Tarasque", "Loren Warr", "The Hollow Reaper", "Cerubin The Reborn"]:
|
||||||
|
return 9 * 60 * 60
|
||||||
|
elif self.name in ["Vizaresh"]:
|
||||||
|
return 17 * 60 * 60
|
||||||
|
elif self.name in ["Atma"]:
|
||||||
|
return 3 * 60 * 60
|
||||||
|
elif self.name in ["T.A.M.", "Zaal The Immortal"]:
|
||||||
|
return 6 * 60 * 60
|
||||||
|
elif self.name in ["Abmouth Indomitus"]:
|
||||||
|
return 9 * 60 * 60
|
||||||
|
# No/unknown respawn timer?
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
class WebsocketClient:
|
||||||
|
timer_data = []
|
||||||
|
|
||||||
|
def getWBTimer(self, name=None):
|
||||||
|
if not name:
|
||||||
|
blob = ""
|
||||||
|
for x in sorted(self.timer_data, key=lambda y: y.name):
|
||||||
|
msg = self.formatMessage(x)
|
||||||
|
blob += (msg + "\n") if msg else ""
|
||||||
|
return blob
|
||||||
|
for x in self.timer_data:
|
||||||
|
if x.name == name:
|
||||||
|
return self.formatMessage(x).strip()
|
||||||
|
|
||||||
|
def formatMessage(self, x: TimerObj):
|
||||||
|
if x.name in ['Tarasque', 'Vizaresh']:
|
||||||
|
return ""
|
||||||
|
if x.alive_immortal():
|
||||||
|
return f"`{x.name.split()[0]: <8}` :: mortal <t:{x.time}:R>"
|
||||||
|
else:
|
||||||
|
rt = x.get_respawn_timer()
|
||||||
|
if rt != 0:
|
||||||
|
if (x.time + rt) < x.getTime() < (x.time + 1.5 * rt):
|
||||||
|
return f"`{x.nick(): <8}` :: should have spawned <t:{abs((x.time + rt))}:R>... next one <t:{x.time + rt + x.get_respawn_timer()}:R>"
|
||||||
|
if x.time < x.getTime() < (x.time + 10 * rt):
|
||||||
|
skips = 0
|
||||||
|
time = x.time
|
||||||
|
while time < x.getTime():
|
||||||
|
time += x.get_respawn_timer()
|
||||||
|
skips += 1
|
||||||
|
if (x.time + rt) < x.getTime():
|
||||||
|
return f"`{x.nick(): <8}` :: spawn <t:{x.time + rt * skips}:R> [Skipped: {skips - 1}]"
|
||||||
|
return f"`{x.nick(): <8}` :: spawn <t:{x.time + rt}:R>"
|
||||||
|
else:
|
||||||
|
return f"`{x.nick(): <8}` :: mortal <t:{x.time + rt}:R>"
|
||||||
|
return ""
|
||||||
|
|
||||||
|
async def internal(self, uri):
|
||||||
|
async with websockets.connect(uri) as websocket:
|
||||||
|
websocket: WebSocketClientProtocol
|
||||||
|
data = await websocket.recv()
|
||||||
|
if data == "#auth":
|
||||||
|
await websocket.send("#login dbs nFa*n4+p~#__H)6NVvQ]W.Veg8!`q6h[Pp9q6HKDk")
|
||||||
|
while True:
|
||||||
|
data = DictObject(json.loads(await websocket.recv()))
|
||||||
|
print(data.payload)
|
||||||
|
for x in data.payload:
|
||||||
|
found = False
|
||||||
|
for y in self.timer_data:
|
||||||
|
if y.name == x.name and not found:
|
||||||
|
y.update(x)
|
||||||
|
found = True
|
||||||
|
if not found:
|
||||||
|
self.timer_data.append(TimerObj(x))
|
||||||
|
print(self.getWBTimer())
|
||||||
|
|
||||||
|
async def monitor(self, uri, method):
|
||||||
|
# Auto reconnect
|
||||||
|
while True:
|
||||||
|
await method(uri)
|
||||||
|
await asyncio.sleep(10)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
b = loop.create_task(self.monitor("ws://37.187.118.232:25501/internal/timers", self.internal))
|
||||||
|
loop.run_until_complete(b)
|
||||||
|
|
||||||
|
|
||||||
|
WebsocketClient()
|
||||||
+182
@@ -0,0 +1,182 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
a = """ UNKNOWN_2(3507), //0xDB3 - listentest.java
|
||||||
|
KNU_BOT_NPC_DESCRIPTION(658522), //0xa0c5a - KnubotNPCDescriptionIIR_c
|
||||||
|
ADD_TEMPLATE(86912780), //0x52e2f0c - AddTemplateIIR_t
|
||||||
|
GRID_DESTINATION_SELECT(104417101), //0x639474d - GridDestinationSelectIIR_t
|
||||||
|
CENTRAL_CONTROLLER_STATE(139685733), //0x8536F65 - CentralControllerStateIIR_t - 2021-01-07
|
||||||
|
WEATHER_CONTROL(207248749), //0xC5a5d6d - WeatherControlIIR_t
|
||||||
|
PET_TO_MASTER(221781762), //0xd381f02 - PetToMasterIIR_c
|
||||||
|
FLUSH_RDB_CACHES(276329306), //0x1078735a - FlushRDBCachesIIR_c
|
||||||
|
SHOP_SEARCH_RESULT(321942351), //0x1330734f
|
||||||
|
SHOP_SEARCH_REQUEST(341462886), //0x145a4f66
|
||||||
|
CENTRAL_CONTROLLER_FULL_UPDATE(354759431), //0x15253307 - CentralControllerFullUpdateIIR_t - 2021-01-07
|
||||||
|
ACCEPT_BS_INVITE(376062814), //0x166a435e - AcceptBSInviteIIR_t
|
||||||
|
ADD_PET(424562550), //0x194e4f76 - AddPetIIR_c
|
||||||
|
SET_POS(425609582), //0x195e496e - SetPosIIR_c
|
||||||
|
CLIENT_REQUEST_CLOSE_GUI(456941901), //0x1b3c614d - ClientRequestCloseGUIIIR_c - 2021-01-07
|
||||||
|
REFLECT_ATTACK(473583479), //0x1c3a4f77 - ReflectAttackIIR_t
|
||||||
|
SPECIAL_ATTACK_WEAPON(490475292), //0x1d3c0f1c - SpecialAttackWeaponIIR_t
|
||||||
|
ClientContainerAddItem (525164414), //0x1F4D5F7E - ClientContainerAddItemIIR_t - 2021-01-07
|
||||||
|
MentorInvite (536950654), //0x2001377e - MentorInviteIIR_c
|
||||||
|
Action (541676156), //0x2049527c - ActionIIR_t
|
||||||
|
Script (542066801), //0x204f4871 - ScriptIIR_t
|
||||||
|
FormatFeedback (543902579), //0x206b4b73 - FormatFeedbackIIR_t
|
||||||
|
KnuBotAnswer (553854077), //0x2103247d - KnubotAnswerIIR_c
|
||||||
|
Quest (556550266), //0x212c487a - QuestIIR_t
|
||||||
|
MineFullUpdate (559634040), //0x215b5678 - MineFullUpdateIIR_t
|
||||||
|
LookAt (575816799), //0x2252445f - LookAtIIR_t
|
||||||
|
ShieldAttack (622404726), //0x25192476 - ShieldAttackIIR_t
|
||||||
|
CastNanoSpell (623988077), //0x25314d6d - CastNanoSpellIIR_t
|
||||||
|
ResearchUpdate (624755264), //0x253D0240 - ResearchUpdateIIR - tower related?
|
||||||
|
ResearchUpdate2 (624755276), //0x253d024c
|
||||||
|
FollowTarget (638531185), //0x260f3671 - FollowTargetIIR_c
|
||||||
|
RelocateDynels (642470219), //0x264b514b - RelocateDynelsIIR_t
|
||||||
|
Absorb (642670433), //0x264e5f61 - AbsorbIIR_t
|
||||||
|
Reload (642866785), //0x26515e61 - ReloadIIR_t
|
||||||
|
KnuBotCloseChatWindow (654986338), //0x270a4c62 - KnubotCloseChatWindowIIR_c
|
||||||
|
SimpleCharFullUpdate (656095851), //0x271b3a6b - SimpleCharFullUpdateIIR_t
|
||||||
|
LockableItemFullUpdate (660555345), //0x275f4651 - LockableItemFullUpdateIIR_t - 2021-01-07
|
||||||
|
StartLogout (673521409), //0x28251f01 - StartLogoutIIR_t
|
||||||
|
Attack (675889264), //0x28494070 - AttackIIR_t
|
||||||
|
TeamMemberInfo (678969928), //0x28784248 - TeamMemberInfoIIR_t
|
||||||
|
CreateQuest (689911323), //0x291F361B - CreateQuestIIR_t - 2021-01-07
|
||||||
|
FullCharacter (691028809), //0x29304349 - FullCharacterIIR_t
|
||||||
|
LaserTargetList (691213647), //0x2933154f - LaserTagListIIR_t
|
||||||
|
TrapDisarmed (707084127), //0x2a253f5f - TrapDisarmedIIR_t
|
||||||
|
Fov (707345679), //0x2a293d0f - FovIIR_c
|
||||||
|
Stat (724778350), //0x2b333d6e - StatIIR_t
|
||||||
|
QueueUpdate (741279260), //0x2c2f061c - QueueUpdateIIR_t
|
||||||
|
KnuBotRejectedItems (757146631), //0x2d212407 - KnubotRejectedItemsIIR_c
|
||||||
|
PlayerShopFullUpdate (772221560), //0x2e072a78
|
||||||
|
OrgInfoPacket (774523499), //0x2e2a4a6b - OrgInfoPacketIIR_t
|
||||||
|
N3PlayfieldFullUpdate (806753109), //0x30161355 - n3PlayfieldFullUpdateIIR_t
|
||||||
|
ResearchRequest (823481165), //0x3115534d
|
||||||
|
AreaFormula (824779579), //0x3129233b - AreaFormulaIIR_t
|
||||||
|
InfromPlayer (855716730), //0x3301337a - InfromPlayerIIR_t
|
||||||
|
WaypointPath (858857538), //0x33312042 - WaypointPathIIR_c - 2021-01-07
|
||||||
|
Mail (859514983), //0x333b2867 - MailIIR_c
|
||||||
|
ApplySpells (875306269), //0x342c1d1d - ApplySpellsIIR_t
|
||||||
|
Bank (876357759), //0x343c287f - BankIIR_t
|
||||||
|
ShopInventory (893341522), //0x353f4f52
|
||||||
|
TemplateAction (894457412), //0x35505644 - TemplateActionIIR_t
|
||||||
|
Trade (908611438), //0x36284f6e - TradeIIR_t
|
||||||
|
Despawn (911278200), //0x36510078 - n3ToClientQuitIIR_t
|
||||||
|
DoorFullUpdate (911888497), //0x365a5071 - DoorFullUpdateIIR_t
|
||||||
|
CityAdvantages (912151899), //0x365e555b - CityAdvantagesIIR_t
|
||||||
|
HealthDamage (923805036), //0x3710256c - HealthDamageIIR_t
|
||||||
|
PickUp (924019819), //0x37136C6B - ClientGetItemIIR_t - 2021-01-07
|
||||||
|
FightModeUpdate (924648770), //0x371d0542 - FightModeUpdate_t
|
||||||
|
SetShopName (926823699), //0x373e3513
|
||||||
|
Buff (959724648), //0x39343c68 - BuffIIR_c
|
||||||
|
KnuBotTrade (974859276), //0x3a1b2c0c - KnubotTradeIIR_c
|
||||||
|
ItemReplaced (975321936), //0x3A223B50 - ItemReplacedIIR_c - 2021-01-07
|
||||||
|
DropTemplate (975454017), //0x3a243f41 - DropTemplateIIR_t
|
||||||
|
GridSelected (976366154), //0x3a322a4a - GridSelectedIIR_t
|
||||||
|
SimpleItemFullUpdate (990979439), //0x3b11256f - SimpleItemFullUpdateIIR_t
|
||||||
|
KnuBotOpenChatWindow (991112548), //0x3b132d64 - KnubotOpenChatWindowIIR_c
|
||||||
|
WeaponItemFullUpdate (991765096), //0x3b1d2268 - WeaponItemFullUpdateIIR_t
|
||||||
|
SocialActionCmd (992544625), //0x3b290771 - SocialActionCmd_t
|
||||||
|
Raid (993732728), //0x3b3b2878 - RaidIIR_c
|
||||||
|
ShadowLevel (1008609283), //0x3c1e2803 - ShadowLevelIIR_t
|
||||||
|
Clone (1009144185), //0x3c265179 - CloneIIR_t
|
||||||
|
ServerPathPosDebugInfo2 (1031040112), //0x3d746c70 - ServerPathPosDebugInfoIIR_c - 2021-01-07, might be same as ServerPathPosDebugInfo
|
||||||
|
ShopCommission (1029391684), //0x3d5b4544
|
||||||
|
ServerPathPosDebugInfo (1031040124), //0x3d746c7c - Found new hex and added as ServerPathPosDebugInfo2 2021-01-07
|
||||||
|
Skill (1042306656), //0x3e205660 - SkillIIR_t
|
||||||
|
ClientRequestDemolish (1058762608), //0x3f1b6f70 - ClientRequestDemolishIIR_c - 2021-01-07
|
||||||
|
LeaveBattle (1060772116), //0x3f3a1914 - LeaveBattleIIR_t
|
||||||
|
ShopInfo (1079725863), //0x405b4f27
|
||||||
|
AppearanceUpdate (1096961805), //0x41624f0d - AppearanceUpdateIIR_c
|
||||||
|
N3Teleport (1125743906), //0x43197d22 - n3TeleportIIR_t
|
||||||
|
PerkUpdate (1130328099), //0x435f7023 - PerkUpdateIIR
|
||||||
|
SendScore (1145584442), //0x44483b3a - SendScoreIIR_t
|
||||||
|
Resurrect (1147087371), //0x445f2a0b - ResurrectIIR_t
|
||||||
|
UpdateClientVisual (1158097419), //0x45072a0b - Found new hex and added as UpdateClientVisual2 2021-01-07
|
||||||
|
UpdateClientVisual2 (1158097453), //0x45072a2d - UpdateClientVisualIIR_t - 2021-01-07, might be same as UpdateClientVisual
|
||||||
|
HouseDemolishStart (1160199946), //0x45273f0a
|
||||||
|
PlaySound (1163733304), //0x455d2938 - PlaySoundIIR_c
|
||||||
|
AttackInfo (1174417174), //0x46002f16 - AttackInfoIIR_t
|
||||||
|
TeamMember (1177627950), //0x46312d2e - TeamMemberIIR_t
|
||||||
|
SpawnMech (1179451402), //0x464d000a - SpawnMechIIR_t
|
||||||
|
QuestFullUpdate (1180319841), //0x465a4061 - QuestFullUpdateIIR_t
|
||||||
|
ChestItemFullUpdate (1180327283), //0x465a5d73 - ChestFullUpdateIIR_t
|
||||||
|
MarketSend (1191915028), //0x470B2E14 - MarketSendIIR_c - 2021-01-07
|
||||||
|
NanoAttack (1193746750), //0x4727213e
|
||||||
|
DropDynel (1195914803), //0x47483633 - DropDynelIIR_t
|
||||||
|
ContainerAddItem (1196653092), //0x47537a24 - ContainerAddItemIIR_t
|
||||||
|
InventoryUpdated2 (1214149122), //0x485E7202 - InventoryUpdatedIIR_t - 2021-01-07
|
||||||
|
Visibility (1226974738), //0x49222612 - VisibilityIIR_t
|
||||||
|
KnubotBase (1243422725), //0x4a1d2005 - KnubotBaseIIR_c - 2021-01-07
|
||||||
|
StopFight (1245782078), //0x4a41203e - StopFightIIR_t
|
||||||
|
BattleOver (1258694937), //0x4b062919 - BattleOverIIR_t
|
||||||
|
InventoryUpdated (1264480770), //0x4b5e7202 - 2021-01-07 Found a dump where it is 0x485E7202 for InventoryUpdated (added that as InventoryUpdated2)
|
||||||
|
n3LocalityUpdate (1280508704), //0x4c530320 - n3LocalityUpdateIIR_t - 2021-01-07
|
||||||
|
DoorStatusUpdate (1283276859), //0x4c7d403b - DoorStatusUpdateIIR_t
|
||||||
|
TeamInvite2 (1294610747), //0x4d2a313b - TeamInviteIIR_t - 2021-01-07, might be same as TeamInvite
|
||||||
|
TeamInvite (1294613048), //0x4d2a3a38 - 2021-01-07 Found a dump where it is 0x4d2a313b for TeamInvite (added that as TeamInvite2)
|
||||||
|
ShopStatus (1295200295), //0x4d333027
|
||||||
|
InfoPacket (1295524910), //0x4d38242e - InfoPacketIIR_t
|
||||||
|
SpellList (1296367892), //0x4d450114 - SpellListIIR_t
|
||||||
|
RaidCmd (1314020952), //0x4E525E58 - RaidCmdIIR_c - 2021-01-07
|
||||||
|
InventoryUpdate (1314089334), //0x4e536976 - InventoryUpdateIIR_t
|
||||||
|
CorpseFullUpdate (1330073093), //0x4f474e05 - CorpseFullUpdateIIR_t
|
||||||
|
Feedback (1347702041), //0x50544d19 - FeedbackIIR_t
|
||||||
|
CharSecSpecAttack (1363747104), //0x51492120 - CharSecSpecAttackIIR_t
|
||||||
|
BankCorpse (1377907744), //0x52213420 - BankCorpseIIR_t
|
||||||
|
GenericCmd (1381132376), //0x52526858 - GenericCmd_t
|
||||||
|
PathMoveCmd (1382441770), //0x5266632a
|
||||||
|
ClientRequestBuild (1392579606), //0x53011416 - ClientRequestBuildIIR_c - 2021-01-07
|
||||||
|
ArriveAtBs (1410218791), //0x540e3b27 - ArriveAtBsIIR_t
|
||||||
|
CharDCMove (1410404643), //0x54111123 - CharDCMoveIIR_t
|
||||||
|
ClientMoveItemToInventory (1416181567), //0x5469373F - ClientMoveItemToInventoryIIR_t - 2021-01-07
|
||||||
|
PlayfieldAllTowers (1428293414), //0x55220726 - PlayfieldAllTowersIIR_t
|
||||||
|
KnuBotFinishTrade (1432890148), //0x55682b24 - KnubotFinishTradeIIR_c
|
||||||
|
KnuBotAnswerList (1433423153), //0x55704d31 - KnubotAnswerListIIR_c
|
||||||
|
ClientRequestBuy (1434019330), //0x55796602 - ClientRequestBuyIIR_c - 2021-01-07
|
||||||
|
StopLogout (1446326328), //0x56353038 - StopLogoutIIR_t
|
||||||
|
CharInPlay (1460412473), //0x570c2039 - CharInPlayIIR_t
|
||||||
|
ShopUpdate (1479942688), //0x58362220 - ShopUpdateIIR_t
|
||||||
|
MechInfo (1482113593), //0x58574239 - MechInfoIIR_t
|
||||||
|
RemovePet (1484007951), //0x58742a0f - RemovePetIIR_c
|
||||||
|
PlayfieldAllCities (1495335206), //0x59210126 - PlayfieldAllCitiesIIR_t
|
||||||
|
TrapItemFullUpdate (1496398120), //0x59313928 - TrapItemFullUpdateIIR_t
|
||||||
|
Inspect (1515741029), //0x5a585f65 - InspectIIR_c
|
||||||
|
PlayfieldTowerUpdateClient (1528694060), //0x5b1e052 - PlayfieldTowerUpdateClientIIR_t
|
||||||
|
ServerPosDebugInfo (1545864196), //0x5c240404 - ServerPosDebugInfoIIR_c
|
||||||
|
QuestAlternative (1547920905), //0x5c436609 - QuestAlternativeIIR_t
|
||||||
|
FullAuto (1548372282), //0x5c4a493a - FullAutoIIR_t
|
||||||
|
ChatCmd (1548900987), //0x5c525a7b
|
||||||
|
MissedAttackInfo (1550142248), //0x5c654b28 - MissedAttackInfoIIR_t
|
||||||
|
KnuBotAppendText (1567642410), //0x5d70532a - KnubotAppendTextIIR_c
|
||||||
|
CharacterAction (1581741936), //0x5e477770 - CharacterActionIIR_t
|
||||||
|
HouseDisappeared (1583046663), //0x5e5b6007
|
||||||
|
Impulse (1598704748), //0x5f4a4c6c - ImpulseIIR_c
|
||||||
|
PlayfieldAnarchyF (1598757433), //0x5f4b1a39 - PlayfieldAnarchyFIIR_t
|
||||||
|
ChatText (1598768170), //0x5f4b442a - ChatTextIIR_t
|
||||||
|
GameTime (1599226158), //0x5f52412e - GameTimeIIR_t
|
||||||
|
SetWantedDirection (1612717326), //0x60201d0e - SetWantedDirectionIIR_t
|
||||||
|
AoTransportSignal (1651777045), //0x62741e15 - AOTransportSignalIIR_c
|
||||||
|
PetCommand (1664299779), //0x63333303 - 2021-01-07 Found a dump where it is 0x6B333303 for PetCommand (added that as PetCommand2)
|
||||||
|
OrgServer (1683499527), //0x64582a07 - OrgServerIIR_c
|
||||||
|
PetCommand2 (1798517507), //0x6B333303 - PetCommandIIR_c - 2021-01-07 Could be a typo and/or same as PetCommand
|
||||||
|
SetStat (1851741806), //0x6e5f566e - SetStatIIR_t
|
||||||
|
SetName (1934514811), //0x734e5a7b - SetNameIIR_t
|
||||||
|
StopMovingCmd (1949180692), //0x742e2314 - StopMovingCmd_t
|
||||||
|
SpecialAttackInfo (1968115989), //0x754f1115 - SpecialAttackInfoIIR_t
|
||||||
|
GiveQuestToMember (1998784807), //0x77230927 - GiveQuestToMembersIIR_t
|
||||||
|
KnuBotStartTrade (2019835933), //0x7864401d - KnubotStartTradeIIR_c
|
||||||
|
GfxTrigger (2049057282), //0x7a222202 - GfxTriggerIIR_t
|
||||||
|
ACGQuest (2053533449), //0x7a666f09 - ACGQuestIIR_t - 2021-01-07
|
||||||
|
ShopItemPrice (2113941807), //0x7e00312f
|
||||||
|
NewLevel (2134923798), //0x7f405a16 - NewLevelIIR_t
|
||||||
|
OrgClient (2135634184), //0x7f4b3108 - OrgClientIIR_c
|
||||||
|
VendingMachineFullUpdate (2136230149); //0x7f544905 - VendingMachineFullUpdateIIR_t
|
||||||
|
"""
|
||||||
|
|
||||||
|
d = [x.strip() for x in a.split("\n")]
|
||||||
|
print(d)
|
||||||
|
for y in d:
|
||||||
|
x = y.split("(")
|
||||||
|
if m := re.sub( r"([A-Z]+)", r" \1", x[0]).split():
|
||||||
|
print("_".join([xx.upper() for xx in m])+"("+x[1])
|
||||||
+10
-17
@@ -4,9 +4,8 @@ import sys
|
|||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import mariadb
|
import mysql.connector
|
||||||
# noinspection PyProtectedMember
|
# noinspection PyProtectedMember
|
||||||
from mariadb._mariadb import ConnectionPool, OperationalError
|
|
||||||
from pkg_resources import parse_version
|
from pkg_resources import parse_version
|
||||||
|
|
||||||
from conf.config import BotConfig
|
from conf.config import BotConfig
|
||||||
@@ -23,7 +22,7 @@ class DB:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.pool_size = 4
|
self.pool_size = 4
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
self.pool: ConnectionPool = None
|
self.pool = None
|
||||||
self.enhanced_like_regex = re.compile(r"(\s+)(\S+)\s+<EXTENDED_LIKE=(\d+)>\s+\?(\s*)", re.IGNORECASE)
|
self.enhanced_like_regex = re.compile(r"(\s+)(\S+)\s+<EXTENDED_LIKE=(\d+)>\s+\?(\s*)", re.IGNORECASE)
|
||||||
self.lastrowid = None
|
self.lastrowid = None
|
||||||
self.logger = Logger(__name__)
|
self.logger = Logger(__name__)
|
||||||
@@ -40,10 +39,14 @@ class DB:
|
|||||||
self.type = self.MARIADB
|
self.type = self.MARIADB
|
||||||
self.connect_detail = {'host': host, 'port': port, 'user': username,
|
self.connect_detail = {'host': host, 'port': port, 'user': username,
|
||||||
'password': password, 'database': database_name, 'autocommit': True}
|
'password': password, 'database': database_name, 'autocommit': True}
|
||||||
self.pool = mariadb.ConnectionPool(pool_name=database_name, pool_size=self.pool_size,
|
self.pool = mysql.connector.pooling.MySQLConnectionPool(pool_name=database_name, pool_size=self.pool_size,
|
||||||
pool_reset_connection=False,
|
|
||||||
host=host, port=port, user=username, password=password,
|
host=host, port=port, user=username, password=password,
|
||||||
database=database_name, autocommit=True)
|
database=database_name, autocommit=True
|
||||||
|
)
|
||||||
|
# self.pool = mariadb.ConnectionPool(pool_name=database_name, pool_size=self.pool_size,
|
||||||
|
# pool_reset_connection=False,
|
||||||
|
# host=host, port=port, user=username, password=password,
|
||||||
|
# database=database_name, autocommit=True)
|
||||||
self.exec("SET collation_connection = 'utf8_general_ci'")
|
self.exec("SET collation_connection = 'utf8_general_ci'")
|
||||||
self.exec("SET sql_mode = 'TRADITIONAL,ANSI'")
|
self.exec("SET sql_mode = 'TRADITIONAL,ANSI'")
|
||||||
self.create_db_version_table()
|
self.create_db_version_table()
|
||||||
@@ -58,9 +61,6 @@ class DB:
|
|||||||
def _execute_wrapper(self, sql, params, callback):
|
def _execute_wrapper(self, sql, params, callback):
|
||||||
with self.lock:
|
with self.lock:
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
if self.pool.pool_size < self.pool_size - 1:
|
|
||||||
self.pool.add_connection(mariadb.connect(**self.connect_detail))
|
|
||||||
|
|
||||||
with self.pool.get_connection() as conn:
|
with self.pool.get_connection() as conn:
|
||||||
conn.auto_reconnect = True
|
conn.auto_reconnect = True
|
||||||
conn.autocommit = True
|
conn.autocommit = True
|
||||||
@@ -74,16 +74,9 @@ class DB:
|
|||||||
if string.__contains__("UPDATE ") or string.__contains__("INSERT "):
|
if string.__contains__("UPDATE ") or string.__contains__("INSERT "):
|
||||||
conn.commit()
|
conn.commit()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
print(sql, params)
|
||||||
raise SqlException(f"SQL Error: '{str(e)}' for '{sql}' "
|
raise SqlException(f"SQL Error: '{str(e)}' for '{sql}' "
|
||||||
f"[{', '.join(map(lambda x: str(x), params))}]") from e
|
f"[{', '.join(map(lambda x: str(x), params))}]") from e
|
||||||
except mariadb.OperationalError as e:
|
|
||||||
self.logger.error("Please use 'FLUSH TABLES;' inside of the DB, and consider upping the 'table_definition_cache' value of the Database Server.", e)
|
|
||||||
time.sleep(30)
|
|
||||||
exit(-3)
|
|
||||||
except mariadb.PoolError as e:
|
|
||||||
self.logger.error("No Connections available for the Connection Pool. Restarting in 30 seconds...", e)
|
|
||||||
time.sleep(30)
|
|
||||||
exit(-2)
|
|
||||||
elapsed = time.time() - start_time
|
elapsed = time.time() - start_time
|
||||||
result = callback(cur)
|
result = callback(cur)
|
||||||
if elapsed > 5:
|
if elapsed > 5:
|
||||||
|
|||||||
+3
-3
@@ -133,9 +133,9 @@ class IgnCore:
|
|||||||
registry.start_all()
|
registry.start_all()
|
||||||
if self.db.shared != self.db:
|
if self.db.shared != self.db:
|
||||||
self.db: DB
|
self.db: DB
|
||||||
self.db.shared.pool.close()
|
# self.db.shared.pool.close()
|
||||||
# Creates a Exception for some reason??
|
# Creates an Exception for some reason??
|
||||||
# self.db.shared = None
|
self.db.shared = None
|
||||||
|
|
||||||
# remove commands, events, and settings that are no longer registered
|
# remove commands, events, and settings that are no longer registered
|
||||||
# self.db.exec("DELETE FROM db_version WHERE verified = 0")
|
# self.db.exec("DELETE FROM db_version WHERE verified = 0")
|
||||||
|
|||||||
@@ -236,8 +236,8 @@ class PorkService:
|
|||||||
"SELECT char_id, name, first_name, last_name, level, breed, gender, faction, profession, "
|
"SELECT char_id, name, first_name, last_name, level, breed, gender, faction, profession, "
|
||||||
"profession_title, ai_rank, ai_level, org_id, org_name, org_rank_name, org_rank_id, "
|
"profession_title, ai_rank, ai_level, org_id, org_name, org_rank_name, org_rank_id, "
|
||||||
"dimension, head_id, pvp_rating, pvp_title, source, last_updated "
|
"dimension, head_id, pvp_rating, pvp_title, source, last_updated "
|
||||||
"FROM player WHERE char_id = ?",
|
"FROM player WHERE char_id = %s",
|
||||||
[packet.char_id])
|
(packet.char_id,))
|
||||||
data = cur.fetchone()
|
data = cur.fetchone()
|
||||||
character = None
|
character = None
|
||||||
if data:
|
if data:
|
||||||
@@ -249,9 +249,9 @@ class PorkService:
|
|||||||
inserts.append((packet.char_id, packet.name, "", "", 0, "", "", "", "", "", "", 0, 0, "", "", 6,
|
inserts.append((packet.char_id, packet.name, "", "", 0, "", "", "", "", "", "", 0, 0, "", "", 6,
|
||||||
self.bot.dimension, 0, 0, "", "chat_server", int(time.time())))
|
self.bot.dimension, 0, 0, "", "chat_server", int(time.time())))
|
||||||
if inserts:
|
if inserts:
|
||||||
cur.executemany(insert, inserts)
|
cur.executemany(insert.replace("?", "%s"), inserts)
|
||||||
if updates:
|
if updates:
|
||||||
cur.executemany(update, updates)
|
cur.executemany(update.replace("?", "%s"), updates)
|
||||||
self.updates = []
|
self.updates = []
|
||||||
|
|
||||||
# noinspection SqlResolve
|
# noinspection SqlResolve
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ class Registry:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def pre_start_all(cls):
|
def pre_start_all(cls):
|
||||||
# call pre_start() on instances so they can start any init() processes
|
# call pre_start() on instances, so they can start any init() processes
|
||||||
mods = cls.get_instance("bot").modules
|
mods = cls.get_instance("bot").modules
|
||||||
for key in cls._registry:
|
for key in cls._registry:
|
||||||
if str(cls._registry[key].module_name).split(".")[0] not in mods:
|
if str(cls._registry[key].module_name).split(".")[0] not in mods:
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ class DiscordCommandHandler(BaseModule):
|
|||||||
if type(reply) == str:
|
if type(reply) == str:
|
||||||
reply = self.discord.text.format_message(reply)
|
reply = self.discord.text.format_message(reply)
|
||||||
rsp = f"> {self.parseDiscord(reply)}"
|
rsp = f"> {self.parseDiscord(reply)}"
|
||||||
|
|
||||||
|
# Sender == init? Should be Sender == bot
|
||||||
self.discord.relay_hub_service.send_message(f"Discord_({ctx.channel.name})",
|
self.discord.relay_hub_service.send_message(f"Discord_({ctx.channel.name})",
|
||||||
DictObject({'char_id': 0, 'name': ctx.author.name,
|
DictObject({'char_id': 0, 'name': ctx.author.name,
|
||||||
'discord_handle':
|
'discord_handle':
|
||||||
@@ -87,6 +89,8 @@ class DiscordCommandHandler(BaseModule):
|
|||||||
rsp += f"**__{reply.title}__**\n"
|
rsp += f"**__{reply.title}__**\n"
|
||||||
rsp += self.parseDiscord(reply.msg, blob=True)
|
rsp += self.parseDiscord(reply.msg, blob=True)
|
||||||
rsp += f"\n {self.parseDiscord(reply.page_postfix)}"
|
rsp += f"\n {self.parseDiscord(reply.page_postfix)}"
|
||||||
|
|
||||||
|
# Sender == init? Should be Sender == bot
|
||||||
self.discord.relay_hub_service.send_message(f"Discord_({ctx.channel.name})",
|
self.discord.relay_hub_service.send_message(f"Discord_({ctx.channel.name})",
|
||||||
DictObject({'char_id': 0, 'name': ctx.author.name,
|
DictObject({'char_id': 0, 'name': ctx.author.name,
|
||||||
'discord_handle':
|
'discord_handle':
|
||||||
@@ -151,6 +155,7 @@ class DiscordCommandHandler(BaseModule):
|
|||||||
(r"<a href=(.*?)itemid://(\d+)/(\d+)\1>(.+?)<\/a>", r"[\4](https://aoitems.com/item/\2/\3/)" if blob else r"`\4`"),
|
(r"<a href=(.*?)itemid://(\d+)/(\d+)\1>(.+?)<\/a>", r"[\4](https://aoitems.com/item/\2/\3/)" if blob else r"`\4`"),
|
||||||
(r"<(.+?)>\s*?<\1>", ''),
|
(r"<(.+?)>\s*?<\1>", ''),
|
||||||
(r"<pagebreak>", ''),
|
(r"<pagebreak>", ''),
|
||||||
|
(r"<a.+?href=\'.*?\'><img.+?></a>", r''),
|
||||||
(r"<a.+?href=\'.*?\'>(.*?)</a>", r'`\1`'),
|
(r"<a.+?href=\'.*?\'>(.*?)</a>", r'`\1`'),
|
||||||
(r"<clan>(.*?)</clan>", r":yellow_circle: \1"),
|
(r"<clan>(.*?)</clan>", r":yellow_circle: \1"),
|
||||||
(r"<omni>(.*?)</omni>", r":blue_circle: \1"),
|
(r"<omni>(.*?)</omni>", r":blue_circle: \1"),
|
||||||
@@ -229,14 +234,15 @@ class DiscordCommandHandler(BaseModule):
|
|||||||
if not self.discord.client:
|
if not self.discord.client:
|
||||||
return "Discord module has not been initiated yet. Please try again later."
|
return "Discord module has not been initiated yet. Please try again later."
|
||||||
blob = ""
|
blob = ""
|
||||||
for member in self.discord.guild.members:
|
for member in sorted(self.discord.guild.members, key=lambda x: x.display_name):
|
||||||
member_roles = []
|
member_roles = []
|
||||||
for role in member.roles:
|
for role in member.roles:
|
||||||
if role.name == "@everyone": # Skip @everyone as everyone has it.
|
if role.name == "@everyone": # Skip @everyone as everyone has it.
|
||||||
continue
|
continue
|
||||||
member_roles.append(f"{role.name}")
|
member_roles.append(f"{role.name}")
|
||||||
member_roles.sort(key=str.lower)
|
member_roles.sort(key=str.lower)
|
||||||
blob += f"{member.name + '#' + member.discriminator} ({', '.join(member_roles)})\n"
|
# blob += f"{member.name + '#' + member.discriminator} ({', '.join(member_roles)})\n"
|
||||||
|
blob += f"- <highlight>{member.display_name}</highlight> [{member.name + '#' + member.discriminator}] ({', '.join(member_roles)})<br>"
|
||||||
return ChatBlob(f"Discord Members ({len(self.discord.guild.members):d})", blob)
|
return ChatBlob(f"Discord Members ({len(self.discord.guild.members):d})", blob)
|
||||||
|
|
||||||
@event(event_type="connect", description="Connects the Discord client automatically on startup, if a token exists")
|
@event(event_type="connect", description="Connects the Discord client automatically on startup, if a token exists")
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ class PrivateChannelController:
|
|||||||
self.online_controller = registry.get_instance("online_controller", is_optional=True)
|
self.online_controller = registry.get_instance("online_controller", is_optional=True)
|
||||||
|
|
||||||
def pre_start(self):
|
def pre_start(self):
|
||||||
self.db.create_view("online")
|
|
||||||
self.message_hub_service.register_message_source(self.MESSAGE_SOURCE)
|
self.message_hub_service.register_message_source(self.MESSAGE_SOURCE)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -58,6 +57,8 @@ class PrivateChannelController:
|
|||||||
self.reinvite = []
|
self.reinvite = []
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
self.db.create_view("online")
|
||||||
|
|
||||||
self.message_hub_service.register_message_destination(self.MESSAGE_SOURCE,
|
self.message_hub_service.register_message_destination(self.MESSAGE_SOURCE,
|
||||||
self.handle_incoming_relay_message,
|
self.handle_incoming_relay_message,
|
||||||
["registration"],
|
["registration"],
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ class OrgController:
|
|||||||
"member_count=VALUE(member_count), "
|
"member_count=VALUE(member_count), "
|
||||||
"last_seen=VALUE(last_seen)",
|
"last_seen=VALUE(last_seen)",
|
||||||
data)
|
data)
|
||||||
self.db.exec("DELETE FROM all_orgs where last_seen < ?", [time.time() - 2 * 24 * 60 * 60])
|
# self.db.exec("DELETE FROM all_orgs where last_seen < ?", [time.time() - 2 * 24 * 60 * 60])
|
||||||
self.logger.info(f"Successfully fetched {count} orgs in {time.time() - start:.2f} seconds.")
|
self.logger.info(f"Successfully fetched {count} orgs in {time.time() - start:.2f} seconds.")
|
||||||
self.threads.pop('orgdiscover', None)
|
self.threads.pop('orgdiscover', None)
|
||||||
|
|
||||||
|
|||||||
@@ -414,12 +414,26 @@ class AllianceRelay:
|
|||||||
if self.discord.guild and self.discord.bot:
|
if self.discord.guild and self.discord.bot:
|
||||||
name = f"<header2>DC Server: <highlight>{self.discord.guild.name}</highlight> - " \
|
name = f"<header2>DC Server: <highlight>{self.discord.guild.name}</highlight> - " \
|
||||||
f"Bot: <highlight><myname></highlight></header2>"
|
f"Bot: <highlight><myname></highlight></header2>"
|
||||||
|
nick = ctx.sender.discord_nick if ctx.sender.get('discord_nick', None) \
|
||||||
|
else self.discord.client.user.display_name if ctx.sender.char_id == self.bot.get_char_id() else None
|
||||||
|
if nick:
|
||||||
blob = self.text.format_page('Info',
|
blob = self.text.format_page('Info',
|
||||||
f"<header>::: Information :::</header><br><br>"
|
f"<header>::: Information :::</header><br><br>"
|
||||||
f"This message has been sent to you by:<br><br>"
|
f"This message has been sent to you by:<br><br>"
|
||||||
f"{name}<br>"
|
f"{name}<br>"
|
||||||
f"<tab>Sender: <notice>{ctx.sender.name}</notice><br>"
|
f"<tab>Sender: <notice>{ctx.sender.name}</notice><br>"
|
||||||
f"<tab>Tag: <highlight>{ctx.sender.discord_nick}</highlight><br><br>"
|
f"<tab>Tag: <highlight>{nick}</highlight><br><br>" # Bot ha sno nick!!
|
||||||
|
f"To reply, either respond in the relay or "
|
||||||
|
f"contact them directly at the provided handles.<br><br>"
|
||||||
|
f"<header2>Have you joined our Discord Server yet? "
|
||||||
|
f"If not <highlight>{invite}</highlight> to receive an invite.</header2>")
|
||||||
|
else:
|
||||||
|
blob = self.text.format_page('Info',
|
||||||
|
f"<header>::: Information :::</header><br><br>"
|
||||||
|
f"This message has been sent to you by:<br><br>"
|
||||||
|
f"{name}<br>"
|
||||||
|
f"<tab>Sender: <notice><myname></notice><br>"
|
||||||
|
f"<tab>Tag: <highlight>{self.discord.client.user.display_name}</highlight><br><br>" # Bot has no nick!!
|
||||||
f"To reply, either respond in the relay or "
|
f"To reply, either respond in the relay or "
|
||||||
f"contact them directly at the provided handles.<br><br>"
|
f"contact them directly at the provided handles.<br><br>"
|
||||||
f"<header2>Have you joined our Discord Server yet? "
|
f"<header2>Have you joined our Discord Server yet? "
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ class AOUController:
|
|||||||
obj.profession = guide_info.profession
|
obj.profession = guide_info.profession
|
||||||
obj.faction = guide_info.faction
|
obj.faction = guide_info.faction
|
||||||
obj.level = guide_info.level
|
obj.level = guide_info.level
|
||||||
obj.author = self.format_bbcode_code(guide_info.author)
|
obj.author = self.format_bbcode_code(guide_info.author or "Author Unknown")
|
||||||
obj.aou = self.text.make_chatcmd("AO-Universe.com", "/start https://www.ao-universe.com")
|
obj.aou = self.text.make_chatcmd("AO-Universe.com", "/start https://www.ao-universe.com")
|
||||||
obj.text = self.format_bbcode_code(guide_info.text)
|
obj.text = self.format_bbcode_code(guide_info.text)
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,14 @@ class RandomController:
|
|||||||
self.character_service = registry.get_instance("character_service")
|
self.character_service = registry.get_instance("character_service")
|
||||||
self.command_alias_service = registry.get_instance("command_alias_service")
|
self.command_alias_service = registry.get_instance("command_alias_service")
|
||||||
|
|
||||||
def start(self):
|
def pre_start(self):
|
||||||
self.db.exec("CREATE TABLE IF NOT EXISTS roll (id INT PRIMARY KEY AUTO_INCREMENT, "
|
self.db.shared.exec("CREATE TABLE IF NOT EXISTS roll (id INT PRIMARY KEY AUTO_INCREMENT, "
|
||||||
"created_at INT NOT NULL, "
|
"created_at INT NOT NULL, "
|
||||||
"char_id INT NOT NULL, "
|
"char_id INT NOT NULL, "
|
||||||
"options VARCHAR(2048), "
|
"options VARCHAR(2048), "
|
||||||
"result VARCHAR(255))")
|
"result VARCHAR(255))")
|
||||||
|
|
||||||
|
def start(self):
|
||||||
self.db.create_view("roll")
|
self.db.create_view("roll")
|
||||||
self.command_alias_service.add_alias("verify", "roll verify")
|
self.command_alias_service.add_alias("verify", "roll verify")
|
||||||
self.command_alias_service.add_alias("lootorder", "random")
|
self.command_alias_service.add_alias("lootorder", "random")
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ class ItemsController:
|
|||||||
blob += self.format_items(items, ql)
|
blob += self.format_items(items, ql)
|
||||||
blob += head_foot
|
blob += head_foot
|
||||||
# noinspection LongLine
|
# noinspection LongLine
|
||||||
blob += f"\nItem DB rips created using the {self.text.make_chatcmd('Budabot Items Extractor', '/start https://github.com/Budabot/ItemsExtractor')} tool."
|
blob += f"\nItem DB rips created using a modified version of the {self.text.make_chatcmd('Items Extractor', '/start https://github.com/Budabot/ItemsExtractor')} tool."
|
||||||
|
|
||||||
return ChatBlob(
|
return ChatBlob(
|
||||||
f"Item Search Results ({offset + 1:d} - {min(offset + self.PAGE_SIZE, len(all_items)):d} "
|
f"Item Search Results ({offset + 1:d} - {min(offset + self.PAGE_SIZE, len(all_items)):d} "
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ class LootController:
|
|||||||
f"{loot_item.get_item_str()}",
|
f"{loot_item.get_item_str()}",
|
||||||
request.sender.char_id)
|
request.sender.char_id)
|
||||||
blob += f"{i:d}. {loot_item.get_item_str()}\n"
|
blob += f"{i:d}. {loot_item.get_item_str()}\n"
|
||||||
blob += f" | Winners: <red>{'</red>, <red>'.join(winners)}</red>\n\n"
|
blob += f" | Winners: <yellow>{'</yellow>, <yellow>'.join(winners)}</yellow>\n\n"
|
||||||
if loot_item.count == 0:
|
if loot_item.count == 0:
|
||||||
remove.append(i)
|
remove.append(i)
|
||||||
for i in remove:
|
for i in remove:
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ class NanoController:
|
|||||||
profession = "Martial Artist"
|
profession = "Martial Artist"
|
||||||
strain = strain[7:]
|
strain = strain[7:]
|
||||||
nanoline = self.db.query_single(
|
nanoline = self.db.query_single(
|
||||||
"SELECT * FROM nanos n WHERE n.strain LIKE ? AND profession =? and type='Crystal' LIMIT 1",
|
"SELECT * FROM nanos n WHERE n.strain LIKE ? AND profession =? and type in ('Crystal', 'Misc') LIMIT 1",
|
||||||
[strain, profession])
|
[strain, profession])
|
||||||
|
|
||||||
if not nanoline:
|
if not nanoline:
|
||||||
@@ -174,7 +174,7 @@ class NanoController:
|
|||||||
"SELECT n.* FROM nanos n "
|
"SELECT n.* FROM nanos n "
|
||||||
"where n.strain LIKE ? "
|
"where n.strain LIKE ? "
|
||||||
"and n.profession = ? "
|
"and n.profession = ? "
|
||||||
"and type='Crystal' "
|
"and type in ('Crystal', 'Misc') "
|
||||||
"group by nano_id "
|
"group by nano_id "
|
||||||
"ORDER BY n.strain, n.ql DESC, n.nano_name",
|
"ORDER BY n.strain, n.ql DESC, n.nano_name",
|
||||||
["%" + strain.replace(" ", "%") + "%", profession])
|
["%" + strain.replace(" ", "%") + "%", profession])
|
||||||
@@ -193,6 +193,10 @@ class NanoController:
|
|||||||
|
|
||||||
return ChatBlob("%s %s Nanos" % (nanoline.profession, str(nanoline.strain).replace("_", " ")), blob)
|
return ChatBlob("%s %s Nanos" % (nanoline.profession, str(nanoline.strain).replace("_", " ")), blob)
|
||||||
|
|
||||||
|
# @command(command='disc', params=[Any("search")], access_level="member",
|
||||||
|
# description="Search for the disc to a Crystal, or the other way around.")
|
||||||
|
# def disc_search_command(self, req, search):
|
||||||
|
# pass
|
||||||
@command(command="nanolines", params=[Any("profession")], access_level="member",
|
@command(command="nanolines", params=[Any("profession")], access_level="member",
|
||||||
description="Show nanolines by profession")
|
description="Show nanolines by profession")
|
||||||
def nanolines_profession_cmd(self, _, prof_name):
|
def nanolines_profession_cmd(self, _, prof_name):
|
||||||
@@ -204,7 +208,7 @@ class NanoController:
|
|||||||
"SELECT CASE WHEN strain = 'Composite' THEN 'Composite' ELSE school END as school, strain, profession "
|
"SELECT CASE WHEN strain = 'Composite' THEN 'Composite' ELSE school END as school, strain, profession "
|
||||||
"FROM nanos WHERE Profession = ? "
|
"FROM nanos WHERE Profession = ? "
|
||||||
"and location not like 'No%longer%drops' "
|
"and location not like 'No%longer%drops' "
|
||||||
"and type not in ('Tainted', 'Misc') "
|
"and type not in ('Tainted') "
|
||||||
"GROUP by strain ORDER BY school, strain='Composite', strain", [profession])
|
"GROUP by strain ORDER BY school, strain='Composite', strain", [profession])
|
||||||
|
|
||||||
blob = ""
|
blob = ""
|
||||||
|
|||||||
@@ -33,8 +33,6 @@ class NewsController:
|
|||||||
"Hei", "Salut", "Helló", "Halló", "Ciao", "Olá", "Ahoj", "¡Hola"]
|
"Hei", "Salut", "Helló", "Halló", "Ciao", "Olá", "Ahoj", "¡Hola"]
|
||||||
layout = \
|
layout = \
|
||||||
"""
|
"""
|
||||||
<header>News</header>
|
|
||||||
|
|
||||||
<notice>CURRENT TIME</notice>
|
<notice>CURRENT TIME</notice>
|
||||||
hh:mm - DD.MM.YYYY
|
hh:mm - DD.MM.YYYY
|
||||||
{time}
|
{time}
|
||||||
@@ -173,9 +171,9 @@ hh:mm - DD.MM.YYYY
|
|||||||
last_updated = f"[{self.util.time_to_readable(datetime.utcfromtimestamp(time.time()).timestamp() - last_updated)} ago]"
|
last_updated = f"[{self.util.time_to_readable(datetime.utcfromtimestamp(time.time()).timestamp() - last_updated)} ago]"
|
||||||
else:
|
else:
|
||||||
last_updated = ""
|
last_updated = ""
|
||||||
blob = f"<yellow>{random.choice(self.greetings)} {sender.name} :: " \
|
blob = ChatBlob('Your News', textwrap.dedent(news),
|
||||||
f"{self.text.format_page('Your News', textwrap.dedent(news))} </yellow>{last_updated} " \
|
prefix=f"<yellow>{random.choice(self.greetings)} {sender.name} :: ",
|
||||||
f"{f'<yellow>::</yellow> {name} running' if next_event.is_running() else ''}"
|
suffix=f"</yellow> {last_updated} {f'<yellow>::</yellow> {name} running' if next_event.is_running() else ''}")
|
||||||
self.bot.send_mass_message(sender.char_id, blob)
|
self.bot.send_mass_message(sender.char_id, blob)
|
||||||
if self.preview_recent().get_value() and auto:
|
if self.preview_recent().get_value() and auto:
|
||||||
entry = self.get_newest_entry()
|
entry = self.get_newest_entry()
|
||||||
|
|||||||
@@ -23,16 +23,19 @@ class RecipeController:
|
|||||||
self.items_controller = registry.get_instance("items_controller")
|
self.items_controller = registry.get_instance("items_controller")
|
||||||
self.command_alias_service = registry.get_instance("command_alias_service")
|
self.command_alias_service = registry.get_instance("command_alias_service")
|
||||||
|
|
||||||
def start(self):
|
def pre_start(self):
|
||||||
self.command_alias_service.add_alias("r", "recipe")
|
self.db.shared.exec("CREATE TABLE IF NOT EXISTS recipe ("
|
||||||
self.command_alias_service.add_alias("tradeskill", "recipe")
|
|
||||||
|
|
||||||
self.db.exec("CREATE TABLE IF NOT EXISTS recipe ("
|
|
||||||
"id INT NOT NULL PRIMARY KEY, "
|
"id INT NOT NULL PRIMARY KEY, "
|
||||||
"name VARCHAR(50) NOT NULL, "
|
"name VARCHAR(50) NOT NULL, "
|
||||||
"author VARCHAR(50) NOT NULL, "
|
"author VARCHAR(50) NOT NULL, "
|
||||||
"recipe TEXT NOT NULL, "
|
"recipe TEXT NOT NULL, "
|
||||||
"dt INT NOT NULL DEFAULT 0)")
|
"dt INT NOT NULL DEFAULT 0)")
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.command_alias_service.add_alias("r", "recipe")
|
||||||
|
self.command_alias_service.add_alias("tradeskill", "recipe")
|
||||||
|
|
||||||
|
|
||||||
self.db.create_view("recipe")
|
self.db.create_view("recipe")
|
||||||
recipe_dir = os.path.dirname(os.path.realpath(__file__)) + "/recipes/"
|
recipe_dir = os.path.dirname(os.path.realpath(__file__)) + "/recipes/"
|
||||||
recipes = self.db.query("SELECT id, dt FROM recipe")
|
recipes = self.db.query("SELECT id, dt FROM recipe")
|
||||||
|
|||||||
@@ -467,7 +467,7 @@ class SpecialsController:
|
|||||||
result.hard_cap = weapon_attack + 5
|
result.hard_cap = weapon_attack + 5
|
||||||
result.skill_cap = ((weapon_attack * 16) - result.hard_cap) * 100
|
result.skill_cap = ((weapon_attack * 16) - result.hard_cap) * 100
|
||||||
|
|
||||||
recharge = (weapon_attack * 16) - (fast_attack_skill / 100)
|
recharge = (weapon_attack * 16) - (fast_attack_skill / 100) # same
|
||||||
if recharge < result.hard_cap:
|
if recharge < result.hard_cap:
|
||||||
recharge = result.hard_cap
|
recharge = result.hard_cap
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,25 @@
|
|||||||
|
import datetime
|
||||||
|
import json
|
||||||
import math
|
import math
|
||||||
|
import time
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
from core.aochat.BaseModule import BaseModule
|
from core.aochat.BaseModule import BaseModule
|
||||||
from core.aochat.server_packets import BuddyAdded
|
from core.aochat.server_packets import BuddyAdded
|
||||||
from core.buddy_service import BuddyService
|
from core.buddy_service import BuddyService
|
||||||
|
from core.cache_service import CacheService
|
||||||
from core.chat_blob import ChatBlob
|
from core.chat_blob import ChatBlob
|
||||||
from core.command_param_types import Character, Options, Const, Any, NamedParameters
|
from core.command_param_types import Character, Options, Const, Any, NamedParameters
|
||||||
from core.db import DB
|
from core.db import DB
|
||||||
from core.decorators import instance, command, event
|
from core.decorators import instance, command, event, timerevent
|
||||||
from core.dict_object import DictObject
|
from core.dict_object import DictObject
|
||||||
from core.event_service import EventService
|
from core.event_service import EventService
|
||||||
from core.igncore import IgnCore
|
from core.igncore import IgnCore
|
||||||
from core.job_scheduler import JobScheduler
|
from core.job_scheduler import JobScheduler
|
||||||
|
from core.logger import Logger
|
||||||
|
from core.lookup.org_pork_service import OrgPorkService
|
||||||
from core.lookup.pork_service import PorkService
|
from core.lookup.pork_service import PorkService
|
||||||
from core.message_hub_service import MessageHubService
|
from core.message_hub_service import MessageHubService
|
||||||
from core.private_channel_service import PrivateChannelService
|
from core.private_channel_service import PrivateChannelService
|
||||||
@@ -25,11 +34,14 @@ from modules.standard.tower.tower_events import TowerEventController
|
|||||||
# noinspection DuplicatedCode,SqlCaseVsIf
|
# noinspection DuplicatedCode,SqlCaseVsIf
|
||||||
@instance()
|
@instance()
|
||||||
class TrackController(BaseModule):
|
class TrackController(BaseModule):
|
||||||
|
threads = {}
|
||||||
|
single_org_uri = "https://people.anarchy-online.com/org/stats/d/5/name/%d/basicstats.xml?data_type=json"
|
||||||
PRIVATE_CHANNEL_PREFIX = "[Priv]"
|
PRIVATE_CHANNEL_PREFIX = "[Priv]"
|
||||||
PAGE_SIZE = 20
|
PAGE_SIZE = 20
|
||||||
MESSAGE_SOURCE = "track_log"
|
MESSAGE_SOURCE = "track_log"
|
||||||
|
|
||||||
def inject(self, registry):
|
def inject(self, registry):
|
||||||
|
self.logger = Logger("TRACK")
|
||||||
self.bot: IgnCore = registry.get_instance("bot")
|
self.bot: IgnCore = registry.get_instance("bot")
|
||||||
self.util: Util = registry.get_instance("util")
|
self.util: Util = registry.get_instance("util")
|
||||||
self.pork: PorkService = registry.get_instance("pork_service")
|
self.pork: PorkService = registry.get_instance("pork_service")
|
||||||
@@ -43,6 +55,10 @@ class TrackController(BaseModule):
|
|||||||
self.priv: PrivateChannelService = registry.get_instance("private_channel_service")
|
self.priv: PrivateChannelService = registry.get_instance("private_channel_service")
|
||||||
self.tower: TowerEventController = registry.get_instance("tower_controller")
|
self.tower: TowerEventController = registry.get_instance("tower_controller")
|
||||||
self.message_hub_service: MessageHubService = registry.get_instance("message_hub_service")
|
self.message_hub_service: MessageHubService = registry.get_instance("message_hub_service")
|
||||||
|
self.org_pork: OrgPorkService = registry.get_instance("org_pork_service")
|
||||||
|
self.cache: CacheService = registry.get_instance("cache_service")
|
||||||
|
self.relay_hub_service: MessageHubService = registry.get_instance("message_hub_service")
|
||||||
|
|
||||||
|
|
||||||
def pre_start(self):
|
def pre_start(self):
|
||||||
self.event_service.register_event_type("track_logon")
|
self.event_service.register_event_type("track_logon")
|
||||||
@@ -59,18 +75,22 @@ class TrackController(BaseModule):
|
|||||||
"char_id int not null primary key, "
|
"char_id int not null primary key, "
|
||||||
"initiator int not null, "
|
"initiator int not null, "
|
||||||
"reason varchar(255))")
|
"reason varchar(255))")
|
||||||
|
self.db.exec("CREATE TABLE IF NOT EXISTS track_orgs(org_id int not null primary key, initiator int not null)")
|
||||||
|
self.db.exec("CREATE TABLE IF NOT EXISTS track_org_members(char_id int not null, org_id int not null)")
|
||||||
self.message_hub_service.register_message_source(self.MESSAGE_SOURCE)
|
self.message_hub_service.register_message_source(self.MESSAGE_SOURCE)
|
||||||
|
|
||||||
@event(event_type="connect", description="Autoadd tracked players on connect", is_hidden=True)
|
@event(event_type="connect", description="Autoadd tracked players on connect", is_hidden=True)
|
||||||
def connect_add(self, _1, _2):
|
def connect_add(self, _1, _2):
|
||||||
query = self.db.query("SELECT * from track")
|
for user in self.db.query("SELECT * from track"):
|
||||||
for user in query:
|
self.buddy_service.add_buddy(user.char_id, "track")
|
||||||
|
for user in self.db.query("SELECT char_id FROM track_org_members"):
|
||||||
self.buddy_service.add_buddy(user.char_id, "track")
|
self.buddy_service.add_buddy(user.char_id, "track")
|
||||||
|
|
||||||
@event(event_type="buddy_logon", description="Fire tracker events", is_hidden=True)
|
@event(event_type="buddy_logon", description="Fire tracker events", is_hidden=True)
|
||||||
def track_fire_logon(self, _, event_data):
|
def track_fire_logon(self, _, event_data):
|
||||||
if self.bot.is_ready():
|
if self.bot.is_ready():
|
||||||
if "track" in (self.buddy_service.get_buddy(event_data.char_id) or {'types': []})["types"]:
|
if "track" in (self.buddy_service.get_buddy(event_data.char_id) or {'types': []})["types"]:
|
||||||
|
print("Login: ", event_data.char_id)
|
||||||
if type(event_data) == BuddyAdded:
|
if type(event_data) == BuddyAdded:
|
||||||
self.event_service.fire_event("track_logon",
|
self.event_service.fire_event("track_logon",
|
||||||
self.db.query_single("SELECT * from player where char_id=?",
|
self.db.query_single("SELECT * from player where char_id=?",
|
||||||
@@ -144,6 +164,59 @@ class TrackController(BaseModule):
|
|||||||
self.db.exec("INSERT IGNORE INTO track VALUES(?, ?, ?)",
|
self.db.exec("INSERT IGNORE INTO track VALUES(?, ?, ?)",
|
||||||
[user.char_id, acc.main, reason])
|
[user.char_id, acc.main, reason])
|
||||||
|
|
||||||
|
@command(command="orgtrack", params=[Const('add'), Any("Organisation")], access_level="moderator",
|
||||||
|
description="Initiate tracking for an Organisation", sub_command="add")
|
||||||
|
def track_addorg(self, request, _, search):
|
||||||
|
orgs = self.org_pork.find_org(search)
|
||||||
|
if len(orgs) == 1:
|
||||||
|
orgs = orgs[0]
|
||||||
|
if self.db.exec("REPLACE INTO track_orgs(org_id, initiator) VALUES(?, ?)",
|
||||||
|
[orgs.org_id, request.sender.char_id]) == 1:
|
||||||
|
request.reply(f"Adding the organisation <highlight>{orgs.org_name}</highlight> to the tracking...")
|
||||||
|
org_adder = Thread(name=orgs.org_id, target=self.fetch_single,
|
||||||
|
args=(orgs.org_id, orgs.org_name, request))
|
||||||
|
self.threads[orgs.org_id] = org_adder
|
||||||
|
org_adder.start()
|
||||||
|
else:
|
||||||
|
return f"The organisation <highlight>{orgs.org_name}</highlight> is already being tracked."
|
||||||
|
elif len(orgs) == 0:
|
||||||
|
return f"No org with the name <highlight>{search}</highlight> was found on PoRK."
|
||||||
|
else:
|
||||||
|
blob = "Your search had multiple results; please pick an org:<br>"
|
||||||
|
for org in orgs:
|
||||||
|
blob += f'[{self.text.make_chatcmd("Add", f"/tell <myname> orgtrack add {org.org_id}")}]' \
|
||||||
|
f'[{self.text.make_chatcmd("More", f"/tell <myname> org info {org.org_id}")}]' \
|
||||||
|
f' <highlight>{org.org_name}</highlight> (<highlight>{org.org_id}</highlight>) ' \
|
||||||
|
f'<{org.faction.lower()}>{org.faction}</{org.faction.lower()}> [<highlight>{org.member_count}</highlight> members]' \
|
||||||
|
f'<br><pagebreak>'
|
||||||
|
return ChatBlob("Pick an Org", blob)
|
||||||
|
|
||||||
|
@command(command="orgtrack", params=[Const("rem"), Any("Organisation")], access_level="moderator",
|
||||||
|
description="Add an organisation to the tracking", sub_command="rem")
|
||||||
|
def orgtrack_rem(self, request, _, search):
|
||||||
|
orgs = self.org_pork.find_org(search)
|
||||||
|
orgs = [x for x in orgs if x.org_name.lower().startswith(search.lower()) or (x.org_id == int(search) if search.isdigit() else False)]
|
||||||
|
if len(orgs) == 1:
|
||||||
|
orgs = orgs[0]
|
||||||
|
if self.db.exec("DELETE FROM track_orgs where org_id = ?", [orgs.org_id]) == 1:
|
||||||
|
org_remover = Thread(name=orgs.org_id, target=self.remove_single, args=(orgs.org_id, orgs.org_name))
|
||||||
|
self.threads[orgs.org_id] = org_remover
|
||||||
|
org_remover.start()
|
||||||
|
return f"Removed the organisation <highlight>{orgs.org_name}</highlight> from the roster."
|
||||||
|
else:
|
||||||
|
return f"The organisation <highlight>{orgs.org_name}</highlight> is not on the roster list."
|
||||||
|
elif len(orgs) == 0:
|
||||||
|
return f"The organisation <highlight>{search}</highlight> is not on the roster list."
|
||||||
|
else:
|
||||||
|
blob = "Your search had multiple results; please pick an org:<br>"
|
||||||
|
for org in orgs:
|
||||||
|
blob += f'[{self.text.make_chatcmd("Remove", f"/tell <myname> orgtrack rem {org.org_id}")}]' \
|
||||||
|
f'[{self.text.make_chatcmd("More", f"/tell <myname> org info {org.org_id}")}]' \
|
||||||
|
f' <highlight>{org.org_name}</highlight> (<highlight>{org.org_id}</highlight>) ' \
|
||||||
|
f'<{org.faction.lower()}>{org.faction}</{org.faction.lower()}> [<highlight>{org.member_count}</highlight> members]' \
|
||||||
|
f'<br><pagebreak>'
|
||||||
|
return ChatBlob("Pick an Org", blob)
|
||||||
|
|
||||||
@command(command="track", params=[Const('rem'), Character("character")], access_level="moderator",
|
@command(command="track", params=[Const('rem'), Character("character")], access_level="moderator",
|
||||||
description="Remove character from the tracking", sub_command="rem")
|
description="Remove character from the tracking", sub_command="rem")
|
||||||
def track_rem(self, request, _, user):
|
def track_rem(self, request, _, user):
|
||||||
@@ -180,14 +253,40 @@ class TrackController(BaseModule):
|
|||||||
players = self.get_tracked('p.level desc, p.profession, p.name', False if const else True)
|
players = self.get_tracked('p.level desc, p.profession, p.name', False if const else True)
|
||||||
return self.format_page(players, "tl", offset, page, f"Tracklist by Titlelevel ({len(players)})",
|
return self.format_page(players, "tl", offset, page, f"Tracklist by Titlelevel ({len(players)})",
|
||||||
'No tracked users online', f"track {const or ''} {group or ''}")
|
'No tracked users online', f"track {const or ''} {group or ''}")
|
||||||
|
@command(command="orgtrack",
|
||||||
|
params=[Const('info')],
|
||||||
|
access_level="member",
|
||||||
|
description="Shows tracked orgs")
|
||||||
|
def orgtrack_info(self, _, const):
|
||||||
|
blob = ""
|
||||||
|
for org in self.db.query("SELECT a.*, o.* from track_orgs o LEFT JOIN all_orgs a on o.org_id = a.org_id"):
|
||||||
|
blob += f"- [{self.text.make_tellcmd('Info', f'orgs info {org.org_id}')}] " \
|
||||||
|
f"[{self.text.make_tellcmd('Remove', f'orgtrack rem {org.org_id}')}]" \
|
||||||
|
f" {self.text.get_formatted_faction(org.faction, org.org_name)} ({org.org_id}) with <highlight>{org.member_count}</highlight> memebrs"
|
||||||
|
return ChatBlob("Currently Tracked Organisations", blob)
|
||||||
|
@command(command="orgtrack",
|
||||||
|
params=[Const('list', is_optional=True), NamedParameters(["page"])],
|
||||||
|
access_level="member",
|
||||||
|
description="Shows tracked orgmembers")
|
||||||
|
def track_listorg(self, _, const, named_params):
|
||||||
|
|
||||||
|
page = int(named_params.page or "1")
|
||||||
|
offset = (page - 1) * self.PAGE_SIZE
|
||||||
|
where = "where o.char_id IS NOT NULL" if not const else ""
|
||||||
|
players = self.db.query(f"SELECT p.name, p.level, p.ai_level, p.org_name, p.profession, p.faction, "
|
||||||
|
f"CASE WHEN o.char_id IS NOT NULL THEN 1 ELSE 0 END AS online from track_org_members t "
|
||||||
|
f"left join player p on p.char_id = t.char_id "
|
||||||
|
f"left join online o on o.char_id = t.char_id {where} group by t.char_id order by p.org_name, p.profession, p.level desc, p.name")
|
||||||
|
|
||||||
|
return self.format_page_org(players, "org", offset, page, f"Tracklist by Organisation ({len(players)})",
|
||||||
|
'No tracked users online', f"orgtrack {const or ''} ")
|
||||||
|
|
||||||
def format_row(self, user):
|
def format_row(self, user):
|
||||||
org = f"[<{user.faction.lower()}>{user.org_name}</{user.faction.lower()}>] " if user.org_name else ""
|
org = f"[<{user.faction.lower()}>{user.org_name}</{user.faction.lower()}>] " if user.org_name else ""
|
||||||
return f"<tab>{self.util.get_prof_icon(user.profession)} " \
|
return f"<tab>{self.util.get_prof_icon(user.profession)} " \
|
||||||
f"{self.text.zfill(user.level, 220)}:<green>{self.text.zfill(user.ai_level, 220)}</green> " \
|
f"{self.text.zfill(user.level, 220)}:<green>{self.text.zfill(user.ai_level, 220)}</green> " \
|
||||||
f"<{user.faction.lower()}>{user.name}</{user.faction.lower()}>" \
|
f"<{user.faction.lower()}>{user.name}</{user.faction.lower()}>" \
|
||||||
f" {org}init by <highlight>{user.initiator}</highlight>: {user.reason} " \
|
f" {org} {'[<red>ONLINE</red>]' if user.online == 1 else ''}\n"
|
||||||
f"{'[<red>ONLINE</red>]' if user.online == 1 else ''}\n"
|
|
||||||
|
|
||||||
def format_page(self, tracked, order, offset, page, title, nullmsg, cmd):
|
def format_page(self, tracked, order, offset, page, title, nullmsg, cmd):
|
||||||
selected = tracked[offset:offset + self.PAGE_SIZE]
|
selected = tracked[offset:offset + self.PAGE_SIZE]
|
||||||
@@ -228,3 +327,210 @@ class TrackController(BaseModule):
|
|||||||
|
|
||||||
blob += "</font>\n" + pages
|
blob += "</font>\n" + pages
|
||||||
return ChatBlob(title, blob)
|
return ChatBlob(title, blob)
|
||||||
|
|
||||||
|
def format_page_org(self, tracked, order, offset, page, title, nullmsg, cmd):
|
||||||
|
selected = tracked[offset:offset + self.PAGE_SIZE]
|
||||||
|
count = len(selected)
|
||||||
|
pages = ""
|
||||||
|
if page > 1:
|
||||||
|
pages += "Pages: " + self.text.make_tellcmd("«« Page %d" % (page - 1), f'{cmd} --page={page - 1}')
|
||||||
|
if offset + self.PAGE_SIZE < len(tracked):
|
||||||
|
pages += f" Page {page}/{math.ceil(len(tracked) / self.PAGE_SIZE)}"
|
||||||
|
pages += " " + self.text.make_tellcmd("Page %d »»" % (page + 1), f'{cmd} --page={page + 1}')
|
||||||
|
pages += "\n"
|
||||||
|
if count == 0:
|
||||||
|
return nullmsg
|
||||||
|
else:
|
||||||
|
blob = "\n\n" + pages + "<font color=CCInfoText>"
|
||||||
|
if order == "org":
|
||||||
|
org_name = ""
|
||||||
|
for player in selected:
|
||||||
|
if player.org_name != org_name:
|
||||||
|
org_name = player.org_name
|
||||||
|
blob += f"\n<pagebreak><header>{player.org_name}</header>\n"
|
||||||
|
blob += self.format_row(player)
|
||||||
|
|
||||||
|
blob += "</font>\n" + pages
|
||||||
|
return ChatBlob(title, blob)
|
||||||
|
|
||||||
|
def format_row_org(self, user):
|
||||||
|
org = f"[<{user.faction.lower()}>{user.org_name}</{user.faction.lower()}>] " if user.org_name else ""
|
||||||
|
return f"<tab>{self.util.get_prof_icon(user.profession)} " \
|
||||||
|
f"{self.text.zfill(user.level, 220)}:<green>{self.text.zfill(user.ai_level, 220)}</green> " \
|
||||||
|
f"<{user.faction.lower()}>{user.name}</{user.faction.lower()}>" \
|
||||||
|
f" {org}init by <highlight>{user.initiator}</highlight>: {user.reason} " \
|
||||||
|
f"{'[<red>ONLINE</red>]' if user.online == 1 else ''}\n"
|
||||||
|
|
||||||
|
@timerevent(budatime="24h", description="Update Tracked Orgs")
|
||||||
|
def fetch_orgs(self, _, _1):
|
||||||
|
def discover():
|
||||||
|
start = time.time()
|
||||||
|
self.logger.info("Fetching orgdata..")
|
||||||
|
output = []
|
||||||
|
data = []
|
||||||
|
data2 = []
|
||||||
|
timestamp = 0
|
||||||
|
ours = self.db.query("SELECT * FROM track_orgs t LEFT JOIN all_orgs a ON t.org_id = a.org_id")
|
||||||
|
for org in ours:
|
||||||
|
result = requests.get(self.single_org_uri % org.org_id).json()
|
||||||
|
if result and len(result[1]) > 0:
|
||||||
|
self.cache.store('org_roster', f"{org.org_id}.5.json", json.dumps(result))
|
||||||
|
else:
|
||||||
|
result = json.loads(self.cache.retrieve('org_roster', f"{org.org_id}.5.json").data)
|
||||||
|
d = datetime.datetime.strptime(result[2] + " +0000", '%Y/%m/%d %H:%M:%S %z').timestamp()
|
||||||
|
if d > timestamp:
|
||||||
|
timestamp = d
|
||||||
|
|
||||||
|
for char_info in result[1]:
|
||||||
|
data.append((char_info["CHAR_INSTANCE"], char_info["NAME"], char_info["FIRSTNAME"],
|
||||||
|
char_info["LASTNAME"], char_info["LEVELX"], char_info["BREED"],
|
||||||
|
char_info["SEX"], result[0]["SIDE_NAME"], char_info["PROF"],
|
||||||
|
char_info["PROF_TITLE"], char_info["DEFENDER_RANK_TITLE"], char_info["ALIENLEVEL"],
|
||||||
|
result[0]["ORG_INSTANCE"], result[0]["NAME"], char_info["RANK_TITLE"],
|
||||||
|
char_info["RANK"], char_info["CHAR_DIMENSION"], char_info["HEADID"],
|
||||||
|
0, char_info["PVPTITLE"] or "", "roster", int(time.time())))
|
||||||
|
data2.append((char_info['CHAR_INSTANCE'], result[0]['ORG_INSTANCE']))
|
||||||
|
|
||||||
|
if not self.buddy_service.get_buddy(char_info["CHAR_INSTANCE"]):
|
||||||
|
self.buddy_service.add_buddy(char_info["CHAR_INSTANCE"], "track")
|
||||||
|
output.append(DictObject({"action": "JOIN",
|
||||||
|
"name": char_info['NAME'],
|
||||||
|
"org_name": result[0]["NAME"],
|
||||||
|
"org_id": result[0]["ORG_INSTANCE"],
|
||||||
|
"level": char_info["LEVELX"],
|
||||||
|
"ai_level": char_info["ALIENLEVEL"],
|
||||||
|
"ranks": 0}))
|
||||||
|
self.logger.info(f"[TRACK] Organisation {org.org_name} has been updated.")
|
||||||
|
if len(data) > 1:
|
||||||
|
with self.db.lock:
|
||||||
|
with self.db.pool.get_connection() as conn:
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.executemany("INSERT INTO player(char_id, name, first_name, last_name, "
|
||||||
|
"level, breed, gender, faction, profession, profession_title, "
|
||||||
|
"ai_rank, ai_level, org_id, org_name, org_rank_name, "
|
||||||
|
"org_rank_id, dimension, head_id, pvp_rating, pvp_title, "
|
||||||
|
"source, last_updated) VALUES "
|
||||||
|
"(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) "
|
||||||
|
"ON DUPLICATE KEY UPDATE first_name=VALUE(first_name), "
|
||||||
|
"last_name=VALUE(last_name), level=VALUE(level), "
|
||||||
|
"breed=VALUE(breed), gender=VALUE(gender), "
|
||||||
|
"faction=VALUE(faction), profession=VALUE(profession), "
|
||||||
|
"profession_title=VALUE(profession_title),ai_rank=VALUE(ai_rank), "
|
||||||
|
"ai_level=VALUE(ai_level), org_name=VALUE(org_name), "
|
||||||
|
"org_id=VALUE(org_id), org_rank_name=VALUE(org_rank_name), "
|
||||||
|
"org_rank_id=VALUE(org_rank_id), source=VALUE(source), "
|
||||||
|
"last_updated=VALUE(last_updated)", data)
|
||||||
|
cur.executemany("INSERT INTO track_org_members (char_id, org_id) VALUES(?,?)", data2)
|
||||||
|
conn.commit()
|
||||||
|
for org in ours:
|
||||||
|
left = self.db.query("SELECT p.* FROM track_org_members t LEFT JOIN player p on t.char_id = p.char_id where t.org_id=? and (p.last_updated < ? OR t.org_id != p.org_id)", [org.org_id, time.time()-25*60*60, org.org_id])
|
||||||
|
for player in left:
|
||||||
|
bonus = None
|
||||||
|
player = DictObject(player)
|
||||||
|
if self.buddy_service.remove_buddy(player.char_id, "track"):
|
||||||
|
bonus = "LEAVE"
|
||||||
|
new_data = self.pork.request_char_info(player.name, player.dimension)
|
||||||
|
if new_data and new_data.char_id == player.char_id:
|
||||||
|
self.pork.save_character_info(new_data)
|
||||||
|
else:
|
||||||
|
bonus = "DEL"
|
||||||
|
if bonus:
|
||||||
|
output.append(DictObject({"action": bonus,
|
||||||
|
"name": player.name,
|
||||||
|
"org_name": player.org_name,
|
||||||
|
"org_id": player.org_id,
|
||||||
|
"level": player.level,
|
||||||
|
"ai_level": player.ai_level}))
|
||||||
|
|
||||||
|
self.db.exec("DELETE FROM track_org_members where char_id not in (SELECT char_id from player where org_id=?)", [org.org_id])
|
||||||
|
|
||||||
|
self.log(output, time.time() - start)
|
||||||
|
self.logger.info(
|
||||||
|
f"Successfully fetched {len(data)} players from {len(ours)} orgs "
|
||||||
|
f"in {time.time() - start:.2f} seconds. - ")
|
||||||
|
while (timestamp + 24 * 60 * 60) < datetime.datetime.now().timestamp():
|
||||||
|
timestamp += 24 * 60 * 60
|
||||||
|
self.db.exec("UPDATE timer_event SET next_run=? WHERE handler=? AND event_sub_type=?", [
|
||||||
|
int(timestamp +24*60*60 + 10*60),
|
||||||
|
"modules.standard.track.track_controller.TrackController.fetch_orgs",
|
||||||
|
86400
|
||||||
|
])
|
||||||
|
del self.threads['roster']
|
||||||
|
|
||||||
|
if "roster" not in self.threads.keys():
|
||||||
|
thread = Thread(name="roster", target=discover, daemon=True)
|
||||||
|
self.threads["roster"] = thread
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
def fetch_single(self, org_id, org_name, sender: object):
|
||||||
|
start = time.time()
|
||||||
|
data = []
|
||||||
|
data2 = []
|
||||||
|
accounts = []
|
||||||
|
self.logger.info("Fetching orgdata..")
|
||||||
|
count = 0
|
||||||
|
result = requests.get(self.single_org_uri % org_id).json()
|
||||||
|
for char_info in result[1]:
|
||||||
|
data.append((char_info["CHAR_INSTANCE"], char_info["NAME"], char_info["FIRSTNAME"],
|
||||||
|
char_info["LASTNAME"],
|
||||||
|
char_info["LEVELX"], char_info["BREED"],
|
||||||
|
char_info["SEX"], result[0]["SIDE_NAME"], char_info["PROF"],
|
||||||
|
char_info["PROF_TITLE"], char_info["DEFENDER_RANK_TITLE"], char_info["ALIENLEVEL"],
|
||||||
|
result[0]["ORG_INSTANCE"], result[0]["NAME"], char_info["RANK_TITLE"],
|
||||||
|
char_info["RANK"], char_info["CHAR_DIMENSION"], char_info["HEADID"],
|
||||||
|
0, char_info["PVPTITLE"] or "", "roster", int(time.time())))
|
||||||
|
data2.append((char_info['CHAR_INSTANCE'], result[0]['ORG_INSTANCE']))
|
||||||
|
|
||||||
|
accounts.append((char_info["CHAR_INSTANCE"], char_info["CHAR_INSTANCE"], result[0]["ORG_INSTANCE"],
|
||||||
|
start, start))
|
||||||
|
self.buddy_service.add_buddy(char_info['CHAR_INSTANCE'], "track")
|
||||||
|
count += 1
|
||||||
|
with self.db.pool.get_connection() as conn:
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
cur.executemany("REPLACE INTO player(char_id, name, first_name, last_name, level, breed, "
|
||||||
|
"gender, faction, profession, profession_title, ai_rank, ai_level, "
|
||||||
|
"org_id, org_name, org_rank_name, org_rank_id, dimension, head_id, "
|
||||||
|
"pvp_rating, pvp_title, source, last_updated) VALUES "
|
||||||
|
"(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", data)
|
||||||
|
cur.executemany("REPLACE INTO track_org_members(char_id, org_id) VALUES (?, ?)", data2)
|
||||||
|
|
||||||
|
self.logger.info(f"Organisation {org_name} is now being tracked!")
|
||||||
|
sender.reply(f"<highlight>{org_name}</highlight> is now being tracked. "
|
||||||
|
f"Runtime: {time.time() - start:.2f} seconds.")
|
||||||
|
|
||||||
|
self.logger.info(f"Successfully fetched {count} players in {time.time() - start} seconds.")
|
||||||
|
del self.threads[org_id]
|
||||||
|
|
||||||
|
def remove_single(self, org_id, org_name):
|
||||||
|
members = self.db.query("SELECT * from track_org_members where org_id=?", [org_id])
|
||||||
|
for member in members:
|
||||||
|
self.buddy_service.remove_buddy(member.char_id, "member")
|
||||||
|
self.db.exec("DELETE FROM track_org_members where org_id=?", [org_id])
|
||||||
|
self.db.exec("DELETE FROM online where char_id in (SELECT char_id from player where org_id=?)", [org_id])
|
||||||
|
self.logger.info(f"Organisation {org_name} removed!")
|
||||||
|
del self.threads[org_id]
|
||||||
|
|
||||||
|
def log(self, blob, duration):
|
||||||
|
out = []
|
||||||
|
s = []
|
||||||
|
current = ""
|
||||||
|
|
||||||
|
for entry in blob:
|
||||||
|
s.append(f"[{entry.org_name}] [{entry.action}] {entry.name} "
|
||||||
|
f"({entry.level}/{entry.ai_level})\n")
|
||||||
|
s = sorted(s)
|
||||||
|
if len(s) > 0:
|
||||||
|
s.append(f"\nRuntime: {duration:.2f} seconds.")
|
||||||
|
for entry in s:
|
||||||
|
if len(current) > 1500:
|
||||||
|
out.append(current)
|
||||||
|
current = ""
|
||||||
|
current += entry
|
||||||
|
if len(current) > 10:
|
||||||
|
out.append(current)
|
||||||
|
if len(out) > 0:
|
||||||
|
y = 0
|
||||||
|
for x in out:
|
||||||
|
y += 1
|
||||||
|
blob = ChatBlob(f"Recent changes - {datetime.date.today()} - ({y}/{len(out)})", x, embed=True)
|
||||||
|
self.relay_hub_service.send_message("member_logger", None, blob, blob)
|
||||||
@@ -38,12 +38,14 @@ class CharacterInfoController:
|
|||||||
def pre_start(self):
|
def pre_start(self):
|
||||||
self.bot.register_packet_handler(CharacterName.id, self.character_name_update)
|
self.bot.register_packet_handler(CharacterName.id, self.character_name_update)
|
||||||
|
|
||||||
def start(self):
|
self.db.shared.exec("CREATE TABLE IF NOT EXISTS name_history ("
|
||||||
self.db.exec("CREATE TABLE IF NOT EXISTS name_history ("
|
|
||||||
"char_id INT NOT NULL, "
|
"char_id INT NOT NULL, "
|
||||||
"name VARCHAR(20) NOT NULL, "
|
"name VARCHAR(20) NOT NULL, "
|
||||||
"created_at INT NOT NULL, "
|
"created_at INT NOT NULL, "
|
||||||
"PRIMARY KEY (char_id, name))")
|
"PRIMARY KEY (char_id, name))")
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
|
||||||
self.db.create_view("name_history")
|
self.db.create_view("name_history")
|
||||||
self.command_alias_service.add_alias("w", "whois")
|
self.command_alias_service.add_alias("w", "whois")
|
||||||
self.command_alias_service.add_alias("lookup", "whois")
|
self.command_alias_service.add_alias("lookup", "whois")
|
||||||
@@ -155,7 +157,7 @@ class CharacterInfoController:
|
|||||||
with self.db.pool.get_connection() as conn:
|
with self.db.pool.get_connection() as conn:
|
||||||
with conn.cursor() as cur:
|
with conn.cursor() as cur:
|
||||||
cur.executemany("INSERT IGNORE INTO name_history (char_id, name, created_at) "
|
cur.executemany("INSERT IGNORE INTO name_history (char_id, name, created_at) "
|
||||||
"VALUES (?, ?, ?)",
|
"VALUES (%s, %s, %s)",
|
||||||
self.name_history)
|
self.name_history)
|
||||||
self.name_history = []
|
self.name_history = []
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ cryptography==3.3.2
|
|||||||
discord.py @ git+https://github.com/Rapptz/discord.py@1bfe6b2bb160ce802a1f08afed73941a19a0a651
|
discord.py @ git+https://github.com/Rapptz/discord.py@1bfe6b2bb160ce802a1f08afed73941a19a0a651
|
||||||
emojis==0.6.0
|
emojis==0.6.0
|
||||||
hjson==3.0.2
|
hjson==3.0.2
|
||||||
mariadb==1.0.11
|
mariadb==1.1.7
|
||||||
psutil==5.9.1
|
psutil==5.9.1
|
||||||
pytz==2022.1
|
pytz==2022.1
|
||||||
requests==2.28.0
|
requests==2.28.0
|
||||||
|
|||||||
Reference in New Issue
Block a user