From 40fdf25e49056cc9be88a425b9067b33030fcc3f Mon Sep 17 00:00:00 2001 From: suzxzd <474390146@qq.com> Date: Tue, 18 Jun 2024 09:45:13 +0800 Subject: [PATCH] 6.17 --- .DS_Store | Bin 8196 -> 8196 bytes main/.DS_Store | Bin 0 -> 6148 bytes main/__pycache__/mysql.cpython-310.pyc | Bin 0 -> 5798 bytes main/__pycache__/mysql.cpython-311.pyc | Bin 0 -> 14094 bytes main/client/.DS_Store | Bin 0 -> 6148 bytes main/client/Client.py | 313 ++++++++++++++++++ .../config/__pycache__/config.cpython-310.pyc | Bin 0 -> 418 bytes .../config/__pycache__/config.cpython-311.pyc | Bin 0 -> 475 bytes main/config/config.py | 17 + main/mysql.py | 245 ++++++++++++++ main/server/Server.py | 259 +++++++++++++++ main/test.py | 30 ++ xiao/.DS_Store | Bin 0 -> 6148 bytes ...endMessage\357\274\210li\357\274\211.html" | 86 +++++ xiao/app.py | 42 +++ xiao/static/css/login-style.css | 69 ++++ xiao/templates/index.html | 83 +++++ xiao/templates/login.html | 52 +++ xiao/templates/register.html | 298 +++++++++++++++++ 19 files changed, 1494 insertions(+) create mode 100644 main/.DS_Store create mode 100644 main/__pycache__/mysql.cpython-310.pyc create mode 100644 main/__pycache__/mysql.cpython-311.pyc create mode 100644 main/client/.DS_Store create mode 100644 main/client/Client.py create mode 100644 main/config/__pycache__/config.cpython-310.pyc create mode 100644 main/config/__pycache__/config.cpython-311.pyc create mode 100644 main/config/config.py create mode 100644 main/mysql.py create mode 100644 main/server/Server.py create mode 100644 main/test.py create mode 100644 xiao/.DS_Store create mode 100644 "xiao/MQTT/sendMessage\357\274\210li\357\274\211.html" create mode 100644 xiao/app.py create mode 100644 xiao/static/css/login-style.css create mode 100644 xiao/templates/index.html create mode 100644 xiao/templates/login.html create mode 100644 xiao/templates/register.html diff --git a/.DS_Store b/.DS_Store index 4c33c4eb489f4d4126806b1306f4ff1389a9f147..9e4cb4735299d52029af0347b3231df5f9f526a8 100644 GIT binary patch delta 96 zcmZp1XmQw(DZnewz`)?}9||Uy3G{Fn85`>;7@3+(-Yq1(SyhmciM1c7#%;2;usq|A k$qqt=+!EE*$ciSb3aU+J7wO(SM<#=LVgt`+c8S020CEW*h5!Hn delta 74 zcmZp1XmQw(DZp#Vz`$Vj9}E~6CYK5HaF`mK>L?hQnM~d-B)wTxkdcXXB2bOZWNl&j a$@W6KC$ow4Zk{cZ$vm-vXEVFRUv>bv8yG17 diff --git a/main/.DS_Store b/main/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..cb99b92955dbddacaf4bdcee39b23f353aa84156 GIT binary patch literal 6148 zcmeH~&u`N(6vv;p(xy~MJ%F^!q)1$=QQCD9;u6X@a3u&1fI`xSEh39cldeKlrJTqA zz`wwizl8sV6MUcTi8k#{NPw81WPknRJ*WPpwqqg^!`b*gQJaVyB-YwZWLu2;Ic?aE zY2i4b#u!mZBRZv+f(>umUlqbWd=IYjjpq5pjQcg3q)A?MyWhmlZtX_B;WV6<^Tt1wbH50SSw0M> zuekPH$~3wxhtZ29o(JvQk7ZVbNfu94Kr)Wu^7>_xjpckOXW2McvA*tbnocul?=2RC z{-ERbjt-X{ck!Ut?YM{iqvf*c+_`)2;j`dbdMTe!SeyU3Kh08^ zouHj#xKD!1JMcNFu=#@iRW=TtfqYIMK=Xj#!n(iMulU#D8`G4|Ij{Kg?^+#u&G&C} z@AdoOKKOm^EAy{#Z%_d$Ir42JzgOs>dacd;yPejxreG&;30MN#2=M;kBC&c#ORZ|_ zK&Gw$&>EVRq0Ao(9OD}GjFwu_0~0zFszZgjVhA0McGviMMoXZC#2a3JhTqD+zW z0<269<;jeF^&ywebehgcN8Q_N{}5bz@}(EwJZ;_I_kn~cQf^AlF80HI`}%#)MW<9M z82Ej0eS2eg+A#h>#N;mrVg)7oCn{-3vt{grIm(pwIRmxB zwaaymYww&P^N$?g{n(HNIrq?zb1L`1@;%T+Spr>B9_T#ivYZD!&vXIwf?Nc>$n+fO ziaZ7S)C1ucnYGjc!NBH9N7H&C7UfX0WL@q?IOr7Kjy;=p|Ij@J(s>0(&&2z#awmXz?EH zB>zzmsT&=sS~HWF<4G1KCQ+7eOB2TvgK{=>>4u7fdd*3^2A`_YND7U{PDl1y3hiQ} zakm$==)9nWT=zX0#KAgNJ~VU%vvc+I&E;PMiD-E%p#So!itfan?(&UWYir9pL9@Ng zKrVIriA@XAww~CiJi{|J)X%8bY+a`5=Bc87eton=+B!uYB~-)~r887aelr6?hUAaH zJ4RAj4-C>(!t;^oyJ%V5$^m0rI>6Wg#-4NmR4&QWu^8jWE0_f;P}m9XHCn2@8E-xQ z60c^K9b^Aw5_@SvYywkSgK{<{W3Tg=q<%PkdhB4m0iavzL4^7yR+6a2BSt}WXtO*1HH5iRr-pNrpX)H#7)c?v&$ff!y!<>%Mby*Py~x1*vc*i`=fN6pPo+OgVHBT&6a zwWZRZNWZii#A>a%qtYQ{GAag{SnbYkVpH?^xW9@8sYFFogggDqCbXR1&LB@Vu!8dB zT~yP^E0^_L_&Mc4&uySi9@ddAPf7$G9pQSBoP2#JSGq) z?DX34^O3G$GS!=Jo}-Xok-zx=?2Yo*9xCv#V{BI%Rq&P?K9 z>=l%VR4X?2%>%=vr--fCj-5^GfCKDp zHU3dM+b_j9+V9ZZ7ram70DIIw!E3DjQ#|}!xTV57-Cg|wy%hRqc%;rX3y_-kQD(+$ zBOie;qQ#(dKgVN6T?n`pl!zuiN#_)D0ck%ppnne9Y}aVJXy>HI?{hK_y(}aJ4m&{` zu4_g(r2njzZ8QdRbllk3hG_1H19J~Y|ID~;*nnZ%>c4D4Wudf4C5FbIjlYNoP}$Fs z4Kjz*f7dkjglP=Q;D9*C9G@}Ip13cFQ-bHd*fn>7VSR9}-l_HwXR8~qS6SU{##>bi zP?xGtPhDZ{Z> zWk0zCn(HBvl5FP>}g-4GH$)_>_#E5+cf=oK!!yIhf2J{@-Dvh3@k)7NI5Zi!3 zlK#Ur4=sQMFrcm1H2DuW%oRNJHLB>OZ2PGwCyv4@=bs^=Dw)}RW4#}%X!>x4KPcVY z=+pKUCgilMfb-cVg{8rniE|xs)@$CB=hp9K`}&w#pHg+5sv|JDMIMO{@e4ERr2DO{nnE_FW`mHo)iW*XT7F?fXpa$xKk zn+9Buv1+S?7KsbnRoM<4?Vt=#U!;o8qu)SP%crS@8!1Hb_#~FZ4Z2+Tz+M}NGr$%ArGNi&6V{|l&@%b7w^ zIzxBNJ5o0HzB@8jwAfhP`d|^6!YJF1(rf{-o$Z&RN3z%oqPQ_)XwWrlP+IH6L5tIi z=u&mSSx}X%^3veVncSkfyVY!|>V}HLt!8_3JgPRICfjwak@^K^cMD!R^%t~!;^EVe z(s1nTJ`!81C`_Dqf2bpKs+D#&!o<^_tM&-8CF z6VJC7~jB7PELw+*BvY0-@rb~ zBF_SS%1L6)r^nuOC0$XK+MHjmtLtzSW2M{(u>t_8Yubf4Y zuRZ4uXNEJRVkg^TFUd1^&bhC-_uTWk!=DBMJ_^&*lV`?SDC!U7rU*R6>)MAjMO~!? zN}yBJ7=4PSG4D#bPT-YEF{c=EWlym#O5{XZU>nVL;EuE1xovk?FRgwj;GSD_hNtsx~^pu|Q;-7ulF z0_B0S5!Vu06liUZT6F?*oa%h=Ha>KVT-~vOGN@2?RSjA*V@ZazaXXvKmW@dCW2_DZnB%QJgDsVT(6w9gw+7iPR}t zpia5SXlWR&%Q0GpjF#2B194eAHX(>9TXVpSB&~&Q&56t@R-oZAU7uH*6}KM~)A5l` zPV>ab)5T(%FBTh{5T;ThfjL^WaB{0A6YW zFw)6N_y`h~lgA{T>gUsjEW`kt;C6sU@?>Z+NmilxI z);c9RXB-ztdJq6+)|~6uSiX*4$2w}>{;BlDP*O|@nky-2-p5Ddl77n~uStIFfpp_o zY!JbegaFw=J`ccJ>_Sy2d-1Pcef`z!K*3*^+qd9S{Ox&vyXtSx4i1_~}(bxps zk4Wt>ri$Fr4TMcd+>D@POIJHsLE3@^wgS++C&UYBoeQeQL|KlX6}8|%^6c<o)%9e$3(pf3MMfPw;D4(F|Dzft;j-M*dc-k;3rQ5sLVpu4Y}my z^K<93hYNw0Tr3}GRRgWrCky^a?%+a1ZQH4~^(y{7dH){Ozb8A0qQ=QEguCv+PB@av z>@*IPd$W`1Cc?(9fkCK<9uPLHgIRQ4&jGWz9n9hrs(@KMn)hh(yslF;E(KW`dFFIH zab6P7NT}kahnxex2lu=S0>^B$$UWHd7jVyG(8a^pmxFuW^{>x8!J!FBOr9M-B3>j6 zL6%ta78wcng}3n$mzbCuPgi7+KI|C*s^hgW03{6K4d)s!H_tVLj0rt3A6)R>+@pl{ z=R^C|(EjXjfsf>lF4QP|d!BDs`S$D+tL#@}3+&&<7KVAXhTFxE~+C6B*d$L)Yt zXKp*g1ou!d<@ zOD6$`dqKvPgGKY#%sra-H>>{U?BK0H?c7V(_P%}S%|kc#(11{wGWo+Ge;A&FJdg2#>HUK|43ZVGJ*E-(rezW_=)_l`WwQ1+gp}c>;>ff)h z`}GHef@U%XzIFys_mUGJJ-~9Xv&ktAuuK`&4Oq4eTP1LyHr$$zn3VBx(AkyQ^uNhy zymrB1GO9Ux$drnfbH>w98R|UA+XcofodJ)g-CoCJ=1r7T52DIzwJy*Z>Ic+Y4%?ij zP7=XWDw?3~##xuGF0lK0b!T0dTqwE(3Ukx+GckvBI3da-6X_=|B*DMr zCZ*(fTJt_}At6qtlM~~>ZCH$0@ft^(v+pP`*lLOMBhckcowZEcO)Sb5`Aq;>YL)eP zBP+EnR}X&o;7=NV+&wLM5v5Jx$Dc^mAQ^MWw&GV0_{38ngNU=QDneX`w(kchtz*TOB z;l0-R5cPgre=oBb@*->u_wQg9cW{um@f-_fiE?`kGWIQ=p`84aHo1kOGQb^W8~O+| z0(%$bkc3+k@_x8zJj$u3i|)T|LkGyr8l;(sbIuLQ31~)c1CXUYbyF>!HzN7wooe&W z+|iZVwuOgoT+k<8;rEt{G4mM}sDG7$eO0oTKv2V-<$D4joBN2ODvP!Zm2rV@0p+Yf zPGz-VmlmM1K?%SPEK%{WcbaCIG)_}7Wy%yi?zmaz5(#DKxsqMOj=(Gvrp7i-48fit z^G`O0J2?)!33QBjK}<}gMM;1%QUU*{ZbVd1YD7saLKw9 zaW7!;DFC<=+}_5O@B<5;e7I8$cjg{n;WsSvElYgM!ls+G3g4o0`7(cSi9eX<52^ei zg+D|%821RWd7}k@;paDBK00?aceGF&ncr=E3?^?xCP!cQwS)aMwMhH=H#3X=V1JZZ zjB=2-=`eHgzY7(B!2uenvh`NR_8`i#E(```T$YHfyxb6dvNID?Dikw}(<;CS!^n_? z>J_Y|m*FCzCemGcRD}92Dp@LBa&5r2(G#qZr>^ez$77pC!{J4cng3@LPVI5IPTCY1;8X32!bWgLskVh zjF}Aau!g4AS2G%lF-hO!7%0#U0ke6?xZy{H^8b(??#B?Y3z}K#ECuSG8l+y@iI%6u zw~#l5IOLIINP;|Cdn5_;b#@kbbpgjwmdeG`+^(WwQEe3_VvSALSeT5%zt#(v^y6?)c;+L_SJ{9RzmbDF{--e9Ic@ z_;f4<27-icM)4kFwYm(%i9i`x6oNb$7yYS}zD_d@)|zcEB_Kn~KLUW_FbIZ0q-{CU zu@vdZN4BYvZMor(BTc#CLZl6NG4K!p^X$h>t=G2}9%#RwAzQ4_61_gW>g6_uf&Vs! z=e@weHBHN*=u#-U(3lT(si7`~d<(TLAXN?7SzBn zWfoh5{kxdOT^!^q3(sFd4Wc>WYNYkVXNE4*jmDNSs*shZTPK|D^otptIMu@1%a|>#t}2G1y&=EyN+c(ou=DtU#N0TWrdPYnqMw8=b zjar>SJz|Njg|6zk=}}P}MaWn=_ z{)mu=vq5eOTp3XRc+u5AF096vK8KV=lwQQL2#`TQ6=2c>Z#6f zGT(=v{4}@#pb1>{+yK22YSh(tKJ=g(dN9Wo>gsdekLy5g2D}{vIB z&372OWhW9-mo?d0BK;y^3X0V6@dkdQ$Q8(>YLT&KZ)WXrDE6`F1)y?~^_^!p@2;voP zuX?}heZzmnKko`I@)Z>(%#Lm2K$gyVE;JJ27Z7DK-NJ`iWNJaM;{bk}b>*fd6x9t}e5SS{MVio_mA!(qrTo>6vJ=cCrfd|aM} zU^JSK&QL=9dC*S}cU*5R<>fEbv{2r*! zom^;F0$cKdEoxv(b_h>cx1u<90z7y}EmB6%*#-w-n{z{0tvwAC%Zjgj!un-SPKxhg z)R(Q8E}j|a&PeE|*^~p=gD88YHxc{*z===M{ru$0jX&l7;g28u&8?qZ zyLJ7>AF{6veTuQ6TisL-+E}29En0`w78{+Cy$FjjJKlowm}9pRVHF)9;(c9+bfp-H)vD- zR{*GZeBkt#90cuKYCDjxJ*d_m1mh0QDz@ZXcBm~oa>rKqwq?F!iSM{s_v?n=?p032 z6}}_SpH}(P%lx?|{#>3h61wf?UDZfdc+b)c8|Fyuwp7#`Tce7J*ye4=#w;jEJFR|mr2FS7m2 z&9k0&TKe8ZiRZ~!vCK-ICv07?xQt|Ze_(f+8_S^Lwd^FDJ?Ay(_gBNNL#5`@&A5&y zi2}!_d2s`l9pCcCIBYXvV$ZmW0;0t0be>TV0Rh3YG9QvF^;HG-9s)uSzu5%@H$sj! zrrKbXx=i>}?t8a>@z;O+r?+lj{rT-5U9*V@X#t8E-k&8Dh&&)thRB2CP)K?K!Se`E z=tyq?(5fX7H>&XhvE-B)(hrUD8b2;hTLsYxl+X&$qrXmJQLmquSn@)bEHe+UBP}Wy z{|{(i4$$`&7t!6z(S1wNeZTK}O6~i)@3lSyMiXF>t^_yCUAlJW?Xfq< zZXC|H_Nc8rO7CH{cVxNuxuxFcl;>Z{_r9$5zMK!n)L;x$ec*X|rQzY_h676t2R=CY zJ3im=oZ9f55_)cxL7HCTvspo{s)#X;T{k2W>_V=$9{0g>afX?*9&FocUTu9#sk!v?La z_1}S|eh+?n0{vb7)`cn9irW)kp)RI%w`a&GfiH`~`xb1vv=*CT*VW&6#G-Fc`w4Np0}bp#yFQmB9e{`#pxRgpH|nrLC2wFrNb2ICs2H5^Ez9{zJou3qVlf* zpoaB-frf4Ex^Xn$x=(H0mwT$v(v=&WJ67OB-x>b)@Z}?OM{-C0|8!}%zn)sGZyngk zEbj3F{E!L{M3@gF9OOqjt18Co{~jmwrwDMaobCXMIwJ4T^pMdc%9@{#@r=}uF?j%H zOdb(UBwYUmBpz!4Fl!kIg4KNh?7DM<7REm+Y}fzpQM^cK259a{QJfY<@;aB)ipZI*uMp;PBFd(Dv%|g0u{`X4+O#7wb_^E4=i}q z+HE&mK1ixNo>Y#jKH5 q1U$;Y9mL(W2u*GpoZxbBZ5Zbhd|{Im>cU}{gFA@3TY*6K%l`s-s>pfo8d_X{HN2TKSAH9vp?6i6pR0R`Pv`7Ztp#t$K)g9eEPjU{__ zy`J0L6z3R#tzYiWfF*!A-4S~aQ}c88i5*qOh;%;V5zkoR39nbfr26}Wb5C%A0S~zU z%HQ2?huxN^{?pFstM@RjWKuv1NC7Dz1*E|574Y6mn=cX-rGONW0-p-__o2}pd*PTE zpALo?0f;lE!?=!Fg4jGk?1f_@Gc-#oF{xG~h9#Z(R&~8_OiVf~Zsv39W~&Ls;&$d+ zl*4+Wq7;wsyK!FAcnMIV=Zeulx)7TX%D-O~NAa3L> zJB|Pgu#+M&PoA0g{QS`{&vSu__t)wC(E#8>lmF3BARULI$>x zi5s|y9o)k179tC`C&2HZR<;r%5`+un^bZHa(b4e<{psEMah z9%rO#)|`~6t&}3>{F#-wQVUj!s!13Z^r;Dev{SaAxr8ZQ5(H;SETmJC1?7U2K9uch zI})s*GwEtm-6L09clzGnftug=5OuN*U!~EE<#W1_@M=5>CA=Nqhtez7)0Fb0_P&8q zkFH8zz2HH8n+Hj(5nK|!R1XK&cVQT0G0lVex?SlO8|j>746jpiuBHz7zDlNL8Z{c< MumufhLBsv|1@)|WbN~PV literal 0 HcmV?d00001 diff --git a/main/config/__pycache__/config.cpython-311.pyc b/main/config/__pycache__/config.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9f89627244799e2c57fcd09db8b31c0975d297c9 GIT binary patch literal 475 zcmXv~OHaZ;5T3#Ug;Ft+sPVzUL=zH2LGYCr--h9NB(1~b#>v|xj|p}PVM@>R?{q<^t7qcEESx$Kl#M6@xU}r z-Bm8YZw~Z|hcGHhQYgdXdXQNQvYSCB8)R~!5?_pjz=NL-mq1?eQIJr46viR9J=zI2 UwnmqnnK_d}5YbnKyUSegA4Xe|)c^nh literal 0 HcmV?d00001 diff --git a/main/config/config.py b/main/config/config.py new file mode 100644 index 0000000..1445111 --- /dev/null +++ b/main/config/config.py @@ -0,0 +1,17 @@ + +#mysql +mysql_config = { + 'db_name': 'mqtt_test', + 'db_user': 'mqtt_test', + 'db_password': '12345678', + 'db_port': 3306, + 'db_host': '101.43.101.59' +} + +#MQTT broker +HOST = "101.43.101.59" +PORT = 1883 + +#topic +publish_topic={'login_topic':'login','like_topic':'like', + 'chat_topic':'chat','register_topic':'register'} \ No newline at end of file diff --git a/main/mysql.py b/main/mysql.py new file mode 100644 index 0000000..c85963c --- /dev/null +++ b/main/mysql.py @@ -0,0 +1,245 @@ +from main.config.config import mysql_config +from peewee import * +import bcrypt +import datetime + + + +#链接数据库 +db = MySQLDatabase(mysql_config['db_name'], user=mysql_config['db_user'], password=mysql_config['db_password'], + host=mysql_config['db_host'], port=mysql_config['db_port']) + +#数据对象 +####################################################### +#基类 +class BaseModel(Model): + class Meta: + database = db + +#用户类 +class UserModel(BaseModel): + id=AutoField() + name = CharField(max_length=64) + password = CharField(max_length=128) + + + class Meta: + db_table = 'user' + + +#信息类 +class ChatModel(BaseModel): + id=AutoField() + message = TextField() + senderId=BigIntegerField() + time = DateTimeField(default=datetime.datetime.now) + class Meta: + db_table = 'chat' + +#点赞类 +class LikeModel(BaseModel): + id = AutoField() + messageId = ForeignKeyField(ChatModel, backref='likes') + count = IntegerField(default=0) + + class Meta: + db_table = 'like' + +class CreateTable: + @staticmethod + def create(): + db.connect() + db.create_tables([UserModel, ChatModel,LikeModel]) + + + +#用户操作 +########################################## +def hash_password(password): + # 生成盐值 + salt = bcrypt.gensalt() + # 生成哈希值 + hashed = bcrypt.hashpw(password.encode('utf-8'), salt) + return hashed + +# 验证密码 +def check_password(hashed, password): + # 验证密码 + return bcrypt.checkpw(password.encode('utf-8'), hashed) + + +#用户信息传递 +class UserManage: + @staticmethod + def chackName(name):#检测用户是否存在,不存在则打印提示并返回None,否则返回UserModel + try: + user = UserModel.get(UserModel.name == name) + return user + except UserModel.DoesNotExist: + print(f"No user found with name: {name}") + return None + except Exception as error: + print(f"An error occurred: {error}") + return None + @staticmethod + def chackPassword(password):#如果密码正确则返回True + # 密码加密 + hashPassword = hash_password(password) + return check_password(hashPassword,password) + + + @staticmethod + def addUser(name, password): + try: + pwd = hash_password(password) + UserModel.insert(name=name, password=pwd).execute() + return True + except Exception as error: + print(error) + return False + + @staticmethod + def verifyUser(name, password): + user = UserManage.chackName(name) + if user is None: + return False + hashed_password_bytes = user.password.encode('utf-8') + return check_password(hashed_password_bytes, password) + +################################################################ +class ChatManage: + + # 获取并返回所有 chat 数据 + @staticmethod + def getAllManage(): + try: + all_chats = ChatModel.select() + # 将数据转换为列表形式 + chat_list = [] + for chat in all_chats: + chat_data = { + 'id': chat.id, + 'message': chat.message, + 'senderId': chat.senderId, + 'time': chat.time + } + chat_list.append(chat_data) + return chat_list + except Exception as error: + print(error) + return None + + @staticmethod + def AddChat(message,senderId): + try: + ChatModel.insert(message=message,senderId=senderId).execute() + return True + except Exception as error: + print(error) + return False + + + +################################################################# +#taoyu: +class LikeModel(BaseModel): + id = AutoField() + messageId = ForeignKeyField(ChatModel, backref='likes') + count = IntegerField(default=0) + + class Meta: + db_table = 'like' + +def display_all_users(): + try: + users = UserModel.select() + user_list = [] + + for user in users: + last_message = ChatModel.select().where(ChatModel.senderId == user.id).order_by( + ChatModel.time.desc()).first() + if last_message: + last_message_time = last_message.time + else: + last_message_time = "No messages found" + + user_data = { + "id": user.id, + "name": user.name, + "last_message_time": last_message_time + } + user_list.append(user_data) + + print(f"Total users: {len(user_list)}") + print("User list:", user_list) + except Exception as error: + print(f"An error occurred while fetching users: {error}") + + + +class LikeManage: + @staticmethod + def like_message(messageId): + try: + like, created = LikeModel.get_or_create(messageId=messageId, defaults={'count': 0}) + if not created: + like.count += 1 + like.save() + return like.count + except Exception as error: + print(f"An error occurred: {error}") + return None + +class SecurityQuestionModel(BaseModel): + user_id = ForeignKeyField(UserModel, backref='security_question') + question = TextField() + answer = CharField(max_length=128) # 存储加密后的答案 + + class Meta: + db_table = 'security_question' + +class SecurityQuestionManage: + + @staticmethod + def set_security_question(user_name, question, answer): + try: + user = UserModel.get(UserModel.name == user_name) + hashed_answer = hash_password(answer) + SecurityQuestionModel.insert(user_id=user.id, question=question, answer=hashed_answer).execute() + return True + except UserModel.DoesNotExist: + print("用户不存在。") + return False + except Exception as error: + print(f"发生错误: {error}") + return False + + @staticmethod + def verify_security_answer(user_name, answer, new_password): + try: + user = UserModel.get(UserModel.name == user_name) + security_question = SecurityQuestionModel.get(SecurityQuestionModel.user_id == user.id) + if bcrypt.checkpw(answer.encode('utf-8'), security_question.answer.encode('utf-8')): + return SecurityQuestionManage.reset_password(user_name, new_password) + except (UserModel.DoesNotExist, SecurityQuestionModel.DoesNotExist): + print("用户或密保问题不存在。") + return False + except Exception as error: + print(f"发生错误: {error}") + return False + + @staticmethod + def reset_password(user_name, new_password): + try: + user = UserModel.get(UserModel.name == user_name) + hashed_password = hash_password(new_password) + user.password = hashed_password + user.save() + return True + except UserModel.DoesNotExist: + print("用户不存在。") + return False + except Exception as error: + print(f"发生错误: {error}") + return False + diff --git a/main/server/Server.py b/main/server/Server.py new file mode 100644 index 0000000..23bbe0b --- /dev/null +++ b/main/server/Server.py @@ -0,0 +1,259 @@ + +import paho.mqtt.client as mqtt + +from main.config.config import HOST, PORT,publish_topic +from queue import Queue +import datetime +import threading +from threading import Thread, Event +import threading +from queue import Queue +import paho.mqtt.client as mqtt +from main.mysql import * +from abc import abstractmethod +import time + +class Server: + def __init__(self): + self.client = mqtt.Client() + self.client.on_connect = self.on_connect + self.client.on_message = self.on_message + self.client.connect(HOST, PORT, 60) + self.lock = threading.Lock() + self.loopNum = 0 + + def start_loop(self): + # 用线程锁来控制同时仅能一个loop_forever + if self.loopNum == 0: + self.lock.acquire() + print('进程锁加载') + self.loopNum = 1 + self.client._thread_terminate = False + self.client.loop_forever() + + def stop_loop(self): + # 停止这个线程 + if self.loopNum == 1: + self.lock.release() + print('进程锁结束!!') + self.client._thread_terminate = True + self.loopNum = 0 + + def serverStart(self):#启动进程,使用threading(python自带进程管理库)进行管理 + loopThread = threading.Thread(target=self.start_loop) + loopThread.start() + return loopThread + + @abstractmethod + def on_connect(self, client, userdata, flags, rc): + if rc == 0: + print("Connected successfully") + client.subscribe('test') # 订阅 login 主题 + else: + print("Failed to connect, return code %d\n", rc) + + @abstractmethod + def on_message(self, client, userdata, msg): + # 规定传入数据均为dict的形式 + data = eval(msg.payload.decode('utf-8')) + print(data) + return data + + + +class Register(Server): + def __init__(self): + super().__init__() + self.serverStart() + def on_connect(self, client, userdata, flags, rc): + if rc == 0: + print("Connected successfully") + client.subscribe(publish_topic['register_topic']) # 订阅 register 主题 + else: + print("Failed to connect, return code %d\n", rc) + def on_message(self, client, userdata, msg): + # 规定传入数据均为dict的形式 + data = eval(msg.payload.decode('utf-8')) + print(data) + userName = data.get('userName') + userPwd = data.get('userPwd') + returnTopic = data.get('returnTopic') + self.register(userName, userPwd, returnTopic) + return data + + def register(self, userName, userPwd, returnTopic): + user = UserManage.chackName(userName) + if user == None: + print("用户不存在,允许注册") + if UserManage.addUser(userName, userPwd): + print("用户添加成功!") + data = {'code': 1, "message": "用户添加成功!"} + self.client.publish(returnTopic, str(data).encode(), 1) + else: + print("用户添加失败,错误发生在服务器!") + data = {'code': 0, "message": "用户添加失败,错误发生在服务器!"} + self.client.publish(returnTopic, str(data).encode(), 1) + else: + print("用户存在,不允许注册") + data = {'code': 0, "message": "用户添加失败,用户存在"} + self.client.publish(returnTopic, str(data).encode(), 1) + + +class Login(Server): + def __init__(self): + super().__init__() + self.serverStart() + + + def on_connect(self, client, userdata, flags, rc): + if rc == 0: + print("Connected successfully") + client.subscribe(publish_topic['login_topic']) # 订阅 login 主题 + else: + print("Failed to connect, return code %d\n", rc) + + def on_message(self, client, userdata, msg): + # 规定传入数据均为dict的形式 + data = eval(msg.payload.decode('utf-8')) + print(data) + userName = data.get('userName') + userPwd = data.get('userPwd') + returnTopic = data.get('returnTopic') + self.login(userName, userPwd, returnTopic) + return data + + def login(self, userName, userPwd, returnTopic): + user = UserManage.chackName(userName) + if user == None: + print("账号或密码错误") + data = {'code': 0, 'message':"账号或密码错误"} + self.client.publish(returnTopic, str(data).encode(), 1) + else: + if UserManage.verifyUser(userName,userPwd): + print(f"{userName}通过验证,欢迎") + data = {'code': 1, "message": f"验证通过,欢迎回来{userName}"} + self.client.publish(returnTopic, str(data).encode(), 1) + else: + print("账号或密码错误") + data = {'code': 0, 'message': "账号或密码错误"} + self.client.publish(returnTopic, str(data).encode(), 1) + + +################################################################### +#taoyu +class Like(Server): + def __init__(self): + super().__init__() + self.serverStart() + + + def on_connect(self, client, userdata, flags, rc): + if rc == 0: + print("Connected successfully") + client.subscribe('like') + client.subscribe('login') # 订阅 login 主题 + else: + print("Failed to connect, return code %d\n", rc) + + + def on_message(self, client, userdata, msg): + # 规定传入数据均为dict的形式 + if msg.topic == 'like': + data = eval(msg.payload.decode('utf-8')) + messageId = data.get('message_id') + returnTopic = data.get('return_topic') + + if not messageId: + print("Invalid message format") + return + + + # 更新点赞数量 + new_count = LikeManage.like_message(messageId) + + if new_count is None: + print(f"Failed to update like count for message ID: {messageId}") + return + + print(f'处理并新的点赞计数成功') + # 此处可以输出最高点赞的消息ID + try: + top_message_id = LikeModel.select().order_by(LikeModel.count.desc()).get() + if top_message_id: + print(f'Top liked message ID: {top_message_id}') + else: + print('No top liked message found.') + except Exception as e: + print(f"Error retrieving top liked message: {e}") +################################################################################### +#jia yikun +class ChatSave(Server): + def __init__(self): + super().__init__() + self.serverStart() + + def on_connect(self,client, userdata, flags, rc): + + if rc==0: + #self.connected=True + print("Connected successfully") + client.subscribe('chatsend') # 订阅 chat 主题 + else: + raise Exception("Failed to connect mqtt server.") + + def on_message(self, client, userdata, msg): + # 接收用户消息 + data = eval(msg.payload.decode('utf-8')) + message = data.get('message') + userName = data.get('userName') + returnTopic = data.get('returnTopic') + user=UserManage.chackName(userName) + if user == None: + data = {'code': 0, 'message': "消息发送失败,找不到用户"} + self.client.publish(returnTopic, str(data).encode(), 1) + else: + print('new_message ',user.id,':', message) + chat = ChatManage() + if chat.AddChat(message, user.id): + data = {'code': 1, 'message': "消息发送成功"} + self.client.publish(returnTopic, str(data).encode(), 1) + else: + data = {'code': 0, 'message': "消息发送失败"} + self.client.publish(returnTopic, str(data).encode(), 1) + +class ChatAll(Server): + def __init__(self): + super().__init__() + self.serverStart() + + def on_connect(self,client, userdata, flags, rc): + + if rc==0: + #self.connected=True + print("Connected successfully") + client.subscribe('chatall') # 订阅 chat 主题 + else: + raise Exception("Failed to connect mqtt server.") + + def on_message(self, client, userdata, msg): + # 接收用户消息 + data = eval(msg.payload.decode('utf-8')) + returnTopic = data.get('returnTopic') + chat = ChatManage() + payload = str(chat.getAllManage()) + print('历史消息为:') + print(payload) + return self.client.publish(returnTopic, payload=payload, qos=2, retain=False) + + + + +################################################################################### +def main(): + a=Register() #进程1,处理注册 + b=Login() #进程2,处理登入 + c=Like() #进程3,处理点赞 + d=ChatAll() #进程4,处理所有消息 + e=ChatSave() #进程5,处理消息报存 + +main() \ No newline at end of file diff --git a/main/test.py b/main/test.py new file mode 100644 index 0000000..b7796d4 --- /dev/null +++ b/main/test.py @@ -0,0 +1,30 @@ + + +############################################ +#此为我自己进行功能测试的文件,你们可以随意更改,随意提交 +############################################ + +import bcrypt + +# 加密密码 +def hash_password(password): + # 生成盐值 + salt = bcrypt.gensalt() + # 生成哈希值 + hashed = bcrypt.hashpw(password.encode('utf-8'), salt) + return hashed + +# 验证密码 +def check_password(hashed, password): + # 验证密码 + return bcrypt.checkpw(password.encode('utf-8'), hashed) + +# 示例使用 +if __name__ == "__main__": + password = "my_secure_password" + hashed_password = hash_password(password) + print(f"Hashed password: {hashed_password}") + + # 验证密码 + is_correct = check_password(hashed_password, "my_secur1e_password") + print(f"Password is correct: {is_correct}") \ No newline at end of file diff --git a/xiao/.DS_Store b/xiao/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..324544c1ef48898842e3cad227ce95c1e2b9024c GIT binary patch literal 6148 zcmeHK!AiqG5Z!H~-B5%a6nYGJEn3?uh?f}a!Gi})(Su5DY|&uMO4FJ{Ddem_=!oD__u2*`1dqgdXA zu?*oEHzfK04B**W?3kUfHfw)5zkOKScvqqlnfZlT`e@GiHGGVtbXcps@j}sBS}uu_ zD2uD$PG-TdI~=8ccW{AEZ7Jh$I`4*OQ9tWAs|PX}cB7;}Pytb|4=$JIQPPu{FGoo) zRk49y5Vo*8PGvl + + + + + MQTT Chat + + +
+ + + + + + + + + +
+
+ + + +
+
+ + + +
+
+

Messages:

+
    +
    +
    +

    Users:

    +
      +
      + + + + + \ No newline at end of file diff --git a/xiao/app.py b/xiao/app.py new file mode 100644 index 0000000..7d38fc6 --- /dev/null +++ b/xiao/app.py @@ -0,0 +1,42 @@ +# xiaoxianyue code +from flask import Flask, render_template, request, redirect, url_for +from client.Client import Login, Register # 导入编写的登录和注册 + +app = Flask(__name__) # 创建一个 Flask 应用实例 + + +@app.route('/') # 定义根路由,默认访问这个路由 +def index(): + return redirect(url_for('login')) # 重定向到登录页面 + + +@app.route('/login', methods=['GET', 'POST']) # 定义登录路由,支持 GET 和 POST 方法 +def login(): + if request.method == 'POST': # 如果是 POST 请求,处理登录表单数据 + username = request.form['username'] # 从表单获取用户名 + password = request.form['password'] # 从表单获取密码 + login_client = Login(username, password) # 创建一个登录客户端,用于向 MQTT 发送登录信息 + # 这里假设登录状态由 MQTT 消息处理,可能需要一些回调机制来处理响应 + return redirect(url_for('profile')) # 登录成功后重定向到用户个人资料页面,临时开发的页面 + return render_template('login.html') # 如果是 GET 请求,显示登录表单 + + +@app.route('/register', methods=['GET', 'POST']) # 定义注册路由,支持 GET 和 POST 方法 +def register(): + if request.method == 'POST': # 如果是 POST 请求,处理注册表单数据 + username = request.form['username'] # 从表单获取用户名 + password = request.form['password'] # 从表单获取密码 + register_client = Register(username, password) # 创建一个注册客户端,用于向 MQTT 发送注册信息 + # 注册状态处理类似登录 + return redirect(url_for('login')) # 注册成功后重定向到登录页面 + return render_template('register.html') # 如果是 GET 请求,显示注册表单 + + +@app.route('/profile') # 定义用户个人资料页面的路由 +def profile(): + # 显示用户信息页面,此处需要适当填充 + return 'Welcome, user!' # 显示欢迎信息,实际开发中应显示用户相关信息 + + +if __name__ == '__main__': + app.run(debug=True) # 启动 Flask 应用,开启调试模式 \ No newline at end of file diff --git a/xiao/static/css/login-style.css b/xiao/static/css/login-style.css new file mode 100644 index 0000000..d21c87c --- /dev/null +++ b/xiao/static/css/login-style.css @@ -0,0 +1,69 @@ +* { + margin: 0; + padding: 0; +} + +/*html {*/ +/* height: 100%;*/ +/* width: 100%;*/ +/* overflow: hidden;*/ +/* margin: 0;*/ +/* padding: 0;*/ +/* background: url("{{ url_for('static', filename='images/Desert.png') }}") no-repeat 0px 0px;*/ +/* background-repeat: no-repeat;*/ +/* background-size: 100% 100%;*/ +/* -moz-background-size: 100% 100%;*/ +/*}*/ + +body { + display: flex; + align-items: center; + justify-content: center; + height: 100%; +} + +a +#loginDiv { + width: 37%; + display: flex; + justify-content: center; + align-items: center; + height: 300px; + background-color: rgba(75, 81, 95, 0.3); + box-shadow: 7px 7px 17px rgba(52, 56, 66, 0.5); + border-radius: 5px; +} + +#name_trip { + margin-left: 50px; + color: red; +} + +p { + margin-top: 30px; + margin-left: 20px; + color: azure; +} + +input { + margin-left: 15px; + border-radius: 5px; + border-style: hidden; + height: 30px; + width: 140px; + background-color: rgba(216, 191, 216, 0.5); + outline: none; + color: #f0edf3; + padding-left: 10px; +} + +.button { + border-color: cornsilk; + background-color: rgba(100, 149, 237, .7); + color: aliceblue; + border-style: hidden; + border-radius: 5px; + width: 100px; + height: 31px; + font-size: 16px; +} \ No newline at end of file diff --git a/xiao/templates/index.html b/xiao/templates/index.html new file mode 100644 index 0000000..d8f4cea --- /dev/null +++ b/xiao/templates/index.html @@ -0,0 +1,83 @@ + + + + + + Login/Register + + + + + +
      +
      +
      登录
      + + +
      +
      + + + +
      +
      + + + +
      + +
      + + + + + + + + + + + + +
      + +
      +
      + +
      +
      注册
      +
      + + + +
      +
      + + + +
      +
      + + + +
      +
      + +
      +
      + +
      + + + + + \ No newline at end of file diff --git a/xiao/templates/login.html b/xiao/templates/login.html new file mode 100644 index 0000000..90756f3 --- /dev/null +++ b/xiao/templates/login.html @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + 登陆 + + + + + +
      +
      +

      登录

      +

      用户名:

      +

      密码:

      +
      + + +
      +
      +
      + + + + + diff --git a/xiao/templates/register.html b/xiao/templates/register.html new file mode 100644 index 0000000..5d5c34a --- /dev/null +++ b/xiao/templates/register.html @@ -0,0 +1,298 @@ + + + + + + + + 注册 + + + + +
      +
      +

      注册

      +

      用户姓名:

      + +

      用户密码:

      + + + +

      + + + + +

      +
      +
      + + + + + +